diff --git a/DEPS b/DEPS index 2703e5eb..ee43e20 100644 --- a/DEPS +++ b/DEPS
@@ -36,11 +36,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '7e8cc21d574e00d13391da59f00be6bba62c31cd', + 'skia_revision': 'c42475cea23bfdb22b5d6cad6042577e47bd6a5c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'a90e831ead0d9623d7bfb3afc6b4f6c7e800f1a4', + 'v8_revision': '8e8649093cb16688093b49a7046de3d67b8f3068', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -48,7 +48,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '5695fc990fae1897f31bd418f9278e931776abdf', + 'angle_revision': '8bad46d40e23671d4a723a2daf4ca1e252bb0617', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -56,7 +56,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'cfb31d67a40310ed64d942ba346cf0cd3a01cadf', + 'pdfium_revision': '3c27a84d15c06f85cc7f455f96dc124673f9f9d2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '3cab5572b1fcf5a8f6018529dc30dc8d21b2a4bd', + 'boringssl_revision': '95c69563dc5422c3b3cd3a0bf435944a7530a12d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -80,7 +80,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '0949e1bef9d6b25ee44eb69a54e0cc6f8a677375', + 'nacl_revision': '4623c4f8a10b85cc3c97f7ecb2f7cb48a1da665e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype-android # and whatever else without interference from each other. @@ -88,7 +88,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': '9f8a0a8c0d4522f4014fbdba199222d44d638730', + 'catapult_revision': '7c4d195ab2d092b848cc05c9bd17b38365959588', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -178,7 +178,7 @@ Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '214fe8f93103621c5103eecfbe547f8a10a423f2', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'fe43b3cad0afb2c5280ed5d23910a6d744976251', 'src/third_party/webdriver/pylib': Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd', @@ -214,7 +214,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'd0d6cf9a9a302f1af62d0fd188fade3d205525a4', # commit position 13393 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '05929e21d437bc5f80309455f168a9e4bb2bc94b', # commit position 13407 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 802ac8a..d2245475 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -903,8 +903,8 @@ preferred_actions_.insert(kPreferredActions[i]); for (size_t i = 0; i < kReservedActionsLength; ++i) reserved_actions_.insert(kReservedActions[i]); - for (size_t i = 0; i < kNonrepeatableActionsLength; ++i) - nonrepeatable_actions_.insert(kNonrepeatableActions[i]); + for (size_t i = 0; i < kRepeatableActionsLength; ++i) + repeatable_actions_.insert(kRepeatableActions[i]); for (size_t i = 0; i < kActionsAllowedInAppModeOrPinnedModeLength; ++i) { actions_allowed_in_app_mode_.insert( kActionsAllowedInAppModeOrPinnedMode[i]); @@ -970,10 +970,8 @@ bool AcceleratorController::CanPerformAction( AcceleratorAction action, const ui::Accelerator& accelerator) { - if (nonrepeatable_actions_.find(action) != nonrepeatable_actions_.end() && - accelerator.IsRepeat()) { + if (accelerator.IsRepeat() && !repeatable_actions_.count(action)) return false; - } AcceleratorProcessingRestriction restriction = GetAcceleratorProcessingRestriction(action);
diff --git a/ash/accelerators/accelerator_controller.h b/ash/accelerators/accelerator_controller.h index 0e6b12e..2ed610d 100644 --- a/ash/accelerators/accelerator_controller.h +++ b/ash/accelerators/accelerator_controller.h
@@ -205,8 +205,8 @@ std::set<int> preferred_actions_; // Reserved actions. See accelerator_table.h for details. std::set<int> reserved_actions_; - // Actions which will not be repeated while holding the accelerator key. - std::set<int> nonrepeatable_actions_; + // Actions which will be repeated while holding the accelerator key. + std::set<int> repeatable_actions_; // Actions allowed in app mode. std::set<int> actions_allowed_in_app_mode_; // Actions allowed in pinned mode.
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc index 73f26a0..642ceb7 100644 --- a/ash/accelerators/accelerator_table.cc +++ b/ash/accelerators/accelerator_table.cc
@@ -403,36 +403,25 @@ const size_t kActionsAllowedAtModalWindowLength = arraysize(kActionsAllowedAtModalWindow); -const AcceleratorAction kNonrepeatableActions[] = { - // TODO(mazda): Add other actions which should not be repeated. - CYCLE_BACKWARD_MRU, - CYCLE_FORWARD_MRU, - EXIT, - NEXT_IME, - PREVIOUS_IME, - OPEN_FEEDBACK_PAGE, - PRINT_UI_HIERARCHIES, // Don't fill the logs if the key is held down. - ROTATE_SCREEN, - ROTATE_WINDOW, - SCALE_UI_UP, - SCALE_UI_DOWN, - SCALE_UI_RESET, - TAKE_WINDOW_SCREENSHOT, - TAKE_PARTIAL_SCREENSHOT, - TAKE_SCREENSHOT, - TOGGLE_FULLSCREEN, - TOGGLE_MAXIMIZED, - TOGGLE_OVERVIEW, - WINDOW_MINIMIZE, +const AcceleratorAction kRepeatableActions[] = { + FOCUS_NEXT_PANE, + FOCUS_PREVIOUS_PANE, + MAGNIFY_SCREEN_ZOOM_IN, + MAGNIFY_SCREEN_ZOOM_OUT, + MEDIA_NEXT_TRACK, + MEDIA_PREV_TRACK, + RESTORE_TAB, #if defined(OS_CHROMEOS) - DEBUG_TOGGLE_TOUCH_PAD, - DEBUG_TOGGLE_TOUCH_SCREEN, - LOCK_SCREEN, - SUSPEND, -#endif + BRIGHTNESS_DOWN, + BRIGHTNESS_UP, + KEYBOARD_BRIGHTNESS_DOWN, + KEYBOARD_BRIGHTNESS_UP, + VOLUME_DOWN, + VOLUME_UP, +#endif // defined(OS_CHROMEOS) }; -const size_t kNonrepeatableActionsLength = arraysize(kNonrepeatableActions); +const size_t kRepeatableActionsLength = arraysize(kRepeatableActions); const AcceleratorAction kActionsAllowedInAppModeOrPinnedMode[] = { DEBUG_PRINT_LAYER_HIERARCHY,
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h index 6c4add763..7d40cf6 100644 --- a/ash/accelerators/accelerator_table.h +++ b/ash/accelerators/accelerator_table.h
@@ -233,9 +233,9 @@ ASH_EXPORT extern const AcceleratorAction kActionsAllowedAtModalWindow[]; ASH_EXPORT extern const size_t kActionsAllowedAtModalWindowLength; -// Actions which will not be repeated while holding an accelerator key. -ASH_EXPORT extern const AcceleratorAction kNonrepeatableActions[]; -ASH_EXPORT extern const size_t kNonrepeatableActionsLength; +// Actions which may be repeated by holding an accelerator key. +ASH_EXPORT extern const AcceleratorAction kRepeatableActions[]; +ASH_EXPORT extern const size_t kRepeatableActionsLength; // Actions allowed in app mode or pinned mode. ASH_EXPORT extern const AcceleratorAction
diff --git a/ash/accelerators/accelerator_table_unittest.cc b/ash/accelerators/accelerator_table_unittest.cc index 95329282..4bb8c86 100644 --- a/ash/accelerators/accelerator_table_unittest.cc +++ b/ash/accelerators/accelerator_table_unittest.cc
@@ -66,12 +66,11 @@ } } -TEST(AcceleratorTableTest, CheckDuplicatedNonrepeatableActions) { +TEST(AcceleratorTableTest, CheckDuplicatedRepeatableActions) { std::set<AcceleratorAction> actions; - for (size_t i = 0; i < kNonrepeatableActionsLength; ++i) { - EXPECT_TRUE(actions.insert(kNonrepeatableActions[i]).second) - << "Duplicated action: " << kNonrepeatableActions[i] - << " at index: " << i; + for (size_t i = 0; i < kRepeatableActionsLength; ++i) { + EXPECT_TRUE(actions.insert(kRepeatableActions[i]).second) + << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i; } }
diff --git a/ash/accelerators/exit_warning_handler.h b/ash/accelerators/exit_warning_handler.h index 9a4c93f..c678f84d 100644 --- a/ash/accelerators/exit_warning_handler.h +++ b/ash/accelerators/exit_warning_handler.h
@@ -18,16 +18,15 @@ namespace ash { -// In order to avoid accidental exits when the user presses the exit -// shortcut by mistake, we require the user press it twice within a -// period of time. During that time we show a popup informing the -// user of this. +// In order to avoid accidental exits when the user presses the exit shortcut by +// mistake, we require that the user press it twice within a short period of +// time. During that time we show a popup informing the user of this. // // Notes: // -// The corresponding accelerator must be non-repeatable (see -// kNonrepeatableActions in accelerator_table.cc). Otherwise the "Double Press -// Exit" will be activated just by holding it down, i.e. probably every time. +// The corresponding accelerator must not be repeatable (see kRepeatableActions +// in accelerator_table.cc). Otherwise, the "Double Press Exit" will be +// activated just by holding it down, i.e. probably every time. // // State Transition Diagrams: //
diff --git a/ash/ash.gyp b/ash/ash.gyp index c352832..d2dce7d 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -77,6 +77,8 @@ 'common/metrics/user_metrics_action.h', 'common/multi_profile_uma.cc', 'common/multi_profile_uma.h', + 'common/popup_message.cc', + 'common/popup_message.h', 'common/root_window_controller_common.cc', 'common/root_window_controller_common.h', 'common/session/session_state_delegate.cc', @@ -281,9 +283,15 @@ 'common/system/user/login_status.h', 'common/system/user/rounded_image_view.cc', 'common/system/user/rounded_image_view.h', + 'common/system/user/tray_user.cc', + 'common/system/user/tray_user.h', 'common/system/user/tray_user_separator.cc', 'common/system/user/tray_user_separator.h', + 'common/system/user/user_card_view.cc', + 'common/system/user/user_card_view.h', 'common/system/user/user_observer.h', + 'common/system/user/user_view.cc', + 'common/system/user/user_view.h', 'common/system/volume_control_delegate.h', 'common/system/web_notification/ash_popup_alignment_delegate.cc', 'common/system/web_notification/ash_popup_alignment_delegate.h', @@ -536,8 +544,6 @@ 'pointer_watcher_delegate.h', 'pointer_watcher_delegate_aura.cc', 'pointer_watcher_delegate_aura.h', - 'popup_message.cc', - 'popup_message.h', 'root_window_controller.cc', 'root_window_controller.h', 'root_window_settings.cc', @@ -636,12 +642,6 @@ 'system/toast/toast_overlay.h', 'system/tray/system_tray.cc', 'system/tray/system_tray.h', - 'system/user/tray_user.cc', - 'system/user/tray_user.h', - 'system/user/user_card_view.cc', - 'system/user/user_card_view.h', - 'system/user/user_view.cc', - 'system/user/user_view.h', 'touch/touch_hud_debug.cc', 'touch/touch_hud_debug.h', 'touch/touch_hud_projection.cc', @@ -897,6 +897,7 @@ 'autoclick/autoclick_unittest.cc', 'common/display/display_info_unittest.cc', 'common/material_design/material_design_controller_unittest.cc', + 'common/popup_message_unittest.cc', 'common/shelf/shelf_model_unittest.cc', 'common/system/chromeos/power/power_status_unittest.cc', 'common/system/chromeos/power/power_status_view_unittest.cc', @@ -909,6 +910,7 @@ 'common/system/ime/tray_ime_chromeos_unittest.cc', 'common/system/tray/tray_details_view_unittest.cc', 'common/system/update/tray_update_unittest.cc', + 'common/system/user/tray_user_unittest.cc', 'content/display/screen_orientation_controller_chromeos_unittest.cc', 'content/keyboard_overlay/keyboard_overlay_delegate_unittest.cc', 'content/keyboard_overlay/keyboard_overlay_view_unittest.cc', @@ -945,7 +947,6 @@ 'metrics/task_switch_metrics_recorder_unittest.cc', 'metrics/task_switch_time_tracker_unittest.cc', 'metrics/user_metrics_recorder_unittest.cc', - 'popup_message_unittest.cc', 'root_window_controller_unittest.cc', 'rotator/screen_rotation_animation_unittest.cc', 'screen_util_unittest.cc', @@ -971,7 +972,6 @@ 'system/overview/overview_button_tray_unittest.cc', 'system/toast/toast_manager_unittest.cc', 'system/tray/system_tray_unittest.cc', - 'system/user/tray_user_unittest.cc', 'system/web_notification/ash_popup_alignment_delegate_unittest.cc', 'system/web_notification/web_notification_tray_unittest.cc', 'test/ash_test_helper_unittest.cc',
diff --git a/ash/ash_touch_exploration_manager_chromeos.cc b/ash/ash_touch_exploration_manager_chromeos.cc index ff01bd71..7e60f17 100644 --- a/ash/ash_touch_exploration_manager_chromeos.cc +++ b/ash/ash_touch_exploration_manager_chromeos.cc
@@ -63,8 +63,10 @@ if (!VolumeAdjustSoundEnabled()) return; if (!audio_handler_->IsOutputMuted() && - audio_handler_->GetOutputVolumePercent() != 100) - PlaySystemSoundIfSpokenFeedback(chromeos::SOUND_VOLUME_ADJUST); + audio_handler_->GetOutputVolumePercent() != 100) { + WmShell::Get()->GetAccessibilityDelegate()->PlayEarcon( + chromeos::SOUND_VOLUME_ADJUST); + } } void AshTouchExplorationManager::PlayPassthroughEarcon() {
diff --git a/ash/common/DEPS b/ash/common/DEPS index 1412c1f7..a1417d7 100644 --- a/ash/common/DEPS +++ b/ash/common/DEPS
@@ -5,3 +5,9 @@ "+ui", "-ui/aura", ] + +specific_include_rules = { + ".*test\.cc": [ + "+ash/test", + ] +} \ No newline at end of file
diff --git a/ash/ash_view_ids.h b/ash/common/ash_view_ids.h similarity index 74% rename from ash/ash_view_ids.h rename to ash/common/ash_view_ids.h index 61bf3cf..ed63b56 100644 --- a/ash/ash_view_ids.h +++ b/ash/common/ash_view_ids.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_ASH_VIEW_IDS_H_ -#define ASH_ASH_VIEW_IDS_H_ +#ifndef ASH_COMMON_ASH_VIEW_IDS_H_ +#define ASH_COMMON_ASH_VIEW_IDS_H_ namespace ash { @@ -15,4 +15,4 @@ } // namespace ash -#endif // ASH_ASH_VIEW_IDS_H_ +#endif // ASH_COMMON_ASH_VIEW_IDS_H_
diff --git a/ash/popup_message.cc b/ash/common/popup_message.cc similarity index 93% rename from ash/popup_message.cc rename to ash/common/popup_message.cc index 231e4da..f745499 100644 --- a/ash/popup_message.cc +++ b/ash/common/popup_message.cc
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/popup_message.h" +#include "ash/common/popup_message.h" -#include "ash/wm/window_animations.h" +#include "ash/common/wm_lookup.h" +#include "ash/common/wm_window.h" #include "grit/ash_resources.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/geometry/insets.h" @@ -14,6 +15,7 @@ #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/widget.h" +#include "ui/wm/core/window_animations.h" namespace ash { namespace { @@ -199,11 +201,10 @@ view_ = new MessageBubble(caption, message, message_type, anchor, arrow, size_override, arrow_offset); widget_ = view_->GetWidget(); - - gfx::NativeView native_view = widget_->GetNativeView(); - wm::SetWindowVisibilityAnimationType( - native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); - wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_HIDE); + WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget_); + window->SetVisibilityAnimationType( + ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); + window->SetVisibilityAnimationTransition(::wm::ANIMATE_HIDE); view_->GetWidget()->Show(); } @@ -221,11 +222,12 @@ } void PopupMessage::CancelHidingAnimation() { - if (!widget_ || !widget_->GetNativeView()) + if (!widget_) return; - gfx::NativeView native_view = widget_->GetNativeView(); - wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_NONE); + WmWindow* window = WmLookup::Get()->GetWindowForWidget(widget_); + if (window) + window->SetVisibilityAnimationTransition(::wm::ANIMATE_NONE); } } // namespace ash
diff --git a/ash/popup_message.h b/ash/common/popup_message.h similarity index 95% rename from ash/popup_message.h rename to ash/common/popup_message.h index 5da93d0..c31e2c1 100644 --- a/ash/popup_message.h +++ b/ash/common/popup_message.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_POPUP_MESSAGE_H_ -#define ASH_POPUP_MESSAGE_H_ +#ifndef ASH_COMMON_POPUP_MESSAGE_H_ +#define ASH_COMMON_POPUP_MESSAGE_H_ #include "ash/ash_export.h" #include "base/gtest_prod_util.h" @@ -79,4 +79,4 @@ } // namespace ash -#endif // ASH_POPUP_MESSAGE_H_ +#endif // ASH_COMMON_POPUP_MESSAGE_H_
diff --git a/ash/popup_message_unittest.cc b/ash/common/popup_message_unittest.cc similarity index 97% rename from ash/popup_message_unittest.cc rename to ash/common/popup_message_unittest.cc index 90559c0e..9bdcce0 100644 --- a/ash/popup_message_unittest.cc +++ b/ash/common/popup_message_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/popup_message.h" +#include "ash/common/popup_message.h" #include "ash/test/ash_test_base.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/common/system/DEPS b/ash/common/system/DEPS index d0d4503..cb8bd0b5 100644 --- a/ash/common/system/DEPS +++ b/ash/common/system/DEPS
@@ -3,10 +3,4 @@ include_rules = [ # TODO(jamescook): Remove this. "+ash/system/tray/system_tray.h", -] - -specific_include_rules = { - ".*test\.cc": [ - "+ash/test", - ] -} +] \ No newline at end of file
diff --git a/ash/system/user/tray_user.cc b/ash/common/system/user/tray_user.cc similarity index 98% rename from ash/system/user/tray_user.cc rename to ash/common/system/user/tray_user.cc index e0699c1a..4633076 100644 --- a/ash/system/user/tray_user.cc +++ b/ash/common/system/user/tray_user.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 "ash/system/user/tray_user.h" +#include "ash/common/system/user/tray_user.h" #include "ash/common/ash_switches.h" #include "ash/common/session/session_state_delegate.h" @@ -13,9 +13,9 @@ #include "ash/common/system/tray/tray_item_view.h" #include "ash/common/system/tray/tray_utils.h" #include "ash/common/system/user/rounded_image_view.h" +#include "ash/common/system/user/user_view.h" #include "ash/common/wm_shell.h" #include "ash/system/tray/system_tray.h" -#include "ash/system/user/user_view.h" #include "base/logging.h" #include "base/strings/string16.h" #include "components/signin/core/account_id/account_id.h"
diff --git a/ash/system/user/tray_user.h b/ash/common/system/user/tray_user.h similarity index 95% rename from ash/system/user/tray_user.h rename to ash/common/system/user/tray_user.h index 897cb81..1373db3 100644 --- a/ash/system/user/tray_user.h +++ b/ash/common/system/user/tray_user.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_USER_TRAY_USER_H_ -#define ASH_SYSTEM_USER_TRAY_USER_H_ +#ifndef ASH_COMMON_SYSTEM_USER_TRAY_USER_H_ +#define ASH_COMMON_SYSTEM_USER_TRAY_USER_H_ #include "ash/ash_export.h" #include "ash/common/session/session_types.h" @@ -93,4 +93,4 @@ } // namespace ash -#endif // ASH_SYSTEM_USER_TRAY_USER_H_ +#endif // ASH_COMMON_SYSTEM_USER_TRAY_USER_H_
diff --git a/ash/system/user/tray_user_unittest.cc b/ash/common/system/user/tray_user_unittest.cc similarity index 94% rename from ash/system/user/tray_user_unittest.cc rename to ash/common/system/user/tray_user_unittest.cc index 39adf62..b55ab9a 100644 --- a/ash/system/user/tray_user_unittest.cc +++ b/ash/common/system/user/tray_user_unittest.cc
@@ -6,13 +6,11 @@ #include "ash/common/shell_delegate.h" #include "ash/common/system/tray/tray_constants.h" +#include "ash/common/system/user/tray_user.h" #include "ash/common/system/user/tray_user_separator.h" +#include "ash/common/system/user/user_view.h" #include "ash/common/wm_shell.h" -#include "ash/root_window_controller.h" -#include "ash/shell.h" #include "ash/system/tray/system_tray.h" -#include "ash/system/user/tray_user.h" -#include "ash/system/user/user_view.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test/test_session_state_delegate.h" @@ -69,7 +67,7 @@ void TrayUserTest::SetUp() { test::AshTestBase::SetUp(); - tray_ = Shell::GetPrimaryRootWindowController()->GetSystemTray(); + tray_ = GetPrimarySystemTray(); delegate_ = test::AshTestHelper::GetTestSessionStateDelegate(); } @@ -132,7 +130,7 @@ InitializeParameters(1, false); // Move the mouse over the status area and click to open the status menu. - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + ui::test::EventGenerator& generator = GetEventGenerator(); EXPECT_FALSE(tray()->IsAnyBubbleVisible()); @@ -154,7 +152,7 @@ TEST_F(TrayUserTest, AccessibleLabelContainsSingleUserInfo) { InitializeParameters(1, false); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + ui::test::EventGenerator& generator = GetEventGenerator(); ShowTrayMenu(&generator); views::View* view = @@ -169,7 +167,7 @@ TEST_F(TrayUserTest, AccessibleLabelContainsMultiUserInfo) { InitializeParameters(1, true); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + ui::test::EventGenerator& generator = GetEventGenerator(); ShowTrayMenu(&generator); views::View* view = @@ -191,7 +189,7 @@ InitializeParameters(1, true); // Move the mouse over the status area and click to open the status menu. - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + ui::test::EventGenerator& generator = GetEventGenerator(); generator.set_async(false); int max_users = delegate()->GetMaximumNumberOfLoggedInUsers(); @@ -250,7 +248,7 @@ TEST_F(TrayUserTest, MutiUserModeButtonClicks) { // Have two users. InitializeParameters(2, true); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + ui::test::EventGenerator& generator = GetEventGenerator(); ShowTrayMenu(&generator); // Switch to a new user - which has a capitalized name.
diff --git a/ash/system/user/user_card_view.cc b/ash/common/system/user/user_card_view.cc similarity index 99% rename from ash/system/user/user_card_view.cc rename to ash/common/system/user/user_card_view.cc index 8356091..77e228023 100644 --- a/ash/system/user/user_card_view.cc +++ b/ash/common/system/user/user_card_view.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 "ash/system/user/user_card_view.h" +#include "ash/common/system/user/user_card_view.h" #include <algorithm> #include <vector> @@ -39,7 +39,7 @@ #include "ui/views/layout/box_layout.h" #if defined(OS_CHROMEOS) -#include "ash/ash_view_ids.h" +#include "ash/common/ash_view_ids.h" #include "ash/common/media_delegate.h" #include "ash/common/system/chromeos/media_security/media_capture_observer.h" #include "ui/views/controls/image_view.h"
diff --git a/ash/system/user/user_card_view.h b/ash/common/system/user/user_card_view.h similarity index 87% rename from ash/system/user/user_card_view.h rename to ash/common/system/user/user_card_view.h index 2d9584b..07504af 100644 --- a/ash/system/user/user_card_view.h +++ b/ash/common/system/user/user_card_view.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_USER_USER_CARD_VIEW_H_ -#define ASH_SYSTEM_USER_USER_CARD_VIEW_H_ +#ifndef ASH_COMMON_SYSTEM_USER_USER_CARD_VIEW_H_ +#define ASH_COMMON_SYSTEM_USER_USER_CARD_VIEW_H_ #include "base/macros.h" #include "ui/views/view.h" @@ -40,4 +40,4 @@ } // namespace tray } // namespace ash -#endif // ASH_SYSTEM_USER_USER_CARD_VIEW_H_ +#endif // ASH_COMMON_SYSTEM_USER_USER_CARD_VIEW_H_
diff --git a/ash/system/user/user_view.cc b/ash/common/system/user/user_view.cc similarity index 99% rename from ash/system/user/user_view.cc rename to ash/common/system/user/user_view.cc index ae1526f..6bbb6a2 100644 --- a/ash/system/user/user_view.cc +++ b/ash/common/system/user/user_view.cc
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/user/user_view.h" +#include "ash/common/system/user/user_view.h" #include <algorithm> #include <utility> #include "ash/common/multi_profile_uma.h" +#include "ash/common/popup_message.h" #include "ash/common/session/session_state_delegate.h" #include "ash/common/shell_delegate.h" #include "ash/common/shell_window_ids.h" @@ -18,13 +19,12 @@ #include "ash/common/system/user/button_from_view.h" #include "ash/common/system/user/login_status.h" #include "ash/common/system/user/rounded_image_view.h" +#include "ash/common/system/user/user_card_view.h" #include "ash/common/wm_lookup.h" #include "ash/common/wm_root_window_controller.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "ash/popup_message.h" #include "ash/system/tray/system_tray.h" -#include "ash/system/user/user_card_view.h" #include "components/signin/core/account_id/account_id.h" #include "components/user_manager/user_info.h" #include "grit/ash_resources.h"
diff --git a/ash/system/user/user_view.h b/ash/common/system/user/user_view.h similarity index 93% rename from ash/system/user/user_view.h rename to ash/common/system/user/user_view.h index 8972db4..69b2673 100644 --- a/ash/system/user/user_view.h +++ b/ash/common/system/user/user_view.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_USER_USER_VIEW_H_ -#define ASH_SYSTEM_USER_USER_VIEW_H_ +#ifndef ASH_COMMON_SYSTEM_USER_USER_VIEW_H_ +#define ASH_COMMON_SYSTEM_USER_USER_VIEW_H_ #include <memory> #include "ash/common/session/session_types.h" #include "ash/common/system/tray/tray_constants.h" -#include "ash/system/user/tray_user.h" +#include "ash/common/system/user/tray_user.h" #include "base/macros.h" #include "ui/views/controls/button/button.h" #include "ui/views/focus/focus_manager.h" @@ -104,4 +104,4 @@ } // namespace tray } // namespace ash -#endif // ASH_SYSTEM_USER_USER_VIEW_H_ +#endif // ASH_COMMON_SYSTEM_USER_USER_VIEW_H_
diff --git a/ash/display/screen_orientation_controller_chromeos.cc b/ash/display/screen_orientation_controller_chromeos.cc index 5c11a35..10afdd43 100644 --- a/ash/display/screen_orientation_controller_chromeos.cc +++ b/ash/display/screen_orientation_controller_chromeos.cc
@@ -112,6 +112,16 @@ ApplyLockForActiveWindow(); } +void ScreenOrientationController::UnlockAll() { + for (auto pair : locking_windows_) + pair.first->RemoveObserver(this); + locking_windows_.clear(); + Shell::GetInstance()->activation_client()->RemoveObserver(this); + SetRotationLocked(false); + if (user_rotation_ != current_rotation_) + SetDisplayRotation(user_rotation_, display::Display::ROTATION_SOURCE_USER); +} + bool ScreenOrientationController::ScreenOrientationProviderSupported() const { return WmShell::Get() ->maximize_mode_controller() @@ -386,11 +396,13 @@ void ScreenOrientationController::ApplyLockForActiveWindow() { aura::Window* active_window = Shell::GetInstance()->activation_client()->GetActiveWindow(); - for (auto const& windows : locking_windows_) { - if (windows.first->TargetVisibility() && - active_window->Contains(windows.first)) { - LockRotationToOrientation(windows.second); - return; + if (active_window) { + for (auto const& windows : locking_windows_) { + if (windows.first->TargetVisibility() && + active_window->Contains(windows.first)) { + LockRotationToOrientation(windows.second); + return; + } } } SetRotationLocked(false);
diff --git a/ash/display/screen_orientation_controller_chromeos.h b/ash/display/screen_orientation_controller_chromeos.h index 1f1fcff..3b92826 100644 --- a/ash/display/screen_orientation_controller_chromeos.h +++ b/ash/display/screen_orientation_controller_chromeos.h
@@ -57,6 +57,9 @@ blink::WebScreenOrientationLockType lock_orientation); void UnlockOrientationForWindow(aura::Window* window); + // Unlock all and set the rotation back to the user specified rotation. + void UnlockAll(); + bool ScreenOrientationProviderSupported() const; bool ignore_display_configuration_updates() const {
diff --git a/ash/mus/BUILD.gn b/ash/mus/BUILD.gn index ff000bed..f9d57e6 100644 --- a/ash/mus/BUILD.gn +++ b/ash/mus/BUILD.gn
@@ -104,6 +104,10 @@ "//ui/views", "//ui/views/mus:for_mojo_application", ] + + if (is_chromeos) { + deps += [ "//chromeos" ] + } } mojo_native_application("mus") { @@ -180,7 +184,7 @@ "//base", "//base/test:test_config", "//mojo/public/cpp/system", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/ui/common:mus_common", "//services/ui/public/cpp", "//services/ui/public/cpp/tests:test_support",
diff --git a/ash/mus/accelerator_registrar_unittest.cc b/ash/mus/accelerator_registrar_unittest.cc index 3d970eb..97dc91b 100644 --- a/ash/mus/accelerator_registrar_unittest.cc +++ b/ash/mus/accelerator_registrar_unittest.cc
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "mojo/public/cpp/bindings/binding.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/ui/common/event_matcher_util.h" #include "services/ui/public/cpp/window.h" #include "services/ui/public/interfaces/accelerator_registrar.mojom.h" @@ -67,9 +67,9 @@ DISALLOW_COPY_AND_ASSIGN(TestAcceleratorHandler); }; -class AcceleratorRegistrarTest : public shell::test::ShellTest { +class AcceleratorRegistrarTest : public shell::test::ServiceTest { public: - AcceleratorRegistrarTest() : shell::test::ShellTest("exe:mash_unittests") {} + AcceleratorRegistrarTest() : shell::test::ServiceTest("exe:mash_unittests") {} ~AcceleratorRegistrarTest() override {} protected:
diff --git a/ash/mus/app_launch_unittest.cc b/ash/mus/app_launch_unittest.cc index 449cbebf..b11bb3b 100644 --- a/ash/mus/app_launch_unittest.cc +++ b/ash/mus/app_launch_unittest.cc
@@ -5,7 +5,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/run_loop.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/ui/public/interfaces/window_server_test.mojom.h" namespace ash { @@ -16,15 +16,15 @@ callback.Run(); } -class AppLaunchTest : public shell::test::ShellTest { +class AppLaunchTest : public shell::test::ServiceTest { public: - AppLaunchTest() : ShellTest("exe:mash_unittests") {} + AppLaunchTest() : ServiceTest("exe:mash_unittests") {} ~AppLaunchTest() override {} private: void SetUp() override { base::CommandLine::ForCurrentProcess()->AppendSwitch("use-test-config"); - ShellTest::SetUp(); + ServiceTest::SetUp(); } DISALLOW_COPY_AND_ASSIGN(AppLaunchTest);
diff --git a/ash/mus/bridge/wm_shell_mus.cc b/ash/mus/bridge/wm_shell_mus.cc index 6c42ca3..582e750 100644 --- a/ash/mus/bridge/wm_shell_mus.cc +++ b/ash/mus/bridge/wm_shell_mus.cc
@@ -99,6 +99,8 @@ client_->AddObserver(this); WmShell::Set(this); + CreateMaximizeModeController(); + CreateMruWindowTracker(); accessibility_delegate_.reset(new DefaultAccessibilityDelegate); @@ -108,6 +110,9 @@ WmShellMus::~WmShellMus() { // This order mirrors that of Shell. + // Destroy maximize mode controller early on since it has some observers which + // need to be removed. + DeleteMaximizeModeController(); DeleteSystemTrayDelegate(); DeleteWindowSelectorController(); DeleteMruWindowTracker();
diff --git a/ash/mus/container_ids.cc b/ash/mus/container_ids.cc index cd724707..e3407fdf 100644 --- a/ash/mus/container_ids.cc +++ b/ash/mus/container_ids.cc
@@ -36,6 +36,9 @@ case Container::DRAG_AND_TOOLTIPS: return kShellWindowId_DragImageAndTooltipContainer; + + case Container::OVERLAY: + return kShellWindowId_OverlayContainer; } return kShellWindowId_Invalid; }
diff --git a/ash/mus/window_manager_application.cc b/ash/mus/window_manager_application.cc index aeef95e..ac84148 100644 --- a/ash/mus/window_manager_application.cc +++ b/ash/mus/window_manager_application.cc
@@ -23,6 +23,10 @@ #include "ui/events/event.h" #include "ui/views/mus/aura_init.h" +#if defined(OS_CHROMEOS) +#include "chromeos/dbus/dbus_thread_manager.h" +#endif + namespace ash { namespace mus { @@ -40,6 +44,10 @@ // Destroy the WindowManager while still valid. This way we ensure // OnWillDestroyRootWindowController() is called (if it hasn't been already). window_manager_.reset(); + +#if defined(OS_CHROMEOS) + chromeos::DBusThreadManager::Shutdown(); +#endif } void WindowManagerApplication::OnAcceleratorRegistrarDestroyed( @@ -49,6 +57,11 @@ void WindowManagerApplication::InitWindowManager( ::ui::WindowTreeClient* window_tree_client) { +#if defined(OS_CHROMEOS) + // Must occur after mojo::ApplicationRunner has initialized AtExitManager, but + // before WindowManager::Init(). + chromeos::DBusThreadManager::Initialize(); +#endif window_manager_->Init(window_tree_client); window_manager_->AddObserver(this); }
diff --git a/ash/mus/window_manager_unittest.cc b/ash/mus/window_manager_unittest.cc index 5400deb7d..d084d1d 100644 --- a/ash/mus/window_manager_unittest.cc +++ b/ash/mus/window_manager_unittest.cc
@@ -11,7 +11,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/run_loop.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/ui/public/cpp/window.h" #include "services/ui/public/cpp/window_tree_client.h" #include "services/ui/public/cpp/window_tree_client_delegate.h" @@ -34,9 +34,9 @@ DISALLOW_COPY_AND_ASSIGN(WindowTreeClientDelegate); }; -class WindowManagerTest : public shell::test::ShellTest { +class WindowManagerTest : public shell::test::ServiceTest { public: - WindowManagerTest() : shell::test::ShellTest("exe:mash_unittests") {} + WindowManagerTest() : shell::test::ServiceTest("exe:mash_unittests") {} ~WindowManagerTest() override {} private:
diff --git a/ash/public/interfaces/OWNERS b/ash/public/interfaces/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/ash/public/interfaces/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/ash/public/interfaces/container.mojom b/ash/public/interfaces/container.mojom index e0269a1..e49b830 100644 --- a/ash/public/interfaces/container.mojom +++ b/ash/public/interfaces/container.mojom
@@ -20,6 +20,7 @@ BUBBLES, MENUS, DRAG_AND_TOOLTIPS, + OVERLAY, }; const string kWindowContainer_Property = "ash:window-container";
diff --git a/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png b/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png index 0f17aa9d..00900cb 100644 --- a/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png +++ b/ash/resources/default_100_percent/common/multi_window_resize_horizontal.png Binary files differ
diff --git a/ash/resources/default_100_percent/common/multi_window_resize_vertical.png b/ash/resources/default_100_percent/common/multi_window_resize_vertical.png index 7dceda4..cc4632a 100644 --- a/ash/resources/default_100_percent/common/multi_window_resize_vertical.png +++ b/ash/resources/default_100_percent/common/multi_window_resize_vertical.png Binary files differ
diff --git a/ash/resources/default_200_percent/common/multi_window_resize_horizontal.png b/ash/resources/default_200_percent/common/multi_window_resize_horizontal.png new file mode 100644 index 0000000..4f1f5b3a --- /dev/null +++ b/ash/resources/default_200_percent/common/multi_window_resize_horizontal.png Binary files differ
diff --git a/ash/resources/default_200_percent/common/multi_window_resize_vertical.png b/ash/resources/default_200_percent/common/multi_window_resize_vertical.png index 80f7d62e..04f3969 100644 --- a/ash/resources/default_200_percent/common/multi_window_resize_vertical.png +++ b/ash/resources/default_200_percent/common/multi_window_resize_vertical.png Binary files differ
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index b93bb87..a4b1f37 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -56,11 +56,17 @@ AppListButton::~AppListButton() {} void AppListButton::OnAppListShown() { - AnimateInkDrop(views::InkDropState::ACTIVATED, nullptr); + if (ash::MaterialDesignController::IsShelfMaterial()) + AnimateInkDrop(views::InkDropState::ACTIVATED, nullptr); + else + SchedulePaint(); } void AppListButton::OnAppListDismissed() { - AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr); + if (ash::MaterialDesignController::IsShelfMaterial()) + AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr); + else + SchedulePaint(); } bool AppListButton::OnMousePressed(const ui::MouseEvent& event) {
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 964a8b69..00287912 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -380,7 +380,6 @@ cancelling_drag_model_changed_(false), last_hidden_index_(0), closing_event_time_(base::TimeTicks()), - got_deleted_(nullptr), drag_and_drop_item_pinned_(false), drag_and_drop_shelf_id_(0), drag_replaced_view_(nullptr), @@ -403,10 +402,6 @@ ShelfView::~ShelfView() { bounds_animator_->RemoveObserver(this); model_->RemoveObserver(this); - // If we are inside the MenuRunner, we need to know if we were getting - // deleted while it was running. - if (got_deleted_) - *got_deleted_ = true; } void ShelfView::Init() { @@ -1593,7 +1588,7 @@ void ShelfView::ShelfItemRemoved(int model_index, ShelfID id) { if (id == context_menu_id_) - launcher_menu_runner_.reset(); + launcher_menu_runner_->Cancel(); { base::AutoReset<bool> cancelling_drag(&cancelling_drag_model_changed_, true); @@ -1705,57 +1700,58 @@ last_pressed_index_ = view_model_->GetIndexOfView(sender); DCHECK_LT(-1, last_pressed_index_); - { - ScopedTargetRootWindow scoped_target( - sender->GetWidget()->GetNativeView()->GetRootWindow()); - // Slow down activation animations if shift key is pressed. - std::unique_ptr<ui::ScopedAnimationDurationScaleMode> slowing_animations; - if (event.IsShiftDown()) { - slowing_animations.reset(new ui::ScopedAnimationDurationScaleMode( - ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); - } - - // Collect usage statistics before we decide what to do with the click. - switch (model_->items()[last_pressed_index_].type) { - case TYPE_APP_SHORTCUT: - case TYPE_WINDOWED_APP: - case TYPE_PLATFORM_APP: - case TYPE_BROWSER_SHORTCUT: - WmShell::Get()->RecordUserMetricsAction(UMA_LAUNCHER_CLICK_ON_APP); - break; - - case TYPE_APP_LIST: - WmShell::Get()->RecordUserMetricsAction( - UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON); - break; - - case TYPE_APP_PANEL: - case TYPE_DIALOG: - case TYPE_IME_MENU: - break; - - case TYPE_UNDEFINED: - NOTREACHED() << "ShelfItemType must be set."; - break; - } - - ShelfItemDelegate::PerformedAction performed_action = - item_manager_ - ->GetShelfItemDelegate(model_->items()[last_pressed_index_].id) - ->ItemSelected(event); - - shelf_button_pressed_metric_tracker_.ButtonPressed(event, sender, - performed_action); - - // For the app list menu no TRIGGERED ink drop effect is needed and it - // handles its own ACTIVATED/DEACTIVATED states. - if (performed_action == ShelfItemDelegate::kNewWindowCreated || - (performed_action != ShelfItemDelegate::kAppListMenuShown && - !ShowListMenuForView(model_->items()[last_pressed_index_], sender, - event, ink_drop))) { - ink_drop->AnimateToState(views::InkDropState::ACTION_TRIGGERED); - } + scoped_target_root_window_.reset(new ScopedTargetRootWindow( + sender->GetWidget()->GetNativeView()->GetRootWindow())); + // Slow down activation animations if shift key is pressed. + std::unique_ptr<ui::ScopedAnimationDurationScaleMode> slowing_animations; + if (event.IsShiftDown()) { + slowing_animations.reset(new ui::ScopedAnimationDurationScaleMode( + ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); } + + // Collect usage statistics before we decide what to do with the click. + switch (model_->items()[last_pressed_index_].type) { + case TYPE_APP_SHORTCUT: + case TYPE_WINDOWED_APP: + case TYPE_PLATFORM_APP: + case TYPE_BROWSER_SHORTCUT: + WmShell::Get()->RecordUserMetricsAction(UMA_LAUNCHER_CLICK_ON_APP); + break; + + case TYPE_APP_LIST: + WmShell::Get()->RecordUserMetricsAction( + UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON); + break; + + case TYPE_APP_PANEL: + case TYPE_DIALOG: + case TYPE_IME_MENU: + break; + + case TYPE_UNDEFINED: + NOTREACHED() << "ShelfItemType must be set."; + break; + } + + ShelfItemDelegate::PerformedAction performed_action = + item_manager_ + ->GetShelfItemDelegate(model_->items()[last_pressed_index_].id) + ->ItemSelected(event); + + shelf_button_pressed_metric_tracker_.ButtonPressed(event, sender, + performed_action); + + // For the app list menu no TRIGGERED ink drop effect is needed and it + // handles its own ACTIVATED/DEACTIVATED states. + if (performed_action == ShelfItemDelegate::kNewWindowCreated || + (performed_action != ShelfItemDelegate::kAppListMenuShown && + !ShowListMenuForView(model_->items()[last_pressed_index_], sender, event, + ink_drop))) { + ink_drop->AnimateToState(views::InkDropState::ACTION_TRIGGERED); + } + // Allow the menu to clear |scoped_target_root_window_| during OnMenuClosed. + if (!IsShowingMenu()) + scoped_target_root_window_.reset(); } bool ShelfView::ShowListMenuForView(const ShelfItem& item, @@ -1774,11 +1770,8 @@ ink_drop->AnimateToState(views::InkDropState::ACTIVATED); context_menu_id_ = item.id; - ShowMenu(list_menu_model.get(), source, gfx::Point(), false, - ui::GetMenuSourceTypeForEvent(event)); - // Menu is run synchronously, the menu is closed now and we need to go to - // the deactivated state. - ink_drop->AnimateToState(views::InkDropState::DEACTIVATED); + ShowMenu(std::move(list_menu_model), source, gfx::Point(), false, + ui::GetMenuSourceTypeForEvent(event), ink_drop); return true; } @@ -1799,20 +1792,31 @@ return; context_menu_id_ = item ? item->id : 0; - ShowMenu(context_menu_model.get(), source, point, true, source_type); + ShowMenu(std::move(context_menu_model), source, point, true, source_type, + nullptr); } -void ShelfView::ShowMenu(ui::MenuModel* menu_model, +void ShelfView::ShowMenu(std::unique_ptr<ui::MenuModel> menu_model, views::View* source, const gfx::Point& click_point, bool context_menu, - ui::MenuSourceType source_type) { + ui::MenuSourceType source_type, + views::InkDrop* ink_drop) { + menu_model_ = std::move(menu_model); + menu_model_adapter_.reset(new views::MenuModelAdapter( + menu_model_.get(), + base::Bind(&ShelfView::OnMenuClosed, base::Unretained(this), ink_drop))); + closing_event_time_ = base::TimeTicks(); - launcher_menu_runner_.reset(new views::MenuRunner( - menu_model, context_menu ? views::MenuRunner::CONTEXT_MENU : 0)); + int run_types = views::MenuRunner::ASYNC; + if (context_menu) + run_types |= views::MenuRunner::CONTEXT_MENU; + launcher_menu_runner_.reset( + new views::MenuRunner(menu_model_adapter_->CreateMenu(), run_types)); aura::Window* window = source->GetWidget()->GetNativeWindow(); - ScopedTargetRootWindow scoped_target(window->GetRootWindow()); + scoped_target_root_window_.reset( + new ScopedTargetRootWindow(window->GetRootWindow())); views::MenuAnchorPosition menu_alignment = views::MENU_ANCHOR_TOPLEFT; gfx::Rect anchor = gfx::Rect(click_point, gfx::Size()); @@ -1833,34 +1837,31 @@ views::MENU_ANCHOR_BUBBLE_ABOVE, views::MENU_ANCHOR_BUBBLE_RIGHT, views::MENU_ANCHOR_BUBBLE_LEFT); } - // If this is deleted while the menu is running, the shelf will also be gone. - bool got_deleted = false; - got_deleted_ = &got_deleted; - ShelfWidget* shelf_widget = shelf_->shelf_widget(); - shelf_widget->ForceUndimming(true); + shelf_->shelf_widget()->ForceUndimming(true); // NOTE: if you convert to HAS_MNEMONICS be sure to update menu building code. - if (launcher_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, anchor, - menu_alignment, source_type) == - views::MenuRunner::MENU_DELETED) { - if (!got_deleted) { - got_deleted_ = nullptr; - context_menu_id_ = 0; - shelf_widget->ForceUndimming(false); - } - return; - } - got_deleted_ = nullptr; + launcher_menu_runner_->RunMenuAt(source->GetWidget(), nullptr, anchor, + menu_alignment, source_type); +} + +void ShelfView::OnMenuClosed(views::InkDrop* ink_drop) { context_menu_id_ = 0; - shelf_widget->ForceUndimming(false); + shelf_->shelf_widget()->ForceUndimming(false); // Hide the hide overflow bubble after showing a context menu for its items. if (owner_overflow_bubble_) owner_overflow_bubble_->HideBubbleAndRefreshButton(); - // Unpinning an item will reset |launcher_menu_runner_| before coming here. - if (launcher_menu_runner_) - closing_event_time_ = launcher_menu_runner_->closing_event_time(); + closing_event_time_ = launcher_menu_runner_->closing_event_time(); + + if (ink_drop) + ink_drop->AnimateToState(views::InkDropState::DEACTIVATED); + + launcher_menu_runner_.reset(); + menu_model_adapter_.reset(); + menu_model_.reset(); + scoped_target_root_window_.reset(); + Shell::GetInstance()->UpdateShelfVisibility(); }
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index dbd1811..64799a19 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -33,6 +33,7 @@ namespace views { class BoundsAnimator; +class MenuModelAdapter; class MenuRunner; } @@ -41,6 +42,7 @@ class DragImageView; class OverflowBubble; class OverflowButton; +class ScopedTargetRootWindow; class Shelf; class ShelfButton; class ShelfDelegate; @@ -311,11 +313,15 @@ // If |context_menu| is set, the displayed menu is a context menu and not // a menu listing one or more running applications. // The |click_point| is only used for |context_menu|'s. - void ShowMenu(ui::MenuModel* menu_model, + void ShowMenu(std::unique_ptr<ui::MenuModel> menu_model, views::View* source, const gfx::Point& click_point, bool context_menu, - ui::MenuSourceType source_type); + ui::MenuSourceType source_type, + views::InkDrop* ink_drop); + + // Callback for MenuModelAdapter. + void OnMenuClosed(views::InkDrop* ink_drop); // Overridden from views::BoundsAnimatorObserver: void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override; @@ -385,7 +391,11 @@ std::unique_ptr<views::FocusSearch> focus_search_; + // Manages the context menu, and the list menu. + std::unique_ptr<ui::MenuModel> menu_model_; + std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_; std::unique_ptr<views::MenuRunner> launcher_menu_runner_; + std::unique_ptr<ScopedTargetRootWindow> scoped_target_root_window_; base::ObserverList<ShelfIconObserver> observers_; @@ -405,10 +415,6 @@ // The timestamp of the event which closed the last menu - or 0. base::TimeTicks closing_event_time_; - // When this object gets deleted while a menu is shown, this pointed - // element will be set to false. - bool* got_deleted_; - // True if a drag and drop operation created/pinned the item in the launcher // and it needs to be deleted/unpinned again if the operation gets cancelled. bool drag_and_drop_item_pinned_;
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 40cec06..43eba9d 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -2583,16 +2583,12 @@ EXPECT_THAT(browser_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::ACTION_PENDING)); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ShelfViewTestAPI::CloseMenu, - base::Unretained(test_api_.get()))); - - // Mouse release will spawn a menu which will then get closed by the above - // posted task. + // Mouse release will spawn a menu which we will then close. ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, mouse_location, mouse_location, ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); button->OnMouseReleased(release_event); + test_api_->CloseMenu(); EXPECT_EQ(views::InkDropState::HIDDEN, browser_button_ink_drop_->GetTargetInkDropState()); EXPECT_THAT(browser_button_ink_drop_->GetAndResetRequestedStates(),
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc b/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc index 02b7103..4164e8bf 100644 --- a/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc +++ b/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc
@@ -4,7 +4,7 @@ #include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h" -#include "ash/ash_view_ids.h" +#include "ash/common/ash_view_ids.h" #include "ash/common/media_delegate.h" #include "ash/common/session/session_state_delegate.h" #include "ash/common/system/chromeos/media_security/media_capture_observer.h"
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc b/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc index ea9baffb..15072c7 100644 --- a/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc +++ b/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
@@ -4,7 +4,7 @@ #include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h" -#include "ash/ash_view_ids.h" +#include "ash/common/ash_view_ids.h" #include "ash/common/system/tray/system_tray_bubble.h" #include "ash/common/system/tray/tray_item_view.h" #include "ash/system/status_area_widget.h"
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc index 5526e3fd..8691317 100644 --- a/ash/system/tray/system_tray.cc +++ b/ash/system/tray/system_tray.cc
@@ -18,13 +18,13 @@ #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray_accessibility.h" #include "ash/common/system/update/tray_update.h" +#include "ash/common/system/user/tray_user.h" #include "ash/common/system/user/tray_user_separator.h" #include "ash/common/system/web_notification/web_notification_tray.h" #include "ash/common/wm_lookup.h" #include "ash/common/wm_root_window_controller.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "ash/system/user/tray_user.h" #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/system/user/DEPS b/ash/system/user/DEPS deleted file mode 100644 index a6b411b..0000000 --- a/ash/system/user/DEPS +++ /dev/null
@@ -1,4 +0,0 @@ -include_rules = [ - # This directory is being migrated to //ash/common types. - "-ui/aura", -]
diff --git a/ash/sysui/sysui_application.cc b/ash/sysui/sysui_application.cc index adef771..61e1b9a3 100644 --- a/ash/sysui/sysui_application.cc +++ b/ash/sysui/sysui_application.cc
@@ -32,7 +32,6 @@ #include "base/threading/sequenced_worker_pool.h" #include "services/catalog/public/cpp/resource_loader.h" #include "services/shell/public/cpp/connector.h" -#include "services/ui/common/gpu_service.h" #include "services/ui/public/cpp/property_type_converters.h" #include "services/ui/public/interfaces/input_devices/input_device_server.mojom.h" #include "ui/aura/env.h" @@ -309,8 +308,6 @@ void SysUIApplication::OnStart(::shell::Connector* connector, const ::shell::Identity& identity, uint32_t id) { - ui::GpuService::Initialize(connector); - ash_init_.reset(new AshInit()); ash_init_->Initialize(connector, identity);
diff --git a/base/BUILD.gn b/base/BUILD.gn index 6cd965d..e44570c 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -406,8 +406,6 @@ "mac/launch_services_util.h", "mac/launchd.cc", "mac/launchd.h", - "mac/libdispatch_task_runner.cc", - "mac/libdispatch_task_runner.h", "mac/mac_logging.h", "mac/mac_logging.mm", "mac/mac_util.h", @@ -1794,7 +1792,6 @@ "mac/call_with_eh_frame_unittest.mm", "mac/dispatch_source_mach_unittest.cc", "mac/foundation_util_unittest.mm", - "mac/libdispatch_task_runner_unittest.cc", "mac/mac_util_unittest.mm", "mac/mach_port_broker_unittest.cc", "mac/objc_property_releaser_unittest.mm",
diff --git a/base/base.gyp b/base/base.gyp index f8764797..0c1ad352 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -450,7 +450,6 @@ 'mac/call_with_eh_frame_unittest.mm', 'mac/dispatch_source_mach_unittest.cc', 'mac/foundation_util_unittest.mm', - 'mac/libdispatch_task_runner_unittest.cc', 'mac/mac_util_unittest.mm', 'mac/mach_port_broker_unittest.cc', 'mac/objc_property_releaser_unittest.mm',
diff --git a/base/base.gypi b/base/base.gypi index d335b97..cb41e79 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -297,8 +297,6 @@ 'mac/launch_services_util.h', 'mac/launchd.cc', 'mac/launchd.h', - 'mac/libdispatch_task_runner.cc', - 'mac/libdispatch_task_runner.h', 'mac/mac_logging.h', 'mac/mac_logging.mm', 'mac/mac_util.h',
diff --git a/base/bind_internal.h b/base/bind_internal.h index 6b692a8..41c34ff 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h
@@ -46,6 +46,60 @@ // BindState<> -- Stores the curried parameters, and is the main entry point // into the Bind() system. +template <typename...> +struct make_void { + using type = void; +}; + +// A clone of C++17 std::void_t. +// Unlike the original version, we need |make_void| as a helper struct to avoid +// a C++14 defect. +// ref: http://en.cppreference.com/w/cpp/types/void_t +// ref: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558 +template <typename... Ts> +using void_t = typename make_void<Ts...>::type; + +template <typename Callable, + typename Signature = decltype(&Callable::operator())> +struct ExtractCallableRunTypeImpl; + +template <typename Callable, typename R, typename... Args> +struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> { + using Type = R(Args...); +}; + +// Evaluated to RunType of the given callable type. +// Example: +// auto f = [](int, char*) { return 0.1; }; +// ExtractCallableRunType<decltype(f)> +// is evaluated to +// double(int, char*); +template <typename Callable> +using ExtractCallableRunType = + typename ExtractCallableRunTypeImpl<Callable>::Type; + +// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator() +// and convertible to the corresponding function pointer. Otherwise, it's +// std::false_type. +// Example: +// IsConvertibleToRunType<void(*)()>::value is false. +// +// struct Foo {}; +// IsConvertibleToRunType<void(Foo::*)()>::value is false. +// +// auto f = []() {}; +// IsConvertibleToRunType<decltype(f)>::value is true. +// +// int i = 0; +// auto g = [i]() {}; +// IsConvertibleToRunType<decltype(g)>::value is false. +template <typename Functor, typename SFINAE = void> +struct IsConvertibleToRunType : std::false_type {}; + +template <typename Callable> +struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>> + : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {}; + // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw // pointer to a RefCounted type. // Implementation note: This non-specialized case handles zero-arity case only. @@ -76,14 +130,34 @@ // FunctorTraits<> // // See description at top of file. -template <typename Functor> +template <typename Functor, typename SFINAE = void> struct FunctorTraits; +// For a callable type that is convertible to the corresponding function type. +// This specialization is intended to allow binding captureless lambdas by +// base::Bind(), based on the fact that captureless lambdas can be convertible +// to the function type while capturing lambdas can't. +template <typename Functor> +struct FunctorTraits< + Functor, + typename std::enable_if<IsConvertibleToRunType<Functor>::value>::type> { + using RunType = ExtractCallableRunType<Functor>; + static constexpr bool is_method = false; + static constexpr bool is_nullable = false; + + template <typename... RunArgs> + static ExtractReturnType<RunType> + Invoke(const Functor& functor, RunArgs&&... args) { + return functor(std::forward<RunArgs>(args)...); + } +}; + // For functions. template <typename R, typename... Args> struct FunctorTraits<R (*)(Args...)> { using RunType = R(Args...); static constexpr bool is_method = false; + static constexpr bool is_nullable = true; template <typename... RunArgs> static R Invoke(R (*function)(Args...), RunArgs&&... args) { @@ -98,6 +172,7 @@ struct FunctorTraits<R(__stdcall*)(Args...)> { using RunType = R(Args...); static constexpr bool is_method = false; + static constexpr bool is_nullable = true; template <typename... RunArgs> static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) { @@ -110,6 +185,7 @@ struct FunctorTraits<R(__fastcall*)(Args...)> { using RunType = R(Args...); static constexpr bool is_method = false; + static constexpr bool is_nullable = true; template <typename... RunArgs> static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) { @@ -124,6 +200,7 @@ struct FunctorTraits<R (Receiver::*)(Args...)> { using RunType = R(Receiver*, Args...); static constexpr bool is_method = true; + static constexpr bool is_nullable = true; template <typename ReceiverPtr, typename... RunArgs> static R Invoke(R (Receiver::*method)(Args...), @@ -143,6 +220,7 @@ struct FunctorTraits<R (Receiver::*)(Args...) const> { using RunType = R(const Receiver*, Args...); static constexpr bool is_method = true; + static constexpr bool is_nullable = true; template <typename ReceiverPtr, typename... RunArgs> static R Invoke(R (Receiver::*method)(Args...) const, @@ -176,6 +254,7 @@ struct FunctorTraits<Callback<R(Args...), copy_mode>> { using RunType = R(Args...); static constexpr bool is_method = false; + static constexpr bool is_nullable = true; template <typename CallbackType, typename... RunArgs> static R Invoke(CallbackType&& callback, RunArgs&&... args) { @@ -281,6 +360,17 @@ using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>; using Type = MakeFunctionType<ReturnType, UnboundArgs>; }; +template <typename Functor> +typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type +IsNull(const Functor& functor) { + return !functor; +} + +template <typename Functor> +typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type +IsNull(const Functor&) { + return false; +} // BindState<> // @@ -292,7 +382,7 @@ : BindStateBase(&Destroy), functor_(std::move(functor)), bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) { - DCHECK(functor_); + DCHECK(!IsNull(functor_)); } Functor functor_;
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index 5a7ce386..a14e761 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc
@@ -1038,6 +1038,36 @@ EXPECT_EQ(0, move_assigns); } +TEST_F(BindTest, CapturelessLambda) { + EXPECT_FALSE(internal::IsConvertibleToRunType<void>::value); + EXPECT_FALSE(internal::IsConvertibleToRunType<int>::value); + EXPECT_FALSE(internal::IsConvertibleToRunType<void(*)()>::value); + EXPECT_FALSE(internal::IsConvertibleToRunType<void(NoRef::*)()>::value); + + auto f = []() {}; + EXPECT_TRUE(internal::IsConvertibleToRunType<decltype(f)>::value); + + int i = 0; + auto g = [i]() {}; + EXPECT_FALSE(internal::IsConvertibleToRunType<decltype(g)>::value); + + auto h = [](int, double) { return 'k'; }; + EXPECT_TRUE((std::is_same< + char(int, double), + internal::ExtractCallableRunType<decltype(h)>>::value)); + + EXPECT_EQ(42, Bind([] { return 42; }).Run()); + EXPECT_EQ(42, Bind([](int i) { return i * 7; }, 6).Run()); + + int x = 1; + base::Callback<void(int)> cb = + Bind([](int* x, int i) { *x *= i; }, Unretained(&x)); + cb.Run(6); + EXPECT_EQ(6, x); + cb.Run(7); + EXPECT_EQ(42, x); +} + // Callback construction and assignment tests. // - Construction from an InvokerStorageHolder should not cause ref/deref. // - Assignment from other callback should only cause one ref
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc index bdbcd2f2..e60de076 100644 --- a/base/bind_unittest.nc +++ b/base/bind_unittest.nc
@@ -201,6 +201,13 @@ Closure callback_mismatches_bind_type = Bind(&VoidPolymorphic1<int>); } +#elif defined(NCTEST_DISALLOW_CAPTURING_LAMBDA) // [r"fatal error: implicit instantiation of undefined template 'base::internal::FunctorTraits<\(lambda at ../../base/bind_unittest.nc:[0-9]+:[0-9]+\), void>'"] + +void WontCompile() { + int i = 0; + Bind([i]() {}); +} + #endif } // namespace base
diff --git a/base/callback_helpers.cc b/base/callback_helpers.cc index 8fd3dde..838e6c8d 100644 --- a/base/callback_helpers.cc +++ b/base/callback_helpers.cc
@@ -23,21 +23,18 @@ ScopedClosureRunner& ScopedClosureRunner::operator=( ScopedClosureRunner&& other) { - Reset(other.Release()); + ReplaceClosure(other.Release()); return *this; } -void ScopedClosureRunner::Reset() { +void ScopedClosureRunner::RunAndReset() { Closure old_closure = Release(); if (!old_closure.is_null()) old_closure.Run(); } -void ScopedClosureRunner::Reset(const Closure& closure) { - Closure old_closure = Release(); +void ScopedClosureRunner::ReplaceClosure(const Closure& closure) { closure_ = closure; - if (!old_closure.is_null()) - old_closure.Run(); } Closure ScopedClosureRunner::Release() {
diff --git a/base/callback_helpers.h b/base/callback_helpers.h index c4b0d867..782371f 100644 --- a/base/callback_helpers.h +++ b/base/callback_helpers.h
@@ -37,15 +37,15 @@ ScopedClosureRunner(ScopedClosureRunner&& other); - // Calls the current closure if it's set and replaces it with the closure from - // |other|. + // Releases the current closure if it's set and replaces it with the closure + // from |other|. ScopedClosureRunner& operator=(ScopedClosureRunner&& other); // Calls the current closure and resets it, so it wont be called again. - void Reset(); + void RunAndReset(); - // Calls the current closure and replaces it with the new one. - void Reset(const Closure& closure); + // Replaces closure with the new one releasing the old one without calling it. + void ReplaceClosure(const Closure& closure); // Releases the Closure without calling. Closure Release() WARN_UNUSED_RESULT;
diff --git a/base/callback_helpers_unittest.cc b/base/callback_helpers_unittest.cc index 0e42852..82839963 100644 --- a/base/callback_helpers_unittest.cc +++ b/base/callback_helpers_unittest.cc
@@ -14,7 +14,7 @@ (*value)++; } -TEST(BindHelpersTest, TestScopedClosureRunnerExitScope) { +TEST(CallbackHelpersTest, TestScopedClosureRunnerExitScope) { int run_count = 0; { base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count)); @@ -23,7 +23,7 @@ EXPECT_EQ(1, run_count); } -TEST(BindHelpersTest, TestScopedClosureRunnerRelease) { +TEST(CallbackHelpersTest, TestScopedClosureRunnerRelease) { int run_count = 0; base::Closure c; { @@ -36,29 +36,32 @@ EXPECT_EQ(1, run_count); } -TEST(BindHelpersTest, TestScopedClosureRunnerReset) { +TEST(CallbackHelpersTest, TestScopedClosureRunnerReplaceClosure) { int run_count_1 = 0; int run_count_2 = 0; { base::ScopedClosureRunner runner; - runner.Reset(base::Bind(&Increment, &run_count_1)); - runner.Reset(base::Bind(&Increment, &run_count_2)); - EXPECT_EQ(1, run_count_1); + runner.ReplaceClosure(base::Bind(&Increment, &run_count_1)); + runner.ReplaceClosure(base::Bind(&Increment, &run_count_2)); + EXPECT_EQ(0, run_count_1); EXPECT_EQ(0, run_count_2); } + EXPECT_EQ(0, run_count_1); EXPECT_EQ(1, run_count_2); +} +TEST(CallbackHelpersTest, TestScopedClosureRunnerRunAndReset) { int run_count_3 = 0; { base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count_3)); EXPECT_EQ(0, run_count_3); - runner.Reset(); + runner.RunAndReset(); EXPECT_EQ(1, run_count_3); } EXPECT_EQ(1, run_count_3); } -TEST(BindHelpersTest, TestScopedClosureRunnerMoveConstructor) { +TEST(CallbackHelpersTest, TestScopedClosureRunnerMoveConstructor) { int run_count = 0; { std::unique_ptr<base::ScopedClosureRunner> runner( @@ -70,35 +73,22 @@ EXPECT_EQ(1, run_count); } -TEST(BindHelpersTest, TestScopedClosureRunnerMoveAssignment) { - int run_count = 0; +TEST(CallbackHelpersTest, TestScopedClosureRunnerMoveAssignment) { + int run_count_1 = 0; + int run_count_2 = 0; { - base::ScopedClosureRunner runner; + base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count_1)); { - base::ScopedClosureRunner runner2(base::Bind(&Increment, &run_count)); + base::ScopedClosureRunner runner2(base::Bind(&Increment, &run_count_2)); runner = std::move(runner2); + EXPECT_EQ(0, run_count_1); + EXPECT_EQ(0, run_count_2); } - EXPECT_EQ(0, run_count); + EXPECT_EQ(0, run_count_1); + EXPECT_EQ(0, run_count_2); } - EXPECT_EQ(1, run_count); -} - -TEST(BindHelpersTest, TestScopedClosureRunnerRunOnReplace) { - int run_count1 = 0; - int run_count2 = 0; - { - base::ScopedClosureRunner runner1(base::Bind(&Increment, &run_count1)); - { - base::ScopedClosureRunner runner2(base::Bind(&Increment, &run_count2)); - runner1 = std::move(runner2); - EXPECT_EQ(1, run_count1); - EXPECT_EQ(0, run_count2); - } - EXPECT_EQ(1, run_count1); - EXPECT_EQ(0, run_count2); - } - EXPECT_EQ(1, run_count1); - EXPECT_EQ(1, run_count2); + EXPECT_EQ(0, run_count_1); + EXPECT_EQ(1, run_count_2); } } // namespace
diff --git a/base/feature_list.cc b/base/feature_list.cc index 4673210..435165e1 100644 --- a/base/feature_list.cc +++ b/base/feature_list.cc
@@ -23,6 +23,9 @@ // have more control over initialization timing. Leaky. FeatureList* g_instance = nullptr; +// Tracks whether the FeatureList instance was initialized via an accessor. +bool g_initialized_from_accessor = false; + // Some characters are not allowed to appear in feature names or the associated // field trial names, as they are used as special characters for command-line // serialization. This function checks that the strings are ASCII (since they @@ -35,10 +38,7 @@ } // namespace -FeatureList::FeatureList() - : initialized_(false), - initialized_from_command_line_(false) { -} +FeatureList::FeatureList() {} FeatureList::~FeatureList() {} @@ -133,7 +133,11 @@ // static bool FeatureList::IsEnabled(const Feature& feature) { - return GetInstance()->IsFeatureEnabled(feature); + if (!g_instance) { + g_initialized_from_accessor = true; + return feature.default_state == FEATURE_ENABLED_BY_DEFAULT; + } + return g_instance->IsFeatureEnabled(feature); } // static @@ -158,6 +162,10 @@ // For example, we initialize an instance in chrome/browser/ // chrome_browser_main.cc and do not override it in content/browser/ // browser_main_loop.cc. + // If the singleton was previously initialized from within an accessor, we + // want to prevent callers from reinitializing the singleton and masking the + // accessor call(s) which likely returned incorrect information. + CHECK(!g_initialized_from_accessor); bool instance_existed_before = false; if (g_instance) { if (g_instance->initialized_from_command_line_) @@ -192,6 +200,7 @@ void FeatureList::ClearInstanceForTesting() { delete g_instance; g_instance = nullptr; + g_initialized_from_accessor = false; } void FeatureList::FinalizeInitialization() {
diff --git a/base/feature_list.h b/base/feature_list.h index 2a47427f..e9ed00a 100644 --- a/base/feature_list.h +++ b/base/feature_list.h
@@ -247,10 +247,10 @@ // Whether this object has been fully initialized. This gets set to true as a // result of FinalizeInitialization(). - bool initialized_; + bool initialized_ = false; // Whether this object has been initialized from command line. - bool initialized_from_command_line_; + bool initialized_from_command_line_ = false; DISALLOW_COPY_AND_ASSIGN(FeatureList); };
diff --git a/base/feature_list_unittest.cc b/base/feature_list_unittest.cc index a7e7b711..9d1dcb7 100644 --- a/base/feature_list_unittest.cc +++ b/base/feature_list_unittest.cc
@@ -457,4 +457,15 @@ EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault)); } +TEST_F(FeatureListTest, UninitializedInstance_IsEnabledReturnsFalse) { + ClearFeatureListInstance(); + // This test case simulates the calling pattern found in code which does not + // explicitly initialize the features list. + // All IsEnabled() calls should return the default value in this scenario. + EXPECT_EQ(nullptr, FeatureList::GetInstance()); + EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault)); + EXPECT_EQ(nullptr, FeatureList::GetInstance()); + EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault)); +} + } // namespace base
diff --git a/base/files/file_path.cc b/base/files/file_path.cc index ca0d1d1b..0b06493 100644 --- a/base/files/file_path.cc +++ b/base/files/file_path.cc
@@ -537,7 +537,7 @@ bool FilePath::EndsWithSeparator() const { if (empty()) return false; - return IsSeparator(path_[path_.size() - 1]); + return IsSeparator(path_.back()); } FilePath FilePath::AsEndingWithSeparator() const {
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc index 824e3d8a..e9d2508 100644 --- a/base/files/file_path_watcher_fsevents.cc +++ b/base/files/file_path_watcher_fsevents.cc
@@ -4,16 +4,18 @@ #include "base/files/file_path_watcher_fsevents.h" +#include <dispatch/dispatch.h> + #include <list> #include "base/bind.h" #include "base/files/file_util.h" #include "base/lazy_instance.h" #include "base/logging.h" -#include "base/mac/libdispatch_task_runner.h" #include "base/mac/scoped_cftyperef.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" +#include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" namespace base { @@ -23,19 +25,6 @@ // The latency parameter passed to FSEventsStreamCreate(). const CFAbsoluteTime kEventLatencySeconds = 0.3; -class FSEventsTaskRunner : public mac::LibDispatchTaskRunner { - public: - FSEventsTaskRunner() - : mac::LibDispatchTaskRunner("org.chromium.FilePathWatcherFSEvents") { - } - - protected: - ~FSEventsTaskRunner() override {} -}; - -static LazyInstance<FSEventsTaskRunner>::Leaky g_task_runner = - LAZY_INSTANCE_INITIALIZER; - // Resolve any symlinks in the path. FilePath ResolvePath(const FilePath& path) { const unsigned kMaxLinksToResolve = 255; @@ -79,7 +68,12 @@ } // namespace -FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) { +FilePathWatcherFSEvents::FilePathWatcherFSEvents() + : queue_(dispatch_queue_create( + base::StringPrintf( + "org.chromium.base.FilePathWatcher.%p", this).c_str(), + DISPATCH_QUEUE_SERIAL)), + fsevent_stream_(nullptr) { } bool FilePathWatcherFSEvents::Watch(const FilePath& path, @@ -98,9 +92,14 @@ callback_ = callback; FSEventStreamEventId start_event = FSEventsGetCurrentEventId(); - g_task_runner.Get().PostTask( - FROM_HERE, Bind(&FilePathWatcherFSEvents::StartEventStream, this, - start_event, path)); + // The block runtime would implicitly capture the reference, not the object + // it's referencing. Copy the path into a local, so that the value is + // captured by the block's scope. + const FilePath path_copy(path); + + dispatch_async(queue_, ^{ + StartEventStream(start_event, path_copy); + }); return true; } @@ -108,10 +107,12 @@ set_cancelled(); callback_.Reset(); - // Switch to the dispatch queue thread to tear down the event stream. - g_task_runner.Get().PostTask( - FROM_HERE, - Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this)); + // Switch to the dispatch queue to tear down the event stream. As the queue + // is owned by this object, and this method is called from the destructor, + // execute the block synchronously. + dispatch_sync(queue_, ^{ + CancelOnMessageLoopThread(); + }); } // static @@ -124,8 +125,6 @@ const FSEventStreamEventId event_ids[]) { FilePathWatcherFSEvents* watcher = reinterpret_cast<FilePathWatcherFSEvents*>(event_watcher); - DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread()); - bool root_changed = watcher->ResolveTargetPath(); std::vector<FilePath> paths; FSEventStreamEventId root_change_at = FSEventStreamGetLatestEventId(stream); @@ -144,10 +143,9 @@ if (root_changed) { // Resetting the event stream from within the callback fails (FSEvents spews // bad file descriptor errors), so post a task to do the reset. - g_task_runner.Get().PostTask( - FROM_HERE, - Bind(&FilePathWatcherFSEvents::UpdateEventStream, watcher, - root_change_at)); + dispatch_async(watcher->queue_, ^{ + watcher->UpdateEventStream(root_change_at); + }); } watcher->OnFilePathsChanged(paths); @@ -165,7 +163,6 @@ void FilePathWatcherFSEvents::OnFilePathsChanged( const std::vector<FilePath>& paths) { - DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread()); DCHECK(!resolved_target_.empty()); task_runner()->PostTask( FROM_HERE, Bind(&FilePathWatcherFSEvents::DispatchEvents, this, paths, @@ -194,7 +191,6 @@ // For all other implementations, the "message loop thread" is the IO thread, // as returned by task_runner(). This implementation, however, needs to // cancel pending work on the Dispatch Queue thread. - DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread()); if (fsevent_stream_) { DestroyEventStream(); @@ -205,8 +201,6 @@ void FilePathWatcherFSEvents::UpdateEventStream( FSEventStreamEventId start_event) { - DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread()); - // It can happen that the watcher gets canceled while tasks that call this // function are still in flight, so abort if this situation is detected. if (resolved_target_.empty()) @@ -237,8 +231,7 @@ start_event, kEventLatencySeconds, kFSEventStreamCreateFlagWatchRoot); - FSEventStreamSetDispatchQueue(fsevent_stream_, - g_task_runner.Get().GetDispatchQueue()); + FSEventStreamSetDispatchQueue(fsevent_stream_, queue_); if (!FSEventStreamStart(fsevent_stream_)) { task_runner()->PostTask( @@ -247,7 +240,6 @@ } bool FilePathWatcherFSEvents::ResolveTargetPath() { - DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread()); FilePath resolved = ResolvePath(target_).StripTrailingSeparators(); bool changed = resolved != resolved_target_; resolved_target_ = resolved; @@ -274,7 +266,6 @@ void FilePathWatcherFSEvents::StartEventStream(FSEventStreamEventId start_event, const FilePath& path) { - DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread()); DCHECK(resolved_target_.empty()); target_ = path;
diff --git a/base/files/file_path_watcher_fsevents.h b/base/files/file_path_watcher_fsevents.h index 1ebe463..cfbe020b 100644 --- a/base/files/file_path_watcher_fsevents.h +++ b/base/files/file_path_watcher_fsevents.h
@@ -12,6 +12,7 @@ #include "base/files/file_path.h" #include "base/files/file_path_watcher.h" +#include "base/mac/scoped_dispatch_object.h" #include "base/macros.h" namespace base { @@ -76,16 +77,19 @@ // (Only accessed from the message_loop() thread.) FilePathWatcher::Callback callback_; + // The dispatch queue on which the the event stream is scheduled. + ScopedDispatchObject<dispatch_queue_t> queue_; + // Target path to watch (passed to callback). - // (Only accessed from the libdispatch thread.) + // (Only accessed from the libdispatch queue.) FilePath target_; // Target path with all symbolic links resolved. - // (Only accessed from the libdispatch thread.) + // (Only accessed from the libdispatch queue.) FilePath resolved_target_; // Backend stream we receive event callbacks from (strong reference). - // (Only accessed from the libdispatch thread.) + // (Only accessed from the libdispatch queue.) FSEventStreamRef fsevent_stream_; DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents);
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc index ae293fe8..87bddd3 100644 --- a/base/files/file_path_watcher_linux.cc +++ b/base/files/file_path_watcher_linux.cc
@@ -677,7 +677,7 @@ if (watches_[i].subdir.empty()) return false; } - return watches_[watches_.size() - 1].subdir.empty(); + return watches_.back().subdir.empty(); } } // namespace
diff --git a/base/logging.h b/base/logging.h index fd148aa..f06535da 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -456,11 +456,17 @@ // Make all CHECK functions discard their log strings to reduce code // bloat, and improve performance, for official release builds. -// TODO(akalin): This would be more valuable if there were some way to -// remove BreakDebugger() from the backtrace, perhaps by turning it -// into a macro (like __debugbreak() on Windows). +#if defined(COMPILER_GCC) || __clang__ +#define LOGGING_CRASH() __builtin_trap() +#else +#define LOGGING_CRASH() ((void)(*(volatile char*)0 = 0)) +#endif + +// This is not calling BreakDebugger since this is called frequently, and +// calling an out-of-line function instead of a noreturn inline macro prevents +// compiler optimizations. #define CHECK(condition) \ - !(condition) ? ::base::debug::BreakDebugger() : EAT_STREAM_PARAMETERS + !(condition) ? LOGGING_CRASH() : EAT_STREAM_PARAMETERS #define PCHECK(condition) CHECK(condition)
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm index d872fc3..4f6fa60a 100644 --- a/base/mac/foundation_util.mm +++ b/base/mac/foundation_util.mm
@@ -155,7 +155,7 @@ exec_name.GetComponents(&components); // It's an error if we don't get any components. - if (!components.size()) + if (components.empty()) return FilePath(); // Don't prepend '/' to the first component.
diff --git a/base/mac/libdispatch_task_runner.cc b/base/mac/libdispatch_task_runner.cc deleted file mode 100644 index dcbeecc..0000000 --- a/base/mac/libdispatch_task_runner.cc +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/mac/libdispatch_task_runner.h" - -#include <stdint.h> - -#include "base/callback.h" - -namespace base { -namespace mac { - -LibDispatchTaskRunner::LibDispatchTaskRunner(const char* name) - : queue_(dispatch_queue_create(name, NULL)), - queue_finalized_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED) { - dispatch_set_context(queue_, this); - dispatch_set_finalizer_f(queue_, &LibDispatchTaskRunner::Finalizer); -} - -bool LibDispatchTaskRunner::PostDelayedTask( - const tracked_objects::Location& from_here, - const Closure& task, - base::TimeDelta delay) { - if (!queue_) - return false; - - // The block runtime would implicitly copy the reference, not the object - // it's referencing. Copy the closure into block storage so it's available - // to run. - __block const Closure task_copy = task; - void(^run_task)(void) = ^{ - task_copy.Run(); - }; - - int64_t delay_nano = - delay.InMicroseconds() * base::Time::kNanosecondsPerMicrosecond; - if (delay_nano > 0) { - dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay_nano); - dispatch_after(time, queue_, run_task); - } else { - dispatch_async(queue_, run_task); - } - return true; -} - -bool LibDispatchTaskRunner::RunsTasksOnCurrentThread() const { - return queue_ == dispatch_get_current_queue(); -} - -bool LibDispatchTaskRunner::PostNonNestableDelayedTask( - const tracked_objects::Location& from_here, - const Closure& task, - base::TimeDelta delay) { - return PostDelayedTask(from_here, task, delay); -} - -void LibDispatchTaskRunner::Shutdown() { - dispatch_release(queue_); - queue_ = NULL; - queue_finalized_.Wait(); -} - -dispatch_queue_t LibDispatchTaskRunner::GetDispatchQueue() const { - return queue_; -} - -LibDispatchTaskRunner::~LibDispatchTaskRunner() { - if (queue_) { - dispatch_set_context(queue_, NULL); - dispatch_set_finalizer_f(queue_, NULL); - dispatch_release(queue_); - } -} - -void LibDispatchTaskRunner::Finalizer(void* context) { - LibDispatchTaskRunner* self = static_cast<LibDispatchTaskRunner*>(context); - self->queue_finalized_.Signal(); -} - -} // namespace mac -} // namespace base
diff --git a/base/mac/libdispatch_task_runner.h b/base/mac/libdispatch_task_runner.h deleted file mode 100644 index b479bc7..0000000 --- a/base/mac/libdispatch_task_runner.h +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_ -#define BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_ - -#include <dispatch/dispatch.h> - -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" - -namespace base { -namespace mac { - -// This is an implementation of the TaskRunner interface that runs closures on -// a thread managed by Apple's libdispatch. This has the benefit of being able -// to PostTask() and friends to a dispatch queue, while being reusable as a -// dispatch_queue_t. -// -// One would use this class if an object lives exclusively on one thread but -// needs a dispatch_queue_t for use in a system API. This ensures all dispatch -// callbacks happen on the same thread as Closure tasks. -// -// A LibDispatchTaskRunner will continue to run until all references to the -// underlying dispatch queue are released. -// -// Important Notes: -// - There is no MessageLoop running on this thread, and ::current() returns -// NULL. -// - No nested loops can be run, and all tasks are run non-nested. -// - Work scheduled via libdispatch runs at the same priority as and is -// interleaved with posted tasks, though FIFO order is guaranteed. -// -class BASE_EXPORT LibDispatchTaskRunner : public base::SingleThreadTaskRunner { - public: - // Starts a new serial dispatch queue with a given name. - explicit LibDispatchTaskRunner(const char* name); - - // base::TaskRunner: - bool PostDelayedTask(const tracked_objects::Location& from_here, - const Closure& task, - base::TimeDelta delay) override; - bool RunsTasksOnCurrentThread() const override; - - // base::SequencedTaskRunner: - bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, - const Closure& task, - base::TimeDelta delay) override; - - // This blocks the calling thread until all work on the dispatch queue has - // been run and the queue has been destroyed. Destroying a queue requires - // ALL retained references to it to be released. Any new tasks posted to - // this thread after shutdown are dropped. - void Shutdown(); - - // Returns the dispatch queue associated with this task runner, for use with - // system APIs that take dispatch queues. The caller is responsible for - // retaining the result. - // - // All properties (context, finalizer, etc.) are managed by this class, and - // clients should only use the result of this for dispatch_async(). - dispatch_queue_t GetDispatchQueue() const; - - protected: - ~LibDispatchTaskRunner() override; - - private: - static void Finalizer(void* context); - - dispatch_queue_t queue_; - - // The event on which Shutdown waits until Finalizer runs. - base::WaitableEvent queue_finalized_; -}; - -} // namespace mac -} // namespace base - -#endif // BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_
diff --git a/base/mac/libdispatch_task_runner_unittest.cc b/base/mac/libdispatch_task_runner_unittest.cc deleted file mode 100644 index a7bc928..0000000 --- a/base/mac/libdispatch_task_runner_unittest.cc +++ /dev/null
@@ -1,229 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/mac/libdispatch_task_runner.h" - -#include <stddef.h> - -#include "base/bind.h" -#include "base/mac/bind_objc_block.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/stringprintf.h" -#include "testing/gtest/include/gtest/gtest.h" - -class LibDispatchTaskRunnerTest : public testing::Test { - public: - void SetUp() override { - task_runner_ = new base::mac::LibDispatchTaskRunner( - "org.chromium.LibDispatchTaskRunnerTest"); - } - - // DispatchLastTask is used to run the main test thread's MessageLoop until - // all non-delayed tasks are run on the LibDispatchTaskRunner. - void DispatchLastTask() { - dispatch_async(task_runner_->GetDispatchQueue(), ^{ - message_loop_.task_runner()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); - }); - base::RunLoop().Run(); - task_runner_->Shutdown(); - } - - // VerifyTaskOrder takes the expectations from TaskOrderMarkers and compares - // them against the recorded values. - void VerifyTaskOrder(const char* const expectations[], - size_t num_expectations) { - size_t actual_size = task_order_.size(); - - for (size_t i = 0; i < num_expectations; ++i) { - if (i >= actual_size) { - EXPECT_LE(i, actual_size) << "Expected " << expectations[i]; - continue; - } - - EXPECT_EQ(expectations[i], task_order_[i]); - } - - if (actual_size > num_expectations) { - EXPECT_LE(actual_size, num_expectations) << "Extra tasks were run:"; - for (size_t i = num_expectations; i < actual_size; ++i) { - EXPECT_EQ("<none>", task_order_[i]) << " (i=" << i << ")"; - } - } - } - - // The message loop for the test main thread. - base::MessageLoop message_loop_; - - // The task runner under test. - scoped_refptr<base::mac::LibDispatchTaskRunner> task_runner_; - - // Vector that records data from TaskOrderMarker. - std::vector<std::string> task_order_; -}; - -// Scoper that records the beginning and end of a running task. -class TaskOrderMarker { - public: - TaskOrderMarker(LibDispatchTaskRunnerTest* test, const std::string& name) - : test_(test), - name_(name) { - test->task_order_.push_back(std::string("BEGIN ") + name); - } - ~TaskOrderMarker() { - test_->task_order_.push_back(std::string("END ") + name_); - } - - private: - LibDispatchTaskRunnerTest* test_; - std::string name_; -}; - -void RecordTaskOrder(LibDispatchTaskRunnerTest* test, const std::string& name) { - TaskOrderMarker marker(test, name); -} - -// Returns a closure that records the task order. -base::Closure BoundRecordTaskOrder(LibDispatchTaskRunnerTest* test, - const std::string& name) { - return base::Bind(&RecordTaskOrder, base::Unretained(test), name); -} - -TEST_F(LibDispatchTaskRunnerTest, PostTask) { - task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Basic Task")); - DispatchLastTask(); - const char* const expectations[] = { - "BEGIN Basic Task", - "END Basic Task" - }; - VerifyTaskOrder(expectations, arraysize(expectations)); -} - -TEST_F(LibDispatchTaskRunnerTest, PostTaskWithinTask) { - task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ - TaskOrderMarker marker(this, "Outer"); - task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Inner")); - })); - DispatchLastTask(); - - const char* const expectations[] = { - "BEGIN Outer", - "END Outer", - "BEGIN Inner", - "END Inner" - }; - VerifyTaskOrder(expectations, arraysize(expectations)); -} - -TEST_F(LibDispatchTaskRunnerTest, NoMessageLoop) { - task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ - TaskOrderMarker marker(this, - base::StringPrintf("MessageLoop = %p", base::MessageLoop::current())); - })); - DispatchLastTask(); - - const char* const expectations[] = { - "BEGIN MessageLoop = 0x0", - "END MessageLoop = 0x0" - }; - VerifyTaskOrder(expectations, arraysize(expectations)); -} - -TEST_F(LibDispatchTaskRunnerTest, DispatchAndPostTasks) { - dispatch_async(task_runner_->GetDispatchQueue(), ^{ - TaskOrderMarker marker(this, "First Block"); - }); - task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First Task")); - dispatch_async(task_runner_->GetDispatchQueue(), ^{ - TaskOrderMarker marker(this, "Second Block"); - }); - task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second Task")); - DispatchLastTask(); - - const char* const expectations[] = { - "BEGIN First Block", - "END First Block", - "BEGIN First Task", - "END First Task", - "BEGIN Second Block", - "END Second Block", - "BEGIN Second Task", - "END Second Task", - }; - VerifyTaskOrder(expectations, arraysize(expectations)); -} - -TEST_F(LibDispatchTaskRunnerTest, NonNestable) { - task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ - TaskOrderMarker marker(this, "First"); - task_runner_->PostNonNestableTask(FROM_HERE, base::BindBlock(^{ - TaskOrderMarker marker(this, "Second NonNestable"); - message_loop_.task_runner()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); - })); - })); - base::RunLoop().Run(); - task_runner_->Shutdown(); - - const char* const expectations[] = { - "BEGIN First", - "END First", - "BEGIN Second NonNestable", - "END Second NonNestable" - }; - VerifyTaskOrder(expectations, arraysize(expectations)); -} - -TEST_F(LibDispatchTaskRunnerTest, PostDelayed) { - base::TimeTicks post_time; - __block base::TimeTicks run_time; - const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(50); - - task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "First")); - post_time = base::TimeTicks::Now(); - task_runner_->PostDelayedTask(FROM_HERE, base::BindBlock(^{ - TaskOrderMarker marker(this, "Timed"); - run_time = base::TimeTicks::Now(); - message_loop_.task_runner()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); - }), delta); - task_runner_->PostTask(FROM_HERE, BoundRecordTaskOrder(this, "Second")); - base::RunLoop().Run(); - task_runner_->Shutdown(); - - const char* const expectations[] = { - "BEGIN First", - "END First", - "BEGIN Second", - "END Second", - "BEGIN Timed", - "END Timed", - }; - VerifyTaskOrder(expectations, arraysize(expectations)); - - EXPECT_GE(run_time, post_time + delta); -} - -TEST_F(LibDispatchTaskRunnerTest, PostAfterShutdown) { - EXPECT_TRUE(task_runner_->PostTask(FROM_HERE, - BoundRecordTaskOrder(this, "First"))); - EXPECT_TRUE(task_runner_->PostTask(FROM_HERE, - BoundRecordTaskOrder(this, "Second"))); - task_runner_->Shutdown(); - EXPECT_FALSE(task_runner_->PostTask(FROM_HERE, base::BindBlock(^{ - TaskOrderMarker marker(this, "Not Run"); - ADD_FAILURE() << "Should not run a task after Shutdown"; - }))); - - const char* const expectations[] = { - "BEGIN First", - "END First", - "BEGIN Second", - "END Second" - }; - VerifyTaskOrder(expectations, arraysize(expectations)); -}
diff --git a/base/memory/memory_pressure_monitor.h b/base/memory/memory_pressure_monitor.h index 6073bd3..a4adba4 100644 --- a/base/memory/memory_pressure_monitor.h +++ b/base/memory/memory_pressure_monitor.h
@@ -6,6 +6,7 @@ #define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_ #include "base/base_export.h" +#include "base/callback.h" #include "base/macros.h" #include "base/memory/memory_pressure_listener.h" @@ -23,6 +24,7 @@ class BASE_EXPORT MemoryPressureMonitor { public: using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; + using DispatchCallback = base::Callback<void(MemoryPressureLevel level)>; virtual ~MemoryPressureMonitor(); @@ -32,6 +34,10 @@ // Returns the currently observed memory pressure. virtual MemoryPressureLevel GetCurrentPressureLevel() const = 0; + // Sets a notification callback. The default callback invokes + // base::MemoryPressureListener::NotifyMemoryPressure. + virtual void SetDispatchCallback(const DispatchCallback& callback) = 0; + protected: MemoryPressureMonitor();
diff --git a/base/memory/memory_pressure_monitor_chromeos.cc b/base/memory/memory_pressure_monitor_chromeos.cc index 2d0b0a6..5138d01 100644 --- a/base/memory/memory_pressure_monitor_chromeos.cc +++ b/base/memory/memory_pressure_monitor_chromeos.cc
@@ -113,6 +113,8 @@ critical_pressure_threshold_percent_( GetCriticalMemoryThresholdInPercent(thresholds)), low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))), + dispatch_callback_( + base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), weak_ptr_factory_(this) { StartObserving(); LOG_IF(ERROR, @@ -230,7 +232,7 @@ return; } moderate_pressure_repeat_count_ = 0; - MemoryPressureListener::NotifyMemoryPressure(current_memory_pressure_level_); + dispatch_callback_.Run(current_memory_pressure_level_); } // Gets the used ChromeOS memory in percent. @@ -271,5 +273,10 @@ return percentage; } +void MemoryPressureMonitor::SetDispatchCallback( + const DispatchCallback& callback) { + dispatch_callback_ = callback; +} + } // namespace chromeos } // namespace base
diff --git a/base/memory/memory_pressure_monitor_chromeos.h b/base/memory/memory_pressure_monitor_chromeos.h index 5529c3b4..1000f300 100644 --- a/base/memory/memory_pressure_monitor_chromeos.h +++ b/base/memory/memory_pressure_monitor_chromeos.h
@@ -60,6 +60,7 @@ // Get the current memory pressure level. MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() const override; + void SetDispatchCallback(const DispatchCallback& callback) override; // Returns a type-casted version of the current memory pressure monitor. A // simple wrapper to base::MemoryPressureMonitor::Get. @@ -107,6 +108,8 @@ // File descriptor used to detect low memory condition. ScopedFD low_mem_file_; + DispatchCallback dispatch_callback_; + base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor);
diff --git a/base/memory/memory_pressure_monitor_mac.cc b/base/memory/memory_pressure_monitor_mac.cc index ec807ee..d3430e9 100644 --- a/base/memory/memory_pressure_monitor_mac.cc +++ b/base/memory/memory_pressure_monitor_mac.cc
@@ -8,6 +8,8 @@ #include <stddef.h> #include <sys/sysctl.h> +#include "base/bind.h" +#include "base/logging.h" #include "base/mac/mac_util.h" // Redeclare for partial 10.9 availability. @@ -32,11 +34,12 @@ } void MemoryPressureMonitor::NotifyMemoryPressureChanged( - dispatch_source_s* event_source) { + dispatch_source_s* event_source, + const MemoryPressureMonitor::DispatchCallback& dispatch_callback) { int mac_memory_pressure = dispatch_source_get_data(event_source); MemoryPressureListener::MemoryPressureLevel memory_pressure_level = MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure); - MemoryPressureListener::NotifyMemoryPressure(memory_pressure_level); + dispatch_callback.Run(memory_pressure_level); } MemoryPressureMonitor::MemoryPressureMonitor() @@ -47,9 +50,12 @@ DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0, DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))) { + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))), + dispatch_callback_( + base::Bind(&MemoryPressureListener::NotifyMemoryPressure)) { dispatch_source_set_event_handler(memory_level_event_source_, ^{ - NotifyMemoryPressureChanged(memory_level_event_source_.get()); + NotifyMemoryPressureChanged(memory_level_event_source_.get(), + dispatch_callback_); }); dispatch_resume(memory_level_event_source_); } @@ -67,5 +73,10 @@ return MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure); } +void MemoryPressureMonitor::SetDispatchCallback( + const DispatchCallback& callback) { + dispatch_callback_ = callback; +} + } // namespace mac } // namespace base
diff --git a/base/memory/memory_pressure_monitor_mac.h b/base/memory/memory_pressure_monitor_mac.h index b975b6e..89794f67 100644 --- a/base/memory/memory_pressure_monitor_mac.h +++ b/base/memory/memory_pressure_monitor_mac.h
@@ -28,15 +28,21 @@ // Returns the currently-observed memory pressure. MemoryPressureLevel GetCurrentPressureLevel() const override; + void SetDispatchCallback(const DispatchCallback& callback) override; + private: friend TestMemoryPressureMonitor; static MemoryPressureLevel MemoryPressureLevelForMacMemoryPressure(int mac_memory_pressure); - static void NotifyMemoryPressureChanged(dispatch_source_s* event_source); + static void NotifyMemoryPressureChanged( + dispatch_source_s* event_source, + const DispatchCallback& dispatch_callback); ScopedDispatchObject<dispatch_source_t> memory_level_event_source_; + DispatchCallback dispatch_callback_; + DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor); };
diff --git a/base/memory/memory_pressure_monitor_win.cc b/base/memory/memory_pressure_monitor_win.cc index 8ac66ce..a93b425 100644 --- a/base/memory/memory_pressure_monitor_win.cc +++ b/base/memory/memory_pressure_monitor_win.cc
@@ -82,6 +82,8 @@ current_memory_pressure_level_( MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), moderate_pressure_repeat_count_(0), + dispatch_callback_( + base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), weak_ptr_factory_(this) { InferThresholds(); StartObserving(); @@ -94,6 +96,8 @@ current_memory_pressure_level_( MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), moderate_pressure_repeat_count_(0), + dispatch_callback_( + base::Bind(&MemoryPressureListener::NotifyMemoryPressure)), weak_ptr_factory_(this) { DCHECK_GE(moderate_threshold_mb_, critical_threshold_mb_); DCHECK_LE(0, critical_threshold_mb_); @@ -198,7 +202,7 @@ // happen for moderate and critical pressure levels. DCHECK_NE(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, current_memory_pressure_level_); - MemoryPressureListener::NotifyMemoryPressure(current_memory_pressure_level_); + dispatch_callback_.Run(current_memory_pressure_level_); } void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() { @@ -250,5 +254,10 @@ return true; } +void MemoryPressureMonitor::SetDispatchCallback( + const DispatchCallback& callback) { + dispatch_callback_ = callback; +} + } // namespace win } // namespace base
diff --git a/base/memory/memory_pressure_monitor_win.h b/base/memory/memory_pressure_monitor_win.h index 5689ac6..b52a2d2 100644 --- a/base/memory/memory_pressure_monitor_win.h +++ b/base/memory/memory_pressure_monitor_win.h
@@ -63,6 +63,7 @@ // Get the current memory pressure level. This can be called from any thread. MemoryPressureLevel GetCurrentPressureLevel() const override; + void SetDispatchCallback(const DispatchCallback& callback) override; // Returns the moderate pressure level free memory threshold, in MB. int moderate_threshold_mb() const { return moderate_threshold_mb_; } @@ -132,6 +133,8 @@ // Ensures that this object is used from a single thread. base::ThreadChecker thread_checker_; + DispatchCallback dispatch_callback_; + // Weak pointer factory to ourself used for scheduling calls to // CheckMemoryPressure/CheckMemoryPressureAndRecordStatistics via |timer_|. base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_;
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 9d37691..ee936928 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc
@@ -464,7 +464,8 @@ if (deferred_non_nestable_work_queue_.empty()) return false; - PendingTask pending_task = deferred_non_nestable_work_queue_.front(); + PendingTask pending_task = + std::move(deferred_non_nestable_work_queue_.front()); deferred_non_nestable_work_queue_.pop(); RunTask(pending_task); @@ -497,7 +498,7 @@ nestable_tasks_allowed_ = true; } -bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { +bool MessageLoop::DeferOrRunPendingTask(PendingTask pending_task) { if (pending_task.nestable || run_loop_->run_depth_ == 1) { RunTask(pending_task); // Show that we ran a task (Note: a new one might arrive as a @@ -507,25 +508,25 @@ // We couldn't run the task now because we're in a nested message loop // and the task isn't nestable. - deferred_non_nestable_work_queue_.push(pending_task); + deferred_non_nestable_work_queue_.push(std::move(pending_task)); return false; } -void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { +void MessageLoop::AddToDelayedWorkQueue(PendingTask pending_task) { // Move to the delayed work queue. - delayed_work_queue_.push(pending_task); + delayed_work_queue_.push(std::move(pending_task)); } bool MessageLoop::DeletePendingTasks() { bool did_work = !work_queue_.empty(); while (!work_queue_.empty()) { - PendingTask pending_task = work_queue_.front(); + PendingTask pending_task = std::move(work_queue_.front()); work_queue_.pop(); if (!pending_task.delayed_run_time.is_null()) { // We want to delete delayed tasks in the same order in which they would // normally be deleted in case of any funny dependencies between delayed // tasks. - AddToDelayedWorkQueue(pending_task); + AddToDelayedWorkQueue(std::move(pending_task)); } } did_work |= !deferred_non_nestable_work_queue_.empty(); @@ -613,15 +614,17 @@ // Execute oldest task. do { - PendingTask pending_task = work_queue_.front(); + PendingTask pending_task = std::move(work_queue_.front()); work_queue_.pop(); if (!pending_task.delayed_run_time.is_null()) { - AddToDelayedWorkQueue(pending_task); + int sequence_num = pending_task.sequence_num; + TimeTicks delayed_run_time = pending_task.delayed_run_time; + AddToDelayedWorkQueue(std::move(pending_task)); // If we changed the topmost task, then it is time to reschedule. - if (delayed_work_queue_.top().task.Equals(pending_task.task)) - pump_->ScheduleDelayedWork(pending_task.delayed_run_time); + if (delayed_work_queue_.top().sequence_num == sequence_num) + pump_->ScheduleDelayedWork(delayed_run_time); } else { - if (DeferOrRunPendingTask(pending_task)) + if (DeferOrRunPendingTask(std::move(pending_task))) return true; } } while (!work_queue_.empty()); @@ -653,13 +656,14 @@ } } - PendingTask pending_task = delayed_work_queue_.top(); + PendingTask pending_task = + std::move(const_cast<PendingTask&>(delayed_work_queue_.top())); delayed_work_queue_.pop(); if (!delayed_work_queue_.empty()) *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; - return DeferOrRunPendingTask(pending_task); + return DeferOrRunPendingTask(std::move(pending_task)); } bool MessageLoop::DoIdleWork() {
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index 1230f41..761c18c 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h
@@ -450,10 +450,10 @@ // Calls RunTask or queues the pending_task on the deferred task list if it // cannot be run right now. Returns true if the task was run. - bool DeferOrRunPendingTask(const PendingTask& pending_task); + bool DeferOrRunPendingTask(PendingTask pending_task); // Adds the pending task to delayed_work_queue_. - void AddToDelayedWorkQueue(const PendingTask& pending_task); + void AddToDelayedWorkQueue(PendingTask pending_task); // Delete tasks that haven't run yet without running them. Used in the // destructor to make sure all the task's destructors get called. Returns
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc index 7bb942f..6cf89bd 100644 --- a/base/message_loop/message_pump_perftest.cc +++ b/base/message_loop/message_pump_perftest.cc
@@ -271,7 +271,7 @@ TaskQueue loop_local_queue; queue->ReloadWorkQueue(&loop_local_queue); while (!loop_local_queue.empty()) { - PendingTask t = loop_local_queue.front(); + PendingTask t = std::move(loop_local_queue.front()); loop_local_queue.pop(); loop.RunTask(t); }
diff --git a/base/pending_task.cc b/base/pending_task.cc index c0999bab..73834bd 100644 --- a/base/pending_task.cc +++ b/base/pending_task.cc
@@ -9,9 +9,9 @@ namespace base { PendingTask::PendingTask(const tracked_objects::Location& posted_from, - const base::Closure& task) + base::Closure task) : base::TrackingInfo(posted_from, TimeTicks()), - task(task), + task(std::move(task)), posted_from(posted_from), sequence_num(0), nestable(true), @@ -19,22 +19,24 @@ } PendingTask::PendingTask(const tracked_objects::Location& posted_from, - const base::Closure& task, + base::Closure task, TimeTicks delayed_run_time, bool nestable) : base::TrackingInfo(posted_from, delayed_run_time), - task(task), + task(std::move(task)), posted_from(posted_from), sequence_num(0), nestable(nestable), is_high_res(false) { } -PendingTask::PendingTask(const PendingTask& other) = default; +PendingTask::PendingTask(PendingTask&& other) = default; PendingTask::~PendingTask() { } +PendingTask& PendingTask::operator=(PendingTask&& other) = default; + bool PendingTask::operator<(const PendingTask& other) const { // Since the top of a priority queue is defined as the "greatest" element, we // need to invert the comparison here. We want the smaller time to be at the
diff --git a/base/pending_task.h b/base/pending_task.h index c31ab9a..5761653 100644 --- a/base/pending_task.h +++ b/base/pending_task.h
@@ -19,14 +19,16 @@ // for use by classes that queue and execute tasks. struct BASE_EXPORT PendingTask : public TrackingInfo { PendingTask(const tracked_objects::Location& posted_from, - const Closure& task); + Closure task); PendingTask(const tracked_objects::Location& posted_from, - const Closure& task, + Closure task, TimeTicks delayed_run_time, bool nestable); - PendingTask(const PendingTask& other); + PendingTask(PendingTask&& other); ~PendingTask(); + PendingTask& operator=(PendingTask&& other); + // Used to support sorting. bool operator<(const PendingTask& other) const;
diff --git a/base/third_party/symbolize/utilities.h b/base/third_party/symbolize/utilities.h index 3971145..65c5ba0 100644 --- a/base/third_party/symbolize/utilities.h +++ b/base/third_party/symbolize/utilities.h
@@ -6,6 +6,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -typedef uint64_t uint64_t; + #define HAVE_SYMBOLIZE 1 #define ATTRIBUTE_NOINLINE __attribute__ ((noinline))
diff --git a/base/threading/worker_pool_posix.cc b/base/threading/worker_pool_posix.cc index dcebe0a..b0a2b871 100644 --- a/base/threading/worker_pool_posix.cc +++ b/base/threading/worker_pool_posix.cc
@@ -150,8 +150,7 @@ DCHECK(!terminated_) << "This thread pool is already terminated. Do not post new tasks."; - pending_tasks_.push(*pending_task); - pending_task->task.Reset(); + pending_tasks_.push(std::move(*pending_task)); // We have enough worker threads. if (static_cast<size_t>(num_idle_threads_) >= pending_tasks_.size()) { @@ -186,7 +185,7 @@ } } - PendingTask pending_task = pending_tasks_.front(); + PendingTask pending_task = std::move(pending_tasks_.front()); pending_tasks_.pop(); return pending_task; }
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc index d4dc2cc2..ebdddd3 100644 --- a/base/trace_event/trace_config.cc +++ b/base/trace_event/trace_config.cc
@@ -14,6 +14,7 @@ #include "base/strings/pattern.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/memory_dump_request_args.h" @@ -411,7 +412,8 @@ if (category.empty()) continue; // Synthetic delays are of the form 'DELAY(delay;option;option;...)'. - if (category.find(kSyntheticDelayCategoryFilterPrefix) == 0 && + if (base::StartsWith(category, kSyntheticDelayCategoryFilterPrefix, + base::CompareCase::SENSITIVE) && category.at(category.size() - 1) == ')') { category = category.substr( strlen(kSyntheticDelayCategoryFilterPrefix),
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 0661caf6..db1db257 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -334,7 +334,7 @@ } struct TraceLog::RegisteredAsyncObserver { - RegisteredAsyncObserver(WeakPtr<AsyncEnabledStateObserver> observer) + explicit RegisteredAsyncObserver(WeakPtr<AsyncEnabledStateObserver> observer) : observer(observer), task_runner(ThreadTaskRunnerHandle::Get()) {} ~RegisteredAsyncObserver() {} @@ -897,7 +897,7 @@ flush_task_runner_ = ThreadTaskRunnerHandle::IsSet() ? ThreadTaskRunnerHandle::Get() : nullptr; - DCHECK(!thread_message_loops_.size() || flush_task_runner_); + DCHECK(thread_message_loops_.empty() || flush_task_runner_); flush_output_callback_ = cb; if (thread_shared_chunk_) { @@ -1354,11 +1354,12 @@ phase == TRACE_EVENT_PHASE_COMPLETE) { AllocationContextTracker::GetInstanceForCurrentThread() ->PushPseudoStackFrame(name); - } else if (phase == TRACE_EVENT_PHASE_END) + } else if (phase == TRACE_EVENT_PHASE_END) { // The pop for |TRACE_EVENT_PHASE_COMPLETE| events // is in |TraceLog::UpdateTraceEventDuration|. AllocationContextTracker::GetInstanceForCurrentThread() ->PopPseudoStackFrame(name); + } } }
diff --git a/build/android/adb_command_line.py b/build/android/adb_command_line.py index 72f42b6..e758b09 100755 --- a/build/android/adb_command_line.py +++ b/build/android/adb_command_line.py
@@ -44,7 +44,7 @@ def read_flags(device): try: return device.ReadFile(args.device_path, as_root=as_root).rstrip() - except device_errors.AdbCommandFailedError: + except device_errors.CommandFailedError: return '' # File might not exist. descriptions = all_devices.pMap(lambda d: d.build_description).pGet(None)
diff --git a/build/android/gyp/emma_instr.py b/build/android/gyp/emma_instr.py index 9ba6776..abb5653e 100755 --- a/build/android/gyp/emma_instr.py +++ b/build/android/gyp/emma_instr.py
@@ -58,6 +58,8 @@ help='Space separated list of source files. ' 'source-dirs should not be specified if ' 'source-files is specified') + option_parser.add_option('--java-sources-file', + help='File containing newline-separated .java paths') option_parser.add_option('--src-root', help='Root of the src repository.') option_parser.add_option('--emma-jar', @@ -102,17 +104,15 @@ build_utils.GetPythonDependencies()) -def _GetSourceDirsFromSourceFiles(source_files_string): - """Returns list of directories for the files in |source_files_string|. +def _GetSourceDirsFromSourceFiles(source_files): + """Returns list of directories for the files in |source_files|. Args: - source_files_string: String generated from GN or GYP containing the list - of source files. + source_files: List of source files. Returns: List of source directories. """ - source_files = build_utils.ParseGypList(source_files_string) return list(set(os.path.dirname(source_file) for source_file in source_files)) @@ -158,7 +158,8 @@ """ if not (options.input_path and options.output_path and options.coverage_file and options.sources_list_file and - (options.source_files or options.source_dirs) and + (options.source_files or options.source_dirs or + options.java_sources_file) and options.src_root and options.emma_jar): option_parser.error('All arguments are required.') @@ -196,7 +197,17 @@ if options.source_dirs: source_dirs = build_utils.ParseGypList(options.source_dirs) else: - source_dirs = _GetSourceDirsFromSourceFiles(options.source_files) + source_files = [] + if options.source_files: + source_files += build_utils.ParseGypList(options.source_files) + if options.java_sources_file: + with open(options.java_sources_file) as f: + source_files.extend(l.strip() for l in f) + source_dirs = _GetSourceDirsFromSourceFiles(source_files) + + # TODO(GYP): In GN, we are passed the list of sources, detecting source + # directories, then walking them to re-establish the list of sources. + # This can obviously be simplified! _CreateSourcesListFile(source_dirs, options.sources_list_file, options.src_root)
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index 6c91424..7b5264d3 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -324,7 +324,17 @@ options.javac_includes = build_utils.ParseGypList(options.javac_includes) options.jar_excluded_classes = ( build_utils.ParseGypList(options.jar_excluded_classes)) - return options, args + + java_files = [] + for arg in args: + # Interpret a path prefixed with @ as a file containing a list of sources. + if arg.startswith('@'): + with open(arg[1:]) as f: + java_files.extend(l.strip() for l in f) + else: + java_files.append(arg) + + return options, java_files def main(argv):
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index edb1f4b..9f5e3e3 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -131,6 +131,15 @@ self.all_deps_config_paths.remove(path) self.all_deps_configs.remove(GetDepConfig(path)) + def PrebuiltJarPaths(self): + ret = [] + for config in self.Direct('java_library'): + if config['is_prebuilt']: + ret.append(config['jar_path']) + ret.extend(Deps(config['deps_configs']).PrebuiltJarPaths()) + return ret + + def _MergeAssets(all_assets): """Merges all assets from the given deps. @@ -226,6 +235,7 @@ # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') + parser.add_option('--java-sources-file', help='Path to .sources file') parser.add_option('--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option('--requires-android', action='store_true', @@ -267,6 +277,7 @@ required_options_map = { 'java_binary': ['build_config', 'jar_path'], 'java_library': ['build_config', 'jar_path'], + 'java_prebuilt': ['build_config', 'jar_path'], 'android_assets': ['build_config'], 'android_resources': ['build_config', 'resources_zip'], 'android_apk': ['build_config', 'jar_path', 'dex_path', 'resources_zip'], @@ -280,6 +291,11 @@ build_utils.CheckOptions(options, parser, required_options) + # Java prebuilts are the same as libraries except for in gradle files. + is_java_prebuilt = options.type == 'java_prebuilt' + if is_java_prebuilt: + options.type = 'java_library' + if options.type == 'java_library': if options.supports_android and not options.dex_path: raise Exception('java_library that supports Android requires a dex path.') @@ -325,15 +341,33 @@ d for d in all_resources_deps if not d in tested_apk_resources_deps] # Initialize some common config. + # Any value that needs to be queryable by dependents must go within deps_info. config = { 'deps_info': { 'name': os.path.basename(options.build_config), 'path': options.build_config, 'type': options.type, 'deps_configs': direct_deps_config_paths - } + }, + # Info needed only by generate_gradle.py. + 'gradle': {} } deps_info = config['deps_info'] + gradle = config['gradle'] + + # Required for generating gradle files. + if options.type == 'java_library': + deps_info['is_prebuilt'] = is_java_prebuilt + + if options.android_manifest: + gradle['android_manifest'] = options.android_manifest + if options.type in ('java_binary', 'java_library', 'android_apk'): + if options.java_sources_file: + gradle['java_sources_file'] = options.java_sources_file + gradle['dependent_prebuilt_jars'] = deps.PrebuiltJarPaths() + gradle['dependent_projects'] = ( + [c['path'] for c in direct_library_deps if not c['is_prebuilt']]) + if (options.type in ('java_binary', 'java_library') and not options.bypass_platform_checks): @@ -367,6 +401,7 @@ # Classpath values filled in below (after applying tested_apk_config). config['javac'] = {} + if options.type in ('java_binary', 'java_library'): # Only resources might have srcjars (normal srcjar targets are listed in # srcjar_deps). A resource's srcjar contains the R.java file for those
diff --git a/build/common.gypi b/build/common.gypi index 7120836..66f152d 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -4634,19 +4634,20 @@ 'target_conditions': [ ['_toolset=="target"', { - 'ldflags': [ - # Experimentation found that using four linking threads - # saved ~20% of link time. - # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36 - # Only apply this to the target linker, since the host - # linker might not be gold, but isn't used much anyway. - # TODO(raymes): Disable threading because gold is frequently - # crashing on the bots: crbug.com/161942. - # '-Wl,--threads', - # '-Wl,--thread-count=4', - ], 'conditions': [ # TODO(thestig): Enable this for disabled cases. + [ 'linux_use_bundled_binutils==1', { + 'ldflags': [ + # Experimentation found that using four linking threads + # saved ~20% of link time. + # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36 + # Only apply this to the target linker, since the host + # linker might not be gold, but isn't used much anyway. + '-Wl,--threads', + '-Wl,--thread-count=4', + ], + }], + # TODO(thestig): Enable this for disabled cases. [ 'buildtype!="Official" and chromeos==0 and release_valgrind_build==0 and asan==0 and lsan==0 and tsan==0 and msan==0 and ubsan==0 and ubsan_security==0 and ubsan_vptr==0', { 'ldflags': [ '-Wl,--detect-odr-violations',
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index d177932..363a53a 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -102,7 +102,7 @@ assert(type == "android_apk" || type == "java_library" || type == "android_resources" || type == "deps_dex" || type == "android_assets" || type == "resource_rewriter" || - type == "java_binary" || type == "group") + type == "java_binary" || type == "group" || type == "java_prebuilt") forward_variables_from(invoker, [ @@ -159,7 +159,8 @@ rebase_path(build_config, root_build_dir), ] - is_java = type == "java_library" || type == "java_binary" + is_java = type == "java_library" || type == "java_binary" || + type == "java_prebuilt" is_apk = type == "android_apk" is_android_assets = type == "android_assets" is_android_resources = type == "android_resources" @@ -314,6 +315,12 @@ } } + if (defined(invoker.java_sources_file)) { + args += [ + "--java-sources-file", + rebase_path(invoker.java_sources_file, root_build_dir), + ] + } if (defined(invoker.srcjar)) { args += [ "--srcjar", @@ -1039,77 +1046,56 @@ } template("emma_instr") { - set_sources_assignment_filter([]) - forward_variables_from(invoker, [ "testonly" ]) + action(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) - assert(invoker.source_files != [] || true) # Mark as used - - if (invoker.emma_instrument) { - _output_jar_target = "${target_name}__process" _coverage_file = "$target_out_dir/${target_name}.em" _source_dirs_listing_file = "$target_out_dir/${target_name}_sources.txt" _emma_jar = "${android_sdk_root}/tools/lib/emma.jar" - _rebased_source_files = rebase_path(invoker.source_files, root_build_dir) - action(_output_jar_target) { - forward_variables_from(invoker, [ "deps" ]) - script = "//build/android/gyp/emma_instr.py" - depfile = "${target_gen_dir}/${target_name}.d" - inputs = [ - _emma_jar, - invoker.input_jar_path, - ] - outputs = [ - depfile, - _coverage_file, - _source_dirs_listing_file, - invoker.output_jar_path, - ] - args = [ - "instrument_jar", - "--input-path", - rebase_path(invoker.input_jar_path, root_build_dir), - "--output-path", - rebase_path(invoker.output_jar_path, root_build_dir), - "--depfile", - rebase_path(depfile, root_build_dir), - "--coverage-file", - rebase_path(_coverage_file, root_build_dir), - "--sources-list-file", - rebase_path(_source_dirs_listing_file, root_build_dir), - "--source-files=$_rebased_source_files", - "--src-root", - rebase_path("//", root_build_dir), - "--emma-jar", - rebase_path(_emma_jar, root_build_dir), - ] - - if (emma_filter != "") { - args += [ - "--filter-string", - emma_filter, - ] - } - } - } else { - _output_jar_target = "${target_name}__copy_jar" - copy(_output_jar_target) { - forward_variables_from(invoker, [ "deps" ]) - - sources = [ - invoker.input_jar_path, - ] - outputs = [ - invoker.output_jar_path, - ] - } - } - - group(target_name) { - forward_variables_from(invoker, [ "visibility" ]) - public_deps = [ - ":$_output_jar_target", + script = "//build/android/gyp/emma_instr.py" + depfile = "${target_gen_dir}/${target_name}.d" + inputs = invoker.java_files + [ + _emma_jar, + invoker.input_jar_path, + ] + outputs = [ + depfile, + _coverage_file, + _source_dirs_listing_file, + invoker.output_jar_path, ] + args = [ + "instrument_jar", + "--input-path", + rebase_path(invoker.input_jar_path, root_build_dir), + "--output-path", + rebase_path(invoker.output_jar_path, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + "--coverage-file", + rebase_path(_coverage_file, root_build_dir), + "--sources-list-file", + rebase_path(_source_dirs_listing_file, root_build_dir), + "--src-root", + rebase_path("//", root_build_dir), + "--emma-jar", + rebase_path(_emma_jar, root_build_dir), + ] + _rebased_java_sources_file = + rebase_path(invoker.java_sources_file, root_build_dir) + args += [ "--java-sources-file=$_rebased_java_sources_file" ] + + if (emma_filter != "") { + args += [ + "--filter-string", + emma_filter, + ] + } } } @@ -1688,7 +1674,7 @@ } write_build_config(_build_config_target_name) { - type = "java_library" + type = "java_prebuilt" supports_android = _supports_android requires_android = defined(invoker.requires_android) && invoker.requires_android @@ -1797,7 +1783,8 @@ # $jar_path.interface.jar # # Variables - # java_files: List of .java files to compile. + # java_files: List of .java files to compile (same as exists in java_sources_file) + # java_sources_file: Path to file containing list of files to compile. # chromium_code: If true, enable extra warnings. # srcjar_deps: List of srcjar dependencies. The .java files contained in the # dependencies srcjar outputs will be compiled and added to the output jar. @@ -1807,18 +1794,9 @@ set_sources_assignment_filter([]) forward_variables_from(invoker, [ "testonly" ]) - assert(defined(invoker.java_files)) assert(defined(invoker.build_config)) assert(defined(invoker.jar_path)) - _java_files = invoker.java_files - _final_jar_path = invoker.jar_path - _javac_jar_path = "$target_gen_dir/$target_name.javac.jar" - _process_prebuilt_jar_path = - "$target_gen_dir/$target_name.process_prebuilt.jar" - _final_ijar_path = get_path_info(_final_jar_path, "dir") + "/" + - get_path_info(_final_jar_path, "name") + ".interface.jar" - _build_config = invoker.build_config _input_jars_paths = [] @@ -1891,15 +1869,28 @@ # Mark srcjar_deps as used. assert(_srcjar_deps == [] || true) - _rebased_build_config = rebase_path(_build_config, root_build_dir) - _rebased_jar_path = rebase_path(_javac_jar_path, root_build_dir) - _javac_target_name = "${target_name}__javac" _process_prebuilt_target_name = "${target_name}__process_prebuilt" - _emma_instr_target_name = "${target_name}__emma_instr" _ijar_target_name = "${target_name}__ijar" _final_target_name = target_name + _final_jar_path = invoker.jar_path + _javac_jar_path = "$target_gen_dir/$target_name.javac.jar" + _process_prebuilt_jar_path = _final_jar_path + _final_ijar_path = get_path_info(_final_jar_path, "dir") + "/" + + get_path_info(_final_jar_path, "name") + ".interface.jar" + + _emma_instrument = defined(invoker.emma_instrument) && + invoker.emma_instrument && invoker.java_files != [] + if (_emma_instrument) { + _emma_instr_target_name = "${target_name}__emma_instr" + _process_prebuilt_jar_path = + "$target_gen_dir/$target_name.process_prebuilt.jar" + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _rebased_jar_path = rebase_path(_javac_jar_path, root_build_dir) + action(_javac_target_name) { script = "//build/android/gyp/javac.py" depfile = "$target_gen_dir/$target_name.d" @@ -1913,10 +1904,13 @@ _javac_jar_path, _javac_jar_path + ".md5.stamp", ] - sources = _java_files + _java_srcjars + sources = invoker.java_files + _java_srcjars inputs = [ _build_config, ] + if (invoker.java_files != []) { + inputs += [ invoker.java_sources_file ] + } _rebased_java_srcjars = rebase_path(_java_srcjars, root_build_dir) _rebased_depfile = rebase_path(depfile, root_build_dir) @@ -1976,7 +1970,9 @@ foreach(e, _processor_args) { args += [ "--processor-arg=" + e ] } - args += rebase_path(_java_files, root_build_dir) + if (invoker.java_files != []) { + args += [ "@" + rebase_path(invoker.java_sources_file, root_build_dir) ] + } } process_java_prebuilt(_process_prebuilt_target_name) { @@ -1996,37 +1992,47 @@ } } - emma_instr(_emma_instr_target_name) { - visibility = [ - ":$_ijar_target_name", - ":$_final_target_name", - ] + if (_emma_instrument) { + emma_instr(_emma_instr_target_name) { + forward_variables_from(invoker, + [ + "java_files", + "java_sources_file", + ]) - forward_variables_from(invoker, [ "emma_instrument" ]) + input_jar_path = _process_prebuilt_jar_path + output_jar_path = _final_jar_path - input_jar_path = _process_prebuilt_jar_path - output_jar_path = _final_jar_path - source_files = _java_files - - deps = [ - ":$_process_prebuilt_target_name", - ] + deps = [ + ":$_process_prebuilt_target_name", + ] + } } generate_interface_jar(_ijar_target_name) { input_jar = _final_jar_path output_jar = _final_ijar_path - deps = [ - ":$_emma_instr_target_name", - ] + if (_emma_instrument) { + deps = [ + ":$_emma_instr_target_name", + ] + } else { + deps = [ + ":$_process_prebuilt_target_name", + ] + } } group(_final_target_name) { forward_variables_from(invoker, [ "visibility" ]) public_deps = [ - ":$_emma_instr_target_name", ":$_ijar_target_name", ] + if (_emma_instrument) { + public_deps += [ ":$_emma_instr_target_name" ] + } else { + public_deps += [ ":$_process_prebuilt_target_name" ] + } } } @@ -2112,6 +2118,15 @@ } } + _java_files = [] + if (defined(invoker.java_files)) { + _java_files += invoker.java_files + } + if (_java_files != []) { + _java_sources_file = "$_base_path.sources" + write_file(_java_sources_file, rebase_path(_java_files, root_build_dir)) + } + # Define build_config_deps which will be a list of targets required to # build the _build_config. if (defined(invoker.override_build_config)) { @@ -2139,6 +2154,9 @@ if (_supports_android) { dex_path = _dex_path } + if (_java_files != []) { + java_sources_file = _java_sources_file + } } _accumulated_deps += [ ":$build_config_target_name" ] } @@ -2153,10 +2171,6 @@ _srcjars = invoker.srcjars } - _java_files = [] - if (defined(invoker.java_files)) { - _java_files += invoker.java_files - } assert(_java_files != [] || _srcjar_deps != [] || _srcjars != []) _compile_java_target = "${_template_name}__compile_java" @@ -2181,6 +2195,9 @@ jar_path = _jar_path build_config = _build_config java_files = _java_files + if (_java_files != []) { + java_sources_file = _java_sources_file + } srcjar_deps = _srcjar_deps srcjars = _srcjars chromium_code = _chromium_code
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 7b1bbed..a6cc4fe 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1676,6 +1676,9 @@ if (defined(invoker.deps)) { deps += invoker.deps } + if (defined(invoker.alternative_locale_resource_dep)) { + deps += [ invoker.alternative_locale_resource_dep ] + } } _srcjar_deps += [ ":$process_resources_target" ] @@ -1783,6 +1786,9 @@ if (defined(invoker.apk_under_test)) { deps += [ "${invoker.apk_under_test}__java" ] } + if (emma_coverage && !_emma_never_instrument) { + deps += [ "//third_party/android_tools:emma_device" ] + } } # TODO(cjhopman): This is only ever needed to calculate the list of tests to
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 15ff58c..30d8017 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -208,8 +208,7 @@ } # Linker warnings. - if ( fatal_linker_warnings && - !(is_chromeos && current_cpu == "arm") && + if (fatal_linker_warnings && !(is_chromeos && current_cpu == "arm") && !(is_android && use_order_profiling) && !is_mac && !is_ios) { # TODO(jochen): Enable this on chromeos on arm. http://crbug.com/356580 # TODO(lizeb,pasko): Fix link errors when linking with order_profiling=1 @@ -318,18 +317,19 @@ cflags += [ "-mstackrealign" ] } } else { - ldflags += [ - "-B$gold_path", - # Experimentation found that using four linking threads - # saved ~20% of link time. - # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36 - # Only apply this to the target linker, since the host - # linker might not be gold, but isn't used much anyway. - # TODO(raymes): Disable threading because gold is frequently - # crashing on the bots: crbug.com/161942. - #"-Wl,--threads", - #"-Wl,--thread-count=4", - ] + ldflags += [ "-B$gold_path" ] + + if (linux_use_bundled_binutils) { + ldflags += [ + # Experimentation found that using four linking threads + # saved ~20% of link time. + # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36 + # Only apply this to the target linker, since the host + # linker might not be gold, but isn't used much anyway. + "-Wl,--threads", + "-Wl,--thread-count=4", + ] + } } if (gdb_index) {
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni index ac2c61ac..219b580b 100644 --- a/build/config/ios/rules.gni +++ b/build/config/ios/rules.gni
@@ -377,6 +377,58 @@ } } +# Compile a strings file and add it to a bundle_data so that it is available +# at runtime in the bundle. +# +# Arguments +# +# source: +# string, path of the strings file to compile. +# +# output: +# string, path of the compiled file in the final bundle. +# +# Forwards all variables to the bundle_data target. +template("bundle_data_strings") { + assert(defined(invoker.source), "source needs to be defined for $target_name") + assert(defined(invoker.output), "output needs to be defined for $target_name") + + _source_extension = get_path_info(invoker.source, "extension") + assert(_source_extension == "strings", + "source must be a .strings for $target_name") + + _target_name = target_name + _convert_target = target_name + "_compile_strings" + + convert_plist(_convert_target) { + visibility = [ ":$_target_name" ] + source = invoker.source + output = + "$target_gen_dir/$_target_name/" + get_path_info(invoker.source, "file") + format = "binary1" + } + + bundle_data(_target_name) { + forward_variables_from(invoker, + "*", + [ + "source", + "output", + ]) + + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":$_convert_target" ] + + sources = get_target_outputs(":$_convert_target") + + outputs = [ + invoker.output, + ] + } +} + # Template to package a shared library into an iOS framework bundle. # # This template provides two targets to control whether the framework is
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 29336ce2..8cf538d3 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi
@@ -76,32 +76,6 @@ '../third_party/WebKit/Source/platform/blink_platform_tests.gyp:blink_platform_unittests', '../third_party/WebKit/Source/web/web_tests.gyp:webkit_unit_tests', '../third_party/WebKit/Source/wtf/wtf_tests.gyp:wtf_unittests', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_ecdsa_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_bn_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_pqueue_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_digest_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_cipher_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_hkdf_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_constant_time_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_thread_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_base64_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_gcm_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_bytestring_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_evp_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_dsa_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_rsa_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_hmac_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_aead_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_ssl_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_err_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_lhash_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_pbkdf_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_dh_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs12_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_example_mul', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_ec_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_bio_test', - '../third_party/boringssl/boringssl_tests.gyp:boringssl_pkcs7_test', '../third_party/boringssl/boringssl_tests.gyp:boringssl_unittests', '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests', '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py index 2003ff6..d1aa1aac 100755 --- a/build/linux/sysroot_scripts/install-sysroot.py +++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -36,22 +36,26 @@ URL_PATH = 'chrome-linux-sysroot/toolchain' REVISION_AMD64 = 'c52471d9dec240c8d0a88fa98aa1eefeee32e22f' REVISION_ARM = 'c52471d9dec240c8d0a88fa98aa1eefeee32e22f' +REVISION_ARM64 = 'bd10c315594d2a20e31a94a7a6c7adb9a0961c56' REVISION_I386 = 'c52471d9dec240c8d0a88fa98aa1eefeee32e22f' REVISION_MIPS = 'c52471d9dec240c8d0a88fa98aa1eefeee32e22f' TARBALL_AMD64 = 'debian_wheezy_amd64_sysroot.tgz' TARBALL_ARM = 'debian_wheezy_arm_sysroot.tgz' +TARBALL_ARM64 = 'debian_jessie_arm64_sysroot.tgz' TARBALL_I386 = 'debian_wheezy_i386_sysroot.tgz' TARBALL_MIPS = 'debian_wheezy_mips_sysroot.tgz' TARBALL_AMD64_SHA1SUM = 'ca4ed6e7c9e333b046be19d38584a11f6785eea6' TARBALL_ARM_SHA1SUM = '1fab0c2b1e93a933ddc593df3b43872b0ba5ded2' +TARBALL_ARM64_SHA1SUM = '0db3be51912e0be46bb1b906fc196c5c1dfc090f' TARBALL_I386_SHA1SUM = '80c48c303319af2284e4a104c882d888af75ba81' TARBALL_MIPS_SHA1SUM = '01da32a35288627e05cfca193b7f3659531c6f7d' SYSROOT_DIR_AMD64 = 'debian_wheezy_amd64-sysroot' SYSROOT_DIR_ARM = 'debian_wheezy_arm-sysroot' +SYSROOT_DIR_ARM64 = 'debian_jessie_arm64-sysroot' SYSROOT_DIR_I386 = 'debian_wheezy_i386-sysroot' SYSROOT_DIR_MIPS = 'debian_wheezy_mips-sysroot' -valid_archs = ('arm', 'i386', 'amd64', 'mips') +valid_archs = ('arm', 'arm64', 'i386', 'amd64', 'mips') class Error(Exception): @@ -129,7 +133,7 @@ # Don't attampt to install arm64 since this is currently and android-only # architecture. target_arch = DetectTargetArch() - if target_arch and target_arch not in (host_arch, 'i386', 'arm64'): + if target_arch and target_arch not in (host_arch, 'i386'): InstallSysroot(target_arch) @@ -170,6 +174,11 @@ tarball_filename = TARBALL_ARM tarball_sha1sum = TARBALL_ARM_SHA1SUM revision = REVISION_ARM + elif target_arch == 'arm64': + sysroot = os.path.join(linux_dir, SYSROOT_DIR_ARM64) + tarball_filename = TARBALL_ARM64 + tarball_sha1sum = TARBALL_ARM64_SHA1SUM + revision = REVISION_ARM64 elif target_arch == 'i386': sysroot = os.path.join(linux_dir, SYSROOT_DIR_I386) tarball_filename = TARBALL_I386
diff --git a/build/linux/sysroot_scripts/packagelist.jessie.arm64 b/build/linux/sysroot_scripts/packagelist.jessie.arm64 index c95cbf0d..7a3358cc 100644 --- a/build/linux/sysroot_scripts/packagelist.jessie.arm64 +++ b/build/linux/sysroot_scripts/packagelist.jessie.arm64
@@ -20,8 +20,8 @@ main/e/e2fsprogs/libcomerr2_1.42.12-1.1_arm64.deb main/e/elfutils/libelf1_0.159-4.2_arm64.deb main/e/elfutils/libelf-dev_0.159-4.2_arm64.deb -main/e/expat/libexpat1_2.1.0-6+deb8u1_arm64.deb -main/e/expat/libexpat1-dev_2.1.0-6+deb8u1_arm64.deb +main/e/expat/libexpat1_2.1.0-6+deb8u2_arm64.deb +main/e/expat/libexpat1-dev_2.1.0-6+deb8u2_arm64.deb main/f/fontconfig/libfontconfig1_2.11.0-6.3_arm64.deb main/f/fontconfig/libfontconfig1-dev_2.11.0-6.3_arm64.deb main/f/freetype/libfreetype6_2.5.2-3+deb8u1_arm64.deb @@ -86,7 +86,7 @@ main/libp/libpng/libpng12-dev_1.2.50-2+deb8u2_arm64.deb main/libp/libpthread-stubs/libpthread-stubs0-dev_0.3-4_arm64.deb main/libs/libselinux/libselinux1_2.3-2_arm64.deb -main/libt/libtasn1-6/libtasn1-6_4.2-3+deb8u1_arm64.deb +main/libt/libtasn1-6/libtasn1-6_4.2-3+deb8u2_arm64.deb main/libt/libthai/libthai0_0.1.21-1_arm64.deb main/libx/libx11/libx11-6_1.6.2-3_arm64.deb main/libx/libx11/libx11-dev_1.6.2-3_arm64.deb @@ -127,7 +127,7 @@ main/libx/libxtst/libxtst6_1.2.2-1+b1_arm64.deb main/libx/libxtst/libxtst-dev_1.2.2-1+b1_arm64.deb main/libx/libxxf86vm/libxxf86vm1_1.1.3-1+b1_arm64.deb -main/l/linux/linux-libc-dev_3.16.7-ckt25-1_arm64.deb +main/l/linux/linux-libc-dev_3.16.7-ckt25-2_arm64.deb main/m/mesa/libgl1-mesa-dev_10.3.2-1+deb8u1_arm64.deb main/m/mesa/libgl1-mesa-glx_10.3.2-1+deb8u1_arm64.deb main/m/mesa/libglapi-mesa_10.3.2-1+deb8u1_arm64.deb @@ -138,8 +138,8 @@ main/n/nspr/libnspr4-dev_4.10.7-1+deb8u1_arm64.deb main/n/nss/libnss3_3.17.2-1.1+deb8u2_arm64.deb main/n/nss/libnss3-dev_3.17.2-1.1+deb8u2_arm64.deb -main/o/openssl/libssl1.0.0_1.0.1k-3+deb8u4_arm64.deb -main/o/openssl/libssl-dev_1.0.1k-3+deb8u4_arm64.deb +main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u2_arm64.deb +main/o/openssl/libssl-dev_1.0.1t-1+deb8u2_arm64.deb main/o/orbit2/liborbit2_2.14.19-0.3_arm64.deb main/p/p11-kit/libp11-kit0_0.20.7-1_arm64.deb main/p/pam/libpam0g_1.1.8-3.1+deb8u1+b1_arm64.deb
diff --git a/build/linux/unbundle/zlib.gn b/build/linux/unbundle/zlib.gn index ecde1c9..020fc7e 100644 --- a/build/linux/unbundle/zlib.gn +++ b/build/linux/unbundle/zlib.gn
@@ -9,11 +9,16 @@ headers = [ "zlib.h" ] } +config("system_zlib") { + defines = [ "USE_SYSTEM_ZLIB=1" ] +} + source_set("zlib") { deps = [ ":zlib_shim", ] libs = [ "z" ] + public_configs = [ ":system_zlib" ] } shim_headers("minizip_shim") {
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 4886d7b..f1be4f7 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -484,11 +484,15 @@ "trees/blocking_task_runner.h", "trees/channel_impl.h", "trees/channel_main.h", + "trees/clip_node.cc", + "trees/clip_node.h", "trees/compositor_mode.h", "trees/damage_tracker.cc", "trees/damage_tracker.h", "trees/draw_property_utils.cc", "trees/draw_property_utils.h", + "trees/effect_node.cc", + "trees/effect_node.h", "trees/latency_info_swap_promise_monitor.cc", "trees/latency_info_swap_promise_monitor.h", "trees/layer_tree_host.cc", @@ -525,6 +529,8 @@ "trees/remote_channel_main.h", "trees/remote_proto_channel.h", "trees/scoped_abort_remaining_swap_promises.h", + "trees/scroll_node.cc", + "trees/scroll_node.h", "trees/single_thread_proxy.cc", "trees/single_thread_proxy.h", "trees/swap_promise_monitor.cc", @@ -533,6 +539,8 @@ "trees/task_runner_provider.h", "trees/threaded_channel.cc", "trees/threaded_channel.h", + "trees/transform_node.cc", + "trees/transform_node.h", "trees/tree_synchronizer.cc", "trees/tree_synchronizer.h", ] @@ -657,6 +665,8 @@ "test/fake_video_frame_provider.h", "test/geometry_test_utils.cc", "test/geometry_test_utils.h", + "test/layer_internals_for_test.cc", + "test/layer_internals_for_test.h", "test/layer_test_common.cc", "test/layer_test_common.h", "test/layer_tree_host_common_test.cc", @@ -995,7 +1005,7 @@ test("cc_perftests") { sources = [ "animation/animation_host_perftest.cc", - "ipc/cc_param_traits_perftest.cc", + "ipc/cc_serialization_perftest.cc", "layers/layer_perftest.cc", "layers/picture_layer_impl_perftest.cc", "quads/draw_quad_perftest.cc", @@ -1016,12 +1026,15 @@ "//base", "//base/test:test_support", "//cc/ipc", + "//cc/ipc:interfaces", "//cc/surfaces", "//cc/surfaces:surface_id", "//gpu", "//gpu:test_support", "//gpu/command_buffer/common:gles2_utils", "//media", + "//mojo/edk/system", + "//mojo/public/cpp/bindings", "//skia", "//testing/gmock", "//testing/gtest",
diff --git a/cc/cc.gyp b/cc/cc.gyp index 3d0394e8..ef836c9c 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp
@@ -545,11 +545,15 @@ 'trees/blocking_task_runner.h', 'trees/channel_impl.h', 'trees/channel_main.h', + 'trees/clip_node.cc', + 'trees/clip_node.h', 'trees/compositor_mode.h', 'trees/damage_tracker.cc', 'trees/damage_tracker.h', 'trees/draw_property_utils.cc', 'trees/draw_property_utils.h', + 'trees/effect_node.cc', + 'trees/effect_node.h', 'trees/latency_info_swap_promise_monitor.cc', 'trees/latency_info_swap_promise_monitor.h', 'trees/layer_tree_host.cc', @@ -586,6 +590,8 @@ 'trees/remote_channel_main.h', 'trees/remote_proto_channel.h', 'trees/scoped_abort_remaining_swap_promises.h', + 'trees/scroll_node.cc', + 'trees/scroll_node.h', 'trees/single_thread_proxy.cc', 'trees/single_thread_proxy.h', 'trees/swap_promise_monitor.cc', @@ -594,6 +600,8 @@ 'trees/task_runner_provider.h', 'trees/threaded_channel.cc', 'trees/threaded_channel.h', + 'trees/transform_node.cc', + 'trees/transform_node.h', 'trees/tree_synchronizer.cc', 'trees/tree_synchronizer.h', ],
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 271c2c4f..2b5c33e 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp
@@ -243,6 +243,8 @@ 'test/fake_video_frame_provider.h', 'test/geometry_test_utils.cc', 'test/geometry_test_utils.h', + 'test/layer_internals_for_test.cc', + 'test/layer_internals_for_test.h', 'test/layer_test_common.cc', 'test/layer_test_common.h', 'test/layer_tree_host_common_test.cc', @@ -403,7 +405,6 @@ 'sources': [ # Note: sources list duplicated in GN build. 'animation/animation_host_perftest.cc', - 'ipc/cc_param_traits_perftest.cc', 'layers/layer_perftest.cc', 'layers/picture_layer_impl_perftest.cc', 'quads/draw_quad_perftest.cc',
diff --git a/cc/input/scroll_state.cc b/cc/input/scroll_state.cc index f0c0d7e..8b6a140 100644 --- a/cc/input/scroll_state.cc +++ b/cc/input/scroll_state.cc
@@ -7,6 +7,7 @@ #include <utility> #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" namespace cc {
diff --git a/cc/input/scroll_state_data.cc b/cc/input/scroll_state_data.cc index 1ba778d9..567a024 100644 --- a/cc/input/scroll_state_data.cc +++ b/cc/input/scroll_state_data.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/input/scroll_state_data.h" +#include "cc/trees/scroll_node.h" namespace cc { @@ -39,7 +40,7 @@ ElementId ScrollStateData::current_native_scrolling_element() const { if (current_native_scrolling_node_) - return current_native_scrolling_node_->data.element_id; + return current_native_scrolling_node_->element_id; return current_native_scrolling_element_; }
diff --git a/cc/input/scroll_state_unittest.cc b/cc/input/scroll_state_unittest.cc index b7299007..1a3a8965 100644 --- a/cc/input/scroll_state_unittest.cc +++ b/cc/input/scroll_state_unittest.cc
@@ -10,6 +10,7 @@ #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h index 753f6e71..43431c6 100644 --- a/cc/ipc/cc_param_traits_macros.h +++ b/cc/ipc/cc_param_traits_macros.h
@@ -184,6 +184,8 @@ IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor) IPC_STRUCT_TRAITS_MEMBER(root_overflow_x_hidden) IPC_STRUCT_TRAITS_MEMBER(root_overflow_y_hidden) + IPC_STRUCT_TRAITS_MEMBER( + is_resourceless_software_draw_with_scroll_or_animation) IPC_STRUCT_TRAITS_MEMBER(location_bar_offset) IPC_STRUCT_TRAITS_MEMBER(location_bar_content_translation) IPC_STRUCT_TRAITS_MEMBER(root_background_color)
diff --git a/cc/ipc/cc_param_traits_perftest.cc b/cc/ipc/cc_param_traits_perftest.cc deleted file mode 100644 index 1cf40f1a..0000000 --- a/cc/ipc/cc_param_traits_perftest.cc +++ /dev/null
@@ -1,155 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "cc/ipc/cc_param_traits.h" -#include "cc/output/compositor_frame.h" -#include "cc/quads/picture_draw_quad.h" -#include "ipc/ipc_message.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/perf/perf_test.h" - -using cc::CompositorFrame; -using cc::DelegatedFrameData; -using cc::DrawQuad; -using cc::PictureDrawQuad; -using cc::RenderPass; -using cc::SharedQuadState; - -namespace content { -namespace { - -static const int kTimeLimitMillis = 2000; -static const int kNumWarmupRuns = 20; -static const int kTimeCheckInterval = 10; - -class CCParamTraitsPerfTest : public testing::Test { - protected: - static void RunTest(const std::string& test_name, - const CompositorFrame& frame) { - for (int i = 0; i < kNumWarmupRuns; ++i) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - IPC::ParamTraits<CompositorFrame>::Write(&msg, frame); - } - - base::TimeTicks start = base::TimeTicks::Now(); - base::TimeTicks end = - start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); - base::TimeDelta min_time; - int count = 0; - while (start < end) { - for (int i = 0; i < kTimeCheckInterval; ++i) { - IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); - IPC::ParamTraits<CompositorFrame>::Write(&msg, frame); - ++count; - } - - base::TimeTicks now = base::TimeTicks::Now(); - if (now - start < min_time || min_time.is_zero()) - min_time = now - start; - start = base::TimeTicks::Now(); - } - - perf_test::PrintResult( - "min_frame_serialization_time", "", test_name, - min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", true); - } -}; - -TEST_F(CCParamTraitsPerfTest, DelegatedFrame_ManyQuads_1_4000) { - std::unique_ptr<CompositorFrame> frame(new CompositorFrame); - - std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); - render_pass->CreateAndAppendSharedQuadState(); - for (int i = 0; i < 4000; ++i) { - PictureDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); - quad->shared_quad_state = render_pass->shared_quad_state_list.back(); - } - - frame->delegated_frame_data.reset(new DelegatedFrameData); - frame->delegated_frame_data->render_pass_list.push_back( - std::move(render_pass)); - - RunTest("DelegatedFrame_ManyQuads_1_4000", *frame); -} - -TEST_F(CCParamTraitsPerfTest, DelegatedFrame_ManyQuads_1_100000) { - std::unique_ptr<CompositorFrame> frame(new CompositorFrame); - - std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); - render_pass->CreateAndAppendSharedQuadState(); - for (int i = 0; i < 100000; ++i) { - PictureDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); - quad->shared_quad_state = render_pass->shared_quad_state_list.back(); - } - - frame->delegated_frame_data.reset(new DelegatedFrameData); - frame->delegated_frame_data->render_pass_list.push_back( - std::move(render_pass)); - - RunTest("DelegatedFrame_ManyQuads_1_100000", *frame); -} - -TEST_F(CCParamTraitsPerfTest, DelegatedFrame_ManyQuads_4000_4000) { - std::unique_ptr<CompositorFrame> frame(new CompositorFrame); - - std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); - for (int i = 0; i < 4000; ++i) { - render_pass->CreateAndAppendSharedQuadState(); - PictureDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); - quad->shared_quad_state = render_pass->shared_quad_state_list.back(); - } - - frame->delegated_frame_data.reset(new DelegatedFrameData); - frame->delegated_frame_data->render_pass_list.push_back( - std::move(render_pass)); - - RunTest("DelegatedFrame_ManyQuads_4000_4000", *frame); -} - -TEST_F(CCParamTraitsPerfTest, DelegatedFrame_ManyQuads_100000_100000) { - std::unique_ptr<CompositorFrame> frame(new CompositorFrame); - - std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); - for (int i = 0; i < 100000; ++i) { - render_pass->CreateAndAppendSharedQuadState(); - PictureDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); - quad->shared_quad_state = render_pass->shared_quad_state_list.back(); - } - - frame->delegated_frame_data.reset(new DelegatedFrameData); - frame->delegated_frame_data->render_pass_list.push_back( - std::move(render_pass)); - - RunTest("DelegatedFrame_ManyQuads_100000_100000", *frame); -} - -TEST_F(CCParamTraitsPerfTest, DelegatedFrame_ManyRenderPasses_10000_100) { - std::unique_ptr<CompositorFrame> frame(new CompositorFrame); - frame->delegated_frame_data.reset(new DelegatedFrameData); - - for (int i = 0; i < 1000; ++i) { - std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); - for (int j = 0; j < 100; ++j) { - render_pass->CreateAndAppendSharedQuadState(); - PictureDrawQuad* quad = - render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); - quad->shared_quad_state = render_pass->shared_quad_state_list.back(); - } - frame->delegated_frame_data->render_pass_list.push_back( - std::move(render_pass)); - } - - RunTest("DelegatedFrame_ManyRenderPasses_10000_100", *frame); -} - -} // namespace -} // namespace content
diff --git a/cc/ipc/cc_serialization_perftest.cc b/cc/ipc/cc_serialization_perftest.cc new file mode 100644 index 0000000..cad0894 --- /dev/null +++ b/cc/ipc/cc_serialization_perftest.cc
@@ -0,0 +1,217 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> + +#include "base/test/launcher/unit_test_launcher.h" +#include "base/test/test_suite.h" +#include "cc/ipc/cc_param_traits.h" +#include "cc/ipc/compositor_frame.mojom.h" +#include "cc/ipc/compositor_frame_metadata_struct_traits.h" +#include "cc/ipc/compositor_frame_struct_traits.h" +#include "cc/ipc/render_pass_struct_traits.h" +#include "cc/ipc/selection_struct_traits.h" +#include "cc/ipc/shared_quad_state_struct_traits.h" +#include "cc/ipc/surface_id_struct_traits.h" +#include "cc/ipc/transferable_resource_struct_traits.h" +#include "cc/output/compositor_frame.h" +#include "cc/quads/picture_draw_quad.h" +#include "gpu/ipc/common/mailbox_holder_struct_traits.h" +#include "gpu/ipc/common/mailbox_struct_traits.h" +#include "gpu/ipc/common/sync_token_struct_traits.h" +#include "ipc/ipc_message.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" +#include "ui/events/mojo/latency_info_struct_traits.h" +#include "ui/gfx/geometry/mojo/geometry.mojom.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "ui/gfx/mojo/selection_bound_struct_traits.h" + +namespace cc { +namespace { + +static const int kTimeLimitMillis = 2000; +static const int kNumWarmupRuns = 20; +static const int kTimeCheckInterval = 10; + +class CCSerializationPerfTest : public testing::Test { + protected: + static void RunTestParamTraits(const std::string& test_name, + const CompositorFrame& frame) { + for (int i = 0; i < kNumWarmupRuns; ++i) { + IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); + IPC::ParamTraits<CompositorFrame>::Write(&msg, frame); + } + + base::TimeTicks start = base::TimeTicks::Now(); + base::TimeTicks end = + start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); + base::TimeDelta min_time; + size_t count = 0; + while (start < end) { + for (int i = 0; i < kTimeCheckInterval; ++i) { + IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); + IPC::ParamTraits<CompositorFrame>::Write(&msg, frame); + ++count; + } + + base::TimeTicks now = base::TimeTicks::Now(); + if (now - start < min_time || min_time.is_zero()) + min_time = now - start; + start = base::TimeTicks::Now(); + } + + perf_test::PrintResult( + "ParamTraits: min_frame_serialization_time", "", test_name, + min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", true); + perf_test::PrintResult("ParamTraits: num runs in 2 seconds", "", test_name, + count, "", true); + } + + static void RunTestStructTraits(const std::string& test_name, + const CompositorFrame& frame) { + for (int i = 0; i < kNumWarmupRuns; ++i) { + mojo::Array<uint8_t> data = mojom::CompositorFrame::Serialize(&frame); + DCHECK_GT(data.size(), 0u); + } + + base::TimeTicks start = base::TimeTicks::Now(); + base::TimeTicks end = + start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); + base::TimeDelta min_time; + size_t count = 0; + while (start < end) { + for (int i = 0; i < kTimeCheckInterval; ++i) { + mojo::Array<uint8_t> data = mojom::CompositorFrame::Serialize(&frame); + DCHECK_GT(data.size(), 0u); + ++count; + } + + base::TimeTicks now = base::TimeTicks::Now(); + if (now - start < min_time || min_time.is_zero()) + min_time = now - start; + start = base::TimeTicks::Now(); + } + + perf_test::PrintResult( + "StructTraits min_frame_serialization_time", "", test_name, + min_time.InMillisecondsF() / kTimeCheckInterval * 1000, "us", true); + perf_test::PrintResult("StructTraits: num runs in 2 seconds", "", test_name, + count, "", true); + } + + static void RunTest(const std::string& test_name, CompositorFrame frame) { + RunTestStructTraits(test_name, frame); + RunTestParamTraits(test_name, frame); + } +}; + +TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_1_4000) { + CompositorFrame frame; + + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + render_pass->CreateAndAppendSharedQuadState(); + for (int i = 0; i < 4000; ++i) { + const gfx::Rect bounds(100, 100, 100, 100); + const bool kForceAntiAliasingOff = true; + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(render_pass->shared_quad_state_list.back(), bounds, bounds, + SK_ColorRED, kForceAntiAliasingOff); + } + + frame.delegated_frame_data.reset(new DelegatedFrameData); + frame.delegated_frame_data->render_pass_list.push_back( + std::move(render_pass)); + + RunTest("DelegatedFrame_ManyQuads_1_4000", std::move(frame)); +} + +TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_1_100000) { + CompositorFrame frame; + + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + render_pass->CreateAndAppendSharedQuadState(); + for (int i = 0; i < 100000; ++i) { + const gfx::Rect bounds(100, 100, 100, 100); + const bool kForceAntiAliasingOff = true; + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(render_pass->shared_quad_state_list.back(), bounds, bounds, + SK_ColorRED, kForceAntiAliasingOff); + } + + frame.delegated_frame_data.reset(new DelegatedFrameData); + frame.delegated_frame_data->render_pass_list.push_back( + std::move(render_pass)); + + RunTest("DelegatedFrame_ManyQuads_1_100000", std::move(frame)); +} + +TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_4000_4000) { + CompositorFrame frame; + + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + for (int i = 0; i < 4000; ++i) { + const gfx::Rect bounds(100, 100, 100, 100); + const bool kForceAntiAliasingOff = true; + render_pass->CreateAndAppendSharedQuadState(); + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(render_pass->shared_quad_state_list.back(), bounds, bounds, + SK_ColorRED, kForceAntiAliasingOff); + } + + frame.delegated_frame_data.reset(new DelegatedFrameData); + frame.delegated_frame_data->render_pass_list.push_back( + std::move(render_pass)); + + RunTest("DelegatedFrame_ManyQuads_4000_4000", std::move(frame)); +} + +TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyQuads_100000_100000) { + CompositorFrame frame; + + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + for (int i = 0; i < 100000; ++i) { + render_pass->CreateAndAppendSharedQuadState(); + const gfx::Rect bounds(100, 100, 100, 100); + const bool kForceAntiAliasingOff = true; + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(render_pass->shared_quad_state_list.back(), bounds, bounds, + SK_ColorRED, kForceAntiAliasingOff); + } + + frame.delegated_frame_data.reset(new DelegatedFrameData); + frame.delegated_frame_data->render_pass_list.push_back( + std::move(render_pass)); + + RunTest("DelegatedFrame_ManyQuads_100000_100000", std::move(frame)); +} + +TEST_F(CCSerializationPerfTest, DelegatedFrame_ManyRenderPasses_10000_100) { + CompositorFrame frame; + frame.delegated_frame_data.reset(new DelegatedFrameData); + + for (int i = 0; i < 1000; ++i) { + std::unique_ptr<RenderPass> render_pass = RenderPass::Create(); + for (int j = 0; j < 100; ++j) { + render_pass->CreateAndAppendSharedQuadState(); + const gfx::Rect bounds(100, 100, 100, 100); + const bool kForceAntiAliasingOff = true; + SolidColorDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + quad->SetNew(render_pass->shared_quad_state_list.back(), bounds, bounds, + SK_ColorRED, kForceAntiAliasingOff); + } + frame.delegated_frame_data->render_pass_list.push_back( + std::move(render_pass)); + } + + RunTest("DelegatedFrame_ManyRenderPasses_10000_100", std::move(frame)); +} + +} // namespace +} // namespace cc
diff --git a/cc/ipc/compositor_frame_metadata.mojom b/cc/ipc/compositor_frame_metadata.mojom index 8db3460..93d1ca9f 100644 --- a/cc/ipc/compositor_frame_metadata.mojom +++ b/cc/ipc/compositor_frame_metadata.mojom
@@ -20,6 +20,7 @@ float max_page_scale_factor; bool root_overflow_x_hidden; bool root_overflow_y_hidden; + bool is_resourceless_software_draw_with_scroll_or_animation; gfx.mojom.Vector2dF location_bar_offset; gfx.mojom.Vector2dF location_bar_content_translation; uint32 root_background_color;
diff --git a/cc/ipc/compositor_frame_metadata_struct_traits.cc b/cc/ipc/compositor_frame_metadata_struct_traits.cc index 5294bde..177abbb 100644 --- a/cc/ipc/compositor_frame_metadata_struct_traits.cc +++ b/cc/ipc/compositor_frame_metadata_struct_traits.cc
@@ -29,6 +29,8 @@ out->max_page_scale_factor = data.max_page_scale_factor(); out->root_overflow_x_hidden = data.root_overflow_x_hidden(); out->root_overflow_y_hidden = data.root_overflow_y_hidden(); + out->is_resourceless_software_draw_with_scroll_or_animation = + data.is_resourceless_software_draw_with_scroll_or_animation(); if (!data.ReadLocationBarOffset(&out->location_bar_offset) || !data.ReadLocationBarContentTranslation( &out->location_bar_content_translation)) {
diff --git a/cc/ipc/compositor_frame_metadata_struct_traits.h b/cc/ipc/compositor_frame_metadata_struct_traits.h index fedd13e..9bf8c07 100644 --- a/cc/ipc/compositor_frame_metadata_struct_traits.h +++ b/cc/ipc/compositor_frame_metadata_struct_traits.h
@@ -57,6 +57,11 @@ return metadata.root_overflow_y_hidden; } + static bool is_resourceless_software_draw_with_scroll_or_animation( + const cc::CompositorFrameMetadata& metadata) { + return metadata.is_resourceless_software_draw_with_scroll_or_animation; + } + static gfx::Vector2dF location_bar_offset( const cc::CompositorFrameMetadata& metadata) { return metadata.location_bar_offset;
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc index 248ea4c..f74f10ad 100644 --- a/cc/ipc/struct_traits_unittest.cc +++ b/cc/ipc/struct_traits_unittest.cc
@@ -267,6 +267,7 @@ const float max_page_scale_factor = 4.6f; const bool root_overflow_x_hidden = true; const bool root_overflow_y_hidden = true; + const bool is_resourceless_software_draw_with_scroll_or_animation = true; const gfx::Vector2dF location_bar_offset(1234.5f, 5432.1f); const gfx::Vector2dF location_bar_content_translation(1234.5f, 5432.1f); const uint32_t root_background_color = 1337; @@ -300,6 +301,8 @@ input.max_page_scale_factor = max_page_scale_factor; input.root_overflow_x_hidden = root_overflow_x_hidden; input.root_overflow_y_hidden = root_overflow_y_hidden; + input.is_resourceless_software_draw_with_scroll_or_animation = + is_resourceless_software_draw_with_scroll_or_animation; input.location_bar_offset = location_bar_offset; input.location_bar_content_translation = location_bar_content_translation; input.root_background_color = root_background_color; @@ -320,6 +323,8 @@ EXPECT_EQ(max_page_scale_factor, output.max_page_scale_factor); EXPECT_EQ(root_overflow_x_hidden, output.root_overflow_x_hidden); EXPECT_EQ(root_overflow_y_hidden, output.root_overflow_y_hidden); + EXPECT_EQ(is_resourceless_software_draw_with_scroll_or_animation, + output.is_resourceless_software_draw_with_scroll_or_animation); EXPECT_EQ(location_bar_offset, output.location_bar_offset); EXPECT_EQ(location_bar_content_translation, output.location_bar_content_translation);
diff --git a/cc/layers/heads_up_display_layer.cc b/cc/layers/heads_up_display_layer.cc index 0492cb0a..2feb1fa 100644 --- a/cc/layers/heads_up_display_layer.cc +++ b/cc/layers/heads_up_display_layer.cc
@@ -63,7 +63,7 @@ std::unique_ptr<LayerImpl> HeadsUpDisplayLayer::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return HeadsUpDisplayLayerImpl::Create(tree_impl, layer_id_); + return HeadsUpDisplayLayerImpl::Create(tree_impl, id()); } void HeadsUpDisplayLayer::SetTypeForProtoSerialization(
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 60afdfb..30c110e 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -31,8 +31,10 @@ #include "cc/proto/layer.pb.h" #include "cc/proto/skia_conversions.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/transform_node.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -41,55 +43,60 @@ base::StaticAtomicSequenceNumber g_next_layer_id; +Layer::Inputs::Inputs() + : // Layer IDs start from 1. + layer_id(g_next_layer_id.GetNext() + 1), + masks_to_bounds(false), + mask_layer(nullptr), + replica_layer(nullptr), + opacity(1.f), + blend_mode(SkXfermode::kSrcOver_Mode), + is_root_for_isolated_group(false), + contents_opaque(false), + is_drawable(false), + double_sided(true), + should_flatten_transform(true), + sorting_context_id(0), + use_parent_backface_visibility(false), + background_color(0), + scroll_clip_layer_id(INVALID_ID), + user_scrollable_horizontal(true), + user_scrollable_vertical(true), + main_thread_scrolling_reasons( + MainThreadScrollingReason::kNotScrollingOnMain), + is_container_for_fixed_position_layers(false), + mutable_properties(MutableProperty::kNone), + scroll_parent(nullptr), + clip_parent(nullptr), + has_will_change_transform_hint(false), + hide_layer_and_subtree(false), + client(nullptr) {} + +Layer::Inputs::~Inputs() {} + scoped_refptr<Layer> Layer::Create() { return make_scoped_refptr(new Layer()); } Layer::Layer() - : // Layer IDs start from 1. - layer_id_(g_next_layer_id.GetNext() + 1), - ignore_set_needs_commit_(false), - sorting_context_id_(0), + : ignore_set_needs_commit_(false), parent_(nullptr), layer_tree_host_(nullptr), - scroll_clip_layer_id_(INVALID_ID), num_descendants_that_draw_content_(0), transform_tree_index_(-1), effect_tree_index_(-1), clip_tree_index_(-1), scroll_tree_index_(-1), property_tree_sequence_number_(-1), - mutable_properties_(MutableProperty::kNone), - main_thread_scrolling_reasons_( - MainThreadScrollingReason::kNotScrollingOnMain), should_flatten_transform_from_property_tree_(false), - user_scrollable_horizontal_(true), - user_scrollable_vertical_(true), - is_root_for_isolated_group_(false), - is_container_for_fixed_position_layers_(false), - is_drawable_(false), draws_content_(false), - hide_layer_and_subtree_(false), - masks_to_bounds_(false), - contents_opaque_(false), - double_sided_(true), - should_flatten_transform_(true), - use_parent_backface_visibility_(false), use_local_transform_for_backface_visibility_(false), should_check_backface_visibility_(false), force_render_surface_for_testing_(false), subtree_property_changed_(false), layer_property_changed_(false), - has_will_change_transform_hint_(false), - background_color_(0), safe_opaque_background_color_(0), - opacity_(1.f), - blend_mode_(SkXfermode::kSrcOver_Mode), draw_blend_mode_(SkXfermode::kSrcOver_Mode), - scroll_parent_(nullptr), - clip_parent_(nullptr), - replica_layer_(nullptr), - client_(nullptr), num_unclipped_descendants_(0) {} Layer::~Layer() { @@ -105,13 +112,13 @@ // Remove the parent reference from all children and dependents. RemoveAllChildren(); - if (mask_layer_.get()) { - DCHECK_EQ(this, mask_layer_->parent()); - mask_layer_->RemoveFromParent(); + if (inputs_.mask_layer.get()) { + DCHECK_EQ(this, inputs_.mask_layer->parent()); + inputs_.mask_layer->RemoveFromParent(); } - if (replica_layer_.get()) { - DCHECK_EQ(this, replica_layer_->parent()); - replica_layer_->RemoveFromParent(); + if (inputs_.replica_layer.get()) { + DCHECK_EQ(this, inputs_.replica_layer->parent()); + inputs_.replica_layer->RemoveFromParent(); } } @@ -123,18 +130,18 @@ layer_tree_host_->property_trees()->RemoveIdFromIdToIndexMaps(id()); layer_tree_host_->property_trees()->needs_rebuild = true; layer_tree_host_->UnregisterLayer(this); - if (element_id_) { + if (inputs_.element_id) { layer_tree_host_->animation_host()->UnregisterElement( - element_id_, ElementListType::ACTIVE); + inputs_.element_id, ElementListType::ACTIVE); layer_tree_host_->RemoveFromElementMap(this); } } if (host) { host->property_trees()->needs_rebuild = true; host->RegisterLayer(this); - if (element_id_) { + if (inputs_.element_id) { host->AddToElementMap(this); - host->animation_host()->RegisterElement(element_id_, + host->animation_host()->RegisterElement(inputs_.element_id, ElementListType::ACTIVE); } } @@ -146,13 +153,13 @@ // side for the new host. SetNeedsPushProperties(); - for (size_t i = 0; i < children_.size(); ++i) - children_[i]->SetLayerTreeHost(host); + for (size_t i = 0; i < inputs_.children.size(); ++i) + inputs_.children[i]->SetLayerTreeHost(host); - if (mask_layer_.get()) - mask_layer_->SetLayerTreeHost(host); - if (replica_layer_.get()) - replica_layer_->SetLayerTreeHost(host); + if (inputs_.mask_layer.get()) + inputs_.mask_layer->SetLayerTreeHost(host); + if (inputs_.replica_layer.get()) + inputs_.replica_layer->SetLayerTreeHost(host); const bool has_any_animation = layer_tree_host_ ? layer_tree_host_->HasAnyAnimation(this) : false; @@ -238,7 +245,7 @@ } void Layer::AddChild(scoped_refptr<Layer> child) { - InsertChild(child, children_.size()); + InsertChild(child, inputs_.children.size()); } void Layer::InsertChild(scoped_refptr<Layer> child, size_t index) { @@ -249,8 +256,8 @@ child->SetParent(this); child->SetSubtreePropertyChanged(); - index = std::min(index, children_.size()); - children_.insert(children_.begin() + index, child); + index = std::min(index, inputs_.children.size()); + inputs_.children.insert(inputs_.children.begin() + index, child); SetNeedsFullTreeSync(); } @@ -261,29 +268,28 @@ } void Layer::RemoveChildOrDependent(Layer* child) { - if (mask_layer_.get() == child) { - mask_layer_->SetParent(nullptr); - mask_layer_ = nullptr; + if (inputs_.mask_layer.get() == child) { + inputs_.mask_layer->SetParent(nullptr); + inputs_.mask_layer = nullptr; SetNeedsFullTreeSync(); return; } - if (replica_layer_.get() == child) { - replica_layer_->SetParent(nullptr); - replica_layer_ = nullptr; + if (inputs_.replica_layer.get() == child) { + inputs_.replica_layer->SetParent(nullptr); + inputs_.replica_layer = nullptr; SetNeedsFullTreeSync(); return; } - for (LayerList::iterator iter = children_.begin(); - iter != children_.end(); - ++iter) { + for (LayerList::iterator iter = inputs_.children.begin(); + iter != inputs_.children.end(); ++iter) { if (iter->get() != child) continue; child->SetParent(nullptr); AddDrawableDescendants(-child->NumDescendantsThatDrawContent() - (child->DrawsContent() ? 1 : 0)); - children_.erase(iter); + inputs_.children.erase(iter); SetNeedsFullTreeSync(); return; } @@ -299,12 +305,12 @@ // Find the index of |reference| in |children_|. auto reference_it = - std::find_if(children_.begin(), children_.end(), + std::find_if(inputs_.children.begin(), inputs_.children.end(), [reference](const scoped_refptr<Layer>& layer) { return layer.get() == reference; }); - DCHECK(reference_it != children_.end()); - size_t reference_index = reference_it - children_.begin(); + DCHECK(reference_it != inputs_.children.end()); + size_t reference_index = reference_it - inputs_.children.begin(); reference->RemoveFromParent(); if (new_layer.get()) { @@ -317,7 +323,7 @@ DCHECK(IsPropertyChangeAllowed()); if (bounds() == size) return; - bounds_ = size; + inputs_.bounds = size; if (!layer_tree_host_) return; @@ -336,8 +342,8 @@ void Layer::RemoveAllChildren() { DCHECK(IsPropertyChangeAllowed()); - while (children_.size()) { - Layer* layer = children_[0].get(); + while (inputs_.children.size()) { + Layer* layer = inputs_.children[0].get(); DCHECK_EQ(this, layer->parent()); layer->RemoveFromParent(); } @@ -345,7 +351,7 @@ void Layer::SetChildren(const LayerList& children) { DCHECK(IsPropertyChangeAllowed()); - if (children == children_) + if (children == inputs_.children) return; RemoveAllChildren(); @@ -365,25 +371,25 @@ DCHECK(IsPropertyChangeAllowed()); if (void* source = request->source()) { auto it = - std::find_if(copy_requests_.begin(), copy_requests_.end(), + std::find_if(inputs_.copy_requests.begin(), inputs_.copy_requests.end(), [source](const std::unique_ptr<CopyOutputRequest>& x) { return x->source() == source; }); - if (it != copy_requests_.end()) - copy_requests_.erase(it); + if (it != inputs_.copy_requests.end()) + inputs_.copy_requests.erase(it); } if (request->IsEmpty()) return; - copy_requests_.push_back(std::move(request)); + inputs_.copy_requests.push_back(std::move(request)); SetSubtreePropertyChanged(); SetNeedsCommit(); } void Layer::SetBackgroundColor(SkColor background_color) { DCHECK(IsPropertyChangeAllowed()); - if (background_color_ == background_color) + if (inputs_.background_color == background_color) return; - background_color_ = background_color; + inputs_.background_color = background_color; SetNeedsCommit(); } @@ -406,27 +412,27 @@ void Layer::SetMasksToBounds(bool masks_to_bounds) { DCHECK(IsPropertyChangeAllowed()); - if (masks_to_bounds_ == masks_to_bounds) + if (inputs_.masks_to_bounds == masks_to_bounds) return; - masks_to_bounds_ = masks_to_bounds; + inputs_.masks_to_bounds = masks_to_bounds; SetNeedsCommit(); SetSubtreePropertyChanged(); } void Layer::SetMaskLayer(Layer* mask_layer) { DCHECK(IsPropertyChangeAllowed()); - if (mask_layer_.get() == mask_layer) + if (inputs_.mask_layer.get() == mask_layer) return; - if (mask_layer_.get()) { - DCHECK_EQ(this, mask_layer_->parent()); - mask_layer_->RemoveFromParent(); + if (inputs_.mask_layer.get()) { + DCHECK_EQ(this, inputs_.mask_layer->parent()); + inputs_.mask_layer->RemoveFromParent(); } - mask_layer_ = mask_layer; - if (mask_layer_.get()) { - mask_layer_->RemoveFromParent(); - DCHECK(!mask_layer_->parent()); - mask_layer_->SetParent(this); - mask_layer_->SetIsMask(true); + inputs_.mask_layer = mask_layer; + if (inputs_.mask_layer.get()) { + inputs_.mask_layer->RemoveFromParent(); + DCHECK(!inputs_.mask_layer->parent()); + inputs_.mask_layer->SetParent(this); + inputs_.mask_layer->SetIsMask(true); } SetSubtreePropertyChanged(); SetNeedsFullTreeSync(); @@ -434,17 +440,17 @@ void Layer::SetReplicaLayer(Layer* layer) { DCHECK(IsPropertyChangeAllowed()); - if (replica_layer_.get() == layer) + if (inputs_.replica_layer.get() == layer) return; - if (replica_layer_.get()) { - DCHECK_EQ(this, replica_layer_->parent()); - replica_layer_->RemoveFromParent(); + if (inputs_.replica_layer.get()) { + DCHECK_EQ(this, inputs_.replica_layer->parent()); + inputs_.replica_layer->RemoveFromParent(); } - replica_layer_ = layer; - if (replica_layer_.get()) { - DCHECK(!replica_layer_->parent()); - replica_layer_->RemoveFromParent(); - replica_layer_->SetParent(this); + inputs_.replica_layer = layer; + if (inputs_.replica_layer.get()) { + DCHECK(!inputs_.replica_layer->parent()); + inputs_.replica_layer->RemoveFromParent(); + inputs_.replica_layer->SetParent(this); } SetSubtreePropertyChanged(); SetNeedsFullTreeSync(); @@ -452,9 +458,9 @@ void Layer::SetFilters(const FilterOperations& filters) { DCHECK(IsPropertyChangeAllowed()); - if (filters_ == filters) + if (inputs_.filters == filters) return; - filters_ = filters; + inputs_.filters = filters; SetSubtreePropertyChanged(); SetNeedsCommit(); } @@ -470,9 +476,9 @@ void Layer::SetBackgroundFilters(const FilterOperations& filters) { DCHECK(IsPropertyChangeAllowed()); - if (background_filters_ == filters) + if (inputs_.background_filters == filters) return; - background_filters_ = filters; + inputs_.background_filters = filters; SetLayerPropertyChanged(); SetNeedsCommit(); } @@ -482,12 +488,12 @@ DCHECK_GE(opacity, 0.f); DCHECK_LE(opacity, 1.f); - if (opacity_ == opacity) + if (inputs_.opacity == opacity) return; // We need to force a property tree rebuild when opacity changes from 1 to a // non-1 value or vice-versa as render surfaces can change. - bool force_rebuild = opacity == 1.f || opacity_ == 1.f; - opacity_ = opacity; + bool force_rebuild = opacity == 1.f || inputs_.opacity == 1.f; + inputs_.opacity = opacity; SetSubtreePropertyChanged(); if (layer_tree_host_ && !force_rebuild) { PropertyTrees* property_trees = layer_tree_host_->property_trees(); @@ -495,8 +501,8 @@ if (effect_id_to_index != property_trees->effect_id_to_index_map.end()) { EffectNode* node = property_trees->effect_tree.Node(effect_id_to_index->second); - node->data.opacity = opacity; - node->data.effect_changed = true; + node->opacity = opacity; + node->effect_changed = true; property_trees->effect_tree.set_needs_update(true); SetNeedsCommitNoRebuild(); return; @@ -506,7 +512,7 @@ } float Layer::EffectiveOpacity() const { - return hide_layer_and_subtree_ ? 0.f : opacity_; + return inputs_.hide_layer_and_subtree ? 0.f : inputs_.opacity; } bool Layer::OpacityIsAnimating() const { @@ -528,7 +534,7 @@ void Layer::SetBlendMode(SkXfermode::Mode blend_mode) { DCHECK(IsPropertyChangeAllowed()); - if (blend_mode_ == blend_mode) + if (inputs_.blend_mode == blend_mode) return; // Allowing only blend modes that are defined in the CSS Compositing standard: @@ -571,33 +577,33 @@ return; } - blend_mode_ = blend_mode; + inputs_.blend_mode = blend_mode; SetNeedsCommit(); SetSubtreePropertyChanged(); } void Layer::SetIsRootForIsolatedGroup(bool root) { DCHECK(IsPropertyChangeAllowed()); - if (is_root_for_isolated_group_ == root) + if (inputs_.is_root_for_isolated_group == root) return; - is_root_for_isolated_group_ = root; + inputs_.is_root_for_isolated_group = root; SetNeedsCommit(); } void Layer::SetContentsOpaque(bool opaque) { DCHECK(IsPropertyChangeAllowed()); - if (contents_opaque_ == opaque) + if (inputs_.contents_opaque == opaque) return; - contents_opaque_ = opaque; + inputs_.contents_opaque = opaque; SetNeedsCommit(); SetSubtreePropertyChanged(); } void Layer::SetPosition(const gfx::PointF& position) { DCHECK(IsPropertyChangeAllowed()); - if (position_ == position) + if (inputs_.position == position) return; - position_ = position; + inputs_.position = position; if (!layer_tree_host_) return; @@ -610,10 +616,9 @@ property_trees->transform_id_to_index_map[id()]); TransformNode* transform_node = property_trees->transform_tree.Node(transform_tree_index()); - transform_node->data.update_post_local_transform(position, - transform_origin()); - transform_node->data.needs_local_transform_update = true; - transform_node->data.transform_changed = true; + transform_node->update_post_local_transform(position, transform_origin()); + transform_node->needs_local_transform_update = true; + transform_node->transform_changed = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); SetNeedsCommitNoRebuild(); return; @@ -623,11 +628,11 @@ } bool Layer::IsContainerForFixedPositionLayers() const { - if (!transform_.IsIdentityOrTranslation()) + if (!inputs_.transform.IsIdentityOrTranslation()) return true; - if (parent_ && !parent_->transform_.IsIdentityOrTranslation()) + if (parent_ && !parent_->inputs_.transform.IsIdentityOrTranslation()) return true; - return is_container_for_fixed_position_layers_; + return inputs_.is_container_for_fixed_position_layers; } bool Are2dAxisAligned(const gfx::Transform& a, const gfx::Transform& b) { @@ -647,7 +652,7 @@ void Layer::SetTransform(const gfx::Transform& transform) { DCHECK(IsPropertyChangeAllowed()); - if (transform_ == transform) + if (inputs_.transform == transform) return; SetSubtreePropertyChanged(); @@ -656,37 +661,38 @@ if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::TRANSFORM, id())) { // We need to trigger a rebuild if we could have affected 2d axis - // alignment. We'll check to see if transform and transform_ are axis + // alignment. We'll check to see if transform and inputs_.transform + // are axis // align with respect to one another. DCHECK_EQ(transform_tree_index(), property_trees->transform_id_to_index_map[id()]); TransformNode* transform_node = property_trees->transform_tree.Node(transform_tree_index()); bool preserves_2d_axis_alignment = - Are2dAxisAligned(transform_, transform); - transform_node->data.local = transform; - transform_node->data.needs_local_transform_update = true; - transform_node->data.transform_changed = true; + Are2dAxisAligned(inputs_.transform, transform); + transform_node->local = transform; + transform_node->needs_local_transform_update = true; + transform_node->transform_changed = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); if (preserves_2d_axis_alignment) SetNeedsCommitNoRebuild(); else SetNeedsCommit(); - transform_ = transform; + inputs_.transform = transform; return; } } - transform_ = transform; + inputs_.transform = transform; SetNeedsCommit(); } void Layer::SetTransformOrigin(const gfx::Point3F& transform_origin) { DCHECK(IsPropertyChangeAllowed()); - if (transform_origin_ == transform_origin) + if (inputs_.transform_origin == transform_origin) return; - transform_origin_ = transform_origin; + inputs_.transform_origin = transform_origin; if (!layer_tree_host_) return; @@ -699,11 +705,10 @@ property_trees->transform_id_to_index_map[id()]); TransformNode* transform_node = property_trees->transform_tree.Node(transform_tree_index()); - transform_node->data.update_pre_local_transform(transform_origin); - transform_node->data.update_post_local_transform(position(), - transform_origin); - transform_node->data.needs_local_transform_update = true; - transform_node->data.transform_changed = true; + transform_node->update_pre_local_transform(transform_origin); + transform_node->update_post_local_transform(position(), transform_origin); + transform_node->needs_local_transform_update = true; + transform_node->transform_changed = true; layer_tree_host_->property_trees()->transform_tree.set_needs_update(true); SetNeedsCommitNoRebuild(); return; @@ -750,16 +755,16 @@ void Layer::SetScrollParent(Layer* parent) { DCHECK(IsPropertyChangeAllowed()); - if (scroll_parent_ == parent) + if (inputs_.scroll_parent == parent) return; - if (scroll_parent_) - scroll_parent_->RemoveScrollChild(this); + if (inputs_.scroll_parent) + inputs_.scroll_parent->RemoveScrollChild(this); - scroll_parent_ = parent; + inputs_.scroll_parent = parent; - if (scroll_parent_) - scroll_parent_->AddScrollChild(this); + if (inputs_.scroll_parent) + inputs_.scroll_parent->AddScrollChild(this); SetNeedsCommit(); } @@ -780,16 +785,16 @@ void Layer::SetClipParent(Layer* ancestor) { DCHECK(IsPropertyChangeAllowed()); - if (clip_parent_ == ancestor) + if (inputs_.clip_parent == ancestor) return; - if (clip_parent_) - clip_parent_->RemoveClipChild(this); + if (inputs_.clip_parent) + inputs_.clip_parent->RemoveClipChild(this); - clip_parent_ = ancestor; + inputs_.clip_parent = ancestor; - if (clip_parent_) - clip_parent_->AddClipChild(this); + if (inputs_.clip_parent) + inputs_.clip_parent->AddClipChild(this); SetNeedsCommit(); if (layer_tree_host_) @@ -813,9 +818,9 @@ void Layer::SetScrollOffset(const gfx::ScrollOffset& scroll_offset) { DCHECK(IsPropertyChangeAllowed()); - if (scroll_offset_ == scroll_offset) + if (inputs_.scroll_offset == scroll_offset) return; - scroll_offset_ = scroll_offset; + inputs_.scroll_offset = scroll_offset; if (!layer_tree_host_) return; @@ -830,8 +835,8 @@ property_trees->transform_id_to_index_map[id()]); TransformNode* transform_node = property_trees->transform_tree.Node(transform_tree_index()); - transform_node->data.scroll_offset = CurrentScrollOffset(); - transform_node->data.needs_local_transform_update = true; + transform_node->scroll_offset = CurrentScrollOffset(); + transform_node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); SetNeedsCommitNoRebuild(); return; @@ -846,9 +851,9 @@ // This function only gets called during a BeginMainFrame, so there // is no need to call SetNeedsUpdate here. DCHECK(layer_tree_host_ && layer_tree_host_->CommitRequested()); - if (scroll_offset_ == scroll_offset) + if (inputs_.scroll_offset == scroll_offset) return; - scroll_offset_ = scroll_offset; + inputs_.scroll_offset = scroll_offset; SetNeedsPushProperties(); bool needs_rebuild = true; @@ -863,8 +868,8 @@ property_trees->transform_id_to_index_map[id()]); TransformNode* transform_node = property_trees->transform_tree.Node(transform_tree_index()); - transform_node->data.scroll_offset = CurrentScrollOffset(); - transform_node->data.needs_local_transform_update = true; + transform_node->scroll_offset = CurrentScrollOffset(); + transform_node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); needs_rebuild = false; } @@ -872,31 +877,31 @@ if (needs_rebuild) property_trees->needs_rebuild = true; - if (!did_scroll_callback_.is_null()) - did_scroll_callback_.Run(); + if (!inputs_.did_scroll_callback.is_null()) + inputs_.did_scroll_callback.Run(); // The callback could potentially change the layer structure: // "this" may have been destroyed during the process. } void Layer::SetScrollClipLayerId(int clip_layer_id) { DCHECK(IsPropertyChangeAllowed()); - if (scroll_clip_layer_id_ == clip_layer_id) + if (inputs_.scroll_clip_layer_id == clip_layer_id) return; - scroll_clip_layer_id_ = clip_layer_id; + inputs_.scroll_clip_layer_id = clip_layer_id; SetNeedsCommit(); } Layer* Layer::scroll_clip_layer() const { - return layer_tree_host()->LayerById(scroll_clip_layer_id_); + return layer_tree_host()->LayerById(inputs_.scroll_clip_layer_id); } void Layer::SetUserScrollable(bool horizontal, bool vertical) { DCHECK(IsPropertyChangeAllowed()); - if (user_scrollable_horizontal_ == horizontal && - user_scrollable_vertical_ == vertical) + if (inputs_.user_scrollable_horizontal == horizontal && + inputs_.user_scrollable_vertical == vertical) return; - user_scrollable_horizontal_ = horizontal; - user_scrollable_vertical_ = vertical; + inputs_.user_scrollable_horizontal = horizontal; + inputs_.user_scrollable_vertical = vertical; SetNeedsCommit(); } @@ -905,10 +910,10 @@ DCHECK(IsPropertyChangeAllowed()); DCHECK(main_thread_scrolling_reasons); uint32_t new_reasons = - main_thread_scrolling_reasons_ | main_thread_scrolling_reasons; - if (main_thread_scrolling_reasons_ == new_reasons) + inputs_.main_thread_scrolling_reasons | main_thread_scrolling_reasons; + if (inputs_.main_thread_scrolling_reasons == new_reasons) return; - main_thread_scrolling_reasons_ = new_reasons; + inputs_.main_thread_scrolling_reasons = new_reasons; SetNeedsCommit(); } @@ -916,28 +921,28 @@ uint32_t main_thread_scrolling_reasons_to_clear) { DCHECK(IsPropertyChangeAllowed()); DCHECK(main_thread_scrolling_reasons_to_clear); - uint32_t new_reasons = - ~main_thread_scrolling_reasons_to_clear & main_thread_scrolling_reasons_; - if (new_reasons == main_thread_scrolling_reasons_) + uint32_t new_reasons = ~main_thread_scrolling_reasons_to_clear & + inputs_.main_thread_scrolling_reasons; + if (new_reasons == inputs_.main_thread_scrolling_reasons) return; - main_thread_scrolling_reasons_ = new_reasons; + inputs_.main_thread_scrolling_reasons = new_reasons; SetNeedsCommit(); } void Layer::SetNonFastScrollableRegion(const Region& region) { DCHECK(IsPropertyChangeAllowed()); - if (non_fast_scrollable_region_ == region) + if (inputs_.non_fast_scrollable_region == region) return; - non_fast_scrollable_region_ = region; + inputs_.non_fast_scrollable_region = region; SetNeedsCommit(); } void Layer::SetTouchEventHandlerRegion(const Region& region) { DCHECK(IsPropertyChangeAllowed()); - if (touch_event_handler_region_ == region) + if (inputs_.touch_event_handler_region == region) return; - touch_event_handler_region_ = region; + inputs_.touch_event_handler_region = region; SetNeedsCommit(); } @@ -951,18 +956,18 @@ void Layer::SetDoubleSided(bool double_sided) { DCHECK(IsPropertyChangeAllowed()); - if (double_sided_ == double_sided) + if (inputs_.double_sided == double_sided) return; - double_sided_ = double_sided; + inputs_.double_sided = double_sided; SetNeedsCommit(); SetSubtreePropertyChanged(); } void Layer::Set3dSortingContextId(int id) { DCHECK(IsPropertyChangeAllowed()); - if (id == sorting_context_id_) + if (id == inputs_.sorting_context_id) return; - sorting_context_id_ = id; + inputs_.sorting_context_id = id; SetNeedsCommit(); SetSubtreePropertyChanged(); } @@ -1044,18 +1049,18 @@ void Layer::SetShouldFlattenTransform(bool should_flatten) { DCHECK(IsPropertyChangeAllowed()); - if (should_flatten_transform_ == should_flatten) + if (inputs_.should_flatten_transform == should_flatten) return; - should_flatten_transform_ = should_flatten; + inputs_.should_flatten_transform = should_flatten; SetNeedsCommit(); SetSubtreePropertyChanged(); } void Layer::SetUseParentBackfaceVisibility(bool use) { DCHECK(IsPropertyChangeAllowed()); - if (use_parent_backface_visibility_ == use) + if (inputs_.use_parent_backface_visibility == use) return; - use_parent_backface_visibility_ = use; + inputs_.use_parent_backface_visibility = use; SetNeedsPushProperties(); } @@ -1076,19 +1081,19 @@ void Layer::SetIsDrawable(bool is_drawable) { DCHECK(IsPropertyChangeAllowed()); - if (is_drawable_ == is_drawable) + if (inputs_.is_drawable == is_drawable) return; - is_drawable_ = is_drawable; + inputs_.is_drawable = is_drawable; UpdateDrawsContent(HasDrawableContent()); } void Layer::SetHideLayerAndSubtree(bool hide) { DCHECK(IsPropertyChangeAllowed()); - if (hide_layer_and_subtree_ == hide) + if (inputs_.hide_layer_and_subtree == hide) return; - hide_layer_and_subtree_ = hide; + inputs_.hide_layer_and_subtree = hide; SetNeedsCommit(); SetSubtreePropertyChanged(); } @@ -1098,25 +1103,25 @@ return; SetNeedsPushProperties(); - update_rect_.Union(dirty_rect); + inputs_.update_rect.Union(dirty_rect); if (DrawsContent()) SetNeedsUpdate(); } bool Layer::DescendantIsFixedToContainerLayer() const { - for (size_t i = 0; i < children_.size(); ++i) { - if (children_[i]->position_constraint_.is_fixed_position() || - children_[i]->DescendantIsFixedToContainerLayer()) + for (size_t i = 0; i < inputs_.children.size(); ++i) { + if (inputs_.children[i]->inputs_.position_constraint.is_fixed_position() || + inputs_.children[i]->DescendantIsFixedToContainerLayer()) return true; } return false; } void Layer::SetIsContainerForFixedPositionLayers(bool container) { - if (is_container_for_fixed_position_layers_ == container) + if (inputs_.is_container_for_fixed_position_layers == container) return; - is_container_for_fixed_position_layers_ = container; + inputs_.is_container_for_fixed_position_layers = container; if (layer_tree_host_ && layer_tree_host_->CommitRequested()) return; @@ -1128,9 +1133,9 @@ void Layer::SetPositionConstraint(const LayerPositionConstraint& constraint) { DCHECK(IsPropertyChangeAllowed()); - if (position_constraint_ == constraint) + if (inputs_.position_constraint == constraint) return; - position_constraint_ = constraint; + inputs_.position_constraint = constraint; SetNeedsCommit(); } @@ -1159,10 +1164,10 @@ bool use_paint_properties = paint_properties_.source_frame_number == layer_tree_host_->source_frame_number(); - layer->SetBackgroundColor(background_color_); + layer->SetBackgroundColor(inputs_.background_color); layer->SetSafeOpaqueBackgroundColor(safe_opaque_background_color_); layer->SetBounds(use_paint_properties ? paint_properties_.bounds - : bounds_); + : inputs_.bounds); #if defined(NDEBUG) if (frame_viewer_instrumentation::IsTracingLayerTreeSnapshots()) @@ -1182,30 +1187,31 @@ if (subtree_property_changed_ || layer_property_changed_) layer->NoteLayerPropertyChanged(); if (!FilterIsAnimating()) - layer->SetFilters(filters_); - layer->SetMasksToBounds(masks_to_bounds_); - layer->set_main_thread_scrolling_reasons(main_thread_scrolling_reasons_); - layer->SetNonFastScrollableRegion(non_fast_scrollable_region_); - layer->SetTouchEventHandlerRegion(touch_event_handler_region_); - layer->SetContentsOpaque(contents_opaque_); - layer->SetBlendMode(blend_mode_); - layer->SetPosition(position_); + layer->SetFilters(inputs_.filters); + layer->SetMasksToBounds(inputs_.masks_to_bounds); + layer->set_main_thread_scrolling_reasons( + inputs_.main_thread_scrolling_reasons); + layer->SetNonFastScrollableRegion(inputs_.non_fast_scrollable_region); + layer->SetTouchEventHandlerRegion(inputs_.touch_event_handler_region); + layer->SetContentsOpaque(inputs_.contents_opaque); + layer->SetBlendMode(inputs_.blend_mode); + layer->SetPosition(inputs_.position); layer->set_should_flatten_transform_from_property_tree( should_flatten_transform_from_property_tree_); layer->set_draw_blend_mode(draw_blend_mode_); - layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); + layer->SetUseParentBackfaceVisibility(inputs_.use_parent_backface_visibility); layer->SetUseLocalTransformForBackfaceVisibility( use_local_transform_for_backface_visibility_); layer->SetShouldCheckBackfaceVisibility(should_check_backface_visibility_); if (!TransformIsAnimating()) - layer->SetTransform(transform_); - layer->Set3dSortingContextId(sorting_context_id_); + layer->SetTransform(inputs_.transform); + layer->Set3dSortingContextId(inputs_.sorting_context_id); - layer->SetScrollClipLayer(scroll_clip_layer_id_); - layer->set_user_scrollable_horizontal(user_scrollable_horizontal_); - layer->set_user_scrollable_vertical(user_scrollable_vertical_); - layer->SetElementId(element_id_); - layer->SetMutableProperties(mutable_properties_); + layer->SetScrollClipLayer(inputs_.scroll_clip_layer_id); + layer->set_user_scrollable_horizontal(inputs_.user_scrollable_horizontal); + layer->set_user_scrollable_vertical(inputs_.user_scrollable_vertical); + layer->SetElementId(inputs_.element_id); + layer->SetMutableProperties(inputs_.mutable_properties); // When a scroll offset animation is interrupted the new scroll position on // the pending tree will clobber any impl-side scrolling occuring on the @@ -1220,8 +1226,8 @@ // draws, then damage tracking will become incorrect if we simply clobber the // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e. // union) any update changes that have occurred on the main thread. - update_rect_.Union(layer->update_rect()); - layer->SetUpdateRect(update_rect_); + inputs_.update_rect.Union(layer->update_rect()); + layer->SetUpdateRect(inputs_.update_rect); layer->SetHasWillChangeTransformHint(has_will_change_transform_hint()); layer->SetNeedsPushProperties(); @@ -1229,14 +1235,14 @@ // Reset any state that should be cleared for the next update. subtree_property_changed_ = false; layer_property_changed_ = false; - update_rect_ = gfx::Rect(); + inputs_.update_rect = gfx::Rect(); layer_tree_host()->RemoveLayerShouldPushProperties(this); } void Layer::TakeCopyRequests( std::vector<std::unique_ptr<CopyOutputRequest>>* requests) { - for (auto& it : copy_requests_) { + for (auto& it : inputs_.copy_requests) { scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner = layer_tree_host()->task_runner_provider()->MainThreadTaskRunner(); std::unique_ptr<CopyOutputRequest> original_request = std::move(it); @@ -1253,7 +1259,7 @@ requests->push_back(std::move(main_thread_request)); } - copy_requests_.clear(); + inputs_.copy_requests.clear(); } void Layer::SetTypeForProtoSerialization(proto::LayerNode* proto) const { @@ -1261,26 +1267,26 @@ } void Layer::ToLayerNodeProto(proto::LayerNode* proto) const { - proto->set_id(layer_id_); + proto->set_id(inputs_.layer_id); SetTypeForProtoSerialization(proto); if (parent_) proto->set_parent_id(parent_->id()); DCHECK_EQ(0, proto->children_size()); - for (const auto& child : children_) { + for (const auto& child : inputs_.children) { child->ToLayerNodeProto(proto->add_children()); } - if (mask_layer_) - mask_layer_->ToLayerNodeProto(proto->mutable_mask_layer()); - if (replica_layer_) - replica_layer_->ToLayerNodeProto(proto->mutable_replica_layer()); + if (inputs_.mask_layer) + inputs_.mask_layer->ToLayerNodeProto(proto->mutable_mask_layer()); + if (inputs_.replica_layer) + inputs_.replica_layer->ToLayerNodeProto(proto->mutable_replica_layer()); } void Layer::ClearLayerTreePropertiesForDeserializationAndAddToMap( LayerIdMap* layer_map) { - (*layer_map)[layer_id_] = this; + (*layer_map)[inputs_.layer_id] = this; if (layer_tree_host_) layer_tree_host_->UnregisterLayer(this); @@ -1289,22 +1295,22 @@ parent_ = nullptr; // Clear these properties for all the children and add them to the map. - for (auto& child : children_) { + for (auto& child : inputs_.children) { child->ClearLayerTreePropertiesForDeserializationAndAddToMap(layer_map); } - children_.clear(); + inputs_.children.clear(); - if (mask_layer_) { - mask_layer_->ClearLayerTreePropertiesForDeserializationAndAddToMap( + if (inputs_.mask_layer) { + inputs_.mask_layer->ClearLayerTreePropertiesForDeserializationAndAddToMap( layer_map); - mask_layer_ = nullptr; + inputs_.mask_layer = nullptr; } - if (replica_layer_) { - replica_layer_->ClearLayerTreePropertiesForDeserializationAndAddToMap( - layer_map); - replica_layer_ = nullptr; + if (inputs_.replica_layer) { + inputs_.replica_layer + ->ClearLayerTreePropertiesForDeserializationAndAddToMap(layer_map); + inputs_.replica_layer = nullptr; } } @@ -1312,13 +1318,13 @@ const LayerIdMap& layer_map, LayerTreeHost* layer_tree_host) { DCHECK(!layer_tree_host_); - DCHECK(children_.empty()); - DCHECK(!mask_layer_); - DCHECK(!replica_layer_); + DCHECK(inputs_.children.empty()); + DCHECK(!inputs_.mask_layer); + DCHECK(!inputs_.replica_layer); DCHECK(layer_tree_host); DCHECK(proto.has_id()); - layer_id_ = proto.id(); + inputs_.layer_id = proto.id(); layer_tree_host_ = layer_tree_host; layer_tree_host_->RegisterLayer(this); @@ -1333,36 +1339,36 @@ DCHECK(!child->parent_); child->parent_ = this; child->FromLayerNodeProto(child_proto, layer_map, layer_tree_host_); - children_.push_back(child); + inputs_.children.push_back(child); } if (proto.has_mask_layer()) { - mask_layer_ = LayerProtoConverter::FindOrAllocateAndConstruct( + inputs_.mask_layer = LayerProtoConverter::FindOrAllocateAndConstruct( proto.mask_layer(), layer_map); - mask_layer_->parent_ = this; - mask_layer_->FromLayerNodeProto(proto.mask_layer(), layer_map, - layer_tree_host_); + inputs_.mask_layer->parent_ = this; + inputs_.mask_layer->FromLayerNodeProto(proto.mask_layer(), layer_map, + layer_tree_host_); } if (proto.has_replica_layer()) { - replica_layer_ = LayerProtoConverter::FindOrAllocateAndConstruct( + inputs_.replica_layer = LayerProtoConverter::FindOrAllocateAndConstruct( proto.replica_layer(), layer_map); - replica_layer_->parent_ = this; - replica_layer_->FromLayerNodeProto(proto.replica_layer(), layer_map, - layer_tree_host_); + inputs_.replica_layer->parent_ = this; + inputs_.replica_layer->FromLayerNodeProto(proto.replica_layer(), layer_map, + layer_tree_host_); } } void Layer::ToLayerPropertiesProto(proto::LayerUpdate* layer_update) { // Always set properties metadata for serialized layers. proto::LayerProperties* proto = layer_update->add_layers(); - proto->set_id(layer_id_); + proto->set_id(inputs_.layer_id); LayerSpecificPropertiesToProto(proto); } void Layer::FromLayerPropertiesProto(const proto::LayerProperties& proto) { DCHECK(proto.has_id()); - DCHECK_EQ(layer_id_, proto.id()); + DCHECK_EQ(inputs_.layer_id, proto.id()); FromLayerSpecificPropertiesProto(proto); } @@ -1373,10 +1379,10 @@ paint_properties_.source_frame_number == layer_tree_host_->source_frame_number(); - Point3FToProto(transform_origin_, base->mutable_transform_origin()); - base->set_background_color(background_color_); + Point3FToProto(inputs_.transform_origin, base->mutable_transform_origin()); + base->set_background_color(inputs_.background_color); base->set_safe_opaque_background_color(safe_opaque_background_color_); - SizeToProto(use_paint_properties ? paint_properties_.bounds : bounds_, + SizeToProto(use_paint_properties ? paint_properties_.bounds : inputs_.bounds, base->mutable_bounds()); // TODO(nyquist): Figure out what to do with debug info. See crbug.com/570372. @@ -1387,44 +1393,47 @@ base->set_scroll_tree_index(scroll_tree_index_); Vector2dFToProto(offset_to_transform_parent_, base->mutable_offset_to_transform_parent()); - base->set_double_sided(double_sided_); + base->set_double_sided(inputs_.double_sided); base->set_draws_content(draws_content_); - base->set_hide_layer_and_subtree(hide_layer_and_subtree_); + base->set_hide_layer_and_subtree(inputs_.hide_layer_and_subtree); base->set_subtree_property_changed(subtree_property_changed_); base->set_layer_property_changed(layer_property_changed_); // TODO(nyquist): Add support for serializing FilterOperations for // |filters_| and |background_filters_|. See crbug.com/541321. - base->set_masks_to_bounds(masks_to_bounds_); - base->set_main_thread_scrolling_reasons(main_thread_scrolling_reasons_); - RegionToProto(non_fast_scrollable_region_, + base->set_masks_to_bounds(inputs_.masks_to_bounds); + base->set_main_thread_scrolling_reasons( + inputs_.main_thread_scrolling_reasons); + RegionToProto(inputs_.non_fast_scrollable_region, base->mutable_non_fast_scrollable_region()); - RegionToProto(touch_event_handler_region_, + RegionToProto(inputs_.touch_event_handler_region, base->mutable_touch_event_handler_region()); - base->set_contents_opaque(contents_opaque_); - base->set_opacity(opacity_); - base->set_blend_mode(SkXfermodeModeToProto(blend_mode_)); - base->set_is_root_for_isolated_group(is_root_for_isolated_group_); - PointFToProto(position_, base->mutable_position()); + base->set_contents_opaque(inputs_.contents_opaque); + base->set_opacity(inputs_.opacity); + base->set_blend_mode(SkXfermodeModeToProto(inputs_.blend_mode)); + base->set_is_root_for_isolated_group(inputs_.is_root_for_isolated_group); + PointFToProto(inputs_.position, base->mutable_position()); base->set_is_container_for_fixed_position_layers( - is_container_for_fixed_position_layers_); - position_constraint_.ToProtobuf(base->mutable_position_constraint()); - base->set_should_flatten_transform(should_flatten_transform_); + inputs_.is_container_for_fixed_position_layers); + inputs_.position_constraint.ToProtobuf(base->mutable_position_constraint()); + base->set_should_flatten_transform(inputs_.should_flatten_transform); base->set_should_flatten_transform_from_property_tree( should_flatten_transform_from_property_tree_); base->set_draw_blend_mode(SkXfermodeModeToProto(draw_blend_mode_)); - base->set_use_parent_backface_visibility(use_parent_backface_visibility_); - TransformToProto(transform_, base->mutable_transform()); - base->set_sorting_context_id(sorting_context_id_); + base->set_use_parent_backface_visibility( + inputs_.use_parent_backface_visibility); + TransformToProto(inputs_.transform, base->mutable_transform()); + base->set_sorting_context_id(inputs_.sorting_context_id); base->set_num_descendants_that_draw_content( num_descendants_that_draw_content_); - base->set_scroll_clip_layer_id(scroll_clip_layer_id_); - base->set_user_scrollable_horizontal(user_scrollable_horizontal_); - base->set_user_scrollable_vertical(user_scrollable_vertical_); + base->set_scroll_clip_layer_id(inputs_.scroll_clip_layer_id); + base->set_user_scrollable_horizontal(inputs_.user_scrollable_horizontal); + base->set_user_scrollable_vertical(inputs_.user_scrollable_vertical); - int scroll_parent_id = scroll_parent_ ? scroll_parent_->id() : INVALID_ID; + int scroll_parent_id = + inputs_.scroll_parent ? inputs_.scroll_parent->id() : INVALID_ID; base->set_scroll_parent_id(scroll_parent_id); if (scroll_children_) { @@ -1432,7 +1441,8 @@ base->add_scroll_children_ids(child->id()); } - int clip_parent_id = clip_parent_ ? clip_parent_->id() : INVALID_ID; + int clip_parent_id = + inputs_.clip_parent ? inputs_.clip_parent->id() : INVALID_ID; base->set_clip_parent_id(clip_parent_id); if (clip_children_) { @@ -1440,19 +1450,20 @@ base->add_clip_children_ids(child->id()); } - ScrollOffsetToProto(scroll_offset_, base->mutable_scroll_offset()); + ScrollOffsetToProto(inputs_.scroll_offset, base->mutable_scroll_offset()); // TODO(nyquist): Figure out what to do with CopyRequests. // See crbug.com/570374. - RectToProto(update_rect_, base->mutable_update_rect()); + RectToProto(inputs_.update_rect, base->mutable_update_rect()); // TODO(nyquist): Figure out what to do with ElementAnimations. // See crbug.com/570376. - update_rect_ = gfx::Rect(); + inputs_.update_rect = gfx::Rect(); - base->set_has_will_change_transform_hint(has_will_change_transform_hint_); + base->set_has_will_change_transform_hint( + inputs_.has_will_change_transform_hint); } void Layer::FromLayerSpecificPropertiesProto( @@ -1461,10 +1472,10 @@ DCHECK(layer_tree_host_); const proto::BaseLayerProperties& base = proto.base(); - transform_origin_ = ProtoToPoint3F(base.transform_origin()); - background_color_ = base.background_color(); + inputs_.transform_origin = ProtoToPoint3F(base.transform_origin()); + inputs_.background_color = base.background_color(); safe_opaque_background_color_ = base.safe_opaque_background_color(); - bounds_ = ProtoToSize(base.bounds()); + inputs_.bounds = ProtoToSize(base.bounds()); transform_tree_index_ = base.transform_free_index(); effect_tree_index_ = base.effect_tree_index(); @@ -1472,41 +1483,43 @@ scroll_tree_index_ = base.scroll_tree_index(); offset_to_transform_parent_ = ProtoToVector2dF(base.offset_to_transform_parent()); - double_sided_ = base.double_sided(); + inputs_.double_sided = base.double_sided(); draws_content_ = base.draws_content(); - hide_layer_and_subtree_ = base.hide_layer_and_subtree(); + inputs_.hide_layer_and_subtree = base.hide_layer_and_subtree(); subtree_property_changed_ = base.subtree_property_changed(); layer_property_changed_ = base.layer_property_changed(); - masks_to_bounds_ = base.masks_to_bounds(); - main_thread_scrolling_reasons_ = base.main_thread_scrolling_reasons(); - non_fast_scrollable_region_ = + inputs_.masks_to_bounds = base.masks_to_bounds(); + inputs_.main_thread_scrolling_reasons = base.main_thread_scrolling_reasons(); + inputs_.non_fast_scrollable_region = RegionFromProto(base.non_fast_scrollable_region()); - touch_event_handler_region_ = + inputs_.touch_event_handler_region = RegionFromProto(base.touch_event_handler_region()); - contents_opaque_ = base.contents_opaque(); - opacity_ = base.opacity(); - blend_mode_ = SkXfermodeModeFromProto(base.blend_mode()); - is_root_for_isolated_group_ = base.is_root_for_isolated_group(); - position_ = ProtoToPointF(base.position()); - is_container_for_fixed_position_layers_ = + inputs_.contents_opaque = base.contents_opaque(); + inputs_.opacity = base.opacity(); + inputs_.blend_mode = SkXfermodeModeFromProto(base.blend_mode()); + inputs_.is_root_for_isolated_group = base.is_root_for_isolated_group(); + inputs_.position = ProtoToPointF(base.position()); + inputs_.is_container_for_fixed_position_layers = base.is_container_for_fixed_position_layers(); - position_constraint_.FromProtobuf(base.position_constraint()); - should_flatten_transform_ = base.should_flatten_transform(); + inputs_.position_constraint.FromProtobuf(base.position_constraint()); + inputs_.should_flatten_transform = base.should_flatten_transform(); should_flatten_transform_from_property_tree_ = base.should_flatten_transform_from_property_tree(); draw_blend_mode_ = SkXfermodeModeFromProto(base.draw_blend_mode()); - use_parent_backface_visibility_ = base.use_parent_backface_visibility(); - transform_ = ProtoToTransform(base.transform()); - sorting_context_id_ = base.sorting_context_id(); + inputs_.use_parent_backface_visibility = + base.use_parent_backface_visibility(); + inputs_.transform = ProtoToTransform(base.transform()); + inputs_.sorting_context_id = base.sorting_context_id(); num_descendants_that_draw_content_ = base.num_descendants_that_draw_content(); - scroll_clip_layer_id_ = base.scroll_clip_layer_id(); - user_scrollable_horizontal_ = base.user_scrollable_horizontal(); - user_scrollable_vertical_ = base.user_scrollable_vertical(); + inputs_.scroll_clip_layer_id = base.scroll_clip_layer_id(); + inputs_.user_scrollable_horizontal = base.user_scrollable_horizontal(); + inputs_.user_scrollable_vertical = base.user_scrollable_vertical(); - scroll_parent_ = base.scroll_parent_id() == INVALID_ID - ? nullptr - : layer_tree_host_->LayerById(base.scroll_parent_id()); + inputs_.scroll_parent = + base.scroll_parent_id() == INVALID_ID + ? nullptr + : layer_tree_host_->LayerById(base.scroll_parent_id()); // If there have been scroll children entries in previous deserializations, // clear out the set. If there have been none, initialize the set of children. @@ -1523,9 +1536,10 @@ scroll_children_->insert(child.get()); } - clip_parent_ = base.clip_parent_id() == INVALID_ID - ? nullptr - : layer_tree_host_->LayerById(base.clip_parent_id()); + inputs_.clip_parent = + base.clip_parent_id() == INVALID_ID + ? nullptr + : layer_tree_host_->LayerById(base.clip_parent_id()); // If there have been clip children entries in previous deserializations, // clear out the set. If there have been none, initialize the set of children. @@ -1542,15 +1556,16 @@ clip_children_->insert(child.get()); } - scroll_offset_ = ProtoToScrollOffset(base.scroll_offset()); + inputs_.scroll_offset = ProtoToScrollOffset(base.scroll_offset()); - update_rect_.Union(ProtoToRect(base.update_rect())); + inputs_.update_rect.Union(ProtoToRect(base.update_rect())); - has_will_change_transform_hint_ = base.has_will_change_transform_hint(); + inputs_.has_will_change_transform_hint = + base.has_will_change_transform_hint(); } std::unique_ptr<LayerImpl> Layer::CreateLayerImpl(LayerTreeImpl* tree_impl) { - return LayerImpl::Create(tree_impl, layer_id_); + return LayerImpl::Create(tree_impl, inputs_.layer_id); } bool Layer::DrawsContent() const { @@ -1558,12 +1573,12 @@ } bool Layer::HasDrawableContent() const { - return is_drawable_; + return inputs_.is_drawable; } void Layer::UpdateDrawsContent(bool has_drawable_content) { bool draws_content = has_drawable_content; - DCHECK(is_drawable_ || !has_drawable_content); + DCHECK(inputs_.is_drawable || !has_drawable_content); if (draws_content == draws_content_) return; @@ -1583,7 +1598,7 @@ // TODO(reveman): Save all layer properties that we depend on not // changing until PushProperties() has been called. crbug.com/231016 - paint_properties_.bounds = bounds_; + paint_properties_.bounds = inputs_.bounds; paint_properties_.source_frame_number = layer_tree_host_->source_frame_number(); } @@ -1602,8 +1617,8 @@ std::unique_ptr<base::trace_event::ConvertableToTraceFormat> Layer::TakeDebugInfo() { - if (client_) - return client_->TakeDebugInfo(this); + if (inputs_.client) + return inputs_.client->TakeDebugInfo(this); else return nullptr; } @@ -1631,16 +1646,16 @@ // is no need to request a commit to push this value over, so the value is // set directly rather than by calling Set<Property>. void Layer::OnFilterAnimated(const FilterOperations& filters) { - filters_ = filters; + inputs_.filters = filters; } void Layer::OnOpacityAnimated(float opacity) { DCHECK_GE(opacity, 0.f); DCHECK_LE(opacity, 1.f); - if (opacity_ == opacity) + if (inputs_.opacity == opacity) return; - opacity_ = opacity; + inputs_.opacity = opacity; // Changing the opacity may make a previously hidden layer visible, so a new // recording may be needed. SetNeedsUpdate(); @@ -1651,16 +1666,16 @@ DCHECK_EQ(effect_tree_index(), property_trees->effect_id_to_index_map[id()]); EffectNode* node = property_trees->effect_tree.Node(effect_tree_index()); - node->data.opacity = opacity; + node->opacity = opacity; property_trees->effect_tree.set_needs_update(true); } } } void Layer::OnTransformAnimated(const gfx::Transform& transform) { - if (transform_ == transform) + if (inputs_.transform == transform) return; - transform_ = transform; + inputs_.transform = transform; // Changing the transform may change the visible part of this layer, so a new // recording may be needed. SetNeedsUpdate(); @@ -1672,9 +1687,9 @@ property_trees->transform_id_to_index_map[id()]); TransformNode* node = property_trees->transform_tree.Node(transform_tree_index()); - node->data.local = transform; - node->data.needs_local_transform_update = true; - node->data.has_potential_animation = true; + node->local = transform; + node->needs_local_transform_update = true; + node->has_potential_animation = true; property_trees->transform_tree.set_needs_update(true); } } @@ -1697,7 +1712,7 @@ property_trees->transform_id_to_index_map[id()]); TransformNode* node = property_trees->transform_tree.Node(transform_tree_index()); - node->data.is_currently_animating = is_currently_animating; + node->is_currently_animating = is_currently_animating; } void Layer::OnTransformIsPotentiallyAnimatingChanged( @@ -1713,11 +1728,11 @@ TransformNode* node = property_trees->transform_tree.Node(transform_tree_index()); - node->data.has_potential_animation = has_potential_animation; + node->has_potential_animation = has_potential_animation; if (has_potential_animation) { - node->data.has_only_translation_animations = HasOnlyTranslationTransforms(); + node->has_only_translation_animations = HasOnlyTranslationTransforms(); } else { - node->data.has_only_translation_animations = true; + node->has_only_translation_animations = true; } property_trees->transform_tree.set_needs_update(true); } @@ -1729,7 +1744,7 @@ return; DCHECK_EQ(effect_tree_index(), property_trees->effect_id_to_index_map[id()]); EffectNode* node = property_trees->effect_tree.Node(effect_tree_index()); - node->data.is_currently_animating_opacity = is_currently_animating; + node->is_currently_animating_opacity = is_currently_animating; } void Layer::OnOpacityIsPotentiallyAnimatingChanged( @@ -1740,7 +1755,7 @@ return; DCHECK_EQ(effect_tree_index(), property_trees->effect_id_to_index_map[id()]); EffectNode* node = property_trees->effect_tree.Node(effect_tree_index()); - node->data.has_potential_opacity_animation = + node->has_potential_opacity_animation = has_potential_animation || OpacityCanAnimateOnImplThread(); property_trees->effect_tree.set_needs_update(true); } @@ -1751,9 +1766,9 @@ } void Layer::SetHasWillChangeTransformHint(bool has_will_change) { - if (has_will_change_transform_hint_ == has_will_change) + if (inputs_.has_will_change_transform_hint == has_will_change) return; - has_will_change_transform_hint_ = has_will_change; + inputs_.has_will_change_transform_hint = has_will_change; SetNeedsCommit(); } @@ -1804,21 +1819,21 @@ void Layer::SetElementId(ElementId id) { DCHECK(IsPropertyChangeAllowed()); - if (element_id_ == id) + if (inputs_.element_id == id) return; TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("compositor-worker"), "Layer::SetElementId", "element", id.AsValue().release()); - if (element_id_ && layer_tree_host()) { + if (inputs_.element_id && layer_tree_host()) { layer_tree_host()->animation_host()->UnregisterElement( - element_id_, ElementListType::ACTIVE); + inputs_.element_id, ElementListType::ACTIVE); layer_tree_host()->RemoveFromElementMap(this); } - element_id_ = id; + inputs_.element_id = id; - if (element_id_ && layer_tree_host()) { + if (inputs_.element_id && layer_tree_host()) { layer_tree_host()->animation_host()->RegisterElement( - element_id_, ElementListType::ACTIVE); + inputs_.element_id, ElementListType::ACTIVE); layer_tree_host()->AddToElementMap(this); } @@ -1827,11 +1842,11 @@ void Layer::SetMutableProperties(uint32_t properties) { DCHECK(IsPropertyChangeAllowed()); - if (mutable_properties_ == properties) + if (inputs_.mutable_properties == properties) return; TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("compositor-worker"), "Layer::SetMutableProperties", "properties", properties); - mutable_properties_ = properties; + inputs_.mutable_properties = properties; SetNeedsCommit(); } @@ -1847,7 +1862,7 @@ return layer_tree_host() ->property_trees() ->effect_tree.Node(effect_tree_index()) - ->data.num_copy_requests_in_subtree; + ->num_copy_requests_in_subtree; } gfx::Transform Layer::screen_space_transform() const {
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 7718e00f..addb510 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -81,7 +81,7 @@ static scoped_refptr<Layer> Create(); - int id() const { return layer_id_; } + int id() const { return inputs_.layer_id; } Layer* RootLayer(); Layer* parent() { return parent_; } @@ -94,8 +94,8 @@ void SetChildren(const LayerList& children); bool HasAncestor(const Layer* ancestor) const; - const LayerList& children() const { return children_; } - Layer* child_at(size_t index) { return children_[index].get(); } + const LayerList& children() const { return inputs_.children; } + Layer* child_at(size_t index) { return inputs_.children[index].get(); } // This requests the layer and its subtree be rendered and given to the // callback. If the copy is unable to be produced (the layer is destroyed @@ -103,15 +103,13 @@ // request's source property is set, any prior uncommitted requests having the // same source will be aborted. void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> request); - bool HasCopyRequest() const { - return !copy_requests_.empty(); - } + bool HasCopyRequest() const { return !inputs_.copy_requests.empty(); } void TakeCopyRequests( std::vector<std::unique_ptr<CopyOutputRequest>>* requests); virtual void SetBackgroundColor(SkColor background_color); - SkColor background_color() const { return background_color_; } + SkColor background_color() const { return inputs_.background_color; } void SetSafeOpaqueBackgroundColor(SkColor background_color); // If contents_opaque(), return an opaque color else return a // non-opaque color. Tries to return background_color(), if possible. @@ -120,20 +118,20 @@ // A layer's bounds are in logical, non-page-scaled pixels (however, the // root layer's bounds are in physical pixels). void SetBounds(const gfx::Size& bounds); - gfx::Size bounds() const { return bounds_; } + gfx::Size bounds() const { return inputs_.bounds; } void SetMasksToBounds(bool masks_to_bounds); - bool masks_to_bounds() const { return masks_to_bounds_; } + bool masks_to_bounds() const { return inputs_.masks_to_bounds; } void SetMaskLayer(Layer* mask_layer); - Layer* mask_layer() { return mask_layer_.get(); } - const Layer* mask_layer() const { return mask_layer_.get(); } + Layer* mask_layer() { return inputs_.mask_layer.get(); } + const Layer* mask_layer() const { return inputs_.mask_layer.get(); } virtual void SetNeedsDisplayRect(const gfx::Rect& dirty_rect); void SetNeedsDisplay() { SetNeedsDisplayRect(gfx::Rect(bounds())); } virtual void SetOpacity(float opacity); - float opacity() const { return opacity_; } + float opacity() const { return inputs_.opacity; } float EffectiveOpacity() const; bool OpacityIsAnimating() const; bool HasPotentiallyRunningOpacityAnimation() const; @@ -142,7 +140,7 @@ virtual bool AlwaysUseActiveTreeOpacity() const; void SetBlendMode(SkXfermode::Mode blend_mode); - SkXfermode::Mode blend_mode() const { return blend_mode_; } + SkXfermode::Mode blend_mode() const { return inputs_.blend_mode; } void set_draw_blend_mode(SkXfermode::Mode blend_mode) { if (draw_blend_mode_ == blend_mode) @@ -153,7 +151,7 @@ SkXfermode::Mode draw_blend_mode() const { return draw_blend_mode_; } bool uses_default_blend_mode() const { - return blend_mode_ == SkXfermode::kSrcOver_Mode; + return inputs_.blend_mode == SkXfermode::kSrcOver_Mode; } // A layer is root for an isolated group when it and all its descendants are @@ -162,11 +160,11 @@ // layers within the group to blend with layers outside this group. void SetIsRootForIsolatedGroup(bool root); bool is_root_for_isolated_group() const { - return is_root_for_isolated_group_; + return inputs_.is_root_for_isolated_group; } void SetFilters(const FilterOperations& filters); - const FilterOperations& filters() const { return filters_; } + const FilterOperations& filters() const { return inputs_.filters; } bool FilterIsAnimating() const; bool HasPotentiallyRunningFilterAnimation() const; @@ -175,14 +173,14 @@ // through the WebLayer interface, and are not exposed to HTML. void SetBackgroundFilters(const FilterOperations& filters); const FilterOperations& background_filters() const { - return background_filters_; + return inputs_.background_filters; } virtual void SetContentsOpaque(bool opaque); - bool contents_opaque() const { return contents_opaque_; } + bool contents_opaque() const { return inputs_.contents_opaque; } void SetPosition(const gfx::PointF& position); - gfx::PointF position() const { return position_; } + gfx::PointF position() const { return inputs_.position; } // A layer that is a container for fixed position layers cannot be both // scrollable and have a non-identity transform. @@ -195,11 +193,11 @@ void SetPositionConstraint(const LayerPositionConstraint& constraint); const LayerPositionConstraint& position_constraint() const { - return position_constraint_; + return inputs_.position_constraint; } void SetTransform(const gfx::Transform& transform); - const gfx::Transform& transform() const { return transform_; } + const gfx::Transform& transform() const { return inputs_.transform; } bool TransformIsAnimating() const; bool HasPotentiallyRunningTransformAnimation() const; bool HasOnlyTranslationTransforms() const; @@ -209,7 +207,7 @@ bool AnimationStartScale(float* start_scale) const; void SetTransformOrigin(const gfx::Point3F&); - gfx::Point3F transform_origin() const { return transform_origin_; } + gfx::Point3F transform_origin() const { return inputs_.transform_origin; } bool HasAnyAnimationTargetingProperty(TargetProperty::Type property) const; @@ -217,8 +215,8 @@ void SetScrollParent(Layer* parent); - Layer* scroll_parent() { return scroll_parent_; } - const Layer* scroll_parent() const { return scroll_parent_; } + Layer* scroll_parent() { return inputs_.scroll_parent; } + const Layer* scroll_parent() const { return inputs_.scroll_parent; } void AddScrollChild(Layer* child); void RemoveScrollChild(Layer* child); @@ -230,10 +228,8 @@ void SetClipParent(Layer* ancestor); - Layer* clip_parent() { return clip_parent_; } - const Layer* clip_parent() const { - return clip_parent_; - } + Layer* clip_parent() { return inputs_.clip_parent; } + const Layer* clip_parent() const { return inputs_.clip_parent; } void AddClipChild(Layer* child); void RemoveClipChild(Layer* child); @@ -255,41 +251,43 @@ void SetScrollOffset(const gfx::ScrollOffset& scroll_offset); - gfx::ScrollOffset scroll_offset() const { return scroll_offset_; } + gfx::ScrollOffset scroll_offset() const { return inputs_.scroll_offset; } void SetScrollOffsetFromImplSide(const gfx::ScrollOffset& scroll_offset); void SetScrollClipLayerId(int clip_layer_id); - bool scrollable() const { return scroll_clip_layer_id_ != INVALID_ID; } + bool scrollable() const { return inputs_.scroll_clip_layer_id != INVALID_ID; } Layer* scroll_clip_layer() const; void SetUserScrollable(bool horizontal, bool vertical); bool user_scrollable_horizontal() const { - return user_scrollable_horizontal_; + return inputs_.user_scrollable_horizontal; } - bool user_scrollable_vertical() const { return user_scrollable_vertical_; } + bool user_scrollable_vertical() const { + return inputs_.user_scrollable_vertical; + } void AddMainThreadScrollingReasons(uint32_t main_thread_scrolling_reasons); void ClearMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons_to_clear); uint32_t main_thread_scrolling_reasons() const { - return main_thread_scrolling_reasons_; + return inputs_.main_thread_scrolling_reasons; } bool should_scroll_on_main_thread() const { - return !!main_thread_scrolling_reasons_; + return !!inputs_.main_thread_scrolling_reasons; } void SetNonFastScrollableRegion(const Region& non_fast_scrollable_region); const Region& non_fast_scrollable_region() const { - return non_fast_scrollable_region_; + return inputs_.non_fast_scrollable_region; } void SetTouchEventHandlerRegion(const Region& touch_event_handler_region); const Region& touch_event_handler_region() const { - return touch_event_handler_region_; + return inputs_.touch_event_handler_region; } void set_did_scroll_callback(const base::Closure& callback) { - did_scroll_callback_ = callback; + inputs_.did_scroll_callback = callback; } void SetForceRenderSurfaceForTesting(bool force_render_surface); @@ -297,19 +295,23 @@ return force_render_surface_for_testing_; } - gfx::ScrollOffset CurrentScrollOffset() const { return scroll_offset_; } + gfx::ScrollOffset CurrentScrollOffset() const { + return inputs_.scroll_offset; + } void SetDoubleSided(bool double_sided); - bool double_sided() const { return double_sided_; } + bool double_sided() const { return inputs_.double_sided; } void SetShouldFlattenTransform(bool flatten); - bool should_flatten_transform() const { return should_flatten_transform_; } + bool should_flatten_transform() const { + return inputs_.should_flatten_transform; + } - bool Is3dSorted() const { return sorting_context_id_ != 0; } + bool Is3dSorted() const { return inputs_.sorting_context_id != 0; } void SetUseParentBackfaceVisibility(bool use); bool use_parent_backface_visibility() const { - return use_parent_backface_visibility_; + return inputs_.use_parent_backface_visibility; } void SetUseLocalTransformForBackfaceVisibility(bool use_local); @@ -327,17 +329,18 @@ void SetIsDrawable(bool is_drawable); void SetHideLayerAndSubtree(bool hide); - bool hide_layer_and_subtree() const { return hide_layer_and_subtree_; } + bool hide_layer_and_subtree() const { return inputs_.hide_layer_and_subtree; } void SetReplicaLayer(Layer* layer); - Layer* replica_layer() { return replica_layer_.get(); } - const Layer* replica_layer() const { return replica_layer_.get(); } + Layer* replica_layer() { return inputs_.replica_layer.get(); } + const Layer* replica_layer() const { return inputs_.replica_layer.get(); } - bool has_mask() const { return !!mask_layer_.get(); } - bool has_replica() const { return !!replica_layer_.get(); } + bool has_mask() const { return !!inputs_.mask_layer.get(); } + bool has_replica() const { return !!inputs_.replica_layer.get(); } bool replica_has_mask() const { - return replica_layer_.get() && - (mask_layer_.get() || replica_layer_->mask_layer_.get()); + return inputs_.replica_layer.get() && + (inputs_.mask_layer.get() || + inputs_.replica_layer->inputs_.mask_layer.get()); } int NumDescendantsThatDrawContent() const; @@ -358,7 +361,7 @@ virtual std::unique_ptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(); - void SetLayerClient(LayerClient* client) { client_ = client; } + void SetLayerClient(LayerClient* client) { inputs_.client = client; } virtual void PushPropertiesTo(LayerImpl* layer); @@ -416,8 +419,8 @@ // Constructs a LayerImpl of the correct runtime type for this Layer type. virtual std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl); - bool NeedsDisplayForTesting() const { return !update_rect_.IsEmpty(); } - void ResetNeedsDisplayForTesting() { update_rect_ = gfx::Rect(); } + bool NeedsDisplayForTesting() const { return !inputs_.update_rect.IsEmpty(); } + void ResetNeedsDisplayForTesting() { inputs_.update_rect = gfx::Rect(); } RenderingStatsInstrumentation* rendering_stats_instrumentation() const; @@ -431,7 +434,7 @@ virtual void RunMicroBenchmark(MicroBenchmark* benchmark); void Set3dSortingContextId(int id); - int sorting_context_id() const { return sorting_context_id_; } + int sorting_context_id() const { return inputs_.sorting_context_id; } void set_property_tree_sequence_number(int sequence_number) { property_tree_sequence_number_ = sequence_number; @@ -493,26 +496,16 @@ int num_copy_requests_in_target_subtree(); void SetElementId(ElementId id); - ElementId element_id() const { return element_id_; } + ElementId element_id() const { return inputs_.element_id; } void SetMutableProperties(uint32_t properties); - uint32_t mutable_properties() const { return mutable_properties_; } + uint32_t mutable_properties() const { return inputs_.mutable_properties; } - // Interactions with attached animations. - gfx::ScrollOffset ScrollOffsetForAnimation() const; - void OnFilterAnimated(const FilterOperations& filters); - void OnOpacityAnimated(float opacity); - void OnTransformAnimated(const gfx::Transform& transform); - void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset); - void OnTransformIsCurrentlyAnimatingChanged(bool is_animating); - void OnTransformIsPotentiallyAnimatingChanged(bool is_animating); - void OnOpacityIsCurrentlyAnimatingChanged(bool is_currently_animating); - void OnOpacityIsPotentiallyAnimatingChanged(bool has_potential_animation); bool HasActiveAnimationForTesting() const; void SetHasWillChangeTransformHint(bool has_will_change); bool has_will_change_transform_hint() const { - return has_will_change_transform_hint_; + return inputs_.has_will_change_transform_hint; } protected: @@ -564,30 +557,29 @@ virtual void FromLayerSpecificPropertiesProto( const proto::LayerProperties& proto); - // The update rect is the region of the compositor resource that was - // actually updated by the compositor. For layers that may do updating - // outside the compositor's control (i.e. plugin layers), this information - // is not available and the update rect will remain empty. - // Note this rect is in layer space (not content space). - gfx::Rect update_rect_; - - scoped_refptr<Layer> mask_layer_; - - int layer_id_; + gfx::Rect& update_rect() { return inputs_.update_rect; } // When true, the layer is about to perform an update. Any commit requests // will be handled implicitly after the update completes. bool ignore_set_needs_commit_; - // Layers that share a sorting context id will be sorted together in 3d - // space. 0 is a special value that means this layer will not be sorted and - // will be drawn in paint order. - int sorting_context_id_; - private: friend class base::RefCounted<Layer>; friend class LayerSerializationTest; friend class LayerTreeHostCommon; + friend class LayerTreeHost; + friend class LayerInternalsForTest; + + // Interactions with attached animations. + gfx::ScrollOffset ScrollOffsetForAnimation() const; + void OnFilterAnimated(const FilterOperations& filters); + void OnOpacityAnimated(float opacity); + void OnTransformAnimated(const gfx::Transform& transform); + void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset); + void OnTransformIsCurrentlyAnimatingChanged(bool is_animating); + void OnTransformIsPotentiallyAnimatingChanged(bool is_animating); + void OnOpacityIsCurrentlyAnimatingChanged(bool is_currently_animating); + void OnOpacityIsPotentiallyAnimatingChanged(bool has_potential_animation); void SetParent(Layer* layer); bool DescendantIsFixedToContainerLayer() const; @@ -607,7 +599,95 @@ // indices becomes invalid. void InvalidatePropertyTreesIndices(); - LayerList children_; + // Encapsulates all data, callbacks or interfaces received from the embedder. + // TODO(khushalsagar): This is only valid when PropertyTrees are built + // internally in cc. Update this for the SPv2 path where blink generates + // PropertyTrees. + struct Inputs { + Inputs(); + ~Inputs(); + + int layer_id; + + LayerList children; + + // The update rect is the region of the compositor resource that was + // actually updated by the compositor. For layers that may do updating + // outside the compositor's control (i.e. plugin layers), this information + // is not available and the update rect will remain empty. + // Note this rect is in layer space (not content space). + gfx::Rect update_rect; + + gfx::Size bounds; + bool masks_to_bounds; + + scoped_refptr<Layer> mask_layer; + + // Replica layer used for reflections. + scoped_refptr<Layer> replica_layer; + + float opacity; + SkXfermode::Mode blend_mode; + + bool is_root_for_isolated_group : 1; + + bool contents_opaque : 1; + + gfx::PointF position; + gfx::Transform transform; + gfx::Point3F transform_origin; + + bool is_drawable : 1; + + bool double_sided : 1; + bool should_flatten_transform : 1; + + // Layers that share a sorting context id will be sorted together in 3d + // space. 0 is a special value that means this layer will not be sorted + // and will be drawn in paint order. + int sorting_context_id; + + bool use_parent_backface_visibility : 1; + + SkColor background_color; + + FilterOperations filters; + FilterOperations background_filters; + + gfx::ScrollOffset scroll_offset; + + // This variable indicates which ancestor layer (if any) whose size, + // transformed relative to this layer, defines the maximum scroll offset + // for this layer. + int scroll_clip_layer_id; + bool user_scrollable_horizontal : 1; + bool user_scrollable_vertical : 1; + + uint32_t main_thread_scrolling_reasons; + Region non_fast_scrollable_region; + + Region touch_event_handler_region; + + bool is_container_for_fixed_position_layers : 1; + LayerPositionConstraint position_constraint; + + ElementId element_id; + + uint32_t mutable_properties; + + Layer* scroll_parent; + Layer* clip_parent; + + bool has_will_change_transform_hint : 1; + + bool hide_layer_and_subtree : 1; + + // The following elements can not and are not serialized. + LayerClient* client; + base::Closure did_scroll_callback; + std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests; + }; + Layer* parent_; // Layer instances have a weak pointer to their LayerTreeHost. @@ -615,74 +695,30 @@ // updated via SetLayerTreeHost() if a layer moves between trees. LayerTreeHost* layer_tree_host_; - // Layer properties. - gfx::Size bounds_; + Inputs inputs_; - gfx::ScrollOffset scroll_offset_; - // This variable indicates which ancestor layer (if any) whose size, - // transformed relative to this layer, defines the maximum scroll offset for - // this layer. - int scroll_clip_layer_id_; int num_descendants_that_draw_content_; int transform_tree_index_; int effect_tree_index_; int clip_tree_index_; int scroll_tree_index_; int property_tree_sequence_number_; - ElementId element_id_; - uint32_t mutable_properties_; gfx::Vector2dF offset_to_transform_parent_; - uint32_t main_thread_scrolling_reasons_; bool should_flatten_transform_from_property_tree_ : 1; - bool user_scrollable_horizontal_ : 1; - bool user_scrollable_vertical_ : 1; - bool is_root_for_isolated_group_ : 1; - bool is_container_for_fixed_position_layers_ : 1; - bool is_drawable_ : 1; bool draws_content_ : 1; - bool hide_layer_and_subtree_ : 1; - bool masks_to_bounds_ : 1; - bool contents_opaque_ : 1; - bool double_sided_ : 1; - bool should_flatten_transform_ : 1; - bool use_parent_backface_visibility_ : 1; bool use_local_transform_for_backface_visibility_ : 1; bool should_check_backface_visibility_ : 1; bool force_render_surface_for_testing_ : 1; bool subtree_property_changed_ : 1; bool layer_property_changed_ : 1; - bool has_will_change_transform_hint_ : 1; - Region non_fast_scrollable_region_; - Region touch_event_handler_region_; - gfx::PointF position_; - SkColor background_color_; SkColor safe_opaque_background_color_; - float opacity_; - SkXfermode::Mode blend_mode_; // draw_blend_mode may be different than blend_mode_, // when a RenderSurface re-parents the layer's blend_mode. SkXfermode::Mode draw_blend_mode_; - FilterOperations filters_; - FilterOperations background_filters_; - LayerPositionConstraint position_constraint_; - Layer* scroll_parent_; std::unique_ptr<std::set<Layer*>> scroll_children_; - Layer* clip_parent_; std::unique_ptr<std::set<Layer*>> clip_children_; - gfx::Transform transform_; - gfx::Point3F transform_origin_; - - // Replica layer used for reflections. - scoped_refptr<Layer> replica_layer_; - - LayerClient* client_; - - std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests_; - - base::Closure did_scroll_callback_; - PaintProperties paint_properties_; // These all act like draw properties, so don't need push properties.
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 9a1b979..163ee3a5 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -30,11 +30,15 @@ #include "cc/output/copy_output_request.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/render_pass.h" +#include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/layer_tree_settings.h" #include "cc/trees/proxy.h" +#include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/quad_f.h" @@ -378,7 +382,7 @@ TransformTree& transform_tree = layer_tree_impl()->property_trees()->transform_tree; return transform_tree.Node(transform_tree_index()) - ->data.in_subtree_of_page_scale_layer; + ->in_subtree_of_page_scale_layer; } gfx::Vector2dF LayerImpl::FixedContainerSizeDelta() const { @@ -444,14 +448,14 @@ TransformNode* transform_node = layer_tree_impl()->property_trees()->transform_tree.Node( transform_tree_index()); - if (transform_node && transform_node->data.transform_changed) + if (transform_node && transform_node->transform_changed) return true; if (effect_tree_index() == -1) return false; EffectNode* effect_node = layer_tree_impl()->property_trees()->effect_tree.Node( effect_tree_index()); - if (effect_node && effect_node->data.effect_changed) + if (effect_node && effect_node->effect_changed) return true; return false; } @@ -490,7 +494,7 @@ return layer_tree_impl() ->property_trees() ->effect_tree.Node(effect_tree_index()) - ->data.num_copy_requests_in_subtree; + ->num_copy_requests_in_subtree; } void LayerImpl::UpdatePropertyTreeTransform() { @@ -505,10 +509,10 @@ // thread. TransformNode* node = property_trees->transform_tree.Node( property_trees->transform_id_to_index_map[id()]); - if (node->data.local != transform_) { - node->data.local = transform_; - node->data.needs_local_transform_update = true; - node->data.transform_changed = true; + if (node->local != transform_) { + node->local = transform_; + node->needs_local_transform_update = true; + node->transform_changed = true; property_trees->changed = true; property_trees->transform_tree.set_needs_update(true); // TODO(ajuma): The current criteria for creating clip nodes means that @@ -536,13 +540,12 @@ // activation (and, in that case, the LayerImpl will no longer own a // TransformNode, unless it has non-animation-related reasons for owning a // node). - if (node->data.has_potential_animation != is_animated) { - node->data.has_potential_animation = is_animated; + if (node->has_potential_animation != is_animated) { + node->has_potential_animation = is_animated; if (is_animated) { - node->data.has_only_translation_animations = - HasOnlyTranslationTransforms(); + node->has_only_translation_animations = HasOnlyTranslationTransforms(); } else { - node->data.has_only_translation_animations = true; + node->has_only_translation_animations = true; } property_trees->transform_tree.set_needs_update(true); @@ -561,10 +564,10 @@ // started, but might have finished since then on the compositor thread. EffectNode* node = property_trees->effect_tree.Node( property_trees->effect_id_to_index_map[id()]); - if (node->data.opacity == opacity) + if (node->opacity == opacity) return; - node->data.opacity = opacity; - node->data.effect_changed = true; + node->opacity = opacity; + node->effect_changed = true; property_trees->changed = true; property_trees->effect_tree.set_needs_update(true); } @@ -593,7 +596,7 @@ EffectNode* node = effect_tree.Node(effect_tree_index_); DCHECK(layer_tree_impl()->property_trees()->IsInIdToIndexMap( PropertyTrees::TreeType::EFFECT, id())); - node->data.effect_changed = true; + node->effect_changed = true; layer_tree_impl()->property_trees()->changed = true; effect_tree.set_needs_update(true); } @@ -639,7 +642,7 @@ return; TransformNode* node = property_trees->transform_tree.Node( property_trees->transform_id_to_index_map[id()]); - node->data.is_currently_animating = is_currently_animating; + node->is_currently_animating = is_currently_animating; } void LayerImpl::OnTransformIsPotentiallyAnimatingChanged( @@ -657,7 +660,7 @@ EffectNode* node = property_trees->effect_tree.Node( property_trees->effect_id_to_index_map[id()]); - node->data.is_currently_animating_opacity = is_currently_animating; + node->is_currently_animating_opacity = is_currently_animating; } void LayerImpl::OnOpacityIsPotentiallyAnimatingChanged( @@ -668,7 +671,7 @@ return; EffectNode* node = property_trees->effect_tree.Node( property_trees->effect_id_to_index_map[id()]); - node->data.has_potential_opacity_animation = has_potential_animation; + node->has_potential_opacity_animation = has_potential_animation; property_trees->effect_tree.set_needs_update(true); } @@ -721,8 +724,8 @@ if (clip_node) { DCHECK(property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::CLIP, id())); - clip_node->data.clip = gfx::RectF( - gfx::PointF() + offset_to_transform_parent(), gfx::SizeF(bounds())); + clip_node->clip = gfx::RectF(gfx::PointF() + offset_to_transform_parent(), + gfx::SizeF(bounds())); property_trees->clip_tree.set_needs_update(true); } property_trees->full_tree_damaged = true; @@ -791,7 +794,7 @@ return 1.f; EffectNode* node = property_trees->effect_tree.Node( property_trees->effect_id_to_index_map[id()]); - return node->data.opacity; + return node->opacity; } bool LayerImpl::OpacityIsAnimating() const { @@ -924,9 +927,9 @@ layer_tree_impl()->property_trees()->transform_tree; TransformNode* node = transform_tree.Node(transform_tree_index_); gfx::ScrollOffset current_offset = CurrentScrollOffset(); - if (node->data.scroll_offset != current_offset) { - node->data.scroll_offset = current_offset; - node->data.needs_local_transform_update = true; + if (node->scroll_offset != current_offset) { + node->scroll_offset = current_offset; + node->needs_local_transform_update = true; transform_tree.set_needs_update(true); } } @@ -1108,12 +1111,12 @@ if (layer_tree_impl() ->property_trees() ->effect_tree.Node(effect_tree_index()) - ->data.screen_space_opacity != 1.f) + ->screen_space_opacity != 1.f) return false; if (!layer_tree_impl() ->property_trees() ->transform_tree.Node(transform_tree_index()) - ->data.node_and_ancestors_have_only_integer_translation) + ->node_and_ancestors_have_only_integer_translation) return false; if (static_cast<int>(offset_to_transform_parent().x()) != offset_to_transform_parent().x()) @@ -1145,10 +1148,10 @@ EffectTree& effect_tree = layer_tree_impl_->property_trees()->effect_tree; EffectNode* node = effect_tree.Node(effect_tree_index_); - if (node->data.render_surface) - return node->data.render_surface; + if (node->render_surface) + return node->render_surface; else - return effect_tree.Node(node->data.target_id)->data.render_surface; + return effect_tree.Node(node->target_id)->render_surface; } const RenderSurfaceImpl* LayerImpl::render_target() const { @@ -1156,16 +1159,16 @@ layer_tree_impl_->property_trees()->effect_tree; const EffectNode* node = effect_tree.Node(effect_tree_index_); - if (node->data.render_surface) - return node->data.render_surface; + if (node->render_surface) + return node->render_surface; else - return effect_tree.Node(node->data.target_id)->data.render_surface; + return effect_tree.Node(node->target_id)->render_surface; } bool LayerImpl::IsHidden() const { EffectTree& effect_tree = layer_tree_impl_->property_trees()->effect_tree; EffectNode* node = effect_tree.Node(effect_tree_index_); - return node->data.screen_space_opacity == 0.f; + return node->screen_space_opacity == 0.f; } bool LayerImpl::InsideReplica() const { @@ -1175,9 +1178,9 @@ EffectNode* node = effect_tree.Node(effect_tree_index_); while (node->id > 0) { - if (node->data.replica_layer_id != -1) + if (node->replica_layer_id != -1) return true; - node = effect_tree.Node(node->data.target_id); + node = effect_tree.Node(node->target_id); } return false;
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index 6f9dfbf..179e0a5 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc
@@ -24,12 +24,14 @@ #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/layer_internals_for_test.h" #include "cc/test/layer_test_common.h" #include "cc/test/test_gpu_memory_buffer_manager.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/single_thread_proxy.h" +#include "cc/trees/transform_node.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkColor.h" @@ -129,7 +131,7 @@ // The following member is reset during serialization, so store the original // values. - gfx::Rect update_rect = src->update_rect_; + gfx::Rect update_rect = src->inputs_.update_rect; // Serialize |src| to protobuf and read the first entry in the // LayerUpdate. There are no descendants, so the serialization @@ -140,14 +142,14 @@ proto::LayerProperties props = layer_update.layers(0); // The |dest| layer needs to be able to lookup the scroll and clip parents. - if (src->scroll_parent_) - layer_tree_host_->RegisterLayer(src->scroll_parent_); + if (src->inputs_.scroll_parent) + layer_tree_host_->RegisterLayer(src->inputs_.scroll_parent); if (src->scroll_children_) { for (auto* child : *(src->scroll_children_)) layer_tree_host_->RegisterLayer(child); } - if (src->clip_parent_) - layer_tree_host_->RegisterLayer(src->clip_parent_); + if (src->inputs_.clip_parent) + layer_tree_host_->RegisterLayer(src->inputs_.clip_parent); if (src->clip_children_) { for (auto* child : *(src->clip_children_)) layer_tree_host_->RegisterLayer(child); @@ -157,60 +159,67 @@ src->SetLayerTreeHost(nullptr); scoped_refptr<Layer> dest = Layer::Create(); - dest->layer_id_ = src->layer_id_; + dest->inputs_.layer_id = src->inputs_.layer_id; dest->SetLayerTreeHost(layer_tree_host_.get()); dest->FromLayerPropertiesProto(props); // Verify that both layers are equal. - EXPECT_EQ(src->transform_origin_, dest->transform_origin_); - EXPECT_EQ(src->background_color_, dest->background_color_); - EXPECT_EQ(src->bounds_, dest->bounds_); + EXPECT_EQ(src->inputs_.transform_origin, dest->inputs_.transform_origin); + EXPECT_EQ(src->inputs_.background_color, dest->inputs_.background_color); + EXPECT_EQ(src->inputs_.bounds, dest->inputs_.bounds); EXPECT_EQ(src->transform_tree_index_, dest->transform_tree_index_); EXPECT_EQ(src->effect_tree_index_, dest->effect_tree_index_); EXPECT_EQ(src->clip_tree_index_, dest->clip_tree_index_); EXPECT_EQ(src->offset_to_transform_parent_, dest->offset_to_transform_parent_); - EXPECT_EQ(src->double_sided_, dest->double_sided_); + EXPECT_EQ(src->inputs_.double_sided, dest->inputs_.double_sided); EXPECT_EQ(src->draws_content_, dest->draws_content_); - EXPECT_EQ(src->hide_layer_and_subtree_, dest->hide_layer_and_subtree_); - EXPECT_EQ(src->masks_to_bounds_, dest->masks_to_bounds_); - EXPECT_EQ(src->main_thread_scrolling_reasons_, - dest->main_thread_scrolling_reasons_); - EXPECT_EQ(src->non_fast_scrollable_region_, - dest->non_fast_scrollable_region_); - EXPECT_EQ(src->touch_event_handler_region_, - dest->touch_event_handler_region_); - EXPECT_EQ(src->contents_opaque_, dest->contents_opaque_); - EXPECT_EQ(src->opacity_, dest->opacity_); - EXPECT_EQ(src->blend_mode_, dest->blend_mode_); - EXPECT_EQ(src->is_root_for_isolated_group_, - dest->is_root_for_isolated_group_); - EXPECT_EQ(src->position_, dest->position_); - EXPECT_EQ(src->is_container_for_fixed_position_layers_, - dest->is_container_for_fixed_position_layers_); - EXPECT_EQ(src->position_constraint_, dest->position_constraint_); - EXPECT_EQ(src->should_flatten_transform_, dest->should_flatten_transform_); + EXPECT_EQ(src->inputs_.hide_layer_and_subtree, + dest->inputs_.hide_layer_and_subtree); + EXPECT_EQ(src->inputs_.masks_to_bounds, dest->inputs_.masks_to_bounds); + EXPECT_EQ(src->inputs_.main_thread_scrolling_reasons, + dest->inputs_.main_thread_scrolling_reasons); + EXPECT_EQ(src->inputs_.non_fast_scrollable_region, + dest->inputs_.non_fast_scrollable_region); + EXPECT_EQ(src->inputs_.touch_event_handler_region, + dest->inputs_.touch_event_handler_region); + EXPECT_EQ(src->inputs_.contents_opaque, dest->inputs_.contents_opaque); + EXPECT_EQ(src->inputs_.opacity, dest->inputs_.opacity); + EXPECT_EQ(src->inputs_.blend_mode, dest->inputs_.blend_mode); + EXPECT_EQ(src->inputs_.is_root_for_isolated_group, + dest->inputs_.is_root_for_isolated_group); + EXPECT_EQ(src->inputs_.position, dest->inputs_.position); + EXPECT_EQ(src->inputs_.is_container_for_fixed_position_layers, + dest->inputs_.is_container_for_fixed_position_layers); + EXPECT_EQ(src->inputs_.position_constraint, + dest->inputs_.position_constraint); + EXPECT_EQ(src->inputs_.should_flatten_transform, + dest->inputs_.should_flatten_transform); EXPECT_EQ(src->should_flatten_transform_from_property_tree_, dest->should_flatten_transform_from_property_tree_); EXPECT_EQ(src->draw_blend_mode_, dest->draw_blend_mode_); - EXPECT_EQ(src->use_parent_backface_visibility_, - dest->use_parent_backface_visibility_); - EXPECT_EQ(src->transform_, dest->transform_); - EXPECT_EQ(src->sorting_context_id_, dest->sorting_context_id_); + EXPECT_EQ(src->inputs_.use_parent_backface_visibility, + dest->inputs_.use_parent_backface_visibility); + EXPECT_EQ(src->inputs_.transform, dest->inputs_.transform); + EXPECT_EQ(src->inputs_.sorting_context_id, + dest->inputs_.sorting_context_id); EXPECT_EQ(src->num_descendants_that_draw_content_, dest->num_descendants_that_draw_content_); - EXPECT_EQ(src->scroll_clip_layer_id_, dest->scroll_clip_layer_id_); - EXPECT_EQ(src->user_scrollable_horizontal_, - dest->user_scrollable_horizontal_); - EXPECT_EQ(src->user_scrollable_vertical_, dest->user_scrollable_vertical_); - EXPECT_EQ(src->scroll_offset_, dest->scroll_offset_); - EXPECT_EQ(update_rect, dest->update_rect_); + EXPECT_EQ(src->inputs_.scroll_clip_layer_id, + dest->inputs_.scroll_clip_layer_id); + EXPECT_EQ(src->inputs_.user_scrollable_horizontal, + dest->inputs_.user_scrollable_horizontal); + EXPECT_EQ(src->inputs_.user_scrollable_vertical, + dest->inputs_.user_scrollable_vertical); + EXPECT_EQ(src->inputs_.scroll_offset, dest->inputs_.scroll_offset); + EXPECT_EQ(update_rect, dest->inputs_.update_rect); - if (src->scroll_parent_) { - ASSERT_TRUE(dest->scroll_parent_); - EXPECT_EQ(src->scroll_parent_->id(), dest->scroll_parent_->id()); + if (src->inputs_.scroll_parent) { + ASSERT_TRUE(dest->inputs_.scroll_parent); + EXPECT_EQ(src->inputs_.scroll_parent->id(), + dest->inputs_.scroll_parent->id()); } else { - EXPECT_FALSE(dest->scroll_parent_); + EXPECT_FALSE(dest->inputs_.scroll_parent); } if (src->scroll_children_) { ASSERT_TRUE(dest->scroll_children_); @@ -219,11 +228,12 @@ EXPECT_FALSE(dest->scroll_children_); } - if (src->clip_parent_) { - ASSERT_TRUE(dest->clip_parent_); - EXPECT_EQ(src->clip_parent_->id(), dest->clip_parent_->id()); + if (src->inputs_.clip_parent) { + ASSERT_TRUE(dest->inputs_.clip_parent); + EXPECT_EQ(src->inputs_.clip_parent->id(), + dest->inputs_.clip_parent->id()); } else { - ASSERT_FALSE(dest->clip_parent_); + ASSERT_FALSE(dest->inputs_.clip_parent); } if (src->clip_children_) { ASSERT_TRUE(dest->clip_children_); @@ -233,16 +243,16 @@ } // The following member should have been reset during serialization. - EXPECT_EQ(gfx::Rect(), src->update_rect_); + EXPECT_EQ(gfx::Rect(), src->inputs_.update_rect); // Before deleting |dest|, the LayerTreeHost must be unset. dest->SetLayerTreeHost(nullptr); // Cleanup scroll tree. - if (src->scroll_parent_) - layer_tree_host_->UnregisterLayer(src->scroll_parent_); - src->scroll_parent_ = nullptr; - dest->scroll_parent_ = nullptr; + if (src->inputs_.scroll_parent) + layer_tree_host_->UnregisterLayer(src->inputs_.scroll_parent); + src->inputs_.scroll_parent = nullptr; + dest->inputs_.scroll_parent = nullptr; if (src->scroll_children_) { for (auto* child : *(src->scroll_children_)) layer_tree_host_->UnregisterLayer(child); @@ -251,10 +261,10 @@ } // Cleanup clip tree. - if (src->clip_parent_) - layer_tree_host_->UnregisterLayer(src->clip_parent_); - src->clip_parent_ = nullptr; - dest->clip_parent_ = nullptr; + if (src->inputs_.clip_parent) + layer_tree_host_->UnregisterLayer(src->inputs_.clip_parent); + src->inputs_.clip_parent = nullptr; + dest->inputs_.clip_parent = nullptr; if (src->clip_children_) { for (auto* child : *(src->clip_children_)) layer_tree_host_->UnregisterLayer(child); @@ -270,91 +280,96 @@ void RunArbitraryMembersChangedTest() { scoped_refptr<Layer> layer = Layer::Create(); - layer->transform_origin_ = gfx::Point3F(3.0f, 1.0f, 4.0f); - layer->background_color_ = SK_ColorRED; - layer->bounds_ = gfx::Size(3, 14); + layer->inputs_.transform_origin = gfx::Point3F(3.0f, 1.0f, 4.0f); + layer->inputs_.background_color = SK_ColorRED; + layer->inputs_.bounds = gfx::Size(3, 14); layer->transform_tree_index_ = -1; layer->effect_tree_index_ = -1; layer->clip_tree_index_ = 71; layer->offset_to_transform_parent_ = gfx::Vector2dF(3.14f, 1.618f); - layer->double_sided_ = true; + layer->inputs_.double_sided = true; layer->draws_content_ = true; - layer->hide_layer_and_subtree_ = false; - layer->masks_to_bounds_ = true; - layer->main_thread_scrolling_reasons_ = + layer->inputs_.hide_layer_and_subtree = false; + layer->inputs_.masks_to_bounds = true; + layer->inputs_.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; - layer->non_fast_scrollable_region_ = Region(gfx::Rect(5, 1, 14, 3)); - layer->touch_event_handler_region_ = Region(gfx::Rect(3, 14, 1, 5)); - layer->contents_opaque_ = true; - layer->opacity_ = 1.f; - layer->blend_mode_ = SkXfermode::kSrcOver_Mode; - layer->is_root_for_isolated_group_ = true; - layer->position_ = gfx::PointF(3.14f, 6.28f); - layer->is_container_for_fixed_position_layers_ = true; + layer->inputs_.non_fast_scrollable_region = Region(gfx::Rect(5, 1, 14, 3)); + layer->inputs_.touch_event_handler_region = Region(gfx::Rect(3, 14, 1, 5)); + layer->inputs_.contents_opaque = true; + layer->inputs_.opacity = 1.f; + layer->inputs_.blend_mode = SkXfermode::kSrcOver_Mode; + layer->inputs_.is_root_for_isolated_group = true; + layer->inputs_.position = gfx::PointF(3.14f, 6.28f); + layer->inputs_.is_container_for_fixed_position_layers = true; LayerPositionConstraint pos_con; pos_con.set_is_fixed_to_bottom_edge(true); - layer->position_constraint_ = pos_con; - layer->should_flatten_transform_ = true; + layer->inputs_.position_constraint = pos_con; + layer->inputs_.should_flatten_transform = true; layer->should_flatten_transform_from_property_tree_ = true; layer->draw_blend_mode_ = SkXfermode::kSrcOut_Mode; - layer->use_parent_backface_visibility_ = true; + layer->inputs_.use_parent_backface_visibility = true; gfx::Transform transform; transform.Rotate(90); - layer->transform_ = transform; - layer->sorting_context_id_ = 0; + layer->inputs_.transform = transform; + layer->inputs_.sorting_context_id = 0; layer->num_descendants_that_draw_content_ = 5; - layer->scroll_clip_layer_id_ = Layer::INVALID_ID; - layer->user_scrollable_horizontal_ = false; - layer->user_scrollable_vertical_ = true; - layer->scroll_offset_ = gfx::ScrollOffset(3, 14); - layer->update_rect_ = gfx::Rect(14, 15); + layer->inputs_.scroll_clip_layer_id = Layer::INVALID_ID; + layer->inputs_.user_scrollable_horizontal = false; + layer->inputs_.user_scrollable_vertical = true; + layer->inputs_.scroll_offset = gfx::ScrollOffset(3, 14); + layer->inputs_.update_rect = gfx::Rect(14, 15); VerifyBaseLayerPropertiesSerializationAndDeserialization(layer.get()); } void RunAllMembersChangedTest() { scoped_refptr<Layer> layer = Layer::Create(); - layer->transform_origin_ = gfx::Point3F(3.0f, 1.0f, 4.0f); - layer->background_color_ = SK_ColorRED; - layer->bounds_ = gfx::Size(3, 14); + layer->inputs_.transform_origin = gfx::Point3F(3.0f, 1.0f, 4.0f); + layer->inputs_.background_color = SK_ColorRED; + layer->inputs_.bounds = gfx::Size(3, 14); layer->transform_tree_index_ = 39; layer->effect_tree_index_ = 17; layer->clip_tree_index_ = 71; layer->offset_to_transform_parent_ = gfx::Vector2dF(3.14f, 1.618f); - layer->double_sided_ = !layer->double_sided_; + layer->inputs_.double_sided = !layer->inputs_.double_sided; layer->draws_content_ = !layer->draws_content_; - layer->hide_layer_and_subtree_ = !layer->hide_layer_and_subtree_; - layer->masks_to_bounds_ = !layer->masks_to_bounds_; - layer->main_thread_scrolling_reasons_ = + layer->inputs_.hide_layer_and_subtree = + !layer->inputs_.hide_layer_and_subtree; + layer->inputs_.masks_to_bounds = !layer->inputs_.masks_to_bounds; + layer->inputs_.main_thread_scrolling_reasons = MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; - layer->non_fast_scrollable_region_ = Region(gfx::Rect(5, 1, 14, 3)); - layer->touch_event_handler_region_ = Region(gfx::Rect(3, 14, 1, 5)); - layer->contents_opaque_ = !layer->contents_opaque_; - layer->opacity_ = 3.14f; - layer->blend_mode_ = SkXfermode::kSrcIn_Mode; - layer->is_root_for_isolated_group_ = !layer->is_root_for_isolated_group_; - layer->position_ = gfx::PointF(3.14f, 6.28f); - layer->is_container_for_fixed_position_layers_ = - !layer->is_container_for_fixed_position_layers_; + layer->inputs_.non_fast_scrollable_region = Region(gfx::Rect(5, 1, 14, 3)); + layer->inputs_.touch_event_handler_region = Region(gfx::Rect(3, 14, 1, 5)); + layer->inputs_.contents_opaque = !layer->inputs_.contents_opaque; + layer->inputs_.opacity = 3.14f; + layer->inputs_.blend_mode = SkXfermode::kSrcIn_Mode; + layer->inputs_.is_root_for_isolated_group = + !layer->inputs_.is_root_for_isolated_group; + layer->inputs_.position = gfx::PointF(3.14f, 6.28f); + layer->inputs_.is_container_for_fixed_position_layers = + !layer->inputs_.is_container_for_fixed_position_layers; LayerPositionConstraint pos_con; pos_con.set_is_fixed_to_bottom_edge(true); - layer->position_constraint_ = pos_con; - layer->should_flatten_transform_ = !layer->should_flatten_transform_; + layer->inputs_.position_constraint = pos_con; + layer->inputs_.should_flatten_transform = + !layer->inputs_.should_flatten_transform; layer->should_flatten_transform_from_property_tree_ = !layer->should_flatten_transform_from_property_tree_; layer->draw_blend_mode_ = SkXfermode::kSrcOut_Mode; - layer->use_parent_backface_visibility_ = - !layer->use_parent_backface_visibility_; + layer->inputs_.use_parent_backface_visibility = + !layer->inputs_.use_parent_backface_visibility; gfx::Transform transform; transform.Rotate(90); - layer->transform_ = transform; - layer->sorting_context_id_ = 42; + layer->inputs_.transform = transform; + layer->inputs_.sorting_context_id = 42; layer->num_descendants_that_draw_content_ = 5; - layer->scroll_clip_layer_id_ = 17; - layer->user_scrollable_horizontal_ = !layer->user_scrollable_horizontal_; - layer->user_scrollable_vertical_ = !layer->user_scrollable_vertical_; - layer->scroll_offset_ = gfx::ScrollOffset(3, 14); - layer->update_rect_ = gfx::Rect(14, 15); + layer->inputs_.scroll_clip_layer_id = 17; + layer->inputs_.user_scrollable_horizontal = + !layer->inputs_.user_scrollable_horizontal; + layer->inputs_.user_scrollable_vertical = + !layer->inputs_.user_scrollable_vertical; + layer->inputs_.scroll_offset = gfx::ScrollOffset(3, 14); + layer->inputs_.update_rect = gfx::Rect(14, 15); VerifyBaseLayerPropertiesSerializationAndDeserialization(layer.get()); } @@ -367,7 +382,8 @@ scoped_refptr<SolidColorScrollbarLayer> deserialized_scrollbar = SolidColorScrollbarLayer::Create(ScrollbarOrientation::HORIZONTAL, -1, -1, false, Layer::INVALID_ID); - deserialized_scrollbar->layer_id_ = source_scrollbar->layer_id_; + deserialized_scrollbar->inputs_.layer_id = + source_scrollbar->inputs_.layer_id; // FromLayerSpecificPropertiesProto expects a non-null LayerTreeHost to be // set. @@ -393,13 +409,13 @@ scoped_refptr<Layer> layer = Layer::Create(); scoped_refptr<Layer> scroll_parent = Layer::Create(); - layer->scroll_parent_ = scroll_parent.get(); + layer->inputs_.scroll_parent = scroll_parent.get(); scoped_refptr<Layer> scroll_child = Layer::Create(); layer->scroll_children_.reset(new std::set<Layer*>); layer->scroll_children_->insert(scroll_child.get()); scoped_refptr<Layer> clip_parent = Layer::Create(); - layer->clip_parent_ = clip_parent.get(); + layer->inputs_.clip_parent = clip_parent.get(); layer->clip_children_.reset(new std::set<Layer*>); scoped_refptr<Layer> clip_child1 = Layer::Create(); layer->clip_children_->insert(clip_child1.get()); @@ -542,9 +558,9 @@ EXPECT_EQ(layer_src_b->id(), layer_dest_b->id()); // Swap order of the children. - scoped_refptr<Layer> tmp_a = layer_src_root->children_[0]; - layer_src_root->children_[0] = layer_src_root->children_[1]; - layer_src_root->children_[1] = tmp_a; + scoped_refptr<Layer> tmp_a = layer_src_root->inputs_.children[0]; + layer_src_root->inputs_.children[0] = layer_src_root->inputs_.children[1]; + layer_src_root->inputs_.children[1] = tmp_a; // Fake the fact that the destination layers have valid indexes. layer_dest_root->transform_tree_index_ = 33; @@ -1138,41 +1154,41 @@ root->SetPosition(arbitrary_point_f); TransformNode* node = layer_tree_host_->property_trees()->transform_tree.Node( root->transform_tree_index()); - EXPECT_TRUE(node->data.transform_changed); + EXPECT_TRUE(node->transform_changed); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( root->PushPropertiesTo(root_impl.get()); child->PushPropertiesTo(child_impl.get()); child2->PushPropertiesTo(child2_impl.get()); grand_child->PushPropertiesTo(grand_child_impl.get()); layer_tree_host_->property_trees()->ResetAllChangeTracking()); - EXPECT_FALSE(node->data.transform_changed); + EXPECT_FALSE(node->transform_changed); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); child->SetPosition(arbitrary_point_f); node = layer_tree_host_->property_trees()->transform_tree.Node( child->transform_tree_index()); - EXPECT_TRUE(node->data.transform_changed); + EXPECT_TRUE(node->transform_changed); // child2 is not in the subtree of child, but its scroll parent is. So, its // to_screen will be effected by change in position of child2. layer_tree_host_->property_trees()->transform_tree.UpdateTransforms( child2->transform_tree_index()); node = layer_tree_host_->property_trees()->transform_tree.Node( child2->transform_tree_index()); - EXPECT_TRUE(node->data.transform_changed); + EXPECT_TRUE(node->transform_changed); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( child->PushPropertiesTo(child_impl.get()); grand_child->PushPropertiesTo(grand_child_impl.get()); layer_tree_host_->property_trees()->ResetAllChangeTracking()); node = layer_tree_host_->property_trees()->transform_tree.Node( child->transform_tree_index()); - EXPECT_FALSE(node->data.transform_changed); + EXPECT_FALSE(node->transform_changed); gfx::Point3F arbitrary_point_3f = gfx::Point3F(0.125f, 0.25f, 0.f); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); root->SetTransformOrigin(arbitrary_point_3f); node = layer_tree_host_->property_trees()->transform_tree.Node( root->transform_tree_index()); - EXPECT_TRUE(node->data.transform_changed); + EXPECT_TRUE(node->transform_changed); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( root->PushPropertiesTo(root_impl.get()); child->PushPropertiesTo(child_impl.get()); @@ -1186,7 +1202,7 @@ root->SetTransform(arbitrary_transform); node = layer_tree_host_->property_trees()->transform_tree.Node( root->transform_tree_index()); - EXPECT_TRUE(node->data.transform_changed); + EXPECT_TRUE(node->transform_changed); } TEST_F(LayerTest, AddAndRemoveChild) { @@ -2192,20 +2208,22 @@ scoped_refptr<Layer> layer = Layer::Create(); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(layer)); + LayerInternalsForTest layer_internals(layer.get()); + EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(1); - layer->OnOpacityAnimated(0.5f); + layer_internals.OnOpacityAnimated(0.5f); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(1); gfx::Transform transform; transform.Rotate(45.0); - layer->OnTransformAnimated(transform); + layer_internals.OnTransformAnimated(transform); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); // Scroll offset animation should not schedule a layer update since it is // handled similarly to normal compositor scroll updates. EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(0); - layer->OnScrollOffsetAnimated(gfx::ScrollOffset(10, 10)); + layer_internals.OnScrollOffsetAnimated(gfx::ScrollOffset(10, 10)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); }
diff --git a/cc/layers/layer_utils.cc b/cc/layers/layer_utils.cc index 0eeab138..b3b6d53 100644 --- a/cc/layers/layer_utils.cc +++ b/cc/layers/layer_utils.cc
@@ -7,6 +7,7 @@ #include "cc/layers/layer_impl.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/box_f.h" namespace cc { @@ -18,7 +19,7 @@ } inline bool HasAncestorTransformAnimation(const TransformNode* transform_node) { - return transform_node->data.to_screen_is_potentially_animated; + return transform_node->to_screen_is_potentially_animated; } inline bool HasAncestorFilterAnimation(const LayerImpl& layer) { @@ -92,7 +93,7 @@ // HasAncestorFilterAnimation() for reference. if (HasTransformAnimationThatInflatesBounds(*layer)) { - coalesced_transform.ConcatTransform(transform_node->data.pre_local); + coalesced_transform.ConcatTransform(transform_node->pre_local); coalesced_transform.TransformBox(&box); coalesced_transform.MakeIdentity(); @@ -101,9 +102,9 @@ return false; box = inflated; - coalesced_transform.ConcatTransform(transform_node->data.post_local); + coalesced_transform.ConcatTransform(transform_node->post_local); } else { - coalesced_transform.ConcatTransform(transform_node->data.to_parent); + coalesced_transform.ConcatTransform(transform_node->to_parent); } }
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc index 6bbcf107..09bb588b 100644 --- a/cc/layers/painted_scrollbar_layer.cc +++ b/cc/layers/painted_scrollbar_layer.cc
@@ -245,7 +245,7 @@ updated = true; } - if (update_rect_.IsEmpty() && track_resource_) + if (update_rect().IsEmpty() && track_resource_) return updated; if (!track_resource_ || scrollbar_->NeedsPaintPart(TRACK)) {
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc index 1a742f9..a2d128ca 100644 --- a/cc/layers/render_surface_impl.cc +++ b/cc/layers/render_surface_impl.cc
@@ -21,6 +21,7 @@ #include "cc/quads/shared_quad_state.h" #include "cc/trees/damage_tracker.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/occlusion.h" #include "third_party/skia/include/core/SkImageFilter.h" @@ -45,9 +46,9 @@ EffectTree& effect_tree = owning_layer_->layer_tree_impl()->property_trees()->effect_tree; EffectNode* node = effect_tree.Node(EffectTreeIndex()); - EffectNode* target_node = effect_tree.Node(node->data.target_id); + EffectNode* target_node = effect_tree.Node(node->target_id); if (target_node->id != 0) - return target_node->data.render_surface; + return target_node->render_surface; else return this; } @@ -56,9 +57,9 @@ const EffectTree& effect_tree = owning_layer_->layer_tree_impl()->property_trees()->effect_tree; const EffectNode* node = effect_tree.Node(EffectTreeIndex()); - const EffectNode* target_node = effect_tree.Node(node->data.target_id); + const EffectNode* target_node = effect_tree.Node(node->target_id); if (target_node->id != 0) - return target_node->data.render_surface; + return target_node->render_surface; else return this; } @@ -125,43 +126,43 @@ } bool RenderSurfaceImpl::HasReplica() const { - return OwningEffectNode()->data.replica_layer_id != -1; + return OwningEffectNode()->replica_layer_id != -1; } const LayerImpl* RenderSurfaceImpl::ReplicaLayer() const { - int replica_layer_id = OwningEffectNode()->data.replica_layer_id; + int replica_layer_id = OwningEffectNode()->replica_layer_id; return owning_layer_->layer_tree_impl()->LayerById(replica_layer_id); } LayerImpl* RenderSurfaceImpl::ReplicaLayer() { - int replica_layer_id = OwningEffectNode()->data.replica_layer_id; + int replica_layer_id = OwningEffectNode()->replica_layer_id; return owning_layer_->layer_tree_impl()->LayerById(replica_layer_id); } LayerImpl* RenderSurfaceImpl::MaskLayer() { - int mask_layer_id = OwningEffectNode()->data.mask_layer_id; + int mask_layer_id = OwningEffectNode()->mask_layer_id; return owning_layer_->layer_tree_impl()->LayerById(mask_layer_id); } bool RenderSurfaceImpl::HasMask() const { - return OwningEffectNode()->data.mask_layer_id != -1; + return OwningEffectNode()->mask_layer_id != -1; } LayerImpl* RenderSurfaceImpl::ReplicaMaskLayer() { - int replica_mask_layer_id = OwningEffectNode()->data.replica_mask_layer_id; + int replica_mask_layer_id = OwningEffectNode()->replica_mask_layer_id; return owning_layer_->layer_tree_impl()->LayerById(replica_mask_layer_id); } bool RenderSurfaceImpl::HasReplicaMask() const { - return OwningEffectNode()->data.replica_mask_layer_id != -1; + return OwningEffectNode()->replica_mask_layer_id != -1; } const FilterOperations& RenderSurfaceImpl::BackgroundFilters() const { - return OwningEffectNode()->data.background_filters; + return OwningEffectNode()->background_filters; } bool RenderSurfaceImpl::HasCopyRequest() const { - return OwningEffectNode()->data.has_copy_request; + return OwningEffectNode()->has_copy_request; } int RenderSurfaceImpl::TransformTreeIndex() const {
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index ef16f8b4..6852fee 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -27,9 +27,11 @@ #include "cc/test/mock_occlusion_tracker.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/occlusion_tracker.h" +#include "cc/trees/scroll_node.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/tree_synchronizer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -543,7 +545,7 @@ layer_tree_host_->UpdateLayers(); EffectNode* node = layer_tree_host_->property_trees()->effect_tree.Node( scrollbar_layer->effect_tree_index()); - EXPECT_EQ(node->data.opacity, 0.f); + EXPECT_EQ(node->opacity, 0.f); // This tests that the initial opacity(0) of the scrollbar gets pushed onto // the pending tree and then onto the active tree. @@ -555,12 +557,12 @@ EXPECT_TRUE(layer_tree_impl->IsPendingTree()); node = layer_tree_impl->property_trees()->effect_tree.Node( scrollbar_layer->effect_tree_index()); - EXPECT_EQ(node->data.opacity, 0.f); + EXPECT_EQ(node->opacity, 0.f); host_impl->ActivateSyncTree(); layer_tree_impl = host_impl->active_tree(); node = layer_tree_impl->property_trees()->effect_tree.Node( scrollbar_layer->effect_tree_index()); - EXPECT_EQ(node->data.opacity, 0.f); + EXPECT_EQ(node->opacity, 0.f); // This tests that activation does not change the opacity of scrollbar layer. LayerImpl* scrollbar_layer_impl = @@ -572,12 +574,12 @@ EXPECT_TRUE(layer_tree_impl->IsPendingTree()); node = layer_tree_impl->property_trees()->effect_tree.Node( scrollbar_layer->effect_tree_index()); - EXPECT_EQ(node->data.opacity, 0.f); + EXPECT_EQ(node->opacity, 0.f); host_impl->ActivateSyncTree(); layer_tree_impl = host_impl->active_tree(); node = layer_tree_impl->property_trees()->effect_tree.Node( scrollbar_layer->effect_tree_index()); - EXPECT_EQ(node->data.opacity, 0.25f); + EXPECT_EQ(node->opacity, 0.25f); } TEST_F(ScrollbarLayerTest, ScrollbarLayerPushProperties) { @@ -621,7 +623,7 @@ EffectNode* node = host_impl->active_tree()->property_trees()->effect_tree.Node( scrollbar_layer->effect_tree_index()); - EXPECT_EQ(node->data.opacity, 1.f); + EXPECT_EQ(node->opacity, 1.f); } class ScrollbarLayerSolidColorThumbTest : public testing::Test {
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index eab540e..7d1e142 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc
@@ -201,7 +201,7 @@ // SetTextureMailbox could be called externally and the same mailbox used for // different textures. Such callers notify this layer that the texture has // changed by calling SetNeedsDisplay, so check for that here. - return updated || !update_rect_.IsEmpty(); + return updated || !update_rect().IsEmpty(); } void TextureLayer::PushPropertiesTo(LayerImpl* layer) {
diff --git a/cc/layers/video_layer.cc b/cc/layers/video_layer.cc index fe4f2ed..177721b 100644 --- a/cc/layers/video_layer.cc +++ b/cc/layers/video_layer.cc
@@ -35,7 +35,7 @@ // // This is the inefficient legacy redraw path for videos. It's better to // communicate this directly to the VideoLayerImpl. - updated |= !update_rect_.IsEmpty(); + updated |= !update_rect().IsEmpty(); return updated; }
diff --git a/cc/layers/viewport.cc b/cc/layers/viewport.cc index d80d40c..d4c3fd5 100644 --- a/cc/layers/viewport.cc +++ b/cc/layers/viewport.cc
@@ -9,6 +9,7 @@ #include "cc/input/top_controls_manager.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" #include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/geometry/vector2d_f.h"
diff --git a/cc/output/compositor_frame_metadata.cc b/cc/output/compositor_frame_metadata.cc index a98eee2..afd9741 100644 --- a/cc/output/compositor_frame_metadata.cc +++ b/cc/output/compositor_frame_metadata.cc
@@ -6,14 +6,7 @@ namespace cc { -CompositorFrameMetadata::CompositorFrameMetadata() - : device_scale_factor(0.f), - page_scale_factor(0.f), - min_page_scale_factor(0.f), - max_page_scale_factor(0.f), - root_overflow_x_hidden(false), - root_overflow_y_hidden(false), - root_background_color(SK_ColorWHITE) {} +CompositorFrameMetadata::CompositorFrameMetadata() = default; CompositorFrameMetadata::CompositorFrameMetadata( CompositorFrameMetadata&& other) = default;
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h index c2e13fe..d6f0e60 100644 --- a/cc/output/compositor_frame_metadata.h +++ b/cc/output/compositor_frame_metadata.h
@@ -31,21 +31,27 @@ CompositorFrameMetadata Clone() const; // The device scale factor used to generate this compositor frame. - float device_scale_factor; + float device_scale_factor = 0.f; // Scroll offset and scale of the root layer. This can be used for tasks // like positioning windowed plugins. gfx::Vector2dF root_scroll_offset; - float page_scale_factor; + float page_scale_factor = 0.f; // These limits can be used together with the scroll/scale fields above to // determine if scrolling/scaling in a particular direction is possible. gfx::SizeF scrollable_viewport_size; gfx::SizeF root_layer_size; - float min_page_scale_factor; - float max_page_scale_factor; - bool root_overflow_x_hidden; - bool root_overflow_y_hidden; + float min_page_scale_factor = 0.f; + float max_page_scale_factor = 0.f; + bool root_overflow_x_hidden = false; + bool root_overflow_y_hidden = false; + + // WebView makes quality decisions for rastering resourceless software frames + // based on information that a scroll or animation is active. + // TODO(aelias): Remove this and always enable filtering if there aren't apps + // depending on this anymore. + bool is_resourceless_software_draw_with_scroll_or_animation = false; // Used to position the Android location top bar and page content, whose // precise position is computed by the renderer compositor. @@ -55,7 +61,7 @@ // This color is usually obtained from the background color of the <body> // element. It can be used for filling in gutter areas around the frame when // it's too small to fill the box the parent reserved for it. - SkColor root_background_color; + SkColor root_background_color = SK_ColorWHITE; // Provides selection region updates relative to the current viewport. If the // selection is empty or otherwise unused, the bound types will indicate such.
diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc index 9d80336..06aee77 100644 --- a/cc/output/delegating_renderer.cc +++ b/cc/output/delegating_renderer.cc
@@ -77,8 +77,7 @@ float device_scale_factor, const gfx::ColorSpace& device_color_space, const gfx::Rect& device_viewport_rect, - const gfx::Rect& device_clip_rect, - bool disable_picture_quad_image_filtering) { + const gfx::Rect& device_clip_rect) { TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame"); DCHECK(!delegated_frame_data_);
diff --git a/cc/output/delegating_renderer.h b/cc/output/delegating_renderer.h index 831f943..eeec14a 100644 --- a/cc/output/delegating_renderer.h +++ b/cc/output/delegating_renderer.h
@@ -32,8 +32,7 @@ float device_scale_factor, const gfx::ColorSpace& device_color_space, const gfx::Rect& device_viewport_rect, - const gfx::Rect& device_clip_rect, - bool disable_picture_quad_image_filtering) override; + const gfx::Rect& device_clip_rect) override; void Finish() override {}
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index a677f0e..61865b1d 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc
@@ -200,8 +200,7 @@ float device_scale_factor, const gfx::ColorSpace& device_color_space, const gfx::Rect& device_viewport_rect, - const gfx::Rect& device_clip_rect, - bool disable_picture_quad_image_filtering) { + const gfx::Rect& device_clip_rect) { TRACE_EVENT0("cc", "DirectRenderer::DrawFrame"); UMA_HISTOGRAM_COUNTS( "Renderer4.renderPassCount", @@ -218,8 +217,6 @@ frame.root_damage_rect.Intersect(gfx::Rect(device_viewport_rect.size())); frame.device_viewport_rect = device_viewport_rect; frame.device_clip_rect = device_clip_rect; - frame.disable_picture_quad_image_filtering = - disable_picture_quad_image_filtering; EnsureBackbuffer();
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h index 63d40af..d0687cd 100644 --- a/cc/output/direct_renderer.h +++ b/cc/output/direct_renderer.h
@@ -38,8 +38,7 @@ float device_scale_factor, const gfx::ColorSpace& device_color_space, const gfx::Rect& device_viewport_rect, - const gfx::Rect& device_clip_rect, - bool disable_picture_quad_image_filtering) override; + const gfx::Rect& device_clip_rect) override; virtual void SwapBuffersComplete() {} virtual void DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) {} @@ -65,8 +64,6 @@ gfx::Transform projection_matrix; gfx::Transform window_matrix; - bool disable_picture_quad_image_filtering; - OverlayCandidateList overlay_list; CALayerOverlayList ca_layer_overlay_list; };
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index 51377a35..e8dbf43 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc
@@ -66,13 +66,13 @@ } void DrawFrame(Renderer* renderer, const gfx::Rect& viewport_rect) { renderer->DrawFrame(&render_passes_in_draw_order_, 1.f, gfx::ColorSpace(), - viewport_rect, viewport_rect, false); + viewport_rect, viewport_rect); } void DrawFrame(Renderer* renderer, const gfx::Rect& viewport_rect, const gfx::Rect& clip_rect) { renderer->DrawFrame(&render_passes_in_draw_order_, 1.f, gfx::ColorSpace(), - viewport_rect, clip_rect, false); + viewport_rect, clip_rect); } RenderPassList render_passes_in_draw_order_; @@ -1693,7 +1693,7 @@ bool has_alpha)); MOCK_METHOD0(BindFramebuffer, void()); MOCK_METHOD0(GetFramebufferCopyTextureFormat, GLenum()); - MOCK_METHOD1(SwapBuffers_, void(CompositorFrame& frame)); + MOCK_METHOD1(SwapBuffers_, void(CompositorFrame& frame)); // NOLINT void SwapBuffers(CompositorFrame frame) override { SwapBuffers_(frame); } }; @@ -1739,7 +1739,7 @@ render_passes_in_draw_order_); renderer_->DrawFrame(&render_passes_in_draw_order_, device_scale_factor, gfx::ColorSpace(), device_viewport_rect, - device_viewport_rect, false); + device_viewport_rect); } OutputSurfaceMockContext* Context() {
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc index 2e7ccc755..3c7e16b 100644 --- a/cc/output/overlay_unittest.cc +++ b/cc/output/overlay_unittest.cc
@@ -1222,7 +1222,7 @@ void DrawFrame(RenderPassList* pass_list, const gfx::Rect& viewport_rect) { renderer_->DrawFrame(pass_list, 1.f, gfx::ColorSpace(), viewport_rect, - viewport_rect, false); + viewport_rect); } void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata());
diff --git a/cc/output/renderer.h b/cc/output/renderer.h index 2b5a52c9..f349295c 100644 --- a/cc/output/renderer.h +++ b/cc/output/renderer.h
@@ -73,8 +73,7 @@ float device_scale_factor, const gfx::ColorSpace& device_color_space, const gfx::Rect& device_viewport_rect, - const gfx::Rect& device_clip_rect, - bool disable_picture_quad_image_filtering) = 0; + const gfx::Rect& device_clip_rect) = 0; // Waits for rendering to finish. virtual void Finish() = 0;
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index 0368ad9..ee169b7 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc
@@ -56,24 +56,20 @@ RendererClient* client, const RendererSettings* settings, OutputSurface* output_surface, - ResourceProvider* resource_provider, - bool use_image_hijack_canvas) { + ResourceProvider* resource_provider) { return base::WrapUnique(new SoftwareRenderer(client, settings, output_surface, - resource_provider, - use_image_hijack_canvas)); + resource_provider)); } SoftwareRenderer::SoftwareRenderer(RendererClient* client, const RendererSettings* settings, OutputSurface* output_surface, - ResourceProvider* resource_provider, - bool use_image_hijack_canvas) + ResourceProvider* resource_provider) : DirectRenderer(client, settings, output_surface, resource_provider), is_scissor_enabled_(false), is_backbuffer_discarded_(false), output_device_(output_surface->software_device()), - current_canvas_(nullptr), - use_image_hijack_canvas_(use_image_hijack_canvas) { + current_canvas_(nullptr) { if (resource_provider_) { capabilities_.max_texture_size = resource_provider_->max_texture_size(); capabilities_.best_texture_format = @@ -366,13 +362,19 @@ const bool needs_transparency = SkScalarRoundToInt(quad->shared_quad_state->opacity * 255) < 255; const bool disable_image_filtering = - frame->disable_picture_quad_image_filtering || quad->nearest_neighbor; + disable_picture_quad_image_filtering_ || quad->nearest_neighbor; TRACE_EVENT0("cc", "SoftwareRenderer::DrawPictureQuad"); RasterSource::PlaybackSettings playback_settings; playback_settings.playback_to_shared_canvas = true; - playback_settings.use_image_hijack_canvas = use_image_hijack_canvas_; + // Indicates whether content rasterization should happen through an + // ImageHijackCanvas, which causes image decodes to be managed by an + // ImageDecodeController. PictureDrawQuads are used for resourceless software + // draws, while a GPU ImageDecodeController may be in use by the compositor + // providing the RasterSource. So we disable the image hijack canvas to avoid + // trying to use the GPU ImageDecodeController while doing a software draw. + playback_settings.use_image_hijack_canvas = false; if (needs_transparency || disable_image_filtering) { // TODO(aelias): This isn't correct in all cases. We should detect these // cases and fall back to a persistent bitmap backing
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h index 5a0bb04..c7e0f809 100644 --- a/cc/output/software_renderer.h +++ b/cc/output/software_renderer.h
@@ -30,8 +30,7 @@ RendererClient* client, const RendererSettings* settings, OutputSurface* output_surface, - ResourceProvider* resource_provider, - bool use_image_hijack_canvas); + ResourceProvider* resource_provider); ~SoftwareRenderer() override; const RendererCapabilitiesImpl& Capabilities() const override; @@ -40,6 +39,10 @@ void DiscardBackbuffer() override; void EnsureBackbuffer() override; + void SetDisablePictureQuadImageFiltering(bool disable) { + disable_picture_quad_image_filtering_ = disable; + } + protected: void BindFramebufferToOutputSurface(DrawingFrame* frame) override; bool BindFramebufferToTexture(DrawingFrame* frame, @@ -64,8 +67,7 @@ SoftwareRenderer(RendererClient* client, const RendererSettings* settings, OutputSurface* output_surface, - ResourceProvider* resource_provider, - bool use_image_hijack_canvas); + ResourceProvider* resource_provider); void DidChangeVisibility() override; @@ -104,6 +106,8 @@ const RenderPassDrawQuad* quad, SkShader::TileMode content_tile_mode) const; + bool disable_picture_quad_image_filtering_ = false; + RendererCapabilitiesImpl capabilities_; bool is_scissor_enabled_; bool is_backbuffer_discarded_; @@ -117,13 +121,6 @@ current_framebuffer_lock_; sk_sp<SkCanvas> current_framebuffer_canvas_; - // Indicates whether content rasterization should happen through an - // ImageHijackCanvas, which causes image decodes to be managed by an - // ImageDecodeController. We set this to false during resourceless software - // draw when a GPU ImageDecodeController is in use, as software rasterization - // cannot use the GPU IDC. - const bool use_image_hijack_canvas_; - DISALLOW_COPY_AND_ASSIGN(SoftwareRenderer); };
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc index 087db9b..be76d35 100644 --- a/cc/output/software_renderer_unittest.cc +++ b/cc/output/software_renderer_unittest.cc
@@ -42,8 +42,7 @@ resource_provider_ = FakeResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get()); renderer_ = SoftwareRenderer::Create( - this, &settings_, output_surface_.get(), resource_provider(), - true /* use_image_hijack_canvas */); + this, &settings_, output_surface_.get(), resource_provider()); } ResourceProvider* resource_provider() const { @@ -68,7 +67,7 @@ loop.QuitClosure()))); renderer()->DrawFrame(list, device_scale_factor, gfx::ColorSpace(), - device_viewport_rect, device_viewport_rect, false); + device_viewport_rect, device_viewport_rect); loop.Run(); return bitmap_result; }
diff --git a/cc/proto/property_tree.proto b/cc/proto/property_tree.proto index afdd13e..230c62e 100644 --- a/cc/proto/property_tree.proto +++ b/cc/proto/property_tree.proto
@@ -85,7 +85,7 @@ } // Proto for struct EffectNodeData. -// NEXT ID: 20 +// NEXT ID: 21 message EffectNodeData { optional float opacity = 1; optional float screen_space_opacity = 2; @@ -105,6 +105,7 @@ optional int64 mask_layer_id = 17; optional int64 replica_layer_id = 18; optional int64 replica_mask_layer_id = 19; + optional Vector2dF sublayer_scale = 20; } // Proto for struct ScrollNodeData
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc index 56e4b57..1bc2e04 100644 --- a/cc/raster/bitmap_raster_buffer_provider.cc +++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -103,11 +103,15 @@ return resource_provider_->best_texture_format(); } -bool BitmapRasterBufferProvider::GetResourceRequiresSwizzle( +bool BitmapRasterBufferProvider::IsResourceSwizzleRequired( bool must_support_alpha) const { return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } +bool BitmapRasterBufferProvider::IsPartialRasterSupported() const { + return true; +} + void BitmapRasterBufferProvider::Shutdown() {} } // namespace cc
diff --git a/cc/raster/bitmap_raster_buffer_provider.h b/cc/raster/bitmap_raster_buffer_provider.h index 045622626..182be515 100644 --- a/cc/raster/bitmap_raster_buffer_provider.h +++ b/cc/raster/bitmap_raster_buffer_provider.h
@@ -35,7 +35,8 @@ void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override; void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool GetResourceRequiresSwizzle(bool must_support_alpha) const override; + bool IsResourceSwizzleRequired(bool must_support_alpha) const override; + bool IsPartialRasterSupported() const override; void Shutdown() override; protected:
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc index 0cd802b1..adeddbd 100644 --- a/cc/raster/gpu_raster_buffer_provider.cc +++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -188,12 +188,16 @@ return resource_provider_->best_render_buffer_format(); } -bool GpuRasterBufferProvider::GetResourceRequiresSwizzle( +bool GpuRasterBufferProvider::IsResourceSwizzleRequired( bool must_support_alpha) const { // This doesn't require a swizzle because we rasterize to the correct format. return false; } +bool GpuRasterBufferProvider::IsPartialRasterSupported() const { + return true; +} + void GpuRasterBufferProvider::Shutdown() { pending_raster_buffers_.clear(); }
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h index ef69754..dc4fb61d 100644 --- a/cc/raster/gpu_raster_buffer_provider.h +++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -33,7 +33,8 @@ void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override; void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool GetResourceRequiresSwizzle(bool must_support_alpha) const override; + bool IsResourceSwizzleRequired(bool must_support_alpha) const override; + bool IsPartialRasterSupported() const override; void Shutdown() override; void PlaybackOnWorkerThread(
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc index a9ff50f..44e3845 100644 --- a/cc/raster/one_copy_raster_buffer_provider.cc +++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -148,11 +148,15 @@ return resource_provider_->best_texture_format(); } -bool OneCopyRasterBufferProvider::GetResourceRequiresSwizzle( +bool OneCopyRasterBufferProvider::IsResourceSwizzleRequired( bool must_support_alpha) const { return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } +bool OneCopyRasterBufferProvider::IsPartialRasterSupported() const { + return true; +} + void OneCopyRasterBufferProvider::Shutdown() { staging_pool_.Shutdown(); pending_raster_buffers_.clear();
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h index 44ceb7a..008a5bd4 100644 --- a/cc/raster/one_copy_raster_buffer_provider.h +++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -40,7 +40,8 @@ void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override; void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool GetResourceRequiresSwizzle(bool must_support_alpha) const override; + bool IsResourceSwizzleRequired(bool must_support_alpha) const override; + bool IsPartialRasterSupported() const override; void Shutdown() override; // Playback raster source and copy result into |resource|.
diff --git a/cc/raster/raster_buffer_provider.h b/cc/raster/raster_buffer_provider.h index 1cdfba2..616d123 100644 --- a/cc/raster/raster_buffer_provider.h +++ b/cc/raster/raster_buffer_provider.h
@@ -60,7 +60,11 @@ virtual ResourceFormat GetResourceFormat(bool must_support_alpha) const = 0; // Determine if the resource requires swizzling. - virtual bool GetResourceRequiresSwizzle(bool must_support_alpha) const = 0; + virtual bool IsResourceSwizzleRequired(bool must_support_alpha) const = 0; + + // Determine if the RasterBufferProvider can handle partial raster into + // resources. + virtual bool IsPartialRasterSupported() const = 0; // Shutdown for doing cleanup. virtual void Shutdown() = 0;
diff --git a/cc/raster/zero_copy_raster_buffer_provider.cc b/cc/raster/zero_copy_raster_buffer_provider.cc index b89b45b..e33bb43 100644 --- a/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/cc/raster/zero_copy_raster_buffer_provider.cc
@@ -111,11 +111,15 @@ return resource_provider_->best_texture_format(); } -bool ZeroCopyRasterBufferProvider::GetResourceRequiresSwizzle( +bool ZeroCopyRasterBufferProvider::IsResourceSwizzleRequired( bool must_support_alpha) const { return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } +bool ZeroCopyRasterBufferProvider::IsPartialRasterSupported() const { + return false; +} + void ZeroCopyRasterBufferProvider::Shutdown() {} } // namespace cc
diff --git a/cc/raster/zero_copy_raster_buffer_provider.h b/cc/raster/zero_copy_raster_buffer_provider.h index f813a59b..67262c7 100644 --- a/cc/raster/zero_copy_raster_buffer_provider.h +++ b/cc/raster/zero_copy_raster_buffer_provider.h
@@ -37,7 +37,8 @@ void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override; void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool GetResourceRequiresSwizzle(bool must_support_alpha) const override; + bool IsResourceSwizzleRequired(bool must_support_alpha) const override; + bool IsPartialRasterSupported() const override; void Shutdown() override; protected:
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index e9803961..d38110e 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -1184,7 +1184,9 @@ sk_bitmap.setImmutable(); sk_image_ = SkImage::MakeFromBitmap(sk_bitmap); } else { - NOTREACHED() << "Image not valid"; + // TODO(enne): fix race condition of shared bitmap manager going away + // that can cause this to happen. This will cause the read lock + // to not be valid. } }
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index e4ad249b..d20f8f82 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc
@@ -52,7 +52,6 @@ texture_mailbox_deleter_(std::move(texture_mailbox_deleter)) { DCHECK(surface_manager_); DCHECK(output_surface_); - DCHECK(texture_mailbox_deleter_); DCHECK_EQ(!scheduler_, !begin_frame_source_); surface_manager_->AddObserver(this); @@ -163,6 +162,7 @@ GL_TEXTURE_2D))); if (output_surface_->context_provider()) { + DCHECK(texture_mailbox_deleter_); std::unique_ptr<GLRenderer> renderer = GLRenderer::Create( this, &settings_, output_surface_.get(), resource_provider.get(), texture_mailbox_deleter_.get(), settings_.highp_threshold_min); @@ -171,6 +171,7 @@ renderer_ = std::move(renderer); } else if (output_surface_->vulkan_context_provider()) { #if defined(ENABLE_VULKAN) + DCHECK(texture_mailbox_deleter_); std::unique_ptr<VulkanRenderer> renderer = VulkanRenderer::Create( this, &settings_, output_surface_.get(), resource_provider.get(), texture_mailbox_deleter_.get(), settings_.highp_threshold_min); @@ -182,10 +183,10 @@ #endif } else { std::unique_ptr<SoftwareRenderer> renderer = SoftwareRenderer::Create( - this, &settings_, output_surface_.get(), resource_provider.get(), - true /* use_image_hijack_canvas */); + this, &settings_, output_surface_.get(), resource_provider.get()); if (!renderer) return; + software_renderer_ = renderer.get(); renderer_ = std::move(renderer); } @@ -290,14 +291,22 @@ gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_); gfx::Rect device_clip_rect = external_clip_.IsEmpty() ? device_viewport_rect : external_clip_; - bool disable_picture_quad_image_filtering = false; + + bool disable_image_filtering = + frame.metadata.is_resourceless_software_draw_with_scroll_or_animation; + if (software_renderer_) { + software_renderer_->SetDisablePictureQuadImageFiltering( + disable_image_filtering); + } else { + // This should only be set for software draws in synchronous compositor. + DCHECK(!disable_image_filtering); + } renderer_->DecideRenderPassAllocationsForFrame( frame_data->render_pass_list); renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_, device_color_space_, device_viewport_rect, - device_clip_rect, - disable_picture_quad_image_filtering); + device_clip_rect); } else { TRACE_EVENT_INSTANT0("cc", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD); }
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h index 5d477ff..9df93d41 100644 --- a/cc/surfaces/display.h +++ b/cc/surfaces/display.h
@@ -39,6 +39,7 @@ class RendererSettings; class ResourceProvider; class SharedBitmapManager; +class SoftwareRenderer; class Surface; class SurfaceAggregator; class SurfaceIdAllocator; @@ -142,6 +143,7 @@ std::unique_ptr<SurfaceAggregator> aggregator_; std::unique_ptr<TextureMailboxDeleter> texture_mailbox_deleter_; std::unique_ptr<DirectRenderer> renderer_; + SoftwareRenderer* software_renderer_ = nullptr; std::vector<ui::LatencyInfo> stored_latency_info_; private:
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 23f2123..8fcc04a 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h
@@ -57,13 +57,6 @@ new FakeOutputSurface(std::move(software_device), false)); } - static std::unique_ptr<FakeOutputSurface> - Create3dWithResourcelessSoftwareSupport() { - return base::WrapUnique(new FakeOutputSurface( - TestContextProvider::Create(), TestContextProvider::CreateWorker(), - base::WrapUnique(new SoftwareOutputDevice), false)); - } - static std::unique_ptr<FakeOutputSurface> CreateDelegating3d() { return base::WrapUnique( new FakeOutputSurface(TestContextProvider::Create(),
diff --git a/cc/test/fake_picture_layer.cc b/cc/test/fake_picture_layer.cc index 291342cd..a4e9e8f4 100644 --- a/cc/test/fake_picture_layer.cc +++ b/cc/test/fake_picture_layer.cc
@@ -32,8 +32,8 @@ std::unique_ptr<LayerImpl> FakePictureLayer::CreateLayerImpl( LayerTreeImpl* tree_impl) { if (is_mask()) - return FakePictureLayerImpl::CreateMask(tree_impl, layer_id_); - return FakePictureLayerImpl::Create(tree_impl, layer_id_); + return FakePictureLayerImpl::CreateMask(tree_impl, id()); + return FakePictureLayerImpl::Create(tree_impl, id()); } bool FakePictureLayer::Update() {
diff --git a/cc/test/fake_raster_buffer_provider.cc b/cc/test/fake_raster_buffer_provider.cc index 9657b6be..9c24db2 100644 --- a/cc/test/fake_raster_buffer_provider.cc +++ b/cc/test/fake_raster_buffer_provider.cc
@@ -28,11 +28,15 @@ return ResourceFormat::RGBA_8888; } -bool FakeRasterBufferProviderImpl::GetResourceRequiresSwizzle( +bool FakeRasterBufferProviderImpl::IsResourceSwizzleRequired( bool must_support_alpha) const { return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } +bool FakeRasterBufferProviderImpl::IsPartialRasterSupported() const { + return true; +} + void FakeRasterBufferProviderImpl::Shutdown() {} } // namespace cc
diff --git a/cc/test/fake_raster_buffer_provider.h b/cc/test/fake_raster_buffer_provider.h index 00ab04a6..37738a55 100644 --- a/cc/test/fake_raster_buffer_provider.h +++ b/cc/test/fake_raster_buffer_provider.h
@@ -23,7 +23,8 @@ void ReleaseBufferForRaster(std::unique_ptr<RasterBuffer> buffer) override; void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; - bool GetResourceRequiresSwizzle(bool must_support_alpha) const override; + bool IsResourceSwizzleRequired(bool must_support_alpha) const override; + bool IsPartialRasterSupported() const override; void Shutdown() override; };
diff --git a/cc/test/layer_internals_for_test.cc b/cc/test/layer_internals_for_test.cc new file mode 100644 index 0000000..321330c --- /dev/null +++ b/cc/test/layer_internals_for_test.cc
@@ -0,0 +1,27 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/layer_internals_for_test.h" + +#include "cc/layers/layer.h" + +namespace cc { + +LayerInternalsForTest::LayerInternalsForTest(Layer* layer) : layer_(layer) {} + +void LayerInternalsForTest::OnOpacityAnimated(float opacity) { + layer_->OnOpacityAnimated(opacity); +} + +void LayerInternalsForTest::OnTransformAnimated( + const gfx::Transform& transform) { + layer_->OnTransformAnimated(transform); +} + +void LayerInternalsForTest::OnScrollOffsetAnimated( + const gfx::ScrollOffset& scroll_offset) { + layer_->OnScrollOffsetAnimated(scroll_offset); +} + +} // namespace cc
diff --git a/cc/test/layer_internals_for_test.h b/cc/test/layer_internals_for_test.h new file mode 100644 index 0000000..58fce8c --- /dev/null +++ b/cc/test/layer_internals_for_test.h
@@ -0,0 +1,28 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TEST_LAYER_INTERNALS_FOR_TEST_H_ +#define CC_TEST_LAYER_INTERNALS_FOR_TEST_H_ + +#include "base/macros.h" +#include "cc/layers/layer.h" + +namespace cc { + +// Utility class to give tests access to Layer private methods. +class LayerInternalsForTest { + public: + explicit LayerInternalsForTest(Layer* layer); + + void OnOpacityAnimated(float opacity); + void OnTransformAnimated(const gfx::Transform& transform); + void OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset); + + private: + Layer* layer_; +}; + +} // namespace cc + +#endif // CC_TEST_LAYER_INTERNALS_FOR_TEST_H_
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index b20ef02..13fc919 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc
@@ -80,10 +80,15 @@ gfx::Rect device_clip_rect = external_device_clip_rect_.IsEmpty() ? device_viewport_rect : external_device_clip_rect_; + + if (software_renderer_) { + software_renderer_->SetDisablePictureQuadImageFiltering( + disable_picture_quad_image_filtering_); + } + renderer_->DecideRenderPassAllocationsForFrame(*pass_list); renderer_->DrawFrame(pass_list, device_scale_factor, gfx::ColorSpace(), - device_viewport_rect, device_clip_rect, - disable_picture_quad_image_filtering_); + device_viewport_rect, device_clip_rect); // Wait for the readback to complete. if (output_surface_->context_provider()) @@ -182,9 +187,11 @@ main_thread_task_runner_.get(), 0, 1, delegated_sync_points_required, settings_.renderer_settings.use_gpu_memory_buffer_resources, settings_.use_image_texture_targets); - renderer_ = SoftwareRenderer::Create( - this, &settings_.renderer_settings, output_surface_.get(), - resource_provider_.get(), true /* use_image_hijack_canvas */); + std::unique_ptr<SoftwareRenderer> renderer = + SoftwareRenderer::Create(this, &settings_.renderer_settings, + output_surface_.get(), resource_provider_.get()); + software_renderer_ = renderer.get(); + renderer_ = std::move(renderer); } } // namespace cc
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h index 90f349b0..4f9eb6e 100644 --- a/cc/test/pixel_test.h +++ b/cc/test/pixel_test.h
@@ -58,6 +58,7 @@ std::unique_ptr<ResourceProvider> resource_provider_; std::unique_ptr<TextureMailboxDeleter> texture_mailbox_deleter_; std::unique_ptr<DirectRenderer> renderer_; + SoftwareRenderer* software_renderer_ = nullptr; std::unique_ptr<SkBitmap> result_bitmap_; gfx::Vector2d external_device_viewport_offset_; gfx::Rect external_device_clip_rect_; @@ -118,11 +119,7 @@ const RendererSettings* settings, OutputSurface* output_surface, ResourceProvider* resource_provider) - : SoftwareRenderer(client, - settings, - output_surface, - resource_provider, - true /* use_image_hijack_canvas */) {} + : SoftwareRenderer(client, settings, output_surface, resource_provider) {} }; class GLRendererWithFlippedSurface : public GLRenderer {
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index 3f83286..950f8f0 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc
@@ -932,7 +932,7 @@ // Get the resource. uint64_t resource_content_id = 0; Resource* resource = nullptr; - if (use_partial_raster_ && tile->invalidated_id()) { + if (UsePartialRaster() && tile->invalidated_id()) { // TODO(danakj): For resources that are in use, we should still grab them // and copy from them instead of rastering everything. crbug.com/492754 resource = @@ -1229,8 +1229,7 @@ } bool TileManager::DetermineResourceRequiresSwizzle(const Tile* tile) const { - return raster_buffer_provider_->GetResourceRequiresSwizzle( - !tile->is_opaque()); + return raster_buffer_provider_->IsResourceSwizzleRequired(!tile->is_opaque()); } std::unique_ptr<base::trace_event::ConvertableToTraceFormat> @@ -1246,6 +1245,11 @@ return std::move(state); } +bool TileManager::UsePartialRaster() const { + return use_partial_raster_ && + raster_buffer_provider_->IsPartialRasterSupported(); +} + // Utility function that can be used to create a "Task set finished" task that // posts |callback| to |task_runner| when run. scoped_refptr<TileTask> TileManager::CreateTaskSetFinishedTask(
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h index 87a8e5c..ce69a7d 100644 --- a/cc/tiles/tile_manager.h +++ b/cc/tiles/tile_manager.h
@@ -293,6 +293,8 @@ std::unique_ptr<base::trace_event::ConvertableToTraceFormat> ScheduledTasksStateAsValue() const; + bool UsePartialRaster() const; + TileManagerClient* client_; base::SequencedTaskRunner* task_runner_; ResourcePool* resource_pool_;
diff --git a/cc/trees/clip_node.cc b/cc/trees/clip_node.cc new file mode 100644 index 0000000..b5efb98f --- /dev/null +++ b/cc/trees/clip_node.cc
@@ -0,0 +1,111 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/trace_event/trace_event_argument.h" +#include "cc/base/math_util.h" +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/property_tree.pb.h" +#include "cc/trees/clip_node.h" + +namespace cc { + +ClipNode::ClipNode() + : id(-1), + parent_id(-1), + owner_id(-1), + transform_id(-1), + target_id(-1), + applies_local_clip(true), + layer_clipping_uses_only_local_clip(false), + target_is_clipped(false), + layers_are_clipped(false), + layers_are_clipped_when_surfaces_disabled(false), + resets_clip(false) {} + +ClipNode::ClipNode(const ClipNode& other) = default; + +bool ClipNode::operator==(const ClipNode& other) const { + return id == other.id && parent_id == other.parent_id && + owner_id == other.owner_id && clip == other.clip && + combined_clip_in_target_space == other.combined_clip_in_target_space && + clip_in_target_space == other.clip_in_target_space && + transform_id == other.transform_id && target_id == other.target_id && + applies_local_clip == other.applies_local_clip && + layer_clipping_uses_only_local_clip == + other.layer_clipping_uses_only_local_clip && + target_is_clipped == other.target_is_clipped && + layers_are_clipped == other.layers_are_clipped && + layers_are_clipped_when_surfaces_disabled == + other.layers_are_clipped_when_surfaces_disabled && + resets_clip == other.resets_clip; +} + +void ClipNode::ToProtobuf(proto::TreeNode* proto) const { + proto->set_id(id); + proto->set_parent_id(parent_id); + proto->set_owner_id(owner_id); + + DCHECK(!proto->has_clip_node_data()); + proto::ClipNodeData* data = proto->mutable_clip_node_data(); + + RectFToProto(clip, data->mutable_clip()); + RectFToProto(combined_clip_in_target_space, + data->mutable_combined_clip_in_target_space()); + RectFToProto(clip_in_target_space, data->mutable_clip_in_target_space()); + + data->set_transform_id(transform_id); + data->set_target_id(target_id); + data->set_applies_local_clip(applies_local_clip); + data->set_layer_clipping_uses_only_local_clip( + layer_clipping_uses_only_local_clip); + data->set_target_is_clipped(target_is_clipped); + data->set_layers_are_clipped(layers_are_clipped); + data->set_layers_are_clipped_when_surfaces_disabled( + layers_are_clipped_when_surfaces_disabled); + data->set_resets_clip(resets_clip); +} + +void ClipNode::FromProtobuf(const proto::TreeNode& proto) { + id = proto.id(); + parent_id = proto.parent_id(); + owner_id = proto.owner_id(); + + DCHECK(proto.has_clip_node_data()); + const proto::ClipNodeData& data = proto.clip_node_data(); + + clip = ProtoToRectF(data.clip()); + combined_clip_in_target_space = + ProtoToRectF(data.combined_clip_in_target_space()); + clip_in_target_space = ProtoToRectF(data.clip_in_target_space()); + + transform_id = data.transform_id(); + target_id = data.target_id(); + applies_local_clip = data.applies_local_clip(); + layer_clipping_uses_only_local_clip = + data.layer_clipping_uses_only_local_clip(); + target_is_clipped = data.target_is_clipped(); + layers_are_clipped = data.layers_are_clipped(); + layers_are_clipped_when_surfaces_disabled = + data.layers_are_clipped_when_surfaces_disabled(); + resets_clip = data.resets_clip(); +} + +void ClipNode::AsValueInto(base::trace_event::TracedValue* value) const { + value->SetInteger("id", id); + value->SetInteger("parent_id", parent_id); + value->SetInteger("owner_id", owner_id); + MathUtil::AddToTracedValue("clip", clip, value); + value->SetInteger("transform_id", transform_id); + value->SetInteger("target_id", target_id); + value->SetBoolean("applies_local_clip", applies_local_clip); + value->SetBoolean("layer_clipping_uses_only_local_clip", + layer_clipping_uses_only_local_clip); + value->SetBoolean("target_is_clipped", target_is_clipped); + value->SetBoolean("layers_are_clipped", layers_are_clipped); + value->SetBoolean("layers_are_clipped_when_surfaces_disabled", + layers_are_clipped_when_surfaces_disabled); + value->SetBoolean("resets_clip", resets_clip); +} + +} // namespace cc
diff --git a/cc/trees/clip_node.h b/cc/trees/clip_node.h new file mode 100644 index 0000000..289930b --- /dev/null +++ b/cc/trees/clip_node.h
@@ -0,0 +1,82 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_CLIP_NODE_H_ +#define CC_TREES_CLIP_NODE_H_ + +#include "cc/base/cc_export.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace base { +namespace trace_event { +class TracedValue; +} // namespace trace_event +} // namespace base + +namespace cc { + +namespace proto { +class TreeNode; +} // namespace proto + +struct CC_EXPORT ClipNode { + ClipNode(); + ClipNode(const ClipNode& other); + + int id; + int parent_id; + int owner_id; + + // The clip rect that this node contributes, expressed in the space of its + // transform node. + gfx::RectF clip; + + // Clip nodes are uses for two reasons. First, they are used for determining + // which parts of each layer are visible. Second, they are used for + // determining whether a clip needs to be applied when drawing a layer, and if + // so, the rect that needs to be used. These can be different since not all + // clips need to be applied directly to each layer. For example, a layer is + // implicitly clipped by the bounds of its target render surface and by clips + // applied to this surface. |combined_clip_in_target_space| is used for + // computing visible rects, and |clip_in_target_space| is used for computing + // clips applied at draw time. Both rects are expressed in the space of the + // target transform node, and may include clips contributed by ancestors. + gfx::RectF combined_clip_in_target_space; + gfx::RectF clip_in_target_space; + + // The id of the transform node that defines the clip node's local space. + int transform_id; + + // The id of the transform node that defines the clip node's target space. + int target_id; + + // Whether this node contributes a new clip (that is, whether |clip| needs to + // be applied), rather than only inheriting ancestor clips. + bool applies_local_clip : 1; + + // When true, |clip_in_target_space| does not include clips from ancestor + // nodes. + bool layer_clipping_uses_only_local_clip : 1; + + // True if target surface needs to be drawn with a clip applied. + bool target_is_clipped : 1; + + // True if layers with this clip tree node need to be drawn with a clip + // applied. + bool layers_are_clipped : 1; + bool layers_are_clipped_when_surfaces_disabled : 1; + + // Nodes that correspond to unclipped surfaces disregard ancestor clips. + bool resets_clip : 1; + + bool operator==(const ClipNode& other) const; + + void ToProtobuf(proto::TreeNode* proto) const; + void FromProtobuf(const proto::TreeNode& proto); + void AsValueInto(base::trace_event::TracedValue* value) const; +}; + +} // namespace cc + +#endif // CC_TREES_CLIP_NODE_H_
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index f2c7022..612c9a9 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -12,10 +12,13 @@ #include "cc/layers/draw_properties.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" +#include "cc/trees/clip_node.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree.h" #include "cc/trees/property_tree_builder.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc { @@ -46,45 +49,89 @@ layer->effect_tree_index()); if (effect_node->owner_id != layer->id()) return; - DCHECK_EQ(effect_node->data.mask_layer_id, -1) << "layer: " << layer->id(); - DCHECK_EQ(effect_node->data.replica_layer_id, -1) << "layer: " << layer->id(); - DCHECK(effect_node->data.background_filters.IsEmpty()); + DCHECK_EQ(effect_node->mask_layer_id, -1) << "layer: " << layer->id(); + DCHECK_EQ(effect_node->replica_layer_id, -1) << "layer: " << layer->id(); + DCHECK(effect_node->background_filters.IsEmpty()); } #endif +static void AddSublayerScaleToTransform(const int effect_node_id, + const EffectTree& effect_tree, + gfx::Transform* transform) { + const EffectNode* effect_node = effect_tree.Node(effect_node_id); + const EffectNode* target_effect_node = + effect_node->has_render_surface + ? effect_node + : effect_tree.Node(effect_node->target_id); + transform->matrix().postScale(target_effect_node->sublayer_scale.x(), + target_effect_node->sublayer_scale.y(), 1.f); +} + +#if DCHECK_IS_ON() +void VerifySublayerScalesMatch(const int effect_node_id, + const int target_transform_id, + const EffectTree& effect_tree, + const TransformTree& transform_tree) { + const TransformNode* target_transform_node = + transform_tree.Node(target_transform_id); + const EffectNode* effect_node = effect_tree.Node(effect_node_id); + const EffectNode* target_effect_node = + effect_node->has_render_surface + ? effect_node + : effect_tree.Node(effect_node->target_id); + DCHECK(target_transform_node->sublayer_scale == + target_effect_node->sublayer_scale) + << " sublayer scale from transform tree: " + << target_transform_node->sublayer_scale.ToString() + << " sublayer scale from effect tree: " + << target_effect_node->sublayer_scale.ToString(); +} +#endif + template <typename LayerType> bool ComputeClipRectInTargetSpace(const LayerType* layer, const ClipNode* clip_node, const TransformTree& transform_tree, + const EffectTree& effect_tree, int target_node_id, gfx::RectF* clip_rect_in_target_space) { DCHECK(layer->clip_tree_index() == clip_node->id); - DCHECK(clip_node->data.target_id != target_node_id); + DCHECK(clip_node->target_id != target_node_id); gfx::Transform clip_to_target; - if (clip_node->data.target_id > target_node_id) { + if (clip_node->target_id > target_node_id) { // In this case, layer has a scroll parent. We need to keep the scale // at the layer's target but remove the scale at the scroll parent's // target. - if (transform_tree.ComputeTransformWithDestinationSublayerScale( - clip_node->data.target_id, target_node_id, &clip_to_target)) { + if (transform_tree.ComputeTransform(clip_node->target_id, target_node_id, + &clip_to_target)) { + // We don't have to apply sublayer scale when target is root. + if (target_node_id != 0) { + AddSublayerScaleToTransform(layer->effect_tree_index(), effect_tree, + &clip_to_target); +#if DCHECK_IS_ON() + VerifySublayerScalesMatch(layer->effect_tree_index(), target_node_id, + effect_tree, transform_tree); +#endif + } + const TransformNode* source_node = - transform_tree.Node(clip_node->data.target_id); - if (source_node->data.sublayer_scale.x() != 0.f && - source_node->data.sublayer_scale.y() != 0.f) - clip_to_target.Scale(1.0f / source_node->data.sublayer_scale.x(), - 1.0f / source_node->data.sublayer_scale.y()); + transform_tree.Node(clip_node->target_id); + if (source_node->sublayer_scale.x() != 0.f && + source_node->sublayer_scale.y() != 0.f) + clip_to_target.Scale(1.0f / source_node->sublayer_scale.x(), + 1.0f / source_node->sublayer_scale.y()); *clip_rect_in_target_space = MathUtil::MapClippedRect( - clip_to_target, clip_node->data.clip_in_target_space); + clip_to_target, clip_node->clip_in_target_space); } else { return false; } } else { - if (transform_tree.ComputeTransform(clip_node->data.target_id, - target_node_id, &clip_to_target)) { + if (transform_tree.ComputeTransform(clip_node->target_id, target_node_id, + &clip_to_target)) { *clip_rect_in_target_space = MathUtil::ProjectClippedRect( - clip_to_target, clip_node->data.clip_in_target_space); + clip_to_target, clip_node->clip_in_target_space); } else { return false; } @@ -138,14 +185,14 @@ static ConditionalClip ComputeCurrentClip(const ClipNode* clip_node, const TransformTree& transform_tree, int target_transform_id) { - if (clip_node->data.transform_id != target_transform_id) - return ComputeLocalRectInTargetSpace(clip_node->data.clip, transform_tree, - clip_node->data.transform_id, + if (clip_node->transform_id != target_transform_id) + return ComputeLocalRectInTargetSpace(clip_node->clip, transform_tree, + clip_node->transform_id, target_transform_id); - gfx::RectF current_clip = clip_node->data.clip; + gfx::RectF current_clip = clip_node->clip; gfx::Vector2dF sublayer_scale = - transform_tree.Node(target_transform_id)->data.sublayer_scale; + transform_tree.Node(target_transform_id)->sublayer_scale; if (sublayer_scale.x() > 0 && sublayer_scale.y() > 0) current_clip.Scale(sublayer_scale.x(), sublayer_scale.y()); return ConditionalClip{true /* is_clipped */, current_clip}; @@ -159,7 +206,7 @@ const TransformTree& transform_tree) { const ClipNode* clip_node = clip_tree.Node(local_clip_id); const EffectNode* target_node = effect_tree.Node(target_id); - int target_transform_id = target_node->data.transform_id; + int target_transform_id = target_node->transform_id; bool is_clipped = false; // Collect all the clips that need to be accumulated. @@ -168,17 +215,17 @@ // If target is not direct ancestor of clip, this will find least common // ancestor between the target and the clip. while (target_node->id >= 0 && clip_node->id >= 0) { - while (target_node->data.clip_id > clip_node->id || - target_node->data.has_unclipped_descendants) { - target_node = effect_tree.Node(target_node->data.target_id); + while (target_node->clip_id > clip_node->id || + target_node->has_unclipped_descendants) { + target_node = effect_tree.Node(target_node->target_id); } - if (target_node->data.clip_id == clip_node->id) + if (target_node->clip_id == clip_node->id) break; - while (target_node->data.clip_id < clip_node->id) { + while (target_node->clip_id < clip_node->id) { parent_chain.push(clip_node); clip_node = clip_tree.parent(clip_node); } - if (target_node->data.clip_id == clip_node->id) { + if (target_node->clip_id == clip_node->id) { // Target is responsible for applying this clip_node (id equals to // target_node's clip id), no need to accumulate this as part of clip // rect. @@ -190,12 +237,12 @@ // TODO(weiliangc): If we don't create clip for render surface, we don't need // to check applies_local_clip. - while (!clip_node->data.applies_local_clip && parent_chain.size() > 0) { + while (!clip_node->applies_local_clip && parent_chain.size() > 0) { clip_node = parent_chain.top(); parent_chain.pop(); } - if (!clip_node->data.applies_local_clip) + if (!clip_node->applies_local_clip) // No clip node applying clip in between. return ConditionalClip{false, gfx::RectF()}; @@ -207,7 +254,7 @@ while (parent_chain.size() > 0) { clip_node = parent_chain.top(); parent_chain.pop(); - if (!clip_node->data.applies_local_clip) { + if (!clip_node->applies_local_clip) { continue; } ConditionalClip current_clip = @@ -237,14 +284,14 @@ const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); if (!non_root_surfaces_enabled) { layer->set_clip_rect( - gfx::ToEnclosingRect(clip_node->data.clip_in_target_space)); + gfx::ToEnclosingRect(clip_node->clip_in_target_space)); continue; } // When both the layer and the target are unclipped, the entire layer // content rect is visible. - const bool fully_visible = !clip_node->data.layers_are_clipped && - !clip_node->data.target_is_clipped; + const bool fully_visible = + !clip_node->layers_are_clipped && !clip_node->target_is_clipped; if (!fully_visible) { const TransformNode* transform_node = @@ -252,22 +299,21 @@ int target_node_id = transform_tree.ContentTargetId(transform_node->id); // The clip node stores clip rect in its target space. - gfx::RectF clip_rect_in_target_space = - clip_node->data.clip_in_target_space; + gfx::RectF clip_rect_in_target_space = clip_node->clip_in_target_space; // If required, this clip rect should be mapped to the current layer's // target space. - if (clip_node->data.target_id != target_node_id) { + if (clip_node->target_id != target_node_id) { // In this case, layer has a clip parent or scroll parent (or shares the // target with an ancestor layer that has clip parent) and the clip // parent's target is different from the layer's target. As the layer's // target has unclippped descendants, it is unclippped. - if (!clip_node->data.layers_are_clipped) + if (!clip_node->layers_are_clipped) continue; // Compute the clip rect in target space and store it. if (!ComputeClipRectInTargetSpace(layer, clip_node, transform_tree, - target_node_id, + effect_tree, target_node_id, &clip_rect_in_target_space)) continue; } @@ -284,21 +330,23 @@ bool GetLayerClipRect(const scoped_refptr<Layer> layer, const ClipNode* clip_node, const TransformTree& transform_tree, + const EffectTree& effect_tree, int target_node_id, gfx::RectF* clip_rect_in_target_space) { return ComputeClipRectInTargetSpace(layer.get(), clip_node, transform_tree, - target_node_id, + effect_tree, target_node_id, clip_rect_in_target_space); } bool GetLayerClipRect(const LayerImpl* layer, const ClipNode* clip_node, const TransformTree& transform_tree, + const EffectTree& effect_tree, int target_node_id, gfx::RectF* clip_rect_in_target_space) { // This is equivalent of calling ComputeClipRectInTargetSpace. *clip_rect_in_target_space = gfx::RectF(layer->clip_rect()); - return transform_tree.Node(target_node_id)->data.ancestors_are_invertible; + return transform_tree.Node(target_node_id)->ancestors_are_invertible; } template <typename LayerType> @@ -330,7 +378,7 @@ effect_tree.Node(effect_ancestor_with_copy_request); ConditionalClip clip_in_layer_space = ComputeTargetRectInLocalSpace( accumulated_clip_in_copy_request_space, transform_tree, - copy_request_effect_node->data.transform_id, + copy_request_effect_node->transform_id, layer->transform_tree_index()); if (clip_in_layer_space.is_clipped) { @@ -351,9 +399,9 @@ if (!non_root_surfaces_enabled) { // When we only have a root surface, the clip node and the layer must // necessarily have the same target (the root). - if (transform_node->data.ancestors_are_invertible) { + if (transform_node->ancestors_are_invertible) { gfx::RectF combined_clip_rect_in_target_space = - clip_node->data.combined_clip_in_target_space; + clip_node->combined_clip_in_target_space; gfx::Transform target_to_content; target_to_content.Translate(-layer->offset_to_transform_parent().x(), -layer->offset_to_transform_parent().y()); @@ -373,8 +421,8 @@ // When both the layer and the target are unclipped, the entire layer // content rect is visible. - const bool fully_visible = !clip_node->data.layers_are_clipped && - !clip_node->data.target_is_clipped; + const bool fully_visible = + !clip_node->layers_are_clipped && !clip_node->target_is_clipped; if (fully_visible) { layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); @@ -387,12 +435,12 @@ // this clip rect should be mapped to the current layer's target space. gfx::RectF combined_clip_rect_in_target_space; - if (clip_node->data.target_id != target_node_id) { + if (clip_node->target_id != target_node_id) { // In this case, layer has a clip parent or scroll parent (or shares the // target with an ancestor layer that has clip parent) and the clip // parent's target is different from the layer's target. As the layer's // target has unclippped descendants, it is unclippped. - if (!clip_node->data.layers_are_clipped) { + if (!clip_node->layers_are_clipped) { layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); continue; } @@ -403,18 +451,18 @@ // the combined clip has even the clip parent's target's clip baked into // it and as our target is different, we don't want to use it in our // visible rect computation. - if (!GetLayerClipRect(layer, clip_node, transform_tree, target_node_id, + if (!GetLayerClipRect(layer, clip_node, transform_tree, effect_tree, + target_node_id, &combined_clip_rect_in_target_space)) { layer->set_visible_layer_rect(gfx::Rect(layer_bounds)); continue; } } else { - if (clip_node->data.target_is_clipped) { + if (clip_node->target_is_clipped) { combined_clip_rect_in_target_space = - clip_node->data.combined_clip_in_target_space; + clip_node->combined_clip_in_target_space; } else { - combined_clip_rect_in_target_space = - clip_node->data.clip_in_target_space; + combined_clip_rect_in_target_space = clip_node->clip_in_target_space; } } @@ -443,7 +491,7 @@ } gfx::Transform target_to_layer; - if (transform_node->data.ancestors_are_invertible) { + if (transform_node->ancestors_are_invertible) { target_to_layer = transform_tree.FromTarget(transform_node->id); } else { if (!transform_tree.ComputeTransformWithSourceSublayerScale( @@ -471,7 +519,7 @@ static bool HasSingularTransform(int transform_tree_index, const TransformTree& tree) { const TransformNode* node = tree.Node(transform_tree_index); - return !node->data.is_invertible || !node->data.ancestors_are_invertible; + return !node->is_invertible || !node->ancestors_are_invertible; } template <typename LayerType> @@ -489,7 +537,7 @@ const TransformTree& tree) { const TransformNode* node = tree.Node(transform_tree_index); return layer->use_local_transform_for_backface_visibility() - ? node->data.local.IsBackFaceVisible() + ? node->local.IsBackFaceVisible() : tree.ToTarget(transform_tree_index).IsBackFaceVisible(); } @@ -497,7 +545,7 @@ int transform_tree_index, const TransformTree& tree) { const TransformNode* node = tree.Node(transform_tree_index); - return !node->data.to_screen_is_potentially_animated; + return !node->to_screen_is_potentially_animated; } static inline bool TransformToScreenIsKnown(LayerImpl* layer, @@ -554,7 +602,7 @@ std::vector<LayerImpl*>* visible_layer_list) { for (auto* layer_impl : *layer_tree_impl) { bool layer_is_drawn = - effect_tree.Node(layer_impl->effect_tree_index())->data.is_drawn; + effect_tree.Node(layer_impl->effect_tree_index())->is_drawn; if (!IsRootLayer(layer_impl) && LayerShouldBeSkipped(layer_impl, layer_is_drawn, transform_tree, @@ -576,7 +624,7 @@ EffectNode* node = effect_tree->Node(layer->effect_tree_index()); - if (node->owner_id == layer->id() && node->data.has_render_surface) + if (node->owner_id == layer->id() && node->has_render_surface) layer->SetHasRenderSurface(true); else layer->SetHasRenderSurface(false); @@ -593,16 +641,15 @@ transform_tree.Node(layer->transform_tree_index()); const EffectNode* effect_node = effect_tree.Node(layer->effect_tree_index()); - if (effect_node->data.has_render_surface && - effect_node->data.num_copy_requests_in_subtree > 0) + if (effect_node->has_render_surface && + effect_node->num_copy_requests_in_subtree > 0) return false; // If the layer transform is not invertible, it should be skipped. // TODO(ajuma): Correctly process subtrees with singular transform for the // case where we may animate to a non-singular transform and wish to // pre-raster. - return !transform_node->data.node_and_ancestors_are_animated_or_invertible || - effect_node->data.hidden_by_backface_visibility || - !effect_node->data.is_drawn; + return !transform_node->node_and_ancestors_are_animated_or_invertible || + effect_node->hidden_by_backface_visibility || !effect_node->is_drawn; } bool LayerShouldBeSkipped(LayerImpl* layer, @@ -627,7 +674,7 @@ LayerList* update_layer_list) { for (auto* layer : *layer_tree_host) { bool layer_is_drawn = - effect_tree.Node(layer->effect_tree_index())->data.is_drawn; + effect_tree.Node(layer->effect_tree_index())->is_drawn; if (!IsRootLayer(layer) && LayerShouldBeSkipped(layer, layer_is_drawn, transform_tree, @@ -665,18 +712,18 @@ ClipNode* clip_node = clip_tree->Node(i); if (clip_node->id == 1) { - ResetIfHasNanCoordinate(&clip_node->data.clip); - clip_node->data.clip_in_target_space = clip_node->data.clip; - clip_node->data.combined_clip_in_target_space = clip_node->data.clip; + ResetIfHasNanCoordinate(&clip_node->clip); + clip_node->clip_in_target_space = clip_node->clip; + clip_node->combined_clip_in_target_space = clip_node->clip; continue; } const TransformNode* transform_node = - transform_tree.Node(clip_node->data.transform_id); + transform_tree.Node(clip_node->transform_id); ClipNode* parent_clip_node = clip_tree->parent(clip_node); gfx::Transform parent_to_current; const TransformNode* parent_target_transform_node = - transform_tree.Node(parent_clip_node->data.target_id); + transform_tree.Node(parent_clip_node->target_id); bool success = true; // Clips must be combined in target space. We cannot, for example, combine @@ -690,110 +737,105 @@ // target space. So, we need to get the ancestor clip rect in the current // clip node's target space. gfx::RectF parent_combined_clip_in_target_space = - parent_clip_node->data.combined_clip_in_target_space; + parent_clip_node->combined_clip_in_target_space; gfx::RectF parent_clip_in_target_space = - parent_clip_node->data.clip_in_target_space; + parent_clip_node->clip_in_target_space; if (parent_target_transform_node && - parent_target_transform_node->id != clip_node->data.target_id && + parent_target_transform_node->id != clip_node->target_id && non_root_surfaces_enabled) { success &= transform_tree.ComputeTransformWithDestinationSublayerScale( - parent_target_transform_node->id, clip_node->data.target_id, + parent_target_transform_node->id, clip_node->target_id, &parent_to_current); - if (parent_target_transform_node->data.sublayer_scale.x() > 0 && - parent_target_transform_node->data.sublayer_scale.y() > 0) + if (parent_target_transform_node->sublayer_scale.x() > 0 && + parent_target_transform_node->sublayer_scale.y() > 0) parent_to_current.Scale( - 1.f / parent_target_transform_node->data.sublayer_scale.x(), - 1.f / parent_target_transform_node->data.sublayer_scale.y()); + 1.f / parent_target_transform_node->sublayer_scale.x(), + 1.f / parent_target_transform_node->sublayer_scale.y()); // If we can't compute a transform, it's because we had to use the inverse // of a singular transform. We won't draw in this case, so there's no need // to compute clips. if (!success) continue; parent_combined_clip_in_target_space = MathUtil::ProjectClippedRect( - parent_to_current, - parent_clip_node->data.combined_clip_in_target_space); + parent_to_current, parent_clip_node->combined_clip_in_target_space); parent_clip_in_target_space = MathUtil::ProjectClippedRect( - parent_to_current, parent_clip_node->data.clip_in_target_space); + parent_to_current, parent_clip_node->clip_in_target_space); } // Only nodes affected by ancestor clips will have their clip adjusted due // to intersecting with an ancestor clip. But, we still need to propagate // the combined clip to our children because if they are clipped, they may // need to clip using our parent clip and if we don't propagate it here, // it will be lost. - if (clip_node->data.resets_clip && non_root_surfaces_enabled) { - if (clip_node->data.applies_local_clip) { - clip_node->data.clip_in_target_space = MathUtil::MapClippedRect( - transform_tree.ToTarget(clip_node->data.transform_id), - clip_node->data.clip); - ResetIfHasNanCoordinate(&clip_node->data.clip_in_target_space); - clip_node->data.combined_clip_in_target_space = - gfx::IntersectRects(clip_node->data.clip_in_target_space, + if (clip_node->resets_clip && non_root_surfaces_enabled) { + if (clip_node->applies_local_clip) { + clip_node->clip_in_target_space = MathUtil::MapClippedRect( + transform_tree.ToTarget(clip_node->transform_id), clip_node->clip); + ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); + clip_node->combined_clip_in_target_space = + gfx::IntersectRects(clip_node->clip_in_target_space, parent_combined_clip_in_target_space); } else { - DCHECK(!clip_node->data.target_is_clipped); - DCHECK(!clip_node->data.layers_are_clipped); - clip_node->data.combined_clip_in_target_space = + DCHECK(!clip_node->target_is_clipped); + DCHECK(!clip_node->layers_are_clipped); + clip_node->combined_clip_in_target_space = parent_combined_clip_in_target_space; } - ResetIfHasNanCoordinate(&clip_node->data.combined_clip_in_target_space); + ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); continue; } - bool use_only_parent_clip = !clip_node->data.applies_local_clip; + bool use_only_parent_clip = !clip_node->applies_local_clip; if (use_only_parent_clip) { - clip_node->data.combined_clip_in_target_space = + clip_node->combined_clip_in_target_space = parent_combined_clip_in_target_space; if (!non_root_surfaces_enabled) { - clip_node->data.clip_in_target_space = - parent_clip_node->data.clip_in_target_space; - } else if (!clip_node->data.target_is_clipped) { - clip_node->data.clip_in_target_space = parent_clip_in_target_space; + clip_node->clip_in_target_space = + parent_clip_node->clip_in_target_space; + } else if (!clip_node->target_is_clipped) { + clip_node->clip_in_target_space = parent_clip_in_target_space; } else { // Render Surface applies clip and the owning layer itself applies // no clip. So, clip_in_target_space is not used and hence we can set // it to an empty rect. - clip_node->data.clip_in_target_space = gfx::RectF(); + clip_node->clip_in_target_space = gfx::RectF(); } } else { gfx::Transform source_to_target; if (!non_root_surfaces_enabled) { - source_to_target = - transform_tree.ToScreen(clip_node->data.transform_id); + source_to_target = transform_tree.ToScreen(clip_node->transform_id); } else if (transform_tree.ContentTargetId(transform_node->id) == - clip_node->data.target_id) { - source_to_target = - transform_tree.ToTarget(clip_node->data.transform_id); + clip_node->target_id) { + source_to_target = transform_tree.ToTarget(clip_node->transform_id); } else { success = transform_tree.ComputeTransformWithDestinationSublayerScale( - transform_node->id, clip_node->data.target_id, &source_to_target); + transform_node->id, clip_node->target_id, &source_to_target); // source_to_target computation should be successful as target is an // ancestor of the transform node. DCHECK(success); } gfx::RectF source_clip_in_target_space = - MathUtil::MapClippedRect(source_to_target, clip_node->data.clip); + MathUtil::MapClippedRect(source_to_target, clip_node->clip); // With surfaces disabled, the only case where we use only the local clip // for layer clipping is the case where no non-viewport ancestor node // applies a local clip. bool layer_clipping_uses_only_local_clip = non_root_surfaces_enabled - ? clip_node->data.layer_clipping_uses_only_local_clip - : !parent_clip_node->data - .layers_are_clipped_when_surfaces_disabled; + ? clip_node->layer_clipping_uses_only_local_clip + : !parent_clip_node->layers_are_clipped_when_surfaces_disabled; if (!layer_clipping_uses_only_local_clip) { - clip_node->data.clip_in_target_space = gfx::IntersectRects( + clip_node->clip_in_target_space = gfx::IntersectRects( parent_clip_in_target_space, source_clip_in_target_space); } else { - clip_node->data.clip_in_target_space = source_clip_in_target_space; + clip_node->clip_in_target_space = source_clip_in_target_space; } - clip_node->data.combined_clip_in_target_space = gfx::IntersectRects( + clip_node->combined_clip_in_target_space = gfx::IntersectRects( parent_combined_clip_in_target_space, source_clip_in_target_space); } - ResetIfHasNanCoordinate(&clip_node->data.clip_in_target_space); - ResetIfHasNanCoordinate(&clip_node->data.combined_clip_in_target_space); + ResetIfHasNanCoordinate(&clip_node->clip_in_target_space); + ResetIfHasNanCoordinate(&clip_node->combined_clip_in_target_space); } clip_tree->set_needs_update(false); } @@ -812,13 +854,13 @@ EffectNode* node = effect_tree->Node(i); if (i == 1) { // Render target on the first effect node is root. - node->data.target_id = 0; + node->target_id = 0; } else if (!can_render_to_separate_surface) { - node->data.target_id = 1; - } else if (effect_tree->parent(node)->data.has_render_surface) { - node->data.target_id = node->parent_id; + node->target_id = 1; + } else if (effect_tree->parent(node)->has_render_surface) { + node->target_id = node->parent_id; } else { - node->data.target_id = effect_tree->parent(node)->data.target_id; + node->target_id = effect_tree->parent(node)->target_id; } } } @@ -837,9 +879,9 @@ const TransformTree* transform_tree = &property_trees->transform_tree; EffectNode* root_effect_node = effect_tree->Node(1); const RenderSurfaceImpl* root_render_surface = - root_effect_node->data.render_surface; - gfx::Rect root_clip = gfx::ToEnclosingRect( - clip_tree->Node(root_effect_node->data.clip_id)->data.clip); + root_effect_node->render_surface; + gfx::Rect root_clip = + gfx::ToEnclosingRect(clip_tree->Node(root_effect_node->clip_id)->clip); if (root_render_surface->is_clipped()) DCHECK(root_clip == root_render_surface->clip_rect()) << "clip on root render surface: " @@ -847,13 +889,12 @@ << " v.s. root effect node's clip: " << root_clip.ToString(); for (int i = 2; i < static_cast<int>(effect_tree->size()); ++i) { EffectNode* effect_node = effect_tree->Node(i); - const EffectNode* target_node = - effect_tree->Node(effect_node->data.target_id); + const EffectNode* target_node = effect_tree->Node(effect_node->target_id); ConditionalClip accumulated_clip_rect = - ComputeAccumulatedClip(*clip_tree, effect_node->data.clip_id, - *effect_tree, target_node->id, *transform_tree); + ComputeAccumulatedClip(*clip_tree, effect_node->clip_id, *effect_tree, + target_node->id, *transform_tree); gfx::RectF accumulated_clip = accumulated_clip_rect.clip_rect; - const RenderSurfaceImpl* render_surface = effect_node->data.render_surface; + const RenderSurfaceImpl* render_surface = effect_node->render_surface; if (render_surface && render_surface->is_clipped()) { DCHECK(gfx::ToEnclosingRect(accumulated_clip) == render_surface->clip_rect()) @@ -872,9 +913,9 @@ const TransformTree* transform_tree = &property_trees->transform_tree; const EffectNode* effect_node = effect_tree->Node(layer->effect_tree_index()); const EffectNode* target_node = - effect_node->data.has_render_surface + effect_node->has_render_surface ? effect_node - : effect_tree->Node(effect_node->data.target_id); + : effect_tree->Node(effect_node->target_id); // TODO(weiliangc): When effect node has up to date render surface info on // compositor thread, no need to check for resourceless draw mode if (!property_trees->non_root_surfaces_enabled) { @@ -889,15 +930,15 @@ if ((!property_trees->non_root_surfaces_enabled && clip_tree->Node(layer->clip_tree_index()) - ->data.layers_are_clipped_when_surfaces_disabled) || - clip_tree->Node(layer->clip_tree_index())->data.layers_are_clipped) { + ->layers_are_clipped_when_surfaces_disabled) || + clip_tree->Node(layer->clip_tree_index())->layers_are_clipped) { DCHECK(layer->clip_rect() == gfx::ToEnclosingRect(accumulated_clip)) << " layer: " << layer->id() << " clip id: " << layer->clip_tree_index() << " layer clip: " << layer->clip_rect().ToString() << " v.s. " << gfx::ToEnclosingRect(accumulated_clip).ToString() << " and clip node clip: " - << gfx::ToEnclosingRect(clip_tree->Node(layer->clip_tree_index()) - ->data.clip_in_target_space) + << gfx::ToEnclosingRect( + clip_tree->Node(layer->clip_tree_index())->clip_in_target_space) .ToString(); } } @@ -906,10 +947,10 @@ const EffectTree& effect_tree, const int effect_tree_index) { const EffectNode* node = effect_tree.Node(effect_tree_index); - if (node->data.has_render_surface) - return node->data.transform_id; - node = effect_tree.Node(node->data.target_id); - return node->data.transform_id; + if (node->has_render_surface) + return node->transform_id; + node = effect_tree.Node(node->target_id); + return node->transform_id; } static void VerifyDrawTransformsMatch(LayerImpl* layer, @@ -917,17 +958,19 @@ const int source_id = layer->transform_tree_index(); int destination_id = FindTargetTransformTreeIndexFromEffectTree( property_trees->effect_tree, layer->effect_tree_index()); - // TODO(jaydasika) : Remove this after sorting out how sublayer scale works - // for these ids. - if (destination_id == 0 || destination_id == 1) - return; gfx::Transform draw_transform; property_trees->transform_tree.ComputeTransform(source_id, destination_id, &draw_transform); - TransformNode* target_node = - property_trees->transform_tree.Node(destination_id); - draw_transform.matrix().postScale(target_node->data.sublayer_scale.x(), - target_node->data.sublayer_scale.y(), 1.f); + // We don't have to apply sublayer scale when target is root. + if (destination_id != 0) { + AddSublayerScaleToTransform(layer->effect_tree_index(), + property_trees->effect_tree, &draw_transform); +#if DCHECK_IS_ON() + VerifySublayerScalesMatch(layer->effect_tree_index(), destination_id, + property_trees->effect_tree, + property_trees->transform_tree); +#endif + } if (layer->should_flatten_transform_from_property_tree()) draw_transform.FlattenTo2d(); draw_transform.Translate(layer->offset_to_transform_parent().x(), @@ -1049,7 +1092,7 @@ EffectNode* node = property_trees->effect_tree.Node(layer->effect_tree_index()); if (node->owner_id == layer->id()) - node->data.render_surface = layer->render_surface(); + node->render_surface = layer->render_surface(); #if DCHECK_IS_ON() if (can_render_to_separate_surface) ValidateRenderSurfaceForLayer(layer); @@ -1088,28 +1131,44 @@ layer->offset_to_transform_parent().y()); } else { // Surfaces need to apply their sublayer scale. - xform.Scale(node->data.sublayer_scale.x(), node->data.sublayer_scale.y()); + xform.Scale(node->sublayer_scale.x(), node->sublayer_scale.y()); } return xform; } -static void SetSurfaceDrawTransform(const TransformTree& tree, +static void SetSurfaceDrawTransform(const TransformTree& transform_tree, + const EffectTree& effect_tree, RenderSurfaceImpl* render_surface) { - const TransformNode* node = tree.Node(render_surface->TransformTreeIndex()); + const TransformNode* transform_node = + transform_tree.Node(render_surface->TransformTreeIndex()); + const EffectNode* effect_node = + effect_tree.Node(render_surface->EffectTreeIndex()); // The draw transform of root render surface is identity tranform. - if (node->id == 1) { + if (transform_node->id == 1) { render_surface->SetDrawTransform(gfx::Transform()); return; } gfx::Transform render_surface_transform; - const TransformNode* target_node = tree.Node(tree.TargetId(node->id)); - tree.ComputeTransformWithDestinationSublayerScale(node->id, target_node->id, - &render_surface_transform); - if (node->data.sublayer_scale.x() != 0.0 && - node->data.sublayer_scale.y() != 0.0) - render_surface_transform.Scale(1.0 / node->data.sublayer_scale.x(), - 1.0 / node->data.sublayer_scale.y()); + const TransformNode* target_transform_node = + transform_tree.Node(transform_tree.TargetId(transform_node->id)); + transform_tree.ComputeTransform(transform_node->id, target_transform_node->id, + &render_surface_transform); + // We don't have to apply sublayer scale when target is root. + if (target_transform_node->id != 0) { + AddSublayerScaleToTransform(effect_node->target_id, effect_tree, + &render_surface_transform); +#if DCHECK_IS_ON() + VerifySublayerScalesMatch(effect_node->target_id, target_transform_node->id, + effect_tree, transform_tree); +#endif + } + + DCHECK(transform_node->sublayer_scale == effect_node->sublayer_scale); + if (effect_node->sublayer_scale.x() != 0.0 && + effect_node->sublayer_scale.y() != 0.0) + render_surface_transform.Scale(1.0 / effect_node->sublayer_scale.x(), + 1.0 / effect_node->sublayer_scale.y()); render_surface->SetDrawTransform(render_surface_transform); } @@ -1118,7 +1177,7 @@ DCHECK(render_surface->OwningLayerId() == clip_node->owner_id) << "we now create clip node for every render surface"; - render_surface->SetIsClipped(clip_node->data.target_is_clipped); + render_surface->SetIsClipped(clip_node->target_is_clipped); } static void SetSurfaceClipRect(const ClipNode* parent_clip_node, @@ -1132,9 +1191,9 @@ const TransformNode* transform_node = transform_tree.Node(render_surface->TransformTreeIndex()); if (transform_tree.TargetId(transform_node->id) == - parent_clip_node->data.target_id) { + parent_clip_node->target_id) { render_surface->SetClipRect( - gfx::ToEnclosingRect(parent_clip_node->data.clip_in_target_space)); + gfx::ToEnclosingRect(parent_clip_node->clip_in_target_space)); return; } @@ -1144,7 +1203,7 @@ gfx::Transform clip_parent_target_to_target; const bool success = transform_tree.ComputeTransformWithDestinationSublayerScale( - parent_clip_node->data.target_id, + parent_clip_node->target_id, transform_tree.TargetId(transform_node->id), &clip_parent_target_to_target); @@ -1153,11 +1212,10 @@ return; } - DCHECK_LT(parent_clip_node->data.target_id, + DCHECK_LT(parent_clip_node->target_id, transform_tree.TargetId(transform_node->id)); render_surface->SetClipRect(gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - clip_parent_target_to_target, - parent_clip_node->data.clip_in_target_space))); + clip_parent_target_to_target, parent_clip_node->clip_in_target_space))); } template <typename LayerType> @@ -1206,7 +1264,7 @@ // (included) and its target surface (excluded). const EffectNode* node = tree.Node(render_surface->EffectTreeIndex()); float draw_opacity = tree.EffectiveOpacity(node); - for (node = tree.parent(node); node && !node->data.has_render_surface; + for (node = tree.parent(node); node && !node->has_render_surface; node = tree.parent(node)) { draw_opacity *= tree.EffectiveOpacity(node); } @@ -1232,8 +1290,8 @@ const LayerImpl* replica_layer = render_surface->ReplicaLayer(); const TransformNode* surface_transform_node = tree.Node(render_surface->TransformTreeIndex()); - replica_to_surface.Scale(surface_transform_node->data.sublayer_scale.x(), - surface_transform_node->data.sublayer_scale.y()); + replica_to_surface.Scale(surface_transform_node->sublayer_scale.x(), + surface_transform_node->sublayer_scale.y()); replica_to_surface.Translate(replica_layer->offset_to_transform_parent().x(), replica_layer->offset_to_transform_parent().y()); gfx::Transform replica_transform_node_to_surface; @@ -1241,11 +1299,10 @@ render_surface->TransformTreeIndex(), &replica_transform_node_to_surface); replica_to_surface.PreconcatTransform(replica_transform_node_to_surface); - if (surface_transform_node->data.sublayer_scale.x() != 0 && - surface_transform_node->data.sublayer_scale.y() != 0) { - replica_to_surface.Scale( - 1.0 / surface_transform_node->data.sublayer_scale.x(), - 1.0 / surface_transform_node->data.sublayer_scale.y()); + if (surface_transform_node->sublayer_scale.x() != 0 && + surface_transform_node->sublayer_scale.y() != 0) { + replica_to_surface.Scale(1.0 / surface_transform_node->sublayer_scale.x(), + 1.0 / surface_transform_node->sublayer_scale.y()); } return replica_to_surface; } @@ -1267,15 +1324,15 @@ layer->draw_properties().screen_space_transform; } layer->draw_properties().screen_space_transform_is_animating = - transform_node->data.to_screen_is_potentially_animated; + transform_node->to_screen_is_potentially_animated; layer->draw_properties().opacity = LayerDrawOpacity(layer, property_trees->effect_tree); if (property_trees->non_root_surfaces_enabled) { - layer->draw_properties().is_clipped = clip_node->data.layers_are_clipped; + layer->draw_properties().is_clipped = clip_node->layers_are_clipped; } else { layer->draw_properties().is_clipped = - clip_node->data.layers_are_clipped_when_surfaces_disabled; + clip_node->layers_are_clipped_when_surfaces_disabled; } gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect( @@ -1303,7 +1360,8 @@ SetSurfaceIsClipped(clip_node, render_surface); SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); - SetSurfaceDrawTransform(property_trees->transform_tree, render_surface); + SetSurfaceDrawTransform(property_trees->transform_tree, + property_trees->effect_tree, render_surface); render_surface->SetScreenSpaceTransform( property_trees->transform_tree.ToScreenSpaceTransformWithoutSublayerScale( render_surface->TransformTreeIndex())); @@ -1358,15 +1416,14 @@ // When the page scale layer is also the root layer, the node should also // store the combined scale factor and not just the page scale factor. float post_local_scale_factor = page_scale_factor * device_scale_factor; - node->data.post_local_scale_factor = post_local_scale_factor; - node->data.post_local = device_transform; - node->data.post_local.Scale(post_local_scale_factor, - post_local_scale_factor); + node->post_local_scale_factor = post_local_scale_factor; + node->post_local = device_transform; + node->post_local.Scale(post_local_scale_factor, post_local_scale_factor); } else { - node->data.post_local_scale_factor = page_scale_factor; - node->data.update_post_local_transform(gfx::PointF(), gfx::Point3F()); + node->post_local_scale_factor = page_scale_factor; + node->update_post_local_transform(gfx::PointF(), gfx::Point3F()); } - node->data.needs_local_transform_update = true; + node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); } @@ -1402,11 +1459,11 @@ TransformNode* node = property_trees->transform_tree.Node( overscroll_elasticity_layer->transform_tree_index()); - if (node->data.scroll_offset == gfx::ScrollOffset(elastic_overscroll)) + if (node->scroll_offset == gfx::ScrollOffset(elastic_overscroll)) return; - node->data.scroll_offset = gfx::ScrollOffset(elastic_overscroll); - node->data.needs_local_transform_update = true; + node->scroll_offset = gfx::ScrollOffset(elastic_overscroll); + node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); }
diff --git a/cc/trees/effect_node.cc b/cc/trees/effect_node.cc new file mode 100644 index 0000000..c26ddd93 --- /dev/null +++ b/cc/trees/effect_node.cc
@@ -0,0 +1,141 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/trace_event/trace_event_argument.h" +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/property_tree.pb.h" +#include "cc/trees/effect_node.h" + +namespace cc { + +EffectNode::EffectNode() + : id(-1), + parent_id(-1), + owner_id(-1), + opacity(1.f), + screen_space_opacity(1.f), + has_render_surface(false), + render_surface(nullptr), + has_copy_request(false), + hidden_by_backface_visibility(false), + double_sided(false), + is_drawn(true), + subtree_hidden(false), + has_potential_opacity_animation(false), + is_currently_animating_opacity(false), + effect_changed(false), + num_copy_requests_in_subtree(0), + has_unclipped_descendants(false), + transform_id(0), + clip_id(0), + target_id(0), + mask_layer_id(-1), + replica_layer_id(-1), + replica_mask_layer_id(-1) {} + +EffectNode::EffectNode(const EffectNode& other) = default; + +bool EffectNode::operator==(const EffectNode& other) const { + return id == other.id && parent_id == other.parent_id && + owner_id == other.owner_id && opacity == other.opacity && + screen_space_opacity == other.screen_space_opacity && + has_render_surface == other.has_render_surface && + has_copy_request == other.has_copy_request && + background_filters == other.background_filters && + sublayer_scale == other.sublayer_scale && + hidden_by_backface_visibility == other.hidden_by_backface_visibility && + double_sided == other.double_sided && is_drawn == other.is_drawn && + subtree_hidden == other.subtree_hidden && + has_potential_opacity_animation == + other.has_potential_opacity_animation && + is_currently_animating_opacity == + other.is_currently_animating_opacity && + effect_changed == other.effect_changed && + num_copy_requests_in_subtree == other.num_copy_requests_in_subtree && + transform_id == other.transform_id && clip_id == other.clip_id && + target_id == other.target_id && mask_layer_id == other.mask_layer_id && + replica_layer_id == other.replica_layer_id && + replica_mask_layer_id == other.replica_mask_layer_id; +} + +void EffectNode::ToProtobuf(proto::TreeNode* proto) const { + proto->set_id(id); + proto->set_parent_id(parent_id); + proto->set_owner_id(owner_id); + + DCHECK(!proto->has_effect_node_data()); + proto::EffectNodeData* data = proto->mutable_effect_node_data(); + data->set_opacity(opacity); + data->set_screen_space_opacity(screen_space_opacity); + data->set_has_render_surface(has_render_surface); + data->set_has_copy_request(has_copy_request); + data->set_hidden_by_backface_visibility(hidden_by_backface_visibility); + data->set_double_sided(double_sided); + data->set_is_drawn(is_drawn); + data->set_subtree_hidden(subtree_hidden); + data->set_has_potential_opacity_animation(has_potential_opacity_animation); + data->set_is_currently_animating_opacity(is_currently_animating_opacity); + data->set_effect_changed(effect_changed); + data->set_num_copy_requests_in_subtree(num_copy_requests_in_subtree); + data->set_transform_id(transform_id); + data->set_clip_id(clip_id); + data->set_target_id(target_id); + data->set_mask_layer_id(mask_layer_id); + data->set_replica_layer_id(replica_layer_id); + data->set_replica_mask_layer_id(replica_mask_layer_id); + Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale()); +} + +void EffectNode::FromProtobuf(const proto::TreeNode& proto) { + id = proto.id(); + parent_id = proto.parent_id(); + owner_id = proto.owner_id(); + + DCHECK(proto.has_effect_node_data()); + const proto::EffectNodeData& data = proto.effect_node_data(); + + opacity = data.opacity(); + screen_space_opacity = data.screen_space_opacity(); + has_render_surface = data.has_render_surface(); + has_copy_request = data.has_copy_request(); + hidden_by_backface_visibility = data.hidden_by_backface_visibility(); + double_sided = data.double_sided(); + is_drawn = data.is_drawn(); + subtree_hidden = data.subtree_hidden(); + has_potential_opacity_animation = data.has_potential_opacity_animation(); + is_currently_animating_opacity = data.is_currently_animating_opacity(); + effect_changed = data.effect_changed(); + num_copy_requests_in_subtree = data.num_copy_requests_in_subtree(); + transform_id = data.transform_id(); + clip_id = data.clip_id(); + target_id = data.target_id(); + mask_layer_id = data.mask_layer_id(); + replica_layer_id = data.replica_layer_id(); + replica_mask_layer_id = data.replica_mask_layer_id(); + sublayer_scale = ProtoToVector2dF(data.sublayer_scale()); +} + +void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { + value->SetInteger("id", id); + value->SetInteger("parent_id", parent_id); + value->SetInteger("owner_id", owner_id); + value->SetDouble("opacity", opacity); + value->SetBoolean("has_render_surface", has_render_surface); + value->SetBoolean("has_copy_request", has_copy_request); + value->SetBoolean("double_sided", double_sided); + value->SetBoolean("is_drawn", is_drawn); + value->SetBoolean("has_potential_opacity_animation", + has_potential_opacity_animation); + value->SetBoolean("effect_changed", effect_changed); + value->SetInteger("num_copy_requests_in_subtree", + num_copy_requests_in_subtree); + value->SetInteger("transform_id", transform_id); + value->SetInteger("clip_id", clip_id); + value->SetInteger("target_id", target_id); + value->SetInteger("mask_layer_id", mask_layer_id); + value->SetInteger("replica_layer_id", replica_layer_id); + value->SetInteger("replica_mask_layer_id", replica_mask_layer_id); +} + +} // namespace cc
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h new file mode 100644 index 0000000..1e3c73c --- /dev/null +++ b/cc/trees/effect_node.h
@@ -0,0 +1,73 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_EFFECT_NODE_H_ +#define CC_TREES_EFFECT_NODE_H_ + +#include "cc/base/cc_export.h" +#include "cc/output/filter_operations.h" + +namespace base { +namespace trace_event { +class TracedValue; +} // namespace trace_event +} // namespace base + +namespace cc { + +class RenderSurfaceImpl; + +namespace proto { +class TreeNode; +} // namespace proto + +struct CC_EXPORT EffectNode { + EffectNode(); + EffectNode(const EffectNode& other); + + int id; + int parent_id; + int owner_id; + + float opacity; + float screen_space_opacity; + + FilterOperations background_filters; + + gfx::Vector2dF sublayer_scale; + + bool has_render_surface; + RenderSurfaceImpl* render_surface; + bool has_copy_request; + bool hidden_by_backface_visibility; + bool double_sided; + bool is_drawn; + // TODO(jaydasika) : Delete this after implementation of + // SetHideLayerAndSubtree is cleaned up. (crbug.com/595843) + bool subtree_hidden; + bool has_potential_opacity_animation; + bool is_currently_animating_opacity; + // We need to track changes to effects on the compositor to compute damage + // rect. + bool effect_changed; + int num_copy_requests_in_subtree; + bool has_unclipped_descendants; + int transform_id; + int clip_id; + // Effect node id of which this effect contributes to. + int target_id; + int mask_layer_id; + int replica_layer_id; + int replica_mask_layer_id; + + bool operator==(const EffectNode& other) const; + + void ToProtobuf(proto::TreeNode* proto) const; + void FromProtobuf(const proto::TreeNode& proto); + void AsValueInto(base::trace_event::TracedValue* value) const; +}; + +} // namespace cc + +#endif // CC_TREES_EFFECT_NODE_H_
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 98aa7f3..0263d55 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -18,9 +18,11 @@ #include "cc/proto/begin_main_frame_and_commit_state.pb.h" #include "cc/proto/gfx_conversions.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree_builder.h" +#include "cc/trees/scroll_node.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/transform.h" @@ -219,11 +221,10 @@ ScrollTree* scroll_tree) { for (LayerImpl* layer : *layer_list) { if (layer->is_drawn_render_surface_layer_list_member()) { - DCHECK_GT(scroll_tree->Node(layer->scroll_tree_index()) - ->data.num_drawn_descendants, - 0); - scroll_tree->Node(layer->scroll_tree_index()) - ->data.num_drawn_descendants--; + DCHECK_GT( + scroll_tree->Node(layer->scroll_tree_index())->num_drawn_descendants, + 0); + scroll_tree->Node(layer->scroll_tree_index())->num_drawn_descendants--; } layer->set_is_drawn_render_surface_layer_list_member(false); } @@ -303,14 +304,14 @@ ScrollTree* scroll_tree) { for (int i = static_cast<int>(scroll_tree->size()) - 1; i > 0; --i) { ScrollNode* node = scroll_tree->Node(i); - scroll_tree->parent(node)->data.num_drawn_descendants += - node->data.num_drawn_descendants; + scroll_tree->parent(node)->num_drawn_descendants += + node->num_drawn_descendants; } for (LayerImpl* layer : *layer_tree_impl) { bool scrolls_drawn_descendant = false; if (layer->scrollable()) { ScrollNode* node = scroll_tree->Node(layer->scroll_tree_index()); - if (node->data.num_drawn_descendants > 0) + if (node->num_drawn_descendants > 0) scrolls_drawn_descendant = true; } layer->set_scrolls_drawn_descendant(scrolls_drawn_descendant); @@ -324,7 +325,7 @@ bool can_render_to_separate_surface) { ScrollTree* scroll_tree = &property_trees->scroll_tree; for (int i = 0; i < static_cast<int>(scroll_tree->size()); ++i) - scroll_tree->Node(i)->data.num_drawn_descendants = 0; + scroll_tree->Node(i)->num_drawn_descendants = 0; // Add all non-skipped surfaces to the initial render surface layer list. Add // all non-skipped layers to the layer list of their target surface, and @@ -338,8 +339,7 @@ layer->set_is_drawn_render_surface_layer_list_member(false); bool layer_is_drawn = - property_trees->effect_tree.Node(layer->effect_tree_index()) - ->data.is_drawn; + property_trees->effect_tree.Node(layer->effect_tree_index())->is_drawn; bool is_root = layer_tree_impl->IsRootLayer(layer); bool skip_layer = !is_root && draw_property_utils::LayerShouldBeSkipped( @@ -399,7 +399,7 @@ continue; layer->set_is_drawn_render_surface_layer_list_member(true); - scroll_tree->Node(layer->scroll_tree_index())->data.num_drawn_descendants++; + scroll_tree->Node(layer->scroll_tree_index())->num_drawn_descendants++; layer->render_target()->layer_list().push_back(layer); // The layer contributes its drawable content rect to its render target.
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 4f47e2ea..52386ed 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -40,10 +40,14 @@ #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_host_common_test.h" #include "cc/test/test_task_graph_runner.h" +#include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/task_runner_provider.h" +#include "cc/trees/transform_node.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/effects/SkOffsetImageFilter.h" @@ -189,7 +193,7 @@ const int transform_tree_size = parent->layer_tree_impl() ->property_trees() ->transform_tree.next_available_id(); - EXPECT_LT(node->data.transform_id, transform_tree_size); + EXPECT_LT(node->transform_id, transform_tree_size); } TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) { @@ -1373,7 +1377,7 @@ EffectTree& effect_tree = parent->layer_tree_impl()->property_trees()->effect_tree; EffectNode* node = effect_tree.Node(render_surface1->effect_tree_index()); - EXPECT_TRUE(node->data.is_drawn); + EXPECT_TRUE(node->is_drawn); // When parent is transparent, the layer should not be drawn. parent->OnOpacityAnimated(0.f); @@ -1388,7 +1392,7 @@ } node = effect_tree.Node(render_surface1->effect_tree_index()); - EXPECT_FALSE(node->data.is_drawn); + EXPECT_FALSE(node->is_drawn); EXPECT_EQ(gfx::Rect(), render_surface1->visible_layer_rect()); } @@ -1707,9 +1711,6 @@ EXPECT_TRUE(child->test_properties()->should_flatten_transform); EXPECT_FALSE(grand_child->test_properties()->should_flatten_transform); - gfx::Transform expected_child_draw_transform = identity_matrix; - gfx::Transform expected_grand_child_draw_transform = identity_matrix; - gfx::Transform flattened_rotation_about_y = rotation_about_y_axis; flattened_rotation_about_y.FlattenTo2d(); @@ -3675,7 +3676,7 @@ EXPECT_FALSE(root->layer_tree_impl() ->property_trees() ->transform_tree.Node(grand_child->transform_tree_index()) - ->data.ancestors_are_invertible); + ->ancestors_are_invertible); // CalcDrawProps skips a subtree when a layer's screen space transform is // uninvertible @@ -3748,7 +3749,7 @@ host_impl.active_tree() ->property_trees() ->transform_tree.Node(grand_child_ptr->transform_tree_index()) - ->data.ancestors_are_invertible); + ->ancestors_are_invertible); // Since |grand_child| has an uninvertible screen space transform, it is // skipped so @@ -4993,7 +4994,7 @@ gfx::Transform expected_duplicate_child_draw_transform = child->DrawTransform(); - EXPECT_TRANSFORMATION_MATRIX_EQ(child->DrawTransform(), + EXPECT_TRANSFORMATION_MATRIX_EQ(expected_duplicate_child_draw_transform, duplicate_child_non_owner->DrawTransform()); EXPECT_TRANSFORMATION_MATRIX_EQ( child->ScreenSpaceTransform(), @@ -5207,7 +5208,7 @@ EffectTree& tree = root_layer->layer_tree_impl()->property_trees()->effect_tree; EffectNode* node = tree.Node(child_ptr->effect_tree_index()); - EXPECT_FALSE(node->data.is_drawn); + EXPECT_FALSE(node->is_drawn); // A layer should be drawn and it should contribute to drawn surface when // it has animating opacity even if it has opacity 0. @@ -5223,7 +5224,7 @@ child_ptr = root_layer->layer_tree_impl()->LayerById(2); tree = root_layer->layer_tree_impl()->property_trees()->effect_tree; node = tree.Node(child_ptr->effect_tree_index()); - EXPECT_TRUE(node->data.is_drawn); + EXPECT_TRUE(node->is_drawn); EXPECT_TRUE(tree.ContributesToDrawnSurface(child_ptr->effect_tree_index())); // But if the opacity of the layer remains 0 after activation, it should not @@ -5239,7 +5240,7 @@ ExecuteCalculateDrawProperties(active_root); node = active_effect_tree.Node(active_child->effect_tree_index()); - EXPECT_FALSE(node->data.is_drawn); + EXPECT_FALSE(node->is_drawn); EXPECT_FALSE(active_effect_tree.ContributesToDrawnSurface( active_child->effect_tree_index())); } @@ -5723,15 +5724,15 @@ EffectTree& tree = root_layer->layer_tree_impl()->property_trees()->effect_tree; EffectNode* node = tree.Node(copy_grand_parent_layer->effect_tree_index()); - EXPECT_FALSE(node->data.is_drawn); + EXPECT_FALSE(node->is_drawn); node = tree.Node(copy_parent_layer->effect_tree_index()); - EXPECT_FALSE(node->data.is_drawn); + EXPECT_FALSE(node->is_drawn); node = tree.Node(copy_layer->effect_tree_index()); - EXPECT_TRUE(node->data.is_drawn); + EXPECT_TRUE(node->is_drawn); node = tree.Node(copy_child_layer->effect_tree_index()); - EXPECT_TRUE(node->data.is_drawn); + EXPECT_TRUE(node->is_drawn); node = tree.Node(copy_grand_child_layer->effect_tree_index()); - EXPECT_FALSE(node->data.is_drawn); + EXPECT_FALSE(node->is_drawn); // Though copy_layer is drawn, it shouldn't contribute to drawn surface as its // actually hidden. @@ -6650,24 +6651,24 @@ const EffectTree& tree = root->layer_tree_impl()->property_trees()->effect_tree; EXPECT_TRUE(tree.Node(render_surface1->effect_tree_index()) - ->data.hidden_by_backface_visibility); + ->hidden_by_backface_visibility); EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) - ->data.hidden_by_backface_visibility); + ->hidden_by_backface_visibility); back_facing->OnTransformAnimated(identity_transform); render_surface2->OnTransformAnimated(rotate_about_y); ExecuteCalculateDrawProperties(root); EXPECT_FALSE(tree.Node(render_surface1->effect_tree_index()) - ->data.hidden_by_backface_visibility); + ->hidden_by_backface_visibility); EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) - ->data.hidden_by_backface_visibility); + ->hidden_by_backface_visibility); render_surface1->OnTransformAnimated(rotate_about_y); ExecuteCalculateDrawProperties(root); EXPECT_TRUE(tree.Node(render_surface1->effect_tree_index()) - ->data.hidden_by_backface_visibility); + ->hidden_by_backface_visibility); EXPECT_TRUE(tree.Node(render_surface2->effect_tree_index()) - ->data.hidden_by_backface_visibility); + ->hidden_by_backface_visibility); } TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) { @@ -9332,7 +9333,7 @@ ClipTree& clip_tree = root->layer_tree_impl()->property_trees()->clip_tree; ClipNode* clip_node = clip_tree.Node(render_surface->clip_tree_index()); - EXPECT_FALSE(clip_node->data.applies_local_clip); + EXPECT_FALSE(clip_node->applies_local_clip); EXPECT_EQ(gfx::Rect(20, 20), test_layer->visible_layer_rect()); } @@ -9980,13 +9981,13 @@ TransformTree& tree = root->layer_tree_impl()->property_trees()->transform_tree; TransformNode* node = tree.Node(render_surface1->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f)); node = tree.Node(between_targets->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f)); node = tree.Node(render_surface2->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f)); EXPECT_EQ(gfx::Rect(15, 15), test_layer->visible_layer_rect()); } @@ -10126,20 +10127,20 @@ EffectTree& tree = root->layer_tree_host()->property_trees()->effect_tree; EffectNode* node = tree.Node(animated->effect_tree_index()); - EXPECT_FALSE(node->data.is_currently_animating_opacity); - EXPECT_TRUE(node->data.has_potential_opacity_animation); + EXPECT_FALSE(node->is_currently_animating_opacity); + EXPECT_TRUE(node->has_potential_opacity_animation); animation_ptr->set_time_offset(base::TimeDelta::FromMilliseconds(0)); root->layer_tree_host()->AnimateLayers( base::TimeTicks::FromInternalValue(std::numeric_limits<int64_t>::max())); node = tree.Node(animated->effect_tree_index()); - EXPECT_TRUE(node->data.is_currently_animating_opacity); - EXPECT_TRUE(node->data.has_potential_opacity_animation); + EXPECT_TRUE(node->is_currently_animating_opacity); + EXPECT_TRUE(node->has_potential_opacity_animation); player->AbortAnimations(TargetProperty::OPACITY, false /*needs_completion*/); node = tree.Node(animated->effect_tree_index()); - EXPECT_FALSE(node->data.is_currently_animating_opacity); - EXPECT_FALSE(node->data.has_potential_opacity_animation); + EXPECT_FALSE(node->is_currently_animating_opacity); + EXPECT_FALSE(node->has_potential_opacity_animation); } TEST_F(LayerTreeHostCommonTest, TransformAnimationsTrackingTest) { @@ -10190,21 +10191,21 @@ TransformTree& tree = root->layer_tree_host()->property_trees()->transform_tree; TransformNode* node = tree.Node(animated->transform_tree_index()); - EXPECT_FALSE(node->data.is_currently_animating); - EXPECT_TRUE(node->data.has_potential_animation); + EXPECT_FALSE(node->is_currently_animating); + EXPECT_TRUE(node->has_potential_animation); animation_ptr->set_time_offset(base::TimeDelta::FromMilliseconds(0)); root->layer_tree_host()->AnimateLayers( base::TimeTicks::FromInternalValue(std::numeric_limits<int64_t>::max())); node = tree.Node(animated->transform_tree_index()); - EXPECT_TRUE(node->data.is_currently_animating); - EXPECT_TRUE(node->data.has_potential_animation); + EXPECT_TRUE(node->is_currently_animating); + EXPECT_TRUE(node->has_potential_animation); player->AbortAnimations(TargetProperty::TRANSFORM, false /*needs_completion*/); node = tree.Node(animated->transform_tree_index()); - EXPECT_FALSE(node->data.is_currently_animating); - EXPECT_FALSE(node->data.has_potential_animation); + EXPECT_FALSE(node->is_currently_animating); + EXPECT_FALSE(node->has_potential_animation); } TEST_F(LayerTreeHostCommonTest, SerializeScrollUpdateInfo) { @@ -10341,82 +10342,81 @@ property_tree_root->id = kRootPropertyTreeNodeId; property_tree_root->parent_id = kInvalidPropertyTreeNodeId; property_tree_root->owner_id = kInvalidPropertyTreeNodeId; - property_tree_root->data.scrollable = false; - property_tree_root->data.main_thread_scrolling_reasons = + property_tree_root->scrollable = false; + property_tree_root->main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; - property_tree_root->data.contains_non_fast_scrollable_region = false; - property_tree_root->data.transform_id = kRootPropertyTreeNodeId; + property_tree_root->contains_non_fast_scrollable_region = false; + property_tree_root->transform_id = kRootPropertyTreeNodeId; // The node owned by root1 ScrollNode scroll_root1; scroll_root1.id = 1; scroll_root1.owner_id = root1->id(); - scroll_root1.data.user_scrollable_horizontal = true; - scroll_root1.data.user_scrollable_vertical = true; - scroll_root1.data.transform_id = root1->transform_tree_index(); + scroll_root1.user_scrollable_horizontal = true; + scroll_root1.user_scrollable_vertical = true; + scroll_root1.transform_id = root1->transform_tree_index(); expected_scroll_tree.Insert(scroll_root1, 0); // The node owned by parent2 ScrollNode scroll_parent2; scroll_parent2.id = 2; scroll_parent2.owner_id = parent2->id(); - scroll_parent2.data.scrollable = true; - scroll_parent2.data.main_thread_scrolling_reasons = + scroll_parent2.scrollable = true; + scroll_parent2.main_thread_scrolling_reasons = parent2->main_thread_scrolling_reasons(); - scroll_parent2.data.scroll_clip_layer_bounds = root1->bounds(); - scroll_parent2.data.bounds = parent2->bounds(); - scroll_parent2.data.max_scroll_offset_affected_by_page_scale = true; - scroll_parent2.data.is_inner_viewport_scroll_layer = true; - scroll_parent2.data.user_scrollable_horizontal = true; - scroll_parent2.data.user_scrollable_vertical = true; - scroll_parent2.data.transform_id = parent2->transform_tree_index(); + scroll_parent2.scroll_clip_layer_bounds = root1->bounds(); + scroll_parent2.bounds = parent2->bounds(); + scroll_parent2.max_scroll_offset_affected_by_page_scale = true; + scroll_parent2.is_inner_viewport_scroll_layer = true; + scroll_parent2.user_scrollable_horizontal = true; + scroll_parent2.user_scrollable_vertical = true; + scroll_parent2.transform_id = parent2->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent2, 1); // The node owned by child6 ScrollNode scroll_child6; scroll_child6.id = 3; scroll_child6.owner_id = child6->id(); - scroll_child6.data.main_thread_scrolling_reasons = + scroll_child6.main_thread_scrolling_reasons = child6->main_thread_scrolling_reasons(); - scroll_child6.data.should_flatten = true; - scroll_child6.data.user_scrollable_horizontal = true; - scroll_child6.data.user_scrollable_vertical = true; - scroll_child6.data.transform_id = child6->transform_tree_index(); + scroll_child6.should_flatten = true; + scroll_child6.user_scrollable_horizontal = true; + scroll_child6.user_scrollable_vertical = true; + scroll_child6.transform_id = child6->transform_tree_index(); expected_scroll_tree.Insert(scroll_child6, 2); // The node owned by child7, child7 also owns a transform node ScrollNode scroll_child7; scroll_child7.id = 4; scroll_child7.owner_id = child7->id(); - scroll_child7.data.scrollable = true; - scroll_child7.data.scroll_clip_layer_bounds = parent3->bounds(); - scroll_child7.data.bounds = child7->bounds(); - scroll_child7.data.user_scrollable_horizontal = true; - scroll_child7.data.user_scrollable_vertical = true; - scroll_child7.data.transform_id = child7->transform_tree_index(); + scroll_child7.scrollable = true; + scroll_child7.scroll_clip_layer_bounds = parent3->bounds(); + scroll_child7.bounds = child7->bounds(); + scroll_child7.user_scrollable_horizontal = true; + scroll_child7.user_scrollable_vertical = true; + scroll_child7.transform_id = child7->transform_tree_index(); expected_scroll_tree.Insert(scroll_child7, 1); // The node owned by grand_child11, grand_child11 also owns a transform node ScrollNode scroll_grand_child11; scroll_grand_child11.id = 5; scroll_grand_child11.owner_id = grand_child11->id(); - scroll_grand_child11.data.scrollable = true; - scroll_grand_child11.data.user_scrollable_horizontal = true; - scroll_grand_child11.data.user_scrollable_vertical = true; - scroll_grand_child11.data.transform_id = - grand_child11->transform_tree_index(); + scroll_grand_child11.scrollable = true; + scroll_grand_child11.user_scrollable_horizontal = true; + scroll_grand_child11.user_scrollable_vertical = true; + scroll_grand_child11.transform_id = grand_child11->transform_tree_index(); expected_scroll_tree.Insert(scroll_grand_child11, 4); // The node owned by parent5 ScrollNode scroll_parent5; scroll_parent5.id = 8; scroll_parent5.owner_id = parent5->id(); - scroll_parent5.data.contains_non_fast_scrollable_region = true; - scroll_parent5.data.bounds = gfx::Size(10, 10); - scroll_parent5.data.should_flatten = true; - scroll_parent5.data.user_scrollable_horizontal = true; - scroll_parent5.data.user_scrollable_vertical = true; - scroll_parent5.data.transform_id = parent5->transform_tree_index(); + scroll_parent5.contains_non_fast_scrollable_region = true; + scroll_parent5.bounds = gfx::Size(10, 10); + scroll_parent5.should_flatten = true; + scroll_parent5.user_scrollable_horizontal = true; + scroll_parent5.user_scrollable_vertical = true; + scroll_parent5.transform_id = parent5->transform_tree_index(); expected_scroll_tree.Insert(scroll_parent5, 1); expected_scroll_tree.SetScrollOffset(parent2->id(), gfx::ScrollOffset(0, 0));
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 0c6928e..dd3c629 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -82,6 +82,7 @@ #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/tree_synchronizer.h" #include "gpu/GLES2/gl2extchromium.h" @@ -277,6 +278,13 @@ // It is released before shutdown. DCHECK(!output_surface_); + DCHECK(!renderer_); + DCHECK(!resource_provider_); + DCHECK(!resource_pool_); + DCHECK(!tile_task_manager_); + DCHECK(!single_thread_synchronous_task_graph_runner_); + DCHECK(!image_decode_controller_); + if (input_handler_client_) { input_handler_client_->WillShutdown(); input_handler_client_ = NULL; @@ -298,10 +306,6 @@ animation_host_->ClearTimelines(); animation_host_->SetMutatorHostClient(nullptr); - - CleanUpTileManagerAndUIResources(); - renderer_ = nullptr; - resource_provider_ = nullptr; } void LayerTreeHostImpl::BeginMainFrameAborted(CommitEarlyOutReason reason) { @@ -1595,6 +1599,11 @@ !OuterViewportScrollLayer()->user_scrollable_vertical(); } + if (GetDrawMode() == DRAW_MODE_RESOURCELESS_SOFTWARE) { + metadata.is_resourceless_software_draw_with_scroll_or_animation = + IsActivelyScrolling() || animation_host_->NeedsAnimateLayers(); + } + for (LayerImpl* surface_layer : active_tree_->SurfaceLayers()) { metadata.referenced_surfaces.push_back( static_cast<SurfaceLayerImpl*>(surface_layer)->surface_id()); @@ -1669,28 +1678,9 @@ resource_provider_.get()); } - if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) { - bool disable_picture_quad_image_filtering = - IsActivelyScrolling() || animation_host_->NeedsAnimateLayers(); - - // We must disable the image hijack canvas when using GPU rasterization but - // performing a resourceless software draw. Otherwise, we will attempt to - // use the GPU ImageDecodeController during software raster. - bool use_image_hijack_canvas = !use_gpu_rasterization_; - - std::unique_ptr<SoftwareRenderer> temp_software_renderer = - SoftwareRenderer::Create(this, &settings_.renderer_settings, - output_surface_, nullptr, - use_image_hijack_canvas); - temp_software_renderer->DrawFrame( - &frame->render_passes, active_tree_->device_scale_factor(), - gfx::ColorSpace(), DeviceViewport(), DeviceClip(), - disable_picture_quad_image_filtering); - } else { - renderer_->DrawFrame(&frame->render_passes, - active_tree_->device_scale_factor(), gfx::ColorSpace(), - DeviceViewport(), DeviceClip(), false); - } + renderer_->DrawFrame(&frame->render_passes, + active_tree_->device_scale_factor(), gfx::ColorSpace(), + DeviceViewport(), DeviceClip()); // The render passes should be consumed by the renderer. DCHECK(frame->render_passes.empty()); @@ -2147,9 +2137,9 @@ resource_provider_.get(), texture_mailbox_deleter_.get(), settings_.renderer_settings.highp_threshold_min); } else if (output_surface_->software_device()) { - renderer_ = SoftwareRenderer::Create( - this, &settings_.renderer_settings, output_surface_, - resource_provider_.get(), true /* use_image_hijack_canvas */); + renderer_ = + SoftwareRenderer::Create(this, &settings_.renderer_settings, + output_surface_, resource_provider_.get()); } DCHECK(renderer_); @@ -2468,11 +2458,11 @@ InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; - if (!!scroll_node->data.main_thread_scrolling_reasons) { + if (!!scroll_node->main_thread_scrolling_reasons) { TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread"); scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD; scroll_status.main_thread_scrolling_reasons = - scroll_node->data.main_thread_scrolling_reasons; + scroll_node->main_thread_scrolling_reasons; return scroll_status; } @@ -2486,7 +2476,7 @@ return scroll_status; } - if (scroll_node->data.contains_non_fast_scrollable_region) { + if (scroll_node->contains_non_fast_scrollable_region) { bool clipped = false; gfx::Transform inverse_screen_space_transform( gfx::Transform::kSkipInitialization); @@ -2512,7 +2502,7 @@ } } - if (!scroll_node->data.scrollable) { + if (!scroll_node->scrollable) { TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable"); scroll_status.thread = InputHandler::SCROLL_IGNORED; scroll_status.main_thread_scrolling_reasons = @@ -2539,7 +2529,7 @@ static bool IsMainThreadScrolling(const InputHandler::ScrollStatus& status, const ScrollNode* scroll_node) { if (status.thread == InputHandler::SCROLL_ON_MAIN_THREAD) { - if (!!scroll_node->data.main_thread_scrolling_reasons) { + if (!!scroll_node->main_thread_scrolling_reasons) { DCHECK(MainThreadScrollingReason::MainThreadCanSetScrollReasons( status.main_thread_scrolling_reasons)); } else { @@ -2623,7 +2613,7 @@ ScrollNode* scroll_node = scroll_tree.Node(child->scroll_tree_index()); for (; scroll_tree.parent(scroll_node); scroll_node = scroll_tree.parent(scroll_node)) { - if (scroll_node->data.scrollable) + if (scroll_node->scrollable) return scroll_node->owner_id == scroll_ancestor->id(); } return false; @@ -2773,9 +2763,9 @@ gfx::Vector2dF adjusted_scroll(delta); adjusted_scroll.Scale(1.f / scale_factor); - if (!scroll_node->data.user_scrollable_horizontal) + if (!scroll_node->user_scrollable_horizontal) adjusted_scroll.set_x(0); - if (!scroll_node->data.user_scrollable_vertical) + if (!scroll_node->user_scrollable_vertical) adjusted_scroll.set_y(0); gfx::ScrollOffset old_offset = @@ -2807,9 +2797,9 @@ current_offset + gfx::ScrollOffset(delta), scroll_node); DCHECK_EQ( ElementId(active_tree()->LayerById(scroll_node->owner_id)->element_id()), - scroll_node->data.element_id); + scroll_node->element_id); - animation_host_->ImplOnlyScrollAnimationCreate(scroll_node->data.element_id, + animation_host_->ImplOnlyScrollAnimationCreate(scroll_node->element_id, target_offset, current_offset); SetNeedsOneBeginImplFrame(); @@ -2827,9 +2817,9 @@ ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); if (scroll_node) { gfx::Vector2dF delta = scroll_delta; - if (!scroll_node->data.user_scrollable_horizontal) + if (!scroll_node->user_scrollable_horizontal) delta.set_x(0); - if (!scroll_node->data.user_scrollable_vertical) + if (!scroll_node->user_scrollable_vertical) delta.set_y(0); if (ScrollAnimationUpdateTarget(scroll_node, delta)) { @@ -2859,11 +2849,11 @@ if (scroll_node) { for (; scroll_tree.parent(scroll_node); scroll_node = scroll_tree.parent(scroll_node)) { - if (!scroll_node->data.scrollable || - scroll_node->data.is_outer_viewport_scroll_layer) + if (!scroll_node->scrollable || + scroll_node->is_outer_viewport_scroll_layer) continue; - if (scroll_node->data.is_inner_viewport_scroll_layer) { + if (scroll_node->is_inner_viewport_scroll_layer) { gfx::Vector2dF scrolled = viewport()->ScrollAnimated(pending_delta); // Viewport::ScrollAnimated returns pending_delta as long as it // starts an animation. @@ -3013,7 +3003,7 @@ // details. const float kEpsilon = 0.1f; - if (scroll_node->data.is_inner_viewport_scroll_layer) { + if (scroll_node->is_inner_viewport_scroll_layer) { bool affect_top_controls = !wheel_scrolling_; Viewport::ScrollResult result = viewport()->ScrollBy( delta, viewport_point, scroll_state->is_direct_manipulation(), @@ -3034,7 +3024,7 @@ bool scrolled = std::abs(applied_delta.x()) > kEpsilon; scrolled = scrolled || std::abs(applied_delta.y()) > kEpsilon; - if (scrolled && !scroll_node->data.is_inner_viewport_scroll_layer) { + if (scrolled && !scroll_node->is_inner_viewport_scroll_layer) { // If the applied delta is within 45 degrees of the input // delta, bail out to make it easier to scroll just one layer // in one direction without affecting any of its parents. @@ -3072,8 +3062,8 @@ // Skip the outer viewport scroll layer so that we try to scroll the // viewport only once. i.e. The inner viewport layer represents the // viewport. - if (!scroll_node->data.scrollable || - scroll_node->data.is_outer_viewport_scroll_layer) + if (!scroll_node->scrollable || + scroll_node->is_outer_viewport_scroll_layer) continue; current_scroll_chain.push_front(scroll_node); } @@ -3173,8 +3163,8 @@ for (; scroll_tree.parent(scroll_node); scroll_node = scroll_tree.parent(scroll_node)) { // The inner viewport layer represents the viewport. - if (!scroll_node->data.scrollable || - scroll_node->data.is_outer_viewport_scroll_layer) + if (!scroll_node->scrollable || + scroll_node->is_outer_viewport_scroll_layer) continue; float height = @@ -3830,10 +3820,10 @@ const gfx::Vector2dF& scroll_delta) { DCHECK_EQ( ElementId(active_tree()->LayerById(scroll_node->owner_id)->element_id()), - scroll_node->data.element_id); + scroll_node->element_id); return animation_host_->ImplOnlyScrollAnimationUpdateTarget( - scroll_node->data.element_id, scroll_delta, + scroll_node->element_id, scroll_delta, active_tree_->property_trees()->scroll_tree.MaxScrollOffset( scroll_node->id), CurrentBeginFrameArgs().frame_time);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 43e5e4db..b3807cf 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -62,8 +62,10 @@ #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" +#include "cc/trees/transform_node.h" #include "media/base/media.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -2940,7 +2942,7 @@ host_impl_->active_tree()->property_trees()->effect_tree.Node( active_scrollbar_layer->effect_tree_index()); EXPECT_FLOAT_EQ(active_scrollbar_layer->Opacity(), - active_tree_node->data.opacity); + active_tree_node->opacity); host_impl_->ScrollbarAnimationControllerForId(scroll->id()) ->DidMouseMoveNear(0); @@ -2964,14 +2966,14 @@ host_impl_->pending_tree() ->property_trees() ->always_use_active_tree_opacity_effect_ids.push_back(400); - EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity); + EXPECT_FLOAT_EQ(1.f, active_tree_node->opacity); EXPECT_FLOAT_EQ(1.f, active_scrollbar_layer->Opacity()); - EXPECT_FLOAT_EQ(0.f, pending_tree_node->data.opacity); + EXPECT_FLOAT_EQ(0.f, pending_tree_node->opacity); host_impl_->ActivateSyncTree(); active_tree_node = host_impl_->active_tree()->property_trees()->effect_tree.Node( active_scrollbar_layer->effect_tree_index()); - EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity); + EXPECT_FLOAT_EQ(1.f, active_tree_node->opacity); EXPECT_FLOAT_EQ(1.f, active_scrollbar_layer->Opacity()); } }; @@ -9647,7 +9649,7 @@ class ResourcelessSoftwareLayerTreeHostImplTest : public LayerTreeHostImplTest { protected: std::unique_ptr<OutputSurface> CreateOutputSurface() override { - return FakeOutputSurface::Create3dWithResourcelessSoftwareSupport(); + return FakeOutputSurface::CreateDelegating3d(); } }; @@ -9854,7 +9856,7 @@ TransformNode* node = host_impl_->active_tree()->property_trees()->transform_tree.Node( test_layer->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f)); gfx::Transform external_transform; external_transform.Translate(10, 10); @@ -9870,7 +9872,7 @@ resourceless_software_draw); node = host_impl_->active_tree()->property_trees()->transform_tree.Node( test_layer->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f)); // Clear the external transform. external_transform = gfx::Transform(); @@ -9881,7 +9883,7 @@ resourceless_software_draw); node = host_impl_->active_tree()->property_trees()->transform_tree.Node( test_layer->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f)); } TEST_F(LayerTreeHostImplTest, ScrollAnimated) { @@ -10897,27 +10899,27 @@ host_impl_->active_tree()->property_trees()->transform_tree.Node( page_scale_layer->transform_tree_index()); // SetPageScaleOnActiveTree also updates the factors in property trees. - EXPECT_EQ(active_tree_node->data.post_local_scale_factor, 2.f); + EXPECT_EQ(active_tree_node->post_local_scale_factor, 2.f); EXPECT_EQ(host_impl_->active_tree()->current_page_scale_factor(), 2.f); TransformNode* pending_tree_node = host_impl_->pending_tree()->property_trees()->transform_tree.Node( page_scale_layer->transform_tree_index()); - EXPECT_EQ(pending_tree_node->data.post_local_scale_factor, 1.f); + EXPECT_EQ(pending_tree_node->post_local_scale_factor, 1.f); EXPECT_EQ(host_impl_->pending_tree()->current_page_scale_factor(), 2.f); host_impl_->pending_tree()->UpdateDrawProperties(false); pending_tree_node = host_impl_->pending_tree()->property_trees()->transform_tree.Node( page_scale_layer->transform_tree_index()); - EXPECT_EQ(pending_tree_node->data.post_local_scale_factor, 2.f); + EXPECT_EQ(pending_tree_node->post_local_scale_factor, 2.f); host_impl_->ActivateSyncTree(); host_impl_->active_tree()->UpdateDrawProperties(false); active_tree_node = host_impl_->active_tree()->property_trees()->transform_tree.Node( page_scale_layer->transform_tree_index()); - EXPECT_EQ(active_tree_node->data.post_local_scale_factor, 2.f); + EXPECT_EQ(active_tree_node->post_local_scale_factor, 2.f); } TEST_F(LayerTreeHostImplTest, SubLayerScaleForNodeInSubtreeOfPageScaleLayer) { @@ -10940,7 +10942,7 @@ TransformNode* node = host_impl_->active_tree()->property_trees()->transform_tree.Node( in_subtree_of_page_scale_layer->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(1.f, 1.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(1.f, 1.f)); host_impl_->active_tree()->SetPageScaleOnActiveTree(2.f); @@ -10949,7 +10951,7 @@ in_subtree_of_page_scale_layer = host_impl_->active_tree()->LayerById(100); node = host_impl_->active_tree()->property_trees()->transform_tree.Node( in_subtree_of_page_scale_layer->transform_tree_index()); - EXPECT_EQ(node->data.sublayer_scale, gfx::Vector2dF(2.f, 2.f)); + EXPECT_EQ(node->sublayer_scale, gfx::Vector2dF(2.f, 2.f)); } TEST_F(LayerTreeHostImplTest, JitterTest) {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 74e73a25..3e298044 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -45,12 +45,15 @@ #include "cc/test/fake_scoped_ui_resource.h" #include "cc/test/fake_video_frame_provider.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/layer_internals_for_test.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" +#include "cc/trees/transform_node.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/khronos/GLES2/gl2.h" @@ -978,11 +981,11 @@ EffectNode* node = effect_tree.Node(root_->effect_tree_index()); switch (layer_tree_host()->source_frame_number()) { case 1: - node->data.opacity = 0.5f; - node->data.is_currently_animating_opacity = true; + node->opacity = 0.5f; + node->is_currently_animating_opacity = true; break; case 2: - node->data.is_currently_animating_opacity = false; + node->is_currently_animating_opacity = false; break; } } @@ -997,12 +1000,12 @@ PostSetNeedsCommitToMainThread(); break; case 1: - EXPECT_EQ(node->data.opacity, 0.75f); + EXPECT_EQ(node->opacity, 0.75f); impl->sync_tree()->root_layer_for_testing()->OnOpacityAnimated(0.75f); PostSetNeedsCommitToMainThread(); break; case 2: - EXPECT_EQ(node->data.opacity, 0.5f); + EXPECT_EQ(node->opacity, 0.5f); EndTest(); break; } @@ -1034,14 +1037,14 @@ rotate10.Rotate(10.f); switch (layer_tree_host()->source_frame_number()) { case 1: - node->data.local = rotate10; - node->data.is_currently_animating = true; + node->local = rotate10; + node->is_currently_animating = true; break; case 2: - node->data.is_currently_animating = true; + node->is_currently_animating = true; break; case 3: - node->data.is_currently_animating = false; + node->is_currently_animating = false; break; } } @@ -1062,19 +1065,19 @@ PostSetNeedsCommitToMainThread(); break; case 1: - EXPECT_EQ(node->data.local, rotate20); + EXPECT_EQ(node->local, rotate20); impl->sync_tree()->root_layer_for_testing()->OnTransformAnimated( rotate20); PostSetNeedsCommitToMainThread(); break; case 2: - EXPECT_EQ(node->data.local, rotate20); + EXPECT_EQ(node->local, rotate20); impl->sync_tree()->root_layer_for_testing()->OnTransformAnimated( rotate20); PostSetNeedsCommitToMainThread(); break; case 3: - EXPECT_EQ(node->data.local, rotate10); + EXPECT_EQ(node->local, rotate10); EndTest(); } } @@ -1116,7 +1119,7 @@ if (layer_tree_host()->source_frame_number() == 1) { gfx::Transform scale; scale.Scale(2.0, 2.0); - child_->OnTransformAnimated(scale); + LayerInternalsForTest(child_.get()).OnTransformAnimated(scale); } }
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index 9d7ba1f..4d660a5 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -25,6 +25,7 @@ #include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/transform_node.h" namespace cc { namespace { @@ -1686,7 +1687,7 @@ translate.Translate(5, 5); switch (host_impl->sync_tree()->source_frame_number()) { case 2: - EXPECT_TRANSFORMATION_MATRIX_EQ(node->data.local, translate); + EXPECT_TRANSFORMATION_MATRIX_EQ(node->local, translate); EndTest(); break; default:
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index fecc96ca..759586a 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -23,6 +23,7 @@ #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/vector2d_conversions.h"
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index d0e1b73..4d6ec707 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -33,12 +33,16 @@ #include "cc/layers/render_surface_impl.h" #include "cc/layers/scrollbar_layer_impl_base.h" #include "cc/resources/ui_resource_request.h" +#include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/occlusion_tracker.h" #include "cc/trees/property_tree.h" #include "cc/trees/property_tree_builder.h" +#include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -158,13 +162,12 @@ if (transform_id != -1) { TransformNode* node = transform_tree.Node(transform_id); - if (node->data.scroll_offset != - scroll_tree.current_scroll_offset(layer_id)) { - node->data.scroll_offset = scroll_tree.current_scroll_offset(layer_id); - node->data.needs_local_transform_update = true; + if (node->scroll_offset != scroll_tree.current_scroll_offset(layer_id)) { + node->scroll_offset = scroll_tree.current_scroll_offset(layer_id); + node->needs_local_transform_update = true; transform_tree.set_needs_update(true); } - node->data.transform_changed = true; + node->transform_changed = true; property_trees()->changed = true; set_needs_update_draw_properties(); } @@ -357,8 +360,8 @@ if (clip_node) { DCHECK_EQ(layer->id(), clip_node->owner_id); gfx::SizeF bounds = gfx::SizeF(layer->bounds()); - if (clip_node->data.clip.size() != bounds) { - clip_node->data.clip.set_size(bounds); + if (clip_node->clip.size() != bounds) { + clip_node->clip.set_size(bounds); clip_tree->set_needs_update(true); } } @@ -619,10 +622,10 @@ if (property_trees_.IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, id)) { EffectNode* node = property_trees_.effect_tree.Node( property_trees_.effect_id_to_index_map[id]); - if (!node->data.is_currently_animating_opacity || - node->data.opacity == layer_id_to_opacity.second) + if (!node->is_currently_animating_opacity || + node->opacity == layer_id_to_opacity.second) continue; - node->data.opacity = layer_id_to_opacity.second; + node->opacity = layer_id_to_opacity.second; property_trees_.effect_tree.set_needs_update(true); } } @@ -634,11 +637,11 @@ id)) { TransformNode* node = property_trees_.transform_tree.Node( property_trees_.transform_id_to_index_map[id]); - if (!node->data.is_currently_animating || - node->data.local == layer_id_to_transform.second) + if (!node->is_currently_animating || + node->local == layer_id_to_transform.second) continue; - node->data.local = layer_id_to_transform.second; - node->data.needs_local_transform_update = true; + node->local = layer_id_to_transform.second; + node->needs_local_transform_update = true; property_trees_.transform_tree.set_needs_update(true); } } @@ -1660,18 +1663,18 @@ // We first check if the point is clipped by viewport. const ClipNode* clip_node = clip_tree.Node(1); gfx::Rect combined_clip_in_target_space = - gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space); + gfx::ToEnclosingRect(clip_node->combined_clip_in_target_space); if (!PointHitsRect(screen_space_point, gfx::Transform(), combined_clip_in_target_space, NULL)) return true; for (const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); clip_node->id > 1; clip_node = clip_tree.parent(clip_node)) { - if (clip_node->data.applies_local_clip) { + if (clip_node->applies_local_clip) { const TransformNode* transform_node = - transform_tree.Node(clip_node->data.target_id); + transform_tree.Node(clip_node->target_id); gfx::Rect combined_clip_in_target_space = - gfx::ToEnclosingRect(clip_node->data.combined_clip_in_target_space); + gfx::ToEnclosingRect(clip_node->combined_clip_in_target_space); const LayerImpl* target_layer = layer->layer_tree_impl()->LayerById(transform_node->owner_id);
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index a7997b8..7c190da 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -14,6 +14,7 @@ #include "cc/test/layer_tree_host_common_test.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" +#include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/layer_tree_host_impl.h" #include "ui/gfx/geometry/size_conversions.h" @@ -447,7 +448,7 @@ ClipTree& clip_tree = host_impl().active_tree()->property_trees()->clip_tree; ClipNode* clip_node = clip_tree.Node(result_layer->clip_tree_index()); - EXPECT_NE(clip_node->data.transform_id, clip_node->data.target_id); + EXPECT_NE(clip_node->transform_id, clip_node->target_id); } TEST_F(LayerTreeImplTest, HitTestingSiblings) {
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index fe5b0a3..09519af 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc
@@ -211,9 +211,11 @@ &outset_top, &outset_right, &outset_bottom, &outset_left); // The filter can move pixels from outside of the clip, so allow affected_area - // to expand outside the clip. - affected_area_in_target.Inset( - -outset_left, -outset_top, -outset_right, -outset_bottom); + // to expand outside the clip. Notably the content we're concerned with here + // is not the affected area, but rather stuff slightly outside it. Thus the + // directions of the outsets are reversed from normal. + affected_area_in_target.Inset(-outset_right, -outset_bottom, -outset_left, + -outset_top); SimpleEnclosedRegion affected_occlusion = *occlusion_from_inside_target; affected_occlusion.Intersect(affected_area_in_target);
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc index 7a7599d..ec11958c 100644 --- a/cc/trees/occlusion_tracker_unittest.cc +++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -1464,12 +1464,14 @@ occlusion_rect = gfx::Rect(0, 0, 50, 200); break; case RIGHT: + // This is the right edge; filtered_surface is scaled by half. occlusion_rect = gfx::Rect(100, 0, 50, 200); break; case TOP: occlusion_rect = gfx::Rect(0, 0, 200, 50); break; case BOTTOM: + // This is the bottom edge; filtered_surface is scaled by half. occlusion_rect = gfx::Rect(0, 100, 200, 50); break; } @@ -1501,9 +1503,9 @@ occlusion.occlusion_from_outside_target().ToString()); // The surface has a background blur, so it needs pixels that are - // currently considered occluded in order to be drawn. So the pixels it - // needs should be removed some the occluded area so that when we get to - // the parent they are drawn. + // currently considered occluded in order to be drawn. The pixels it + // needs should be removed from the occluded area, so that they are drawn + // when we get to the parent. this->VisitContributingSurface(filtered_surface, &occlusion); this->EnterLayer(parent, &occlusion); @@ -1536,6 +1538,127 @@ ALL_OCCLUSIONTRACKER_TEST( OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter); +class OcclusionTrackerTestDontOccludePixelsNeededForDropShadowBackgroundFilter + : public OcclusionTrackerTest { + protected: + explicit OcclusionTrackerTestDontOccludePixelsNeededForDropShadowBackgroundFilter( + bool opaque_layers) + : OcclusionTrackerTest(opaque_layers) {} + void RunMyTest() override { + gfx::Transform scale_by_half; + scale_by_half.Scale(0.5, 0.5); + + FilterOperations filters; + filters.Append(FilterOperation::CreateDropShadowFilter(gfx::Point(10, 10), + 5, SK_ColorBLACK)); + + enum Direction { + LEFT, + RIGHT, + TOP, + BOTTOM, + LAST_DIRECTION = BOTTOM, + }; + + for (int i = 0; i <= LAST_DIRECTION; ++i) { + SCOPED_TRACE(i); + + // Make a 50x50 filtered surface that is adjacent to occluding layers + // which are above it in the z-order in various configurations. The + // surface is scaled to test that the pixel moving is done in the target + // space, where the background filter is applied. + TestContentLayerImpl* parent = this->CreateRoot( + this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); + LayerImpl* filtered_surface = this->CreateDrawingLayer( + parent, scale_by_half, gfx::PointF(50.f, 50.f), gfx::Size(100, 100), + false); + filtered_surface->test_properties()->background_filters = filters; + gfx::Rect occlusion_rect; + switch (i) { + case LEFT: + occlusion_rect = gfx::Rect(0, 0, 50, 200); + break; + case RIGHT: + // This is the right edge; filtered_surface is scaled by half. + occlusion_rect = gfx::Rect(100, 0, 50, 200); + break; + case TOP: + occlusion_rect = gfx::Rect(0, 0, 200, 50); + break; + case BOTTOM: + // This is the bottom edge; filtered_surface is scaled by half. + occlusion_rect = gfx::Rect(0, 100, 200, 50); + break; + } + + LayerImpl* occluding_layer = this->CreateDrawingLayer( + parent, this->identity_matrix, gfx::PointF(occlusion_rect.origin()), + occlusion_rect.size(), true); + occluding_layer->test_properties()->force_render_surface = false; + this->CalcDrawEtc(parent); + + TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 200, 200)); + + // This layer occludes pixels directly beside the filtered_surface. + // Because filtered surface blends pixels in a radius, it will need to see + // some of the pixels (up to radius far) underneath the occluding layers. + this->VisitLayer(occluding_layer, &occlusion); + + EXPECT_EQ(occlusion_rect.ToString(), + occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); + + this->VisitLayer(filtered_surface, &occlusion); + + // The occlusion is used fully inside the surface. + gfx::Rect occlusion_inside_surface = + occlusion_rect - gfx::Vector2d(50, 50); + EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); + EXPECT_EQ(occlusion_inside_surface.ToString(), + occlusion.occlusion_from_outside_target().ToString()); + + // The surface has a background filter, so it needs pixels that are + // currently considered occluded in order to be drawn. The pixels it + // needs should be removed from the occluded area, so that they are drawn + // when we get to the parent. + this->VisitContributingSurface(filtered_surface, &occlusion); + this->EnterLayer(parent, &occlusion); + + gfx::Rect expected_occlusion; + switch (i) { + case LEFT: + // The right half of the occlusion is close enough to cast a shadow + // that would be visible in the background filter. The shadow reaches + // 3*5 + 10 = 25 pixels to the right. + expected_occlusion = gfx::Rect(0, 0, 25, 200); + break; + case RIGHT: + // The shadow spreads 3*5 - 10 = 5 pixels to the left, so the + // occlusion must recede by 5 to account for that. + expected_occlusion = gfx::Rect(105, 0, 45, 200); + break; + case TOP: + // Similar to LEFT. + expected_occlusion = gfx::Rect(0, 0, 200, 25); + break; + case BOTTOM: + // Similar to RIGHT. + expected_occlusion = gfx::Rect(0, 105, 200, 45); + break; + } + + EXPECT_EQ(expected_occlusion.ToString(), + occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); + + this->DestroyLayers(); + } + } +}; + +ALL_OCCLUSIONTRACKER_TEST( + OcclusionTrackerTestDontOccludePixelsNeededForDropShadowBackgroundFilter); + class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice : public OcclusionTrackerTest { protected:
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 9f87656..62de5d7 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -10,60 +10,22 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/trace_event/trace_event_argument.h" -#include "cc/base/math_util.h" -#include "cc/input/main_thread_scrolling_reason.h" -#include "cc/input/scroll_state.h" #include "cc/layers/layer_impl.h" #include "cc/output/copy_output_request.h" -#include "cc/proto/gfx_conversions.h" #include "cc/proto/property_tree.pb.h" -#include "cc/proto/scroll_offset.pb.h" #include "cc/proto/synced_property_conversions.h" -#include "cc/proto/transform.pb.h" -#include "cc/proto/vector2df.pb.h" +#include "cc/trees/clip_node.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree.h" +#include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/vector2d_conversions.h" namespace cc { template <typename T> -bool TreeNode<T>::operator==(const TreeNode<T>& other) const { - return id == other.id && parent_id == other.parent_id && - owner_id == other.owner_id && data == other.data; -} - -template <typename T> -void TreeNode<T>::ToProtobuf(proto::TreeNode* proto) const { - proto->set_id(id); - proto->set_parent_id(parent_id); - proto->set_owner_id(owner_id); - data.ToProtobuf(proto); -} - -template <typename T> -void TreeNode<T>::FromProtobuf(const proto::TreeNode& proto) { - id = proto.id(); - parent_id = proto.parent_id(); - owner_id = proto.owner_id(); - data.FromProtobuf(proto); -} - -template <typename T> -void TreeNode<T>::AsValueInto(base::trace_event::TracedValue* value) const { - value->SetInteger("id", id); - value->SetInteger("parent_id", parent_id); - value->SetInteger("owner_id", owner_id); - data.AsValueInto(value); -} - -template struct TreeNode<TransformNodeData>; -template struct TreeNode<ClipNodeData>; -template struct TreeNode<EffectNodeData>; -template struct TreeNode<ScrollNodeData>; - -template <typename T> PropertyTree<T>::PropertyTree() : needs_update_(false) { nodes_.push_back(T()); @@ -71,9 +33,15 @@ back()->parent_id = -1; } +// Equivalent to +// PropertyTree<T>::~PropertyTree() = default; +// but due to a gcc bug the generated destructor will have wrong symbol +// visibility in component build. template <typename T> -PropertyTree<T>::~PropertyTree() { -} +PropertyTree<T>::~PropertyTree() {} + +template <typename T> +PropertyTree<T>& PropertyTree<T>::operator=(const PropertyTree<T>&) = default; TransformTree::TransformTree() : source_to_parent_updates_allowed_(true), @@ -83,8 +51,8 @@ cached_data_.push_back(TransformCachedNodeData()); } -TransformTree::~TransformTree() { -} +TransformTree::~TransformTree() = default; +TransformTree& TransformTree::operator=(const TransformTree&) = default; template <typename T> int PropertyTree<T>::Insert(const T& tree_node, int parent_id) { @@ -156,542 +124,6 @@ template class PropertyTree<EffectNode>; template class PropertyTree<ScrollNode>; -TransformNodeData::TransformNodeData() - : source_node_id(-1), - sorting_context_id(0), - needs_local_transform_update(true), - node_and_ancestors_are_animated_or_invertible(true), - is_invertible(true), - ancestors_are_invertible(true), - has_potential_animation(false), - is_currently_animating(false), - to_screen_is_potentially_animated(false), - has_only_translation_animations(true), - flattens_inherited_transform(false), - node_and_ancestors_are_flat(true), - node_and_ancestors_have_only_integer_translation(true), - scrolls(false), - needs_sublayer_scale(false), - affected_by_inner_viewport_bounds_delta_x(false), - affected_by_inner_viewport_bounds_delta_y(false), - affected_by_outer_viewport_bounds_delta_x(false), - affected_by_outer_viewport_bounds_delta_y(false), - in_subtree_of_page_scale_layer(false), - transform_changed(false), - post_local_scale_factor(1.0f) {} - -TransformNodeData::TransformNodeData(const TransformNodeData& other) = default; - -TransformNodeData::~TransformNodeData() { -} - -bool TransformNodeData::operator==(const TransformNodeData& other) const { - return pre_local == other.pre_local && local == other.local && - post_local == other.post_local && to_parent == other.to_parent && - source_node_id == other.source_node_id && - sorting_context_id == other.sorting_context_id && - needs_local_transform_update == other.needs_local_transform_update && - node_and_ancestors_are_animated_or_invertible == - other.node_and_ancestors_are_animated_or_invertible && - is_invertible == other.is_invertible && - ancestors_are_invertible == other.ancestors_are_invertible && - has_potential_animation == other.has_potential_animation && - is_currently_animating == other.is_currently_animating && - to_screen_is_potentially_animated == - other.to_screen_is_potentially_animated && - has_only_translation_animations == - other.has_only_translation_animations && - flattens_inherited_transform == other.flattens_inherited_transform && - node_and_ancestors_are_flat == other.node_and_ancestors_are_flat && - node_and_ancestors_have_only_integer_translation == - other.node_and_ancestors_have_only_integer_translation && - scrolls == other.scrolls && - needs_sublayer_scale == other.needs_sublayer_scale && - affected_by_inner_viewport_bounds_delta_x == - other.affected_by_inner_viewport_bounds_delta_x && - affected_by_inner_viewport_bounds_delta_y == - other.affected_by_inner_viewport_bounds_delta_y && - affected_by_outer_viewport_bounds_delta_x == - other.affected_by_outer_viewport_bounds_delta_x && - affected_by_outer_viewport_bounds_delta_y == - other.affected_by_outer_viewport_bounds_delta_y && - in_subtree_of_page_scale_layer == - other.in_subtree_of_page_scale_layer && - transform_changed == other.transform_changed && - post_local_scale_factor == other.post_local_scale_factor && - sublayer_scale == other.sublayer_scale && - scroll_offset == other.scroll_offset && - scroll_snap == other.scroll_snap && - source_offset == other.source_offset && - source_to_parent == other.source_to_parent; -} - -void TransformNodeData::update_pre_local_transform( - const gfx::Point3F& transform_origin) { - pre_local.MakeIdentity(); - pre_local.Translate3d(-transform_origin.x(), -transform_origin.y(), - -transform_origin.z()); -} - -void TransformNodeData::update_post_local_transform( - const gfx::PointF& position, - const gfx::Point3F& transform_origin) { - post_local.MakeIdentity(); - post_local.Scale(post_local_scale_factor, post_local_scale_factor); - post_local.Translate3d( - position.x() + source_offset.x() + transform_origin.x(), - position.y() + source_offset.y() + transform_origin.y(), - transform_origin.z()); -} - -void TransformNodeData::ToProtobuf(proto::TreeNode* proto) const { - DCHECK(!proto->has_transform_node_data()); - proto::TranformNodeData* data = proto->mutable_transform_node_data(); - - TransformToProto(pre_local, data->mutable_pre_local()); - TransformToProto(local, data->mutable_local()); - TransformToProto(post_local, data->mutable_post_local()); - - TransformToProto(to_parent, data->mutable_to_parent()); - - data->set_source_node_id(source_node_id); - data->set_sorting_context_id(sorting_context_id); - - data->set_needs_local_transform_update(needs_local_transform_update); - - data->set_node_and_ancestors_are_animated_or_invertible( - node_and_ancestors_are_animated_or_invertible); - - data->set_is_invertible(is_invertible); - data->set_ancestors_are_invertible(ancestors_are_invertible); - - data->set_has_potential_animation(has_potential_animation); - data->set_is_currently_animating(is_currently_animating); - data->set_to_screen_is_potentially_animated( - to_screen_is_potentially_animated); - data->set_has_only_translation_animations(has_only_translation_animations); - - data->set_flattens_inherited_transform(flattens_inherited_transform); - data->set_node_and_ancestors_are_flat(node_and_ancestors_are_flat); - - data->set_node_and_ancestors_have_only_integer_translation( - node_and_ancestors_have_only_integer_translation); - data->set_scrolls(scrolls); - data->set_needs_sublayer_scale(needs_sublayer_scale); - - data->set_affected_by_inner_viewport_bounds_delta_x( - affected_by_inner_viewport_bounds_delta_x); - data->set_affected_by_inner_viewport_bounds_delta_y( - affected_by_inner_viewport_bounds_delta_y); - data->set_affected_by_outer_viewport_bounds_delta_x( - affected_by_outer_viewport_bounds_delta_x); - data->set_affected_by_outer_viewport_bounds_delta_y( - affected_by_outer_viewport_bounds_delta_y); - - data->set_in_subtree_of_page_scale_layer(in_subtree_of_page_scale_layer); - data->set_transform_changed(transform_changed); - data->set_post_local_scale_factor(post_local_scale_factor); - - Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale()); - ScrollOffsetToProto(scroll_offset, data->mutable_scroll_offset()); - Vector2dFToProto(scroll_snap, data->mutable_scroll_snap()); - Vector2dFToProto(source_offset, data->mutable_source_offset()); - Vector2dFToProto(source_to_parent, data->mutable_source_to_parent()); -} - -void TransformNodeData::FromProtobuf(const proto::TreeNode& proto) { - DCHECK(proto.has_transform_node_data()); - const proto::TranformNodeData& data = proto.transform_node_data(); - - pre_local = ProtoToTransform(data.pre_local()); - local = ProtoToTransform(data.local()); - post_local = ProtoToTransform(data.post_local()); - - to_parent = ProtoToTransform(data.to_parent()); - - source_node_id = data.source_node_id(); - sorting_context_id = data.sorting_context_id(); - - needs_local_transform_update = data.needs_local_transform_update(); - - node_and_ancestors_are_animated_or_invertible = - data.node_and_ancestors_are_animated_or_invertible(); - - is_invertible = data.is_invertible(); - ancestors_are_invertible = data.ancestors_are_invertible(); - - has_potential_animation = data.has_potential_animation(); - is_currently_animating = data.is_currently_animating(); - to_screen_is_potentially_animated = data.to_screen_is_potentially_animated(); - has_only_translation_animations = data.has_only_translation_animations(); - - flattens_inherited_transform = data.flattens_inherited_transform(); - node_and_ancestors_are_flat = data.node_and_ancestors_are_flat(); - - node_and_ancestors_have_only_integer_translation = - data.node_and_ancestors_have_only_integer_translation(); - scrolls = data.scrolls(); - needs_sublayer_scale = data.needs_sublayer_scale(); - - affected_by_inner_viewport_bounds_delta_x = - data.affected_by_inner_viewport_bounds_delta_x(); - affected_by_inner_viewport_bounds_delta_y = - data.affected_by_inner_viewport_bounds_delta_y(); - affected_by_outer_viewport_bounds_delta_x = - data.affected_by_outer_viewport_bounds_delta_x(); - affected_by_outer_viewport_bounds_delta_y = - data.affected_by_outer_viewport_bounds_delta_y(); - - in_subtree_of_page_scale_layer = data.in_subtree_of_page_scale_layer(); - transform_changed = data.transform_changed(); - post_local_scale_factor = data.post_local_scale_factor(); - - sublayer_scale = ProtoToVector2dF(data.sublayer_scale()); - scroll_offset = ProtoToScrollOffset(data.scroll_offset()); - scroll_snap = ProtoToVector2dF(data.scroll_snap()); - source_offset = ProtoToVector2dF(data.source_offset()); - source_to_parent = ProtoToVector2dF(data.source_to_parent()); -} - -void TransformNodeData::AsValueInto( - base::trace_event::TracedValue* value) const { - MathUtil::AddToTracedValue("pre_local", pre_local, value); - MathUtil::AddToTracedValue("local", local, value); - MathUtil::AddToTracedValue("post_local", post_local, value); - // TODO(sunxd): make frameviewer work without target_id - value->SetInteger("target_id", 0); - value->SetInteger("content_target_id", 0); - value->SetInteger("source_node_id", source_node_id); - value->SetInteger("sorting_context_id", sorting_context_id); -} - -TransformCachedNodeData::TransformCachedNodeData() - : target_id(-1), content_target_id(-1) {} - -TransformCachedNodeData::TransformCachedNodeData( - const TransformCachedNodeData& other) = default; - -TransformCachedNodeData::~TransformCachedNodeData() {} - -bool TransformCachedNodeData::operator==( - const TransformCachedNodeData& other) const { - return from_target == other.from_target && to_target == other.to_target && - from_screen == other.from_screen && to_screen == other.to_screen && - target_id == other.target_id && - content_target_id == other.content_target_id; -} - -void TransformCachedNodeData::ToProtobuf( - proto::TransformCachedNodeData* proto) const { - TransformToProto(from_target, proto->mutable_from_target()); - TransformToProto(to_target, proto->mutable_to_target()); - TransformToProto(from_screen, proto->mutable_from_screen()); - TransformToProto(to_screen, proto->mutable_to_screen()); - proto->set_target_id(target_id); - proto->set_content_target_id(content_target_id); -} - -void TransformCachedNodeData::FromProtobuf( - const proto::TransformCachedNodeData& proto) { - from_target = ProtoToTransform(proto.from_target()); - to_target = ProtoToTransform(proto.to_target()); - from_screen = ProtoToTransform(proto.from_screen()); - to_screen = ProtoToTransform(proto.to_screen()); - target_id = proto.target_id(); - content_target_id = proto.content_target_id(); -} - -ClipNodeData::ClipNodeData() - : transform_id(-1), - target_id(-1), - applies_local_clip(true), - layer_clipping_uses_only_local_clip(false), - target_is_clipped(false), - layers_are_clipped(false), - layers_are_clipped_when_surfaces_disabled(false), - resets_clip(false) {} - -ClipNodeData::ClipNodeData(const ClipNodeData& other) = default; - -bool ClipNodeData::operator==(const ClipNodeData& other) const { - return clip == other.clip && - combined_clip_in_target_space == other.combined_clip_in_target_space && - clip_in_target_space == other.clip_in_target_space && - transform_id == other.transform_id && target_id == other.target_id && - applies_local_clip == other.applies_local_clip && - layer_clipping_uses_only_local_clip == - other.layer_clipping_uses_only_local_clip && - target_is_clipped == other.target_is_clipped && - layers_are_clipped == other.layers_are_clipped && - layers_are_clipped_when_surfaces_disabled == - other.layers_are_clipped_when_surfaces_disabled && - resets_clip == other.resets_clip; -} - -void ClipNodeData::ToProtobuf(proto::TreeNode* proto) const { - DCHECK(!proto->has_clip_node_data()); - proto::ClipNodeData* data = proto->mutable_clip_node_data(); - - RectFToProto(clip, data->mutable_clip()); - RectFToProto(combined_clip_in_target_space, - data->mutable_combined_clip_in_target_space()); - RectFToProto(clip_in_target_space, data->mutable_clip_in_target_space()); - - data->set_transform_id(transform_id); - data->set_target_id(target_id); - data->set_applies_local_clip(applies_local_clip); - data->set_layer_clipping_uses_only_local_clip( - layer_clipping_uses_only_local_clip); - data->set_target_is_clipped(target_is_clipped); - data->set_layers_are_clipped(layers_are_clipped); - data->set_layers_are_clipped_when_surfaces_disabled( - layers_are_clipped_when_surfaces_disabled); - data->set_resets_clip(resets_clip); -} - -void ClipNodeData::FromProtobuf(const proto::TreeNode& proto) { - DCHECK(proto.has_clip_node_data()); - const proto::ClipNodeData& data = proto.clip_node_data(); - - clip = ProtoToRectF(data.clip()); - combined_clip_in_target_space = - ProtoToRectF(data.combined_clip_in_target_space()); - clip_in_target_space = ProtoToRectF(data.clip_in_target_space()); - - transform_id = data.transform_id(); - target_id = data.target_id(); - applies_local_clip = data.applies_local_clip(); - layer_clipping_uses_only_local_clip = - data.layer_clipping_uses_only_local_clip(); - target_is_clipped = data.target_is_clipped(); - layers_are_clipped = data.layers_are_clipped(); - layers_are_clipped_when_surfaces_disabled = - data.layers_are_clipped_when_surfaces_disabled(); - resets_clip = data.resets_clip(); -} - -void ClipNodeData::AsValueInto(base::trace_event::TracedValue* value) const { - MathUtil::AddToTracedValue("clip", clip, value); - value->SetInteger("transform_id", transform_id); - value->SetInteger("target_id", target_id); - value->SetBoolean("applies_local_clip", applies_local_clip); - value->SetBoolean("layer_clipping_uses_only_local_clip", - layer_clipping_uses_only_local_clip); - value->SetBoolean("target_is_clipped", target_is_clipped); - value->SetBoolean("layers_are_clipped", layers_are_clipped); - value->SetBoolean("layers_are_clipped_when_surfaces_disabled", - layers_are_clipped_when_surfaces_disabled); - value->SetBoolean("resets_clip", resets_clip); -} - -EffectNodeData::EffectNodeData() - : opacity(1.f), - screen_space_opacity(1.f), - has_render_surface(false), - render_surface(nullptr), - has_copy_request(false), - hidden_by_backface_visibility(false), - double_sided(false), - is_drawn(true), - subtree_hidden(false), - has_potential_opacity_animation(false), - is_currently_animating_opacity(false), - effect_changed(false), - num_copy_requests_in_subtree(0), - has_unclipped_descendants(false), - transform_id(0), - clip_id(0), - target_id(0), - mask_layer_id(-1), - replica_layer_id(-1), - replica_mask_layer_id(-1) {} - -EffectNodeData::EffectNodeData(const EffectNodeData& other) = default; - -bool EffectNodeData::operator==(const EffectNodeData& other) const { - return opacity == other.opacity && - screen_space_opacity == other.screen_space_opacity && - has_render_surface == other.has_render_surface && - has_copy_request == other.has_copy_request && - background_filters == other.background_filters && - hidden_by_backface_visibility == other.hidden_by_backface_visibility && - double_sided == other.double_sided && is_drawn == other.is_drawn && - subtree_hidden == other.subtree_hidden && - has_potential_opacity_animation == - other.has_potential_opacity_animation && - is_currently_animating_opacity == - other.is_currently_animating_opacity && - effect_changed == other.effect_changed && - num_copy_requests_in_subtree == other.num_copy_requests_in_subtree && - transform_id == other.transform_id && clip_id == other.clip_id && - target_id == other.target_id && mask_layer_id == other.mask_layer_id && - replica_layer_id == other.replica_layer_id && - replica_mask_layer_id == other.replica_mask_layer_id; -} - -void EffectNodeData::ToProtobuf(proto::TreeNode* proto) const { - DCHECK(!proto->has_effect_node_data()); - proto::EffectNodeData* data = proto->mutable_effect_node_data(); - data->set_opacity(opacity); - data->set_screen_space_opacity(screen_space_opacity); - data->set_has_render_surface(has_render_surface); - data->set_has_copy_request(has_copy_request); - data->set_hidden_by_backface_visibility(hidden_by_backface_visibility); - data->set_double_sided(double_sided); - data->set_is_drawn(is_drawn); - data->set_subtree_hidden(subtree_hidden); - data->set_has_potential_opacity_animation(has_potential_opacity_animation); - data->set_is_currently_animating_opacity(is_currently_animating_opacity); - data->set_effect_changed(effect_changed); - data->set_num_copy_requests_in_subtree(num_copy_requests_in_subtree); - data->set_transform_id(transform_id); - data->set_clip_id(clip_id); - data->set_target_id(target_id); - data->set_mask_layer_id(mask_layer_id); - data->set_replica_layer_id(replica_layer_id); - data->set_replica_mask_layer_id(replica_mask_layer_id); -} - -void EffectNodeData::FromProtobuf(const proto::TreeNode& proto) { - DCHECK(proto.has_effect_node_data()); - const proto::EffectNodeData& data = proto.effect_node_data(); - - opacity = data.opacity(); - screen_space_opacity = data.screen_space_opacity(); - has_render_surface = data.has_render_surface(); - has_copy_request = data.has_copy_request(); - hidden_by_backface_visibility = data.hidden_by_backface_visibility(); - double_sided = data.double_sided(); - is_drawn = data.is_drawn(); - subtree_hidden = data.subtree_hidden(); - has_potential_opacity_animation = data.has_potential_opacity_animation(); - is_currently_animating_opacity = data.is_currently_animating_opacity(); - effect_changed = data.effect_changed(); - num_copy_requests_in_subtree = data.num_copy_requests_in_subtree(); - transform_id = data.transform_id(); - clip_id = data.clip_id(); - target_id = data.target_id(); - mask_layer_id = data.mask_layer_id(); - replica_layer_id = data.replica_layer_id(); - replica_mask_layer_id = data.replica_mask_layer_id(); -} - -void EffectNodeData::AsValueInto(base::trace_event::TracedValue* value) const { - value->SetDouble("opacity", opacity); - value->SetBoolean("has_render_surface", has_render_surface); - value->SetBoolean("has_copy_request", has_copy_request); - value->SetBoolean("double_sided", double_sided); - value->SetBoolean("is_drawn", is_drawn); - value->SetBoolean("has_potential_opacity_animation", - has_potential_opacity_animation); - value->SetBoolean("effect_changed", effect_changed); - value->SetInteger("num_copy_requests_in_subtree", - num_copy_requests_in_subtree); - value->SetInteger("transform_id", transform_id); - value->SetInteger("clip_id", clip_id); - value->SetInteger("target_id", target_id); - value->SetInteger("mask_layer_id", mask_layer_id); - value->SetInteger("replica_layer_id", replica_layer_id); - value->SetInteger("replica_mask_layer_id", replica_mask_layer_id); -} - -ScrollNodeData::ScrollNodeData() - : scrollable(false), - main_thread_scrolling_reasons( - MainThreadScrollingReason::kNotScrollingOnMain), - contains_non_fast_scrollable_region(false), - max_scroll_offset_affected_by_page_scale(false), - is_inner_viewport_scroll_layer(false), - is_outer_viewport_scroll_layer(false), - should_flatten(false), - user_scrollable_horizontal(false), - user_scrollable_vertical(false), - transform_id(0), - num_drawn_descendants(0) {} - -ScrollNodeData::ScrollNodeData(const ScrollNodeData& other) = default; - -bool ScrollNodeData::operator==(const ScrollNodeData& other) const { - return scrollable == other.scrollable && - main_thread_scrolling_reasons == other.main_thread_scrolling_reasons && - contains_non_fast_scrollable_region == - other.contains_non_fast_scrollable_region && - scroll_clip_layer_bounds == other.scroll_clip_layer_bounds && - bounds == other.bounds && - max_scroll_offset_affected_by_page_scale == - other.max_scroll_offset_affected_by_page_scale && - is_inner_viewport_scroll_layer == - other.is_inner_viewport_scroll_layer && - is_outer_viewport_scroll_layer == - other.is_outer_viewport_scroll_layer && - offset_to_transform_parent == other.offset_to_transform_parent && - should_flatten == other.should_flatten && - user_scrollable_horizontal == other.user_scrollable_horizontal && - user_scrollable_vertical == other.user_scrollable_vertical && - element_id == other.element_id && transform_id == other.transform_id; -} - -void ScrollNodeData::ToProtobuf(proto::TreeNode* proto) const { - DCHECK(!proto->has_scroll_node_data()); - proto::ScrollNodeData* data = proto->mutable_scroll_node_data(); - data->set_scrollable(scrollable); - data->set_main_thread_scrolling_reasons(main_thread_scrolling_reasons); - data->set_contains_non_fast_scrollable_region( - contains_non_fast_scrollable_region); - SizeToProto(scroll_clip_layer_bounds, - data->mutable_scroll_clip_layer_bounds()); - SizeToProto(bounds, data->mutable_bounds()); - data->set_max_scroll_offset_affected_by_page_scale( - max_scroll_offset_affected_by_page_scale); - data->set_is_inner_viewport_scroll_layer(is_inner_viewport_scroll_layer); - data->set_is_outer_viewport_scroll_layer(is_outer_viewport_scroll_layer); - Vector2dFToProto(offset_to_transform_parent, - data->mutable_offset_to_transform_parent()); - data->set_should_flatten(should_flatten); - data->set_user_scrollable_horizontal(user_scrollable_horizontal); - data->set_user_scrollable_vertical(user_scrollable_vertical); - element_id.ToProtobuf(data->mutable_element_id()); - data->set_transform_id(transform_id); -} - -void ScrollNodeData::FromProtobuf(const proto::TreeNode& proto) { - DCHECK(proto.has_scroll_node_data()); - const proto::ScrollNodeData& data = proto.scroll_node_data(); - - scrollable = data.scrollable(); - main_thread_scrolling_reasons = data.main_thread_scrolling_reasons(); - contains_non_fast_scrollable_region = - data.contains_non_fast_scrollable_region(); - scroll_clip_layer_bounds = ProtoToSize(data.scroll_clip_layer_bounds()); - bounds = ProtoToSize(data.bounds()); - max_scroll_offset_affected_by_page_scale = - data.max_scroll_offset_affected_by_page_scale(); - is_inner_viewport_scroll_layer = data.is_inner_viewport_scroll_layer(); - is_outer_viewport_scroll_layer = data.is_outer_viewport_scroll_layer(); - offset_to_transform_parent = - ProtoToVector2dF(data.offset_to_transform_parent()); - should_flatten = data.should_flatten(); - user_scrollable_horizontal = data.user_scrollable_horizontal(); - user_scrollable_vertical = data.user_scrollable_vertical(); - element_id.FromProtobuf(data.element_id()); - transform_id = data.transform_id(); -} - -void ScrollNodeData::AsValueInto(base::trace_event::TracedValue* value) const { - value->SetBoolean("scrollable", scrollable); - MathUtil::AddToTracedValue("scroll_clip_layer_bounds", - scroll_clip_layer_bounds, value); - MathUtil::AddToTracedValue("bounds", bounds, value); - MathUtil::AddToTracedValue("offset_to_transform_parent", - offset_to_transform_parent, value); - value->SetBoolean("should_flatten", should_flatten); - value->SetBoolean("user_scrollable_horizontal", user_scrollable_horizontal); - value->SetBoolean("user_scrollable_vertical", user_scrollable_vertical); - - element_id.AddToTracedValue(value); - value->SetInteger("transform_id", transform_id); -} - int TransformTree::Insert(const TransformNode& tree_node, int parent_id) { int node_id = PropertyTree<TransformNode>::Insert(tree_node, parent_id); DCHECK_EQ(node_id, static_cast<int>(cached_data_.size())); @@ -731,11 +163,11 @@ bool success = ComputeTransform(source_id, dest_id, transform); const TransformNode* dest_node = Node(dest_id); - if (!dest_node->data.needs_sublayer_scale) + if (!dest_node->needs_sublayer_scale) return success; - transform->matrix().postScale(dest_node->data.sublayer_scale.x(), - dest_node->data.sublayer_scale.y(), 1.f); + transform->matrix().postScale(dest_node->sublayer_scale.x(), + dest_node->sublayer_scale.y(), 1.f); return success; } @@ -746,15 +178,15 @@ bool success = ComputeTransform(source_id, dest_id, transform); const TransformNode* source_node = Node(source_id); - if (!source_node->data.needs_sublayer_scale) + if (!source_node->needs_sublayer_scale) return success; - if (source_node->data.sublayer_scale.x() == 0 || - source_node->data.sublayer_scale.y() == 0) + if (source_node->sublayer_scale.x() == 0 || + source_node->sublayer_scale.y() == 0) return false; - transform->Scale(1.f / source_node->data.sublayer_scale.x(), - 1.f / source_node->data.sublayer_scale.y()); + transform->Scale(1.f / source_node->sublayer_scale.x(), + 1.f / source_node->sublayer_scale.y()); return success; } @@ -766,13 +198,13 @@ bool TransformTree::NeedsSourceToParentUpdate(TransformNode* node) { return (source_to_parent_updates_allowed() && - node->parent_id != node->data.source_node_id); + node->parent_id != node->source_node_id); } void TransformTree::ResetChangeTracking() { for (int id = 1; id < static_cast<int>(size()); ++id) { TransformNode* node = Node(id); - node->data.transform_changed = false; + node->transform_changed = false; } } @@ -780,18 +212,17 @@ TransformNode* node = Node(id); TransformNode* parent_node = parent(node); TransformNode* target_node = Node(TargetId(id)); - TransformNode* source_node = Node(node->data.source_node_id); + TransformNode* source_node = Node(node->source_node_id); property_trees()->UpdateCachedNumber(); - if (node->data.needs_local_transform_update || - NeedsSourceToParentUpdate(node)) + if (node->needs_local_transform_update || NeedsSourceToParentUpdate(node)) UpdateLocalTransform(node); else UndoSnapping(node); UpdateScreenSpaceTransform(node, parent_node, target_node); UpdateSublayerScale(node); - UpdateTargetSpaceTransform(node, target_node); UpdateAnimationProperties(node, parent_node); UpdateSnapping(node); + UpdateTargetSpaceTransform(node, target_node); UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); UpdateTransformChanged(node, parent_node, source_node); UpdateNodeAndAncestorsAreAnimatedOrInvertible(node, parent_node); @@ -822,8 +253,8 @@ // R^{-1} * A^{-1}. If at least one of A and R isn't flat, the inverse of // flattened(A * R) won't be R^{-1} * A{-1}, so multiplying C's to_screen and // A's from_screen will not produce the correct result. - if (!dest || (dest->data.ancestors_are_invertible && - dest->data.node_and_ancestors_are_flat)) { + if (!dest || + (dest->ancestors_are_invertible && dest->node_and_ancestors_are_flat)) { transform->ConcatTransform(ToScreen(current->id)); if (dest) transform->ConcatTransform(FromScreen(dest->id)); @@ -843,10 +274,9 @@ source_to_destination.push_back(current->id); current = parent(current); bool destination_has_non_zero_sublayer_scale = - dest->data.sublayer_scale.x() != 0.f && - dest->data.sublayer_scale.y() != 0.f; + dest->sublayer_scale.x() != 0.f && dest->sublayer_scale.y() != 0.f; DCHECK(destination_has_non_zero_sublayer_scale || - !dest->data.ancestors_are_invertible); + !dest->ancestors_are_invertible); for (; current && current->id > dest_id; current = parent(current)) { if (destination_has_non_zero_sublayer_scale && TargetId(current->id) == dest_id && @@ -860,9 +290,8 @@ combined_transform = ToTarget(current->id); // The stored target space transform has sublayer scale baked in, but we // need the unscaled transform. - combined_transform.matrix().postScale(1.0f / dest->data.sublayer_scale.x(), - 1.0f / dest->data.sublayer_scale.y(), - 1.0f); + combined_transform.matrix().postScale( + 1.0f / dest->sublayer_scale.x(), 1.0f / dest->sublayer_scale.y(), 1.0f); } else if (current->id < dest_id) { // We have reached the lowest common ancestor of the source and destination // nodes. This case can occur when we are transforming between a node @@ -891,9 +320,9 @@ for (size_t i = 0; i < source_to_destination_size; ++i) { size_t index = source_to_destination_size - 1 - i; const TransformNode* node = Node(source_to_destination[index]); - if (node->data.flattens_inherited_transform) + if (node->flattens_inherited_transform) combined_transform.FlattenTo2d(); - combined_transform.PreconcatTransform(node->data.to_parent); + combined_transform.PreconcatTransform(node->to_parent); } transform->ConcatTransform(combined_transform); @@ -909,8 +338,8 @@ // Just as in CombineTransformsBetween, we can use screen space transforms in // this computation only when there isn't any non-trivial flattening // involved. - if (current->data.ancestors_are_invertible && - current->data.node_and_ancestors_are_flat) { + if (current->ancestors_are_invertible && + current->node_and_ancestors_are_flat) { transform->PreconcatTransform(FromScreen(current->id)); if (dest) transform->PreconcatTransform(ToScreen(dest->id)); @@ -931,11 +360,11 @@ } void TransformTree::UpdateLocalTransform(TransformNode* node) { - gfx::Transform transform = node->data.post_local; + gfx::Transform transform = node->post_local; if (NeedsSourceToParentUpdate(node)) { gfx::Transform to_parent; - ComputeTransform(node->data.source_node_id, node->parent_id, &to_parent); - node->data.source_to_parent = to_parent.To2dTranslation(); + ComputeTransform(node->source_node_id, node->parent_id, &to_parent); + node->source_to_parent = to_parent.To2dTranslation(); } gfx::Vector2dF fixed_position_adjustment; @@ -943,76 +372,73 @@ property_trees()->inner_viewport_container_bounds_delta(); gfx::Vector2dF outer_viewport_bounds_delta = property_trees()->outer_viewport_container_bounds_delta(); - if (node->data.affected_by_inner_viewport_bounds_delta_x) + if (node->affected_by_inner_viewport_bounds_delta_x) fixed_position_adjustment.set_x(inner_viewport_bounds_delta.x()); - else if (node->data.affected_by_outer_viewport_bounds_delta_x) + else if (node->affected_by_outer_viewport_bounds_delta_x) fixed_position_adjustment.set_x(outer_viewport_bounds_delta.x()); - if (node->data.affected_by_inner_viewport_bounds_delta_y) + if (node->affected_by_inner_viewport_bounds_delta_y) fixed_position_adjustment.set_y(inner_viewport_bounds_delta.y()); - else if (node->data.affected_by_outer_viewport_bounds_delta_y) + else if (node->affected_by_outer_viewport_bounds_delta_y) fixed_position_adjustment.set_y(outer_viewport_bounds_delta.y()); - transform.Translate( - node->data.source_to_parent.x() - node->data.scroll_offset.x() + - fixed_position_adjustment.x(), - node->data.source_to_parent.y() - node->data.scroll_offset.y() + - fixed_position_adjustment.y()); - transform.PreconcatTransform(node->data.local); - transform.PreconcatTransform(node->data.pre_local); - node->data.set_to_parent(transform); - node->data.needs_local_transform_update = false; + transform.Translate(node->source_to_parent.x() - node->scroll_offset.x() + + fixed_position_adjustment.x(), + node->source_to_parent.y() - node->scroll_offset.y() + + fixed_position_adjustment.y()); + transform.PreconcatTransform(node->local); + transform.PreconcatTransform(node->pre_local); + node->set_to_parent(transform); + node->needs_local_transform_update = false; } void TransformTree::UpdateScreenSpaceTransform(TransformNode* node, TransformNode* parent_node, TransformNode* target_node) { if (!parent_node) { - SetToScreen(node->id, node->data.to_parent); - node->data.ancestors_are_invertible = true; - node->data.to_screen_is_potentially_animated = false; - node->data.node_and_ancestors_are_flat = node->data.to_parent.IsFlat(); + SetToScreen(node->id, node->to_parent); + node->ancestors_are_invertible = true; + node->to_screen_is_potentially_animated = false; + node->node_and_ancestors_are_flat = node->to_parent.IsFlat(); } else { gfx::Transform to_screen_space_transform = ToScreen(parent_node->id); - if (node->data.flattens_inherited_transform) + if (node->flattens_inherited_transform) to_screen_space_transform.FlattenTo2d(); - to_screen_space_transform.PreconcatTransform(node->data.to_parent); - node->data.ancestors_are_invertible = - parent_node->data.ancestors_are_invertible; - node->data.node_and_ancestors_are_flat = - parent_node->data.node_and_ancestors_are_flat && - node->data.to_parent.IsFlat(); + to_screen_space_transform.PreconcatTransform(node->to_parent); + node->ancestors_are_invertible = parent_node->ancestors_are_invertible; + node->node_and_ancestors_are_flat = + parent_node->node_and_ancestors_are_flat && node->to_parent.IsFlat(); SetToScreen(node->id, to_screen_space_transform); } gfx::Transform from_screen; if (!ToScreen(node->id).GetInverse(&from_screen)) - node->data.ancestors_are_invertible = false; + node->ancestors_are_invertible = false; SetFromScreen(node->id, from_screen); } void TransformTree::UpdateSublayerScale(TransformNode* node) { // The sublayer scale depends on the screen space transform, so update it too. - if (!node->data.needs_sublayer_scale) { - node->data.sublayer_scale = gfx::Vector2dF(1.0f, 1.0f); + if (!node->needs_sublayer_scale) { + node->sublayer_scale = gfx::Vector2dF(1.0f, 1.0f); return; } float layer_scale_factor = device_scale_factor_ * device_transform_scale_factor_; - if (node->data.in_subtree_of_page_scale_layer) + if (node->in_subtree_of_page_scale_layer) layer_scale_factor *= page_scale_factor_; - node->data.sublayer_scale = MathUtil::ComputeTransform2dScaleComponents( + node->sublayer_scale = MathUtil::ComputeTransform2dScaleComponents( ToScreen(node->id), layer_scale_factor); } void TransformTree::UpdateTargetSpaceTransform(TransformNode* node, TransformNode* target_node) { gfx::Transform target_space_transform; - if (node->data.needs_sublayer_scale) { + if (node->needs_sublayer_scale) { target_space_transform.MakeIdentity(); - target_space_transform.Scale(node->data.sublayer_scale.x(), - node->data.sublayer_scale.y()); + target_space_transform.Scale(node->sublayer_scale.x(), + node->sublayer_scale.y()); } else { // In order to include the root transform for the root surface, we walk up // to the root of the transform tree in ComputeTransform. @@ -1023,7 +449,7 @@ gfx::Transform from_target; if (!target_space_transform.GetInverse(&from_target)) - node->data.ancestors_are_invertible = false; + node->ancestors_are_invertible = false; SetToTarget(node->id, target_space_transform); SetFromTarget(node->id, from_target); } @@ -1032,23 +458,22 @@ TransformNode* parent_node) { bool ancestor_is_animating = false; if (parent_node) - ancestor_is_animating = parent_node->data.to_screen_is_potentially_animated; - node->data.to_screen_is_potentially_animated = - node->data.has_potential_animation || ancestor_is_animating; + ancestor_is_animating = parent_node->to_screen_is_potentially_animated; + node->to_screen_is_potentially_animated = + node->has_potential_animation || ancestor_is_animating; } void TransformTree::UndoSnapping(TransformNode* node) { // to_parent transform has the scroll snap from previous frame baked in. // We need to undo it and use the un-snapped transform to compute current // target and screen space transforms. - node->data.to_parent.Translate(-node->data.scroll_snap.x(), - -node->data.scroll_snap.y()); + node->to_parent.Translate(-node->scroll_snap.x(), -node->scroll_snap.y()); } void TransformTree::UpdateSnapping(TransformNode* node) { - if (!node->data.scrolls || node->data.to_screen_is_potentially_animated || + if (!node->scrolls || node->to_screen_is_potentially_animated || !ToScreen(node->id).IsScaleOrTranslation() || - !node->data.ancestors_are_invertible) { + !node->ancestors_are_invertible) { return; } @@ -1071,67 +496,60 @@ // Now that we have our scroll delta, we must apply it to each of our // combined, to/from matrices. SetToScreen(node->id, rounded); - node->data.to_parent.Translate(translation.x(), translation.y()); + node->to_parent.Translate(translation.x(), translation.y()); gfx::Transform from_screen = FromScreen(node->id); from_screen.matrix().postTranslate(-translation.x(), -translation.y(), 0); SetFromScreen(node->id, from_screen); - gfx::Transform to_target = ToTarget(node->id); - to_target.Translate(translation.x(), translation.y()); - SetToTarget(node->id, to_target); - gfx::Transform from_target = FromTarget(node->id); - from_target.matrix().postTranslate(-translation.x(), -translation.y(), 0); - SetFromTarget(node->id, from_target); - node->data.scroll_snap = translation; + node->scroll_snap = translation; } void TransformTree::UpdateTransformChanged(TransformNode* node, TransformNode* parent_node, TransformNode* source_node) { - if (parent_node && parent_node->data.transform_changed) { - node->data.transform_changed = true; + if (parent_node && parent_node->transform_changed) { + node->transform_changed = true; return; } if (source_node && source_node->id != parent_node->id && - source_to_parent_updates_allowed_ && source_node->data.transform_changed) - node->data.transform_changed = true; + source_to_parent_updates_allowed_ && source_node->transform_changed) + node->transform_changed = true; } void TransformTree::UpdateNodeAndAncestorsAreAnimatedOrInvertible( TransformNode* node, TransformNode* parent_node) { if (!parent_node) { - node->data.node_and_ancestors_are_animated_or_invertible = - node->data.has_potential_animation || node->data.is_invertible; + node->node_and_ancestors_are_animated_or_invertible = + node->has_potential_animation || node->is_invertible; return; } - if (!parent_node->data.node_and_ancestors_are_animated_or_invertible) { - node->data.node_and_ancestors_are_animated_or_invertible = false; + if (!parent_node->node_and_ancestors_are_animated_or_invertible) { + node->node_and_ancestors_are_animated_or_invertible = false; return; } - bool is_invertible = node->data.is_invertible; + bool is_invertible = node->is_invertible; // Even when the current node's transform and the parent's screen space // transform are invertible, the current node's screen space transform can // become uninvertible due to floating-point arithmetic. - if (!node->data.ancestors_are_invertible && - parent_node->data.ancestors_are_invertible) + if (!node->ancestors_are_invertible && parent_node->ancestors_are_invertible) is_invertible = false; - node->data.node_and_ancestors_are_animated_or_invertible = - node->data.has_potential_animation || is_invertible; + node->node_and_ancestors_are_animated_or_invertible = + node->has_potential_animation || is_invertible; } void TransformTree::SetDeviceTransform(const gfx::Transform& transform, gfx::PointF root_position) { gfx::Transform root_post_local = transform; TransformNode* node = Node(1); - root_post_local.Scale(node->data.post_local_scale_factor, - node->data.post_local_scale_factor); + root_post_local.Scale(node->post_local_scale_factor, + node->post_local_scale_factor); root_post_local.Translate(root_position.x(), root_position.y()); - if (node->data.post_local == root_post_local) + if (node->post_local == root_post_local) return; - node->data.post_local = root_post_local; - node->data.needs_local_transform_update = true; + node->post_local = root_post_local; + node->needs_local_transform_update = true; set_needs_update(true); } @@ -1152,7 +570,7 @@ set_needs_update(true); for (int i : nodes_affected_by_inner_viewport_bounds_delta_) - Node(i)->data.needs_local_transform_update = true; + Node(i)->needs_local_transform_update = true; } void TransformTree::UpdateOuterViewportContainerBoundsDelta() { @@ -1161,7 +579,7 @@ set_needs_update(true); for (int i : nodes_affected_by_outer_viewport_bounds_delta_) - Node(i)->data.needs_local_transform_update = true; + Node(i)->needs_local_transform_update = true; } void TransformTree::AddNodeAffectedByInnerViewportBoundsDelta(int node_id) { @@ -1250,10 +668,9 @@ } const TransformNode* node = Node(id); gfx::Transform screen_space_transform = ToScreen(id); - if (node->data.sublayer_scale.x() != 0.0 && - node->data.sublayer_scale.y() != 0.0) - screen_space_transform.Scale(1.0 / node->data.sublayer_scale.x(), - 1.0 / node->data.sublayer_scale.y()); + if (node->sublayer_scale.x() != 0.0 && node->sublayer_scale.y() != 0.0) + screen_space_transform.Scale(1.0 / node->sublayer_scale.x(), + 1.0 / node->sublayer_scale.y()); return screen_space_transform; } @@ -1340,14 +757,14 @@ } float EffectTree::EffectiveOpacity(const EffectNode* node) const { - return node->data.subtree_hidden ? 0.f : node->data.opacity; + return node->subtree_hidden ? 0.f : node->opacity; } void EffectTree::UpdateOpacities(EffectNode* node, EffectNode* parent_node) { - node->data.screen_space_opacity = EffectiveOpacity(node); + node->screen_space_opacity = EffectiveOpacity(node); if (parent_node) - node->data.screen_space_opacity *= parent_node->data.screen_space_opacity; + node->screen_space_opacity *= parent_node->screen_space_opacity; } void EffectTree::UpdateIsDrawn(EffectNode* node, EffectNode* parent_node) { @@ -1358,64 +775,80 @@ // 2) Nodes that have a background filter. // 3) Nodes with animating screen space opacity on main thread or pending tree // are drawn if their parent is drawn irrespective of their opacity. - if (node->data.has_copy_request) - node->data.is_drawn = true; + if (node->has_copy_request) + node->is_drawn = true; else if (EffectiveOpacity(node) == 0.f && - (!node->data.has_potential_opacity_animation || + (!node->has_potential_opacity_animation || property_trees()->is_active) && - node->data.background_filters.IsEmpty()) - node->data.is_drawn = false; + node->background_filters.IsEmpty()) + node->is_drawn = false; else if (parent_node) - node->data.is_drawn = parent_node->data.is_drawn; + node->is_drawn = parent_node->is_drawn; else - node->data.is_drawn = true; + node->is_drawn = true; } void EffectTree::UpdateEffectChanged(EffectNode* node, EffectNode* parent_node) { - if (parent_node && parent_node->data.effect_changed) { - node->data.effect_changed = true; + if (parent_node && parent_node->effect_changed) { + node->effect_changed = true; } } void EffectTree::UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node) { if (!parent_node) { - node->data.hidden_by_backface_visibility = false; + node->hidden_by_backface_visibility = false; return; } - if (parent_node->data.hidden_by_backface_visibility) { - node->data.hidden_by_backface_visibility = true; + if (parent_node->hidden_by_backface_visibility) { + node->hidden_by_backface_visibility = true; return; } TransformTree& transform_tree = property_trees()->transform_tree; - if (node->data.has_render_surface && !node->data.double_sided) { - TransformNode* transform_node = - transform_tree.Node(node->data.transform_id); - if (transform_node->data.is_invertible && - transform_node->data.ancestors_are_invertible) { - if (transform_node->data.sorting_context_id) { + if (node->has_render_surface && !node->double_sided) { + TransformNode* transform_node = transform_tree.Node(node->transform_id); + if (transform_node->is_invertible && + transform_node->ancestors_are_invertible) { + if (transform_node->sorting_context_id) { const TransformNode* parent_transform_node = transform_tree.parent(transform_node); if (parent_transform_node && - parent_transform_node->data.sorting_context_id == - transform_node->data.sorting_context_id) { + parent_transform_node->sorting_context_id == + transform_node->sorting_context_id) { gfx::Transform surface_draw_transform; transform_tree.ComputeTransform( transform_node->id, transform_tree.TargetId(transform_node->id), &surface_draw_transform); - node->data.hidden_by_backface_visibility = + node->hidden_by_backface_visibility = surface_draw_transform.IsBackFaceVisible(); } else { - node->data.hidden_by_backface_visibility = - transform_node->data.local.IsBackFaceVisible(); + node->hidden_by_backface_visibility = + transform_node->local.IsBackFaceVisible(); } return; } } } - node->data.hidden_by_backface_visibility = false; + node->hidden_by_backface_visibility = false; +} + +void EffectTree::UpdateSublayerScale(EffectNode* effect_node) { + if (!effect_node->has_render_surface || effect_node->transform_id == 0) { + effect_node->sublayer_scale = gfx::Vector2dF(1.0f, 1.0f); + return; + } + + TransformTree& transform_tree = property_trees()->transform_tree; + float layer_scale_factor = transform_tree.device_scale_factor() * + transform_tree.device_transform_scale_factor(); + TransformNode* transform_node = + transform_tree.Node(effect_node->transform_id); + if (transform_node->in_subtree_of_page_scale_layer) + layer_scale_factor *= transform_tree.page_scale_factor(); + effect_node->sublayer_scale = MathUtil::ComputeTransform2dScaleComponents( + transform_tree.ToScreen(transform_node->id), layer_scale_factor); } void EffectTree::UpdateEffects(int id) { @@ -1426,6 +859,7 @@ UpdateIsDrawn(node, parent_node); UpdateEffectChanged(node, parent_node); UpdateBackfaceVisibility(node, parent_node); + UpdateSublayerScale(node); } void EffectTree::AddCopyRequest(int node_id, @@ -1463,8 +897,8 @@ int node_id, std::vector<std::unique_ptr<CopyOutputRequest>>* requests) { EffectNode* effect_node = Node(node_id); - DCHECK(effect_node->data.has_render_surface); - DCHECK(effect_node->data.has_copy_request); + DCHECK(effect_node->has_render_surface); + DCHECK(effect_node->has_copy_request); auto range = copy_requests_.equal_range(node_id); for (auto it = range.first; it != range.second; ++it) @@ -1477,7 +911,7 @@ // The area needs to be transformed from the space of content that draws to // the surface to the space of the surface itself. - int destination_id = effect_node->data.transform_id; + int destination_id = effect_node->transform_id; int source_id; if (effect_node->parent_id != -1) { // For non-root surfaces, transform only by sub-layer scale. @@ -1503,8 +937,8 @@ void EffectTree::ClearCopyRequests() { for (auto& node : nodes()) { - node.data.num_copy_requests_in_subtree = 0; - node.data.has_copy_request = false; + node.num_copy_requests_in_subtree = 0; + node.has_copy_request = false; } // Any copy requests that are still left will be aborted (sending an empty @@ -1517,13 +951,13 @@ DCHECK_GE(id, 0); const EffectNode* node = Node(id); while (node->id > 1) { - if (node->data.has_copy_request) + if (node->has_copy_request) return node->id; node = parent(node); } - if (node->data.has_copy_request) + if (node->has_copy_request) return node->id; else return -1; @@ -1539,41 +973,41 @@ // copy requests. EffectNode* node = Node(id); EffectNode* parent_node = parent(node); - return node->data.is_drawn && (!parent_node || parent_node->data.is_drawn); + return node->is_drawn && (!parent_node || parent_node->is_drawn); } void EffectTree::ResetChangeTracking() { for (int id = 1; id < static_cast<int>(size()); ++id) { EffectNode* node = Node(id); - node->data.effect_changed = false; + node->effect_changed = false; } } void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations( TransformNode* node, TransformNode* parent_node) { - node->data.node_and_ancestors_have_only_integer_translation = - node->data.to_parent.IsIdentityOrIntegerTranslation(); + node->node_and_ancestors_have_only_integer_translation = + node->to_parent.IsIdentityOrIntegerTranslation(); if (parent_node) - node->data.node_and_ancestors_have_only_integer_translation = - node->data.node_and_ancestors_have_only_integer_translation && - parent_node->data.node_and_ancestors_have_only_integer_translation; + node->node_and_ancestors_have_only_integer_translation = + node->node_and_ancestors_have_only_integer_translation && + parent_node->node_and_ancestors_have_only_integer_translation; } void ClipTree::SetViewportClip(gfx::RectF viewport_rect) { if (size() < 2) return; ClipNode* node = Node(1); - if (viewport_rect == node->data.clip) + if (viewport_rect == node->clip) return; - node->data.clip = viewport_rect; + node->clip = viewport_rect; set_needs_update(true); } gfx::RectF ClipTree::ViewportClip() { const unsigned long min_size = 1; DCHECK_GT(size(), min_size); - return Node(1)->data.clip; + return Node(1)->clip; } bool ClipTree::operator==(const ClipTree& other) const { @@ -1730,21 +1164,21 @@ gfx::ScrollOffset ScrollTree::MaxScrollOffset(int scroll_node_id) const { const ScrollNode* scroll_node = Node(scroll_node_id); - gfx::SizeF scroll_bounds = gfx::SizeF(scroll_node->data.bounds.width(), - scroll_node->data.bounds.height()); + gfx::SizeF scroll_bounds = + gfx::SizeF(scroll_node->bounds.width(), scroll_node->bounds.height()); - if (scroll_node->data.is_inner_viewport_scroll_layer) { + if (scroll_node->is_inner_viewport_scroll_layer) { scroll_bounds.Enlarge( property_trees()->inner_viewport_scroll_bounds_delta().x(), property_trees()->inner_viewport_scroll_bounds_delta().y()); } - if (!scroll_node->data.scrollable || scroll_bounds.IsEmpty()) + if (!scroll_node->scrollable || scroll_bounds.IsEmpty()) return gfx::ScrollOffset(); TransformTree& transform_tree = property_trees()->transform_tree; float scale_factor = 1.f; - if (scroll_node->data.max_scroll_offset_affected_by_page_scale) + if (scroll_node->max_scroll_offset_affected_by_page_scale) scale_factor = transform_tree.page_scale_factor(); gfx::SizeF scaled_scroll_bounds = gfx::ScaleSize(scroll_bounds, scale_factor); @@ -1764,14 +1198,13 @@ gfx::Size ScrollTree::scroll_clip_layer_bounds(int scroll_node_id) const { const ScrollNode* scroll_node = Node(scroll_node_id); - gfx::Size scroll_clip_layer_bounds = - scroll_node->data.scroll_clip_layer_bounds; + gfx::Size scroll_clip_layer_bounds = scroll_node->scroll_clip_layer_bounds; gfx::Vector2dF scroll_clip_layer_bounds_delta; - if (scroll_node->data.is_inner_viewport_scroll_layer) { + if (scroll_node->is_inner_viewport_scroll_layer) { scroll_clip_layer_bounds_delta.Add( property_trees()->inner_viewport_container_bounds_delta()); - } else if (scroll_node->data.is_outer_viewport_scroll_layer) { + } else if (scroll_node->is_outer_viewport_scroll_layer) { scroll_clip_layer_bounds_delta.Add( property_trees()->outer_viewport_container_bounds_delta()); } @@ -1802,13 +1235,13 @@ const ScrollNode* scroll_node = Node(scroll_node_id); const TransformTree& transform_tree = property_trees()->transform_tree; const TransformNode* transform_node = - transform_tree.Node(scroll_node->data.transform_id); + transform_tree.Node(scroll_node->transform_id); gfx::Transform screen_space_transform( - 1, 0, 0, 1, scroll_node->data.offset_to_transform_parent.x(), - scroll_node->data.offset_to_transform_parent.y()); + 1, 0, 0, 1, scroll_node->offset_to_transform_parent.x(), + scroll_node->offset_to_transform_parent.y()); screen_space_transform.ConcatTransform( transform_tree.ToScreen(transform_node->id)); - if (scroll_node->data.should_flatten) + if (scroll_node->should_flatten) screen_space_transform.FlattenTo2d(); return screen_space_transform; } @@ -2016,17 +1449,17 @@ const gfx::Vector2dF& scroll, LayerTreeImpl* layer_tree_impl) { gfx::ScrollOffset adjusted_scroll(scroll); - if (!scroll_node->data.user_scrollable_horizontal) + if (!scroll_node->user_scrollable_horizontal) adjusted_scroll.set_x(0); - if (!scroll_node->data.user_scrollable_vertical) + if (!scroll_node->user_scrollable_vertical) adjusted_scroll.set_y(0); - DCHECK(scroll_node->data.scrollable); + DCHECK(scroll_node->scrollable); gfx::ScrollOffset old_offset = current_scroll_offset(scroll_node->owner_id); gfx::ScrollOffset new_offset = ClampScrollOffsetToLimits(old_offset + adjusted_scroll, scroll_node); if (SetScrollOffset(scroll_node->owner_id, new_offset)) layer_tree_impl->DidUpdateScrollOffset(scroll_node->owner_id, - scroll_node->data.transform_id); + scroll_node->transform_id); gfx::ScrollOffset unscrolled = old_offset + gfx::ScrollOffset(scroll) - new_offset; @@ -2191,11 +1624,11 @@ effect_tree.Node(effect_id_to_index_map[id]); EffectNode* target_effect_node = target_tree->effect_tree.Node(target_tree->effect_id_to_index_map[id]); - float source_opacity = source_effect_node->data.opacity; - float target_opacity = target_effect_node->data.opacity; + float source_opacity = source_effect_node->opacity; + float target_opacity = target_effect_node->opacity; if (source_opacity == target_opacity) continue; - target_effect_node->data.opacity = source_opacity; + target_effect_node->opacity = source_opacity; target_tree->effect_tree.set_needs_update(true); } } @@ -2235,7 +1668,7 @@ for (int i = 1; i < static_cast<int>(transform_tree.size()); ++i) { TransformNode* node = transform_tree.Node(i); TransformNode* parent_node = transform_tree.parent(node); - TransformNode* source_node = transform_tree.Node(node->data.source_node_id); + TransformNode* source_node = transform_tree.Node(node->source_node_id); transform_tree.UpdateTransformChanged(node, parent_node, source_node); } } @@ -2243,16 +1676,16 @@ void PropertyTrees::PushChangeTrackingTo(PropertyTrees* tree) { for (int id = 1; id < static_cast<int>(effect_tree.size()); ++id) { EffectNode* node = effect_tree.Node(id); - if (node->data.effect_changed) { + if (node->effect_changed) { EffectNode* target_node = tree->effect_tree.Node(node->id); - target_node->data.effect_changed = true; + target_node->effect_changed = true; } } for (int id = 1; id < static_cast<int>(transform_tree.size()); ++id) { TransformNode* node = transform_tree.Node(id); - if (node->data.transform_changed) { + if (node->transform_changed) { TransformNode* target_node = tree->transform_tree.Node(node->id); - target_node->data.transform_changed = true; + target_node->transform_changed = true; } } // Ensure that change tracking is updated even if property trees don't have @@ -2332,8 +1765,7 @@ cached_data_.animation_scales[transform_node_id] .to_screen_has_scale_animation = - !node->data.has_only_translation_animations || - ancestor_is_animating_scale; + !node->has_only_translation_animations || ancestor_is_animating_scale; // Once we've failed to compute a maximum animated scale at an ancestor, we // continue to fail. @@ -2351,8 +1783,7 @@ // as another node is decreasing scale from 10 to 1. Naively combining these // scales would produce a scale of 100. bool failed_for_multiple_scale_animations = - ancestor_is_animating_scale && - !node->data.has_only_translation_animations; + ancestor_is_animating_scale && !node->has_only_translation_animations; if (failed_at_ancestor || failed_for_non_scale_or_translation || failed_for_multiple_scale_animations) { @@ -2371,10 +1802,10 @@ .combined_maximum_animation_target_scale = 0.f; cached_data_.animation_scales[transform_node_id] .combined_starting_animation_scale = 0.f; - } else if (node->data.has_only_translation_animations) { + } else if (node->has_only_translation_animations) { // An ancestor is animating scale. gfx::Vector2dF local_scales = - MathUtil::ComputeTransform2dScaleComponents(node->data.local, 0.f); + MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f); float max_local_scale = std::max(local_scales.x(), local_scales.y()); cached_data_.animation_scales[transform_node_id] .combined_maximum_animation_target_scale = @@ -2393,7 +1824,7 @@ layer_impl, &cached_data_.animation_scales[transform_node_id] .local_starting_animation_scale); gfx::Vector2dF local_scales = - MathUtil::ComputeTransform2dScaleComponents(node->data.local, 0.f); + MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f); float max_local_scale = std::max(local_scales.x(), local_scales.y()); if (cached_data_.animation_scales[transform_node_id]
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index b40c909..4dbf6c4 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -14,7 +14,6 @@ #include "cc/animation/element_id.h" #include "cc/base/cc_export.h" #include "cc/base/synced_property.h" -#include "cc/output/filter_operations.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/transform.h" @@ -28,22 +27,21 @@ namespace cc { namespace proto { -class ClipNodeData; -class EffectNodeData; class PropertyTree; class PropertyTrees; class ScrollNodeData; -class TransformNodeData; -class TransformCachedNodeData; -class TransformTreeData; class TreeNode; } // namespace proto class CopyOutputRequest; class LayerTreeImpl; -class RenderSurfaceImpl; class ScrollState; +struct ClipNode; +struct EffectNode; struct ScrollAndScaleSet; +struct ScrollNode; +struct TransformNode; +struct TransformCachedNodeData; // ------------------------------*IMPORTANT*--------------------------------- // Each class declared here has a corresponding proto defined in @@ -54,288 +52,6 @@ typedef SyncedProperty<AdditionGroup<gfx::ScrollOffset>> SyncedScrollOffset; -template <typename T> -struct CC_EXPORT TreeNode { - TreeNode() : id(-1), parent_id(-1), owner_id(-1), data() {} - int id; - int parent_id; - int owner_id; - T data; - - bool operator==(const TreeNode<T>& other) const; - - void ToProtobuf(proto::TreeNode* proto) const; - void FromProtobuf(const proto::TreeNode& proto); - - void AsValueInto(base::trace_event::TracedValue* value) const; -}; - -struct CC_EXPORT TransformNodeData { - TransformNodeData(); - TransformNodeData(const TransformNodeData& other); - ~TransformNodeData(); - - // The local transform information is combined to form to_parent (ignoring - // snapping) as follows: - // - // to_parent = M_post_local * T_scroll * M_local * M_pre_local. - // - // The pre/post may seem odd when read LTR, but we multiply our points from - // the right, so the pre_local matrix affects the result "first". This lines - // up with the notions of pre/post used in skia and gfx::Transform. - // - // TODO(vollick): The values labeled with "will be moved..." take up a lot of - // space, but are only necessary for animated or scrolled nodes (otherwise - // we'll just use the baked to_parent). These values will be ultimately stored - // directly on the transform/scroll display list items when that's possible, - // or potentially in a scroll tree. - // - // TODO(vollick): will be moved when accelerated effects are implemented. - gfx::Transform pre_local; - gfx::Transform local; - gfx::Transform post_local; - - gfx::Transform to_parent; - - // This is the node with respect to which source_offset is defined. This will - // not be needed once layerization moves to cc, but is needed in order to - // efficiently update the transform tree for changes to position in the layer - // tree. - int source_node_id; - - // This id determines which 3d rendering context the node is in. 0 is a - // special value and indicates that the node is not in any 3d rendering - // context. - int sorting_context_id; - - // TODO(vollick): will be moved when accelerated effects are implemented. - bool needs_local_transform_update : 1; - - bool node_and_ancestors_are_animated_or_invertible : 1; - - bool is_invertible : 1; - bool ancestors_are_invertible : 1; - - bool has_potential_animation : 1; - bool is_currently_animating : 1; - bool to_screen_is_potentially_animated : 1; - bool has_only_translation_animations : 1; - - // Flattening, when needed, is only applied to a node's inherited transform, - // never to its local transform. - bool flattens_inherited_transform : 1; - - // This is true if the to_parent transform at every node on the path to the - // root is flat. - bool node_and_ancestors_are_flat : 1; - - // This is needed to know if a layer can use lcd text. - bool node_and_ancestors_have_only_integer_translation : 1; - - bool scrolls : 1; - - bool needs_sublayer_scale : 1; - - // These are used to position nodes wrt the right or bottom of the inner or - // outer viewport. - bool affected_by_inner_viewport_bounds_delta_x : 1; - bool affected_by_inner_viewport_bounds_delta_y : 1; - bool affected_by_outer_viewport_bounds_delta_x : 1; - bool affected_by_outer_viewport_bounds_delta_y : 1; - - // Layer scale factor is used as a fallback when we either cannot adjust - // raster scale or if the raster scale cannot be extracted from the screen - // space transform. For layers in the subtree of the page scale layer, the - // layer scale factor should include the page scale factor. - bool in_subtree_of_page_scale_layer : 1; - - // We need to track changes to to_screen transform to compute the damage rect. - bool transform_changed : 1; - - // TODO(vollick): will be moved when accelerated effects are implemented. - float post_local_scale_factor; - - gfx::Vector2dF sublayer_scale; - - // TODO(vollick): will be moved when accelerated effects are implemented. - gfx::ScrollOffset scroll_offset; - - // We scroll snap where possible, but this means fixed-pos elements must be - // adjusted. This value stores the snapped amount for this purpose. - gfx::Vector2dF scroll_snap; - - // TODO(vollick): will be moved when accelerated effects are implemented. - gfx::Vector2dF source_offset; - gfx::Vector2dF source_to_parent; - - bool operator==(const TransformNodeData& other) const; - - void set_to_parent(const gfx::Transform& transform) { - to_parent = transform; - is_invertible = to_parent.IsInvertible(); - } - - void update_pre_local_transform(const gfx::Point3F& transform_origin); - - void update_post_local_transform(const gfx::PointF& position, - const gfx::Point3F& transform_origin); - - void ToProtobuf(proto::TreeNode* proto) const; - void FromProtobuf(const proto::TreeNode& proto); - - void AsValueInto(base::trace_event::TracedValue* value) const; -}; - -// TODO(sunxd): move this into PropertyTrees::cached_data_. -struct CC_EXPORT TransformCachedNodeData { - TransformCachedNodeData(); - TransformCachedNodeData(const TransformCachedNodeData& other); - ~TransformCachedNodeData(); - - gfx::Transform from_target; - gfx::Transform to_target; - gfx::Transform from_screen; - gfx::Transform to_screen; - int target_id; - // This id is used for all content that draws into a render surface associated - // with this transform node. - int content_target_id; - - bool operator==(const TransformCachedNodeData& other) const; - - void ToProtobuf(proto::TransformCachedNodeData* proto) const; - void FromProtobuf(const proto::TransformCachedNodeData& proto); -}; - -typedef TreeNode<TransformNodeData> TransformNode; - -struct CC_EXPORT ClipNodeData { - ClipNodeData(); - ClipNodeData(const ClipNodeData& other); - - // The clip rect that this node contributes, expressed in the space of its - // transform node. - gfx::RectF clip; - - // Clip nodes are uses for two reasons. First, they are used for determining - // which parts of each layer are visible. Second, they are used for - // determining whether a clip needs to be applied when drawing a layer, and if - // so, the rect that needs to be used. These can be different since not all - // clips need to be applied directly to each layer. For example, a layer is - // implicitly clipped by the bounds of its target render surface and by clips - // applied to this surface. |combined_clip_in_target_space| is used for - // computing visible rects, and |clip_in_target_space| is used for computing - // clips applied at draw time. Both rects are expressed in the space of the - // target transform node, and may include clips contributed by ancestors. - gfx::RectF combined_clip_in_target_space; - gfx::RectF clip_in_target_space; - - // The id of the transform node that defines the clip node's local space. - int transform_id; - - // The id of the transform node that defines the clip node's target space. - int target_id; - - // Whether this node contributes a new clip (that is, whether |clip| needs to - // be applied), rather than only inheriting ancestor clips. - bool applies_local_clip : 1; - - // When true, |clip_in_target_space| does not include clips from ancestor - // nodes. - bool layer_clipping_uses_only_local_clip : 1; - - // True if target surface needs to be drawn with a clip applied. - bool target_is_clipped : 1; - - // True if layers with this clip tree node need to be drawn with a clip - // applied. - bool layers_are_clipped : 1; - bool layers_are_clipped_when_surfaces_disabled : 1; - - // Nodes that correspond to unclipped surfaces disregard ancestor clips. - bool resets_clip : 1; - - bool operator==(const ClipNodeData& other) const; - - void ToProtobuf(proto::TreeNode* proto) const; - void FromProtobuf(const proto::TreeNode& proto); - void AsValueInto(base::trace_event::TracedValue* value) const; -}; - -typedef TreeNode<ClipNodeData> ClipNode; - -struct CC_EXPORT EffectNodeData { - EffectNodeData(); - EffectNodeData(const EffectNodeData& other); - - float opacity; - float screen_space_opacity; - - FilterOperations background_filters; - - bool has_render_surface; - RenderSurfaceImpl* render_surface; - bool has_copy_request; - bool hidden_by_backface_visibility; - bool double_sided; - bool is_drawn; - // TODO(jaydasika) : Delete this after implementation of - // SetHideLayerAndSubtree is cleaned up. (crbug.com/595843) - bool subtree_hidden; - bool has_potential_opacity_animation; - bool is_currently_animating_opacity; - // We need to track changes to effects on the compositor to compute damage - // rect. - bool effect_changed; - int num_copy_requests_in_subtree; - bool has_unclipped_descendants; - int transform_id; - int clip_id; - // Effect node id of which this effect contributes to. - int target_id; - int mask_layer_id; - int replica_layer_id; - int replica_mask_layer_id; - - bool operator==(const EffectNodeData& other) const; - - void ToProtobuf(proto::TreeNode* proto) const; - void FromProtobuf(const proto::TreeNode& proto); - void AsValueInto(base::trace_event::TracedValue* value) const; -}; - -typedef TreeNode<EffectNodeData> EffectNode; - -struct CC_EXPORT ScrollNodeData { - ScrollNodeData(); - ScrollNodeData(const ScrollNodeData& other); - - bool scrollable; - uint32_t main_thread_scrolling_reasons; - bool contains_non_fast_scrollable_region; - gfx::Size scroll_clip_layer_bounds; - gfx::Size bounds; - bool max_scroll_offset_affected_by_page_scale; - bool is_inner_viewport_scroll_layer; - bool is_outer_viewport_scroll_layer; - gfx::Vector2dF offset_to_transform_parent; - bool should_flatten; - bool user_scrollable_horizontal; - bool user_scrollable_vertical; - ElementId element_id; - int transform_id; - // Number of drawn layers pointing to this node or any of its descendants. - int num_drawn_descendants; - - bool operator==(const ScrollNodeData& other) const; - - void ToProtobuf(proto::TreeNode* proto) const; - void FromProtobuf(const proto::TreeNode& proto); - void AsValueInto(base::trace_event::TracedValue* value) const; -}; - -typedef TreeNode<ScrollNodeData> ScrollNode; - class PropertyTrees; template <typename T> @@ -343,7 +59,13 @@ public: PropertyTree(); PropertyTree(const PropertyTree& other) = delete; + + // These C++ special member functions cannot be implicit inline because + // they are exported by CC_EXPORT. They will be instantiated in every + // compilation units that included this header, and compilation can fail + // because T may be incomplete. ~PropertyTree(); + PropertyTree<T>& operator=(const PropertyTree<T>&); bool operator==(const PropertyTree<T>& other) const; @@ -400,7 +122,14 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { public: TransformTree(); + + // These C++ special member functions cannot be implicit inline because + // they are exported by CC_EXPORT. They will be instantiated in every + // compilation units that included this header, and compilation can fail + // because TransformCachedNodeData may be incomplete. + TransformTree(const TransformTree&) = delete; ~TransformTree(); + TransformTree& operator=(const TransformTree&); bool operator==(const TransformTree& other) const; @@ -604,6 +333,8 @@ float EffectiveOpacity(const EffectNode* node) const; + void UpdateSublayerScale(EffectNode* node); + void UpdateEffects(int id); void UpdateEffectChanged(EffectNode* node, EffectNode* parent_node);
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 7f35dd9..f9ebb6f 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -13,9 +13,13 @@ #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/output/copy_output_request.h" +#include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" +#include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -280,7 +284,7 @@ bool is_root = !Parent(layer); // Whether we have an ancestor clip that we might need to apply. - bool ancestor_clips_subtree = is_root || parent->data.layers_are_clipped; + bool ancestor_clips_subtree = is_root || parent->layers_are_clipped; bool layers_are_clipped = false; bool has_unclipped_surface = false; @@ -299,7 +303,7 @@ // of its own, but clips from ancestor nodes don't need to be considered // when computing clip rects or visibility. has_unclipped_surface = true; - DCHECK(!parent->data.applies_local_clip); + DCHECK(!parent->applies_local_clip); } // A surface with unclipped descendants cannot be clipped by its ancestor // clip at draw time since the unclipped descendants aren't affected by the @@ -320,8 +324,7 @@ // Without surfaces, all non-viewport clips have to be applied using layer // clipping. bool layers_are_clipped_when_surfaces_disabled = - layer_clips_subtree || - parent->data.layers_are_clipped_when_surfaces_disabled; + layer_clips_subtree || parent->layers_are_clipped_when_surfaces_disabled; // Render surface's clip is needed during hit testing. So, we need to create // a clip node for every render surface. @@ -329,9 +332,9 @@ if (!requires_node) { data_for_children->clip_tree_parent = parent_id; - DCHECK_EQ(layers_are_clipped, parent->data.layers_are_clipped); + DCHECK_EQ(layers_are_clipped, parent->layers_are_clipped); DCHECK_EQ(layers_are_clipped_when_surfaces_disabled, - parent->data.layers_are_clipped_when_surfaces_disabled); + parent->layers_are_clipped_when_surfaces_disabled); } else { LayerType* transform_parent = data_for_children->transform_tree_parent; if (PositionConstraint(layer).is_fixed_position() && @@ -339,32 +342,31 @@ transform_parent = data_for_children->transform_fixed_parent; } ClipNode node; - node.data.clip = - gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(), - gfx::SizeF(layer->bounds())); - node.data.transform_id = transform_parent->transform_tree_index(); - node.data.target_id = data_for_children->property_trees->effect_tree - .Node(data_for_children->render_target) - ->data.transform_id; + node.clip = gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(), + gfx::SizeF(layer->bounds())); + node.transform_id = transform_parent->transform_tree_index(); + node.target_id = data_for_children->property_trees->effect_tree + .Node(data_for_children->render_target) + ->transform_id; node.owner_id = layer->id(); if (ancestor_clips_subtree || layer_clips_subtree) { // Surfaces reset the rect used for layer clipping. At other nodes, layer // clipping state from ancestors must continue to get propagated. - node.data.layer_clipping_uses_only_local_clip = + node.layer_clipping_uses_only_local_clip = (created_render_surface && NumUnclippedDescendants(layer) == 0) || !ancestor_clips_subtree; } else { // Otherwise, we're either unclipped, or exist only in order to apply our // parent's clips in our space. - node.data.layer_clipping_uses_only_local_clip = false; + node.layer_clipping_uses_only_local_clip = false; } - node.data.applies_local_clip = layer_clips_subtree; - node.data.resets_clip = has_unclipped_surface; - node.data.target_is_clipped = data_for_children->target_is_clipped; - node.data.layers_are_clipped = layers_are_clipped; - node.data.layers_are_clipped_when_surfaces_disabled = + node.applies_local_clip = layer_clips_subtree; + node.resets_clip = has_unclipped_surface; + node.target_is_clipped = data_for_children->target_is_clipped; + node.layers_are_clipped = layers_are_clipped; + node.layers_are_clipped_when_surfaces_disabled = layers_are_clipped_when_surfaces_disabled; data_for_children->clip_tree_parent = @@ -528,14 +530,14 @@ data_for_children->property_trees->transform_id_to_index_map[layer->id()] = node->id; - node->data.scrolls = is_scrollable; - node->data.flattens_inherited_transform = data_for_children->should_flatten; + node->scrolls = is_scrollable; + node->flattens_inherited_transform = data_for_children->should_flatten; - node->data.sorting_context_id = layer->sorting_context_id(); + node->sorting_context_id = layer->sorting_context_id(); if (layer == data_from_ancestor.page_scale_layer) data_for_children->in_subtree_of_page_scale_layer = true; - node->data.in_subtree_of_page_scale_layer = + node->in_subtree_of_page_scale_layer = data_for_children->in_subtree_of_page_scale_layer; // Surfaces inherently flatten transforms. @@ -546,19 +548,19 @@ data_for_children->property_trees->transform_tree.SetTargetId( node->id, data_for_children->property_trees->effect_tree .Node(data_from_ancestor.render_target) - ->data.transform_id); + ->transform_id); data_for_children->property_trees->transform_tree.SetContentTargetId( node->id, data_for_children->property_trees->effect_tree .Node(data_for_children->render_target) - ->data.transform_id); + ->transform_id); DCHECK_NE( data_for_children->property_trees->transform_tree.TargetId(node->id), kInvalidPropertyTreeNodeId); - node->data.has_potential_animation = has_potentially_animated_transform; - node->data.is_currently_animating = layer->TransformIsAnimating(); + node->has_potential_animation = has_potentially_animated_transform; + node->is_currently_animating = layer->TransformIsAnimating(); if (has_potentially_animated_transform) { - node->data.has_only_translation_animations = + node->has_only_translation_animations = layer->HasOnlyTranslationTransforms(); } @@ -574,57 +576,57 @@ } if (has_surface && !is_root) - node->data.needs_sublayer_scale = true; + node->needs_sublayer_scale = true; - node->data.source_node_id = source_index; - node->data.post_local_scale_factor = post_local_scale_factor; + node->source_node_id = source_index; + node->post_local_scale_factor = post_local_scale_factor; if (is_root) { data_for_children->property_trees->transform_tree.SetDeviceTransform( *data_from_ancestor.device_transform, layer->position()); data_for_children->property_trees->transform_tree .SetDeviceTransformScaleFactor(*data_from_ancestor.device_transform); } else { - node->data.source_offset = source_offset; - node->data.update_post_local_transform(layer->position(), - TransformOrigin(layer)); + node->source_offset = source_offset; + node->update_post_local_transform(layer->position(), + TransformOrigin(layer)); } if (is_overscroll_elasticity_layer) { DCHECK(!is_scrollable); - node->data.scroll_offset = + node->scroll_offset = gfx::ScrollOffset(data_from_ancestor.elastic_overscroll); } else if (!ScrollParent(layer)) { - node->data.scroll_offset = layer->CurrentScrollOffset(); + node->scroll_offset = layer->CurrentScrollOffset(); } if (is_fixed) { if (data_from_ancestor.affected_by_inner_viewport_bounds_delta) { - node->data.affected_by_inner_viewport_bounds_delta_x = + node->affected_by_inner_viewport_bounds_delta_x = PositionConstraint(layer).is_fixed_to_right_edge(); - node->data.affected_by_inner_viewport_bounds_delta_y = + node->affected_by_inner_viewport_bounds_delta_y = PositionConstraint(layer).is_fixed_to_bottom_edge(); - if (node->data.affected_by_inner_viewport_bounds_delta_x || - node->data.affected_by_inner_viewport_bounds_delta_y) { + if (node->affected_by_inner_viewport_bounds_delta_x || + node->affected_by_inner_viewport_bounds_delta_y) { data_for_children->property_trees->transform_tree .AddNodeAffectedByInnerViewportBoundsDelta(node->id); } } else if (data_from_ancestor.affected_by_outer_viewport_bounds_delta) { - node->data.affected_by_outer_viewport_bounds_delta_x = + node->affected_by_outer_viewport_bounds_delta_x = PositionConstraint(layer).is_fixed_to_right_edge(); - node->data.affected_by_outer_viewport_bounds_delta_y = + node->affected_by_outer_viewport_bounds_delta_y = PositionConstraint(layer).is_fixed_to_bottom_edge(); - if (node->data.affected_by_outer_viewport_bounds_delta_x || - node->data.affected_by_outer_viewport_bounds_delta_y) { + if (node->affected_by_outer_viewport_bounds_delta_x || + node->affected_by_outer_viewport_bounds_delta_y) { data_for_children->property_trees->transform_tree .AddNodeAffectedByOuterViewportBoundsDelta(node->id); } } } - node->data.local = layer->transform(); - node->data.update_pre_local_transform(TransformOrigin(layer)); + node->local = layer->transform(); + node->update_pre_local_transform(TransformOrigin(layer)); - node->data.needs_local_transform_update = true; + node->needs_local_transform_update = true; data_from_ancestor.property_trees->transform_tree.UpdateTransforms(node->id); layer->set_offset_to_transform_parent(gfx::Vector2dF()); @@ -632,7 +634,7 @@ // Flattening (if needed) will be handled by |node|. layer->set_should_flatten_transform_from_property_tree(false); - data_for_children->scroll_snap += node->data.scroll_snap; + data_for_children->scroll_snap += node->scroll_snap; node->owner_id = layer->id(); @@ -893,26 +895,26 @@ .push_back(node.owner_id); } - node.data.opacity = Opacity(layer); - node.data.has_render_surface = should_create_render_surface; - node.data.has_copy_request = HasCopyRequest(layer); - node.data.background_filters = BackgroundFilters(layer); - node.data.has_potential_opacity_animation = has_potential_opacity_animation; - node.data.double_sided = DoubleSided(layer); - node.data.subtree_hidden = HideLayerAndSubtree(layer); - node.data.is_currently_animating_opacity = layer->OpacityIsAnimating(); + node.opacity = Opacity(layer); + node.has_render_surface = should_create_render_surface; + node.has_copy_request = HasCopyRequest(layer); + node.background_filters = BackgroundFilters(layer); + node.has_potential_opacity_animation = has_potential_opacity_animation; + node.double_sided = DoubleSided(layer); + node.subtree_hidden = HideLayerAndSubtree(layer); + node.is_currently_animating_opacity = layer->OpacityIsAnimating(); EffectTree& effect_tree = data_for_children->property_trees->effect_tree; if (MaskLayer(layer)) { - node.data.mask_layer_id = MaskLayer(layer)->id(); - effect_tree.AddMaskOrReplicaLayerId(node.data.mask_layer_id); + node.mask_layer_id = MaskLayer(layer)->id(); + effect_tree.AddMaskOrReplicaLayerId(node.mask_layer_id); } if (ReplicaLayer(layer)) { - node.data.replica_layer_id = ReplicaLayer(layer)->id(); - effect_tree.AddMaskOrReplicaLayerId(node.data.replica_layer_id); + node.replica_layer_id = ReplicaLayer(layer)->id(); + effect_tree.AddMaskOrReplicaLayerId(node.replica_layer_id); if (MaskLayer(ReplicaLayer(layer))) { - node.data.replica_mask_layer_id = MaskLayer(ReplicaLayer(layer))->id(); - effect_tree.AddMaskOrReplicaLayerId(node.data.replica_mask_layer_id); + node.replica_mask_layer_id = MaskLayer(ReplicaLayer(layer))->id(); + effect_tree.AddMaskOrReplicaLayerId(node.replica_mask_layer_id); } } @@ -924,19 +926,18 @@ // In this case, we will create a transform node, so it's safe to use the // next available id from the transform tree as this effect node's // transform id. - node.data.transform_id = + node.transform_id = data_from_ancestor.property_trees->transform_tree.next_available_id(); - node.data.has_unclipped_descendants = - (NumUnclippedDescendants(layer) != 0); + node.has_unclipped_descendants = (NumUnclippedDescendants(layer) != 0); } - node.data.clip_id = data_from_ancestor.clip_tree_parent; + node.clip_id = data_from_ancestor.clip_tree_parent; } else { // Root render surface acts the unbounded and untransformed to draw content // into. Transform node created from root layer (includes device scale // factor) and clip node created from root layer (include viewports) applies // to root render surface's content, but not root render surface itself. - node.data.transform_id = kRootPropertyTreeNodeId; - node.data.clip_id = kViewportClipTreeNodeId; + node.transform_id = kRootPropertyTreeNodeId; + node.clip_id = kViewportClipTreeNodeId; } data_for_children->effect_tree_parent = effect_tree.Insert(node, parent_id); int node_id = data_for_children->effect_tree_parent; @@ -991,48 +992,47 @@ } else { ScrollNode node; node.owner_id = layer->id(); - node.data.scrollable = scrollable; - node.data.main_thread_scrolling_reasons = main_thread_scrolling_reasons; - node.data.contains_non_fast_scrollable_region = + node.scrollable = scrollable; + node.main_thread_scrolling_reasons = main_thread_scrolling_reasons; + node.contains_non_fast_scrollable_region = contains_non_fast_scrollable_region; gfx::Size clip_bounds; if (layer->scroll_clip_layer()) { clip_bounds = layer->scroll_clip_layer()->bounds(); DCHECK(layer->scroll_clip_layer()->transform_tree_index() != kInvalidPropertyTreeNodeId); - node.data.max_scroll_offset_affected_by_page_scale = + node.max_scroll_offset_affected_by_page_scale = !data_from_ancestor.property_trees->transform_tree .Node(layer->scroll_clip_layer()->transform_tree_index()) - ->data.in_subtree_of_page_scale_layer && + ->in_subtree_of_page_scale_layer && data_from_ancestor.in_subtree_of_page_scale_layer; } - node.data.scroll_clip_layer_bounds = clip_bounds; - node.data.is_inner_viewport_scroll_layer = + node.scroll_clip_layer_bounds = clip_bounds; + node.is_inner_viewport_scroll_layer = layer == data_from_ancestor.inner_viewport_scroll_layer; - node.data.is_outer_viewport_scroll_layer = + node.is_outer_viewport_scroll_layer = layer == data_from_ancestor.outer_viewport_scroll_layer; - node.data.bounds = layer->bounds(); - node.data.offset_to_transform_parent = layer->offset_to_transform_parent(); - node.data.should_flatten = - layer->should_flatten_transform_from_property_tree(); - node.data.user_scrollable_horizontal = layer->user_scrollable_horizontal(); - node.data.user_scrollable_vertical = layer->user_scrollable_vertical(); - node.data.element_id = layer->element_id(); - node.data.transform_id = + node.bounds = layer->bounds(); + node.offset_to_transform_parent = layer->offset_to_transform_parent(); + node.should_flatten = layer->should_flatten_transform_from_property_tree(); + node.user_scrollable_horizontal = layer->user_scrollable_horizontal(); + node.user_scrollable_vertical = layer->user_scrollable_vertical(); + node.element_id = layer->element_id(); + node.transform_id = data_for_children->transform_tree_parent->transform_tree_index(); data_for_children->scroll_tree_parent = data_for_children->property_trees->scroll_tree.Insert(node, parent_id); data_for_children->main_thread_scrolling_reasons = - node.data.main_thread_scrolling_reasons; + node.main_thread_scrolling_reasons; data_for_children->scroll_tree_parent_created_by_uninheritable_criteria = scroll_node_uninheritable_criteria; data_for_children->property_trees->scroll_id_to_index_map[layer->id()] = data_for_children->scroll_tree_parent; - if (node.data.scrollable) { + if (node.scrollable) { data_for_children->property_trees->scroll_tree.SetBaseScrollOffset( layer->id(), layer->CurrentScrollOffset()); } @@ -1182,9 +1182,9 @@ data_for_children.effect_tree_parent); if (effect_node->owner_id == layer->id()) { - if (effect_node->data.has_copy_request) + if (effect_node->has_copy_request) data_to_parent->num_copy_requests_in_subtree++; - effect_node->data.num_copy_requests_in_subtree = + effect_node->num_copy_requests_in_subtree = data_to_parent->num_copy_requests_in_subtree; } } @@ -1290,10 +1290,10 @@ .clear(); ClipNode root_clip; - root_clip.data.resets_clip = true; - root_clip.data.applies_local_clip = true; - root_clip.data.clip = gfx::RectF(viewport); - root_clip.data.transform_id = kRootPropertyTreeNodeId; + root_clip.resets_clip = true; + root_clip.applies_local_clip = true; + root_clip.clip = gfx::RectF(viewport); + root_clip.transform_id = kRootPropertyTreeNodeId; data_for_recursion.clip_tree_parent = data_for_recursion.property_trees->clip_tree.Insert( root_clip, kRootPropertyTreeNodeId);
diff --git a/cc/trees/property_tree_unittest.cc b/cc/trees/property_tree_unittest.cc index f5f1e05..d007cb2 100644 --- a/cc/trees/property_tree_unittest.cc +++ b/cc/trees/property_tree_unittest.cc
@@ -7,14 +7,21 @@ #include "cc/input/main_thread_scrolling_reason.h" #include "cc/proto/property_tree.pb.h" #include "cc/test/geometry_test_utils.h" +#include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" +#include "cc/trees/effect_node.h" +#include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { namespace { -TEST(PropertyTreeSerializationTest, TransformNodeDataSerialization) { - TransformNodeData original; +TEST(PropertyTreeSerializationTest, TransformNodeSerialization) { + TransformNode original; + original.id = 3; + original.parent_id = 2; + original.owner_id = 4; original.pre_local.Translate3d(1.f, 2.f, 3.f); original.local.Translate3d(3.f, 1.f, 5.f); original.post_local.Translate3d(1.f, 8.f, 3.f); @@ -45,20 +52,6 @@ proto::TreeNode proto; original.ToProtobuf(&proto); - TransformNodeData result; - result.FromProtobuf(proto); - - EXPECT_EQ(original, result); -} - -TEST(PropertyTreeSerializationTest, TransformNodeSerialization) { - TransformNode original; - original.id = 3; - original.parent_id = 2; - original.owner_id = 4; - - proto::TreeNode proto; - original.ToProtobuf(&proto); TransformNode result; result.FromProtobuf(proto); @@ -75,14 +68,14 @@ original.SetContentTargetId(root.id, 4); TransformNode second; second.owner_id = 2; - second.data.local.Translate3d(2.f, 2.f, 0.f); - second.data.source_node_id = 0; + second.local.Translate3d(2.f, 2.f, 0.f); + second.source_node_id = 0; second.id = original.Insert(second, 0); original.SetTargetId(second.id, 0); TransformNode third; third.owner_id = 3; - third.data.scrolls = true; - third.data.source_node_id = 1; + third.scrolls = true; + third.source_node_id = 1; third.id = original.Insert(third, 1); original.SetTargetId(third.id, 0); @@ -109,8 +102,11 @@ EXPECT_EQ(original, result); } -TEST(PropertyTreeSerializationTest, ClipNodeDataSerialization) { - ClipNodeData original; +TEST(PropertyTreeSerializationTest, ClipNodeSerialization) { + ClipNode original; + original.id = 3; + original.parent_id = 2; + original.owner_id = 4; original.clip = gfx::RectF(0.5f, 0.5f); original.combined_clip_in_target_space = gfx::RectF(0.6f, 0.6f); original.clip_in_target_space = gfx::RectF(0.7f, 0.7f); @@ -125,20 +121,6 @@ proto::TreeNode proto; original.ToProtobuf(&proto); - ClipNodeData result; - result.FromProtobuf(proto); - - EXPECT_EQ(original, result); -} - -TEST(PropertyTreeSerializationTest, ClipNodeSerialization) { - ClipNode original; - original.id = 3; - original.parent_id = 2; - original.owner_id = 4; - - proto::TreeNode proto; - original.ToProtobuf(&proto); ClipNode result; result.FromProtobuf(proto); @@ -149,16 +131,16 @@ ClipTree original; ClipNode& root = *original.Node(0); root.owner_id = 1; - root.data.transform_id = 2; - root.data.target_id = 1; + root.transform_id = 2; + root.target_id = 1; ClipNode second; second.owner_id = 2; - second.data.transform_id = 4; - second.data.applies_local_clip = true; + second.transform_id = 4; + second.applies_local_clip = true; ClipNode third; third.owner_id = 3; - third.data.target_id = 3; - third.data.target_is_clipped = false; + third.target_id = 3; + third.target_is_clipped = false; original.Insert(second, 0); original.Insert(third, 1); @@ -176,8 +158,11 @@ EXPECT_EQ(original, result); } -TEST(PropertyTreeSerializationTest, EffectNodeDataSerialization) { - EffectNodeData original; +TEST(PropertyTreeSerializationTest, EffectNodeSerialization) { + EffectNode original; + original.id = 3; + original.parent_id = 2; + original.owner_id = 4; original.opacity = 0.5f; original.screen_space_opacity = 0.6f; original.has_render_surface = false; @@ -186,20 +171,7 @@ original.mask_layer_id = 6; original.replica_layer_id = 10; original.replica_mask_layer_id = 9; - - proto::TreeNode proto; - original.ToProtobuf(&proto); - EffectNodeData result; - result.FromProtobuf(proto); - - EXPECT_EQ(original, result); -} - -TEST(PropertyTreeSerializationTest, EffectNodeSerialization) { - EffectNode original; - original.id = 3; - original.parent_id = 2; - original.owner_id = 4; + original.sublayer_scale = gfx::Vector2dF(0.5f, 0.5f); proto::TreeNode proto; original.ToProtobuf(&proto); @@ -213,19 +185,19 @@ EffectTree original; EffectNode& root = *original.Node(0); root.owner_id = 5; - root.data.transform_id = 2; - root.data.clip_id = 1; + root.transform_id = 2; + root.clip_id = 1; EffectNode second; second.owner_id = 6; - second.data.transform_id = 4; - second.data.opacity = true; - second.data.mask_layer_id = 32; + second.transform_id = 4; + second.opacity = true; + second.mask_layer_id = 32; EffectNode third; third.owner_id = 7; - third.data.clip_id = 3; - third.data.replica_layer_id = 44; - third.data.replica_mask_layer_id = 45; - third.data.has_render_surface = false; + third.clip_id = 3; + third.replica_layer_id = 44; + third.replica_mask_layer_id = 45; + third.has_render_surface = false; original.Insert(second, 0); original.Insert(third, 1); @@ -246,8 +218,11 @@ EXPECT_EQ(original, result); } -TEST(PropertyTreeSerializationTest, ScrollNodeDataSerialization) { - ScrollNodeData original; +TEST(PropertyTreeSerializationTest, ScrollNodeSerialization) { + ScrollNode original; + original.id = 3; + original.parent_id = 2; + original.owner_id = 4; original.scrollable = true; original.main_thread_scrolling_reasons = MainThreadScrollingReason::kScrollbarScrolling; @@ -260,20 +235,6 @@ proto::TreeNode proto; original.ToProtobuf(&proto); - ScrollNodeData result; - result.FromProtobuf(proto); - - EXPECT_EQ(original, result); -} - -TEST(PropertyTreeSerializationTest, ScrollNodeSerialization) { - ScrollNode original; - original.id = 3; - original.parent_id = 2; - original.owner_id = 4; - - proto::TreeNode proto; - original.ToProtobuf(&proto); ScrollNode result; result.FromProtobuf(proto); @@ -286,11 +247,11 @@ ScrollTree& original = property_trees.scroll_tree; ScrollNode second; second.owner_id = 10; - second.data.scrollable = true; - second.data.bounds = gfx::Size(15, 15); + second.scrollable = true; + second.bounds = gfx::Size(15, 15); ScrollNode third; third.owner_id = 20; - third.data.contains_non_fast_scrollable_region = true; + third.contains_non_fast_scrollable_region = true; original.Insert(second, 0); original.Insert(third, 1); @@ -434,7 +395,7 @@ TransformTree& tree = property_trees.transform_tree; TransformNode& root = *tree.Node(0); root.id = 0; - root.data.local.Translate(2, 2); + root.local.Translate(2, 2); tree.SetTargetId(root.id, 0); SetupTransformTreeForTest(&tree); tree.UpdateTransforms(0); @@ -469,13 +430,13 @@ PropertyTrees property_trees; TransformTree& tree = property_trees.transform_tree; TransformNode& root = *tree.Node(0); - root.data.local.Translate(2, 2); + root.local.Translate(2, 2); tree.SetTargetId(root.id, 0); tree.UpdateTransforms(0); TransformNode child; - child.data.local.Translate(3, 3); - child.data.source_node_id = 0; + child.local.Translate(3, 3); + child.source_node_id = 0; child.id = tree.Insert(child, 0); tree.SetTargetId(child.id, 0); @@ -522,19 +483,19 @@ PropertyTrees property_trees; TransformTree& tree = property_trees.transform_tree; TransformNode& root = *tree.Node(0); - root.data.local.Translate(2, 2); + root.local.Translate(2, 2); tree.SetTargetId(root.id, 0); tree.UpdateTransforms(0); TransformNode child; - child.data.local.Translate(3, 3); - child.data.source_node_id = 0; + child.local.Translate(3, 3); + child.source_node_id = 0; child.id = tree.Insert(child, 0); tree.SetTargetId(child.id, 0); TransformNode sibling; - sibling.data.local.Translate(7, 7); - sibling.data.source_node_id = 0; + sibling.local.Translate(7, 7); + sibling.source_node_id = 0; sibling.id = tree.Insert(sibling, 0); tree.SetTargetId(sibling.id, 0); @@ -579,25 +540,25 @@ PropertyTrees property_trees; TransformTree& tree = property_trees.transform_tree; TransformNode& root = *tree.Node(0); - root.data.local.Translate(2, 2); + root.local.Translate(2, 2); tree.SetTargetId(root.id, 0); tree.UpdateTransforms(0); TransformNode singular; - singular.data.local.matrix().set(2, 2, 0.0); - singular.data.source_node_id = 0; + singular.local.matrix().set(2, 2, 0.0); + singular.source_node_id = 0; singular.id = tree.Insert(singular, 0); tree.SetTargetId(singular.id, 0); TransformNode child; - child.data.local.Translate(3, 3); - child.data.source_node_id = 1; + child.local.Translate(3, 3); + child.source_node_id = 1; child.id = tree.Insert(child, 1); tree.SetTargetId(child.id, 0); TransformNode sibling; - sibling.data.local.Translate(7, 7); - sibling.data.source_node_id = 1; + sibling.local.Translate(7, 7); + sibling.source_node_id = 1; sibling.id = tree.Insert(sibling, 1); tree.SetTargetId(sibling.id, 0); @@ -636,31 +597,31 @@ int grand_parent = tree.Insert(TransformNode(), 0); tree.SetContentTargetId(grand_parent, grand_parent); tree.SetTargetId(grand_parent, grand_parent); - tree.Node(grand_parent)->data.source_node_id = 0; + tree.Node(grand_parent)->source_node_id = 0; gfx::Transform rotation_about_x; rotation_about_x.RotateAboutXAxis(15); int parent = tree.Insert(TransformNode(), grand_parent); - tree.Node(parent)->data.needs_sublayer_scale = true; + tree.Node(parent)->needs_sublayer_scale = true; tree.SetTargetId(parent, grand_parent); tree.SetContentTargetId(parent, parent); - tree.Node(parent)->data.source_node_id = grand_parent; - tree.Node(parent)->data.local = rotation_about_x; + tree.Node(parent)->source_node_id = grand_parent; + tree.Node(parent)->local = rotation_about_x; int child = tree.Insert(TransformNode(), parent); tree.SetTargetId(child, parent); tree.SetContentTargetId(child, parent); - tree.Node(child)->data.source_node_id = parent; - tree.Node(child)->data.flattens_inherited_transform = true; - tree.Node(child)->data.local = rotation_about_x; + tree.Node(child)->source_node_id = parent; + tree.Node(child)->flattens_inherited_transform = true; + tree.Node(child)->local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); tree.SetTargetId(grand_child, parent); tree.SetContentTargetId(grand_child, parent); - tree.Node(grand_child)->data.source_node_id = child; - tree.Node(grand_child)->data.flattens_inherited_transform = true; - tree.Node(grand_child)->data.local = rotation_about_x; + tree.Node(grand_child)->source_node_id = child; + tree.Node(grand_child)->flattens_inherited_transform = true; + tree.Node(grand_child)->local = rotation_about_x; tree.set_needs_update(true); SetupTransformTreeForTest(&tree); @@ -690,7 +651,7 @@ EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_about_x, grand_child_to_child); // Remove flattening at grand_child, and recompute transforms. - tree.Node(grand_child)->data.flattens_inherited_transform = false; + tree.Node(grand_child)->flattens_inherited_transform = false; tree.set_needs_update(true); SetupTransformTreeForTest(&tree); draw_property_utils::ComputeTransforms(&tree); @@ -717,13 +678,13 @@ PropertyTrees property_trees; TransformTree& tree = property_trees.transform_tree; TransformNode& root = *tree.Node(0); - root.data.local.Translate(2, 2); + root.local.Translate(2, 2); tree.SetTargetId(root.id, 0); tree.UpdateTransforms(0); TransformNode child; - child.data.local.Scale(2, 2); - child.data.source_node_id = 0; + child.local.Scale(2, 2); + child.source_node_id = 0; child.id = tree.Insert(child, 0); tree.SetTargetId(child.id, 0); @@ -763,8 +724,8 @@ tree.UpdateTransforms(0); TransformNode child; - child.data.local.Scale(0, 0); - child.data.source_node_id = 0; + child.local.Scale(0, 0); + child.source_node_id = 0; child.id = tree.Insert(child, 0); tree.SetTargetId(child.id, 0); @@ -803,40 +764,40 @@ tree.UpdateTransforms(0); TransformNode grand_parent; - grand_parent.data.local.Scale(2.f, 2.f); - grand_parent.data.source_node_id = 0; - grand_parent.data.needs_sublayer_scale = true; + grand_parent.local.Scale(2.f, 2.f); + grand_parent.source_node_id = 0; + grand_parent.needs_sublayer_scale = true; int grand_parent_id = tree.Insert(grand_parent, 0); tree.SetTargetId(grand_parent_id, 0); tree.UpdateTransforms(grand_parent_id); TransformNode parent; - parent.data.local.Translate(15.f, 15.f); - parent.data.source_node_id = grand_parent_id; + parent.local.Translate(15.f, 15.f); + parent.source_node_id = grand_parent_id; int parent_id = tree.Insert(parent, grand_parent_id); tree.SetTargetId(parent_id, grand_parent_id); tree.UpdateTransforms(parent_id); TransformNode child; - child.data.local.Scale(3.f, 3.f); - child.data.source_node_id = parent_id; + child.local.Scale(3.f, 3.f); + child.source_node_id = parent_id; int child_id = tree.Insert(child, parent_id); tree.SetTargetId(child_id, grand_parent_id); tree.UpdateTransforms(child_id); TransformNode grand_child; - grand_child.data.local.Scale(5.f, 5.f); - grand_child.data.source_node_id = child_id; - grand_child.data.needs_sublayer_scale = true; + grand_child.local.Scale(5.f, 5.f); + grand_child.source_node_id = child_id; + grand_child.needs_sublayer_scale = true; int grand_child_id = tree.Insert(grand_child, child_id); tree.SetTargetId(grand_child_id, grand_parent_id); SetupTransformTreeForTest(&tree); tree.UpdateTransforms(grand_child_id); EXPECT_EQ(gfx::Vector2dF(2.f, 2.f), - tree.Node(grand_parent_id)->data.sublayer_scale); + tree.Node(grand_parent_id)->sublayer_scale); EXPECT_EQ(gfx::Vector2dF(30.f, 30.f), - tree.Node(grand_child_id)->data.sublayer_scale); + tree.Node(grand_child_id)->sublayer_scale); // Compute transform from grand_parent to grand_child. gfx::Transform expected_transform_without_sublayer_scale; @@ -921,25 +882,25 @@ tree.UpdateTransforms(0); TransformNode grand_parent; - grand_parent.data.local.Scale(2.f, 0.f); - grand_parent.data.source_node_id = 0; - grand_parent.data.needs_sublayer_scale = true; + grand_parent.local.Scale(2.f, 0.f); + grand_parent.source_node_id = 0; + grand_parent.needs_sublayer_scale = true; int grand_parent_id = tree.Insert(grand_parent, 0); tree.SetTargetId(grand_parent_id, 0); tree.SetContentTargetId(grand_parent_id, grand_parent_id); tree.UpdateTransforms(grand_parent_id); TransformNode parent; - parent.data.local.Translate(1.f, 1.f); - parent.data.source_node_id = grand_parent_id; + parent.local.Translate(1.f, 1.f); + parent.source_node_id = grand_parent_id; int parent_id = tree.Insert(parent, grand_parent_id); tree.SetTargetId(parent_id, grand_parent_id); tree.SetContentTargetId(parent_id, grand_parent_id); tree.UpdateTransforms(parent_id); TransformNode child; - child.data.local.Translate(3.f, 4.f); - child.data.source_node_id = parent_id; + child.local.Translate(3.f, 4.f); + child.source_node_id = parent_id; int child_id = tree.Insert(child, parent_id); tree.SetTargetId(child_id, grand_parent_id); tree.SetContentTargetId(child_id, grand_parent_id); @@ -954,9 +915,9 @@ EXPECT_TRUE(success); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); - tree.Node(grand_parent_id)->data.local.MakeIdentity(); - tree.Node(grand_parent_id)->data.local.Scale(0.f, 2.f); - tree.Node(grand_parent_id)->data.needs_local_transform_update = true; + tree.Node(grand_parent_id)->local.MakeIdentity(); + tree.Node(grand_parent_id)->local.Scale(0.f, 2.f); + tree.Node(grand_parent_id)->needs_local_transform_update = true; tree.set_needs_update(true); SetupTransformTreeForTest(&tree); @@ -966,9 +927,9 @@ EXPECT_TRUE(success); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); - tree.Node(grand_parent_id)->data.local.MakeIdentity(); - tree.Node(grand_parent_id)->data.local.Scale(0.f, 0.f); - tree.Node(grand_parent_id)->data.needs_local_transform_update = true; + tree.Node(grand_parent_id)->local.MakeIdentity(); + tree.Node(grand_parent_id)->local.Scale(0.f, 0.f); + tree.Node(grand_parent_id)->needs_local_transform_update = true; tree.set_needs_update(true); SetupTransformTreeForTest(&tree); @@ -996,8 +957,8 @@ int parent = tree.Insert(TransformNode(), 0); tree.SetContentTargetId(parent, parent); tree.SetTargetId(parent, parent); - tree.Node(parent)->data.source_node_id = 0; - tree.Node(parent)->data.local.Translate(2, 2); + tree.Node(parent)->source_node_id = 0; + tree.Node(parent)->local.Translate(2, 2); gfx::Transform rotation_about_x; rotation_about_x.RotateAboutXAxis(15); @@ -1005,14 +966,14 @@ int child = tree.Insert(TransformNode(), parent); tree.SetContentTargetId(child, child); tree.SetTargetId(child, child); - tree.Node(child)->data.source_node_id = parent; - tree.Node(child)->data.local = rotation_about_x; + tree.Node(child)->source_node_id = parent; + tree.Node(child)->local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); tree.SetContentTargetId(grand_child, grand_child); tree.SetTargetId(grand_child, grand_child); - tree.Node(grand_child)->data.source_node_id = child; - tree.Node(grand_child)->data.flattens_inherited_transform = true; + tree.Node(grand_child)->source_node_id = child; + tree.Node(grand_child)->flattens_inherited_transform = true; tree.set_needs_update(true); SetupTransformTreeForTest(&tree); @@ -1044,18 +1005,18 @@ int child = tree.Insert(EffectNode(), parent); SetupEffectTreeForTest(&tree); - EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 1.f); - tree.Node(parent)->data.opacity = 0.5f; + EXPECT_EQ(tree.Node(child)->screen_space_opacity, 1.f); + tree.Node(parent)->opacity = 0.5f; tree.set_needs_update(true); SetupEffectTreeForTest(&tree); draw_property_utils::ComputeEffects(&tree); - EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 0.5f); + EXPECT_EQ(tree.Node(child)->screen_space_opacity, 0.5f); - tree.Node(child)->data.opacity = 0.5f; + tree.Node(child)->opacity = 0.5f; tree.set_needs_update(true); SetupEffectTreeForTest(&tree); draw_property_utils::ComputeEffects(&tree); - EXPECT_EQ(tree.Node(child)->data.screen_space_opacity, 0.25f); + EXPECT_EQ(tree.Node(child)->screen_space_opacity, 0.25f); } }; @@ -1072,38 +1033,38 @@ int parent = tree.Insert(TransformNode(), 0); tree.SetTargetId(parent, parent); - tree.Node(parent)->data.local.Translate(1.5f, 1.5f); + tree.Node(parent)->local.Translate(1.5f, 1.5f); int child = tree.Insert(TransformNode(), parent); tree.SetTargetId(child, parent); - tree.Node(child)->data.local.Translate(1, 1); + tree.Node(child)->local.Translate(1, 1); tree.set_needs_update(true); SetupTransformTreeForTest(&tree); draw_property_utils::ComputeTransforms(&tree); - EXPECT_FALSE(tree.Node(parent) - ->data.node_and_ancestors_have_only_integer_translation); - EXPECT_FALSE(tree.Node(child) - ->data.node_and_ancestors_have_only_integer_translation); + EXPECT_FALSE( + tree.Node(parent)->node_and_ancestors_have_only_integer_translation); + EXPECT_FALSE( + tree.Node(child)->node_and_ancestors_have_only_integer_translation); - tree.Node(parent)->data.local.Translate(0.5f, 0.5f); - tree.Node(child)->data.local.Translate(0.5f, 0.5f); + tree.Node(parent)->local.Translate(0.5f, 0.5f); + tree.Node(child)->local.Translate(0.5f, 0.5f); tree.set_needs_update(true); SetupTransformTreeForTest(&tree); draw_property_utils::ComputeTransforms(&tree); - EXPECT_TRUE(tree.Node(parent) - ->data.node_and_ancestors_have_only_integer_translation); - EXPECT_FALSE(tree.Node(child) - ->data.node_and_ancestors_have_only_integer_translation); + EXPECT_TRUE( + tree.Node(parent)->node_and_ancestors_have_only_integer_translation); + EXPECT_FALSE( + tree.Node(child)->node_and_ancestors_have_only_integer_translation); - tree.Node(child)->data.local.Translate(0.5f, 0.5f); + tree.Node(child)->local.Translate(0.5f, 0.5f); tree.SetTargetId(child, child); tree.set_needs_update(true); SetupTransformTreeForTest(&tree); draw_property_utils::ComputeTransforms(&tree); - EXPECT_TRUE(tree.Node(parent) - ->data.node_and_ancestors_have_only_integer_translation); - EXPECT_TRUE(tree.Node(child) - ->data.node_and_ancestors_have_only_integer_translation); + EXPECT_TRUE( + tree.Node(parent)->node_and_ancestors_have_only_integer_translation); + EXPECT_TRUE( + tree.Node(child)->node_and_ancestors_have_only_integer_translation); } }; @@ -1120,14 +1081,14 @@ int parent = tree.Insert(TransformNode(), 0); tree.SetTargetId(parent, parent); - tree.Node(parent)->data.scrolls = true; + tree.Node(parent)->scrolls = true; int child = tree.Insert(TransformNode(), parent); TransformNode* child_node = tree.Node(child); tree.SetTargetId(child, parent); - child_node->data.scrolls = true; - child_node->data.local.Scale3d(6.0f, 6.0f, 0.0f); - child_node->data.local.Translate(1.3f, 1.3f); + child_node->scrolls = true; + child_node->local.Scale3d(6.0f, 6.0f, 0.0f); + child_node->local.Translate(1.3f, 1.3f); tree.set_needs_update(true); SetupTransformTreeForTest(&tree); @@ -1138,10 +1099,10 @@ // The following checks are to ensure that snapping is skipped because of // singular transform (and not because of other reasons which also cause // snapping to be skipped). - EXPECT_TRUE(child_node->data.scrolls); + EXPECT_TRUE(child_node->scrolls); EXPECT_TRUE(tree.ToTarget(child).IsScaleOrTranslation()); - EXPECT_FALSE(child_node->data.to_screen_is_potentially_animated); - EXPECT_FALSE(child_node->data.ancestors_are_invertible); + EXPECT_FALSE(child_node->to_screen_is_potentially_animated); + EXPECT_FALSE(child_node->ancestors_are_invertible); gfx::Transform rounded = tree.ToTarget(child); rounded.RoundTranslationComponents();
diff --git a/cc/trees/scroll_node.cc b/cc/trees/scroll_node.cc new file mode 100644 index 0000000..a20fe2f --- /dev/null +++ b/cc/trees/scroll_node.cc
@@ -0,0 +1,127 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/trace_event/trace_event_argument.h" +#include "cc/animation/element_id.h" +#include "cc/base/math_util.h" +#include "cc/input/main_thread_scrolling_reason.h" +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/property_tree.pb.h" +#include "cc/trees/scroll_node.h" + +namespace cc { + +ScrollNode::ScrollNode() + : id(-1), + parent_id(-1), + owner_id(-1), + scrollable(false), + main_thread_scrolling_reasons( + MainThreadScrollingReason::kNotScrollingOnMain), + contains_non_fast_scrollable_region(false), + max_scroll_offset_affected_by_page_scale(false), + is_inner_viewport_scroll_layer(false), + is_outer_viewport_scroll_layer(false), + should_flatten(false), + user_scrollable_horizontal(false), + user_scrollable_vertical(false), + transform_id(0), + num_drawn_descendants(0) {} + +ScrollNode::ScrollNode(const ScrollNode& other) = default; + +bool ScrollNode::operator==(const ScrollNode& other) const { + return id == other.id && parent_id == other.parent_id && + owner_id == other.owner_id && scrollable == other.scrollable && + main_thread_scrolling_reasons == other.main_thread_scrolling_reasons && + contains_non_fast_scrollable_region == + other.contains_non_fast_scrollable_region && + scroll_clip_layer_bounds == other.scroll_clip_layer_bounds && + bounds == other.bounds && + max_scroll_offset_affected_by_page_scale == + other.max_scroll_offset_affected_by_page_scale && + is_inner_viewport_scroll_layer == + other.is_inner_viewport_scroll_layer && + is_outer_viewport_scroll_layer == + other.is_outer_viewport_scroll_layer && + offset_to_transform_parent == other.offset_to_transform_parent && + should_flatten == other.should_flatten && + user_scrollable_horizontal == other.user_scrollable_horizontal && + user_scrollable_vertical == other.user_scrollable_vertical && + element_id == other.element_id && transform_id == other.transform_id; +} + +void ScrollNode::ToProtobuf(proto::TreeNode* proto) const { + proto->set_id(id); + proto->set_parent_id(parent_id); + proto->set_owner_id(owner_id); + + DCHECK(!proto->has_scroll_node_data()); + proto::ScrollNodeData* data = proto->mutable_scroll_node_data(); + data->set_scrollable(scrollable); + data->set_main_thread_scrolling_reasons(main_thread_scrolling_reasons); + data->set_contains_non_fast_scrollable_region( + contains_non_fast_scrollable_region); + SizeToProto(scroll_clip_layer_bounds, + data->mutable_scroll_clip_layer_bounds()); + SizeToProto(bounds, data->mutable_bounds()); + data->set_max_scroll_offset_affected_by_page_scale( + max_scroll_offset_affected_by_page_scale); + data->set_is_inner_viewport_scroll_layer(is_inner_viewport_scroll_layer); + data->set_is_outer_viewport_scroll_layer(is_outer_viewport_scroll_layer); + Vector2dFToProto(offset_to_transform_parent, + data->mutable_offset_to_transform_parent()); + data->set_should_flatten(should_flatten); + data->set_user_scrollable_horizontal(user_scrollable_horizontal); + data->set_user_scrollable_vertical(user_scrollable_vertical); + element_id.ToProtobuf(data->mutable_element_id()); + data->set_transform_id(transform_id); +} + +void ScrollNode::FromProtobuf(const proto::TreeNode& proto) { + id = proto.id(); + parent_id = proto.parent_id(); + owner_id = proto.owner_id(); + + DCHECK(proto.has_scroll_node_data()); + const proto::ScrollNodeData& data = proto.scroll_node_data(); + + scrollable = data.scrollable(); + main_thread_scrolling_reasons = data.main_thread_scrolling_reasons(); + contains_non_fast_scrollable_region = + data.contains_non_fast_scrollable_region(); + scroll_clip_layer_bounds = ProtoToSize(data.scroll_clip_layer_bounds()); + bounds = ProtoToSize(data.bounds()); + max_scroll_offset_affected_by_page_scale = + data.max_scroll_offset_affected_by_page_scale(); + is_inner_viewport_scroll_layer = data.is_inner_viewport_scroll_layer(); + is_outer_viewport_scroll_layer = data.is_outer_viewport_scroll_layer(); + offset_to_transform_parent = + ProtoToVector2dF(data.offset_to_transform_parent()); + should_flatten = data.should_flatten(); + user_scrollable_horizontal = data.user_scrollable_horizontal(); + user_scrollable_vertical = data.user_scrollable_vertical(); + element_id.FromProtobuf(data.element_id()); + transform_id = data.transform_id(); +} + +void ScrollNode::AsValueInto(base::trace_event::TracedValue* value) const { + value->SetInteger("id", id); + value->SetInteger("parent_id", parent_id); + value->SetInteger("owner_id", owner_id); + value->SetBoolean("scrollable", scrollable); + MathUtil::AddToTracedValue("scroll_clip_layer_bounds", + scroll_clip_layer_bounds, value); + MathUtil::AddToTracedValue("bounds", bounds, value); + MathUtil::AddToTracedValue("offset_to_transform_parent", + offset_to_transform_parent, value); + value->SetBoolean("should_flatten", should_flatten); + value->SetBoolean("user_scrollable_horizontal", user_scrollable_horizontal); + value->SetBoolean("user_scrollable_vertical", user_scrollable_vertical); + + element_id.AddToTracedValue(value); + value->SetInteger("transform_id", transform_id); +} + +} // namespace cc
diff --git a/cc/trees/scroll_node.h b/cc/trees/scroll_node.h new file mode 100644 index 0000000..745ee69 --- /dev/null +++ b/cc/trees/scroll_node.h
@@ -0,0 +1,58 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_SCROLL_NODE_H_ +#define CC_TREES_SCROLL_NODE_H_ + +#include "cc/base/cc_export.h" +#include "cc/output/filter_operations.h" +#include "ui/gfx/geometry/size.h" + +namespace base { +namespace trace_event { +class TracedValue; +} // namespace trace_event +} // namespace base + +namespace cc { + +namespace proto { +class TreeNode; +} // namespace proto + +struct CC_EXPORT ScrollNode { + ScrollNode(); + ScrollNode(const ScrollNode& other); + + int id; + int parent_id; + int owner_id; + + bool scrollable; + uint32_t main_thread_scrolling_reasons; + bool contains_non_fast_scrollable_region; + gfx::Size scroll_clip_layer_bounds; + gfx::Size bounds; + bool max_scroll_offset_affected_by_page_scale; + bool is_inner_viewport_scroll_layer; + bool is_outer_viewport_scroll_layer; + gfx::Vector2dF offset_to_transform_parent; + bool should_flatten; + bool user_scrollable_horizontal; + bool user_scrollable_vertical; + ElementId element_id; + int transform_id; + // Number of drawn layers pointing to this node or any of its descendants. + int num_drawn_descendants; + + bool operator==(const ScrollNode& other) const; + + void ToProtobuf(proto::TreeNode* proto) const; + void FromProtobuf(const proto::TreeNode& proto); + void AsValueInto(base::trace_event::TracedValue* value) const; +}; + +} // namespace cc + +#endif // CC_TREES_SCROLL_NODE_H_
diff --git a/cc/trees/transform_node.cc b/cc/trees/transform_node.cc new file mode 100644 index 0000000..ab2693b3 --- /dev/null +++ b/cc/trees/transform_node.cc
@@ -0,0 +1,271 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/trace_event/trace_event_argument.h" +#include "cc/base/math_util.h" +#include "cc/proto/gfx_conversions.h" +#include "cc/proto/property_tree.pb.h" +#include "cc/trees/transform_node.h" +#include "ui/gfx/geometry/point3_f.h" + +namespace cc { + +TransformNode::TransformNode() + : id(-1), + parent_id(-1), + owner_id(-1), + source_node_id(-1), + sorting_context_id(0), + needs_local_transform_update(true), + node_and_ancestors_are_animated_or_invertible(true), + is_invertible(true), + ancestors_are_invertible(true), + has_potential_animation(false), + is_currently_animating(false), + to_screen_is_potentially_animated(false), + has_only_translation_animations(true), + flattens_inherited_transform(false), + node_and_ancestors_are_flat(true), + node_and_ancestors_have_only_integer_translation(true), + scrolls(false), + needs_sublayer_scale(false), + affected_by_inner_viewport_bounds_delta_x(false), + affected_by_inner_viewport_bounds_delta_y(false), + affected_by_outer_viewport_bounds_delta_x(false), + affected_by_outer_viewport_bounds_delta_y(false), + in_subtree_of_page_scale_layer(false), + transform_changed(false), + post_local_scale_factor(1.0f) {} + +TransformNode::TransformNode(const TransformNode&) = default; + +bool TransformNode::operator==(const TransformNode& other) const { + return id == other.id && parent_id == other.parent_id && + owner_id == other.owner_id && pre_local == other.pre_local && + local == other.local && post_local == other.post_local && + to_parent == other.to_parent && + source_node_id == other.source_node_id && + sorting_context_id == other.sorting_context_id && + needs_local_transform_update == other.needs_local_transform_update && + node_and_ancestors_are_animated_or_invertible == + other.node_and_ancestors_are_animated_or_invertible && + is_invertible == other.is_invertible && + ancestors_are_invertible == other.ancestors_are_invertible && + has_potential_animation == other.has_potential_animation && + is_currently_animating == other.is_currently_animating && + to_screen_is_potentially_animated == + other.to_screen_is_potentially_animated && + has_only_translation_animations == + other.has_only_translation_animations && + flattens_inherited_transform == other.flattens_inherited_transform && + node_and_ancestors_are_flat == other.node_and_ancestors_are_flat && + node_and_ancestors_have_only_integer_translation == + other.node_and_ancestors_have_only_integer_translation && + scrolls == other.scrolls && + needs_sublayer_scale == other.needs_sublayer_scale && + affected_by_inner_viewport_bounds_delta_x == + other.affected_by_inner_viewport_bounds_delta_x && + affected_by_inner_viewport_bounds_delta_y == + other.affected_by_inner_viewport_bounds_delta_y && + affected_by_outer_viewport_bounds_delta_x == + other.affected_by_outer_viewport_bounds_delta_x && + affected_by_outer_viewport_bounds_delta_y == + other.affected_by_outer_viewport_bounds_delta_y && + in_subtree_of_page_scale_layer == + other.in_subtree_of_page_scale_layer && + transform_changed == other.transform_changed && + post_local_scale_factor == other.post_local_scale_factor && + sublayer_scale == other.sublayer_scale && + scroll_offset == other.scroll_offset && + scroll_snap == other.scroll_snap && + source_offset == other.source_offset && + source_to_parent == other.source_to_parent; +} + +void TransformNode::update_pre_local_transform( + const gfx::Point3F& transform_origin) { + pre_local.MakeIdentity(); + pre_local.Translate3d(-transform_origin.x(), -transform_origin.y(), + -transform_origin.z()); +} + +void TransformNode::update_post_local_transform( + const gfx::PointF& position, + const gfx::Point3F& transform_origin) { + post_local.MakeIdentity(); + post_local.Scale(post_local_scale_factor, post_local_scale_factor); + post_local.Translate3d( + position.x() + source_offset.x() + transform_origin.x(), + position.y() + source_offset.y() + transform_origin.y(), + transform_origin.z()); +} + +void TransformNode::ToProtobuf(proto::TreeNode* proto) const { + proto->set_id(id); + proto->set_parent_id(parent_id); + proto->set_owner_id(owner_id); + + DCHECK(!proto->has_transform_node_data()); + proto::TranformNodeData* data = proto->mutable_transform_node_data(); + + TransformToProto(pre_local, data->mutable_pre_local()); + TransformToProto(local, data->mutable_local()); + TransformToProto(post_local, data->mutable_post_local()); + + TransformToProto(to_parent, data->mutable_to_parent()); + + data->set_source_node_id(source_node_id); + data->set_sorting_context_id(sorting_context_id); + + data->set_needs_local_transform_update(needs_local_transform_update); + + data->set_node_and_ancestors_are_animated_or_invertible( + node_and_ancestors_are_animated_or_invertible); + + data->set_is_invertible(is_invertible); + data->set_ancestors_are_invertible(ancestors_are_invertible); + + data->set_has_potential_animation(has_potential_animation); + data->set_is_currently_animating(is_currently_animating); + data->set_to_screen_is_potentially_animated( + to_screen_is_potentially_animated); + data->set_has_only_translation_animations(has_only_translation_animations); + + data->set_flattens_inherited_transform(flattens_inherited_transform); + data->set_node_and_ancestors_are_flat(node_and_ancestors_are_flat); + + data->set_node_and_ancestors_have_only_integer_translation( + node_and_ancestors_have_only_integer_translation); + data->set_scrolls(scrolls); + data->set_needs_sublayer_scale(needs_sublayer_scale); + + data->set_affected_by_inner_viewport_bounds_delta_x( + affected_by_inner_viewport_bounds_delta_x); + data->set_affected_by_inner_viewport_bounds_delta_y( + affected_by_inner_viewport_bounds_delta_y); + data->set_affected_by_outer_viewport_bounds_delta_x( + affected_by_outer_viewport_bounds_delta_x); + data->set_affected_by_outer_viewport_bounds_delta_y( + affected_by_outer_viewport_bounds_delta_y); + + data->set_in_subtree_of_page_scale_layer(in_subtree_of_page_scale_layer); + data->set_transform_changed(transform_changed); + data->set_post_local_scale_factor(post_local_scale_factor); + + Vector2dFToProto(sublayer_scale, data->mutable_sublayer_scale()); + ScrollOffsetToProto(scroll_offset, data->mutable_scroll_offset()); + Vector2dFToProto(scroll_snap, data->mutable_scroll_snap()); + Vector2dFToProto(source_offset, data->mutable_source_offset()); + Vector2dFToProto(source_to_parent, data->mutable_source_to_parent()); +} + +void TransformNode::FromProtobuf(const proto::TreeNode& proto) { + id = proto.id(); + parent_id = proto.parent_id(); + owner_id = proto.owner_id(); + + DCHECK(proto.has_transform_node_data()); + const proto::TranformNodeData& data = proto.transform_node_data(); + + pre_local = ProtoToTransform(data.pre_local()); + local = ProtoToTransform(data.local()); + post_local = ProtoToTransform(data.post_local()); + + to_parent = ProtoToTransform(data.to_parent()); + + source_node_id = data.source_node_id(); + sorting_context_id = data.sorting_context_id(); + + needs_local_transform_update = data.needs_local_transform_update(); + + node_and_ancestors_are_animated_or_invertible = + data.node_and_ancestors_are_animated_or_invertible(); + + is_invertible = data.is_invertible(); + ancestors_are_invertible = data.ancestors_are_invertible(); + + has_potential_animation = data.has_potential_animation(); + is_currently_animating = data.is_currently_animating(); + to_screen_is_potentially_animated = data.to_screen_is_potentially_animated(); + has_only_translation_animations = data.has_only_translation_animations(); + + flattens_inherited_transform = data.flattens_inherited_transform(); + node_and_ancestors_are_flat = data.node_and_ancestors_are_flat(); + + node_and_ancestors_have_only_integer_translation = + data.node_and_ancestors_have_only_integer_translation(); + scrolls = data.scrolls(); + needs_sublayer_scale = data.needs_sublayer_scale(); + + affected_by_inner_viewport_bounds_delta_x = + data.affected_by_inner_viewport_bounds_delta_x(); + affected_by_inner_viewport_bounds_delta_y = + data.affected_by_inner_viewport_bounds_delta_y(); + affected_by_outer_viewport_bounds_delta_x = + data.affected_by_outer_viewport_bounds_delta_x(); + affected_by_outer_viewport_bounds_delta_y = + data.affected_by_outer_viewport_bounds_delta_y(); + + in_subtree_of_page_scale_layer = data.in_subtree_of_page_scale_layer(); + transform_changed = data.transform_changed(); + post_local_scale_factor = data.post_local_scale_factor(); + + sublayer_scale = ProtoToVector2dF(data.sublayer_scale()); + scroll_offset = ProtoToScrollOffset(data.scroll_offset()); + scroll_snap = ProtoToVector2dF(data.scroll_snap()); + source_offset = ProtoToVector2dF(data.source_offset()); + source_to_parent = ProtoToVector2dF(data.source_to_parent()); +} + +void TransformNode::AsValueInto(base::trace_event::TracedValue* value) const { + value->SetInteger("id", id); + value->SetInteger("parent_id", parent_id); + value->SetInteger("owner_id", owner_id); + MathUtil::AddToTracedValue("pre_local", pre_local, value); + MathUtil::AddToTracedValue("local", local, value); + MathUtil::AddToTracedValue("post_local", post_local, value); + // TODO(sunxd): make frameviewer work without target_id + value->SetInteger("target_id", 0); + value->SetInteger("content_target_id", 0); + value->SetInteger("source_node_id", source_node_id); + value->SetInteger("sorting_context_id", sorting_context_id); +} + +TransformCachedNodeData::TransformCachedNodeData() + : target_id(-1), content_target_id(-1) {} + +TransformCachedNodeData::TransformCachedNodeData( + const TransformCachedNodeData& other) = default; + +TransformCachedNodeData::~TransformCachedNodeData() {} + +bool TransformCachedNodeData::operator==( + const TransformCachedNodeData& other) const { + return from_target == other.from_target && to_target == other.to_target && + from_screen == other.from_screen && to_screen == other.to_screen && + target_id == other.target_id && + content_target_id == other.content_target_id; +} + +void TransformCachedNodeData::ToProtobuf( + proto::TransformCachedNodeData* proto) const { + TransformToProto(from_target, proto->mutable_from_target()); + TransformToProto(to_target, proto->mutable_to_target()); + TransformToProto(from_screen, proto->mutable_from_screen()); + TransformToProto(to_screen, proto->mutable_to_screen()); + proto->set_target_id(target_id); + proto->set_content_target_id(content_target_id); +} + +void TransformCachedNodeData::FromProtobuf( + const proto::TransformCachedNodeData& proto) { + from_target = ProtoToTransform(proto.from_target()); + to_target = ProtoToTransform(proto.to_target()); + from_screen = ProtoToTransform(proto.from_screen()); + to_screen = ProtoToTransform(proto.to_screen()); + target_id = proto.target_id(); + content_target_id = proto.content_target_id(); +} + +} // namespace cc
diff --git a/cc/trees/transform_node.h b/cc/trees/transform_node.h new file mode 100644 index 0000000..b128d4dd --- /dev/null +++ b/cc/trees/transform_node.h
@@ -0,0 +1,168 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_TRANSFORM_NODE_H_ +#define CC_TREES_TRANSFORM_NODE_H_ + +#include "cc/base/cc_export.h" +#include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/geometry/scroll_offset.h" +#include "ui/gfx/transform.h" + +namespace base { +namespace trace_event { +class TracedValue; +} // namespace trace_event +} // namespace base + +namespace cc { + +namespace proto { +class TransformCachedNodeData; +class TreeNode; +} // namespace proto + +struct CC_EXPORT TransformNode { + TransformNode(); + TransformNode(const TransformNode&); + + int id; + int parent_id; + int owner_id; + + // The local transform information is combined to form to_parent (ignoring + // snapping) as follows: + // + // to_parent = M_post_local * T_scroll * M_local * M_pre_local. + // + // The pre/post may seem odd when read LTR, but we multiply our points from + // the right, so the pre_local matrix affects the result "first". This lines + // up with the notions of pre/post used in skia and gfx::Transform. + // + // TODO(vollick): The values labeled with "will be moved..." take up a lot of + // space, but are only necessary for animated or scrolled nodes (otherwise + // we'll just use the baked to_parent). These values will be ultimately stored + // directly on the transform/scroll display list items when that's possible, + // or potentially in a scroll tree. + // + // TODO(vollick): will be moved when accelerated effects are implemented. + gfx::Transform pre_local; + gfx::Transform local; + gfx::Transform post_local; + + gfx::Transform to_parent; + + // This is the node with respect to which source_offset is defined. This will + // not be needed once layerization moves to cc, but is needed in order to + // efficiently update the transform tree for changes to position in the layer + // tree. + int source_node_id; + + // This id determines which 3d rendering context the node is in. 0 is a + // special value and indicates that the node is not in any 3d rendering + // context. + int sorting_context_id; + + // TODO(vollick): will be moved when accelerated effects are implemented. + bool needs_local_transform_update : 1; + + bool node_and_ancestors_are_animated_or_invertible : 1; + + bool is_invertible : 1; + bool ancestors_are_invertible : 1; + + bool has_potential_animation : 1; + bool is_currently_animating : 1; + bool to_screen_is_potentially_animated : 1; + bool has_only_translation_animations : 1; + + // Flattening, when needed, is only applied to a node's inherited transform, + // never to its local transform. + bool flattens_inherited_transform : 1; + + // This is true if the to_parent transform at every node on the path to the + // root is flat. + bool node_and_ancestors_are_flat : 1; + + // This is needed to know if a layer can use lcd text. + bool node_and_ancestors_have_only_integer_translation : 1; + + bool scrolls : 1; + + bool needs_sublayer_scale : 1; + + // These are used to position nodes wrt the right or bottom of the inner or + // outer viewport. + bool affected_by_inner_viewport_bounds_delta_x : 1; + bool affected_by_inner_viewport_bounds_delta_y : 1; + bool affected_by_outer_viewport_bounds_delta_x : 1; + bool affected_by_outer_viewport_bounds_delta_y : 1; + + // Layer scale factor is used as a fallback when we either cannot adjust + // raster scale or if the raster scale cannot be extracted from the screen + // space transform. For layers in the subtree of the page scale layer, the + // layer scale factor should include the page scale factor. + bool in_subtree_of_page_scale_layer : 1; + + // We need to track changes to to_screen transform to compute the damage rect. + bool transform_changed : 1; + + // TODO(vollick): will be moved when accelerated effects are implemented. + float post_local_scale_factor; + + gfx::Vector2dF sublayer_scale; + + // TODO(vollick): will be moved when accelerated effects are implemented. + gfx::ScrollOffset scroll_offset; + + // We scroll snap where possible, but this means fixed-pos elements must be + // adjusted. This value stores the snapped amount for this purpose. + gfx::Vector2dF scroll_snap; + + // TODO(vollick): will be moved when accelerated effects are implemented. + gfx::Vector2dF source_offset; + gfx::Vector2dF source_to_parent; + + bool operator==(const TransformNode& other) const; + + void set_to_parent(const gfx::Transform& transform) { + to_parent = transform; + is_invertible = to_parent.IsInvertible(); + } + + void update_pre_local_transform(const gfx::Point3F& transform_origin); + + void update_post_local_transform(const gfx::PointF& position, + const gfx::Point3F& transform_origin); + + void ToProtobuf(proto::TreeNode* proto) const; + void FromProtobuf(const proto::TreeNode& proto); + + void AsValueInto(base::trace_event::TracedValue* value) const; +}; + +// TODO(sunxd): move this into PropertyTrees::cached_data_. +struct CC_EXPORT TransformCachedNodeData { + TransformCachedNodeData(); + TransformCachedNodeData(const TransformCachedNodeData& other); + ~TransformCachedNodeData(); + + gfx::Transform from_target; + gfx::Transform to_target; + gfx::Transform from_screen; + gfx::Transform to_screen; + int target_id; + // This id is used for all content that draws into a render surface associated + // with this transform node. + int content_target_id; + + bool operator==(const TransformCachedNodeData& other) const; + + void ToProtobuf(proto::TransformCachedNodeData* proto) const; + void FromProtobuf(const proto::TransformCachedNodeData& proto); +}; + +} // namespace cc + +#endif // CC_TREES_TRANSFORM_NODE_H_
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc index 5ac778c..c50ff3ef 100644 --- a/cc/trees/tree_synchronizer_unittest.cc +++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -21,6 +21,7 @@ #include "cc/test/fake_rendering_stats_instrumentation.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/task_runner_provider.h" @@ -60,7 +61,7 @@ std::unique_ptr<LayerImpl> CreateLayerImpl( LayerTreeImpl* tree_impl) override { - return MockLayerImpl::Create(tree_impl, layer_id_); + return MockLayerImpl::Create(tree_impl, id()); } void PushPropertiesTo(LayerImpl* layer_impl) override { @@ -101,25 +102,25 @@ SCOPED_TRACE("mask_layer"); int mask_layer_id = layer->mask_layer()->id(); EXPECT_TRUE(tree_impl->LayerById(mask_layer_id)); - EXPECT_EQ(mask_layer_id, - effect_tree.Node(layer_impl->effect_tree_index()) - ->data.mask_layer_id); + EXPECT_EQ( + mask_layer_id, + effect_tree.Node(layer_impl->effect_tree_index())->mask_layer_id); } if (layer->replica_layer()) { SCOPED_TRACE("replica_layer"); int replica_layer_id = layer->replica_layer()->id(); EXPECT_TRUE(tree_impl->LayerById(layer->replica_layer()->id())); - EXPECT_EQ(replica_layer_id, - effect_tree.Node(layer_impl->effect_tree_index()) - ->data.replica_layer_id); + EXPECT_EQ( + replica_layer_id, + effect_tree.Node(layer_impl->effect_tree_index())->replica_layer_id); if (layer->replica_layer()->mask_layer()) { SCOPED_TRACE("replica_mask_layer"); int replica_mask_layer_id = layer->replica_layer()->mask_layer()->id(); EXPECT_TRUE(tree_impl->LayerById(replica_mask_layer_id)); EXPECT_EQ(replica_mask_layer_id, effect_tree.Node(layer_impl->effect_tree_index()) - ->data.replica_mask_layer_id); + ->replica_mask_layer_id); } }
diff --git a/chrome/VERSION b/chrome/VERSION index 0c92b88..8456c5b 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=54 MINOR=0 -BUILD=2790 +BUILD=2792 PATCH=0
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 7483a0c..fa082e9 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -650,7 +650,7 @@ android:exported="false"/> <receiver android:name="com.google.ipc.invalidation.ticl.android2.AndroidInternalScheduler$AlarmReceiver" android:exported="false"/> - <receiver android:name="com.google.ipc.invalidation.external.client2.contrib.AndroidListener$AlarmReceiver" + <receiver android:name="com.google.ipc.invalidation.external.client.contrib.AndroidListener$AlarmReceiver" android:exported="false"/> <!-- Android Notification service listener -->
diff --git a/chrome/android/java/res/color/dark_mode_tint.xml b/chrome/android/java/res/color/dark_mode_tint.xml index 9026e931..0d032dd 100644 --- a/chrome/android/java/res/color/dark_mode_tint.xml +++ b/chrome/android/java/res/color/dark_mode_tint.xml
@@ -4,10 +4,10 @@ found in the LICENSE file. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_selected="true" android:color="@color/light_active_color" /> - <item android:state_focused="true" android:color="@color/light_active_color" /> - <item android:state_pressed="true" android:color="@color/light_active_color" /> - <item android:state_activated="true" android:color="@color/light_active_color" /> - <item android:state_enabled="false" android:color="#335a5a5a" /> - <item android:color="@color/light_normal_color"/> + <item android:state_selected="true" android:color="@color/toolbar_light_tint" /> + <item android:state_focused="true" android:color="@color/toolbar_light_tint" /> + <item android:state_pressed="true" android:color="@color/toolbar_light_tint" /> + <item android:state_activated="true" android:color="@color/toolbar_light_tint" /> + <item android:state_enabled="false" android:color="#3D000000" /> + <item android:color="@color/toolbar_light_tint"/> </selector>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 2c00620..decd525 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -23,6 +23,7 @@ <color name="google_grey_300">#e0e0e0</color> <color name="google_grey_600">#757575</color> <color name="toolbar_shadow_color">#1d000000</color> + <color name="toolbar_light_tint">#A3000000</color> <!-- Infobar colors --> <color name="infobar_accent_blue">#4285f4</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java index 83fa3b7..7992cf9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java
@@ -66,6 +66,9 @@ // A pointer back to the native part of the implementation for this dialog. long mNativeBluetoothChooserDialogPtr; + // Used to keep track of when the Mode Changed Receiver is registered. + boolean mIsLocationModeChangedReceiverRegistered = false; + @VisibleForTesting final BroadcastReceiver mLocationModeBroadcastReceiver = new BroadcastReceiver() { @Override @@ -152,11 +155,16 @@ mActivity.registerReceiver(mLocationModeBroadcastReceiver, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); + mIsLocationModeChangedReceiverRegistered = true; } // Called to report the dialog's results back to native code. private void finishDialog(int resultCode, String id) { - mActivity.unregisterReceiver(mLocationModeBroadcastReceiver); + if (mIsLocationModeChangedReceiverRegistered) { + mActivity.unregisterReceiver(mLocationModeBroadcastReceiver); + mIsLocationModeChangedReceiverRegistered = false; + } + if (mNativeBluetoothChooserDialogPtr != 0) { nativeOnDialogFinished(mNativeBluetoothChooserDialogPtr, resultCode, id); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java index 1e73dc2e..50d60c9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
@@ -178,7 +178,7 @@ application.initializeSharedClasses(); // Start or stop Physical Web - PhysicalWeb.onChromeStart(application); + PhysicalWeb.onChromeStart(); mDeferredStartupComplete = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java index eccfd16e..4d5ea8f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -140,10 +140,10 @@ */ @SuppressWarnings("unused") @CalledByNative - private static void addShortcut(String id, String url, final String userTitle, String name, - String shortName, String iconUrl, Bitmap icon, int displayMode, int orientation, - int source, long themeColor, long backgroundColor, String manifestUrl, - final long callbackPointer) { + private static void addShortcut(String id, String url, String scopeUrl, + final String userTitle, String name, String shortName, String iconUrl, Bitmap icon, + int displayMode, int orientation, int source, long themeColor, long backgroundColor, + String manifestUrl, final long callbackPointer) { assert !ThreadUtils.runningOnUiThread(); Context context = ContextUtils.getApplicationContext(); @@ -154,15 +154,20 @@ if (CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_WEBAPK)) { WebApkBuilder apkBuilder = ((ChromeApplication) context).createWebApkBuilder(); if (apkBuilder != null) { - apkBuilder.buildWebApkAsync(url, GURLUtils.getOrigin(url), name, shortName, - iconUrl, icon, displayMode, orientation, themeColor, backgroundColor, - manifestUrl); + if (TextUtils.isEmpty(scopeUrl)) { + scopeUrl = GURLUtils.getOrigin(url); + } + apkBuilder.buildWebApkAsync(url, scopeUrl, name, shortName, iconUrl, icon, + displayMode, orientation, themeColor, backgroundColor, manifestUrl); return; } } + if (TextUtils.isEmpty(scopeUrl)) { + scopeUrl = getScopeFromUrl(url); + } shortcutIntent = createWebappShortcutIntent(id, sDelegate.getFullscreenAction(), url, - getScopeFromUrl(url), name, shortName, icon, WEBAPP_SHORTCUT_VERSION, - displayMode, orientation, themeColor, backgroundColor, iconUrl.isEmpty()); + scopeUrl, name, shortName, icon, WEBAPP_SHORTCUT_VERSION, displayMode, + orientation, themeColor, backgroundColor, iconUrl.isEmpty()); shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(context, url)); } else { // Add the shortcut as a launcher icon to open in the browser Activity. @@ -511,9 +516,9 @@ } /** - * Returns the URL with all but the last component of its path removed. This serves as a proxy - * for scope until the scope manifest member is available. This method assumes that the URL - * passed in is a valid URL with a path that contains at least one "/". + * Returns the URL with all but the last component of its path removed. This is used if the + * Web Manifest does not specify a scope. This method assumes that the URL passed in is a + * valid URL with a path that contains at least one "/". * @param url The url to convert to a scope. * @return The scope. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index 93419efc..49d94a65 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -19,6 +19,7 @@ import android.support.v4.widget.ExploreByTouchHelper; import android.util.AttributeSet; import android.util.Pair; +import android.view.DragEvent; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; @@ -384,6 +385,23 @@ return super.dispatchHoverEvent(e); } + @Override + public boolean dispatchDragEvent(DragEvent e) { + ContentViewCore contentViewCore = mTabVisible.getContentViewCore(); + if (contentViewCore == null) return false; + + if (mLayoutManager != null) mLayoutManager.getViewportPixel(mCacheViewport); + contentViewCore.setCurrentTouchEventOffsets(-mCacheViewport.left, -mCacheViewport.top); + boolean ret = super.dispatchDragEvent(e); + + int action = e.getAction(); + if (action == DragEvent.ACTION_DRAG_EXITED || action == DragEvent.ACTION_DRAG_ENDED + || action == DragEvent.ACTION_DROP) { + contentViewCore.setCurrentTouchEventOffsets(0.f, 0.f); + } + return ret; + } + /** * @return The {@link LayoutManager} associated with this view. */ @@ -483,11 +501,11 @@ if (actionMasked == MotionEvent.ACTION_DOWN || actionMasked == MotionEvent.ACTION_HOVER_ENTER) { if (mLayoutManager != null) mLayoutManager.getViewportPixel(mCacheViewport); - contentViewCore.setCurrentMotionEventOffsets(-mCacheViewport.left, -mCacheViewport.top); + contentViewCore.setCurrentTouchEventOffsets(-mCacheViewport.left, -mCacheViewport.top); } else if (canClear && (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL || actionMasked == MotionEvent.ACTION_HOVER_EXIT)) { - contentViewCore.setCurrentMotionEventOffsets(0.f, 0.f); + contentViewCore.setCurrentTouchEventOffsets(0.f, 0.f); } } @@ -902,7 +920,7 @@ * @param contentViewCore The {@link ContentViewCore} to initialize. */ private void initializeContentViewCore(ContentViewCore contentViewCore) { - contentViewCore.setCurrentMotionEventOffsets(0.f, 0.f); + contentViewCore.setCurrentTouchEventOffsets(0.f, 0.f); contentViewCore.setTopControlsHeight( getTopControlsHeightPixels(), contentViewCore.doTopControlsShrinkBlinkSize());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ClearNotificationAlarmReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ClearNotificationAlarmReceiver.java index 3264166..52a7637 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ClearNotificationAlarmReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ClearNotificationAlarmReceiver.java
@@ -21,6 +21,6 @@ @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "Running NotificationCleanupAlarmReceiver"); - UrlManager.getInstance(context).clearNotification(); + UrlManager.getInstance().clearNotification(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java index 9900cd90..22f951a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivity.java
@@ -32,7 +32,6 @@ import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.widget.FadingShadow; import org.chromium.chrome.browser.widget.FadingShadowView; @@ -122,8 +121,7 @@ mIsInitialDisplayRecorded = false; mIsRefreshing = false; mIsRefreshUserInitiated = false; - mPhysicalWebBleClient = - PhysicalWebBleClient.getInstance((ChromeApplication) getApplicationContext()); + mPhysicalWebBleClient = PhysicalWebBleClient.getInstance(); } @Override @@ -169,7 +167,7 @@ @Override protected void onStart() { super.onStart(); - UrlManager.getInstance(this).addObserver(this); + UrlManager.getInstance().addObserver(this); } @Override @@ -198,7 +196,7 @@ @Override protected void onStop() { - UrlManager.getInstance(this).removeObserver(this); + UrlManager.getInstance().removeObserver(this); super.onStop(); } @@ -267,13 +265,13 @@ // Clear the list adapter to trigger the empty list display. mAdapter.clear(); - Collection<UrlInfo> urls = UrlManager.getInstance(this).getUrls(true); + Collection<UrlInfo> urls = UrlManager.getInstance().getUrls(true); // Check the Physical Web preference to ensure we do not resolve URLs when Physical Web is // off or onboarding. Normally the user will not reach this activity unless the preference // is explicitly enabled, but there is a button on the diagnostics page that launches into // the activity without checking the preference state. - if (urls.isEmpty() || !PhysicalWeb.isPhysicalWebPreferenceEnabled(this)) { + if (urls.isEmpty() || !PhysicalWeb.isPhysicalWebPreferenceEnabled()) { finishRefresh(); } else { // Show the swipe-to-refresh busy indicator for refreshes initiated by a swipe.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWeb.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWeb.java index 8f806bab..ed8716c8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWeb.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWeb.java
@@ -4,12 +4,10 @@ package org.chromium.chrome.browser.physicalweb; -import android.content.Context; import android.content.SharedPreferences; import android.os.Build; import org.chromium.base.ContextUtils; -import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager; @@ -37,10 +35,9 @@ /** * Checks whether the Physical Web preference is switched to On. * - * @param context An instance of android.content.Context * @return boolean {@code true} if the preference is On. */ - public static boolean isPhysicalWebPreferenceEnabled(Context context) { + public static boolean isPhysicalWebPreferenceEnabled() { return PrivacyPreferencesManager.getInstance().isPhysicalWebEnabled(); } @@ -48,42 +45,37 @@ * Checks whether the Physical Web onboard flow is active and the user has * not yet elected to either enable or decline the feature. * - * @param context An instance of android.content.Context * @return boolean {@code true} if onboarding is complete. */ - public static boolean isOnboarding(Context context) { + public static boolean isOnboarding() { return PrivacyPreferencesManager.getInstance().isPhysicalWebOnboarding(); } /** * Start the Physical Web feature. * At the moment, this only enables URL discovery over BLE. - * @param application An instance of {@link ChromeApplication}, used to get the - * appropriate PhysicalWebBleClient implementation. */ - public static void startPhysicalWeb(final ChromeApplication application) { - PhysicalWebBleClient.getInstance(application).backgroundSubscribe(new Runnable() { + public static void startPhysicalWeb() { + PhysicalWebBleClient.getInstance().backgroundSubscribe(new Runnable() { @Override public void run() { // We need to clear the list of nearby URLs so that they can be repopulated by the // new subscription, but we don't know whether we are already subscribed, so we need // to pass a callback so that we can clear as soon as we are resubscribed. - UrlManager.getInstance(application).clearNearbyUrls(); + UrlManager.getInstance().clearNearbyUrls(); } }); } /** * Stop the Physical Web feature. - * @param application An instance of {@link ChromeApplication}, used to get the - * appropriate PhysicalWebBleClient implementation. */ - public static void stopPhysicalWeb(final ChromeApplication application) { - PhysicalWebBleClient.getInstance(application).backgroundUnsubscribe(new Runnable() { + public static void stopPhysicalWeb() { + PhysicalWebBleClient.getInstance().backgroundUnsubscribe(new Runnable() { @Override public void run() { // This isn't absolutely necessary, but it's nice to clean up all our shared prefs. - UrlManager.getInstance(application).clearAllUrls(); + UrlManager.getInstance().clearAllUrls(); } }); } @@ -100,12 +92,9 @@ /** * Increments a value tracking how many times we've shown the Physical Web * opt-in notification. - * - * @param context An instance of android.content.Context */ - public static void recordOptInNotification(Context context) { - SharedPreferences sharedPreferences = - ContextUtils.getAppSharedPreferences(); + public static void recordOptInNotification() { + SharedPreferences sharedPreferences = ContextUtils.getAppSharedPreferences(); int value = sharedPreferences.getInt(PREF_PHYSICAL_WEB_NOTIFY_COUNT, 0); sharedPreferences.edit().putInt(PREF_PHYSICAL_WEB_NOTIFY_COUNT, value + 1).apply(); } @@ -113,34 +102,29 @@ /** * Gets the current count of how many times a high-priority opt-in notification * has been shown. - * - * @param context An instance of android.content.Context * @return an integer representing the high-priority notifification display count. */ - public static int getOptInNotifyCount(Context context) { - SharedPreferences sharedPreferences = - ContextUtils.getAppSharedPreferences(); + public static int getOptInNotifyCount() { + SharedPreferences sharedPreferences = ContextUtils.getAppSharedPreferences(); return sharedPreferences.getInt(PREF_PHYSICAL_WEB_NOTIFY_COUNT, 0); } /** * Perform various Physical Web operations that should happen on startup. - * @param application An instance of {@link ChromeApplication}. */ - public static void onChromeStart(ChromeApplication application) { + public static void onChromeStart() { // The PhysicalWebUma calls in this method should be called only when the native library is // loaded. This is always the case on chrome startup. - if (featureIsEnabled() - && (isPhysicalWebPreferenceEnabled(application) || isOnboarding(application))) { + if (featureIsEnabled() && (isPhysicalWebPreferenceEnabled() || isOnboarding())) { boolean ignoreOtherClients = ChromeFeatureList.isEnabled(IGNORE_OTHER_CLIENTS_FEATURE_NAME); ContextUtils.getAppSharedPreferences().edit() .putBoolean(PREF_IGNORE_OTHER_CLIENTS, ignoreOtherClients) .apply(); - startPhysicalWeb(application); - PhysicalWebUma.uploadDeferredMetrics(application); + startPhysicalWeb(); + PhysicalWebUma.uploadDeferredMetrics(); } else { - stopPhysicalWeb(application); + stopPhysicalWeb(); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebBleClient.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebBleClient.java index 01918a3..233bbb7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebBleClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebBleClient.java
@@ -6,6 +6,7 @@ import android.app.Activity; +import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.chrome.browser.ChromeApplication; @@ -21,14 +22,13 @@ /** * Get a singleton instance of this class. - * @param chromeApplication An instance of {@link ChromeApplication}, used to get the - * appropriate PhysicalWebBleClient implementation. * @return an instance of this class (or subclass) as decided by the * application parameter */ - public static PhysicalWebBleClient getInstance(ChromeApplication chromeApplication) { + public static PhysicalWebBleClient getInstance() { if (sInstance == null) { - sInstance = chromeApplication.createPhysicalWebBleClient(); + sInstance = ((ChromeApplication) ContextUtils.getApplicationContext()) + .createPhysicalWebBleClient(); } return sInstance; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebDiagnosticsPage.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebDiagnosticsPage.java index 69eff55..836e46b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebDiagnosticsPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebDiagnosticsPage.java
@@ -104,8 +104,8 @@ LocationUtils locationUtils = LocationUtils.getInstance(); boolean isLocationServicesEnabled = locationUtils.isSystemLocationSettingEnabled(mContext); boolean isLocationPermissionGranted = locationUtils.hasAndroidLocationPermission(mContext); - boolean isPreferenceEnabled = PhysicalWeb.isPhysicalWebPreferenceEnabled(mContext); - boolean isOnboarding = PhysicalWeb.isOnboarding(mContext); + boolean isPreferenceEnabled = PhysicalWeb.isPhysicalWebPreferenceEnabled(); + boolean isOnboarding = PhysicalWeb.isOnboarding(); int prerequisitesResult = Utils.RESULT_SUCCESS; if (!isSdkVersionCorrect @@ -156,7 +156,7 @@ } private void appendUrlManagerReport(StringBuilder sb) { - UrlManager urlManager = UrlManager.getInstance(mContext); + UrlManager urlManager = UrlManager.getInstance(); Set<String> nearbyUrls = new HashSet<>(urlManager.getNearbyUrls()); Set<String> resolvedUrls = new HashSet<>(urlManager.getResolvedUrls());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebUma.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebUma.java index eb672dd..1267b7a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebUma.java
@@ -198,12 +198,12 @@ switch (referer) { case ListUrlsActivity.NOTIFICATION_REFERER: handleTime(context, STANDARD_NOTIFICATION_PRESS_DELAYS, - UrlManager.getInstance(context).getTimeSinceNotificationUpdate(), + UrlManager.getInstance().getTimeSinceNotificationUpdate(), TimeUnit.MILLISECONDS); break; case ListUrlsActivity.OPTIN_REFERER: handleTime(context, OPT_IN_NOTIFICATION_PRESS_DELAYS, - UrlManager.getInstance(context).getTimeSinceNotificationUpdate(), + UrlManager.getInstance().getTimeSinceNotificationUpdate(), TimeUnit.MILLISECONDS); break; case ListUrlsActivity.PREFERENCE_REFERER: @@ -237,8 +237,8 @@ handleEnum(context, createStateString(DATA_CONNECTION, actionName), Utils.isDataConnectionActive(context) ? 1 : 0, BOOLEAN_BOUNDARY); int preferenceState = 2; - if (!PhysicalWeb.isOnboarding(context)) { - preferenceState = PhysicalWeb.isPhysicalWebPreferenceEnabled(context) ? 1 : 0; + if (!PhysicalWeb.isOnboarding()) { + preferenceState = PhysicalWeb.isPhysicalWebPreferenceEnabled() ? 1 : 0; } handleEnum(context, createStateString(PREFERENCE, actionName), preferenceState, TRISTATE_BOUNDARY); @@ -249,7 +249,7 @@ * Additionally, this method will cause future stat records not to be deferred and instead * uploaded immediately. */ - public static void uploadDeferredMetrics(Context context) { + public static void uploadDeferredMetrics() { // If uploads have been explicitely requested, they are now allowed. sUploadAllowed = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java index 71f7e0e..e47895e1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
@@ -103,6 +103,7 @@ * Construct the UrlManager. * @param context An instance of android.content.Context */ + @VisibleForTesting public UrlManager(Context context) { mContext = context; mNotificationManager = new NotificationManagerProxyImpl( @@ -118,14 +119,22 @@ /** * Get a singleton instance of this class. - * @param context An instance of android.content.Context. + * @return A singleton instance of this class. + */ + public static UrlManager getInstance() { + if (sInstance == null) { + sInstance = new UrlManager(ContextUtils.getApplicationContext()); + } + return sInstance; + } + + /** + * Get a singleton instance of this class. + * @param context unused * @return A singleton instance of this class. */ public static UrlManager getInstance(Context context) { - if (sInstance == null) { - sInstance = new UrlManager(context); - } - return sInstance; + return getInstance(); } /** @@ -166,7 +175,7 @@ mNearbyUrls.add(urlInfo.getUrl()); putCachedNearbyUrls(); - if (!PhysicalWeb.isOnboarding(mContext) && !mResolvedUrls.contains(urlInfo.getUrl())) { + if (!PhysicalWeb.isOnboarding() && !mResolvedUrls.contains(urlInfo.getUrl())) { // We need to resolve the URL. resolveUrl(urlInfo); return; @@ -196,7 +205,7 @@ putCachedNearbyUrls(); // If there are no URLs nearby to display, clear the notification. - if (getUrls(PhysicalWeb.isOnboarding(mContext)).isEmpty()) { + if (getUrls(PhysicalWeb.isOnboarding()).isEmpty()) { clearNotification(); } } @@ -320,7 +329,7 @@ putCachedResolvedUrls(); // If there are no URLs nearby to display, clear the notification. - if (getUrls(PhysicalWeb.isOnboarding(mContext)).isEmpty()) { + if (getUrls(PhysicalWeb.isOnboarding()).isEmpty()) { clearNotification(); } } @@ -481,18 +490,18 @@ return; } - if (PhysicalWeb.isOnboarding(mContext)) { - if (PhysicalWeb.getOptInNotifyCount(mContext) < PhysicalWeb.OPTIN_NOTIFY_MAX_TRIES) { + if (PhysicalWeb.isOnboarding()) { + if (PhysicalWeb.getOptInNotifyCount() < PhysicalWeb.OPTIN_NOTIFY_MAX_TRIES) { // high priority notification createOptInNotification(true); - PhysicalWeb.recordOptInNotification(mContext); + PhysicalWeb.recordOptInNotification(); PhysicalWebUma.onOptInHighPriorityNotificationShown(mContext); } else { // min priority notification createOptInNotification(false); PhysicalWebUma.onOptInMinPriorityNotificationShown(mContext); } - } else if (PhysicalWeb.isPhysicalWebPreferenceEnabled(mContext)) { + } else if (PhysicalWeb.isPhysicalWebPreferenceEnabled()) { createNotification(); } } @@ -578,7 +587,7 @@ // Only trigger the notification if we know we didn't have a notification up already // (i.e., we have exactly 1 displayble URL) or this URL doesn't exist in the cache // (and hence the user hasn't swiped away a notification for this URL recently). - if (getUrls(PhysicalWeb.isOnboarding(mContext)).size() != 1 + if (getUrls(PhysicalWeb.isOnboarding()).size() != 1 && urlInfo.hasBeenDisplayed()) { return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PhysicalWebPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PhysicalWebPreferenceFragment.java index 689524c..083aab5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PhysicalWebPreferenceFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PhysicalWebPreferenceFragment.java
@@ -17,7 +17,6 @@ import org.chromium.base.Log; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.physicalweb.ListUrlsActivity; import org.chromium.chrome.browser.physicalweb.PhysicalWeb; import org.chromium.chrome.browser.physicalweb.PhysicalWebUma; @@ -65,8 +64,7 @@ && grantResults[0] == PackageManager.PERMISSION_GRANTED) { PhysicalWebUma.onPrefsLocationGranted(getActivity()); Log.d(TAG, "Location permission granted"); - PhysicalWeb.startPhysicalWeb( - (ChromeApplication) getActivity().getApplicationContext()); + PhysicalWeb.startPhysicalWeb(); } else { PhysicalWebUma.onPrefsLocationDenied(getActivity()); Log.d(TAG, "Location permission denied");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java index 983dcae..c4c2d433 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
@@ -13,7 +13,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.physicalweb.PhysicalWeb; @@ -441,10 +440,10 @@ mSharedPreferences.edit().putInt(PREF_PHYSICAL_WEB, state).apply(); if (enabled) { if (!isOnboarding) { - PhysicalWeb.startPhysicalWeb((ChromeApplication) mContext); + PhysicalWeb.startPhysicalWeb(); } } else { - PhysicalWeb.stopPhysicalWeb((ChromeApplication) mContext); + PhysicalWeb.stopPhysicalWeb(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index 003b5cc..6b1cd17d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -1714,6 +1714,16 @@ public void onUrlFocusChange(final boolean hasFocus) { super.onUrlFocusChange(hasFocus); + // https://crbug.com/623885: The mToolbarButtonsContainer has its translationY modified + // during scroll so when the user scrolls on the NTP, it appears to scroll too. However + // during the URL focus and defocus animations it should not be touched. Unfortunately + // updateNtpTransitionAnimation() is called a few times after the URL focus animation has + // been completed while mUrlFocusChangeInProgress is set to false, causing translationY to + // non-zero at the end. + // We reset the translationY here so the mToolbarButtonsContainer is on screen for the + // defocusing animation. + mToolbarButtonsContainer.setTranslationY(0f); + triggerUrlFocusAnimation(hasFocus); TransitionDrawable shadowDrawable = (TransitionDrawable) mToolbarShadow.getDrawable();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ProgressAnimationSmooth.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ProgressAnimationSmooth.java index 3cae062b..5752248 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ProgressAnimationSmooth.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ProgressAnimationSmooth.java
@@ -33,8 +33,6 @@ @Override public float updateProgress(float targetProgress, float frameTimeSec, int resolution) { - assert mProgress <= targetProgress; - final float acceleratingDuration = computeAcceleratingDuration( targetProgress, frameTimeSec); final float deceleratingDuration = frameTimeSec - acceleratingDuration;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java index 0290f13..026484d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java
@@ -95,6 +95,7 @@ public void run() { animateAlphaTo(0.0f); mIsRunningSmoothIndeterminate = false; + if (mAnimatingView != null) mAnimatingView.cancelAnimation(); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java index 8f1d9a3..a6e27c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java
@@ -249,6 +249,7 @@ */ public void cancelAnimation() { mIsCanceled = true; + mAnimatorSet.cancel(); // Reset position and alpha. setScaleX(0.0f); setTranslationX(0.0f);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java index 45d5e499..67b8d8a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java
@@ -57,6 +57,8 @@ assertEquals(mFinishedEventType, -1); mFinishedEventType = eventType; mFinishedDeviceId = deviceId; + // The native code calls closeDialog() when OnDialogFinished is called. + closeDialog(); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivityTest.java index c1fdced..b008afc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/ListUrlsActivityTest.java
@@ -65,7 +65,7 @@ mContext = getInstrumentation().getTargetContext(); // Restore the onboarding state ContextUtils.getAppSharedPreferences().edit().putInt("physical_web", 2).apply(); - UrlManager urlManager = UrlManager.getInstance(mContext); + UrlManager urlManager = UrlManager.getInstance(); mMockPwsClient = new MockPwsClient(); urlManager.overridePwsClientForTesting(mMockPwsClient); urlManager.overrideNotificationManagerForTesting(new MockNotificationManagerProxy()); @@ -156,7 +156,7 @@ results.add(new PwsResult(url, url, null, title, desc)); mMockPwsClient.addPwsResults(results); mMockPwsClient.addPwsResults(results); - UrlManager.getInstance(mContext).addUrl(url); + UrlManager.getInstance().addUrl(url); getInstrumentation().waitForIdleSync(); }
diff --git a/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/DexLoaderTest.java b/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/DexLoaderTest.java index 1e77656b..a002a79 100644 --- a/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/DexLoaderTest.java +++ b/chrome/android/webapk/shell_apk/javatests/src/org/chromium/webapk/shell_apk/DexLoaderTest.java
@@ -42,15 +42,18 @@ "org.chromium.webapk.shell_apk.test.dex_optimizer.DexOptimizerServiceImpl"; /** - * Name of the dex file in DexOptimizer.apk. + * Name of dex files in DexOptimizer.apk. */ private static final String DEX_ASSET_NAME = "canary.dex"; + private static final String DEX_ASSET_NAME2 = "canary2.dex"; /** - * Class to load to check whether dex is valid. + * Classes to load to check whether dex is valid. */ private static final String CANARY_CLASS_NAME = "org.chromium.webapk.shell_apk.test.canary.Canary"; + private static final String CANARY_CLASS_NAME2 = + "org.chromium.webapk.shell_apk.test.canary.Canary2"; private Context mContext; private Context mRemoteContext; @@ -217,47 +220,33 @@ } /** - * Test that {@link DexLoader#load()} re-extracts the dex file from the APK after a call to - * {@link DexLoader#deleteCachedDexes()}. + * Test loading a dex file from a directory which was previously used for loading a different + * dex file. */ @MediumTest - public void testLoadAfterDeleteCachedDexes() { + public void testLoadDifferentDexInLocalDataDir() { assertTrue(mLocalDexDir.mkdir()); - { - // Load dex the first time. This should extract the dex file from the APK's assets and - // generate the optimized dex file. - FileMonitor localDexDirMonitor = new FileMonitor(mLocalDexDir); - localDexDirMonitor.startWatching(); - ClassLoader loader = DexLoader.load( - mRemoteContext, DEX_ASSET_NAME, CANARY_CLASS_NAME, null, mLocalDexDir); - localDexDirMonitor.stopWatching(); + // Load canary.dex + ClassLoader loader1 = DexLoader.load( + mRemoteContext, DEX_ASSET_NAME, CANARY_CLASS_NAME, null, mLocalDexDir); + assertNotNull(loader1); + assertTrue(canLoadCanaryClass(loader1)); - assertNotNull(loader); - assertTrue(canLoadCanaryClass(loader)); - - assertTrue(localDexDirMonitor.mReadPaths.contains(DEX_ASSET_NAME)); - assertTrue(localDexDirMonitor.mModifiedPaths.contains(DEX_ASSET_NAME)); - } + File canaryDexFile1 = new File(mLocalDexDir, DEX_ASSET_NAME); + assertTrue(canaryDexFile1.exists()); DexLoader.deleteCachedDexes(mLocalDexDir); - { - // Load dex a second time. - FileMonitor localDexDirMonitor = new FileMonitor(mLocalDexDir); - localDexDirMonitor.startWatching(); - ClassLoader loader = DexLoader.load( - mRemoteContext, DEX_ASSET_NAME, CANARY_CLASS_NAME, null, mLocalDexDir); - localDexDirMonitor.stopWatching(); + ClassLoader loader2 = DexLoader.load( + mRemoteContext, DEX_ASSET_NAME2, CANARY_CLASS_NAME2, null, mLocalDexDir); + assertNotNull(loader2); + assertTrue(canLoadClass(loader2, CANARY_CLASS_NAME2)); - // The returned ClassLoader should be valid. - assertNotNull(loader); - assertTrue(canLoadCanaryClass(loader)); - - // We should have re-extracted the dex from the APK's assets. - assertTrue(localDexDirMonitor.mReadPaths.contains(DEX_ASSET_NAME)); - assertTrue(localDexDirMonitor.mModifiedPaths.contains(DEX_ASSET_NAME)); - } + // canary2.dex should have been extracted and the previously extracted canary.dex file + // should have been deleted. + assertTrue(new File(mLocalDexDir, DEX_ASSET_NAME2).exists()); + assertFalse(canaryDexFile1.exists()); } /** @@ -325,8 +314,13 @@ /** Returns whether the ClassLoader can load {@link CANARY_CLASS_NAME} */ private boolean canLoadCanaryClass(ClassLoader loader) { + return canLoadClass(loader, CANARY_CLASS_NAME); + } + + /** Returns whether the ClassLoader can load a class */ + private boolean canLoadClass(ClassLoader loader, String className) { try { - loader.loadClass(CANARY_CLASS_NAME); + loader.loadClass(className); return true; } catch (Exception e) { return false;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 6d229ff0..33a2bf0 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5659,8 +5659,8 @@ <message name="IDS_FLAGS_GESTURE_REQUIREMENT_FOR_MEDIA_PLAYBACK_DESCRIPTION" desc="Description for the flag for gesture requiment for media playback"> User gesture requirement for playing media elements. Disabling this will allow autoplay to work. </message> - <message name="IDS_FLAGS_PASSIVE_DOCUMENT_EVENT_LISTENERS_DESCRIPTION" desc="Description for the flag to adjust the default behaviour for document level passive listeners."> - Forces touchstart, touchmove, mousewheel and wheel event listeners on document level targets (which haven't requested otherwise) to be treated as passive. + <message name="IDS_FLAGS_PASSIVE_DOCUMENT_EVENT_LISTENERS_DESCRIPTION" desc="Description for the flag to adjust the default behaviour for document level passive touch listeners."> + Forces touchstart, and touchmove event listeners on document level targets (which haven't requested otherwise) to be treated as passive. </message> <message name="IDS_FLAGS_PASSIVE_DOCUMENT_EVENT_LISTENERS_NAME" desc="Name for the flag to adjust the default behaviour for document level passive listeners."> Document Level Event Listeners Passive Default
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc index 927d57e..bd0e252f 100644 --- a/chrome/app/mash/mash_runner.cc +++ b/chrome/app/mash/mash_runner.cc
@@ -26,7 +26,7 @@ #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/identity.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/public/interfaces/service_factory.mojom.h" #include "services/shell/runner/common/switches.h" #include "services/shell/runner/host/child_process_base.h" @@ -73,7 +73,7 @@ service_ = CreateService(mojo_name); if (service_) { shell_connection_.reset( - new shell::ShellConnection(service_.get(), std::move(request))); + new shell::ServiceContext(service_.get(), std::move(request))); return; } LOG(ERROR) << "unknown name " << mojo_name; @@ -108,7 +108,7 @@ mojo::BindingSet<ServiceFactory> service_factory_bindings_; std::unique_ptr<shell::Service> service_; - std::unique_ptr<shell::ShellConnection> shell_connection_; + std::unique_ptr<shell::ServiceContext> shell_connection_; DISALLOW_COPY_AND_ASSIGN(DefaultService); }; @@ -187,7 +187,7 @@ init_params->native_runner_delegate = &native_runner_delegate; background_shell.Init(std::move(init_params)); service_.reset(new DefaultService); - shell_connection_.reset(new shell::ShellConnection( + shell_connection_.reset(new shell::ServiceContext( service_.get(), background_shell.CreateServiceRequest("exe:chrome_mash"))); shell_connection_->connector()->Connect("mojo:mash_session"); @@ -205,7 +205,7 @@ // TODO(sky): use MessagePumpMojo. base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); service_.reset(new DefaultService); - shell_connection_.reset(new shell::ShellConnection( + shell_connection_.reset(new shell::ServiceContext( service_.get(), std::move(service_request))); message_loop.Run(); }
diff --git a/chrome/app/mash/mash_runner.h b/chrome/app/mash/mash_runner.h index 2a79f3f..108f9ed 100644 --- a/chrome/app/mash/mash_runner.h +++ b/chrome/app/mash/mash_runner.h
@@ -12,7 +12,7 @@ namespace shell { class Service; -class ShellConnection; +class ServiceContext; } // Responsible for running mash, both child and main processes. @@ -30,7 +30,7 @@ void StartChildApp(shell::mojom::ServiceRequest service_request); std::unique_ptr<shell::Service> service_; - std::unique_ptr<shell::ShellConnection> shell_connection_; + std::unique_ptr<shell::ServiceContext> shell_connection_; DISALLOW_COPY_AND_ASSIGN(MashRunner); };
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 86f4f72e..f45e0b7 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -835,9 +835,16 @@ <message name="IDS_SETTINGS_LINKDOCTOR_PREF" desc="The documentation string of the 'Use Link Doctor' preference to help with navigation errors."> Use a web service to help resolve navigation errors </message> - <message name="IDS_SETTINGS_SUGGEST_PREF" desc="The documentation string of the 'Use Suggest' preference"> - Use a prediction service to help complete searches and URLs typed in the address bar or the app launcher search box - </message> + <if expr="chromeos"> + <message name="IDS_SETTINGS_SUGGEST_PREF" desc="The documentation string of the 'Use Suggest' preference"> + Use a prediction service to help complete searches and URLs typed in the address bar or the app launcher search box + </message> + </if> + <if expr="not chromeos"> + <message name="IDS_SETTINGS_SUGGEST_PREF" desc="The documentation string of the 'Use Suggest' preference"> + Use a prediction service to help complete searches and URLs typed in the address bar + </message> + </if> <message name="IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESCRIPTION" desc="In the advanced options tab, the text next to the checkbox that enables prediction of network actions. Actions include browser-initiated DNS prefetching, TCP and SSL preconnection, and prerendering of webpages."> Use a prediction service to load pages more quickly </message>
diff --git a/chrome/app/theme/chrome_unscaled_resources.grd b/chrome/app/theme/chrome_unscaled_resources.grd index dc26321b5..46433415 100644 --- a/chrome/app/theme/chrome_unscaled_resources.grd +++ b/chrome/app/theme/chrome_unscaled_resources.grd
@@ -73,26 +73,6 @@ <include name="IDR_PROFILE_AVATAR_2X_25" file="default_200_percent/common/profile_avatar_sun_cloud.png" type="BINDATA" /> <include name="IDR_PROFILE_AVATAR_2X_26" file="default_200_percent/common/profile_avatar_placeholder.png" type="BINDATA" /> </if> - <if expr="is_macosx and enable_app_list"> - <!-- App Launcher icons for .app shim, dock icon. Unscaled, because the - icon file built does not depend on UI scale factor. --> - <if expr="_google_chrome"> - <include name="IDR_APP_LIST_16" file="google_chrome/mac/app_list_16.png" type="BINDATA" /> - <include name="IDR_APP_LIST_32" file="google_chrome/mac/app_list_32.png" type="BINDATA" /> - <include name="IDR_APP_LIST_128" file="google_chrome/mac/app_list_128.png" type="BINDATA" /> - <include name="IDR_APP_LIST_256" file="google_chrome/mac/app_list_256.png" type="BINDATA" /> - <include name="IDR_APP_LIST_CANARY_16" file="google_chrome/mac/app_list_canary_16.png" type="BINDATA" /> - <include name="IDR_APP_LIST_CANARY_32" file="google_chrome/mac/app_list_canary_32.png" type="BINDATA" /> - <include name="IDR_APP_LIST_CANARY_128" file="google_chrome/mac/app_list_canary_128.png" type="BINDATA" /> - <include name="IDR_APP_LIST_CANARY_256" file="google_chrome/mac/app_list_canary_256.png" type="BINDATA" /> - </if> - <if expr="not _google_chrome"> - <include name="IDR_APP_LIST_16" file="chromium/mac/app_list_16.png" type="BINDATA" /> - <include name="IDR_APP_LIST_32" file="chromium/mac/app_list_32.png" type="BINDATA" /> - <include name="IDR_APP_LIST_128" file="chromium/mac/app_list_128.png" type="BINDATA" /> - <include name="IDR_APP_LIST_256" file="chromium/mac/app_list_256.png" type="BINDATA" /> - </if> - </if> <if expr="is_linux and enable_app_list"> <!-- App Launcher icons for desktop icon. --> <if expr="_google_chrome">
diff --git a/chrome/app/theme/chromium/mac/app_list_128.png b/chrome/app/theme/chromium/mac/app_list_128.png deleted file mode 100644 index e52551432..0000000 --- a/chrome/app/theme/chromium/mac/app_list_128.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/chromium/mac/app_list_16.png b/chrome/app/theme/chromium/mac/app_list_16.png deleted file mode 100644 index 8e5839e..0000000 --- a/chrome/app/theme/chromium/mac/app_list_16.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/chromium/mac/app_list_256.png b/chrome/app/theme/chromium/mac/app_list_256.png deleted file mode 100644 index 5acdd92..0000000 --- a/chrome/app/theme/chromium/mac/app_list_256.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/chromium/mac/app_list_32.png b/chrome/app/theme/chromium/mac/app_list_32.png deleted file mode 100644 index fa8b860b..0000000 --- a/chrome/app/theme/chromium/mac/app_list_32.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/android/preferences/important_sites_util.cc b/chrome/browser/android/preferences/important_sites_util.cc index 3b0ec0d..6faed99 100644 --- a/chrome/browser/android/preferences/important_sites_util.cc +++ b/chrome/browser/android/preferences/important_sites_util.cc
@@ -8,6 +8,7 @@ #include <map> #include <set> +#include "base/metrics/histogram_macros.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" @@ -18,6 +19,25 @@ namespace { +// Do not change the values here, as they are used for UMA histograms. +enum ReasonStatTypes { + DURABLE = 0, + NOTIFICATIONS, + ENGAGEMENT, + NOTIFICATIONS_AND_ENGAGEMENT, + DURABLE_AND_ENGAGEMENT, + NOTIFICATIONS_AND_DURABLE, + NOTIFICATIONS_AND_DURABLE_AND_ENGAGEMENT, + REASON_UNKNOWN, + REASON_BOUNDARY +}; + +struct ImportantReason { + bool engagement = false; + bool notifications = false; + bool durable = false; +}; + std::vector<std::pair<GURL, double>> GetSortedTopEngagementOrigins( const SiteEngagementService* site_engagement_service, const std::map<GURL, double>& engagement_map, @@ -142,6 +162,106 @@ return final_list; } +void ImportantSitesUtil::RecordMetricsForBlacklistedSites( + Profile* profile, + std::vector<std::string> blacklisted_sites) { + SiteEngagementService* site_engagement_service = + SiteEngagementService::Get(profile); + + std::map<std::string, ImportantReason> reason_map; + + std::map<GURL, double> engagement_map = + site_engagement_service->GetScoreMap(); + + // Site engagement. + for (const auto& url_score_pair : engagement_map) { + if (url_score_pair.second < + SiteEngagementScore::GetMediumEngagementBoundary()) { + continue; + } + const std::string& host = url_score_pair.first.host(); + for (const std::string& blacklisted_site : blacklisted_sites) { + if (host.find(blacklisted_site) != std::string::npos) { + reason_map[blacklisted_site].engagement |= true; + break; + } + } + } + + // Durable. + ContentSettingsForOneType content_settings_list; + HostContentSettingsMapFactory::GetForProfile(profile)->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_DURABLE_STORAGE, + content_settings::ResourceIdentifier(), &content_settings_list); + for (const ContentSettingPatternSource& site : content_settings_list) { + if (site.setting != CONTENT_SETTING_ALLOW) + continue; + GURL origin(site.primary_pattern.ToString()); + if (!origin.is_valid()) + continue; + const std::string& host = origin.host(); + for (const std::string& blacklisted_site : blacklisted_sites) { + if (host.find(blacklisted_site) != std::string::npos) { + reason_map[blacklisted_site].durable |= true; + break; + } + } + } + + // Notifications. + content_settings_list.clear(); + HostContentSettingsMapFactory::GetForProfile(profile)->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_NOTIFICATIONS, + content_settings::ResourceIdentifier(), &content_settings_list); + for (const ContentSettingPatternSource& site : content_settings_list) { + if (site.setting != CONTENT_SETTING_ALLOW) + continue; + GURL origin(site.primary_pattern.ToString()); + if (!origin.is_valid()) + continue; + const std::string& host = origin.host(); + for (const std::string& blacklisted_site : blacklisted_sites) { + if (host.find(blacklisted_site) != std::string::npos) { + reason_map[blacklisted_site].notifications |= true; + break; + } + } + } + + // Note: we don't plan on adding new metrics here, this is just for the finch + // experiment to give us initial data on what signals actually mattered. + for (const auto& reason_pair : reason_map) { + const ImportantReason& reason = reason_pair.second; + if (reason.notifications && reason.durable && reason.engagement) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + NOTIFICATIONS_AND_DURABLE_AND_ENGAGEMENT, + REASON_BOUNDARY); + } else if (reason.notifications && reason.durable) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + NOTIFICATIONS_AND_DURABLE, REASON_BOUNDARY); + } else if (reason.notifications && reason.engagement) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + NOTIFICATIONS_AND_ENGAGEMENT, REASON_BOUNDARY); + } else if (reason.durable && reason.engagement) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + DURABLE_AND_ENGAGEMENT, REASON_BOUNDARY); + } else if (reason.notifications) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + NOTIFICATIONS, REASON_BOUNDARY); + } else if (reason.durable) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + DURABLE, REASON_BOUNDARY); + } else if (reason.engagement) { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + ENGAGEMENT, REASON_BOUNDARY); + } else { + UMA_HISTOGRAM_ENUMERATION("Storage.BlacklistedImportantSites.Reason", + REASON_UNKNOWN, REASON_BOUNDARY); + + } + } +} + void ImportantSitesUtil::MarkOriginAsImportantForTesting(Profile* profile, const GURL& origin) { // First get data from site engagement.
diff --git a/chrome/browser/android/preferences/important_sites_util.h b/chrome/browser/android/preferences/important_sites_util.h index d174d3b..5aae87d 100644 --- a/chrome/browser/android/preferences/important_sites_util.h +++ b/chrome/browser/android/preferences/important_sites_util.h
@@ -28,6 +28,10 @@ size_t max_results, std::vector<GURL>* optional_example_origins); + static void RecordMetricsForBlacklistedSites( + Profile* profile, + std::vector<std::string> blacklisted_sites); + // This marks the given origin as important so we can test features that rely // on important sites. static void MarkOriginAsImportantForTesting(Profile* profile,
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc index b5bb0ef..b878f6fe 100644 --- a/chrome/browser/android/preferences/pref_service_bridge.cc +++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -653,6 +653,11 @@ filter_builder.AddRegisterableDomain(domain); } + if (!excluding_domains.empty()) { + ImportantSitesUtil::RecordMetricsForBlacklistedSites(GetOriginalProfile(), + excluding_domains); + } + browsing_data_remover->RemoveWithFilter( BrowsingDataRemover::Period( static_cast<browsing_data::TimePeriod>(time_period)),
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc index dbf8e8f2..c6b5d7d 100644 --- a/chrome/browser/android/preferences/website_preference_bridge.cc +++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -623,8 +623,8 @@ } // Remove the trailing backslash so the origin is matched correctly in // SingleWebsitePreferences.mergePermissionInfoForTopLevelOrigin. - DCHECK(origin_str[origin_str.size() - 1] == '/'); - origin_str = origin_str.substr(0, origin_str.size() - 1); + DCHECK_EQ('/', origin_str.back()); + origin_str.pop_back(); ScopedJavaLocalRef<jstring> origin = ConvertUTF8ToJavaString(env_, origin_str); Java_WebsitePreferenceBridge_insertLocalStorageInfoIntoMap(
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc index e4769d9..3e1c122b 100644 --- a/chrome/browser/android/shortcut_helper.cc +++ b/chrome/browser/android/shortcut_helper.cc
@@ -72,6 +72,8 @@ base::android::ConvertUTF8ToJavaString(env, webapp_id); ScopedJavaLocalRef<jstring> java_url = base::android::ConvertUTF8ToJavaString(env, info.url.spec()); + ScopedJavaLocalRef<jstring> java_scope_url = + base::android::ConvertUTF8ToJavaString(env, info.scope.spec()); ScopedJavaLocalRef<jstring> java_user_title = base::android::ConvertUTF16ToJavaString(env, info.user_title); ScopedJavaLocalRef<jstring> java_name = @@ -102,6 +104,7 @@ env, java_webapp_id.obj(), java_url.obj(), + java_scope_url.obj(), java_user_title.obj(), java_name.obj(), java_short_name.obj(),
diff --git a/chrome/browser/android/shortcut_info.cc b/chrome/browser/android/shortcut_info.cc index 035ace6..9371a8a 100644 --- a/chrome/browser/android/shortcut_info.cc +++ b/chrome/browser/android/shortcut_info.cc
@@ -35,6 +35,9 @@ if (manifest.start_url.is_valid()) url = manifest.start_url; + if (manifest.scope.is_valid()) + scope = manifest.scope; + // Set the display based on the manifest value, if any. if (manifest.display != blink::WebDisplayModeUndefined) display = manifest.display;
diff --git a/chrome/browser/android/shortcut_info.h b/chrome/browser/android/shortcut_info.h index 0766c54..85716d6a 100644 --- a/chrome/browser/android/shortcut_info.h +++ b/chrome/browser/android/shortcut_info.h
@@ -42,6 +42,7 @@ GURL manifest_url; GURL url; + GURL scope; base::string16 user_title; base::string16 name; base::string16 short_name;
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 5cd24d4..a414b17 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -2355,7 +2355,8 @@ std::unique_ptr<net::test_server::HttpResponse> HandleDownloadRequestWithCookie( std::queue<net::HttpStatusCode>* status_codes, const net::test_server::HttpRequest& request) { - if (request.relative_url.find(kDownloadPathPrefix) != 0) { + if (!base::StartsWith(request.relative_url, kDownloadPathPrefix, + base::CompareCase::SENSITIVE)) { return std::unique_ptr<net::test_server::HttpResponse>(); } @@ -3340,6 +3341,95 @@ WebViewGuestScrollTouchTest, testing::Combine(testing::Bool(), testing::Bool())); +#if defined(USE_AURA) +class WebViewGuestTouchFocusTest : public WebViewTestBase { + public: + WebViewGuestTouchFocusTest() {} + void SetUpCommandLine(base::CommandLine* command_line) override { + WebViewTestBase::SetUpCommandLine(command_line); + + command_line->AppendSwitchASCII(switches::kTouchEvents, + switches::kTouchEventsEnabled); + } + + private: + DISALLOW_COPY_AND_ASSIGN(WebViewGuestTouchFocusTest); +}; + +class FocusChangeWaiter { + public: + explicit FocusChangeWaiter(content::WebContents* web_contents, + bool expected_focus) + : web_contents_(web_contents), expected_focus_(expected_focus) {} + ~FocusChangeWaiter() {} + + void WaitForFocusChange() { + while (expected_focus_ != + IsWebContentsBrowserPluginFocused(web_contents_)) { + base::RunLoop().RunUntilIdle(); + } + } + + private: + content::WebContents* web_contents_; + bool expected_focus_; +}; + +IN_PROC_BROWSER_TEST_F(WebViewGuestTouchFocusTest, + TouchFocusesBrowserPluginInEmbedder) { + // This test is only relevant for non-OOPIF WebView. + if (content::BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) + return; + + LoadAppWithGuest("web_view/guest_focus_test"); + + // Lookup relevant information about guest and embedder. + content::WebContents* embedder_contents = GetEmbedderWebContents(); + + std::vector<content::WebContents*> guest_web_contents_list; + GetGuestViewManager()->WaitForNumGuestsCreated(1u); + GetGuestViewManager()->GetGuestWebContentsList(&guest_web_contents_list); + ASSERT_EQ(1u, guest_web_contents_list.size()); + + content::WebContents* guest_contents = guest_web_contents_list[0]; + + gfx::Rect embedder_rect = embedder_contents->GetContainerBounds(); + gfx::Rect guest_rect = guest_contents->GetContainerBounds(); + + guest_rect.set_x(guest_rect.x() - embedder_rect.x()); + guest_rect.set_y(guest_rect.y() - embedder_rect.y()); + embedder_rect.set_x(0); + embedder_rect.set_y(0); + + // Don't send events that need to be routed until we know the child's surface + // is ready for hit testing. + WaitForGuestSurfaceReady(guest_contents); + + // 1) BrowserPlugin should not be focused at start. + EXPECT_FALSE(IsWebContentsBrowserPluginFocused(guest_contents)); + + // 2) Send touch event to guest, now BrowserPlugin should get focus. + { + gfx::Point point = guest_rect.CenterPoint(); + FocusChangeWaiter focus_waiter(guest_contents, true); + SendRoutedTouchTapSequence(embedder_contents, point); + SendRoutedGestureTapSequence(embedder_contents, point); + focus_waiter.WaitForFocusChange(); + EXPECT_TRUE(IsWebContentsBrowserPluginFocused(guest_contents)); + } + + // 3) Send touch start to embedder, now BrowserPlugin should lose focus. + { + gfx::Point point(10, 10); + FocusChangeWaiter focus_waiter(guest_contents, false); + SendRoutedTouchTapSequence(embedder_contents, point); + SendRoutedGestureTapSequence(embedder_contents,point); + focus_waiter.WaitForFocusChange(); + EXPECT_FALSE(IsWebContentsBrowserPluginFocused(guest_contents)); + } +} +#endif + IN_PROC_BROWSER_TEST_P(WebViewGuestScrollTouchTest, TestGuestGestureScrollsBubble) { // Just in case we're running ChromeOS tests, we need to make sure the
diff --git a/chrome/browser/banners/app_banner_data_fetcher.cc b/chrome/browser/banners/app_banner_data_fetcher.cc index 2b647326..fe4e8742 100644 --- a/chrome/browser/banners/app_banner_data_fetcher.cc +++ b/chrome/browser/banners/app_banner_data_fetcher.cc
@@ -115,6 +115,11 @@ if (is_active_) { FOR_EACH_OBSERVER(Observer, observer_list_, OnDecidedWhetherToShow(this, false)); + if (was_canceled_by_page_ && !page_requested_prompt_) { + TrackBeforeInstallEvent( + BEFORE_INSTALL_EVENT_PROMPT_NOT_CALLED_AFTER_PREVENT_DEFAULT); + } + is_active_ = false; was_canceled_by_page_ = false; page_requested_prompt_ = false; @@ -188,6 +193,7 @@ // Stash the referrer for the case where the banner is redisplayed. if (reply == blink::WebAppBannerPromptReply::Cancel && !page_requested_prompt_) { + TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED); was_canceled_by_page_ = true; referrer_ = referrer; OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel, @@ -195,6 +201,17 @@ return; } + // If we haven't yet returned, but either of |was_canceled_by_page_| or + // |page_requested_prompt_| is true, the page has requested a delayed showing + // of the prompt. Otherwise, the prompt was never canceled by the page. + if (was_canceled_by_page_ || page_requested_prompt_) { + TrackBeforeInstallEvent( + BEFORE_INSTALL_EVENT_PROMPT_CALLED_AFTER_PREVENT_DEFAULT); + was_canceled_by_page_ = false; + } else { + TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_NO_ACTION); + } + AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow( web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); @@ -202,6 +219,7 @@ FOR_EACH_OBSERVER(Observer, observer_list_, OnDecidedWhetherToShow(this, true)); + TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE); ShowBanner(app_icon_url_, app_icon_.get(), app_title_, referrer); is_active_ = false; } @@ -211,7 +229,7 @@ int request_id) { if (was_canceled_by_page_) { // Simulate an "OK" from the website to restart the banner display pipeline. - was_canceled_by_page_ = false; + // Don't reset |was_canceled_by_page_| yet for metrics purposes. OnBannerPromptReply(render_frame_host, request_id, blink::WebAppBannerPromptReply::None, referrer_); } else { @@ -401,6 +419,8 @@ app_icon_.reset(new SkBitmap(bitmap)); event_request_id_ = ++gCurrentRequestID; + + TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED); web_contents->GetMainFrame()->Send( new ChromeViewMsg_AppBannerPromptRequest( web_contents->GetMainFrame()->GetRoutingID(),
diff --git a/chrome/browser/banners/app_banner_metrics.cc b/chrome/browser/banners/app_banner_metrics.cc index f9bbd34..58e373d 100644 --- a/chrome/browser/banners/app_banner_metrics.cc +++ b/chrome/browser/banners/app_banner_metrics.cc
@@ -15,6 +15,7 @@ const char kMinutesHistogram[] = "AppBanners.MinutesFromFirstVisitToBannerShown"; const char kUserResponseHistogram[] = "AppBanners.UserResponse"; +const char kBeforeInstallEventHistogram[] = "AppBanners.BeforeInstallEvent"; void TrackDismissEvent(int event) { DCHECK_LT(DISMISS_EVENT_MIN, event); @@ -48,4 +49,10 @@ UMA_HISTOGRAM_SPARSE_SLOWLY(kUserResponseHistogram, event); } +void TrackBeforeInstallEvent(int event) { + DCHECK_LT(BEFORE_INSTALL_EVENT_MIN, event); + DCHECK_LT(event, BEFORE_INSTALL_EVENT_MAX); + UMA_HISTOGRAM_SPARSE_SLOWLY(kBeforeInstallEventHistogram, event); +} + } // namespace banners
diff --git a/chrome/browser/banners/app_banner_metrics.h b/chrome/browser/banners/app_banner_metrics.h index 8b96d8c8..357911aa 100644 --- a/chrome/browser/banners/app_banner_metrics.h +++ b/chrome/browser/banners/app_banner_metrics.h
@@ -7,7 +7,7 @@ namespace banners { -// Keep in sync with the values defined in histograms.xml. +// This enum backs a UMA histogram, so it should be treated as append-only. enum DisplayEvent { DISPLAY_EVENT_MIN = 0, DISPLAY_EVENT_BANNER_REQUESTED = 1, @@ -25,6 +25,7 @@ DISPLAY_EVENT_MAX = 13, }; +// This enum backs a UMA histogram, so it should be treated as append-only. enum InstallEvent { INSTALL_EVENT_MIN = 20, INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED = 21, @@ -34,6 +35,7 @@ INSTALL_EVENT_MAX = 25, }; +// This enum backs a UMA histogram, so it should be treated as append-only. enum DismissEvent { DISMISS_EVENT_MIN = 40, DISMISS_EVENT_ERROR = 41, @@ -46,6 +48,7 @@ DISMISS_EVENT_MAX = 48, }; +// This enum backs a UMA histogram, so it should be treated as append-only. enum UserResponse { USER_RESPONSE_MIN = 0, USER_RESPONSE_NATIVE_APP_ACCEPTED = 1, @@ -57,17 +60,31 @@ USER_RESPONSE_MAX = 7, }; +// This enum backs a UMA histogram, so it should be treated as append-only. +enum BeforeInstallEvent { + BEFORE_INSTALL_EVENT_MIN = 0, + BEFORE_INSTALL_EVENT_CREATED = 1, + BEFORE_INSTALL_EVENT_COMPLETE = 2, + BEFORE_INSTALL_EVENT_NO_ACTION = 3, + BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED = 4, + BEFORE_INSTALL_EVENT_PROMPT_CALLED_AFTER_PREVENT_DEFAULT = 5, + BEFORE_INSTALL_EVENT_PROMPT_NOT_CALLED_AFTER_PREVENT_DEFAULT = 6, + BEFORE_INSTALL_EVENT_MAX = 7, +}; + extern const char kDismissEventHistogram[]; extern const char kDisplayEventHistogram[]; extern const char kInstallEventHistogram[]; extern const char kMinutesHistogram[]; extern const char kUserResponseHistogram[]; +extern const char kBeforeInstallEventHistogram[]; void TrackDismissEvent(int event); void TrackDisplayEvent(int event); void TrackInstallEvent(int event); void TrackMinutesFromFirstVisitToBannerShown(int minutes); void TrackUserResponse(int event); +void TrackBeforeInstallEvent(int event); }; // namespace banners
diff --git a/chrome/browser/banners/app_banner_settings_helper_unittest.cc b/chrome/browser/banners/app_banner_settings_helper_unittest.cc index 0fb52d0..8f9acd5 100644 --- a/chrome/browser/banners/app_banner_settings_helper_unittest.cc +++ b/chrome/browser/banners/app_banner_settings_helper_unittest.cc
@@ -30,7 +30,10 @@ exploded_reference_time.second = 0; exploded_reference_time.millisecond = 0; - return base::Time::FromLocalExploded(exploded_reference_time); + base::Time out_time; + EXPECT_TRUE( + base::Time::FromLocalExploded(exploded_reference_time, &out_time)); + return out_time; } bool IsWithinDay(base::Time time1, base::Time time2) {
diff --git a/chrome/browser/browsing_data/registrable_domain_filter_builder.cc b/chrome/browser/browsing_data/registrable_domain_filter_builder.cc index 78fe5b4..a060483 100644 --- a/chrome/browser/browsing_data/registrable_domain_filter_builder.cc +++ b/chrome/browser/browsing_data/registrable_domain_filter_builder.cc
@@ -16,6 +16,27 @@ using net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES; using Relation = ContentSettingsPattern::Relation; +namespace { + +// Whether this is a registrable domain. +bool IsRegistrableDomain(const std::string& domain) { + return GetDomainAndRegistry(domain, INCLUDE_PRIVATE_REGISTRIES) == domain; +} + +// Whether this is a subdomain of a registrable domain. +bool IsSubdomainOfARegistrableDomain(const std::string& domain) { + std::string registrable_domain = + GetDomainAndRegistry(domain, INCLUDE_PRIVATE_REGISTRIES); + return registrable_domain != domain && registrable_domain != ""; +} + +// Note that for every domain, exactly one of the following holds: +// 1. IsRegistrableDomain(domain) - e.g. google.com +// 2. IsSubdomainOfARegistrableDomain(domain) - e.g. www.google.com +// 3. GetDomainAndRegistry(domain, _) == "" - e.g. localhost, 127.0.0.1 + +} // namespace + RegistrableDomainFilterBuilder::RegistrableDomainFilterBuilder(Mode mode) : BrowsingDataFilterBuilder(mode) { } @@ -24,11 +45,9 @@ void RegistrableDomainFilterBuilder::AddRegisterableDomain( const std::string& domain) { - // We check that the domain we're given is actually a eTLD+1, or an IP - // address. - DCHECK(GetDomainAndRegistry("www." + domain, INCLUDE_PRIVATE_REGISTRIES) == - domain || - GURL("http://" + domain).HostIsIPAddress()); + // We check that the domain we're given is actually a eTLD+1, an IP address, + // or an internal hostname. + DCHECK(!IsSubdomainOfARegistrableDomain(domain)); domain_list_.insert(domain); } @@ -46,16 +65,16 @@ new std::vector<ContentSettingsPattern>(); patterns_from_domains->reserve(domain_list_.size()); - std::unique_ptr<ContentSettingsPattern::BuilderInterface> builder( - ContentSettingsPattern::CreateBuilder(/* use_legacy_validate */ false)); for (const std::string& domain : domain_list_) { + std::unique_ptr<ContentSettingsPattern::BuilderInterface> builder( + ContentSettingsPattern::CreateBuilder(/* use_legacy_validate */ false)); builder->WithSchemeWildcard() ->WithPortWildcard() ->WithPathWildcard() ->WithHost(domain); - if (!GURL("http://" + domain).HostIsIPAddress()) { + if (IsRegistrableDomain(domain)) builder->WithDomainWildcard(); - } + patterns_from_domains->push_back(builder->Build()); } @@ -99,10 +118,10 @@ const GURL& url) { std::string url_registerable_domain = GetDomainAndRegistry(url, INCLUDE_PRIVATE_REGISTRIES); - return (registerable_domains->find(url_registerable_domain) != - registerable_domains->end() || - (url.HostIsIPAddress() && (registerable_domains->find(url.host()) != - registerable_domains->end()))) == + return (registerable_domains->find( + url_registerable_domain != "" ? url_registerable_domain + : url.host()) != + registerable_domains->end()) == (mode == WHITELIST); } @@ -132,7 +151,7 @@ cookie_domain = cookie_domain.substr(1); std::string parsed_cookie_domain = GetDomainAndRegistry(cookie_domain, INCLUDE_PRIVATE_REGISTRIES); - // This means we're an IP address. + // This means we're an IP address or an internal hostname. if (parsed_cookie_domain.empty()) parsed_cookie_domain = cookie_domain; return (mode == WHITELIST) == (domains_and_ips->find(parsed_cookie_domain) !=
diff --git a/chrome/browser/browsing_data/registrable_domain_filter_builder.h b/chrome/browser/browsing_data/registrable_domain_filter_builder.h index c7501af..c18c681 100644 --- a/chrome/browser/browsing_data/registrable_domain_filter_builder.h +++ b/chrome/browser/browsing_data/registrable_domain_filter_builder.h
@@ -29,6 +29,19 @@ // // See net/base/registry_controlled_domains/registry_controlled_domain.h for // more details on registrable domains and the current list of effective eTLDs. +// +// This filter also recognizes IP addresses and internal hostnames. Neither of +// those have subdomains (or support domain cookies), and so the filter requires +// the cookie (or other data type) source domain to be identical to the +// domain (IP address or internal hostname) for it to be considered a match. +// +// Note that e.g. "subdomain.localhost" is NOT considered to be a subdomain +// of the internal hostname "localhost". It is understood as a registrable +// domain in the scope of the TLD "localhost" (from unknown registry), +// and treated as any other registrable domain. For example, +// "www.subdomain.localhost" will be matched by a filter containing +// "subdomain.localhost". However, it is unrelated to "localhost", whose cookies +// will never be visible on "*.localhost" or vice versa. class RegistrableDomainFilterBuilder : public BrowsingDataFilterBuilder { public: // Constructs a filter with the given |mode| - whitelist or blacklist. @@ -38,7 +51,8 @@ // Adds a registerable domain to the (white- or black-) list. This is expected // to not include subdomains, so basically tld+1. This can also be an IP - // address. + // address or an internal hostname. + // // Refer to net/base/registry_controlled_domains/registry_controlled_domain.h // for more details on registrable domains and the current list of effective. // TLDs. We expect a string that would be returned by
diff --git a/chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc b/chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc index 9880ad6..b56dbcca 100644 --- a/chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc +++ b/chrome/browser/browsing_data/registrable_domain_filter_builder_unittest.cc
@@ -21,7 +21,15 @@ // sp.nom.br is an eTLD, so this is a regular valid registrable domain, just // like google.com. const char kLongETLDDomain[] = "website.sp.nom.br"; -// An IP address can be a registerable domain. +// This domain will also not be found in registries, and since it has only +// one component, it will not be recognized as a valid registrable domain. +const char kInternalHostname[] = "fileserver"; +// This domain will not be found in registries. It will be assumed that +// it belongs to an unknown registry, and since it has two components, +// they will be treated as the second level domain and TLD. Most importantly, +// it will NOT be treated as a subdomain of "fileserver". +const char kUnknownRegistryDomain[] = "second-level-domain.fileserver"; +// IP addresses are supported. const char kIPAddress[] = "192.168.1.1"; struct TestCase { @@ -116,10 +124,12 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter(); TestCase test_cases[] = { - // We matche any URL on the specified domains. + // We match any URL on the specified domains. {"http://www.google.com/foo/bar", true}, {"https://www.sub.google.com/foo/bar", true}, {"https://sub.google.com", true}, @@ -129,6 +139,16 @@ {"http://192.168.1.1", true}, {"http://192.168.1.1:80", true}, + // Internal hostnames do not have subdomains. + {"http://fileserver", true }, + {"http://fileserver/foo/bar", true }, + {"http://website.fileserver/foo/bar", false }, + + // This is a valid registrable domain with the TLD "fileserver", which + // is unrelated to the internal hostname "fileserver". + {"http://second-level-domain.fileserver/foo", true}, + {"http://www.second-level-domain.fileserver/index.html", true}, + // Different domains. {"https://www.youtube.com", false}, {"https://www.google.net", false}, @@ -148,10 +168,12 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const GURL&)> filter = builder.BuildGeneralFilter(); TestCase test_cases[] = { - // We matches any URL that are not on the specified domains. + // We match any URL that are not on the specified domains. {"http://www.google.com/foo/bar", false}, {"https://www.sub.google.com/foo/bar", false}, {"https://sub.google.com", false}, @@ -161,6 +183,16 @@ {"http://192.168.1.1", false}, {"http://192.168.1.1:80", false}, + // Internal hostnames do not have subdomains. + {"http://fileserver", false }, + {"http://fileserver/foo/bar", false }, + {"http://website.fileserver/foo/bar", true }, + + // This is a valid registrable domain with the TLD "fileserver", which + // is unrelated to the internal hostname "fileserver". + {"http://second-level-domain.fileserver/foo", false}, + {"http://www.second-level-domain.fileserver/index.html", false}, + // Different domains. {"https://www.youtube.com", true}, {"https://www.google.net", true}, @@ -180,6 +212,8 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const ContentSettingsPattern&)> filter = builder.BuildWebsiteSettingsPatternMatchesFilter(); @@ -212,6 +246,18 @@ {"https://sp.nom.br", false}, {"http://192.168.1.2", false}, + // Internal hostnames do not have subdomains. + {"http://fileserver", true }, + {"http://[*.]fileserver", false }, + {"http://website.fileserver", false }, + + // This is a valid registrable domain with the TLD "fileserver", which + // is unrelated to the internal hostname "fileserver". + {"http://second-level-domain.fileserver", true}, + {"http://[*.]second-level-domain.fileserver", true}, + {"http://www.second-level-domain.fileserver", true}, + {"http://[*.]www.second-level-domain.fileserver", true}, + // These patterns are more general than our registerable domain filter, // as they apply to more sites. So we don't match them. The content // settings categories that we'll be seeing from browsing_data_remover @@ -230,6 +276,8 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const ContentSettingsPattern&)> filter = builder.BuildWebsiteSettingsPatternMatchesFilter(); @@ -262,6 +310,18 @@ {"https://sp.nom.br", true}, {"http://192.168.1.2", true}, + // Internal hostnames do not have subdomains. + {"fileserver", false }, + {"http://[*.]fileserver", true }, + {"website.fileserver", true }, + + // This is a valid registrable domain with the TLD "fileserver", which + // is unrelated to the internal hostname "fileserver". + {"http://second-level-domain.fileserver", false}, + {"http://[*.]second-level-domain.fileserver", false}, + {"http://www.second-level-domain.fileserver", false}, + {"http://[*.]www.second-level-domain.fileserver", false}, + // These patterns are more general than our registerable domain filter, // as they apply to more sites. So we don't match them. The content // settings categories that we'll be seeing from browsing_data_remover @@ -280,6 +340,8 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const net::CanonicalCookie&)> filter = builder.BuildCookieFilter(); @@ -306,7 +368,18 @@ // Different hosts in general. {"https://www.chrome.com", false}, - {"http://192.168.2.1", false}}; + {"http://192.168.2.1", false}, + + // Internal hostnames do not have subdomains. + {"https://fileserver", true }, + {"http://fileserver/foo/bar", true }, + {"http://website.fileserver", false }, + + // This is a valid registrable domain with the TLD "fileserver", which + // is unrelated to the internal hostname "fileserver". + {"http://second-level-domain.fileserver", true}, + {"https://subdomain.second-level-domain.fileserver", true}, + }; for (TestCase test_case : test_cases) RunTestCase(test_case, filter); @@ -318,6 +391,8 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const net::CanonicalCookie&)> filter = builder.BuildCookieFilter(); @@ -344,7 +419,18 @@ // Different hosts in general. {"https://www.chrome.com", true}, - {"http://192.168.2.1", true}}; + {"http://192.168.2.1", true}, + + // Internal hostnames do not have subdomains. + {"https://fileserver", false }, + {"http://fileserver/foo/bar", false }, + {"http://website.fileserver", true }, + + // This is a valid registrable domain with the TLD "fileserver", which + // is unrelated to the internal hostname "fileserver". + {"http://second-level-domain.fileserver", false}, + {"https://subdomain.second-level-domain.fileserver", false}, + }; for (TestCase test_case : test_cases) RunTestCase(test_case, filter); @@ -356,20 +442,25 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const std::string&)> filter = builder.BuildChannelIDFilter(); TestCase test_cases[] = { - // Channel ID server identifiers can be top-level domains... + // Channel ID server identifiers can be second level domains, ... {"google.com", true}, {"website.sp.nom.br", true}, + {"second-level-domain.fileserver", true}, - // or IP addresses. + // ... IP addresses, or internal hostnames. {"192.168.1.1", true}, + {"fileserver", true}, // Channel IDs not in the whitelist are not matched. {"example.com", false}, {"192.168.1.2", false}, + {"website.fileserver", false}, }; for (TestCase test_case : test_cases) @@ -382,20 +473,25 @@ builder.AddRegisterableDomain(std::string(kGoogleDomain)); builder.AddRegisterableDomain(std::string(kLongETLDDomain)); builder.AddRegisterableDomain(std::string(kIPAddress)); + builder.AddRegisterableDomain(std::string(kUnknownRegistryDomain)); + builder.AddRegisterableDomain(std::string(kInternalHostname)); base::Callback<bool(const std::string&)> filter = builder.BuildChannelIDFilter(); TestCase test_cases[] = { - // Channel ID server identifiers can be top-level domains... + // Channel ID server identifiers can be second level domains, ... {"google.com", false}, {"website.sp.nom.br", false}, + {"second-level-domain.fileserver", false}, - // or IP addresses. + // ...IP addresses, or internal hostnames. {"192.168.1.1", false}, + {"fileserver", false}, // Channel IDs that are not blacklisted are matched. {"example.com", true}, {"192.168.1.2", true}, + {"website.fileserver", true}, }; for (TestCase test_case : test_cases)
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index fba326f..e4db346 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -37,6 +37,7 @@ #include "chromeos/chromeos_switches.h" #include "chromeos/login/user_names.h" #include "components/signin/core/account_id/account_id.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" @@ -57,7 +58,7 @@ // class LoggedInSpokenFeedbackTest : public InProcessBrowserTest { - protected: + public: LoggedInSpokenFeedbackTest() : animation_mode_(ui::ScopedAnimationDurationScaleMode::ZERO_DURATION) {} ~LoggedInSpokenFeedbackTest() override {} @@ -578,7 +579,15 @@ // Press the sticky-key sequence: Search Search. SendKeyPress(ui::VKEY_LWIN); - SendKeyPress(ui::VKEY_LWIN); + + // Sticky key has a minimum 100 ms check to prevent key repeat from toggling + // it. + content::BrowserThread::PostDelayedTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&LoggedInSpokenFeedbackTest::SendKeyPress, + base::Unretained(this), ui::VKEY_LWIN), + base::TimeDelta::FromMilliseconds(200)); + EXPECT_EQ("Sticky mode enabled", speech_monitor_.GetNextUtterance()); // Even once we hear "sticky mode enabled" from the ChromeVox background @@ -607,7 +616,15 @@ // Press the sticky-key sequence: Search Search. SendKeyPress(ui::VKEY_LWIN); - SendKeyPress(ui::VKEY_LWIN); + + // Sticky key has a minimum 100 ms check to prevent key repeat from toggling + // it. + content::BrowserThread::PostDelayedTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&LoggedInSpokenFeedbackTest::SendKeyPress, + base::Unretained(this), ui::VKEY_LWIN), + base::TimeDelta::FromMilliseconds(200)); + EXPECT_EQ("Sticky mode enabled", speech_monitor_.GetNextUtterance()); SendKeyPress(ui::VKEY_H); @@ -615,7 +632,15 @@ } SendKeyPress(ui::VKEY_LWIN); - SendKeyPress(ui::VKEY_LWIN); + + // Sticky key has a minimum 100 ms check to prevent key repeat from toggling + // it. + content::BrowserThread::PostDelayedTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&LoggedInSpokenFeedbackTest::SendKeyPress, + base::Unretained(this), ui::VKEY_LWIN), + base::TimeDelta::FromMilliseconds(200)); + while ("Sticky mode disabled" != speech_monitor_.GetNextUtterance()) { } }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc index 2f0ed35..bf9389d8 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -642,7 +642,7 @@ // |parent| may have a trailing slash if it is a root directory. std::string destination_url_string = params->parent_url; - if (destination_url_string[destination_url_string.size() - 1] != '/') + if (destination_url_string.back() != '/') destination_url_string += '/'; destination_url_string += net::EscapePath(params->new_name);
diff --git a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc index eb3e33e..e16e6e5a 100644 --- a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc +++ b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
@@ -27,6 +27,7 @@ #include "content/public/browser/browser_thread.h" #include "extensions/browser/entry_info.h" #include "mojo/public/cpp/bindings/binding.h" +#include "net/base/escape.h" #include "net/base/filename_util.h" #include "storage/browser/fileapi/file_system_url.h" #include "url/gurl.h" @@ -41,6 +42,10 @@ constexpr base::FilePath::CharType kArcDownloadPath[] = FILE_PATH_LITERAL("/sdcard/Download"); +constexpr base::FilePath::CharType kRemovableMediaPath[] = + FILE_PATH_LITERAL("/media/removable"); +constexpr char kArcRemovableMediaProviderUrl[] = + "content://org.chromium.arc.removablemediaprovider/"; constexpr char kAppIdSeparator = '/'; constexpr char kPngDataUrlPrefix[] = "data:image/png;base64,"; @@ -149,6 +154,15 @@ return true; } + // Convert paths under /media/removable. + base::FilePath relative_path; + if (base::FilePath(kRemovableMediaPath) + .AppendRelativePath(path, &relative_path)) { + *arc_url = GURL(kArcRemovableMediaProviderUrl) + .Resolve(net::EscapePath(relative_path.AsUTF8Unsafe())); + return true; + } + // TODO(kinaba): Add conversion logic once other file systems are supported. return false; }
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index be618d5..d2f554d 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -91,6 +91,7 @@ ::switches::kDisableGpuCompositing, ::switches::kDisableGpuRasterization, ::switches::kDisableLowResTiling, + ::switches::kDisablePepper3DImageChromium, ::switches::kDisablePreferCompositingToLCDText, ::switches::kDisablePanelFitting, ::switches::kDisableRGBA4444Textures,
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc index fdf71837..d731df4 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.cc +++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -103,7 +103,10 @@ int64_t TimestampToDayKey(Time timestamp) { Time::Exploded exploded; timestamp.LocalMidnight().LocalExplode(&exploded); - return (Time::FromUTCExploded(exploded) - Time::UnixEpoch()).InMilliseconds(); + Time out_time; + bool conversion_success = Time::FromUTCExploded(exploded, &out_time); + DCHECK(conversion_success); + return (out_time - Time::UnixEpoch()).InMilliseconds(); } // Helper function (invoked via blocking pool) to fetch information about
diff --git a/chrome/browser/chromeos/profiles/profile_helper.cc b/chrome/browser/chromeos/profiles/profile_helper.cc index 08c4058..91ff48c 100644 --- a/chrome/browser/chromeos/profiles/profile_helper.cc +++ b/chrome/browser/chromeos/profiles/profile_helper.cc
@@ -7,6 +7,7 @@ #include "base/barrier_closure.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/strings/string_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" @@ -138,13 +139,12 @@ // Check that profile directory starts with the correct prefix. std::string prefix(chrome::kProfileDirPrefix); - if (profile_dir.find(prefix) != 0) { + if (!base::StartsWith(profile_dir, prefix, base::CompareCase::SENSITIVE)) { // This happens when creating a TestingProfile in browser tests. return std::string(); } - return profile_dir.substr(prefix.length(), - profile_dir.length() - prefix.length()); + return profile_dir.substr(prefix.length()); } // static
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc index b5e4ac0..ee7029cd 100644 --- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc +++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
@@ -1351,6 +1351,119 @@ host, host, CONTENT_SETTINGS_TYPE_KEYGEN, std::string())); } +TEST_F(HostContentSettingsMapTest, MigrateDomainScopedSettings) { + TestingProfile profile; + HostContentSettingsMap* host_content_settings_map = + HostContentSettingsMapFactory::GetForProfile(&profile); + + // Set old formatted http settings. + GURL http_host("http://example.com/"); + GURL http_host_narrower("http://a.example.com/"); + + // Change default setting to BLOCK. + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_BLOCK); + EXPECT_EQ( + CONTENT_SETTING_BLOCK, + host_content_settings_map->GetContentSetting( + http_host, http_host, CONTENT_SETTINGS_TYPE_COOKIES, std::string())); + // Patterns generated for cookies used to be domain scoped. + host_content_settings_map->SetContentSettingCustomScope( + ContentSettingsPattern::FromURL(http_host), + ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_COOKIES, + std::string(), CONTENT_SETTING_ALLOW); + EXPECT_EQ( + CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + http_host, http_host, CONTENT_SETTINGS_TYPE_COOKIES, std::string())); + // Settings also apply to subdomains. + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + http_host_narrower, http_host_narrower, + CONTENT_SETTINGS_TYPE_COOKIES, std::string())); + + ContentSettingsForOneType settings; + host_content_settings_map->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_COOKIES, std::string(), &settings); + // |host_content_settings_map| contains default setting and a domain scoped + // setting. + EXPECT_EQ(2U, settings.size()); + EXPECT_TRUE(settings[0].primary_pattern.ToString() == "[*.]example.com"); + EXPECT_TRUE(settings[1].primary_pattern.ToString() == "*"); + + // Set old formatted https settings. + GURL https_host("https://example.com/"); + GURL https_host_narrower("https://a.example.com/"); + + // Change default setting to BLOCK. + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_POPUPS, CONTENT_SETTING_BLOCK); + EXPECT_EQ( + CONTENT_SETTING_BLOCK, + host_content_settings_map->GetContentSetting( + https_host, https_host, CONTENT_SETTINGS_TYPE_POPUPS, std::string())); + // Patterns generated for popups used to be domain scoped. + host_content_settings_map->SetContentSettingCustomScope( + ContentSettingsPattern::FromURL(https_host), + ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_POPUPS, + std::string(), CONTENT_SETTING_ALLOW); + EXPECT_EQ( + CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + https_host, https_host, CONTENT_SETTINGS_TYPE_POPUPS, std::string())); + // Settings also apply to subdomains. + EXPECT_EQ(CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + https_host_narrower, https_host_narrower, + CONTENT_SETTINGS_TYPE_POPUPS, std::string())); + + host_content_settings_map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_POPUPS, + std::string(), &settings); + // |host_content_settings_map| contains default setting and a domain scoped + // setting. + EXPECT_EQ(2U, settings.size()); + EXPECT_TRUE(settings[0].primary_pattern.ToString() == + "https://[*.]example.com:443"); + EXPECT_TRUE(settings[1].primary_pattern.ToString() == "*"); + + host_content_settings_map->MigrateDomainScopedSettings(); + + // After migration, settings only affect origins. + EXPECT_EQ( + CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + http_host, http_host, CONTENT_SETTINGS_TYPE_COOKIES, std::string())); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetContentSetting( + http_host_narrower, http_host_narrower, + CONTENT_SETTINGS_TYPE_COOKIES, std::string())); + host_content_settings_map->GetSettingsForOneType( + CONTENT_SETTINGS_TYPE_COOKIES, std::string(), &settings); + // |host_content_settings_map| contains default setting and a origin scoped + // setting. + EXPECT_EQ(2U, settings.size()); + EXPECT_TRUE(settings[0].primary_pattern.ToString() == + "http://example.com:80"); + EXPECT_TRUE(settings[1].primary_pattern.ToString() == "*"); + + EXPECT_EQ( + CONTENT_SETTING_ALLOW, + host_content_settings_map->GetContentSetting( + https_host, https_host, CONTENT_SETTINGS_TYPE_POPUPS, std::string())); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + host_content_settings_map->GetContentSetting( + https_host_narrower, https_host_narrower, + CONTENT_SETTINGS_TYPE_POPUPS, std::string())); + host_content_settings_map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_POPUPS, + std::string(), &settings); + // |host_content_settings_map| contains default setting and a origin scoped + // setting. + EXPECT_EQ(2U, settings.size()); + EXPECT_TRUE(settings[0].primary_pattern.ToString() == + "https://example.com:443"); + EXPECT_TRUE(settings[1].primary_pattern.ToString() == "*"); +} + TEST_F(HostContentSettingsMapTest, InvalidPattern) { // This is a regression test for crbug.com/618529, which fixed a memory leak // when a website setting was set under a URL that mapped to an invalid
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn index 1d58c22f..76669503 100644 --- a/chrome/browser/devtools/BUILD.gn +++ b/chrome/browser/devtools/BUILD.gn
@@ -13,10 +13,8 @@ "//third_party/WebKit/Source/core/inspector:protocol_version", ] blink_protocol = "$root_gen_dir/blink/core/inspector/protocol.json" - browser_protocol = "//content/browser/devtools/browser_protocol.json" inputs = [ blink_protocol, - browser_protocol, ] outputs = [ "$target_gen_dir/devtools_protocol_constants.cc", @@ -26,7 +24,6 @@ args = [ "chrome" ] args += rebase_path(outputs, root_build_dir) args += [ rebase_path(blink_protocol, root_build_dir) ] - args += [ rebase_path(browser_protocol, root_build_dir) ] } # GYP version: chrome/chrome_debugger.gypi:debugger
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 3e683c86..9d61e11 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -6,6 +6,7 @@ #include "build/build_config.h" #include "chrome/browser/devtools/devtools_network_protocol_handler.h" +#include "components/devtools_discovery/devtools_discovery_manager.h" #if !defined(OS_ANDROID) #include "chrome/browser/devtools/devtools_window.h" @@ -13,6 +14,8 @@ #include "content/public/browser/devtools_agent_host.h" #endif // !defined(OS_ANDROID) +using devtools_discovery::DevToolsDiscoveryManager; + ChromeDevToolsManagerDelegate::ChromeDevToolsManagerDelegate() : network_protocol_handler_(new DevToolsNetworkProtocolHandler()) { } @@ -44,6 +47,11 @@ base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand( content::DevToolsAgentHost* agent_host, base::DictionaryValue* command_dict) { + std::unique_ptr<base::DictionaryValue> result = + DevToolsDiscoveryManager::GetInstance()->HandleNewTargetCommand( + command_dict); + if (result) + return result.release(); // Caller takes ownership. return network_protocol_handler_->HandleCommand(agent_host, command_dict); }
diff --git a/chrome/browser/devtools/devtools_protocol_constants.gyp b/chrome/browser/devtools/devtools_protocol_constants.gyp index 6e23876a..44ba629b 100644 --- a/chrome/browser/devtools/devtools_protocol_constants.gyp +++ b/chrome/browser/devtools/devtools_protocol_constants.gyp
@@ -15,13 +15,11 @@ 'action_name': 'devtools_protocol_constants', 'variables': { 'blink_protocol': '<(SHARED_INTERMEDIATE_DIR)/blink/core/inspector/protocol.json', - 'browser_protocol': '../../../content/browser/devtools/browser_protocol.json', 'generator': 'devtools_protocol_constants_generator.py', 'package': 'chrome' }, 'inputs': [ '<(blink_protocol)', - '<(browser_protocol)', '<(generator)', ], 'outputs': [ @@ -35,9 +33,8 @@ '<(SHARED_INTERMEDIATE_DIR)/<(package)/browser/devtools/devtools_protocol_constants.cc', '<(SHARED_INTERMEDIATE_DIR)/<(package)/browser/devtools/devtools_protocol_constants.h', '<(blink_protocol)', - '<(browser_protocol)', ], - 'message': 'Generating DevTools protocol constants from <(blink_protocol) and <(browser_protocol)' + 'message': 'Generating DevTools protocol constants from <(blink_protocol)' } ], },
diff --git a/chrome/browser/devtools/devtools_protocol_constants_generator.py b/chrome/browser/devtools/devtools_protocol_constants_generator.py index 1c84bbd..05c2853 100755 --- a/chrome/browser/devtools/devtools_protocol_constants_generator.py +++ b/chrome/browser/devtools/devtools_protocol_constants_generator.py
@@ -11,7 +11,6 @@ output_cc_path = sys.argv[2] output_h_path = sys.argv[3] blink_protocol_path = sys.argv[4] -browser_protocol_path = sys.argv[5] if len(sys.argv) > 5 else None template_h = string.Template("""\ // Copyright 2013 The Chromium Authors. All rights reserved. @@ -24,8 +23,7 @@ // THIS FILE IS AUTOGENERATED. DO NOT EDIT. // Generated by // chrome/browser/devtools/devtools_protocol_constants_generator.py from -// gen/blink/core/inspector/protocol.json and -// content/browser/devtools/browser_protocol.json +// gen/blink/core/inspector/protocol.json #include <string> @@ -53,8 +51,7 @@ // THIS FILE IS AUTOGENERATED. DO NOT EDIT. // Generated by // chrome/browser/devtools/devtools_protocol_constants_generator.py from -// gen/blink/core/inspector/protocol.json and -// content/browser/devtools/browser_protocol.json +// gen/blink/core/inspector/protocol.json #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -158,11 +155,6 @@ domains = blink_protocol["domains"] -if browser_protocol_path: - browser_protocol_data = open(browser_protocol_path).read() - browser_protocol = json.loads(browser_protocol_data) - domains = domains + browser_protocol["domains"] - namespace_tree = {} for domain in domains:
diff --git a/chrome/browser/devtools/devtools_window_testing.cc b/chrome/browser/devtools/devtools_window_testing.cc index 0cc7f9c..39f585e 100644 --- a/chrome/browser/devtools/devtools_window_testing.cc +++ b/chrome/browser/devtools/devtools_window_testing.cc
@@ -197,9 +197,7 @@ } DevToolsWindow* DevToolsWindowCreationObserver::devtools_window() { - if (devtools_windows_.empty()) - return nullptr; - return devtools_windows_[devtools_windows_.size() - 1]; + return !devtools_windows_.empty() ? devtools_windows_.back() : nullptr; } void DevToolsWindowCreationObserver::CloseAllSync() {
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index ca625e1..fc6b5fb 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -2558,8 +2558,10 @@ EchoReferrerRequestHandler(const net::test_server::HttpRequest& request) { const std::string kReferrerHeader = "Referer"; // SIC - if (request.relative_url.find("/echoreferrer") != 0) + if (!base::StartsWith(request.relative_url, "/echoreferrer", + base::CompareCase::SENSITIVE)) { return std::unique_ptr<net::test_server::HttpResponse>(); + } std::unique_ptr<net::test_server::BasicHttpResponse> response( new net::test_server::BasicHttpResponse());
diff --git a/chrome/browser/download/download_request_limiter_unittest.cc b/chrome/browser/download/download_request_limiter_unittest.cc index 17d79d1b..3583e49 100644 --- a/chrome/browser/download/download_request_limiter_unittest.cc +++ b/chrome/browser/download/download_request_limiter_unittest.cc
@@ -100,7 +100,7 @@ void SetUp(WebContents* web_contents) { PermissionBubbleManager::CreateForWebContents(web_contents); mock_permission_bubble_factory_.reset(new MockPermissionBubbleFactory( - false, PermissionBubbleManager::FromWebContents(web_contents))); + PermissionBubbleManager::FromWebContents(web_contents))); PermissionBubbleManager::FromWebContents(web_contents) ->DisplayPendingRequests(); }
diff --git a/chrome/browser/engagement/site_engagement_score_unittest.cc b/chrome/browser/engagement/site_engagement_score_unittest.cc index 1b1f6e7..1081851 100644 --- a/chrome/browser/engagement/site_engagement_score_unittest.cc +++ b/chrome/browser/engagement/site_engagement_score_unittest.cc
@@ -33,7 +33,10 @@ exploded_reference_time.second = 0; exploded_reference_time.millisecond = 0; - return base::Time::FromLocalExploded(exploded_reference_time); + base::Time out_time; + EXPECT_TRUE( + base::Time::FromLocalExploded(exploded_reference_time, &out_time)); + return out_time; } } // namespace
diff --git a/chrome/browser/engagement/site_engagement_service_unittest.cc b/chrome/browser/engagement/site_engagement_service_unittest.cc index a2a864b9..3c409008 100644 --- a/chrome/browser/engagement/site_engagement_service_unittest.cc +++ b/chrome/browser/engagement/site_engagement_service_unittest.cc
@@ -85,7 +85,10 @@ exploded_reference_time.second = 0; exploded_reference_time.millisecond = 0; - return base::Time::FromLocalExploded(exploded_reference_time); + base::Time out_time; + EXPECT_TRUE( + base::Time::FromLocalExploded(exploded_reference_time, &out_time)); + return out_time; } std::unique_ptr<KeyedService> BuildTestHistoryService(
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc index 0ca4569..b507394 100644 --- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc +++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -134,7 +134,9 @@ const std::string scheme = cookie.IsSecure() ? url::kHttpsScheme : url::kHttpScheme; const std::string host = - domain_key.find('.') != 0 ? domain_key : domain_key.substr(1); + base::StartsWith(domain_key, ".", base::CompareCase::SENSITIVE) + ? domain_key.substr(1) + : domain_key; return GURL(scheme + url::kStandardSchemeSeparator + host + "/"); }
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc index c20ff0fc..c3aa966 100644 --- a/chrome/browser/extensions/api/debugger/debugger_api.cc +++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -109,7 +109,8 @@ int GetButtons() const override; bool Cancel() override; - std::string client_name_; + private: + const base::string16 client_name_; base::Closure dismissed_callback_; DISALLOW_COPY_AND_ASSIGN(ExtensionDevToolsInfoBarDelegate); @@ -119,7 +120,7 @@ const base::Closure& dismissed_callback, const std::string& client_name) : ConfirmInfoBarDelegate(), - client_name_(client_name), + client_name_(base::UTF8ToUTF16(client_name)), dismissed_callback_(dismissed_callback) {} ExtensionDevToolsInfoBarDelegate::~ExtensionDevToolsInfoBarDelegate() { @@ -147,8 +148,7 @@ } base::string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const { - return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, - base::UTF8ToUTF16(client_name_)); + return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, client_name_); } int ExtensionDevToolsInfoBarDelegate::GetButtons() const { @@ -236,7 +236,7 @@ void ExtensionDevToolsInfoBar::InfoBarDismissed() { std::map<ExtensionDevToolsClientHost*, base::Closure> copy = callbacks_; - for (const auto& pair: copy) + for (const auto& pair : copy) pair.second.Run(); }
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc index 98c9956..483482e 100644 --- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc +++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
@@ -182,7 +182,7 @@ const ScopedVector<SpellcheckHunspellDictionary>& dictionaries( service->GetHunspellDictionaries()); - for (const auto& dictionary: dictionaries) { + for (const auto& dictionary : dictionaries) { hunspell_dictionaries_.push_back(dictionary->AsWeakPtr()); if (should_listen) dictionary->AddObserver(this);
diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc index f61dfc7..21131f2 100644 --- a/chrome/browser/extensions/convert_web_app_unittest.cc +++ b/chrome/browser/extensions/convert_web_app_unittest.cc
@@ -80,7 +80,9 @@ exploded.minute = minute; exploded.second = second; exploded.millisecond = millisecond; - return base::Time::FromUTCExploded(exploded); + base::Time out_time; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); + return out_time; } } // namespace
diff --git a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc index a04d053..5544f4cb 100644 --- a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc +++ b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc
@@ -168,7 +168,7 @@ void RemoveAppHandler(const std::string& app_id) override { ExtensionGCMAppHandler::RemoveAppHandler(app_id); - if (!GetGCMDriver()->app_handlers().size()) + if (GetGCMDriver()->app_handlers().empty()) app_handler_count_drop_to_zero_ = true; }
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc index 810b3a53..ad3a68d67 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -317,7 +317,7 @@ // Create a MockPermissionBubbleFactory for the PermissionBubbleManager. mock_permission_bubble_factories_.push_back(base::WrapUnique( - new MockPermissionBubbleFactory(false, permission_bubble_manager))); + new MockPermissionBubbleFactory(permission_bubble_manager))); // Prepare the PermissionBubbleManager to display a mock bubble. permission_bubble_manager->DisplayPendingRequests();
diff --git a/chrome/browser/install_verification/win/module_list_unittest.cc b/chrome/browser/install_verification/win/module_list_unittest.cc index cca65a6a..a9109073 100644 --- a/chrome/browser/install_verification/win/module_list_unittest.cc +++ b/chrome/browser/install_verification/win/module_list_unittest.cc
@@ -44,7 +44,7 @@ ASSERT_GT(module_list->size(), original_list_size); // Unload the module. - release_new_dll.Reset(); + release_new_dll.RunAndReset(); // Reset module_list here. That should typically be the last ref on // msvidc32.dll, so it will be unloaded now.
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index 8e149625..8389c16 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -6,11 +6,6 @@ import("//mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") -gypi_values = exec_script("//build/gypi_to_gn.py", - [ rebase_path("media_router.gypi") ], - "scope", - [ "media_router.gypi" ]) - static_library("router") { deps = [ "//base", @@ -20,18 +15,65 @@ "//content/public/browser", "//url", ] - sources = rebase_path(gypi_values.media_router_sources, - ".", - "//chrome/browser/media/router") + sources = [ + "create_presentation_connection_request.cc", + "create_presentation_connection_request.h", + "issue.cc", + "issue.h", + "issue_manager.cc", + "issue_manager.h", + "issues_observer.cc", + "issues_observer.h", + "media_route.cc", + "media_route.h", + "media_router.h", + "media_router_base.cc", + "media_router_base.h", + "media_router_dialog_controller.cc", + "media_router_dialog_controller.h", + "media_router_factory.cc", + "media_router_factory.h", + "media_router_metrics.cc", + "media_router_metrics.h", + "media_routes_observer.cc", + "media_routes_observer.h", + "media_sink.cc", + "media_sink.h", + "media_sinks_observer.cc", + "media_sinks_observer.h", + "media_source.cc", + "media_source.h", + "media_source_helper.cc", + "media_source_helper.h", + "presentation_media_sinks_observer.cc", + "presentation_media_sinks_observer.h", + "presentation_request.cc", + "presentation_request.h", + "presentation_service_delegate_impl.cc", + "presentation_service_delegate_impl.h", + "presentation_session_messages_observer.cc", + "presentation_session_messages_observer.h", + "render_frame_host_id.h", + "route_request_result.cc", + "route_request_result.h", + ] + if (!is_android) { deps += [ ":mojo_bindings", "//extensions/browser", "//mojo/public/cpp/bindings", ] - sources += rebase_path(gypi_values.media_router_non_android_sources, - ".", - "//chrome/browser/media/router") + sources += [ + "mojo/media_route_provider_util_win.cc", + "mojo/media_route_provider_util_win.h", + "mojo/media_router_mojo_impl.cc", + "mojo/media_router_mojo_impl.h", + "mojo/media_router_mojo_metrics.cc", + "mojo/media_router_mojo_metrics.h", + "mojo/media_router_type_converters.cc", + "mojo/media_router_type_converters.h", + ] } } @@ -48,17 +90,23 @@ "//chrome/test:test_support", "//testing/gmock", ] - sources = rebase_path(gypi_values.media_router_test_support_sources, - ".", - "//chrome/browser/media/router") + sources = [ + "mock_media_router.cc", + "mock_media_router.h", + "mock_screen_availability_listener.cc", + "mock_screen_availability_listener.h", + "test_helper.cc", + "test_helper.h", + ] + if (!is_android) { deps += [ ":mojo_bindings", "//extensions/common", ] - sources += - rebase_path(gypi_values.media_router_non_android_test_support_sources, - ".", - "//chrome/browser/media/router") + sources += [ + "mojo/media_router_mojo_test.cc", + "mojo/media_router_mojo_test.h", + ] } }
diff --git a/chrome/browser/media/router/issue_manager.cc b/chrome/browser/media/router/issue_manager.cc index 37d589f5..d3cb9d4 100644 --- a/chrome/browser/media/router/issue_manager.cc +++ b/chrome/browser/media/router/issue_manager.cc
@@ -6,16 +6,20 @@ #include <algorithm> +#include "content/public/browser/browser_thread.h" + namespace media_router { IssueManager::IssueManager() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } IssueManager::~IssueManager() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } void IssueManager::AddIssue(const Issue& issue) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); for (const Issue& next_issue : issues_) { if (next_issue.Equals(issue)) { return; @@ -26,7 +30,7 @@ } void IssueManager::ClearIssue(const Issue::Id& issue_id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issues_.erase(std::remove_if(issues_.begin(), issues_.end(), [&issue_id](const Issue& issue) { return issue_id == issue.id(); @@ -36,18 +40,18 @@ } size_t IssueManager::GetIssueCount() const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return issues_.size(); } void IssueManager::ClearAllIssues() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issues_.clear(); MaybeUpdateTopIssue(); } void IssueManager::ClearGlobalIssues() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issues_.erase( std::remove_if(issues_.begin(), issues_.end(), [](const Issue& issue) { return issue.is_global(); @@ -56,7 +60,7 @@ } void IssueManager::ClearIssuesWithRouteId(const MediaRoute::Id& route_id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issues_.erase(std::remove_if(issues_.begin(), issues_.end(), [&route_id](const Issue& issue) { return route_id == issue.route_id(); @@ -66,28 +70,29 @@ } void IssueManager::RegisterObserver(IssuesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(observer); DCHECK(!issues_observers_.HasObserver(observer)); issues_observers_.AddObserver(observer); - if (!top_issue_id_.empty()) { - // Find the current top issue and report it to the observer. - for (const auto& next_issue : issues_) { - if (next_issue.id() == top_issue_id_) { - observer->OnIssueUpdated(&next_issue); - } + if (top_issue_id_.empty()) + return; + + // Find the current top issue and report it to the observer. + for (const auto& next_issue : issues_) { + if (next_issue.id() == top_issue_id_) { + observer->OnIssueUpdated(&next_issue); } } } void IssueManager::UnregisterObserver(IssuesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issues_observers_.RemoveObserver(observer); } void IssueManager::MaybeUpdateTopIssue() { - Issue* new_top_issue = nullptr; + const Issue* new_top_issue = nullptr; if (issues_.empty()) { FOR_EACH_OBSERVER(IssuesObserver, issues_observers_, @@ -98,10 +103,10 @@ // Select the first blocking issue in the list of issues. // If there are none, simply select the first issue in the list. new_top_issue = &(issues_.front()); - for (auto it = issues_.begin(); it != issues_.end(); ++it) { + for (const auto& issue : issues_) { // The first blocking issue is of higher priority than the first issue. - if (it->is_blocking()) { - new_top_issue = &(*it); + if (issue.is_blocking()) { + new_top_issue = &issue; break; } }
diff --git a/chrome/browser/media/router/issue_manager.h b/chrome/browser/media/router/issue_manager.h index 51af2de..0c9ae27c 100644 --- a/chrome/browser/media/router/issue_manager.h +++ b/chrome/browser/media/router/issue_manager.h
@@ -12,14 +12,13 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" #include "base/observer_list.h" -#include "base/threading/thread_checker.h" #include "chrome/browser/media/router/issue.h" #include "chrome/browser/media/router/issues_observer.h" namespace media_router { // IssueManager keeps track of current issues related to casting -// connectivity and quality. +// connectivity and quality. It lives on the UI thread. // TODO(apacible): Determine what other issues will be handled here. class IssueManager { public: @@ -72,8 +71,6 @@ // The ID of the current top issue. Issue::Id top_issue_id_; - base::ThreadChecker thread_checker_; - DISALLOW_COPY_AND_ASSIGN(IssueManager); };
diff --git a/chrome/browser/media/router/issue_manager_unittest.cc b/chrome/browser/media/router/issue_manager_unittest.cc index 351cce68..2c67b3c 100644 --- a/chrome/browser/media/router/issue_manager_unittest.cc +++ b/chrome/browser/media/router/issue_manager_unittest.cc
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "chrome/browser/media/router/issue_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" namespace media_router { @@ -25,6 +26,7 @@ IssueManagerUnitTest() {} ~IssueManagerUnitTest() override {} + content::TestBrowserThreadBundle thread_bundle_; IssueManager manager_; private:
diff --git a/chrome/browser/media/router/media_router_base.cc b/chrome/browser/media/router/media_router_base.cc index fd8a50d0..b7b43c37 100644 --- a/chrome/browser/media/router/media_router_base.cc +++ b/chrome/browser/media/router/media_router_base.cc
@@ -10,6 +10,7 @@ #include "base/stl_util.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_thread.h" namespace media_router { @@ -51,7 +52,7 @@ MediaRouterBase::AddPresentationConnectionStateChangedCallback( const MediaRoute::Id& route_id, const content::PresentationConnectionStateChangedCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto* callbacks = presentation_connection_state_callbacks_.get(route_id); if (!callbacks) {
diff --git a/chrome/browser/media/router/media_router_base.h b/chrome/browser/media/router/media_router_base.h index edcfca3..92f29ca 100644 --- a/chrome/browser/media/router/media_router_base.h +++ b/chrome/browser/media/router/media_router_base.h
@@ -12,7 +12,6 @@ #include "base/containers/scoped_ptr_hash_map.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/threading/thread_checker.h" #include "chrome/browser/media/router/media_route.h" #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_routes_observer.h" @@ -64,8 +63,6 @@ std::unique_ptr<PresentationConnectionStateChangedCallbacks>> presentation_connection_state_callbacks_; - base::ThreadChecker thread_checker_; - private: friend class MediaRouterFactory; friend class MediaRouterMojoTest;
diff --git a/chrome/browser/media/router/media_router_dialog_controller.cc b/chrome/browser/media/router/media_router_dialog_controller.cc index 1c89200c..ec8308ce 100644 --- a/chrome/browser/media/router/media_router_dialog_controller.cc +++ b/chrome/browser/media/router/media_router_dialog_controller.cc
@@ -71,12 +71,12 @@ } MediaRouterDialogController::~MediaRouterDialogController() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } bool MediaRouterDialogController::ShowMediaRouterDialogForPresentation( std::unique_ptr<CreatePresentationConnectionRequest> request) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Check if the media router dialog exists for |initiator| and return if so. if (IsShowingMediaRouterDialog()) @@ -89,14 +89,14 @@ // Show the initiator holding the existing media router dialog. ActivateInitiatorWebContents(); - media_router::MediaRouterMetrics::RecordMediaRouterDialogOrigin( + MediaRouterMetrics::RecordMediaRouterDialogOrigin( MediaRouterDialogOpenOrigin::PAGE); return true; } bool MediaRouterDialogController::ShowMediaRouterDialog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Don't create dialog if it already exists. bool dialog_needs_creation = !IsShowingMediaRouterDialog(); @@ -111,7 +111,7 @@ } void MediaRouterDialogController::HideMediaRouterDialog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); CloseMediaRouterDialog(); Reset(); }
diff --git a/chrome/browser/media/router/media_router_dialog_controller.h b/chrome/browser/media/router/media_router_dialog_controller.h index faa3409..bf89f27 100644 --- a/chrome/browser/media/router/media_router_dialog_controller.h +++ b/chrome/browser/media/router/media_router_dialog_controller.h
@@ -9,7 +9,6 @@ #include <string> #include "base/macros.h" -#include "base/threading/thread_checker.h" #include "chrome/browser/media/router/create_presentation_connection_request.h" #include "content/public/browser/web_contents_observer.h" @@ -83,8 +82,6 @@ // Closes the media router dialog if it exists. virtual void CloseMediaRouterDialog() = 0; - base::ThreadChecker thread_checker_; - private: class InitiatorWebContentsObserver;
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc index 9ba4318..33189f86 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/media/router/mojo/media_router_type_converters.h" #include "chrome/browser/media/router/presentation_session_messages_observer.h" #include "chrome/browser/sessions/session_tab_helper.h" +#include "content/public/browser/browser_thread.h" #include "extensions/browser/process_manager.h" #define DVLOG_WITH_INSTANCE(level) \ @@ -89,6 +90,7 @@ availability_(interfaces::MediaRouter::SinkAvailability::UNAVAILABLE), current_wake_reason_(MediaRouteProviderWakeReason::TOTAL_COUNT), weak_factory_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(event_page_tracker_); #if defined(OS_WIN) CanFirewallUseLocalPorts( @@ -98,7 +100,7 @@ } MediaRouterMojoImpl::~MediaRouterMojoImpl() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } // static @@ -116,7 +118,7 @@ void MediaRouterMojoImpl::BindToMojoRequest( mojo::InterfaceRequest<interfaces::MediaRouter> request, const extensions::Extension& extension) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); binding_.reset( new mojo::Binding<interfaces::MediaRouter>(this, std::move(request))); @@ -131,7 +133,7 @@ } void MediaRouterMojoImpl::OnConnectionError() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); media_route_provider_.reset(); binding_.reset(); @@ -152,7 +154,7 @@ interfaces::MediaRouteProviderPtr media_route_provider_ptr, const interfaces::MediaRouter::RegisterMediaRouteProviderCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); #if defined(OS_WIN) // The MRPM may have been upgraded or otherwise reload such that we could be // seeing an MRPM that doesn't know mDNS is enabled, even if we've told a @@ -191,7 +193,7 @@ } void MediaRouterMojoImpl::OnIssue(const interfaces::IssuePtr issue) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG_WITH_INSTANCE(1) << "OnIssue " << issue->title; const Issue& issue_converted = issue.To<Issue>(); issue_manager_.AddIssue(issue_converted); @@ -201,7 +203,7 @@ const mojo::String& media_source, mojo::Array<interfaces::MediaSinkPtr> sinks, mojo::Array<mojo::String> origins) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG_WITH_INSTANCE(1) << "OnSinksReceived"; auto it = sinks_queries_.find(media_source); if (it == sinks_queries_.end()) { @@ -245,7 +247,7 @@ mojo::Array<interfaces::MediaRoutePtr> routes, const mojo::String& media_source, mojo::Array<mojo::String> joinable_route_ids) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG_WITH_INSTANCE(1) << "OnRoutesUpdated"; auto it = routes_queries_.find(media_source); @@ -309,7 +311,7 @@ const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool off_the_record) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!origin.is_valid()) { DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; @@ -337,7 +339,7 @@ const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool off_the_record) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::unique_ptr<RouteRequestResult> error_result; if (!origin.is_valid()) { @@ -372,7 +374,7 @@ const std::vector<MediaRouteResponseCallback>& callbacks, base::TimeDelta timeout, bool off_the_record) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!origin.is_valid()) { DVLOG_WITH_INSTANCE(1) << "Invalid origin: " << origin; @@ -392,7 +394,7 @@ } void MediaRouterMojoImpl::TerminateRoute(const MediaRoute::Id& route_id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG(2) << "TerminateRoute " << route_id; SetWakeReason(MediaRouteProviderWakeReason::TERMINATE_ROUTE); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoTerminateRoute, @@ -400,7 +402,7 @@ } void MediaRouterMojoImpl::DetachRoute(const MediaRoute::Id& route_id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); SetWakeReason(MediaRouteProviderWakeReason::DETACH_ROUTE); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoDetachRoute, @@ -411,7 +413,7 @@ const MediaRoute::Id& route_id, const std::string& message, const SendRouteMessageCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); SetWakeReason(MediaRouteProviderWakeReason::SEND_SESSION_MESSAGE); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoSendSessionMessage, @@ -422,7 +424,7 @@ const MediaRoute::Id& route_id, std::unique_ptr<std::vector<uint8_t>> data, const SendRouteMessageCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); SetWakeReason(MediaRouteProviderWakeReason::SEND_SESSION_BINARY_MESSAGE); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoSendSessionBinaryMessage, @@ -431,12 +433,12 @@ } void MediaRouterMojoImpl::AddIssue(const Issue& issue) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issue_manager_.AddIssue(issue); } void MediaRouterMojoImpl::ClearIssue(const Issue::Id& issue_id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issue_manager_.ClearIssue(issue_id); } @@ -456,7 +458,7 @@ const std::string& search_input, const std::string& domain, const MediaSinkSearchResponseCallback& sink_callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); SetWakeReason(MediaRouteProviderWakeReason::SEARCH_SINKS); RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoSearchSinks, @@ -466,7 +468,7 @@ bool MediaRouterMojoImpl::RegisterMediaSinksObserver( MediaSinksObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Create an observer list for the media source and add |observer| // to it. Fail if |observer| is already registered. @@ -502,7 +504,7 @@ void MediaRouterMojoImpl::UnregisterMediaSinksObserver( MediaSinksObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const MediaSource::Id& source_id = observer->source().id(); auto* sinks_query = sinks_queries_.get(source_id); @@ -534,7 +536,7 @@ void MediaRouterMojoImpl::RegisterMediaRoutesObserver( MediaRoutesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const MediaSource::Id source_id = observer->source_id(); auto* routes_query = routes_queries_.get(source_id); if (!routes_query) { @@ -571,18 +573,18 @@ } void MediaRouterMojoImpl::RegisterIssuesObserver(IssuesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issue_manager_.RegisterObserver(observer); } void MediaRouterMojoImpl::UnregisterIssuesObserver(IssuesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); issue_manager_.UnregisterObserver(observer); } void MediaRouterMojoImpl::RegisterPresentationSessionMessagesObserver( PresentationSessionMessagesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(observer); const MediaRoute::Id& route_id = observer->route_id(); auto* observer_list = messages_observers_.get(route_id); @@ -603,7 +605,7 @@ void MediaRouterMojoImpl::UnregisterPresentationSessionMessagesObserver( PresentationSessionMessagesObserver* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(observer); const MediaRoute::Id& route_id = observer->route_id(); @@ -956,7 +958,7 @@ } void MediaRouterMojoImpl::ExecutePendingRequests() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(media_route_provider_); DCHECK(event_page_tracker_); DCHECK(!media_route_provider_extension_id_.empty());
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.h b/chrome/browser/media/router/mojo/media_router_mojo_impl.h index 3d014bce..075fa1f 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.h +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.h
@@ -45,6 +45,7 @@ // MediaRouter implementation that delegates calls to the component extension. // Also handles the suspension and wakeup of the component extension. +// Lives on the UI thread. class MediaRouterMojoImpl : public MediaRouterBase, public interfaces::MediaRouter { public:
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc index 50d5bc8..c56fba5a 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
@@ -31,6 +31,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/version_info/version_info.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/process_manager.h" #include "extensions/browser/process_manager_factory.h" @@ -134,7 +135,7 @@ }; class SinkResponseCallbackHandler { -public: + public: MOCK_METHOD1(Invoke, void(const std::string& sink_id)); }; @@ -1288,9 +1289,6 @@ void TearDown() override { media_router_.reset(); profile_.reset(); - // Explicitly delete the TestingBrowserProcess before |message_loop_|. - // This allows it to do cleanup before |message_loop_| goes away. - TestingBrowserProcess::DeleteInstance(); } // Constructs bindings so that |media_router_| delegates calls to @@ -1340,6 +1338,7 @@ expected_count); } + content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<MediaRouterMojoImpl> media_router_; RegisterMediaRouteProviderHandler provide_handler_; TestProcessManager* process_manager_; @@ -1349,7 +1348,6 @@ private: std::unique_ptr<TestingProfile> profile_; - base::MessageLoop message_loop_; interfaces::MediaRouteProviderPtr media_route_provider_proxy_; std::unique_ptr<mojo::Binding<interfaces::MediaRouteProvider>> binding_; base::HistogramTester histogram_tester_;
diff --git a/chrome/browser/media/webrtc_event_log_handler.cc b/chrome/browser/media/webrtc_event_log_handler.cc index 0d9bacc..e5f6d49 100644 --- a/chrome/browser/media/webrtc_event_log_handler.cc +++ b/chrome/browser/media/webrtc_event_log_handler.cc
@@ -31,14 +31,13 @@ uint64_t rtc_event_log_id) { static const char kWebRtcEventLogFilePrefix[] = "WebRtcEventLog."; return directory.AppendASCII(kWebRtcEventLogFilePrefix + - base::Int64ToString(rtc_event_log_id)); + base::Uint64ToString(rtc_event_log_id)); } } // namespace WebRtcEventLogHandler::WebRtcEventLogHandler(Profile* profile) : profile_(profile), - is_rtc_event_logging_in_progress_(false), current_rtc_event_log_id_(0) { DCHECK(profile_); thread_checker_.DetachFromThread(); @@ -94,16 +93,13 @@ const base::FilePath& log_directory) { DCHECK(thread_checker_.CalledOnValidThread()); - if (is_rtc_event_logging_in_progress_) { + base::FilePath prefix_path = + GetWebRtcEventLogPrefixPath(log_directory, ++current_rtc_event_log_id_); + if (!host->StartWebRTCEventLog(prefix_path)) { error_callback.Run("RTC event logging already in progress"); return; } - is_rtc_event_logging_in_progress_ = true; - base::FilePath prefix_path = - GetWebRtcEventLogPrefixPath(log_directory, ++current_rtc_event_log_id_); - host->EnableEventLogRecordings(prefix_path); - if (delay.is_zero()) { const bool is_stopped = false, is_manual_stop = false; callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop); @@ -142,13 +138,11 @@ return; } - if (!is_rtc_event_logging_in_progress_) { + if (!host->StopWebRTCEventLog()) { error_callback.Run("No RTC event logging in progress"); return; } - host->DisableEventLogRecordings(); - is_rtc_event_logging_in_progress_ = false; const bool is_stopped = true; callback.Run(prefix_path.AsUTF8Unsafe(), is_stopped, is_manual_stop); }
diff --git a/chrome/browser/media/webrtc_event_log_handler.h b/chrome/browser/media/webrtc_event_log_handler.h index 33eaa5c..985b7ee 100644 --- a/chrome/browser/media/webrtc_event_log_handler.h +++ b/chrome/browser/media/webrtc_event_log_handler.h
@@ -36,8 +36,9 @@ explicit WebRtcEventLogHandler(Profile* profile); - // Starts an RTC event log. The call writes the most recent events to a - // file and then starts logging events for the given |delay|. + // Starts an RTC event log for each peerconnection on the specified |host|. + // The call writes the most recent events to a file and then starts logging + // events for the given |delay|. // If |delay| is zero, the logging will continue until // StopWebRtcEventLogging() // is explicitly invoked. @@ -81,9 +82,6 @@ // The profile associated with our renderer process. Profile* const profile_; - // Must be accessed on the UI thread. - bool is_rtc_event_logging_in_progress_; - // This counter allows saving each log in a separate file. uint64_t current_rtc_event_log_id_;
diff --git a/chrome/browser/media/webrtc_log_uploader_unittest.cc b/chrome/browser/media/webrtc_log_uploader_unittest.cc index 1271bb3..ff257c51 100644 --- a/chrome/browser/media/webrtc_log_uploader_unittest.cc +++ b/chrome/browser/media/webrtc_log_uploader_unittest.cc
@@ -131,8 +131,8 @@ EXPECT_GT(lines.size(), 1u); if (lines.size() < 2) return std::vector<std::string>(); - EXPECT_TRUE(lines[lines.size() - 1].empty()); - if (!lines[lines.size() - 1].empty()) + EXPECT_TRUE(lines.back().empty()); + if (!lines.back().empty()) return std::vector<std::string>(); lines.pop_back(); return lines;
diff --git a/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc b/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc index 00f9d62..389dbaf 100644 --- a/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc +++ b/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc
@@ -169,7 +169,7 @@ base::Unretained(this)))); data_provider()->RefreshData(base::Bind(&ITunesDataProviderTest::StartTest, base::Unretained(this))); - }; + } void OnLibraryChanged() { DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); @@ -402,10 +402,10 @@ DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderUniqueNameTest); }; +// Albums and tracks that aren't the same, but become the same after +// replacing bad characters are not handled properly, but that case should +// never happen in practice. class ITunesDataProviderEscapeTest : public ITunesDataProviderTest { - // Albums and tracks that aren't the same, but become the same after - // replacing bad characters are not handled properly, but that case should - // never happen in practice. public: ITunesDataProviderEscapeTest() {}
diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc index e106960..33c4f54 100644 --- a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc
@@ -100,8 +100,9 @@ double GetVariantTimestamp() const { DCHECK(!folder_dir_.path().empty()); - base::Time variant_epoch = base::Time::FromLocalExploded( - picasa::kPmpVariantTimeEpoch); + base::Time variant_epoch; + EXPECT_TRUE(base::Time::FromLocalExploded(picasa::kPmpVariantTimeEpoch, + &variant_epoch)); int64_t microseconds_since_epoch = (folder_info_.timestamp - variant_epoch).InMicroseconds(); @@ -387,10 +388,12 @@ TEST_F(PicasaFileUtilTest, DateFormat) { base::Time::Exploded exploded_shortmonth = { 2013, 4, 0, 16, 0, 0, 0, 0 }; - base::Time shortmonth = base::Time::FromLocalExploded(exploded_shortmonth); + base::Time shortmonth; + EXPECT_TRUE(base::Time::FromLocalExploded(exploded_shortmonth, &shortmonth)); base::Time::Exploded exploded_shortday = { 2013, 11, 0, 3, 0, 0, 0, 0 }; - base::Time shortday = base::Time::FromLocalExploded(exploded_shortday); + base::Time shortday; + EXPECT_TRUE(base::Time::FromLocalExploded(exploded_shortday, &shortday)); EXPECT_EQ("2013-04-16", DateToPathString(shortmonth)); EXPECT_EQ("2013-11-03", DateToPathString(shortday)); @@ -400,7 +403,8 @@ ScopedVector<TestFolder> test_folders; std::vector<std::string> expected_names; - base::Time test_date = base::Time::FromLocalExploded(test_date_exploded); + base::Time test_date; + EXPECT_TRUE(base::Time::FromLocalExploded(test_date_exploded, &test_date)); base::Time test_date_2 = test_date - base::TimeDelta::FromDays(1); std::string test_date_string = DateToPathString(test_date); @@ -472,7 +476,8 @@ TEST_F(PicasaFileUtilTest, FolderContentsTrivial) { ScopedVector<TestFolder> test_folders; - base::Time test_date = base::Time::FromLocalExploded(test_date_exploded); + base::Time test_date; + EXPECT_TRUE(base::Time::FromLocalExploded(test_date_exploded, &test_date)); test_folders.push_back( new TestFolder("folder-1-empty", test_date, "uid-empty", 0, 0)); @@ -489,7 +494,8 @@ TEST_F(PicasaFileUtilTest, FolderWithManyFiles) { ScopedVector<TestFolder> test_folders; - base::Time test_date = base::Time::FromLocalExploded(test_date_exploded); + base::Time test_date; + EXPECT_TRUE(base::Time::FromLocalExploded(test_date_exploded, &test_date)); test_folders.push_back( new TestFolder("folder-many-files", test_date, "uid-both", 50, 50)); @@ -500,7 +506,8 @@ TEST_F(PicasaFileUtilTest, ManyFolders) { ScopedVector<TestFolder> test_folders; - base::Time test_date = base::Time::FromLocalExploded(test_date_exploded); + base::Time test_date; + EXPECT_TRUE(base::Time::FromLocalExploded(test_date_exploded, &test_date)); for (unsigned int i = 0; i < 50; ++i) { base::Time date = test_date - base::TimeDelta::FromDays(i); @@ -517,7 +524,8 @@ TEST_F(PicasaFileUtilTest, AlbumExistence) { ScopedVector<TestFolder> test_folders; - base::Time test_date = base::Time::FromLocalExploded(test_date_exploded); + base::Time test_date; + EXPECT_TRUE(base::Time::FromLocalExploded(test_date_exploded, &test_date)); std::vector<AlbumInfo> albums; AlbumInfo info; @@ -539,7 +547,8 @@ TEST_F(PicasaFileUtilTest, AlbumContents) { ScopedVector<TestFolder> test_folders; - base::Time test_date = base::Time::FromLocalExploded(test_date_exploded); + base::Time test_date; + EXPECT_TRUE(base::Time::FromLocalExploded(test_date_exploded, &test_date)); std::vector<AlbumInfo> albums; AlbumInfo info;
diff --git a/chrome/browser/net/firefox_proxy_settings.cc b/chrome/browser/net/firefox_proxy_settings.cc index 15fb3a7..59f217d2 100644 --- a/chrome/browser/net/firefox_proxy_settings.cc +++ b/chrome/browser/net/firefox_proxy_settings.cc
@@ -113,8 +113,7 @@ } // Value could be a string. - if (value.size() >= 2U && - value[0] == '"' && value[value.size() - 1] == '"') { + if (value.size() >= 2U && value[0] == '"' && value.back() == '"') { value = value.substr(1, value.size() - 2); // ValueString only accept valid UTF-8. Simply ignore that entry if it is // not UTF-8.
diff --git a/chrome/browser/ntp_snippets/OWNERS b/chrome/browser/ntp_snippets/OWNERS index 16d46010..c7f9cc3f 100644 --- a/chrome/browser/ntp_snippets/OWNERS +++ b/chrome/browser/ntp_snippets/OWNERS
@@ -1,2 +1 @@ -noyau@chromium.org -bauerb@chromium.org +file://components/ntp_snippets/OWNERS
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc index b9216e7..ab7bfc0 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc +++ b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc
@@ -80,9 +80,9 @@ // TODO(mvanouwerkerk): Move the enable logic into the service once we start // observing pref changes. - bool enabled = profile->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled); + bool enabled = false; #if defined(OS_ANDROID) - enabled = enabled && + enabled = profile->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled) && base::FeatureList::IsEnabled(chrome::android::kNTPSnippetsFeature); #endif // OS_ANDROID
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc index 4211e7f..d892a71a 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc +++ b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
@@ -143,6 +143,22 @@ EXPECT_TRUE(result); } +void WriteHTMLAttributes(const PasswordForm& form, base::Pickle* pickle) { + pickle->WriteInt(form.scheme); + pickle->WriteString(form.origin.spec()); + pickle->WriteString(form.action.spec()); + pickle->WriteString16(form.username_element); + pickle->WriteString16(form.username_value); + pickle->WriteString16(form.password_element); + pickle->WriteString16(form.password_value); + pickle->WriteString16(form.submit_element); +} + +void WritePreferenceMetadata(const PasswordForm& form, base::Pickle* pickle) { + pickle->WriteBool(form.preferred); + pickle->WriteBool(form.blacklisted_by_user); +} + } // anonymous namespace // Obscure magic: we need to declare storage for this constant because we use it @@ -1139,9 +1155,12 @@ base::Pickle* pickle, int stored_version, int effective_version); + // If |size_32| is true, stores the number of forms in the pickle as a 32bit + // uint, otherwise as 64 bit size_t. void CreateVersion0Pickle(bool size_32, const PasswordForm& form, base::Pickle* pickle); + void CheckVersion8Pickle(); void CheckVersion7Pickle(); // As explained in http://crbug.com/494229#c11, version 6 added a new optional // field to version 5. This field became required in version 7. Depending on @@ -1153,16 +1172,6 @@ void CheckVersion2Pickle(); void CheckVersion1Pickle(); void CheckVersion0Pickle(bool size_32, PasswordForm::Scheme scheme); - - private: - // Creates a Pickle from |form|. If |size_32| is true, stores the number of - // forms in the pickle as a 32bit uint, otherwise as 64 bit size_t. The latter - // should be the case for versions > 0. If |date_created_internal| is true, - // stores |date_created| as base::Time's internal value, otherwise as time_t. - void CreatePickle(bool size_32, - bool date_created_internal, - const PasswordForm& form, - base::Pickle* pickle); }; void NativeBackendKWalletPickleTest::CreateVersion1PlusPickle( @@ -1171,7 +1180,11 @@ int stored_version, int effective_version) { pickle->WriteInt(stored_version); - CreatePickle(false, true, form, pickle); + pickle->WriteUInt64(1); // Number of forms in the pickle. + WriteHTMLAttributes(form, pickle); + pickle->WriteBool(form.ssl_valid); + WritePreferenceMetadata(form, pickle); + pickle->WriteInt64(form.date_created.ToInternalValue()); if (effective_version < 2) return; pickle->WriteInt(form.type); @@ -1196,32 +1209,31 @@ const PasswordForm& form, base::Pickle* pickle) { pickle->WriteInt(0); - CreatePickle(size_32, false, form, pickle); + // Write the number of forms in the pickle in the appopriate bit size. + if (size_32) + pickle->WriteUInt32(1); + else + pickle->WriteUInt64(1); + WriteHTMLAttributes(form, pickle); + pickle->WriteBool(form.ssl_valid); + WritePreferenceMetadata(form, pickle); + // Old way to store the date. + pickle->WriteInt64(form.date_created.ToTimeT()); } -void NativeBackendKWalletPickleTest::CreatePickle(bool size_32, - bool date_created_internal, - const PasswordForm& form, - base::Pickle* pickle) { - if (size_32) - pickle->WriteUInt32(1); // Size of form list. 32 bits. - else - pickle->WriteUInt64(1); // Size of form list. 64 bits. - pickle->WriteInt(form.scheme); - pickle->WriteString(form.origin.spec()); - pickle->WriteString(form.action.spec()); - pickle->WriteString16(form.username_element); - pickle->WriteString16(form.username_value); - pickle->WriteString16(form.password_element); - pickle->WriteString16(form.password_value); - pickle->WriteString16(form.submit_element); - pickle->WriteBool(form.ssl_valid); - pickle->WriteBool(form.preferred); - pickle->WriteBool(form.blacklisted_by_user); - if (date_created_internal) - pickle->WriteInt64(form.date_created.ToInternalValue()); - else - pickle->WriteInt64(form.date_created.ToTimeT()); +void NativeBackendKWalletPickleTest::CheckVersion8Pickle() { + base::Pickle pickle; + PasswordForm default_values; + PasswordForm form = form_google_; + + // Version 8 pickles deserialize with their own 'skip_zero_click' value. + form.skip_zero_click = false; + CreateVersion1PlusPickle(form, &pickle, 8, 8); + ScopedVector<PasswordForm> form_list = + NativeBackendKWalletStub::DeserializeValue(form.signon_realm, pickle); + EXPECT_EQ(1u, form_list.size()); + if (form_list.size() > 0) + CheckPasswordForm(form, *form_list[0], true); } void NativeBackendKWalletPickleTest::CheckVersion7Pickle() { @@ -1238,15 +1250,6 @@ form.skip_zero_click = true; if (form_list.size() > 0) CheckPasswordForm(form, *form_list[0], true); - - // Version 8 pickles deserialize with their own 'skip_zero_click' value. - form.skip_zero_click = false; - CreateVersion1PlusPickle(form, &pickle, 8, 8); - form_list = - NativeBackendKWalletStub::DeserializeValue(form.signon_realm, pickle); - EXPECT_EQ(1u, form_list.size()); - if (form_list.size() > 0) - CheckPasswordForm(form, *form_list[0], true); } void NativeBackendKWalletPickleTest::CheckVersion6Pickle( @@ -1392,3 +1395,11 @@ CheckVersion6Pickle(false); CheckVersion6Pickle(true); } + +TEST_F(NativeBackendKWalletPickleTest, CheckVersion7Pickle) { + CheckVersion7Pickle(); +} + +TEST_F(NativeBackendKWalletPickleTest, CheckVersion8Pickle) { + CheckVersion8Pickle(); +}
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc index 63dca04..fb82842 100644 --- a/chrome/browser/password_manager/password_store_mac.cc +++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -279,8 +279,7 @@ } // Converts a Keychain time string to a Time object, returning true if -// time_string_bytes was parsable. If the return value is false, the value of -// |time| is unchanged. +// time_string_bytes was parsable. bool TimeFromKeychainTimeString(const char* time_string_bytes, unsigned int byte_length, base::Time* time) { @@ -298,11 +297,7 @@ &exploded_time.minute, &exploded_time.second); free(time_string); - if (assignments == 6) { - *time = base::Time::FromUTCExploded(exploded_time); - return true; - } - return false; + return assignments == 6 && base::Time::FromUTCExploded(exploded_time, time); } // Returns the PasswordForm Scheme corresponding to |auth_type|.
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc index cc23104..b0cc46f 100644 --- a/chrome/browser/password_manager/password_store_mac_unittest.cc +++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -68,8 +68,7 @@ *target_form_ptr = *arg0[0]; } -void Noop() { -} +void Noop() {} class MockPasswordStoreConsumer : public PasswordStoreConsumer { public: @@ -108,7 +107,7 @@ // Macro to simplify calling CheckFormsAgainstExpectations with a useful label. #define CHECK_FORMS(forms, expectations, i) \ - CheckFormsAgainstExpectations(forms, expectations, #forms, i) + CheckFormsAgainstExpectations(forms, expectations, #forms, i) // Ensures that the data in |forms| match |expectations|, causing test failures // for any discrepencies. @@ -118,7 +117,8 @@ const std::vector<PasswordForm*>& forms, const std::vector<PasswordFormData*>& expectations, - const char* forms_label, unsigned int test_number) { + const char* forms_label, + unsigned int test_number) { EXPECT_EQ(expectations.size(), forms.size()) << forms_label << " in test " << test_number; if (expectations.size() != forms.size()) @@ -255,115 +255,43 @@ void SetUp() override { MockAppleKeychain::KeychainTestData test_data[] = { // Basic HTML form. - {kSecAuthenticationTypeHTMLForm, - "some.domain.com", - kSecProtocolTypeHTTP, - NULL, - 0, - NULL, - "20020601171500Z", - "joe_user", - "sekrit", - false}, + {kSecAuthenticationTypeHTMLForm, "some.domain.com", + kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", "joe_user", + "sekrit", false}, // HTML form with path. - {kSecAuthenticationTypeHTMLForm, - "some.domain.com", - kSecProtocolTypeHTTP, - "/insecure.html", - 0, - NULL, - "19991231235959Z", - "joe_user", - "sekrit", - false}, + {kSecAuthenticationTypeHTMLForm, "some.domain.com", + kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "19991231235959Z", + "joe_user", "sekrit", false}, // Secure HTML form with path. - {kSecAuthenticationTypeHTMLForm, - "some.domain.com", - kSecProtocolTypeHTTPS, - "/secure.html", - 0, - NULL, - "20100908070605Z", - "secure_user", - "password", - false}, + {kSecAuthenticationTypeHTMLForm, "some.domain.com", + kSecProtocolTypeHTTPS, "/secure.html", 0, NULL, "20100908070605Z", + "secure_user", "password", false}, // True negative item. - {kSecAuthenticationTypeHTMLForm, - "dont.remember.com", - kSecProtocolTypeHTTP, - NULL, - 0, - NULL, - "20000101000000Z", - "", - "", - true}, + {kSecAuthenticationTypeHTMLForm, "dont.remember.com", + kSecProtocolTypeHTTP, NULL, 0, NULL, "20000101000000Z", "", "", true}, // De-facto negative item, type one. - {kSecAuthenticationTypeHTMLForm, - "dont.remember.com", - kSecProtocolTypeHTTP, - NULL, - 0, - NULL, - "20000101000000Z", - "Password Not Stored", - "", - false}, + {kSecAuthenticationTypeHTMLForm, "dont.remember.com", + kSecProtocolTypeHTTP, NULL, 0, NULL, "20000101000000Z", + "Password Not Stored", "", false}, // De-facto negative item, type two. - {kSecAuthenticationTypeHTMLForm, - "dont.remember.com", - kSecProtocolTypeHTTPS, - NULL, - 0, - NULL, - "20000101000000Z", - "Password Not Stored", - " ", - false}, + {kSecAuthenticationTypeHTMLForm, "dont.remember.com", + kSecProtocolTypeHTTPS, NULL, 0, NULL, "20000101000000Z", + "Password Not Stored", " ", false}, // HTTP auth basic, with port and path. - {kSecAuthenticationTypeHTTPBasic, - "some.domain.com", - kSecProtocolTypeHTTP, - "/insecure.html", - 4567, - "low_security", - "19980330100000Z", - "basic_auth_user", - "basic", - false}, + {kSecAuthenticationTypeHTTPBasic, "some.domain.com", + kSecProtocolTypeHTTP, "/insecure.html", 4567, "low_security", + "19980330100000Z", "basic_auth_user", "basic", false}, // HTTP auth digest, secure. - {kSecAuthenticationTypeHTTPDigest, - "some.domain.com", - kSecProtocolTypeHTTPS, - NULL, - 0, - "high_security", - "19980330100000Z", - "digest_auth_user", - "digest", - false}, + {kSecAuthenticationTypeHTTPDigest, "some.domain.com", + kSecProtocolTypeHTTPS, NULL, 0, "high_security", "19980330100000Z", + "digest_auth_user", "digest", false}, // An FTP password with an invalid date, for edge-case testing. - {kSecAuthenticationTypeDefault, - "a.server.com", - kSecProtocolTypeFTP, - NULL, - 0, - NULL, - "20010203040", - "abc", - "123", - false}, + {kSecAuthenticationTypeDefault, "a.server.com", kSecProtocolTypeFTP, + NULL, 0, NULL, "20010203040", "abc", "123", false}, // Password for an Android application. - {kSecAuthenticationTypeHTMLForm, - "android://hash@com.domain.some/", - kSecProtocolTypeHTTPS, - "", - 0, - NULL, - "20150515141312Z", - "joe_user", - "secret", - false}, + {kSecAuthenticationTypeHTMLForm, "android://hash@com.domain.some/", + kSecProtocolTypeHTTPS, "", 0, NULL, "20150515141312Z", "joe_user", + "secret", false}, }; keychain_ = new MockAppleKeychain(); @@ -417,41 +345,37 @@ } TestExpectations; TestExpectations expected[] = { - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", L"joe_user", L"sekrit", false, - 2002, 6, 1, 17, 15, 0 }, - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/insecure.html", L"joe_user", L"sekrit", false, - 1999, 12, 31, 23, 59, 59 }, - { PasswordForm::SCHEME_HTML, "https://some.domain.com/", - "https://some.domain.com/secure.html", L"secure_user", L"password", true, - 2010, 9, 8, 7, 6, 5 }, - { PasswordForm::SCHEME_HTML, "http://dont.remember.com/", - "http://dont.remember.com/", NULL, NULL, false, - 2000, 1, 1, 0, 0, 0 }, - { PasswordForm::SCHEME_HTML, "http://dont.remember.com/", - "http://dont.remember.com/", NULL, NULL, false, - 2000, 1, 1, 0, 0, 0 }, - { PasswordForm::SCHEME_HTML, "https://dont.remember.com/", - "https://dont.remember.com/", NULL, NULL, true, - 2000, 1, 1, 0, 0, 0 }, - { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", - "http://some.domain.com:4567/insecure.html", L"basic_auth_user", L"basic", - false, 1998, 03, 30, 10, 00, 00 }, - { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", - "https://some.domain.com/", L"digest_auth_user", L"digest", true, - 1998, 3, 30, 10, 0, 0 }, - // This one gives us an invalid date, which we will treat as a "NULL" date - // which is 1601. - { PasswordForm::SCHEME_OTHER, "http://a.server.com/", - "http://a.server.com/", L"abc", L"123", false, - 1601, 1, 1, 0, 0, 0 }, - { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - "", L"joe_user", L"secret", true, - 2015, 5, 15, 14, 13, 12 }, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/", L"joe_user", L"sekrit", false, 2002, 6, 1, 17, + 15, 0}, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/insecure.html", L"joe_user", L"sekrit", false, + 1999, 12, 31, 23, 59, 59}, + {PasswordForm::SCHEME_HTML, "https://some.domain.com/", + "https://some.domain.com/secure.html", L"secure_user", L"password", true, + 2010, 9, 8, 7, 6, 5}, + {PasswordForm::SCHEME_HTML, "http://dont.remember.com/", + "http://dont.remember.com/", NULL, NULL, false, 2000, 1, 1, 0, 0, 0}, + {PasswordForm::SCHEME_HTML, "http://dont.remember.com/", + "http://dont.remember.com/", NULL, NULL, false, 2000, 1, 1, 0, 0, 0}, + {PasswordForm::SCHEME_HTML, "https://dont.remember.com/", + "https://dont.remember.com/", NULL, NULL, true, 2000, 1, 1, 0, 0, 0}, + {PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", + "http://some.domain.com:4567/insecure.html", L"basic_auth_user", + L"basic", false, 1998, 03, 30, 10, 00, 00}, + {PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", + "https://some.domain.com/", L"digest_auth_user", L"digest", true, 1998, + 3, 30, 10, 0, 0}, + // This one gives us an invalid date, which we will treat as a "NULL" date + // which is 1601. + {PasswordForm::SCHEME_OTHER, "http://a.server.com/", + "http://a.server.com/", L"abc", L"123", false, 1601, 1, 1, 0, 0, 0}, + {PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", "", + L"joe_user", L"secret", true, 2015, 5, 15, 14, 13, 12}, }; for (unsigned int i = 0; i < arraysize(expected); ++i) { + SCOPED_TRACE(testing::Message("In iteration ") << i); // Create our fake KeychainItemRef; see MockAppleKeychain docs. SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(i + 1); @@ -459,36 +383,27 @@ bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( *keychain_, keychain_item, &form, true); - EXPECT_TRUE(parsed) << "In iteration " << i; + EXPECT_TRUE(parsed); - EXPECT_EQ(expected[i].scheme, form.scheme) << "In iteration " << i; - EXPECT_EQ(GURL(expected[i].origin), form.origin) << "In iteration " << i; - EXPECT_EQ(expected[i].ssl_valid, form.ssl_valid) << "In iteration " << i; - EXPECT_EQ(std::string(expected[i].signon_realm), form.signon_realm) - << "In iteration " << i; + EXPECT_EQ(expected[i].scheme, form.scheme); + EXPECT_EQ(GURL(expected[i].origin), form.origin); + EXPECT_EQ(expected[i].ssl_valid, form.ssl_valid); + EXPECT_EQ(std::string(expected[i].signon_realm), form.signon_realm); if (expected[i].username) { - EXPECT_EQ(WideToUTF16(expected[i].username), form.username_value) - << "In iteration " << i; - EXPECT_EQ(WideToUTF16(expected[i].password), form.password_value) - << "In iteration " << i; - EXPECT_FALSE(form.blacklisted_by_user) << "In iteration " << i; + EXPECT_EQ(WideToUTF16(expected[i].username), form.username_value); + EXPECT_EQ(WideToUTF16(expected[i].password), form.password_value); + EXPECT_FALSE(form.blacklisted_by_user); } else { - EXPECT_TRUE(form.blacklisted_by_user) << "In iteration " << i; + EXPECT_TRUE(form.blacklisted_by_user); } base::Time::Exploded exploded_time; form.date_created.UTCExplode(&exploded_time); - EXPECT_EQ(expected[i].creation_year, exploded_time.year) - << "In iteration " << i; - EXPECT_EQ(expected[i].creation_month, exploded_time.month) - << "In iteration " << i; - EXPECT_EQ(expected[i].creation_day, exploded_time.day_of_month) - << "In iteration " << i; - EXPECT_EQ(expected[i].creation_hour, exploded_time.hour) - << "In iteration " << i; - EXPECT_EQ(expected[i].creation_minute, exploded_time.minute) - << "In iteration " << i; - EXPECT_EQ(expected[i].creation_second, exploded_time.second) - << "In iteration " << i; + EXPECT_EQ(expected[i].creation_year, exploded_time.year); + EXPECT_EQ(expected[i].creation_month, exploded_time.month); + EXPECT_EQ(expected[i].creation_day, exploded_time.day_of_month); + EXPECT_EQ(expected[i].creation_hour, exploded_time.hour); + EXPECT_EQ(expected[i].creation_minute, exploded_time.minute); + EXPECT_EQ(expected[i].creation_second, exploded_time.second); } { @@ -508,64 +423,76 @@ const size_t expected_merge_matches; }; // Most fields are left blank because we don't care about them for searching. - /* clang-format off */ TestDataAndExpectation test_data[] = { - // An HTML form we've seen. - { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, false, 0 }, - 2, 2 }, - { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - NULL, NULL, NULL, NULL, NULL, L"wrong_user", NULL, false, false, 0 }, - 2, 0 }, - // An HTML form we haven't seen - { { PasswordForm::SCHEME_HTML, "http://www.unseendomain.com/", - NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, false, 0 }, - 0, 0 }, - // Basic auth that should match. - { { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", + // An HTML form we've seen. + {{PasswordForm::SCHEME_HTML, "http://some.domain.com/", NULL, NULL, NULL, + NULL, NULL, L"joe_user", NULL, false, false, 0}, + 2, + 2}, + {{PasswordForm::SCHEME_HTML, "http://some.domain.com/", NULL, NULL, NULL, + NULL, NULL, L"wrong_user", NULL, false, false, 0}, + 2, + 0}, + // An HTML form we haven't seen + {{PasswordForm::SCHEME_HTML, "http://www.unseendomain.com/", NULL, NULL, + NULL, NULL, NULL, L"joe_user", NULL, false, false, 0}, + 0, + 0}, + // Basic auth that should match. + {{PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", NULL, NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, false, false, - 0 }, - 1, 1 }, - // Basic auth with the wrong port. - { { PasswordForm::SCHEME_BASIC, "http://some.domain.com:1111/low_security", + 0}, + 1, + 1}, + // Basic auth with the wrong port. + {{PasswordForm::SCHEME_BASIC, "http://some.domain.com:1111/low_security", NULL, NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, false, false, - 0 }, - 0, 0 }, - // Digest auth we've saved under https, visited with http. - { { PasswordForm::SCHEME_DIGEST, "http://some.domain.com/high_security", + 0}, + 0, + 0}, + // Digest auth we've saved under https, visited with http. + {{PasswordForm::SCHEME_DIGEST, "http://some.domain.com/high_security", NULL, NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, false, false, - 0 }, - 0, 0 }, - // Digest auth that should match. - { { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", - NULL, NULL, NULL, NULL, NULL, L"wrong_user", NULL, false, true, 0 }, - 1, 0 }, - // Digest auth with the wrong domain. - { { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/other_domain", + 0}, + 0, + 0}, + // Digest auth that should match. + {{PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", + NULL, NULL, NULL, NULL, NULL, L"wrong_user", NULL, false, true, 0}, + 1, + 0}, + // Digest auth with the wrong domain. + {{PasswordForm::SCHEME_DIGEST, "https://some.domain.com/other_domain", NULL, NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, false, true, - 0 }, - 0, 0 }, - // Android credentials (both legacy ones with origin, and without). - { { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", + 0}, + 0, + 0}, + // Android credentials (both legacy ones with origin, and without). + {{PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", "android://hash@com.domain.some/", NULL, NULL, NULL, NULL, L"joe_user", - NULL, false, true, 0 }, - 1, 1 }, - { { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, true, 0 }, - 1, 1 }, - // Federated logins do not have a corresponding Keychain entry, and should - // not match the username/password stored for the same application. Note - // that it will match for filling, however, because that part does not know - // that it is a federated login. - { { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - NULL, NULL, NULL, NULL, NULL, L"joe_user", - password_manager::kTestingFederatedLoginMarker, false, true, 0 }, - 1, 0 }, - /// Garbage forms should have no matches. - { { PasswordForm::SCHEME_HTML, "foo/bar/baz", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 0, 0 }, + NULL, false, true, 0}, + 1, + 1}, + {{PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", NULL, + NULL, NULL, NULL, NULL, L"joe_user", NULL, false, true, 0}, + 1, + 1}, + // Federated logins do not have a corresponding Keychain entry, and should + // not match the username/password stored for the same application. Note + // that it will match for filling, however, because that part does not + // know + // that it is a federated login. + {{PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", NULL, + NULL, NULL, NULL, NULL, L"joe_user", + password_manager::kTestingFederatedLoginMarker, false, true, 0}, + 1, + 0}, + /// Garbage forms should have no matches. + {{PasswordForm::SCHEME_HTML, "foo/bar/baz", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, false, false, 0}, + 0, + 0}, }; - /* clang-format on */ MacKeychainPasswordFormAdapter keychain_adapter(keychain_); MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); @@ -637,15 +564,15 @@ MacKeychainPasswordFormAdapter keychain_adapter(keychain_); PasswordFormData base_form_data[] = { - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/insecure.html", - NULL, NULL, NULL, NULL, L"joe_user", NULL, true, false, 0 }, - { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", - "http://some.domain.com:4567/insecure.html", - NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, true, false, 0 }, - { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", - "https://some.domain.com", - NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, true, true, 0 }, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, + L"joe_user", NULL, true, false, 0}, + {PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security", + "http://some.domain.com:4567/insecure.html", NULL, NULL, NULL, NULL, + L"basic_auth_user", NULL, true, false, 0}, + {PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security", + "https://some.domain.com", NULL, NULL, NULL, NULL, L"digest_auth_user", + NULL, true, true, 0}, }; for (unsigned int i = 0; i < arraysize(base_form_data); ++i) { @@ -681,10 +608,10 @@ } for (unsigned int j = 0; j < modified_forms.size(); ++j) { - bool match = keychain_adapter.HasPasswordExactlyMatchingForm( - *modified_forms[j]); - EXPECT_FALSE(match) << "In modified version " << j - << " of base form " << i; + bool match = + keychain_adapter.HasPasswordExactlyMatchingForm(*modified_forms[j]); + EXPECT_FALSE(match) << "In modified version " << j << " of base form " + << i; } } } @@ -694,41 +621,46 @@ PasswordFormData data; bool should_succeed; }; - /* clang-format off */ TestDataAndExpectation test_data[] = { - // Test a variety of scheme/port/protocol/path variations. - { { PasswordForm::SCHEME_HTML, "http://web.site.com/", + // Test a variety of scheme/port/protocol/path variations. + {{PasswordForm::SCHEME_HTML, "http://web.site.com/", "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, - L"anonymous", L"knock-knock", false, false, 0 }, true }, - { { PasswordForm::SCHEME_HTML, "https://web.site.com/", - "https://web.site.com/", NULL, NULL, NULL, NULL, - L"admin", L"p4ssw0rd", false, false, 0 }, true }, - { { PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm", - "http://a.site.com:2222/", NULL, NULL, NULL, NULL, - L"username", L"password", false, false, 0 }, true }, - { { PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm", + L"anonymous", L"knock-knock", false, false, 0}, + true}, + {{PasswordForm::SCHEME_HTML, "https://web.site.com/", + "https://web.site.com/", NULL, NULL, NULL, NULL, L"admin", L"p4ssw0rd", + false, false, 0}, + true}, + {{PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm", + "http://a.site.com:2222/", NULL, NULL, NULL, NULL, L"username", + L"password", false, false, 0}, + true}, + {{PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm", "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL, - L"testname", L"testpass", false, false, 0 }, true }, - // Test that Android credentials can be stored. Also check the legacy form - // when |origin| was still filled with the Android URI (and not left empty). - { { PasswordForm::SCHEME_HTML, "android://hash@com.example.alpha/", - "", NULL, NULL, NULL, NULL, - L"joe_user", L"password", false, true, 0 }, true }, - { { PasswordForm::SCHEME_HTML, "android://hash@com.example.beta/", + L"testname", L"testpass", false, false, 0}, + true}, + // Test that Android credentials can be stored. Also check the legacy form + // when |origin| was still filled with the Android URI (and not left + // empty). + {{PasswordForm::SCHEME_HTML, "android://hash@com.example.alpha/", "", + NULL, NULL, NULL, NULL, L"joe_user", L"password", false, true, 0}, + true}, + {{PasswordForm::SCHEME_HTML, "android://hash@com.example.beta/", "android://hash@com.example.beta/", NULL, NULL, NULL, NULL, - L"jane_user", L"password2", false, true, 0 }, true }, - // Make sure that garbage forms are rejected. - { { PasswordForm::SCHEME_HTML, "gobbledygook", - "gobbledygook", NULL, NULL, NULL, NULL, - L"anonymous", L"knock-knock", false, false, 0 }, false }, - // Test that failing to update a duplicate (forced using the magic failure - // password; see MockAppleKeychain::ItemModifyAttributesAndData) is - // reported. - { { PasswordForm::SCHEME_HTML, "http://some.domain.com", + L"jane_user", L"password2", false, true, 0}, + true}, + // Make sure that garbage forms are rejected. + {{PasswordForm::SCHEME_HTML, "gobbledygook", "gobbledygook", NULL, NULL, + NULL, NULL, L"anonymous", L"knock-knock", false, false, 0}, + false}, + // Test that failing to update a duplicate (forced using the magic failure + // password; see MockAppleKeychain::ItemModifyAttributesAndData) is + // reported. + {{PasswordForm::SCHEME_HTML, "http://some.domain.com", "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, - L"joe_user", L"fail_me", false, false, 0 }, false }, + L"joe_user", L"fail_me", false, false, 0}, + false}, }; - /* clang-format on */ MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); owned_keychain_adapter.SetFindsOnlyOwnedItems(true); @@ -739,10 +671,10 @@ bool add_succeeded = owned_keychain_adapter.AddPassword(*in_form); EXPECT_EQ(test_data[i].should_succeed, add_succeeded); if (add_succeeded) { - EXPECT_TRUE(owned_keychain_adapter.HasPasswordsMergeableWithForm( - *in_form)); - EXPECT_TRUE(owned_keychain_adapter.HasPasswordExactlyMatchingForm( - *in_form)); + EXPECT_TRUE( + owned_keychain_adapter.HasPasswordsMergeableWithForm(*in_form)); + EXPECT_TRUE( + owned_keychain_adapter.HasPasswordExactlyMatchingForm(*in_form)); } } @@ -750,21 +682,26 @@ // TODO(engedy): Add a test to verify that updating Android credentials work. // See: https://crbug.com/476851. { - PasswordFormData data = { - PasswordForm::SCHEME_HTML, "http://some.domain.com", - "http://some.domain.com/insecure.html", NULL, - NULL, NULL, NULL, L"joe_user", L"updated_password", false, false, 0 - }; + PasswordFormData data = {PasswordForm::SCHEME_HTML, + "http://some.domain.com", + "http://some.domain.com/insecure.html", + NULL, + NULL, + NULL, + NULL, + L"joe_user", + L"updated_password", + false, + false, + 0}; std::unique_ptr<PasswordForm> update_form = CreatePasswordFormFromDataForTesting(data); MacKeychainPasswordFormAdapter keychain_adapter(keychain_); EXPECT_TRUE(keychain_adapter.AddPassword(*update_form)); SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(2); PasswordForm stored_form; - internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, - keychain_item, - &stored_form, - true); + internal_keychain_helpers::FillPasswordFormFromKeychainItem( + *keychain_, keychain_item, &stored_form, true); EXPECT_EQ(update_form->password_value, stored_form.password_value); } } @@ -774,26 +711,29 @@ PasswordFormData data; bool should_succeed; }; - /* clang-format off */ TestDataAndExpectation test_data[] = { - // Test deletion of an item that we add. - { { PasswordForm::SCHEME_HTML, "http://web.site.com/", + // Test deletion of an item that we add. + {{PasswordForm::SCHEME_HTML, "http://web.site.com/", "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, - L"anonymous", L"knock-knock", false, false, 0 }, true }, - // Test that Android credentials can be removed. Also check the legacy case - // when |origin| was still filled with the Android URI (and not left empty). - { { PasswordForm::SCHEME_HTML, "android://hash@com.example.alpha/", - "", NULL, NULL, NULL, NULL, - L"joe_user", L"secret", false, true, 0 }, true }, - { { PasswordForm::SCHEME_HTML, "android://hash@com.example.beta/", + L"anonymous", L"knock-knock", false, false, 0}, + true}, + // Test that Android credentials can be removed. Also check the legacy + // case + // when |origin| was still filled with the Android URI (and not left + // empty). + {{PasswordForm::SCHEME_HTML, "android://hash@com.example.alpha/", "", + NULL, NULL, NULL, NULL, L"joe_user", L"secret", false, true, 0}, + true}, + {{PasswordForm::SCHEME_HTML, "android://hash@com.example.beta/", "android://hash@com.example.beta/", NULL, NULL, NULL, NULL, - L"jane_user", L"secret", false, true, 0 }, true }, - // Make sure we don't delete items we don't own. - { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", + L"jane_user", L"secret", false, true, 0}, + true}, + // Make sure we don't delete items we don't own. + {{PasswordForm::SCHEME_HTML, "http://some.domain.com/", "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, - L"joe_user", NULL, true, false, 0 }, false }, + L"joe_user", NULL, true, false, 0}, + false}, }; - /* clang-format on */ MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_); owned_keychain_adapter.SetFindsOnlyOwnedItems(true); @@ -891,83 +831,195 @@ TEST_F(PasswordStoreMacInternalsTest, TestFormMerge) { // Set up a bunch of test data to use in varying combinations. - /* clang-format off */ - PasswordFormData keychain_user_1 = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", "", L"", L"", L"", L"joe_user", L"sekrit", - false, false, 1010101010 }; - PasswordFormData keychain_user_1_with_path = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "", L"", L"", L"", L"joe_user", L"otherpassword", - false, false, 1010101010 }; - PasswordFormData keychain_user_2 = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", "", L"", L"", L"", L"john.doe", L"sesame", - false, false, 958739876 }; - PasswordFormData keychain_blacklist = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", "", L"", L"", L"", NULL, NULL, - false, false, 1010101010 }; - PasswordFormData keychain_android = - { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - "", "", L"", L"", L"", L"joe_user", L"secret", - false, true, 1234567890 }; + PasswordFormData keychain_user_1 = {PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/", + "", + L"", + L"", + L"", + L"joe_user", + L"sekrit", + false, + false, + 1010101010}; + PasswordFormData keychain_user_1_with_path = { + PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/page.html", + "", + L"", + L"", + L"", + L"joe_user", + L"otherpassword", + false, + false, + 1010101010}; + PasswordFormData keychain_user_2 = {PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/", + "", + L"", + L"", + L"", + L"john.doe", + L"sesame", + false, + false, + 958739876}; + PasswordFormData keychain_blacklist = {PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/", + "", + L"", + L"", + L"", + NULL, + NULL, + false, + false, + 1010101010}; + PasswordFormData keychain_android = {PasswordForm::SCHEME_HTML, + "android://hash@com.domain.some/", + "", + "", + L"", + L"", + L"", + L"joe_user", + L"secret", + false, + true, + 1234567890}; - PasswordFormData db_user_1 = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", "http://some.domain.com/action.cgi", - L"submit", L"username", L"password", L"joe_user", L"", - true, false, 1212121212 }; - PasswordFormData db_user_1_with_path = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "http://some.domain.com/handlepage.cgi", - L"submit", L"username", L"password", L"joe_user", L"", - true, false, 1234567890 }; - PasswordFormData db_user_3_with_path = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "http://some.domain.com/handlepage.cgi", - L"submit", L"username", L"password", L"second-account", L"", - true, false, 1240000000 }; - PasswordFormData database_blacklist_with_path = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/path.html", "http://some.domain.com/action.cgi", - L"submit", L"username", L"password", NULL, NULL, - true, false, 1212121212 }; - PasswordFormData db_android = - { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - "android://hash@com.domain.some/", "", L"", L"", L"", L"joe_user", L"", - false, true, 1234567890 }; - PasswordFormData db_federated = - { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - "android://hash@com.domain.some/", "", L"", L"", L"", L"joe_user", - password_manager::kTestingFederatedLoginMarker, - false, true, 3434343434 }; + PasswordFormData db_user_1 = {PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/", + "http://some.domain.com/action.cgi", + L"submit", + L"username", + L"password", + L"joe_user", + L"", + true, + false, + 1212121212}; + PasswordFormData db_user_1_with_path = { + PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/page.html", + "http://some.domain.com/handlepage.cgi", + L"submit", + L"username", + L"password", + L"joe_user", + L"", + true, + false, + 1234567890}; + PasswordFormData db_user_3_with_path = { + PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/page.html", + "http://some.domain.com/handlepage.cgi", + L"submit", + L"username", + L"password", + L"second-account", + L"", + true, + false, + 1240000000}; + PasswordFormData database_blacklist_with_path = { + PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/path.html", + "http://some.domain.com/action.cgi", + L"submit", + L"username", + L"password", + NULL, + NULL, + true, + false, + 1212121212}; + PasswordFormData db_android = {PasswordForm::SCHEME_HTML, + "android://hash@com.domain.some/", + "android://hash@com.domain.some/", + "", + L"", + L"", + L"", + L"joe_user", + L"", + false, + true, + 1234567890}; + PasswordFormData db_federated = { + PasswordForm::SCHEME_HTML, + "android://hash@com.domain.some/", + "android://hash@com.domain.some/", + "", + L"", + L"", + L"", + L"joe_user", + password_manager::kTestingFederatedLoginMarker, + false, + true, + 3434343434}; - PasswordFormData merged_user_1 = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", "http://some.domain.com/action.cgi", - L"submit", L"username", L"password", L"joe_user", L"sekrit", - true, false, 1212121212 }; - PasswordFormData merged_user_1_with_db_path = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "http://some.domain.com/handlepage.cgi", - L"submit", L"username", L"password", L"joe_user", L"sekrit", - true, false, 1234567890 }; - PasswordFormData merged_user_1_with_both_paths = - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "http://some.domain.com/handlepage.cgi", - L"submit", L"username", L"password", L"joe_user", L"otherpassword", - true, false, 1234567890 }; - PasswordFormData merged_android = - { PasswordForm::SCHEME_HTML, "android://hash@com.domain.some/", - "android://hash@com.domain.some/", "", L"", L"", L"", L"joe_user", - L"secret", false, true, 1234567890 }; - /* clang-format on */ + PasswordFormData merged_user_1 = {PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/", + "http://some.domain.com/action.cgi", + L"submit", + L"username", + L"password", + L"joe_user", + L"sekrit", + true, + false, + 1212121212}; + PasswordFormData merged_user_1_with_db_path = { + PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/page.html", + "http://some.domain.com/handlepage.cgi", + L"submit", + L"username", + L"password", + L"joe_user", + L"sekrit", + true, + false, + 1234567890}; + PasswordFormData merged_user_1_with_both_paths = { + PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/page.html", + "http://some.domain.com/handlepage.cgi", + L"submit", + L"username", + L"password", + L"joe_user", + L"otherpassword", + true, + false, + 1234567890}; + PasswordFormData merged_android = {PasswordForm::SCHEME_HTML, + "android://hash@com.domain.some/", + "android://hash@com.domain.some/", + "", + L"", + L"", + L"", + L"joe_user", + L"secret", + false, + true, + 1234567890}; // Build up the big multi-dimensional array of data sets that will actually // drive the test. Use vectors rather than arrays so that initialization is @@ -981,9 +1033,9 @@ MERGE_IO_ARRAY_COUNT // termination marker }; const unsigned int kTestCount = 5; - std::vector< std::vector< std::vector<PasswordFormData*> > > test_data( - MERGE_IO_ARRAY_COUNT, std::vector< std::vector<PasswordFormData*> >( - kTestCount, std::vector<PasswordFormData*>())); + std::vector<std::vector<std::vector<PasswordFormData*>>> test_data( + MERGE_IO_ARRAY_COUNT, std::vector<std::vector<PasswordFormData*>>( + kTestCount, std::vector<PasswordFormData*>())); unsigned int current_test = 0; // Test a merge with a few accounts in both systems, with partial overlap. @@ -1059,9 +1111,8 @@ } ScopedVector<autofill::PasswordForm> merged_forms; - internal_keychain_helpers::MergePasswordForms(&keychain_forms, - &database_forms, - &merged_forms); + internal_keychain_helpers::MergePasswordForms( + &keychain_forms, &database_forms, &merged_forms); CHECK_FORMS(keychain_forms.get(), test_data[KEYCHAIN_OUTPUT][test_case], test_case); @@ -1074,29 +1125,26 @@ TEST_F(PasswordStoreMacInternalsTest, TestPasswordBulkLookup) { PasswordFormData db_data[] = { - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/", "http://some.domain.com/action.cgi", - L"submit", L"username", L"password", L"joe_user", L"", - true, false, 1212121212 }, - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "http://some.domain.com/handlepage.cgi", - L"submit", L"username", L"password", L"joe_user", L"", - true, false, 1234567890 }, - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/page.html", - "http://some.domain.com/handlepage.cgi", - L"submit", L"username", L"password", L"second-account", L"", - true, false, 1240000000 }, - { PasswordForm::SCHEME_HTML, "http://dont.remember.com/", - "http://dont.remember.com/", - "http://dont.remember.com/handlepage.cgi", - L"submit", L"username", L"password", L"joe_user", L"", - true, false, 1240000000 }, - { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/path.html", "http://some.domain.com/action.cgi", - L"submit", L"username", L"password", NULL, NULL, - true, false, 1212121212 }, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/", "http://some.domain.com/action.cgi", + L"submit", L"username", L"password", L"joe_user", L"", true, false, + 1212121212}, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/page.html", + "http://some.domain.com/handlepage.cgi", L"submit", L"username", + L"password", L"joe_user", L"", true, false, 1234567890}, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/page.html", + "http://some.domain.com/handlepage.cgi", L"submit", L"username", + L"password", L"second-account", L"", true, false, 1240000000}, + {PasswordForm::SCHEME_HTML, "http://dont.remember.com/", + "http://dont.remember.com/", "http://dont.remember.com/handlepage.cgi", + L"submit", L"username", L"password", L"joe_user", L"", true, false, + 1240000000}, + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/path.html", "http://some.domain.com/action.cgi", + L"submit", L"username", L"password", NULL, NULL, true, false, + 1212121212}, }; ScopedVector<autofill::PasswordForm> database_forms; for (unsigned int i = 0; i < arraysize(db_data); ++i) { @@ -1115,16 +1163,15 @@ TEST_F(PasswordStoreMacInternalsTest, TestBlacklistedFiltering) { PasswordFormData db_data[] = { - { PasswordForm::SCHEME_HTML, "http://dont.remember.com/", - "http://dont.remember.com/", - "http://dont.remember.com/handlepage.cgi", - L"submit", L"username", L"password", L"joe_user", L"non_empty_password", - true, false, 1240000000 }, - { PasswordForm::SCHEME_HTML, "https://dont.remember.com/", - "https://dont.remember.com/", - "https://dont.remember.com/handlepage_secure.cgi", - L"submit", L"username", L"password", L"joe_user", L"non_empty_password", - true, false, 1240000000 }, + {PasswordForm::SCHEME_HTML, "http://dont.remember.com/", + "http://dont.remember.com/", "http://dont.remember.com/handlepage.cgi", + L"submit", L"username", L"password", L"joe_user", L"non_empty_password", + true, false, 1240000000}, + {PasswordForm::SCHEME_HTML, "https://dont.remember.com/", + "https://dont.remember.com/", + "https://dont.remember.com/handlepage_secure.cgi", L"submit", + L"username", L"password", L"joe_user", L"non_empty_password", true, + false, 1240000000}, }; ScopedVector<autofill::PasswordForm> database_forms; for (unsigned int i = 0; i < arraysize(db_data); ++i) { @@ -1144,9 +1191,7 @@ SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(1); PasswordForm form_without_extracted_password; bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( - *keychain_, - keychain_item, - &form_without_extracted_password, + *keychain_, keychain_item, &form_without_extracted_password, false); // Do not extract password. EXPECT_TRUE(parsed); ASSERT_TRUE(form_without_extracted_password.password_value.empty()); @@ -1158,9 +1203,7 @@ keychain_item = reinterpret_cast<SecKeychainItemRef>(1); PasswordForm form_with_extracted_password; parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( - *keychain_, - keychain_item, - &form_with_extracted_password, + *keychain_, keychain_item, &form_with_extracted_password, true); // Extract password. EXPECT_TRUE(parsed); ASSERT_EQ(ASCIIToUTF16("sekrit"), @@ -1173,9 +1216,7 @@ keychain_item = reinterpret_cast<SecKeychainItemRef>(4); PasswordForm negative_form; parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( - *keychain_, - keychain_item, - &negative_form, + *keychain_, keychain_item, &negative_form, true); // Extract password. EXPECT_TRUE(parsed); ASSERT_TRUE(negative_form.username_value.empty()); @@ -1188,9 +1229,7 @@ keychain_item = reinterpret_cast<SecKeychainItemRef>(5); PasswordForm form_with_empty_password_a; parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( - *keychain_, - keychain_item, - &form_with_empty_password_a, + *keychain_, keychain_item, &form_with_empty_password_a, true); // Extract password. EXPECT_TRUE(parsed); ASSERT_TRUE(form_with_empty_password_a.password_value.empty()); @@ -1202,13 +1241,10 @@ keychain_item = reinterpret_cast<SecKeychainItemRef>(6); PasswordForm form_with_empty_password_b; parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem( - *keychain_, - keychain_item, - &form_with_empty_password_b, + *keychain_, keychain_item, &form_with_empty_password_b, true); // Extract password. EXPECT_TRUE(parsed); - ASSERT_EQ(ASCIIToUTF16(" "), - form_with_empty_password_b.password_value); + ASSERT_EQ(ASCIIToUTF16(" "), form_with_empty_password_b.password_value); ASSERT_TRUE(form_with_empty_password_b.blacklisted_by_user); } @@ -1219,15 +1255,15 @@ // Add a few passwords of various types so that we own some. PasswordFormData owned_password_data[] = { - { PasswordForm::SCHEME_HTML, "http://web.site.com/", - "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, - L"anonymous", L"knock-knock", false, false, 0 }, - { PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm", - "http://a.site.com:2222/", NULL, NULL, NULL, NULL, - L"username", L"password", false, false, 0 }, - { PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm", - "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL, - L"testname", L"testpass", false, false, 0 }, + {PasswordForm::SCHEME_HTML, "http://web.site.com/", + "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL, + L"anonymous", L"knock-knock", false, false, 0}, + {PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm", + "http://a.site.com:2222/", NULL, NULL, NULL, NULL, L"username", + L"password", false, false, 0}, + {PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm", + "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL, + L"testname", L"testpass", false, false, 0}, }; for (unsigned int i = 0; i < arraysize(owned_password_data); ++i) { std::unique_ptr<PasswordForm> form = @@ -1398,26 +1434,46 @@ // Mock Keychain isn't smart enough to be able to support update generically, // so some.domain.com triggers special handling to test it that make inserting // fail. - PasswordFormData joint_data = { - PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/insecure.html", "login.cgi", - L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 - }; + PasswordFormData joint_data = {PasswordForm::SCHEME_HTML, + "http://some.domain.com/", + "http://some.domain.com/insecure.html", + "login.cgi", + L"username", + L"password", + L"submit", + L"joe_user", + L"sekrit", + true, + false, + 1}; std::unique_ptr<PasswordForm> joint_form = CreatePasswordFormFromDataForTesting(joint_data); EXPECT_EQ(AddChangeForForm(*joint_form), login_db()->AddLogin(*joint_form)); MockAppleKeychain::KeychainTestData joint_keychain_data = { - kSecAuthenticationTypeHTMLForm, "some.domain.com", - kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z", - "joe_user", "sekrit", false }; + kSecAuthenticationTypeHTMLForm, + "some.domain.com", + kSecProtocolTypeHTTP, + "/insecure.html", + 0, + NULL, + "20020601171500Z", + "joe_user", + "sekrit", + false}; keychain()->AddTestItem(joint_keychain_data); // Insert a password into the keychain only. MockAppleKeychain::KeychainTestData keychain_only_data = { - kSecAuthenticationTypeHTMLForm, "keychain.only.com", - kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", - "keychain", "only", false - }; + kSecAuthenticationTypeHTMLForm, + "keychain.only.com", + kSecProtocolTypeHTTP, + NULL, + 0, + NULL, + "20020601171500Z", + "keychain", + "only", + false}; keychain()->AddTestItem(keychain_only_data); struct UpdateData { @@ -1427,30 +1483,30 @@ // Make a series of update calls. UpdateData updates[] = { - // Update the keychain+db passwords (the normal password update case). - { { PasswordForm::SCHEME_HTML, "http://some.domain.com/", - "http://some.domain.com/insecure.html", "login.cgi", - L"username", L"password", L"submit", L"joe_user", L"53krit", - true, false, 2 }, - "53krit", - }, - // Update the keychain-only password; this simulates the initial use of a - // password stored by another browsers. - { { PasswordForm::SCHEME_HTML, "http://keychain.only.com/", - "http://keychain.only.com/login.html", "login.cgi", - L"username", L"password", L"submit", L"keychain", L"only", - true, false, 2 }, - "only", - }, - // Update a password that doesn't exist in either location. This tests the - // case where a form is filled, then the stored login is removed, then the - // form is submitted. - { { PasswordForm::SCHEME_HTML, "http://different.com/", - "http://different.com/index.html", "login.cgi", - L"username", L"password", L"submit", L"abc", L"123", - true, false, 2 }, - NULL, - }, + // Update the keychain+db passwords (the normal password update case). + { + {PasswordForm::SCHEME_HTML, "http://some.domain.com/", + "http://some.domain.com/insecure.html", "login.cgi", L"username", + L"password", L"submit", L"joe_user", L"53krit", true, false, 2}, + "53krit", + }, + // Update the keychain-only password; this simulates the initial use of a + // password stored by another browsers. + { + {PasswordForm::SCHEME_HTML, "http://keychain.only.com/", + "http://keychain.only.com/login.html", "login.cgi", L"username", + L"password", L"submit", L"keychain", L"only", true, false, 2}, + "only", + }, + // Update a password that doesn't exist in either location. This tests the + // case where a form is filled, then the stored login is removed, then the + // form is submitted. + { + {PasswordForm::SCHEME_HTML, "http://different.com/", + "http://different.com/index.html", "login.cgi", L"username", + L"password", L"submit", L"abc", L"123", true, false, 2}, + NULL, + }, }; for (unsigned int i = 0; i < arraysize(updates); ++i) { std::unique_ptr<PasswordForm> form = @@ -1472,7 +1528,8 @@ EXPECT_GT(matching_items.size(), 0U) << "iteration " << i; if (matching_items.size() >= 1) EXPECT_EQ(ASCIIToUTF16(updates[i].password), - matching_items[0]->password_value) << "iteration " << i; + matching_items[0]->password_value) + << "iteration " << i; } else { EXPECT_EQ(0U, matching_items.size()) << "iteration " << i; } @@ -1500,11 +1557,18 @@ // fuzzy-matches the www.facebook.com one.) // 1. Add a password for www.facebook.com - PasswordFormData www_form_data = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", - L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1 - }; + PasswordFormData www_form_data = {PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"username", + L"password", + L"submit", + L"joe_user", + L"sekrit", + true, + false, + 1}; std::unique_ptr<PasswordForm> www_form = CreatePasswordFormFromDataForTesting(www_form_data); EXPECT_EQ(AddChangeForForm(*www_form), login_db()->AddLogin(*www_form)); @@ -1586,18 +1650,44 @@ // |check_created|. void CheckRemoveLoginsBetween(PasswordStoreMacTest* test, bool check_created) { PasswordFormData www_form_data_facebook = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", L"submit", L"username", - L"password", L"joe_user", L"sekrit", true, false, 0 }; + PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"submit", + L"username", + L"password", + L"joe_user", + L"sekrit", + true, + false, + 0}; // The old form doesn't have elements names. PasswordFormData www_form_data_facebook_old = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", L"", L"", - L"", L"joe_user", L"oldsekrit", true, false, 0 }; - PasswordFormData www_form_data_other = { - PasswordForm::SCHEME_HTML, "http://different.com/", - "http://different.com/index.html", "login", L"submit", L"username", - L"password", L"different_joe_user", L"sekrit", true, false, 0 }; + PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"", + L"", + L"", + L"joe_user", + L"oldsekrit", + true, + false, + 0}; + PasswordFormData www_form_data_other = {PasswordForm::SCHEME_HTML, + "http://different.com/", + "http://different.com/index.html", + "login", + L"submit", + L"username", + L"password", + L"different_joe_user", + L"sekrit", + true, + false, + 0}; std::unique_ptr<PasswordForm> form_facebook = CreatePasswordFormFromDataForTesting(www_form_data_facebook); std::unique_ptr<PasswordForm> form_facebook_old = @@ -1730,28 +1820,51 @@ // Add a third-party password. MockAppleKeychain::KeychainTestData keychain_data = { - kSecAuthenticationTypeHTMLForm, "some.domain.com", - kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z", - "joe_user", "sekrit", false }; + kSecAuthenticationTypeHTMLForm, + "some.domain.com", + kSecProtocolTypeHTTP, + "/insecure.html", + 0, + NULL, + "20020601171500Z", + "joe_user", + "sekrit", + false}; keychain()->AddTestItem(keychain_data); // Add a password through the adapter. It has the "Chrome" creator tag. // However, it's not referenced by the password database. MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain()); owned_keychain_adapter.SetFindsOnlyOwnedItems(true); - PasswordFormData www_form_data1 = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", L"username", L"password", - L"submit", L"joe_user", L"sekrit", true, false, 1 }; + PasswordFormData www_form_data1 = {PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"username", + L"password", + L"submit", + L"joe_user", + L"sekrit", + true, + false, + 1}; std::unique_ptr<PasswordForm> www_form = CreatePasswordFormFromDataForTesting(www_form_data1); EXPECT_TRUE(owned_keychain_adapter.AddPassword(*www_form)); // Add a password from the current profile. - PasswordFormData www_form_data2 = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", L"username", L"password", - L"submit", L"not_joe_user", L"12345", true, false, 1 }; + PasswordFormData www_form_data2 = {PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"username", + L"password", + L"submit", + L"not_joe_user", + L"12345", + true, + false, + 1}; www_form = CreatePasswordFormFromDataForTesting(www_form_data2); store_->AddLogin(*www_form); FinishAsyncProcessing(); @@ -1790,11 +1903,18 @@ store()->AddObserver(&mock_observer); // 1. Add a password for www.facebook.com to the LoginDatabase. - PasswordFormData www_form_data = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", - L"username", L"password", L"submit", L"joe_user", L"", true, false, 1 - }; + PasswordFormData www_form_data = {PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"username", + L"password", + L"submit", + L"joe_user", + L"", + true, + false, + 1}; std::unique_ptr<PasswordForm> www_form( CreatePasswordFormFromDataForTesting(www_form_data)); EXPECT_EQ(AddChangeForForm(*www_form), login_db()->AddLogin(*www_form)); @@ -1906,8 +2026,9 @@ EXPECT_EQ(blacklisted_form, *matching_items[0]); // The passwords are encrypted using a key from the Keychain. - EXPECT_TRUE(histogram_tester_->GetHistogramSamplesSinceCreation( - "OSX.Keychain.Access")->TotalCount()); + EXPECT_TRUE( + histogram_tester_->GetHistogramSamplesSinceCreation("OSX.Keychain.Access") + ->TotalCount()); histogram_tester_.reset(); }
diff --git a/chrome/browser/password_manager/password_store_proxy_mac_unittest.cc b/chrome/browser/password_manager/password_store_proxy_mac_unittest.cc index ce3837a..bcdd8ce 100644 --- a/chrome/browser/password_manager/password_store_proxy_mac_unittest.cc +++ b/chrome/browser/password_manager/password_store_proxy_mac_unittest.cc
@@ -144,8 +144,7 @@ OSCryptMocker::SetUpWithSingleton(); } -PasswordStoreProxyMacTest::~PasswordStoreProxyMacTest() { -} +PasswordStoreProxyMacTest::~PasswordStoreProxyMacTest() {} void PasswordStoreProxyMacTest::SetUp() { std::unique_ptr<password_manager::LoginDatabase> login_db( @@ -350,9 +349,18 @@ // Add a new autofillable login + a blacklisted login. password_manager::PasswordFormData www_form_data = { - PasswordForm::SCHEME_HTML, "http://www.facebook.com/", - "http://www.facebook.com/index.html", "login", L"username", L"password", - L"submit", L"not_joe_user", L"12345", true, false, 1}; + PasswordForm::SCHEME_HTML, + "http://www.facebook.com/", + "http://www.facebook.com/index.html", + "login", + L"username", + L"password", + L"submit", + L"not_joe_user", + L"12345", + true, + false, + 1}; std::unique_ptr<PasswordForm> form = CreatePasswordFormFromDataForTesting(www_form_data); std::unique_ptr<PasswordForm> blacklisted_form(new PasswordForm(*form)); @@ -456,7 +464,8 @@ // Check the password is still there. if (lock_keychain && store_->password_store_mac()) { static_cast<crypto::MockAppleKeychain*>( - store_->password_store_mac()->keychain())->set_locked(false); + store_->password_store_mac()->keychain()) + ->set_locked(false); } MockPasswordStoreConsumer mock_consumer; store()->GetLogins(form, &mock_consumer); @@ -479,8 +488,7 @@ EXPECT_EQ(static_cast<int>(MigrationStatus::MIGRATED), status); } histogram_tester_.ExpectUniqueSample( - "PasswordManager.KeychainMigration.Status", - status, 1); + "PasswordManager.KeychainMigration.Status", status, 1); } TEST_P(PasswordStoreProxyMacMigrationTest, TestSuccessfullMigration) {
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc index ba154fd..21508c5 100644 --- a/chrome/browser/password_manager/password_store_win_unittest.cc +++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -74,23 +74,24 @@ protected: PasswordStoreWinTest() : ui_thread_(BrowserThread::UI, &message_loop_), - db_thread_(BrowserThread::DB) { - } + db_thread_(BrowserThread::DB) {} - bool CreateIE7PasswordInfo(const std::wstring& url, const base::Time& created, + bool CreateIE7PasswordInfo(const std::wstring& url, + const base::Time& created, IE7PasswordInfo* info) { // Copied from chrome/browser/importer/importer_unittest.cc // The username is "abcdefgh" and the password "abcdefghijkl". - unsigned char data[] = "\x0c\x00\x00\x00\x38\x00\x00\x00\x2c\x00\x00\x00" - "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00" - "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x4e\xfa\x67\x76\x22\x94\xc8\x01" - "\x08\x00\x00\x00\x12\x00\x00\x00\x4e\xfa\x67\x76" - "\x22\x94\xc8\x01\x0c\x00\x00\x00\x61\x00\x62\x00" - "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00" - "\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00" - "\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00" - "\x6c\x00\x00\x00"; + unsigned char data[] = + "\x0c\x00\x00\x00\x38\x00\x00\x00\x2c\x00\x00\x00" + "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00" + "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x4e\xfa\x67\x76\x22\x94\xc8\x01" + "\x08\x00\x00\x00\x12\x00\x00\x00\x4e\xfa\x67\x76" + "\x22\x94\xc8\x01\x0c\x00\x00\x00\x61\x00\x62\x00" + "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00" + "\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00" + "\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00" + "\x6c\x00\x00\x00"; DATA_BLOB input = {0}; DATA_BLOB url_key = {0}; DATA_BLOB output = {0}; @@ -98,10 +99,10 @@ input.pbData = data; input.cbData = sizeof(data); - url_key.pbData = reinterpret_cast<unsigned char*>( - const_cast<wchar_t*>(url.data())); - url_key.cbData = static_cast<DWORD>((url.size() + 1) * - sizeof(std::wstring::value_type)); + url_key.pbData = + reinterpret_cast<unsigned char*>(const_cast<wchar_t*>(url.data())); + url_key.cbData = + static_cast<DWORD>((url.size() + 1) * sizeof(std::wstring::value_type)); if (!CryptProtectData(&input, nullptr, &url_key, nullptr, nullptr, CRYPTPROTECT_UI_FORBIDDEN, &output)) @@ -127,15 +128,14 @@ profile_.reset(new TestingProfile()); base::FilePath path = temp_dir_.path().AppendASCII("web_data_test"); - wdbs_ = new WebDatabaseService(path, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + wdbs_ = new WebDatabaseService( + path, BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)); // Need to add at least one table so the database gets created. wdbs_->AddTable(std::unique_ptr<WebDatabaseTable>(new LoginsTable())); wdbs_->LoadDatabase(); wds_ = new PasswordWebDataService( - wdbs_, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + wdbs_, BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), WebDataServiceBase::ProfileErrorCallback()); wds_->Init(); } @@ -153,7 +153,8 @@ } base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, + BrowserThread::PostTask( + BrowserThread::DB, FROM_HERE, base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); done.Wait(); base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -196,8 +197,9 @@ } MATCHER(EmptyWDResult, "") { - return static_cast<const WDResult<std::vector<PasswordForm*> >*>( - arg)->GetValue().empty(); + return static_cast<const WDResult<std::vector<PasswordForm*>>*>(arg) + ->GetValue() + .empty(); } // Hangs flakily, http://crbug.com/71385. @@ -217,7 +219,8 @@ // task to notify us that it's safe to carry on with the test. WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, + BrowserThread::PostTask( + BrowserThread::DB, FROM_HERE, base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); done.Wait(); @@ -231,16 +234,18 @@ .WillByDefault(QuitUIMessageLoop()); PasswordFormData form_data = { - PasswordForm::SCHEME_HTML, - "http://example.com/", - "http://example.com/origin", - "http://example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"", - L"", - true, false, 1, + PasswordForm::SCHEME_HTML, + "http://example.com/", + "http://example.com/origin", + "http://example.com/action", + L"submit_element", + L"username_element", + L"password_element", + L"", + L"", + true, + false, + 1, }; std::unique_ptr<PasswordForm> form = CreatePasswordFormFromDataForTesting(form_data); @@ -248,16 +253,18 @@ // The returned form will not have 'action' or '*_element' fields set. This // is because credentials imported from IE don't have this information. PasswordFormData expected_form_data = { - PasswordForm::SCHEME_HTML, - "http://example.com/", - "http://example.com/origin", - "", - L"", - L"", - L"", - L"abcdefgh", - L"abcdefghijkl", - true, false, 1, + PasswordForm::SCHEME_HTML, + "http://example.com/", + "http://example.com/origin", + "", + L"", + L"", + L"", + L"abcdefgh", + L"abcdefghijkl", + true, + false, + 1, }; ScopedVector<autofill::PasswordForm> expected_forms; expected_forms.push_back( @@ -277,16 +284,18 @@ EXPECT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare())); PasswordFormData form_data = { - PasswordForm::SCHEME_HTML, - "http://example.com/", - "http://example.com/origin", - "http://example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"", - L"", - true, false, 1, + PasswordForm::SCHEME_HTML, + "http://example.com/", + "http://example.com/origin", + "http://example.com/action", + L"submit_element", + L"username_element", + L"password_element", + L"", + L"", + true, + false, + 1, }; std::unique_ptr<PasswordForm> form = CreatePasswordFormFromDataForTesting(form_data); @@ -317,7 +326,8 @@ // task to notify us that it's safe to carry on with the test. WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); - BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, + BrowserThread::PostTask( + BrowserThread::DB, FROM_HERE, base::Bind(&WaitableEvent::Signal, base::Unretained(&done))); done.Wait(); @@ -330,31 +340,35 @@ .WillByDefault(QuitUIMessageLoop()); PasswordFormData form_data = { - PasswordForm::SCHEME_HTML, - "http://example.com/", - "http://example.com/origin", - "http://example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"", - L"", - true, false, 1, + PasswordForm::SCHEME_HTML, + "http://example.com/", + "http://example.com/origin", + "http://example.com/action", + L"submit_element", + L"username_element", + L"password_element", + L"", + L"", + true, + false, + 1, }; std::unique_ptr<PasswordForm> form = CreatePasswordFormFromDataForTesting(form_data); PasswordFormData expected_form_data = { - PasswordForm::SCHEME_HTML, - "http://example.com/", - "http://example.com/origin", - "http://example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"abcdefgh", - L"abcdefghijkl", - true, false, 1, + PasswordForm::SCHEME_HTML, + "http://example.com/", + "http://example.com/origin", + "http://example.com/action", + L"submit_element", + L"username_element", + L"password_element", + L"abcdefgh", + L"abcdefghijkl", + true, + false, + 1, }; ScopedVector<autofill::PasswordForm> expected_forms; expected_forms.push_back( @@ -386,16 +400,18 @@ store_->Init(syncer::SyncableService::StartSyncFlare()); PasswordFormData form_data = { - PasswordForm::SCHEME_HTML, - "http://example.com/", - "http://example.com/origin", - "http://example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"", - L"", - true, false, 1, + PasswordForm::SCHEME_HTML, + "http://example.com/", + "http://example.com/origin", + "http://example.com/action", + L"submit_element", + L"username_element", + L"password_element", + L"", + L"", + true, + false, + 1, }; std::unique_ptr<PasswordForm> form = CreatePasswordFormFromDataForTesting(form_data);
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc index 3f566d3..36a99f3 100644 --- a/chrome/browser/password_manager/password_store_x_unittest.cc +++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -229,7 +229,7 @@ private: void erase(size_t index) { if (index < all_forms_.size() - 1) - all_forms_[index] = all_forms_[all_forms_.size() - 1]; + all_forms_[index] = all_forms_.back(); all_forms_.pop_back(); }
diff --git a/chrome/browser/profiles/profile_avatar_icon_util.cc b/chrome/browser/profiles/profile_avatar_icon_util.cc index b0fa75e..7c19797 100644 --- a/chrome/browser/profiles/profile_avatar_icon_util.cc +++ b/chrome/browser/profiles/profile_avatar_icon_util.cc
@@ -13,6 +13,7 @@ #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/browser_process.h" @@ -487,7 +488,7 @@ bool IsDefaultAvatarIconUrl(const std::string& url, size_t* icon_index) { DCHECK(icon_index); - if (url.find(kDefaultUrlPrefix) != 0) + if (!base::StartsWith(url, kDefaultUrlPrefix, base::CompareCase::SENSITIVE)) return false; int int_value = -1;
diff --git a/chrome/browser/renderer_host/OWNERS b/chrome/browser/renderer_host/OWNERS index e994eeee..b5e8dfa2 100644 --- a/chrome/browser/renderer_host/OWNERS +++ b/chrome/browser/renderer_host/OWNERS
@@ -9,6 +9,7 @@ per-file chrome_extension_message_filter.*=asargent@chromium.org per-file data_reduction_proxy_resource_throttle_android.*=sgurun@chromium.org +per-file site_per_process_text_input_browsertest.cc=creis@chromium.org # Mac files per-file *.mm=avi@chromium.org
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h index 1f4f5fa..86bdd50 100644 --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
@@ -16,22 +16,11 @@ class RenderWidgetHost; } -namespace ChromeRenderWidgetHostViewMacDelegateInternal { -class SpellCheckObserver; -} - @class HistorySwiper; @interface ChromeRenderWidgetHostViewMacDelegate : NSObject<RenderWidgetHostViewMacDelegate> { @private content::RenderWidgetHost* renderWidgetHost_; // weak - std::unique_ptr< - ChromeRenderWidgetHostViewMacDelegateInternal::SpellCheckObserver> - spellingObserver_; - - // Used for continuous spell checking. - BOOL spellcheckEnabled_; - BOOL spellcheckChecked_; // Responsible for 2-finger swipes history navigation. base::scoped_nsobject<HistorySwiper> historySwiper_;
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm index 37abdf2..f3ac18ba 100644 --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
@@ -24,63 +24,18 @@ #include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" using content::RenderViewHost; @interface ChromeRenderWidgetHostViewMacDelegate () <HistorySwiperDelegate> -- (void)spellCheckEnabled:(BOOL)enabled checked:(BOOL)checked; @end -namespace ChromeRenderWidgetHostViewMacDelegateInternal { - -// Filters the message sent by the renderer to know if spellchecking is enabled -// or not for the currently focused element. -class SpellCheckObserver : public content::WebContentsObserver { - public: - SpellCheckObserver( - RenderViewHost* host, - ChromeRenderWidgetHostViewMacDelegate* view_delegate) - : content::WebContentsObserver( - content::WebContents::FromRenderViewHost(host)), - view_delegate_(view_delegate) { - } - - ~SpellCheckObserver() override {} - - private: - bool OnMessageReceived(const IPC::Message& message) override { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(SpellCheckObserver, message) - IPC_MESSAGE_HANDLER(SpellCheckHostMsg_ToggleSpellCheck, - OnToggleSpellCheck) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; - } - - void OnToggleSpellCheck(bool enabled, bool checked) { - [view_delegate_ spellCheckEnabled:enabled checked:checked]; - } - - ChromeRenderWidgetHostViewMacDelegate* view_delegate_; -}; - -} // namespace ChromeRenderWidgetHostViewMacDelegateInternal - @implementation ChromeRenderWidgetHostViewMacDelegate - (id)initWithRenderWidgetHost:(content::RenderWidgetHost*)renderWidgetHost { self = [super init]; if (self) { renderWidgetHost_ = renderWidgetHost; - RenderViewHost* rvh = RenderViewHost::From(renderWidgetHost_); - if (rvh) { - spellingObserver_.reset( - new ChromeRenderWidgetHostViewMacDelegateInternal::SpellCheckObserver( - rvh, self)); - } - historySwiper_.reset([[HistorySwiper alloc] initWithDelegate:self]); } return self; @@ -175,13 +130,12 @@ content::RenderProcessHost* host = renderWidgetHost_->GetProcess(); Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); DCHECK(profile); - spellcheckChecked_ = - profile->GetPrefs()->GetBoolean(prefs::kEnableContinuousSpellcheck); NSCellStateValue checkedState = - spellcheckChecked_ ? NSOnState : NSOffState; + profile->GetPrefs()->GetBoolean(prefs::kEnableContinuousSpellcheck) ? + NSOnState : NSOffState; [(id)item setState:checkedState]; } - *valid = spellcheckEnabled_; + *valid = YES; return YES; } @@ -254,11 +208,6 @@ !pref->GetBoolean(prefs::kEnableContinuousSpellcheck)); } -- (void)spellCheckEnabled:(BOOL)enabled checked:(BOOL)checked { - spellcheckEnabled_ = enabled; - spellcheckChecked_ = checked; -} - // END Spellchecking methods @end
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc index 35e9c65..47eca0f 100644 --- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc +++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -98,8 +98,7 @@ } private: - void VerifyValue(content::TextInputManagerTester* text_input_manager_tester) { - ASSERT_EQ(tester(), text_input_manager_tester); + void VerifyValue() { std::string value; if (tester()->GetTextInputValue(&value) && expected_value_ == value) OnSuccess(); @@ -122,8 +121,7 @@ } private: - void VerifyType(content::TextInputManagerTester* text_input_manager_tester) { - ASSERT_EQ(tester(), text_input_manager_tester); + void VerifyType() { ui::TextInputType type = tester()->GetTextInputType(&type) ? type : ui::TEXT_INPUT_TYPE_NONE; if (expected_type_ == type) @@ -145,9 +143,7 @@ } private: - void VerifyChange( - content::TextInputManagerTester* text_input_manager_tester) { - ASSERT_EQ(tester(), text_input_manager_tester); + void VerifyChange() { if (tester()->IsTextInputStateChanged()) OnSuccess(); } @@ -170,7 +166,7 @@ } private: - void VerifyType(content::TextInputManagerTester* tester) { + void VerifyType() { ui::TextInputType type; if (!content::GetTextInputTypeForView(web_contents_, view_, &type)) return; @@ -185,6 +181,31 @@ DISALLOW_COPY_AND_ASSIGN(ViewTextInputTypeObserver); }; +// This class observes the |expected_view| for the first change in its +// selection bounds. +class ViewSelectionBoundsChangedObserver : public TextInputManagerObserverBase { + public: + ViewSelectionBoundsChangedObserver( + content::WebContents* web_contents, + content::RenderWidgetHostView* expected_view) + : TextInputManagerObserverBase(web_contents), + expected_view_(expected_view) { + tester()->SetOnSelectionBoundsChangedCallback( + base::Bind(&ViewSelectionBoundsChangedObserver::VerifyChange, + base::Unretained(this))); + } + + private: + void VerifyChange() { + if (expected_view_ == tester()->GetUpdatedView()) + OnSuccess(); + } + + const content::RenderWidgetHostView* const expected_view_; + + DISALLOW_COPY_AND_ASSIGN(ViewSelectionBoundsChangedObserver); +}; + } // namespace // Main class for all TextInputState and IME related tests. @@ -456,6 +477,44 @@ reset_state_observer.Wait(); } +// This test creates a page with multiple child frames and adds an <input> to +// each frame. Then, sequentially, each <input> is focused by sending a tab key. +// Then, after |TextInputState.type| for a view is changed to text, another key +// is pressed (a character) and then the test verifies that TextInputManager +// receives the corresponding update on the change in selection bounds on the +// browser side. +IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest, + TrackSelectionBoundsForChildFrames) { + CreateIframePage("a(b,c(a,b),d)"); + std::vector<content::RenderFrameHost*> frames{ + GetFrame(IndexVector{}), GetFrame(IndexVector{0}), + GetFrame(IndexVector{1}), GetFrame(IndexVector{1, 0}), + GetFrame(IndexVector{1, 1}), GetFrame(IndexVector{2})}; + std::vector<content::RenderWidgetHostView*> views; + for (auto frame : frames) + views.push_back(frame->GetView()); + for (size_t i = 0; i < frames.size(); ++i) + AddInputFieldToFrame(frames[i], "text", "", true); + + content::WebContents* web_contents = active_contents(); + + auto send_tab_insert_text_wait_for_bounds_change = [&web_contents]( + content::RenderWidgetHostView* view) { + ViewTextInputTypeObserver type_observer(web_contents, view, + ui::TEXT_INPUT_TYPE_TEXT); + SimulateKeyPress(web_contents, ui::DomKey::TAB, ui::DomCode::TAB, + ui::VKEY_TAB, false, false, false, false); + type_observer.Wait(); + ViewSelectionBoundsChangedObserver bounds_observer(web_contents, view); + SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('E'), + ui::DomCode::US_E, ui::VKEY_E, false, false, false, false); + bounds_observer.Wait(); + }; + + for (auto view : views) + send_tab_insert_text_wait_for_bounds_change(view); +} + // TODO(ekaramad): The following tests are specifically written for Aura and are // based on InputMethodObserver. Write similar tests for Mac/Android/Mus // (crbug.com/602723).
diff --git a/chrome/browser/resources/chromeos/chromevox/common/key_util.js b/chrome/browser/resources/chromeos/chromevox/common/key_util.js index e823efe..1f64d1c 100644 --- a/chrome/browser/resources/chromeos/chromevox/common/key_util.js +++ b/chrome/browser/resources/chromeos/chromevox/common/key_util.js
@@ -118,7 +118,8 @@ util.prevKeySequence && keySequence.equals(util.prevKeySequence)) { var prevTime = util.modeKeyPressTime; - if (prevTime > 0 && currTime - prevTime < 300) { // Double tap + var delta = currTime - prevTime; + if (prevTime > 0 && delta > 100 && delta < 300) { // Double tap keySequence = util.prevKeySequence; keySequence.doubleTap = true; util.prevKeySequence = null;
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index 5b59259..453b1d2 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -149,7 +149,6 @@ chrome.accessibilityPrivate.onAccessibilityGesture.addListener( this.onAccessibilityGesture_); - Notifications.onStartup(); }; /** @@ -338,7 +337,6 @@ 'switch_to_next' : 'switch_to_classic'); cvox.ChromeVox.tts.speak( announce, cvox.QueueMode.FLUSH, {doNotInterrupt: true}); - Notifications.onModeChange(); // If the new mode is Classic, return false now so we don't announce // anything more.
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/notifications.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/notifications.js index 55e4688..cc6e387 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/notifications.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/notifications.js
@@ -74,7 +74,6 @@ * Runs notifications that should be shown for startup. */ Notifications.onStartup = function() { - return; // Only run on background page. if (document.location.href.indexOf('background.html') == -1) return; @@ -88,7 +87,6 @@ * Runs notifications that should be shown for mode changes. */ Notifications.onModeChange = function() { - return; // Only run on background page. if (document.location.href.indexOf('background.html') == -1) return;
diff --git a/chrome/browser/resources/local_ntp/most_visited_util.js b/chrome/browser/resources/local_ntp/most_visited_util.js index ebf6513..50c089b0 100644 --- a/chrome/browser/resources/local_ntp/most_visited_util.js +++ b/chrome/browser/resources/local_ntp/most_visited_util.js
@@ -284,7 +284,7 @@ data = apiHandle.getMostVisitedItemData(params.rid); if (!data) return; - data.tileSource: NTPLoggingTileSource.CLIENT; + data.tileSource = NTPLoggingTileSource.CLIENT; } if (isFinite(params.dummy) && parseInt(params.dummy, 10)) {
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/md_history/app.html index 4a170c97..a3da52df 100644 --- a/chrome/browser/resources/md_history/app.html +++ b/chrome/browser/resources/md_history/app.html
@@ -1,4 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/cr/ui.html"> +<link rel="import" href="chrome://resources/html/cr/ui/command.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <link rel="import" href="chrome://history/history_toolbar.html"> <link rel="import" href="chrome://history/list_container.html">
diff --git a/chrome/browser/resources/md_history/app.js b/chrome/browser/resources/md_history/app.js index 721e621..6d3f5d4 100644 --- a/chrome/browser/resources/md_history/app.js +++ b/chrome/browser/resources/md_history/app.js
@@ -57,6 +57,10 @@ /** @override */ ready: function() { this.grouped_ = loadTimeData.getBoolean('groupByDomain'); + + cr.ui.decorate('command', cr.ui.Command); + document.addEventListener('canExecute', this.onCanExecute_.bind(this)); + document.addEventListener('command', this.onCommand_.bind(this)); }, /** @private */ @@ -85,18 +89,8 @@ toolbar.count = 0; }, - /** - * Listens for call to delete all selected items and loops through all items - * to determine which ones are selected and deletes these. - */ deleteSelected: function() { - if (!loadTimeData.getBoolean('allowDeletingHistory')) - return; - - // TODO(hsampson): add a popup to check whether the user definitely - // wants to delete the selected items. - /** @type {HistoryListContainerElement} */ (this.$['history']) - .deleteSelected(); + this.$.history.deleteSelectedWithPrompt(); }, /** @@ -120,6 +114,23 @@ searchDomain_: function(e) { this.$.toolbar.setSearchTerm(e.detail.domain); }, /** + * @param {Event} e + * @private + */ + onCanExecute_: function(e) { + e.canExecute = true; + }, + + /** + * @param {Event} e + * @private + */ + onCommand_: function(e) { + if (e.command.id == 'find-command') + this.$.toolbar.showSearchField(); + }, + + /** * @param {!Array<!ForeignSession>} sessionList Array of objects describing * the sessions from other devices. * @param {boolean} isTabSyncEnabled Is tab sync enabled for this profile?
diff --git a/chrome/browser/resources/md_history/compiled_resources2.gyp b/chrome/browser/resources/md_history/compiled_resources2.gyp index 44c5c5ab..cfc189a 100644 --- a/chrome/browser/resources/md_history/compiled_resources2.gyp +++ b/chrome/browser/resources/md_history/compiled_resources2.gyp
@@ -90,6 +90,7 @@ 'target_name': 'app', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util', + '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:command', 'constants', 'history_toolbar', 'list_container',
diff --git a/chrome/browser/resources/md_history/history.html b/chrome/browser/resources/md_history/history.html index f7b9dba..3178400 100644 --- a/chrome/browser/resources/md_history/history.html +++ b/chrome/browser/resources/md_history/history.html
@@ -69,6 +69,13 @@ <span id="loading-message">$i18n{loading}</span> </div> +<if expr="is_macosx"> + <command id="find-command" shortcut="Meta|f /"> +</if> +<if expr="not is_macosx"> + <command id="find-command" shortcut="Ctrl|f /"> +</if> + <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/html/load_time_data.html">
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html index c1a33dc2..0c0a971 100644 --- a/chrome/browser/resources/md_history/history_item.html +++ b/chrome/browser/resources/md_history/history_item.html
@@ -70,6 +70,7 @@ @apply(--layout-center); @apply(--layout-flex); @apply(--layout-horizontal); + height: var(--item-height); overflow: hidden; }
diff --git a/chrome/browser/resources/md_history/history_list.js b/chrome/browser/resources/md_history/history_list.js index 58a3cfe..ba35812 100644 --- a/chrome/browser/resources/md_history/history_list.js +++ b/chrome/browser/resources/md_history/history_list.js
@@ -189,7 +189,9 @@ /** * Performs a request to the backend to delete all selected items. If - * successful, removes them from the view. + * successful, removes them from the view. Does not prompt the user before + * deleting -- see <history-list-container> for a version of this method which + * does prompt. */ deleteSelected: function() { var toBeRemoved = this.historyData_.filter(function(item) {
diff --git a/chrome/browser/resources/md_history/history_toolbar.js b/chrome/browser/resources/md_history/history_toolbar.js index 13f9c35d..d9e85ec 100644 --- a/chrome/browser/resources/md_history/history_toolbar.js +++ b/chrome/browser/resources/md_history/history_toolbar.js
@@ -96,6 +96,12 @@ this.fire('delete-selected'); }, + showSearchField: function() { + /** @type {!CrToolbarElement} */(this.$['main-toolbar']) + .getSearchField() + .showAndFocus(); + }, + /** * If the user is a supervised user the delete button is not shown. * @private
diff --git a/chrome/browser/resources/md_history/list_container.html b/chrome/browser/resources/md_history/list_container.html index bf01abe..eff450f5 100644 --- a/chrome/browser/resources/md_history/list_container.html +++ b/chrome/browser/resources/md_history/list_container.html
@@ -1,11 +1,13 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <link rel="import" href="chrome://history/grouped_list.html"> <link rel="import" href="chrome://history/history_list.html"> <dom-module id="history-list-container"> <template> - <style> + <style include="cr-shared-style"> :host { display: block; height: 100%; @@ -16,6 +18,10 @@ #content > * { height: 100%; } + + #dialog .body { + white-space: pre-wrap; + } </style> <iron-pages id="content" attr-for-selected="id" selected="[[selectedPage_]]"> @@ -29,8 +35,21 @@ searched-term="[[queryResult.info.term]]"> </history-grouped-list> </template> - </template> </iron-pages> + + <cr-dialog id="dialog"> + <div class="title">$i18n{removeSelected}</div> + <div class="body">$i18n{deleteWarning}</div> + <div class="button-container"> + <paper-button class="cancel-button" on-tap="onDialogCancelTap_"> + $i18n{cancel} + </paper-button> + <paper-button class="action-button" on-tap="onDialogConfirmTap_" + autofocus> + $i18n{deleteConfirm} + </paper-button> + </div> + </cr-dialog> </template> <script src="chrome://history/list_container.js"></script> </dom-module>
diff --git a/chrome/browser/resources/md_history/list_container.js b/chrome/browser/resources/md_history/list_container.js index 76cb2f5e..f8bbac0 100644 --- a/chrome/browser/resources/md_history/list_container.js +++ b/chrome/browser/resources/md_history/list_container.js
@@ -83,9 +83,15 @@ .unselectAllItems(count); }, - deleteSelected: function() { - /** @type {HistoryListElement} */ (this.$['infinite-list']) - .deleteSelected(); + /** + * Delete all the currently selected history items. Will prompt the user with + * a dialog to confirm that the deletion should be performed. + */ + deleteSelectedWithPrompt: function() { + if (!loadTimeData.getBoolean('allowDeletingHistory')) + return; + + this.$.dialog.open(); }, /** @@ -131,4 +137,15 @@ } } }, + + /** @private */ + onDialogConfirmTap_: function() { + this.$['infinite-list'].deleteSelected(); + this.$.dialog.close(); + }, + + /** @private */ + onDialogCancelTap_: function() { + this.$.dialog.close(); + } });
diff --git a/chrome/browser/resources/print_preview/print_header.js b/chrome/browser/resources/print_preview/print_header.js index 51f25e7..4eec37f 100644 --- a/chrome/browser/resources/print_preview/print_header.js +++ b/chrome/browser/resources/print_preview/print_header.js
@@ -188,20 +188,25 @@ var html; var label; if (numPages != numSheets) { - html = loadTimeData.getStringF('printPreviewSummaryFormatLong', - '<b>' + numSheets + '</b>', - '<b>' + summaryLabel + '</b>', - numPages, - pagesLabel); + html = loadTimeData.getStringF( + 'printPreviewSummaryFormatLong', + '<b>' + numSheets.toLocaleString() + '</b>', + '<b>' + summaryLabel + '</b>', + numPages.toLocaleString(), + pagesLabel); label = loadTimeData.getStringF('printPreviewSummaryFormatLong', - numSheets, summaryLabel, - numPages, pagesLabel); + numSheets.toLocaleString(), + summaryLabel, + numPages.toLocaleString(), + pagesLabel); } else { - html = loadTimeData.getStringF('printPreviewSummaryFormatShort', - '<b>' + numSheets + '</b>', - '<b>' + summaryLabel + '</b>'); + html = loadTimeData.getStringF( + 'printPreviewSummaryFormatShort', + '<b>' + numSheets.toLocaleString() + '</b>', + '<b>' + summaryLabel + '</b>'); label = loadTimeData.getStringF('printPreviewSummaryFormatShort', - numSheets, summaryLabel); + numSheets.toLocaleString(), + summaryLabel); } // Removing extra spaces from within the string.
diff --git a/chrome/browser/resources/settings/animation/animation.html b/chrome/browser/resources/settings/animation/animation.html new file mode 100644 index 0000000..ecff82f --- /dev/null +++ b/chrome/browser/resources/settings/animation/animation.html
@@ -0,0 +1,3 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/cr/event_target.html"> +<script src="/animation/animation.js"></script>
diff --git a/chrome/browser/resources/settings/animation/animation.js b/chrome/browser/resources/settings/animation/animation.js new file mode 100644 index 0000000..7e07a99 --- /dev/null +++ b/chrome/browser/resources/settings/animation/animation.js
@@ -0,0 +1,92 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Simplified API wrapping native Web Animations with some sugar. + * A compromise between the draft spec and Chrome's evolving support. This API + * will be changed (or removed) as Chrome support evolves. + */ +cr.define('settings.animation', function() { + 'use strict'; + + /** + * Default timing constants. + * @const + */ + var Timing = { + DURATION: 250, + EASING: 'cubic-bezier(0.4, 0, 0.2, 1)', // Fast out, slow in. + }; + + /** + * Offers a small subset of the v1 Animation interface. The underlying + * animation can be reversed, canceled or immediately finished. + * @see https://www.w3.org/TR/web-animations-1/#animation + * + * @constructor + * @extends {cr.EventTarget} + * @param {!Element} el The element to animate. + * @param {!Array<!Object>|!Object<!Array>|!Object<string>} keyframes + * Keyframes, as in Element.prototype.animate. + * @param {number|!KeyframeEffectOptions=} opt_options Duration or options + * object, as in Element.prototype.animate. + */ + function Animation(el, keyframes, opt_options) { + // Disallow direct usage of the underlying animation. + this.animation_ = el.animate(keyframes, opt_options); + + var self = this; + /** @type {!Promise} */ + this.finished = new Promise(function(resolve, reject) { + // If we were implementing the full spec, we'd have to support + // removing or resetting these listeners. + self.animation_.addEventListener('finish', function(e) { + resolve(); + // According to the spec, queue a task to fire the event after + // resolving the promise. + self.queueDispatch_(e); + }); + self.animation_.addEventListener('cancel', function(e) { + reject(new + /** + * @see https://heycam.github.io/webidl/#es-DOMException-call + * @type {function (new:DOMException, string, string)} + */( + DOMException + )('', 'AbortError')); + self.queueDispatch_(e); + }); + }); + } + + Animation.prototype = { + __proto__: cr.EventTarget.prototype, + + finish: function() { + assert(this.animation_); + this.animation_.finish(); + }, + + cancel: function() { + assert(this.animation_); + this.animation_.cancel(); + }, + + /** + * @param {!Event} e + * @private + */ + queueDispatch_: function(e) { + setTimeout(function() { + this.dispatchEvent(e); + this.animation_ = undefined; + }.bind(this)); + }, + }; + + return { + Animation: Animation, + Timing: Timing, + }; +});
diff --git a/chrome/browser/resources/settings/animation/compiled_resources2.gyp b/chrome/browser/resources/settings/animation/compiled_resources2.gyp new file mode 100644 index 0000000..89d95422 --- /dev/null +++ b/chrome/browser/resources/settings/animation/compiled_resources2.gyp
@@ -0,0 +1,16 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'animation', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:event_target', + '<(EXTERNS_GYP):web_animations', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + ], +}
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html index 31c06fc..aab329c73d 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -22,16 +22,22 @@ visibility: hidden; } + #dialog .button-container { + border-top: 1px solid rgba(0, 0, 0, 0.14); + margin-top: 0; + padding-top: 10px; + } + + #dialog .footer { + background-color: #fff; + } + .row { align-items: center; display: flex; min-height: 40px; } - .row .start { - flex: 1; - } - paper-spinner { -webkit-margin-end: 16px; margin-bottom: auto; @@ -85,6 +91,17 @@ display: none; }; } + + #clearFrom { + display: inline; + } + + /* Cap the height on smaller screens to avoid unfavorable clipping. */ + @media screen and (max-height: 714px) { + .body { + max-height: 270px; + } + } </style> <!-- #notice correctly places its own backdrop above #dialog and under @@ -93,11 +110,13 @@ <div class="title">$i18n{clearBrowsingData}</div> <div class="body"> <div class="row"> - <span class="start">$i18n{clearFollowingItemsFrom}</span> - <settings-dropdown-menu id="clearFrom" - pref="{{prefs.browser.clear_data.time_period}}" - menu-options="[[clearFromOptions_]]" no-label-float> - </settings-dropdown-menu> + <span> + $i18n{clearFollowingItemsFrom} + <settings-dropdown-menu id="clearFrom" + pref="{{prefs.browser.clear_data.time_period}}" + menu-options="[[clearFromOptions_]]" no-label-float> + </settings-dropdown-menu> + </span> </div> <settings-checkbox id="browsingCheckbox" pref="{{prefs.browser.clear_data.browsing_history}}"
diff --git a/chrome/browser/resources/settings/compiled_resources2.gyp b/chrome/browser/resources/settings/compiled_resources2.gyp index 664d925e..ba6aece 100644 --- a/chrome/browser/resources/settings/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/compiled_resources2.gyp
@@ -10,6 +10,7 @@ 'a11y_page/compiled_resources2.gyp:*', 'about_page/compiled_resources2.gyp:*', 'advanced_page/compiled_resources2.gyp:*', + 'animation/compiled_resources2.gyp:*', 'appearance_page/compiled_resources2.gyp:*', 'basic_page/compiled_resources2.gyp:*', 'bluetooth_page/compiled_resources2.gyp:*', @@ -56,5 +57,12 @@ ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, + { + 'target_name': 'search_settings', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, ], }
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html index 716072b..89654d1 100644 --- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html +++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
@@ -9,31 +9,7 @@ <dom-module id="settings-dropdown-menu"> <template> <style include="settings-shared"> - .item { - align-items: center; - color: var(--paper-grey-800); - display: flex; - font-size: inherit; - min-height: 48px; - padding: 0 16px; - } - - .item:focus { - background-color: var(--paper-grey-300); - outline: none; - } - - paper-dropdown-menu { - --iron-icon-fill-color: var(--paper-grey-600); - --paper-font-subhead: { - font-size: inherit; - }; - --paper-input-container-underline: { - background: var(--paper-grey-300); - }; - width: 160px; - } - </style> + </style> <paper-dropdown-menu id="dropdownMenu" label="[[menuLabel_]]" on-iron-select="onSelect_" no-label-float$="[[noLabelFloat]]" disabled="[[shouldDisableMenu_(disabled, menuOptions.*)]]"> @@ -42,11 +18,12 @@ <template is="dom-repeat" items="[[menuOptions]]" initial-count="5"> <!--TODO(dpapad): Use <button class="paper-item">..</button> once it lands in paper-item-shared-styles.html--> - <div class="item" role="option" data-value$="[[item.value]]"> + <div class="dropdown-item" role="option" data-value$="[[item.value]]"> [[item.name]] </div> </template> - <div class="item" role="option" data-value$="[[notFoundValue_]]" + <div class="dropdown-item" role="option" + data-value$="[[notFoundValue_]]" hidden$="[[!isSelectedNotFound_(selected_)]]"> $i18n{custom} </div>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 186946de..42a8d2d0 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -4,7 +4,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html index eb12862..675c940 100644 --- a/chrome/browser/resources/settings/search_page/search_page.html +++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -12,28 +12,6 @@ <dom-module id="settings-search-page"> <template> <style include="settings-shared"> - paper-dropdown-menu { - /* TODO(dschuyler): share styling with settings-dropdown-menu */ - --iron-icon-fill-color: var(--paper-grey-600); - } - - paper-listbox div { - align-items: center; - color: var(--paper-grey-800); - display: flex; - font-size: inherit; - min-height: 48px; - padding: 0 16px; - } - - paper-listbox div.iron-selected { - font-weight: bold; - } - - paper-listbox div:focus { - background-color: var(--paper-grey-300); - outline: none; - } </style> <settings-animated-pages id="pages" current-route="{{currentRoute}}" section="search"> @@ -47,7 +25,7 @@ <template is="dom-repeat" items="[[searchEngines_]]"> <!--TODO(dpapad): Use <button class="paper-item">..</button> once it lands in paper-item-shared-styles.html--> - <div role="option">[[item.name]]</div> + <div class="dropdown-item" role="option">[[item.name]]</div> </template> </paper-listbox> </paper-dropdown-menu>
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js new file mode 100644 index 0000000..53d5d22 --- /dev/null +++ b/chrome/browser/resources/settings/search_settings.js
@@ -0,0 +1,195 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('settings', function() { + /** @const {string} */ + var WRAPPER_CSS_CLASS = 'search-highlight-wrapper'; + + /** @const {string} */ + var HIT_CSS_CLASS = 'search-highlight-hit'; + + /** @const {!RegExp} */ + var SANITIZE_REGEX = /[-[\]{}()*+?.,\\^$|#\s]/g; + + /** + * List of elements types that should not be searched at all. + * The only DOM-MODULE node is in <body> which is not searched, therefore + * DOM-MODULE is not needed in this set. + * @const {!Set<string>} + */ + var IGNORED_ELEMENTS = new Set([ + 'CONTENT', + 'CR-EVENTS', + 'IMG', + 'IRON-ICON', + 'IRON-LIST', + 'PAPER-ICON-BUTTON', + /* TODO(dpapad): paper-item is used for dynamically populated dropdown + * menus. Perhaps a better approach is to mark the entire dropdown menu such + * that search algorithm can skip it as a whole instead. + */ + 'PAPER-ITEM', + 'PAPER-RIPPLE', + 'PAPER-SLIDER', + 'PAPER-SPINNER', + 'STYLE', + 'TEMPLATE', + ]); + + /** + * Finds all previous highlighted nodes under |node| (both within self and + * children's Shadow DOM) and removes the highlight (yellow rectangle). + * @param {!Node} node + * @private + */ + function findAndRemoveHighlights_(node) { + var wrappers = node.querySelectorAll('* /deep/ .' + WRAPPER_CSS_CLASS); + + for (var wrapper of wrappers) { + var hitElements = wrapper.querySelectorAll('.' + HIT_CSS_CLASS); + // For each hit element, remove the highlighting. + for (var hitElement of hitElements) { + wrapper.replaceChild(hitElement.firstChild, hitElement); + } + + // Normalize so that adjacent text nodes will be combined. + wrapper.normalize(); + // Restore the DOM structure as it was before the search occurred. + if (wrapper.previousSibling) + wrapper.textContent = ' ' + wrapper.textContent; + if (wrapper.nextSibling) + wrapper.textContent = wrapper.textContent + ' '; + + wrapper.parentElement.replaceChild(wrapper.firstChild, wrapper); + } + } + + /** + * Applies the highlight UI (yellow rectangle) around all matches in |node|. + * @param {!Node} node The text node to be highlighted. |node| ends up + * being removed from the DOM tree. + * @param {!Array<string>} tokens The string tokens after splitting on the + * relevant regExp. Even indices hold text that doesn't need highlighting, + * odd indices hold the text to be highlighted. For example: + * var r = new RegExp('(foo)', 'i'); + * 'barfoobar foo bar'.split(r) => ['bar', 'foo', 'bar ', 'foo', ' bar'] + * @private + */ + function highlight_(node, tokens) { + var wrapper = document.createElement('span'); + wrapper.classList.add(WRAPPER_CSS_CLASS); + // Use existing node as placeholder to determine where to insert the + // replacement content. + node.parentNode.replaceChild(wrapper, node); + + for (var i = 0; i < tokens.length; ++i) { + if (i % 2 == 0) { + wrapper.appendChild(document.createTextNode(tokens[i])); + } else { + var span = document.createElement('span'); + span.classList.add(HIT_CSS_CLASS); + span.style.backgroundColor = 'yellow'; + span.textContent = tokens[i]; + wrapper.appendChild(span); + } + } + } + + /** + * Traverses the entire DOM (including Shadow DOM), finds text nodes that + * match the given regular expression and applies the highlight UI. It also + * ensures that <settings-section> instances become visible if any matches + * occurred under their subtree. + * + * @param {!Element} page The page to be searched, should be either + * <settings-basic-page> or <settings-advanced-page>. + * @param {!RegExp} regExp The regular expression to detect matches. + * @private + */ + function findAndHighlightMatches_(page, regExp) { + function doSearch(node) { + if (IGNORED_ELEMENTS.has(node.tagName)) + return; + + if (node.nodeType == Node.TEXT_NODE) { + var textContent = node.nodeValue.trim(); + if (textContent.length == 0) + return; + + if (regExp.test(textContent)) { + revealParentSection_(node); + highlight_(node, textContent.split(regExp)); + } + // Returning early since TEXT_NODE nodes never have children. + return; + } + + var child = node.firstChild; + while (child !== null) { + // Getting a reference to the |nextSibling| before calling doSearch() + // because |child| could be removed from the DOM within doSearch(). + var nextSibling = child.nextSibling; + doSearch(child); + child = nextSibling; + } + + var shadowRoot = node.shadowRoot; + if (shadowRoot) + doSearch(shadowRoot); + } + + doSearch(page); + } + + /** + * Finds and makes visible the <settings-section> parent of |node|. + * @param {!Node} node + */ + function revealParentSection_(node) { + // Find corresponding SETTINGS-SECTION parent and make it visible. + var parent = node; + while (parent && parent.tagName !== 'SETTINGS-SECTION') { + parent = parent.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? + parent.host : parent.parentNode; + } + if (parent) + parent.hidden = false; + } + + /** + * @param {!Element} page + * @param {boolean} visible + * @private + */ + function setSectionsVisibility_(page, visible) { + var sections = Polymer.dom(page.root).querySelectorAll('settings-section'); + for (var i = 0; i < sections.length; i++) + sections[i].hidden = !visible; + } + + /** + * Performs hierarchical search, starting at the given page element. + * @param {string} text + * @param {!Element} page Must be either <settings-basic-page> or + * <settings-advanced-page>. + */ + function search(text, page) { + findAndRemoveHighlights_(page); + + // Generate search text by escaping any characters that would be problematic + // for regular expressions. + var searchText = text.trim().replace(SANITIZE_REGEX, '\\$&'); + if (searchText.length == 0) { + setSectionsVisibility_(page, true); + return; + } + + setSectionsVisibility_(page, false); + findAndHighlightMatches_(page, new RegExp('(' + searchText + ')', 'i')); + } + + return { + search: search, + }; +});
diff --git a/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp b/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp index c405595..d17a3d8 100644 --- a/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp
@@ -14,8 +14,10 @@ { 'target_name': 'settings_main', 'dependencies': [ - 'settings_main_rendered', + '../compiled_resources2.gyp:search_settings', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:promise_resolver', + 'settings_main_rendered', '../settings_page/compiled_resources2.gyp:main_page_behavior', '../settings_page/compiled_resources2.gyp:settings_router', ],
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html index 2256024..990c85c 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.html +++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -62,4 +62,5 @@ </template> </template> <script src="settings_main.js"></script> + <script src="/search_settings.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js index 254f261..75daea4 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.js +++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -59,6 +59,7 @@ }, }, + /** @override */ created: function() { /** @private {!PromiseResolver} */ this.resolver_ = new PromiseResolver; @@ -129,4 +130,36 @@ toggleAdvancedPage_: function() { this.fire('toggle-advanced-page', !this.isAdvancedMenuOpen_); }, + + /** + * Navigates to the default search page (if necessary). + * @private + */ + ensureInDefaultSearchPage_: function() { + if (this.currentRoute.page != 'basic' || + this.currentRoute.section != '' || + this.currentRoute.subpage.length != 0) { + this.currentRoute = {page: 'basic', section: '', subpage: [], url: ''}; + } + }, + + /** + * @param {string} query + */ + searchContents: function(query) { + this.ensureInDefaultSearchPage_(); + + // Trigger rendering of the basic and advanced pages and search once ready. + // Even if those are already rendered, yield to the message loop before + // initiating searching. + this.showBasicPage_ = true; + setTimeout(function() { + settings.search(query, assert(this.$$('settings-basic-page'))); + }.bind(this), 0); + + this.showAdvancedPage_ = true; + setTimeout(function() { + settings.search(query, assert(this.$$('settings-advanced-page'))); + }.bind(this), 0); + }, });
diff --git a/chrome/browser/resources/settings/settings_menu/compiled_resources2.gyp b/chrome/browser/resources/settings/settings_menu/compiled_resources2.gyp index 287f194..295dcc2 100644 --- a/chrome/browser/resources/settings/settings_menu/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/settings_menu/compiled_resources2.gyp
@@ -6,6 +6,7 @@ { 'target_name': 'settings_menu', 'dependencies': [ + '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-ripple/compiled_resources2.gyp:paper-ripple-extracted', '../settings_page/compiled_resources2.gyp:settings_router', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html index a0eb44a3..adad5296 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.html +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-submenu.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html"> <link rel="import" href="/icons.html"> <link rel="import" href="/settings_shared_css.html"> @@ -53,6 +54,15 @@ }; } + paper-menu div { + position: relative; /* Needed for paper-ripple. */ + } + + paper-ripple { + color: var(--google-blue-500); + opacity: .5; + } + .page-menu paper-menu { --paper-menu-selected-item: { color: var(--google-blue-500);
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.js b/chrome/browser/resources/settings/settings_menu/settings_menu.js index d2a4c905..016b1a8 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.js +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.js
@@ -63,10 +63,25 @@ }, /** + * @param {!Node} target + * @private + */ + ripple_: function(target) { + var ripple = document.createElement('paper-ripple'); + ripple.addEventListener('transitionend', function() { + ripple.remove(); + }); + target.appendChild(ripple); + ripple.downAction(); + ripple.upAction(); + }, + + /** * @param {!Event} event * @private */ openPage_: function(event) { + this.ripple_(/** @type {!Node} */(event.currentTarget)); var submenuRoute = event.currentTarget.parentNode.dataset.page; if (submenuRoute) { this.currentRoute = {
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index be6ba8c..61b8218 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -72,6 +72,12 @@ <structure name="IDR_SETTINGS_ALL_SITES_JS" file="site_settings/all_sites.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_ANIMATION_ANIMATION_HTML" + file="animation/animation.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_ANIMATION_ANIMATION_JS" + file="animation/animation.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_HTML" file="settings_page/settings_animated_pages.html" type="chrome_html" /> @@ -128,6 +134,9 @@ <structure name="IDR_SETTINGS_ON_STARTUP_PAGE_JS" file="on_startup_page/on_startup_page.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_SEARCH_SETTINGS_JS" + file="search_settings.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_STARTUP_URLS_PAGE_HTML" file="on_startup_page/startup_urls_page.html" type="chrome_html" />
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index e3654ec..a04010c 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -27,6 +27,34 @@ background-color: var(--paper-grey-300); } + paper-dropdown-menu { + --iron-icon-fill-color: var(--paper-grey-600); + --paper-font-subhead: { + font-size: inherit; + }; + --paper-input-container-underline: { + background: var(--paper-grey-300); + }; + } + + paper-dropdown-menu .dropdown-item { + align-items: center; + color: var(--paper-grey-800); + display: flex; + font-size: inherit; + min-height: 48px; + padding: 0 16px; + } + + paper-dropdown-menu .dropdown-item.iron-selected { + font-weight: bold; + } + + paper-dropdown-menu .dropdown-item:focus { + background-color: var(--paper-grey-300); + outline: none; + } + span ~ a { -webkit-margin-start: 4px; }
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.html b/chrome/browser/resources/settings/settings_ui/settings_ui.html index f30394e7..ba3b499 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.html +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -3,7 +3,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/app-layout/app-drawer/app-drawer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html"> <link rel="import" href="/direction_delegate.html"> <link rel="import" href="/i18n_setup.html">
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js index a503726..162a0f0 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.js +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -57,6 +57,13 @@ this.$$('app-drawer').toggle(); }, + /** @override */ + ready: function() { + this.$$('cr-toolbar').addEventListener('search-changed', function(e) { + this.$$('settings-main').searchContents(e.detail); + }.bind(this)); + }, + /** @private */ directionDelegateChanged_: function() { this.$$('app-drawer').align = this.directionDelegate.isRtl() ?
diff --git a/chrome/browser/resources/settings/site_settings/media_picker.html b/chrome/browser/resources/settings/site_settings/media_picker.html index f7dd9dc1..733827e 100644 --- a/chrome/browser/resources/settings/site_settings/media_picker.html +++ b/chrome/browser/resources/settings/site_settings/media_picker.html
@@ -1,6 +1,5 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html"> <link rel="import" href="/settings_shared_css.html"> @@ -10,16 +9,6 @@ :host { display: block; } - - paper-dropdown-menu { - --paper-input-container-input: { - font-size: inherit; - }; - - --paper-font-caption: { - font-size: inherit; - } - } </style> <div class="settings-box" id="picker" hidden> <paper-dropdown-menu> @@ -27,9 +16,10 @@ attr-for-selected="media-picker-value" on-iron-activate="onMediaPickerActivate_"> <template is="dom-repeat" items="[[devices]]"> - <paper-item media-picker-value$="[[item.id]]"> + <div class="dropdown-item" role="option" + media-picker-value$="[[item.id]]"> [[item.name]] - </paper-item> + </div> </template> </paper-listbox> </paper-dropdown-menu>
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chrome/browser/resources/settings/site_settings/site_details_permission.html index 42c7b56a7..a18cbdc 100644 --- a/chrome/browser/resources/settings/site_settings/site_details_permission.html +++ b/chrome/browser/resources/settings/site_settings/site_details_permission.html
@@ -2,7 +2,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="/i18n_setup.html"> @@ -18,16 +17,6 @@ display: block; } - paper-dropdown-menu { - --paper-input-container-input: { - font-size: inherit; - }; - - --paper-font-caption: { - font-size: inherit; - } - } - .left-column { -webkit-margin-start: 15px; } @@ -71,14 +60,14 @@ <paper-listbox id="permission" class="dropdown-content" on-iron-activate="onPermissionMenuIronActivate_" attr-for-selected="data-permission-value"> - <paper-item id="allow" + <div id="allow" class="dropdown-item" role="option" data-permission-value$="[[PermissionValues.ALLOW]]"> [[i18n_.allowAction]] - </paper-item> - <paper-item id="block" + </div> + <div id="block" class="dropdown-item" role="option" data-permission-value$="[[PermissionValues.BLOCK]]"> [[i18n_.blockAction]] - </paper-item> + </div> </paper-listbox> </paper-dropdown-menu> </div>
diff --git a/chrome/browser/resources/settings/site_settings/site_list.html b/chrome/browser/resources/settings/site_settings/site_list.html index 2bbd65e..8a94d00e 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.html +++ b/chrome/browser/resources/settings/site_settings/site_list.html
@@ -82,11 +82,14 @@ </div> </template> - <div class="button-container"> - <paper-button on-tap="onAddSiteTap_" class="primary-button no-upper"> - $i18n{addSiteLink} - </paper-button> - </div> + <template is="dom-if" if="{{!allSites}}"> + <div class="button-container"> + <paper-button on-tap="onAddSiteTap_" + class="primary-button no-upper"> + $i18n{addSiteLink} + </paper-button> + </div> + </template> </div> </paper-submenu> </template>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html index 94a485b..16afa796 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -1,5 +1,4 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> <link rel="import" href="/icons.html"> <link rel="import" href="/settings_shared_css.html"> <link rel="import" href="/site_settings/constants.html">
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.cc b/chrome/browser/safe_browsing/safe_browsing_store_file.cc index b19cb236..35fe24a 100644 --- a/chrome/browser/safe_browsing/safe_browsing_store_file.cc +++ b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
@@ -407,17 +407,17 @@ container_merge(&add_prefixes_, beg.add_prefixes_iter_, end.add_prefixes_iter_, - SBAddPrefixLess<SBAddPrefix,SBAddPrefix>); + SBAddPrefixLess<SBAddPrefix, SBAddPrefix>); container_merge(&sub_prefixes_, beg.sub_prefixes_iter_, end.sub_prefixes_iter_, - SBAddPrefixLess<SBSubPrefix,SBSubPrefix>); + SBAddPrefixLess<SBSubPrefix, SBSubPrefix>); container_merge(&add_full_hashes_, beg.add_hashes_iter_, end.add_hashes_iter_, - SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>); + SBAddPrefixHashLess<SBAddFullHash, SBAddFullHash>); container_merge(&sub_full_hashes_, beg.sub_hashes_iter_, @@ -433,13 +433,13 @@ // operations. void SortData() { std::sort(add_prefixes_.begin(), add_prefixes_.end(), - SBAddPrefixLess<SBAddPrefix,SBAddPrefix>); + SBAddPrefixLess<SBAddPrefix, SBAddPrefix>); std::sort(sub_prefixes_.begin(), sub_prefixes_.end(), - SBAddPrefixLess<SBSubPrefix,SBSubPrefix>); + SBAddPrefixLess<SBSubPrefix, SBSubPrefix>); std::sort(add_full_hashes_.begin(), add_full_hashes_.end(), - SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>); + SBAddPrefixHashLess<SBAddFullHash, SBAddFullHash>); std::sort(sub_full_hashes_.begin(), sub_full_hashes_.end(), - SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>); + SBAddPrefixHashLess<SBSubFullHash, SBSubFullHash>); } // Iterator from the beginning of the state's data.
diff --git a/chrome/browser/services/gcm/fake_signin_manager.cc b/chrome/browser/services/gcm/fake_signin_manager.cc deleted file mode 100644 index aa72139..0000000 --- a/chrome/browser/services/gcm/fake_signin_manager.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/services/gcm/fake_signin_manager.h" - -#include "base/observer_list.h" -#include "build/build_config.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/account_tracker_service_factory.h" -#include "chrome/browser/signin/chrome_signin_client_factory.h" -#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" -#include "components/keyed_service/core/keyed_service.h" -#include "components/prefs/pref_service.h" -#include "components/signin/core/browser/account_tracker_service.h" -#include "components/signin/core/common/signin_pref_names.h" -#include "content/public/browser/browser_context.h" - -#if !defined(OS_CHROMEOS) -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#endif - -namespace gcm { - -FakeSigninManager::FakeSigninManager(Profile* profile) -#if defined(OS_CHROMEOS) - : SigninManagerBase( - ChromeSigninClientFactory::GetInstance()->GetForProfile(profile), - AccountTrackerServiceFactory::GetForProfile(profile)), -#else - : SigninManager( - ChromeSigninClientFactory::GetInstance()->GetForProfile(profile), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - AccountTrackerServiceFactory::GetForProfile(profile), - GaiaCookieManagerServiceFactory::GetForProfile(profile)), -#endif - profile_(profile) { - Initialize(NULL); -} - -FakeSigninManager::~FakeSigninManager() { -} - -void FakeSigninManager::SignIn(const std::string& account_id) { - SetAuthenticatedAccountId(account_id); - FOR_EACH_OBSERVER(SigninManagerBase::Observer, - observer_list_, - GoogleSigninSucceeded(account_id, account_id, - std::string())); -} - -void FakeSigninManager::SignOut( - signin_metrics::ProfileSignout signout_source_metric, - signin_metrics::SignoutDelete signout_delete_metric) { - const std::string account_id = GetAuthenticatedAccountId(); - const std::string username = GetAuthenticatedAccountInfo().email; - clear_authenticated_user(); - profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId); - FOR_EACH_OBSERVER(SigninManagerBase::Observer, - observer_list_, - GoogleSignedOut(account_id, username)); -} - -// static -KeyedService* FakeSigninManager::Build(content::BrowserContext* context) { - return new FakeSigninManager(Profile::FromBrowserContext(context)); -} - -} // namespace gcm
diff --git a/chrome/browser/services/gcm/fake_signin_manager.h b/chrome/browser/services/gcm/fake_signin_manager.h deleted file mode 100644 index 7320a54..0000000 --- a/chrome/browser/services/gcm/fake_signin_manager.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SERVICES_GCM_FAKE_SIGNIN_MANAGER_H_ -#define CHROME_BROWSER_SERVICES_GCM_FAKE_SIGNIN_MANAGER_H_ - -#include <string> - -#include "base/macros.h" -#include "build/build_config.h" -#include "components/signin/core/browser/signin_metrics.h" - -#if defined(OS_CHROMEOS) -#include "components/signin/core/browser/signin_manager_base.h" -#else -#include "base/compiler_specific.h" -#include "components/signin/core/browser/signin_manager.h" -#endif - -class KeyedService; -class Profile; - -namespace content { -class BrowserContext; -} - -namespace gcm { - -#if defined(OS_CHROMEOS) -class FakeSigninManager : public SigninManagerBase { -#else -class FakeSigninManager : public SigninManager { -#endif - - public: - explicit FakeSigninManager(Profile* profile); - ~FakeSigninManager() override; - - void SignIn(const std::string& username); -#if defined(OS_CHROMEOS) - void SignOut(signin_metrics::ProfileSignout signout_source_metric, - signin_metrics::SignoutDelete signout_delete_metric); -#else - void SignOut(signin_metrics::ProfileSignout signout_source_metric, - signin_metrics::SignoutDelete signout_delete_metric) override; -#endif - - static KeyedService* Build(content::BrowserContext* context); - - private: - Profile* profile_; - - DISALLOW_COPY_AND_ASSIGN(FakeSigninManager); -}; - -} // namespace gcm - -#endif // CHROME_BROWSER_SERVICES_GCM_FAKE_SIGNIN_MANAGER_H_
diff --git a/chrome/browser/ssl/chrome_security_state_model_client.cc b/chrome/browser/ssl/chrome_security_state_model_client.cc index 0c54067..6f242a4 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client.cc
@@ -114,7 +114,6 @@ if (!security_info.scheme_is_cryptographic) { return security_style; } - security_style_explanations->pkp_bypassed = security_info.pkp_bypassed; if (security_info.sha1_deprecation_status == SecurityStateModel::DEPRECATED_SHA1_MAJOR) { @@ -181,6 +180,14 @@ IDS_SECURE_PROTOCOL_AND_CIPHERSUITE_DESCRIPTION))); } + security_style_explanations->pkp_bypassed = security_info.pkp_bypassed; + if (security_info.pkp_bypassed) { + security_style_explanations->info_explanations.push_back( + content::SecurityStyleExplanation( + "Public-Key Pinning Bypassed", + "Public-key pinning was bypassed by a local root certificate.")); + } + return security_style; }
diff --git a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc index 16f0350..1a4cb852 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc
@@ -111,6 +111,7 @@ EXPECT_EQ(0u, expired_explanation.unauthenticated_explanations.size()); ASSERT_EQ(1u, expired_explanation.broken_explanations.size()); EXPECT_FALSE(expired_explanation.pkp_bypassed); + EXPECT_TRUE(expired_explanation.info_explanations.empty()); // Check that the summary and description are as expected. EXPECT_EQ(l10n_util::GetStringUTF8(IDS_CERTIFICATE_CHAIN_ERROR), @@ -644,6 +645,7 @@ const content::SecurityStyleExplanations& explanation = observer.latest_explanations(); EXPECT_TRUE(explanation.pkp_bypassed); + EXPECT_FALSE(explanation.info_explanations.empty()); } IN_PROC_BROWSER_TEST_F(PKPModelClientTest, PKPEnforced) { @@ -796,6 +798,7 @@ EXPECT_EQ(0u, observer.latest_explanations().secure_explanations.size()); EXPECT_FALSE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); @@ -818,6 +821,7 @@ VALID_CERTIFICATE, browser()); EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_TRUE(mixed_content_explanation.displayed_insecure_content); EXPECT_FALSE(mixed_content_explanation.ran_insecure_content); EXPECT_EQ(content::SECURITY_STYLE_UNAUTHENTICATED, @@ -838,6 +842,7 @@ INVALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); @@ -854,6 +859,7 @@ VALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); @@ -867,6 +873,7 @@ INVALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); @@ -884,6 +891,7 @@ INVALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); } @@ -917,6 +925,7 @@ VALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); @@ -942,6 +951,7 @@ INVALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); @@ -961,6 +971,7 @@ VALID_CERTIFICATE, browser()); EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic); EXPECT_FALSE(observer.latest_explanations().pkp_bypassed); + EXPECT_TRUE(observer.latest_explanations().info_explanations.empty()); EXPECT_FALSE(observer.latest_explanations().displayed_insecure_content); EXPECT_FALSE(observer.latest_explanations().ran_insecure_content); }
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index 298e804c..2d93d117 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -1045,13 +1045,7 @@ // Visit a HTTP page which request WSS connection to a server providing invalid // certificate. Close the page while WSS connection waits for SSLManager's // response from UI thread. -// Disabled on Windows because it was flaking on XP Tests (1). crbug.com/165258 -#if defined(OS_WIN) -#define MAYBE_TestWSSInvalidCertAndClose DISABLED_TestWSSInvalidCertAndClose -#else -#define MAYBE_TestWSSInvalidCertAndClose TestWSSInvalidCertAndClose -#endif -IN_PROC_BROWSER_TEST_F(SSLUITest, MAYBE_TestWSSInvalidCertAndClose) { +IN_PROC_BROWSER_TEST_F(SSLUITest, TestWSSInvalidCertAndClose) { ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(wss_server_expired_.Start());
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc index 756d7ac..34fc785 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -192,6 +192,14 @@ // Notify ProfileSyncService that we are done with configuration. FinishSyncSetup(); + if ((signin_type_ == SigninType::UI_SIGNIN) && + !login_ui_test_utils::DismissSyncConfirmationDialog( + chrome::FindBrowserWithProfile(profile_), + base::TimeDelta::FromSeconds(30))) { + LOG(ERROR) << "Failed to dismiss sync confirmation dialog."; + return false; + } + // Set an implicit passphrase for encryption if an explicit one hasn't already // been set. If an explicit passphrase has been set, immediately return false, // since a decryption passphrase is required.
diff --git a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc index a73aa4cb..1aa1f90 100644 --- a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
@@ -95,7 +95,7 @@ // Assert that the second client has the correct new URL. history::URLRows urls = GetTypedUrlsFromClient(1); ASSERT_EQ(initial_count + 1, urls.size()); - ASSERT_EQ(new_url, urls[urls.size() - 1].url()); + ASSERT_EQ(new_url, urls.back().url()); } IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, AddExpired) { @@ -183,7 +183,7 @@ // Assert that the second client has the correct new URL. history::URLRows urls = GetTypedUrlsFromClient(1); ASSERT_EQ(initial_count + 1, urls.size()); - ASSERT_EQ(new_url, urls[urls.size() - 1].url()); + ASSERT_EQ(new_url, urls.back().url()); // Delete from first client, and wait for them to sync. DeleteUrlFromHistory(0, new_url);
diff --git a/chrome/browser/ui/app_list/app_context_menu_unittest.cc b/chrome/browser/ui/app_list/app_context_menu_unittest.cc index dcecb117..e864e499 100644 --- a/chrome/browser/ui/app_list/app_context_menu_unittest.cc +++ b/chrome/browser/ui/app_list/app_context_menu_unittest.cc
@@ -219,20 +219,12 @@ if (!platform_app) { if (extensions::util::CanHostedAppsOpenInWindows() && extensions::util::IsNewBookmarkAppsEnabled()) { - // MACOS has different logic for this case. - // See chrome/browser/extensions/launch_util.cc for more details. - bool checked = launch_type == extensions::LAUNCH_TYPE_WINDOW; -#if !defined(OS_MACOSX) - checked |= launch_type == extensions::LAUNCH_TYPE_FULLSCREEN; -#endif + bool checked = launch_type == extensions::LAUNCH_TYPE_WINDOW || + launch_type == extensions::LAUNCH_TYPE_FULLSCREEN; states.push_back(MenuState( app_list::AppContextMenu::USE_LAUNCH_TYPE_WINDOW, true, checked)); } else if (!extensions::util::IsNewBookmarkAppsEnabled()) { bool regular_checked = launch_type == extensions::LAUNCH_TYPE_REGULAR; -#if defined(OS_MACOSX) - regular_checked |= (!extensions::util::CanHostedAppsOpenInWindows() && - launch_type == extensions::LAUNCH_TYPE_WINDOW); -#endif states.push_back(MenuState( app_list::AppContextMenu::USE_LAUNCH_TYPE_REGULAR, true,
diff --git a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc index bb0eb859..a604ba8 100644 --- a/chrome/browser/ui/app_list/app_list_controller_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_controller_browsertest.cc
@@ -125,16 +125,9 @@ DISALLOW_COPY_AND_ASSIGN(AppListControllerSearchResultsBrowserTest); }; - -// Flaky on Mac. https://crbug.com/415264 -#if defined(OS_MACOSX) -#define MAYBE_UninstallSearchResult DISABLED_UninstallSearchResult -#else -#define MAYBE_UninstallSearchResult UninstallSearchResult -#endif // Test showing search results, and uninstalling one of them while displayed. IN_PROC_BROWSER_TEST_F(AppListControllerSearchResultsBrowserTest, - MAYBE_UninstallSearchResult) { + UninstallSearchResult) { base::FilePath test_extension_path; ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_extension_path)); test_extension_path = test_extension_path.AppendASCII("extensions")
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate.cc b/chrome/browser/ui/app_list/app_list_controller_delegate.cc index dc4a95531..8127a3e2d 100644 --- a/chrome/browser/ui/app_list/app_list_controller_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
@@ -86,10 +86,6 @@ } bool AppListControllerDelegate::CanDoShowAppInfoFlow() { -#if defined(OS_MACOSX) - // Cocoa app list doesn't yet support the app info dialog. - return false; -#endif return CanShowAppInfoDialog(); }
diff --git a/chrome/browser/ui/app_list/app_list_service_cocoa_mac.h b/chrome/browser/ui/app_list/app_list_service_cocoa_mac.h deleted file mode 100644 index 8d11241c..0000000 --- a/chrome/browser/ui/app_list/app_list_service_cocoa_mac.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_COCOA_MAC_H_ -#define CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_COCOA_MAC_H_ - -#include "base/macros.h" -#include "chrome/browser/ui/app_list/app_list_service_mac.h" - -namespace test { -class AppListServiceMacTestApi; -} - -class AppListControllerDelegateImpl; -@class AppListWindowController; - -namespace base { -template <typename T> -struct DefaultSingletonTraits; -} // namespace base - -// AppListServiceCocoaMac shows and hides the Cocoa app list on Mac. -class AppListServiceCocoaMac : public AppListServiceMac { - public: - ~AppListServiceCocoaMac() override; - - static AppListServiceCocoaMac* GetInstance(); - - // AppListService overrides: - void ShowForProfile(Profile* requested_profile) override; - Profile* GetCurrentAppListProfile() override; - AppListControllerDelegate* GetControllerDelegate() override; - - // AppListServiceImpl overrides: - void CreateForProfile(Profile* requested_profile) override; - void DestroyAppList() override; - - protected: - // AppListServiceMac overrides: - NSWindow* GetNativeWindow() const override; - bool ReadyToShow() override; - - private: - friend class test::AppListServiceMacTestApi; - friend struct base::DefaultSingletonTraits<AppListServiceCocoaMac>; - - AppListServiceCocoaMac(); - - Profile* profile_; - base::scoped_nsobject<AppListWindowController> window_controller_; - std::unique_ptr<AppListControllerDelegateImpl> controller_delegate_; - - DISALLOW_COPY_AND_ASSIGN(AppListServiceCocoaMac); -}; - -#endif // CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_COCOA_MAC_H_
diff --git a/chrome/browser/ui/app_list/app_list_service_cocoa_mac.mm b/chrome/browser/ui/app_list/app_list_service_cocoa_mac.mm deleted file mode 100644 index 38b7c66..0000000 --- a/chrome/browser/ui/app_list/app_list_service_cocoa_mac.mm +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/app_list_service_cocoa_mac.h" - -#include "base/memory/singleton.h" -#include "chrome/browser/ui/app_list/app_list_controller_delegate_impl.h" -#include "chrome/browser/ui/app_list/app_list_view_delegate.h" -#import "ui/app_list/cocoa/app_list_view_controller.h" -#import "ui/app_list/cocoa/app_list_window_controller.h" - -AppListServiceCocoaMac::~AppListServiceCocoaMac() { -} - -// static -AppListServiceCocoaMac* AppListServiceCocoaMac::GetInstance() { - return base::Singleton< - AppListServiceCocoaMac, - base::LeakySingletonTraits<AppListServiceCocoaMac>>::get(); -} - -void AppListServiceCocoaMac::ShowForProfile(Profile* requested_profile) { - CreateForProfile(requested_profile); - DCHECK(ReadyToShow()); - ShowWindowNearDock(); -} - -Profile* AppListServiceCocoaMac::GetCurrentAppListProfile() { - return profile_; -} - -AppListControllerDelegate* AppListServiceCocoaMac::GetControllerDelegate() { - return controller_delegate_.get(); -} - -void AppListServiceCocoaMac::CreateForProfile(Profile* requested_profile) { - DCHECK(requested_profile); - - // App list profiles should not be off-the-record. - DCHECK(!requested_profile->IsOffTheRecord()); - DCHECK(!requested_profile->IsGuestSession()); - - InvalidatePendingProfileLoads(); - if (profile_ && requested_profile->IsSameProfile(profile_)) - return; - - profile_ = requested_profile->GetOriginalProfile(); - SetProfilePath(profile_->GetPath()); - - if (!window_controller_) - window_controller_.reset([[AppListWindowController alloc] init]); - - [[window_controller_ appListViewController] setDelegate:nil]; - [[window_controller_ appListViewController] - setDelegate:GetViewDelegate(profile_)]; -} - -void AppListServiceCocoaMac::DestroyAppList() { - // Due to reference counting, Mac can't guarantee that the widget is deleted, - // but mac supports a visible app list with a NULL profile, so there's also no - // need to tear it down completely. - DismissAppList(); - [[window_controller_ appListViewController] setDelegate:NULL]; - - profile_ = NULL; -} - -NSWindow* AppListServiceCocoaMac::GetNativeWindow() const { - return [window_controller_ window]; -} - -bool AppListServiceCocoaMac::ReadyToShow() { - if (!window_controller_) { - // Note that this will start showing an unpopulated window, the caller needs - // to ensure it will be populated later. - window_controller_.reset([[AppListWindowController alloc] init]); - } - return true; // Cocoa app list can be shown empty. -} - -AppListServiceCocoaMac::AppListServiceCocoaMac() - : profile_(nullptr), - controller_delegate_(new AppListControllerDelegateImpl(this)) { -}
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.h b/chrome/browser/ui/app_list/app_list_service_mac.h deleted file mode 100644 index b9eb8de..0000000 --- a/chrome/browser/ui/app_list/app_list_service_mac.h +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_MAC_H_ -#define CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_MAC_H_ - -#import <Cocoa/Cocoa.h> - -#include <memory> - -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "chrome/browser/apps/app_shim/app_shim_handler_mac.h" -#include "chrome/browser/ui/app_list/app_list_service_impl.h" - -@class AppListAnimationController; - -namespace display { -class Display; -} - -namespace gfx { -class Point; -} - -// AppListServiceMac manages global resources needed for the app list to -// operate, and controls when and how the app list is opened and closed. -class AppListServiceMac : public AppListServiceImpl, - public apps::AppShimHandler { - public: - ~AppListServiceMac() override; - - // Finds the position for a window to anchor it to the dock. This chooses the - // most appropriate position for the window based on whether the dock exists, - // the position of the dock (calculated by the difference between the display - // bounds and display work area), whether the mouse cursor is visible and its - // position. Sets |target_origin| to the coordinates for the window to appear - // at, and |start_origin| to the coordinates the window should begin animating - // from. Coordinates are for the bottom-left coordinate of the window, in - // AppKit space (Y positive is up). - static void FindAnchorPoint(const gfx::Size& window_size, - const display::Display& display, - int primary_display_height, - bool cursor_is_visible, - const gfx::Point& cursor, - NSPoint* target_origin, - NSPoint* start_origin); - - void ShowWindowNearDock(); - void WindowAnimationDidEnd(); - void InitWithProfilePath(Profile* initial_profile, - const base::FilePath& profile_path); - - // AppListService overrides: - void Init(Profile* initial_profile) override; - void DismissAppList() override; - void ShowForCustomLauncherPage(Profile* profile) override; - void HideCustomLauncherPage() override; - bool IsAppListVisible() const override; - void EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) override; - gfx::NativeWindow GetAppListWindow() override; - void CreateShortcut() override; - - // AppShimHandler overrides: - void OnShimLaunch(apps::AppShimHandler::Host* host, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) override; - void OnShimClose(apps::AppShimHandler::Host* host) override; - void OnShimFocus(apps::AppShimHandler::Host* host, - apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) override; - void OnShimSetHidden(apps::AppShimHandler::Host* host, bool hidden) override; - void OnShimQuit(apps::AppShimHandler::Host* host) override; - - protected: - AppListServiceMac(); - - // Returns the native window for the app list, or nil if can't be shown yet. - // Note that, unlike GetAppListWindow(), this does not return null when the - // app list is loaded, but not visible. - virtual NSWindow* GetNativeWindow() const = 0; - - // If the app list is loaded, return true. Otherwise, if supported, - // synchronously prepare an unpopulated app list window to begin showing on - // screen and return true. If that's not supported, return false. - virtual bool ReadyToShow() = 0; - - private: - base::scoped_nsobject<AppListAnimationController> animation_controller_; - base::scoped_nsobject<NSRunningApplication> previously_active_application_; - NSPoint last_start_origin_; - - DISALLOW_COPY_AND_ASSIGN(AppListServiceMac); -}; - -#endif // CHROME_BROWSER_UI_APP_LIST_APP_LIST_SERVICE_MAC_H_
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm deleted file mode 100644 index a38f753..0000000 --- a/chrome/browser/ui/app_list/app_list_service_mac.mm +++ /dev/null
@@ -1,581 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/app_list/app_list_service_mac.h" - -#include <ApplicationServices/ApplicationServices.h> -#import <Cocoa/Cocoa.h> -#include <stddef.h> - -#include <utility> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_util.h" -#include "base/lazy_instance.h" -#import "base/mac/foundation_util.h" -#include "base/memory/singleton.h" -#include "base/message_loop/message_loop.h" -#import "chrome/browser/app_controller_mac.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile_attributes_entry.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/app_list/app_list_positioner.h" -#include "chrome/browser/ui/app_list/app_list_service.h" -#include "chrome/browser/ui/app_list/app_list_service_cocoa_mac.h" -#include "chrome/browser/ui/app_list/app_list_service_impl.h" -#include "chrome/browser/ui/app_list/app_list_util.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/extensions/application_launch.h" -#include "chrome/browser/web_applications/web_app.h" -#include "chrome/browser/web_applications/web_app_mac.h" -#include "chrome/common/channel_info.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" -#include "chrome/common/mac/app_mode_common.h" -#include "chrome/common/pref_names.h" -#include "chrome/grit/google_chrome_strings.h" -#include "components/prefs/pref_service.h" -#include "components/version_info/version_info.h" -#include "content/public/browser/browser_thread.h" -#include "extensions/browser/extension_system.h" -#include "extensions/common/manifest_handlers/file_handler_info.h" -#include "grit/chrome_unscaled_resources.h" -#include "net/base/url_util.h" -#include "ui/app_list/app_list_switches.h" -#include "ui/app_list/search_box_model.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" - -namespace gfx { -class ImageSkia; -} - -// Controller for animations that show or hide the app list. -@interface AppListAnimationController : NSObject<NSAnimationDelegate> { - @private - // When closing, the window to close. Retained until the animation ends. - base::scoped_nsobject<NSWindow> window_; - // The animation started and owned by |self|. Reset when the animation ends. - base::scoped_nsobject<NSViewAnimation> animation_; -} - -// Returns whether |window_| is scheduled to be closed when the animation ends. -- (BOOL)isClosing; - -// Animate |window| to show or close it, after cancelling any current animation. -// Translates from the current location to |targetOrigin| and fades in or out. -- (void)animateWindow:(NSWindow*)window - targetOrigin:(NSPoint)targetOrigin - closing:(BOOL)closing; - -// Called on the UI thread once the animation has completed to reset the -// animation state, close the window (if it is a close animation), and possibly -// terminate Chrome. -- (void)cleanupOnUIThread; - -@end - -namespace { - -// Version of the app list shortcut version installed. -const int kShortcutVersion = 4; - -// Duration of show and hide animations. -const NSTimeInterval kAnimationDuration = 0.2; - -// Distance towards the screen edge that the app list moves from when showing. -const CGFloat kDistanceMovedOnShow = 20; - -std::unique_ptr<web_app::ShortcutInfo> GetAppListShortcutInfo( - const base::FilePath& profile_path) { - std::unique_ptr<web_app::ShortcutInfo> shortcut_info( - new web_app::ShortcutInfo); - version_info::Channel channel = chrome::GetChannel(); - if (channel == version_info::Channel::CANARY) { - shortcut_info->title = - l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME_CANARY); - } else { - shortcut_info->title = - l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME); - } - - shortcut_info->extension_id = app_mode::kAppListModeId; - shortcut_info->description = shortcut_info->title; - shortcut_info->profile_path = profile_path; - - return shortcut_info; -} - -void CreateAppListShim(const base::FilePath& profile_path) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - WebApplicationInfo web_app_info; - std::unique_ptr<web_app::ShortcutInfo> shortcut_info = - GetAppListShortcutInfo(profile_path); - - ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); - version_info::Channel channel = chrome::GetChannel(); - if (channel == version_info::Channel::CANARY) { -#if defined(GOOGLE_CHROME_BUILD) - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_16)); - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_32)); - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_128)); - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_256)); -#else - NOTREACHED(); -#endif - } else { - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_16)); - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_32)); - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_128)); - shortcut_info->favicon.Add( - *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_256)); - } - - web_app::ShortcutLocations shortcut_locations; - PrefService* local_state = g_browser_process->local_state(); - int installed_version = - local_state->GetInteger(prefs::kAppLauncherShortcutVersion); - - // If this is a first-time install, add a dock icon. Otherwise just update - // the target, and wait for OSX to refresh its icon caches. This might not - // occur until a reboot, but OSX does not offer a nicer way. Deleting cache - // files on disk and killing processes can easily result in icon corruption. - if (installed_version == 0) - shortcut_locations.in_quick_launch_bar = true; - - web_app::CreateNonAppShortcut(shortcut_locations, std::move(shortcut_info)); - - local_state->SetInteger(prefs::kAppLauncherShortcutVersion, - kShortcutVersion); -} - -NSRunningApplication* ActiveApplicationNotChrome() { - NSArray* applications = [[NSWorkspace sharedWorkspace] runningApplications]; - for (NSRunningApplication* application in applications) { - if (![application isActive]) - continue; - - if ([application isEqual:[NSRunningApplication currentApplication]]) - return nil; // Chrome is active. - - return application; - } - - return nil; -} - -// Determines which screen edge the dock is aligned to. -AppListPositioner::ScreenEdge DockLocationInDisplay( - const display::Display& display) { - // Assume the dock occupies part of the work area either on the left, right or - // bottom of the display. Note in the autohide case, it is always 4 pixels. - const gfx::Rect work_area = display.work_area(); - const gfx::Rect display_bounds = display.bounds(); - if (work_area.bottom() != display_bounds.bottom()) - return AppListPositioner::SCREEN_EDGE_BOTTOM; - - if (work_area.x() != display_bounds.x()) - return AppListPositioner::SCREEN_EDGE_LEFT; - - if (work_area.right() != display_bounds.right()) - return AppListPositioner::SCREEN_EDGE_RIGHT; - - return AppListPositioner::SCREEN_EDGE_UNKNOWN; -} - -// If |display|'s work area is too close to its boundary on |dock_edge|, adjust -// the work area away from the edge by a constant amount to reduce overlap and -// ensure the dock icon can still be clicked to dismiss the app list. -void AdjustWorkAreaForDock(const display::Display& display, - AppListPositioner* positioner, - AppListPositioner::ScreenEdge dock_edge) { - const int kAutohideDockThreshold = 10; - const int kExtraDistance = 50; // A dock with 40 items is about this size. - - const gfx::Rect work_area = display.work_area(); - const gfx::Rect display_bounds = display.bounds(); - - switch (dock_edge) { - case AppListPositioner::SCREEN_EDGE_LEFT: - if (work_area.x() - display_bounds.x() <= kAutohideDockThreshold) - positioner->WorkAreaInset(kExtraDistance, 0, 0, 0); - break; - case AppListPositioner::SCREEN_EDGE_RIGHT: - if (display_bounds.right() - work_area.right() <= kAutohideDockThreshold) - positioner->WorkAreaInset(0, 0, kExtraDistance, 0); - break; - case AppListPositioner::SCREEN_EDGE_BOTTOM: - if (display_bounds.bottom() - work_area.bottom() <= - kAutohideDockThreshold) { - positioner->WorkAreaInset(0, 0, 0, kExtraDistance); - } - break; - case AppListPositioner::SCREEN_EDGE_UNKNOWN: - case AppListPositioner::SCREEN_EDGE_TOP: - NOTREACHED(); - break; - } -} - -void GetAppListWindowOrigins( - NSWindow* window, NSPoint* target_origin, NSPoint* start_origin) { - display::Screen* const screen = display::Screen::GetScreen(); - // Ensure y coordinates are flipped back into AppKit's coordinate system. - bool cursor_is_visible = CGCursorIsVisible(); - display::Display display; - gfx::Point cursor; - if (!cursor_is_visible) { - // If Chrome is the active application, display on the same display as - // Chrome's keyWindow since this will catch activations triggered, e.g, via - // WebStore install. If another application is active, OSX doesn't provide a - // reliable way to get the display in use. Fall back to the primary display - // since it has the menu bar and is likely to be correct, e.g., for - // activations from Spotlight. - const gfx::NativeView key_view = [[NSApp keyWindow] contentView]; - display = key_view && [NSApp isActive] ? - screen->GetDisplayNearestWindow(key_view) : - screen->GetPrimaryDisplay(); - } else { - cursor = screen->GetCursorScreenPoint(); - display = screen->GetDisplayNearestPoint(cursor); - } - - const NSSize ns_window_size = [window frame].size; - gfx::Size window_size(ns_window_size.width, ns_window_size.height); - int primary_display_height = - NSMaxY([[[NSScreen screens] firstObject] frame]); - AppListServiceMac::FindAnchorPoint(window_size, - display, - primary_display_height, - cursor_is_visible, - cursor, - target_origin, - start_origin); -} - -} // namespace - -AppListServiceMac::AppListServiceMac() { - animation_controller_.reset([[AppListAnimationController alloc] init]); -} - -AppListServiceMac::~AppListServiceMac() {} - -// static -void AppListServiceMac::FindAnchorPoint(const gfx::Size& window_size, - const display::Display& display, - int primary_display_height, - bool cursor_is_visible, - const gfx::Point& cursor, - NSPoint* target_origin, - NSPoint* start_origin) { - AppListPositioner positioner(display, window_size, 0); - AppListPositioner::ScreenEdge dock_location = DockLocationInDisplay(display); - - gfx::Point anchor; - // Snap to the dock edge. If the cursor is greater than the window - // width/height away or not visible, anchor to the center of the dock. - // Otherwise, anchor to the cursor position. - if (dock_location == AppListPositioner::SCREEN_EDGE_UNKNOWN) { - anchor = positioner.GetAnchorPointForScreenCorner( - AppListPositioner::SCREEN_CORNER_BOTTOM_LEFT); - } else { - int snap_distance = - dock_location == AppListPositioner::SCREEN_EDGE_BOTTOM || - dock_location == AppListPositioner::SCREEN_EDGE_TOP ? - window_size.height() : - window_size.width(); - // Subtract the dock area since the display's default work_area will not - // subtract it if the dock is set to auto-hide, and the app list should - // never overlap the dock. - AdjustWorkAreaForDock(display, &positioner, dock_location); - if (!cursor_is_visible || positioner.GetCursorDistanceFromShelf( - dock_location, cursor) > snap_distance) { - anchor = positioner.GetAnchorPointForShelfCenter(dock_location); - } else { - anchor = positioner.GetAnchorPointForShelfCursor(dock_location, cursor); - } - } - - *target_origin = NSMakePoint( - anchor.x() - window_size.width() / 2, - primary_display_height - anchor.y() - window_size.height() / 2); - *start_origin = *target_origin; - - // If the launcher is anchored to the dock (regardless of whether the cursor - // is visible), animate in inwards from the edge of screen - switch (dock_location) { - case AppListPositioner::SCREEN_EDGE_UNKNOWN: - break; - case AppListPositioner::SCREEN_EDGE_LEFT: - start_origin->x -= kDistanceMovedOnShow; - break; - case AppListPositioner::SCREEN_EDGE_RIGHT: - start_origin->x += kDistanceMovedOnShow; - break; - case AppListPositioner::SCREEN_EDGE_TOP: - NOTREACHED(); - break; - case AppListPositioner::SCREEN_EDGE_BOTTOM: - start_origin->y -= kDistanceMovedOnShow; - break; - } -} - -void AppListServiceMac::Init(Profile* initial_profile) { - InitWithProfilePath(initial_profile, initial_profile->GetPath()); -} - -void AppListServiceMac::InitWithProfilePath( - Profile* initial_profile, - const base::FilePath& profile_path) { - // On Mac, Init() is called multiple times for a process: any time there is no - // browser window open and a new window is opened, and during process startup - // to handle the silent launch case (e.g. for app shims). In the startup case, - // a profile has not yet been determined so |initial_profile| will be NULL. - static bool init_called_with_profile = false; - if (initial_profile && !init_called_with_profile) { - init_called_with_profile = true; - PerformStartupChecks(initial_profile); - PrefService* local_state = g_browser_process->local_state(); - if (!IsAppLauncherEnabled()) { - local_state->SetInteger(prefs::kAppLauncherShortcutVersion, 0); - } else { - int installed_shortcut_version = - local_state->GetInteger(prefs::kAppLauncherShortcutVersion); - - if (kShortcutVersion > installed_shortcut_version) - CreateShortcut(); - } - } - - static bool init_called = false; - if (init_called) - return; - - init_called = true; - apps::AppShimHandler::RegisterHandler(app_mode::kAppListModeId, this); - - // Handle the case where Chrome was not running and was started with the app - // launcher shim. The profile has not yet been loaded. To improve response - // times, start animating an empty window which will be populated via - // OnShimLaunch(). Note that if --silent-launch is not also passed, the window - // will instead populate via StartupBrowserCreator::Launch(). Shim-initiated - // launches will always have --silent-launch. - if (base::CommandLine::ForCurrentProcess()-> - HasSwitch(switches::kShowAppList)) { - // Do not show the launcher window when the profile is locked, or if it - // can't be displayed unpopulated. In the latter case, the Show will occur - // in OnShimLaunch() or AppListService::HandleLaunchCommandLine(). - ProfileAttributesEntry* entry = nullptr; - bool has_entry = g_browser_process->profile_manager()-> - GetProfileAttributesStorage(). - GetProfileAttributesWithPath(profile_path, &entry); - if (has_entry && !entry->IsSigninRequired() && ReadyToShow()) - ShowWindowNearDock(); - } -} - -void AppListServiceMac::DismissAppList() { - if (!IsAppListVisible()) - return; - - NSWindow* app_list_window = GetNativeWindow(); - // If the app list is currently the main window, it will activate the next - // Chrome window when dismissed. But if a different application was active - // when the app list was shown, activate that instead. - base::scoped_nsobject<NSRunningApplication> prior_app; - if ([app_list_window isMainWindow]) - prior_app.swap(previously_active_application_); - else - previously_active_application_.reset(); - - // If activation is successful, the app list will lose main status and try to - // close itself again. It can't be closed in this runloop iteration without - // OSX deciding to raise the next Chrome window, and _then_ activating the - // application on top. This also occurs if no activation option is given. - if ([prior_app activateWithOptions:NSApplicationActivateIgnoringOtherApps]) - return; - - [animation_controller_ animateWindow:app_list_window - targetOrigin:last_start_origin_ - closing:YES]; -} - -void AppListServiceMac::ShowForCustomLauncherPage(Profile* profile) { - NOTIMPLEMENTED(); -} - -void AppListServiceMac::HideCustomLauncherPage() { - NOTIMPLEMENTED(); -} - -bool AppListServiceMac::IsAppListVisible() const { - return [GetNativeWindow() isVisible] && - ![animation_controller_ isClosing]; -} - -void AppListServiceMac::EnableAppList(Profile* initial_profile, - AppListEnableSource enable_source) { - AppListServiceImpl::EnableAppList(initial_profile, enable_source); - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - [controller initAppShimMenuController]; -} - -void AppListServiceMac::CreateShortcut() { - CreateAppListShim(GetProfilePath( - g_browser_process->profile_manager()->user_data_dir())); -} - -NSWindow* AppListServiceMac::GetAppListWindow() { - return GetNativeWindow(); -} - -void AppListServiceMac::OnShimLaunch(apps::AppShimHandler::Host* host, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) { - if (GetCurrentAppListProfile() && IsAppListVisible()) { - DismissAppList(); - } else { - // Start by showing a possibly empty window to handle the case where Chrome - // is running, but hasn't yet loaded the app launcher profile. - if (ReadyToShow()) - ShowWindowNearDock(); - Show(); - } - - // Always close the shim process immediately. - host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_DUPLICATE_HOST); -} - -void AppListServiceMac::OnShimClose(apps::AppShimHandler::Host* host) {} - -void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host, - apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) {} - -void AppListServiceMac::OnShimSetHidden(apps::AppShimHandler::Host* host, - bool hidden) {} - -void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {} - -void AppListServiceMac::ShowWindowNearDock() { - if (IsAppListVisible()) - return; - - NSWindow* window = GetAppListWindow(); - DCHECK(window); - NSPoint target_origin; - GetAppListWindowOrigins(window, &target_origin, &last_start_origin_); - [window setFrameOrigin:last_start_origin_]; - - // Before activating, see if an application other than Chrome is currently the - // active application, so that it can be reactivated when dismissing. - previously_active_application_.reset([ActiveApplicationNotChrome() retain]); - - [animation_controller_ animateWindow:window - targetOrigin:target_origin - closing:NO]; - [window makeKeyAndOrderFront:nil]; - [NSApp activateIgnoringOtherApps:YES]; - RecordAppListLaunch(); -} - -void AppListServiceMac::WindowAnimationDidEnd() { - [animation_controller_ cleanupOnUIThread]; -} - -// static -AppListService* AppListService::Get() { - return AppListServiceCocoaMac::GetInstance(); -} - -// static -void AppListService::InitAll(Profile* initial_profile, - const base::FilePath& profile_path) { - AppListServiceCocoaMac::GetInstance()->InitWithProfilePath(initial_profile, - profile_path); -} - -@implementation AppListAnimationController - -- (BOOL)isClosing { - return !!window_; -} - -- (void)animateWindow:(NSWindow*)window - targetOrigin:(NSPoint)targetOrigin - closing:(BOOL)closing { - // First, stop the existing animation, if there is one. - [animation_ stopAnimation]; - - NSRect targetFrame = [window frame]; - targetFrame.origin = targetOrigin; - - // NSViewAnimation has a quirk when setting the curve to NSAnimationEaseOut - // where it attempts to auto-reverse the animation. FadeOut becomes FadeIn - // (good), but FrameKey is also switched (bad). So |targetFrame| needs to be - // put on the StartFrameKey when using NSAnimationEaseOut for showing. - NSArray* animationArray = @[ - @{ - NSViewAnimationTargetKey : window, - NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect, - (closing ? NSViewAnimationEndFrameKey : NSViewAnimationStartFrameKey) : - [NSValue valueWithRect:targetFrame] - } - ]; - animation_.reset( - [[NSViewAnimation alloc] initWithViewAnimations:animationArray]); - [animation_ setDuration:kAnimationDuration]; - [animation_ setDelegate:self]; - - if (closing) { - [animation_ setAnimationCurve:NSAnimationEaseIn]; - window_.reset([window retain]); - } else { - [window setAlphaValue:0.0f]; - [animation_ setAnimationCurve:NSAnimationEaseOut]; - window_.reset(); - } - // This once used a threaded animation, but AppKit would too often ignore - // -[NSView canDrawConcurrently:] and just redraw whole view hierarchies on - // the animation thread anyway, creating a minefield of race conditions. - // Non-threaded means the animation isn't as smooth and doesn't begin unless - // the UI runloop has spun up (after profile loading). - [animation_ setAnimationBlockingMode:NSAnimationNonblocking]; - - [animation_ startAnimation]; -} - -- (void)cleanupOnUIThread { - bool closing = [self isClosing]; - [window_ close]; - window_.reset(); - animation_.reset(); - - if (closing) - apps::AppShimHandler::MaybeTerminate(); -} - -- (void)animationDidEnd:(NSAnimation*)animation { - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AppListServiceMac::WindowAnimationDidEnd, - base::Unretained(AppListServiceCocoaMac::GetInstance()))); -} - -@end
diff --git a/chrome/browser/ui/app_list/app_list_service_mac_interactive_uitest.mm b/chrome/browser/ui/app_list/app_list_service_mac_interactive_uitest.mm deleted file mode 100644 index 1c35da8b..0000000 --- a/chrome/browser/ui/app_list/app_list_service_mac_interactive_uitest.mm +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/app_list/app_list_service_cocoa_mac.h" - -#include <vector> - -#include "base/command_line.h" -#include "base/macros.h" -#include "chrome/browser/apps/app_shim/app_shim_handler_mac.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/mac/app_mode_common.h" -#include "chrome/test/base/in_process_browser_test.h" -#import "ui/app_list/cocoa/app_list_window_controller.h" - -using apps::AppShimHandler; - -namespace test { - -class AppListServiceMacTestApi { - public: - static AppListWindowController* window_controller() { - return AppListServiceCocoaMac::GetInstance()->window_controller_; - } -}; - -} // namespace test - -namespace { - -// Browser test for mac-specific AppListService functionality. -class AppListServiceMacInteractiveTest : public InProcessBrowserTest, - public AppShimHandler::Host { - public: - AppListServiceMacInteractiveTest() : launch_count_(0) {} - - protected: - void LaunchShim() { - // AppList shims always launch normally (never relaunched via dock icon). - AppShimHandler::GetForAppMode(app_mode::kAppListModeId)-> - OnShimLaunch(this, - apps::APP_SHIM_LAUNCH_NORMAL, - std::vector<base::FilePath>()); - } - - AppListViewController* GetViewController() { - return [test::AppListServiceMacTestApi::window_controller() - appListViewController]; - } - - // testing::Test overrides: - void TearDown() override { - // At tear-down, NOTIFICATION_APP_TERMINATING should have been sent for the - // browser shutdown. References to browser-owned objects must be removed - // from the app list UI. - AppListViewController* view_controller = GetViewController(); - // Note this first check will fail if the test doesn't ever show the - // app list, but currently all tests in this file do. - EXPECT_TRUE(view_controller); - EXPECT_FALSE([view_controller delegate]); - } - - // AppShimHandler::Host overrides: - void OnAppLaunchComplete(apps::AppShimLaunchResult result) override { - // AppList shims are always given APP_SHIM_LAUNCH_DUPLICATE_HOST, indicating - // that the shim process should immediately close. - EXPECT_EQ(apps::APP_SHIM_LAUNCH_DUPLICATE_HOST, result); - ++launch_count_; - } - void OnAppClosed() override { NOTREACHED(); } - void OnAppHide() override {} - void OnAppUnhideWithoutActivation() override {} - void OnAppRequestUserAttention(apps::AppShimAttentionType type) override {} - base::FilePath GetProfilePath() const override { - NOTREACHED(); // Currently unused in this test. - return base::FilePath(); - } - std::string GetAppId() const override { return app_mode::kAppListModeId; } - - int launch_count_; - - private: - DISALLOW_COPY_AND_ASSIGN(AppListServiceMacInteractiveTest); -}; - -} // namespace - -IN_PROC_BROWSER_TEST_F(AppListServiceMacInteractiveTest, ShowAppListUsingShim) { - // Check that AppListService has registered as a shim handler for "app_list". - EXPECT_TRUE(AppShimHandler::GetForAppMode(app_mode::kAppListModeId)); - - AppListService* service = AppListService::Get(); - EXPECT_FALSE(service->IsAppListVisible()); - - // Creation should be lazy. - EXPECT_FALSE(GetViewController()); - - // With no saved profile, the default profile should be chosen and saved. - service->Show(); - EXPECT_EQ(browser()->profile(), service->GetCurrentAppListProfile()); - EXPECT_TRUE(service->IsAppListVisible()); - EXPECT_EQ(0, launch_count_); - service->DismissAppList(); - EXPECT_FALSE(service->IsAppListVisible()); - - // Test showing the app list via the shim. The shim should immediately close - // leaving the app list visible. - LaunchShim(); - EXPECT_TRUE(service->IsAppListVisible()); - EXPECT_EQ(1, launch_count_); - - // Launching again should toggle the app list. - LaunchShim(); - EXPECT_FALSE(service->IsAppListVisible()); - EXPECT_EQ(2, launch_count_); - - // Test showing the app list via the shim, then dismissing the app list. - LaunchShim(); - EXPECT_TRUE(service->IsAppListVisible()); - EXPECT_EQ(3, launch_count_); - service->DismissAppList(); - EXPECT_FALSE(service->IsAppListVisible()); - - // View sticks around until shutdown. - AppListViewController* view_controller = GetViewController(); - EXPECT_TRUE(view_controller); - EXPECT_TRUE([view_controller delegate]); -}
diff --git a/chrome/browser/ui/app_list/app_list_service_mac_unittest.mm b/chrome/browser/ui/app_list/app_list_service_mac_unittest.mm deleted file mode 100644 index 978e143..0000000 --- a/chrome/browser/ui/app_list/app_list_service_mac_unittest.mm +++ /dev/null
@@ -1,316 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/app_list/app_list_service_mac.h" - -#include "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" -#include "ui/display/display.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/size.h" - -namespace { - -const int kScreenWidth = 800; -const int kScreenHeight = 600; - -const int kWindowWidth = 100; -const int kWindowHeight = 200; - -// Size of the menu bar along the top of the screen. -const int kMenuBarSize = 22; -// Size of the normal (non-hidden) dock. -const int kDockSize = 30; -// Size of the hidden dock. -const int kHiddenDockSize = 4; - -// Distance to move during the opening animation. -const int kAnimationOffset = 20; - -// The assumed size of the hidden dock. -const int kExtraDistance = 50; - -// A cursor position that is within the dock. This must be < kDockSize. -const int kCursorOnDock = kDockSize / 2; -// A cursor position that is within kWindowWidth pixels of the dock. -const int kCursorNearDockX = kDockSize + kWindowWidth; -// A cursor position that is more than kWindowWidth pixels away from the dock. -const int kCursorAwayFromDockX = kCursorNearDockX + 1; -// A cursor position that is within kWindowHeight pixels of the dock. -const int kCursorNearDockY = kDockSize + kWindowHeight; -// A cursor position that is more than kWindowHeight pixels away from the dock. -const int kCursorAwayFromDockY = kCursorNearDockY + 1; - -// A position for the center of the window that causes the window to overlap the -// edge of the screen. This must be < kWindowWidth / 2 and < kWindowHeight / 2. -const int kWindowNearEdge = kWindowWidth / 4; -// A position for the center of the window that places the window away from all -// edges of the screen. This must be > kWindowWidth / 2, > kWindowHeight / 2, < -// kScreenWidth - kWindowWidth / 2 and < kScreenHeight - kWindowHeight / 2. -const int kWindowAwayFromEdge = 158; - -enum DockLocation { - DOCK_LOCATION_BOTTOM, - DOCK_LOCATION_LEFT, - DOCK_LOCATION_RIGHT, -}; - -// Returns |point| offset by (|x_offset|, |y_offset|). -NSPoint OffsetPoint(const NSPoint& point, CGFloat x_offset, CGFloat y_offset) { - return NSMakePoint(point.x + x_offset, point.y + y_offset); -} - -} // namespace - -class AppListServiceMacUnitTest : public testing::Test { - public: - void SetUp() override { - display_.set_bounds(gfx::Rect(0, 0, kScreenWidth, kScreenHeight)); - display_.set_work_area( - gfx::Rect(0, kMenuBarSize, kScreenWidth, kScreenHeight - kMenuBarSize)); - window_size_ = gfx::Size(kWindowWidth, kWindowHeight); - cursor_is_visible_ = true; - cursor_ = gfx::Point(); - } - - // Sets up the test environment with the dock in a given location. - void PlaceDock(DockLocation location, bool hidden) { - int dock_size = hidden ? kHiddenDockSize : kDockSize; - switch (location) { - case DOCK_LOCATION_BOTTOM: - display_.set_work_area( - gfx::Rect(0, - kMenuBarSize, - kScreenWidth, - kScreenHeight - kMenuBarSize - dock_size)); - break; - case DOCK_LOCATION_LEFT: - display_.set_work_area(gfx::Rect(dock_size, - kMenuBarSize, - kScreenWidth - dock_size, - kScreenHeight - kMenuBarSize)); - break; - case DOCK_LOCATION_RIGHT: - display_.set_work_area(gfx::Rect(0, - kMenuBarSize, - kScreenWidth - dock_size, - kScreenHeight - kMenuBarSize)); - break; - } - } - - // Set whether the test mouse cursor is visible. - void SetCursorVisible(bool visible) { - cursor_is_visible_ = visible; - } - - // Set up the test mouse cursor in a given location. - void PlaceCursor(int x, int y) { - cursor_ = gfx::Point(x, y); - } - - void DoFindAnchorPoint(NSPoint* target_origin, - NSPoint* start_origin) { - AppListServiceMac::FindAnchorPoint(window_size_, - display_, - kScreenHeight, - cursor_is_visible_, - cursor_, - target_origin, - start_origin); - } - - private: - display::Display display_; - gfx::Size window_size_; - bool cursor_is_visible_; - gfx::Point cursor_; -}; - -// Tests positioning the app list when there is no visible mouse cursor. -TEST_F(AppListServiceMacUnitTest, FindAnchorPointNoCursor) { - SetCursorVisible(false); - PlaceCursor(0, 0); - NSPoint target_origin; - NSPoint start_origin; - - // Bottom dock. Expect the app list to be centered on the dock. - PlaceDock(DOCK_LOCATION_BOTTOM, false); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kScreenWidth / 2 - kWindowWidth / 2, kDockSize), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); - - // Left dock. Expect the app list to be centered on the dock. - PlaceDock(DOCK_LOCATION_LEFT, false); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kDockSize, (kScreenHeight - kMenuBarSize) / 2 - - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, -kAnimationOffset, 0), start_origin); - - // Right dock. Expect the app list to be centered on the dock. - PlaceDock(DOCK_LOCATION_RIGHT, false); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ( - NSMakePoint(kScreenWidth - kDockSize - kWindowWidth, - (kScreenHeight - kMenuBarSize) / 2 - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, kAnimationOffset, 0), start_origin); -} - -// Tests positioning the app list when there is no dock on the display. -TEST_F(AppListServiceMacUnitTest, FindAnchorPointNoDock) { - SetCursorVisible(true); - PlaceCursor(0, 0); - NSPoint target_origin; - NSPoint start_origin; - - // Expect the app list to be in the bottom-left corner. - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(0, 0), target_origin); - EXPECT_NSEQ(target_origin, start_origin); - - // No mouse cursor. This should have no effect. - SetCursorVisible(false); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(0, 0), target_origin); - EXPECT_NSEQ(target_origin, start_origin); -} - -// Tests positioning the app list when the mouse is away from the dock. -TEST_F(AppListServiceMacUnitTest, FindAnchorPointMouseOffDock) { - SetCursorVisible(true); - NSPoint target_origin; - NSPoint start_origin; - - // Bottom dock. Expect the app list to be centered on the dock. - PlaceDock(DOCK_LOCATION_BOTTOM, false); - PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorAwayFromDockY); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kScreenWidth / 2 - kWindowWidth / 2, kDockSize), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); - - // Left dock. Expect the app list to be centered on the dock. - PlaceDock(DOCK_LOCATION_LEFT, false); - PlaceCursor(kCursorAwayFromDockX, kWindowAwayFromEdge); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kDockSize, (kScreenHeight - kMenuBarSize) / 2 - - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, -kAnimationOffset, 0), start_origin); - - // Right dock. Expect the app list to be centered on the dock. - PlaceDock(DOCK_LOCATION_RIGHT, false); - PlaceCursor(kScreenWidth - kCursorAwayFromDockX, kWindowAwayFromEdge); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ( - NSMakePoint(kScreenWidth - kDockSize - kWindowWidth, - (kScreenHeight - kMenuBarSize) / 2 - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, kAnimationOffset, 0), start_origin); -} - -// Tests positioning the app list when the dock is hidden. -TEST_F(AppListServiceMacUnitTest, FindAnchorPointHiddenDock) { - SetCursorVisible(true); - NSPoint target_origin; - NSPoint start_origin; - - // Bottom dock. Expect the app list to be kExtraDistance pixels from the dock - // centered on the mouse X coordinate. - PlaceDock(DOCK_LOCATION_BOTTOM, true); - PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorAwayFromDockY); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kWindowAwayFromEdge - kWindowWidth / 2, - kHiddenDockSize + kExtraDistance), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); - - // Left dock. Expect the app list to be kExtraDistance pixels from the dock - // centered on the mouse Y coordinate. - PlaceDock(DOCK_LOCATION_LEFT, true); - PlaceCursor(kCursorAwayFromDockX, kWindowAwayFromEdge); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ( - NSMakePoint(kHiddenDockSize + kExtraDistance, - kScreenHeight - kWindowAwayFromEdge - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, -kAnimationOffset, 0), start_origin); - - // Right dock. Expect the app list to be kExtraDistance pixels from the dock - // centered on the mouse Y coordinate. - PlaceDock(DOCK_LOCATION_RIGHT, true); - PlaceCursor(kScreenWidth - kCursorAwayFromDockX, kWindowAwayFromEdge); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ( - NSMakePoint( - kScreenWidth - kHiddenDockSize - kWindowWidth - kExtraDistance, - kScreenHeight - kWindowAwayFromEdge - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, kAnimationOffset, 0), start_origin); -} - -// Tests positioning the app list when the mouse is over the dock. -TEST_F(AppListServiceMacUnitTest, FindAnchorPointMouseOnDock) { - SetCursorVisible(true); - NSPoint target_origin; - NSPoint start_origin; - - // Bottom dock (mouse well within dock). Expect the app list to be at the - // bottom centered on the mouse X coordinate. - PlaceDock(DOCK_LOCATION_BOTTOM, false); - PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorOnDock); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kWindowAwayFromEdge - kWindowWidth / 2, kDockSize), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); - - // Bottom dock (outside the dock but still close enough). Expect the app list - // to be at the bottom centered on the mouse X coordinate. - PlaceDock(DOCK_LOCATION_BOTTOM, false); - PlaceCursor(kWindowAwayFromEdge, kScreenHeight - kCursorNearDockY); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kWindowAwayFromEdge - kWindowWidth / 2, kDockSize), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); - - // Left dock. Expect the app list to be at the left centered on the mouse Y - // coordinate. - PlaceDock(DOCK_LOCATION_LEFT, false); - PlaceCursor(kCursorNearDockX, kWindowAwayFromEdge); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kDockSize, kScreenHeight - kWindowAwayFromEdge - - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, -kAnimationOffset, 0), start_origin); - - // Right dock. Expect the app list to be at the right centered on the mouse Y - // coordinate. - PlaceDock(DOCK_LOCATION_RIGHT, false); - PlaceCursor(kScreenWidth - kCursorNearDockX, kWindowAwayFromEdge); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ( - NSMakePoint(kScreenWidth - kDockSize - kWindowWidth, - kScreenHeight - kWindowAwayFromEdge - kWindowHeight / 2), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, kAnimationOffset, 0), start_origin); - - // Bottom dock. Mouse near left edge. App list must not go off screen. - PlaceDock(DOCK_LOCATION_BOTTOM, false); - PlaceCursor(kWindowNearEdge, kScreenHeight - kCursorOnDock); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(0, kDockSize), target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); - - // Bottom dock. Mouse near right edge. App list must not go off screen. - PlaceDock(DOCK_LOCATION_BOTTOM, false); - PlaceCursor(kScreenWidth - kWindowNearEdge, kScreenHeight - kCursorOnDock); - DoFindAnchorPoint(&target_origin, &start_origin); - EXPECT_NSEQ(NSMakePoint(kScreenWidth - kWindowWidth, kDockSize), - target_origin); - EXPECT_NSEQ(OffsetPoint(target_origin, 0, -kAnimationOffset), start_origin); -}
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index 6a1ad09..bcbc88c 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -38,6 +38,8 @@ const char kLastLaunchTime[] = "lastlaunchtime"; const char kShouldSync[] = "should_sync"; const char kSystem[] = "system"; +const char kOrientationLock[] = "orientation_lock"; + constexpr int kSetNotificationsEnabledMinVersion = 6; // Provider of write access to a dictionary storing ARC prefs. @@ -451,6 +453,7 @@ bool sticky = false; bool notifications_enabled = true; bool shortcut = false; + int orientation_lock_value = 0; app->GetString(kName, &name); app->GetString(kPackageName, &package_name); app->GetString(kActivity, &activity); @@ -459,6 +462,7 @@ app->GetBoolean(kSticky, &sticky); app->GetBoolean(kNotificationsEnabled, ¬ifications_enabled); app->GetBoolean(kShortcut, &shortcut); + app->GetInteger(kOrientationLock, &orientation_lock_value); DCHECK(!name.empty()); DCHECK(!shortcut || activity.empty()); @@ -474,12 +478,14 @@ if (SetNotificationsEnabledDeferred(prefs_).Get(app_id, &deferred)) { notifications_enabled = deferred; } + arc::mojom::OrientationLock orientation_lock = + static_cast<arc::mojom::OrientationLock>(orientation_lock_value); - return base::MakeUnique<AppInfo>(name, package_name, activity, intent_uri, - icon_resource_id, last_launch_time, sticky, - notifications_enabled, - ready_apps_.count(app_id) > 0, - arc::ShouldShowInLauncher(app_id), shortcut); + return base::MakeUnique<AppInfo>( + name, package_name, activity, intent_uri, icon_resource_id, + last_launch_time, sticky, notifications_enabled, + ready_apps_.count(app_id) > 0, arc::ShouldShowInLauncher(app_id), + shortcut, orientation_lock); } bool ArcAppListPrefs::IsRegistered(const std::string& app_id) const { @@ -581,14 +587,16 @@ ready_apps_.clear(); } -void ArcAppListPrefs::AddAppAndShortcut(const std::string& name, - const std::string& package_name, - const std::string& activity, - const std::string& intent_uri, - const std::string& icon_resource_id, - const bool sticky, - const bool notifications_enabled, - const bool shortcut) { +void ArcAppListPrefs::AddAppAndShortcut( + const std::string& name, + const std::string& package_name, + const std::string& activity, + const std::string& intent_uri, + const std::string& icon_resource_id, + const bool sticky, + const bool notifications_enabled, + const bool shortcut, + const arc::mojom::OrientationLock orientation_lock) { std::string app_id = shortcut ? GetAppId(package_name, intent_uri) : GetAppId(package_name, activity); bool was_registered = IsRegistered(app_id); @@ -611,6 +619,7 @@ app_dict->SetBoolean(kSticky, sticky); app_dict->SetBoolean(kNotificationsEnabled, notifications_enabled); app_dict->SetBoolean(kShortcut, shortcut); + app_dict->SetInteger(kOrientationLock, static_cast<int>(orientation_lock)); // From now, app is available. if (!ready_apps_.count(app_id)) @@ -623,7 +632,8 @@ } else { AppInfo app_info(name, package_name, activity, intent_uri, icon_resource_id, base::Time(), sticky, notifications_enabled, true, - arc::ShouldShowInLauncher(app_id), shortcut); + arc::ShouldShowInLauncher(app_id), shortcut, + orientation_lock); FOR_EACH_OBSERVER(Observer, observer_list_, OnAppRegistered(app_id, app_info)); @@ -681,10 +691,12 @@ ready_apps_.clear(); for (const auto& app : apps) { + // TODO(oshima): Do we have to update orientation? AddAppAndShortcut(app->name, app->package_name, app->activity, std::string() /* intent_uri */, std::string() /* icon_resource_id */, app->sticky, - app->notifications_enabled, false /* shortcut */); + app->notifications_enabled, false /* shortcut */, + app->orientation_lock); } // Detect removed ARC apps after current refresh. @@ -706,6 +718,13 @@ } } +void ArcAppListPrefs::OnTaskOrientationLockRequested( + int32_t task_id, + const arc::mojom::OrientationLock orientation_lock) { + FOR_EACH_OBSERVER(Observer, observer_list_, + OnTaskOrientationLockRequested(task_id, orientation_lock)); +} + void ArcAppListPrefs::OnAppAdded(arc::mojom::AppInfoPtr app) { if ((app->name.get().empty() || app->package_name.get().empty() || app->activity.get().empty())) { @@ -716,7 +735,8 @@ AddAppAndShortcut(app->name, app->package_name, app->activity, std::string() /* intent_uri */, std::string() /* icon_resource_id */, app->sticky, - app->notifications_enabled, false /* shortcut */); + app->notifications_enabled, false /* shortcut */, + app->orientation_lock); } void ArcAppListPrefs::OnInstallShortcut(arc::mojom::ShortcutInfoPtr shortcut) { @@ -728,7 +748,8 @@ AddAppAndShortcut(shortcut->name, shortcut->package_name, std::string() /* activity */, shortcut->intent_uri, shortcut->icon_resource_id, false /* sticky */, - false /* notifications_enabled */, true /* shortcut */); + false /* notifications_enabled */, true /* shortcut */, + arc::mojom::OrientationLock::NONE); } void ArcAppListPrefs::OnPackageRemoved(const mojo::String& package_name) { @@ -916,7 +937,8 @@ bool notifications_enabled, bool ready, bool showInLauncher, - bool shortcut) + bool shortcut, + arc::mojom::OrientationLock orientation_lock) : name(name), package_name(package_name), activity(activity), @@ -927,7 +949,8 @@ notifications_enabled(notifications_enabled), ready(ready), showInLauncher(showInLauncher), - shortcut(shortcut) {} + shortcut(shortcut), + orientation_lock(orientation_lock) {} // Need to add explicit destructor for chromium style checker error: // Complex class/struct needs an explicit out-of-line destructor
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h index b00e1659..0357525 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -60,7 +60,8 @@ bool notifications_enabled, bool ready, bool showInLauncher, - bool shortcut); + bool shortcut, + arc::mojom::OrientationLock orientation_lock); ~AppInfo(); std::string name; @@ -74,6 +75,7 @@ bool ready; bool showInLauncher; bool shortcut; + arc::mojom::OrientationLock orientation_lock; }; struct PackageInfo { @@ -120,6 +122,10 @@ virtual void OnNotificationsEnabledChanged( const std::string& package_name, bool enabled) {} + virtual void OnTaskOrientationLockRequested( + int32_t task_id, + const arc::mojom::OrientationLock orientation_lock) {} + protected: virtual ~Observer() {} }; @@ -194,7 +200,7 @@ void RemoveApp(const std::string& app_id); private: - FRIEND_TEST_ALL_PREFIXES(ChromeLauncherControllerImplTest, ArcAppPinPolicy); + friend class ChromeLauncherControllerImplTest; // See the Create methods. ArcAppListPrefs(const base::FilePath& base_path, PrefService* prefs); @@ -227,6 +233,9 @@ void OnPackageModified(arc::mojom::ArcPackageInfoPtr package_info) override; void OnPackageListRefreshed( mojo::Array<arc::mojom::ArcPackageInfoPtr> packages) override; + void OnTaskOrientationLockRequested( + int32_t task_id, + const arc::mojom::OrientationLock orientation_lock) override; void AddAppAndShortcut(const std::string& name, const std::string& package_name, @@ -235,7 +244,8 @@ const std::string& icon_resource_id, const bool sticky, const bool notifications_enabled, - const bool shortcut); + const bool shortcut, + arc::mojom::OrientationLock orientation_lock); void DisableAllApps(); void RemoveAllApps(); std::vector<std::string> GetAppIdsNoArcEnabledCheck() const;
diff --git a/chrome/browser/ui/app_list/extension_app_context_menu.cc b/chrome/browser/ui/app_list/extension_app_context_menu.cc index 39d939b6..ca05fca 100644 --- a/chrome/browser/ui/app_list/extension_app_context_menu.cc +++ b/chrome/browser/ui/app_list/extension_app_context_menu.cc
@@ -105,18 +105,11 @@ USE_LAUNCH_TYPE_WINDOW, IDS_APP_CONTEXT_MENU_OPEN_WINDOW); } -#if defined(OS_MACOSX) - // Mac does not support standalone web app browser windows or maximize. - menu_model->AddCheckItemWithStringId( - USE_LAUNCH_TYPE_FULLSCREEN, - IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN); -#else // Even though the launch type is Full Screen it is more accurately // described as Maximized in Ash. menu_model->AddCheckItemWithStringId( USE_LAUNCH_TYPE_FULLSCREEN, IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED); -#endif } menu_model->AddSeparator(ui::NORMAL_SEPARATOR); } @@ -160,11 +153,6 @@ DCHECK_EQ(LAUNCH_NEW, command_id); -#if defined(OS_MACOSX) - // Full screen on Mac launches in a tab. - bool launches_in_window = extensions::util::CanHostedAppsOpenInWindows() && - IsCommandIdChecked(USE_LAUNCH_TYPE_WINDOW); -#else // If --enable-new-bookmark-apps is enabled, then only check if // USE_LAUNCH_TYPE_WINDOW is checked, as USE_LAUNCH_TYPE_PINNED (i.e. open // as pinned tab) and fullscreen-by-default windows do not exist. @@ -173,7 +161,6 @@ ? IsCommandIdChecked(USE_LAUNCH_TYPE_WINDOW) : !(IsCommandIdChecked(USE_LAUNCH_TYPE_PINNED) || IsCommandIdChecked(USE_LAUNCH_TYPE_REGULAR))); -#endif return launches_in_window ? l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW) :
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc index 439cf70..ecdc856 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -3,9 +3,13 @@ // found in the LICENSE file. #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" +#include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm/window_state.h" +#include "ash/common/wm_shell.h" +#include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/shelf/shelf_delegate.h" #include "ash/shelf/shelf_util.h" +#include "ash/shell.h" #include "ash/wm/window_state_aura.h" #include "ash/wm/window_util.h" #include "base/bind.h" @@ -20,6 +24,7 @@ #include "components/exo/shell_surface.h" #include "components/signin/core/account_id/account_id.h" #include "components/user_manager/user_manager.h" +#include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" #include "ui/base/base_window.h" @@ -33,6 +38,17 @@ NON_ACTIVE, // Fullscreen was not activated for an app. }; +blink::WebScreenOrientationLockType BlinkOrientationLockFromMojom( + arc::mojom::OrientationLock orientation_lock) { + if (orientation_lock == arc::mojom::OrientationLock::PORTRAIT) { + return blink::WebScreenOrientationLockPortrait; + } else if (orientation_lock == arc::mojom::OrientationLock::LANDSCAPE) { + return blink::WebScreenOrientationLockLandscape; + } else { + return blink::WebScreenOrientationLockAny; + } +} + } // namespace class ArcAppWindowLauncherController::AppWindow : public ui::BaseWindow { @@ -155,6 +171,19 @@ void SetAlwaysOnTop(bool always_on_top) override { NOTREACHED(); } + arc::mojom::OrientationLock requested_orientation_lock() const { + return requested_orientation_lock_; + } + + void set_requested_orientation_lock(arc::mojom::OrientationLock lock) { + has_requested_orientation_lock_ = true; + requested_orientation_lock_ = lock; + } + + bool has_requested_orientation_lock() const { + return has_requested_orientation_lock_; + } + private: arc::mojom::AppInstance* GetAppInstance() { arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); @@ -183,6 +212,10 @@ // Unowned pointer, represents host Arc window. views::Widget* widget_ = nullptr; + arc::mojom::OrientationLock requested_orientation_lock_ = + arc::mojom::OrientationLock::NONE; + bool has_requested_orientation_lock_ = false; + DISALLOW_COPY_AND_ASSIGN(AppWindow); }; @@ -199,6 +232,8 @@ ArcAppWindowLauncherController::~ArcAppWindowLauncherController() { if (observed_profile_) StopObserving(observed_profile_); + if (observing_shell_) + ash::WmShell::Get()->RemoveShellObserver(this); } // static @@ -284,6 +319,14 @@ return; if (task_id) { + // We need to add the observer after exo started observing shell + // because we want to update the orientation after exo send + // the layout switch information. + if (!observing_shell_) { + observing_shell_ = true; + ash::WmShell::Get()->AddShellObserver(this); + } + AppWindow* app_window = GetAppWindowForTask(task_id); if (app_window) { app_window->set_widget(views::Widget::GetWidgetForNativeWindow(window)); @@ -293,6 +336,11 @@ chrome::MultiUserWindowManager::GetInstance()->SetWindowOwner( window, user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId()); + if (ash::WmShell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled()) { + SetOrientationLockForAppWindow(app_window); + } } } } @@ -391,6 +439,23 @@ } } +void ArcAppWindowLauncherController::OnTaskOrientationLockRequested( + int32_t task_id, + const arc::mojom::OrientationLock orientation_lock) { + // Don't save to AppInfo because this is requested in runtime. + TaskIdToAppWindow::iterator app_it = task_id_to_app_window_.find(task_id); + if (app_it == task_id_to_app_window_.end()) + return; + AppWindow* app_window = app_it->second.get(); + app_window->set_requested_orientation_lock(orientation_lock); + + if (ash::WmShell::Get() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled()) { + SetOrientationLockForAppWindow(app_window); + } +} + AppWindowLauncherItemController* ArcAppWindowLauncherController::ControllerForWindow(aura::Window* window) { AppWindow* app_window = GetAppWindowForTask(active_task_id_); @@ -414,6 +479,18 @@ OnTaskSetActive(active_task_id_); } +void ArcAppWindowLauncherController::OnMaximizeModeStarted() { + for (auto& it : task_id_to_app_window_) + SetOrientationLockForAppWindow(it.second.get()); +} + +void ArcAppWindowLauncherController::OnMaximizeModeEnded() { + ash::ScreenOrientationController* orientation_controller = + ash::Shell::GetInstance()->screen_orientation_controller(); + // Don't unlock one by one because it'll switch to next rotation. + orientation_controller->UnlockAll(); +} + void ArcAppWindowLauncherController::StartObserving(Profile* profile) { aura::Env* env = aura::Env::GetInstanceDontCreate(); if (env) @@ -477,3 +554,24 @@ } app_window->ResetController(); } + +void ArcAppWindowLauncherController::SetOrientationLockForAppWindow( + AppWindow* app_window) { + ash::Shell* shell = ash::Shell::GetInstance(); + aura::Window* window = app_window->widget()->GetNativeWindow(); + if (!window) + return; + arc::mojom::OrientationLock orientation_lock; + if (app_window->has_requested_orientation_lock()) { + orientation_lock = app_window->requested_orientation_lock(); + } else { + ArcAppListPrefs* prefs = ArcAppListPrefs::Get(observed_profile_); + std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = + prefs->GetApp(app_window->app_id()); + if (!app_info) + return; + orientation_lock = app_info->orientation_lock; + } + shell->screen_orientation_controller()->LockOrientationForWindow( + window, BlinkOrientationLockFromMojom(orientation_lock)); +}
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h index cd70f28..68a6babf 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h
@@ -9,6 +9,7 @@ #include <memory> #include <vector> +#include "ash/common/shell_observer.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h" @@ -36,6 +37,7 @@ class ArcAppWindowLauncherController : public AppWindowLauncherController, public aura::EnvObserver, public aura::WindowObserver, + public ash::ShellObserver, public ArcAppListPrefs::Observer { public: ArcAppWindowLauncherController(ChromeLauncherController* owner, @@ -65,6 +67,10 @@ aura::Window* gained_active, aura::Window* lost_active) override; + // ash::ShellObserver: + void OnMaximizeModeStarted() override; + void OnMaximizeModeEnded() override; + // ArcAppListPrefs::Observer: void OnAppReadyChanged(const std::string& app_id, bool ready) override; void OnAppRemoved(const std::string& app_id) override; @@ -73,6 +79,9 @@ const std::string& activity) override; void OnTaskDestroyed(int task_id) override; void OnTaskSetActive(int32_t task_id) override; + void OnTaskOrientationLockRequested( + int32_t task_id, + const arc::mojom::OrientationLock orientation_lock) override; private: class AppWindow; @@ -91,6 +100,8 @@ void CheckForAppWindowWidget(aura::Window* window); + void SetOrientationLockForAppWindow(AppWindow* app_window); + // AppWindowLauncherController: AppWindowLauncherItemController* ControllerForWindow( aura::Window* window) override; @@ -102,6 +113,7 @@ AppControllerMap app_controller_map_; std::vector<aura::Window*> observed_windows_; Profile* observed_profile_ = nullptr; + bool observing_shell_ = false; DISALLOW_COPY_AND_ASSIGN(ArcAppWindowLauncherController); };
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.cc index 84f657ad..174b770 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.cc
@@ -59,5 +59,7 @@ const content::NotificationDetails& details) { DCHECK_EQ(chrome::NOTIFICATION_BROWSER_CLOSING, type); DCHECK_EQ(browser_, content::Source<Browser>(source).ptr()); + registrar_.Remove(this, chrome::NOTIFICATION_BROWSER_CLOSING, + content::Source<Browser>(browser_)); browser_ = nullptr; }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc index 95f9574..c39afdf9 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -18,12 +18,15 @@ #include "ash/common/shelf/shelf_item_delegate_manager.h" #include "ash/common/shelf/shelf_model.h" #include "ash/common/shelf/shelf_model_observer.h" +#include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" +#include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/shell.h" #include "ash/test/ash_test_helper.h" #include "ash/test/shelf_item_delegate_manager_test_api.h" #include "ash/test/test_session_state_delegate.h" #include "ash/test/test_shell_delegate.h" +#include "ash/wm/window_util.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" @@ -98,12 +101,15 @@ #include "ui/aura/client/window_tree_client.h" #include "ui/aura/window.h" #include "ui/base/models/menu_model.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/views/widget/widget.h" using base::ASCIIToUTF16; using extensions::Extension; using extensions::Manifest; using extensions::UnloadedExtensionInfo; +using arc::mojom::OrientationLock; namespace { const char* offline_gmail_url = "https://mail.google.com/mail/mu/u"; @@ -306,6 +312,10 @@ ~ChromeLauncherControllerImplTest() override {} void SetUp() override { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + command_line->AppendSwitch(ash::switches::kAshUseFirstDisplayAsInternal); + command_line->AppendSwitch(ash::switches::kAshEnableTouchViewTesting); + app_list::AppListSyncableServiceFactory::SetUseInTesting(); BrowserWithTestWindowTest::SetUp(); @@ -832,6 +842,12 @@ base::RunLoop().RunUntilIdle(); } + void EnableTabletMode(bool enable) { + ash::MaximizeModeController* controller = + ash::WmShell::Get()->maximize_mode_controller(); + controller->EnableMaximizeModeWindowManager(enable); + } + void ValidateArcState(bool arc_enabled, bool arc_managed, arc::ArcAuthService::State state, @@ -843,20 +859,57 @@ } // Creates app window and set optional Arc application id. - views::Widget* CreateAppWindow(std::string* window_app_id) { + views::Widget* CreateArcWindow(std::string& window_app_id) { views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); params.bounds = gfx::Rect(5, 5, 20, 20); + params.context = GetContext(); views::Widget* widget = new views::Widget(); widget->Init(params); widget->Show(); widget->Activate(); - if (window_app_id) { - exo::ShellSurface::SetApplicationId(widget->GetNativeWindow(), - window_app_id); - } + exo::ShellSurface::SetApplicationId(widget->GetNativeWindow(), + &window_app_id); return widget; } + arc::mojom::AppInfo CreateAppInfo(const std::string& name, + const std::string& activity, + const std::string& package_name, + OrientationLock lock) { + arc::mojom::AppInfo appinfo; + appinfo.name = name; + appinfo.package_name = package_name; + appinfo.activity = activity; + appinfo.orientation_lock = lock; + return appinfo; + } + + std::string AddArcAppAndShortcut(const arc::mojom::AppInfo& app_info) { + ArcAppListPrefs* const prefs = arc_test_.arc_app_list_prefs(); + // Adding app to the prefs, and check that the app is accessible by id. + prefs->AddAppAndShortcut( + app_info.name, app_info.package_name, app_info.activity, + std::string() /* intent_uri */, std::string() /* icon_resource_id */, + false /* sticky */, true /* notifications_enabled */, + false /* shortcut */, app_info.orientation_lock); + const std::string app_id = + ArcAppListPrefs::GetAppId(app_info.package_name, app_info.activity); + EXPECT_TRUE(prefs->GetApp(app_id)); + return app_id; + } + + void NotifyOnTaskCreated(const arc::mojom::AppInfo& appinfo, + int32_t task_id) { + ArcAppListPrefs* const prefs = arc_test_.arc_app_list_prefs(); + prefs->OnTaskCreated(task_id, appinfo.package_name, appinfo.activity); + } + + void NotifyOnTaskOrientationLockRequested(int32_t task_id, + OrientationLock lock) { + ArcAppListPrefs* const prefs = arc_test_.arc_app_list_prefs(); + prefs->OnTaskOrientationLockRequested(task_id, lock); + } + // Needed for extension service & friends to work. scoped_refptr<Extension> extension1_; scoped_refptr<Extension> extension2_; @@ -3345,24 +3398,9 @@ TEST_F(ChromeLauncherControllerImplTest, ArcAppPinPolicy) { arc_test_.SetUp(profile()); InitLauncherControllerWithBrowser(); - - arc::mojom::AppInfo appinfo; - appinfo.name = "Some App"; - appinfo.activity = "SomeActivity"; - appinfo.package_name = "com.example.app"; - - ArcAppListPrefs* const prefs = arc_test_.arc_app_list_prefs(); - ASSERT_TRUE(prefs); - - // Adding app to the prefs, and check that the app is accessible by id. - prefs->AddAppAndShortcut(appinfo.name, appinfo.package_name, appinfo.activity, - std::string() /* intent_uri */, - std::string() /* icon_resource_id */, - false /* sticky */, true /* notifications_enabled */, - false /* shortcut */); - const std::string app_id = - ArcAppListPrefs::GetAppId(appinfo.package_name, appinfo.activity); - EXPECT_TRUE(prefs->GetApp(app_id)); + arc::mojom::AppInfo appinfo = CreateAppInfo( + "Some App", "SomeActivity", "com.example.app", OrientationLock::NONE); + const std::string app_id = AddArcAppAndShortcut(appinfo); // Set policy, that makes pins ARC app. Unlike native extension, for ARC app // package_name (not hash) specified as id. In this test we check that @@ -3427,3 +3465,137 @@ ValidateArcState(true, false, arc::ArcAuthService::State::FETCHING_CODE, "AppList, Chrome"); } + +TEST_F(ChromeLauncherControllerImplTest, ArcOrientationLock) { + DCHECK(display::Display::HasInternalDisplay()); + + extension_service_->AddExtension(arc_support_host_.get()); + arc_test_.SetUp(profile()); + EnableArc(true); + EnableTabletMode(true); + + InitLauncherController(); + arc::ArcAuthService::SetShelfDelegateForTesting(launcher_controller_.get()); + arc::mojom::AppInfo appinfo_none = + CreateAppInfo("None", "None", "com.example.app", OrientationLock::NONE); + arc::mojom::AppInfo appinfo_landscape = CreateAppInfo( + "Landscape", "Landscape", "com.example.app", OrientationLock::LANDSCAPE); + arc::mojom::AppInfo appinfo_portrait = CreateAppInfo( + "Portrait", "Portrait", "com.example.app", OrientationLock::PORTRAIT); + + const std::string app_id_none = AddArcAppAndShortcut(appinfo_none); + const std::string app_id_landscape = AddArcAppAndShortcut(appinfo_landscape); + const std::string app_id_portrait = AddArcAppAndShortcut(appinfo_portrait); + + int32_t task_id_none = 1; + int32_t task_id_landscape = 2; + int32_t task_id_portrait = 3; + + // This needs to be kept on stack because window's property has + // refeference to this. + std::string window_app_id_none("org.chromium.arc.1"); + std::string window_app_id_landscape("org.chromium.arc.2"); + std::string window_app_id_portrait("org.chromium.arc.3"); + + ash::ScreenOrientationController* controller = + ash::Shell::GetInstance()->screen_orientation_controller(); + + // Creating a window with NONE orientation will not lock the screen. + views::Widget* window_none = CreateArcWindow(window_app_id_none); + NotifyOnTaskCreated(appinfo_none, task_id_none); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Create a arc window with PORTRAIT orientation locks the screen to 90. + views::Widget* window_portrait = CreateArcWindow(window_app_id_portrait); + NotifyOnTaskCreated(appinfo_portrait, task_id_portrait); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Create a arc window with LANDSCAPE orientation locks the screen to 0. + views::Widget* window_landscape = CreateArcWindow(window_app_id_landscape); + NotifyOnTaskCreated(appinfo_landscape, task_id_landscape); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Activating a window with NON orientation unlocks the screen. + window_none->Activate(); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Activating a window with PORTRAIT orientation locks the screen to 90. + window_portrait->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Disable Tablet mode, and make sure the screen is unlocked. + EnableTabletMode(false); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Re-enable Tablet mode, and make sure the screen is locked to 90. + EnableTabletMode(true); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + window_portrait->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + window_landscape->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // OnTaskOrientationLockRequested can overwrite the current lock. + NotifyOnTaskOrientationLockRequested(task_id_landscape, + OrientationLock::NONE); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + NotifyOnTaskOrientationLockRequested(task_id_landscape, + OrientationLock::PORTRAIT); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // Non active window won't change the lock. + NotifyOnTaskOrientationLockRequested(task_id_none, + OrientationLock::LANDSCAPE); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // But activating it will change the locked orinetation. + window_none->Activate(); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // OnTaskOrientationLockRequested will not lock the screen in non Tablet mode. + EnableTabletMode(false); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + NotifyOnTaskOrientationLockRequested(task_id_none, OrientationLock::PORTRAIT); + EXPECT_FALSE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_0, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); + + // But it remembers the orientation lock and use it when Tablet mode is + // enabled. + EnableTabletMode(true); + EXPECT_TRUE(controller->rotation_locked()); + EXPECT_EQ(display::Display::ROTATE_90, + display::Screen::GetScreen()->GetPrimaryDisplay().rotation()); +}
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc index 4c8c1d9..efae8f1 100644 --- a/chrome/browser/ui/browser_navigator_browsertest.cc +++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -68,7 +68,7 @@ std::string url_string = url.spec(); const std::string long_prefix = "chrome://chrome/"; const std::string short_prefix = "chrome://"; - if (url_string.find(long_prefix) != 0) + if (!base::StartsWith(url_string, long_prefix, base::CompareCase::SENSITIVE)) return url; url_string.replace(0, long_prefix.length(), short_prefix); return GURL(url_string);
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.mm index 3976e0f..3e268749 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_model_observer_for_cocoa.mm
@@ -65,7 +65,7 @@ void BookmarkModelObserverForCocoa::BookmarkNodeChanged( BookmarkModel* model, const BookmarkNode* node) { - if (!nodes_.size() || nodes_.find(node) != nodes_.end()) + if (nodes_.empty() || nodes_.find(node) != nodes_.end()) Notify(); }
diff --git a/chrome/browser/ui/find_bar/find_bar_controller.cc b/chrome/browser/ui/find_bar/find_bar_controller.cc index 909749f..f30cf92 100644 --- a/chrome/browser/ui/find_bar/find_bar_controller.cc +++ b/chrome/browser/ui/find_bar/find_bar_controller.cc
@@ -8,6 +8,7 @@ #include "base/i18n/rtl.h" #include "base/logging.h" +#include "base/strings/string_util.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" @@ -143,8 +144,10 @@ const base::string16& last_search = find_tab_helper->previous_find_text(); const base::string16& current_search = find_tab_helper->find_text(); - if (last_search.find(current_search) != 0) + if (base::StartsWith(last_search, current_search, + base::CompareCase::SENSITIVE)) { find_bar_->AudibleAlert(); + } } } } else if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
diff --git a/chrome/browser/ui/signin_view_controller_delegate.h b/chrome/browser/ui/signin_view_controller_delegate.h index f2e767a..445a60f4 100644 --- a/chrome/browser/ui/signin_view_controller_delegate.h +++ b/chrome/browser/ui/signin_view_controller_delegate.h
@@ -48,6 +48,10 @@ // content::WebContentsDelegate: bool HandleContextMenu(const content::ContextMenuParams& params) override; + // WebContents is used for executing javascript in the context of a modal sync + // confirmation dialog. + content::WebContents* web_contents_for_testing() { return web_contents_; } + protected: SigninViewControllerDelegate(SigninViewController* signin_view_controller, content::WebContents* web_contents);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index d7d4fbc..3c621fd8 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1029,20 +1029,15 @@ DCHECK(ContainsIndex(index)); DCHECK(id == CommandCloseTabsToRight || id == CommandCloseOtherTabs); bool is_selected = IsTabSelected(index); - int start; + int last_unclosed_tab = -1; if (id == CommandCloseTabsToRight) { - if (is_selected) { - start = selection_model_.selected_indices()[ - selection_model_.selected_indices().size() - 1] + 1; - } else { - start = index + 1; - } - } else { - start = 0; + last_unclosed_tab = + is_selected ? selection_model_.selected_indices().back() : index; } + // NOTE: callers expect the vector to be sorted in descending order. std::vector<int> indices; - for (int i = count() - 1; i >= start; --i) { + for (int i = count() - 1; i > last_unclosed_tab; --i) { if (i != index && !IsTabPinned(i) && (!is_selected || !IsTabSelected(i))) indices.push_back(i); }
diff --git a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc index 6243afd..0e20516 100644 --- a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc +++ b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
@@ -7,7 +7,6 @@ #include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/ui_test_utils.h" @@ -17,7 +16,6 @@ #include "ui/base/ime/composition_text.h" #include "ui/base/ime/dummy_text_input_client.h" #include "ui/base/ime/input_method.h" -#include "url/origin.h" namespace extensions { @@ -109,8 +107,7 @@ IN_PROC_BROWSER_TEST_F(InputImeApiTest, SendKeyEventsOnNormalPage) { // Navigates to special page that sendKeyEvents API has limition with. - GURL test_url(chrome::kChromeUINewTabURL); - ui_test_utils::NavigateToURL(browser(), test_url); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); // Manipulates the focused text input client because the follow cursor // window requires the text input focus. ui::InputMethod* input_method = @@ -125,34 +122,26 @@ ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_; - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - url::Origin origin(web_contents->GetLastCommittedURL()); + std::vector<std::unique_ptr<ui::KeyEvent>> key_events; + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE))); + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE))); + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_CONTROL_DOWN))); + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_CONTROL_DOWN))); + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE))); - // Don't check events if the url has not been correctly set. - if (url::Origin(test_url).IsSameOriginWith(origin)) { - std::vector<std::unique_ptr<ui::KeyEvent>> key_events; - key_events.push_back(std::unique_ptr<ui::KeyEvent>( - new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE))); - key_events.push_back(std::unique_ptr<ui::KeyEvent>( - new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE))); - key_events.push_back(std::unique_ptr<ui::KeyEvent>( - new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_CONTROL_DOWN))); - key_events.push_back(std::unique_ptr<ui::KeyEvent>(new ui::KeyEvent( - ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_CONTROL_DOWN))); - key_events.push_back(std::unique_ptr<ui::KeyEvent>( - new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE))); - - EXPECT_TRUE(CompareKeyEvents(key_events, input_method)); - } + EXPECT_TRUE(CompareKeyEvents(key_events, input_method)); input_method->DetachTextInputClient(client.get()); } IN_PROC_BROWSER_TEST_F(InputImeApiTest, SendKeyEventsOnSpecialPage) { // Navigates to special page that sendKeyEvents API has limition with. - GURL test_url("chrome://flags"); - ui_test_utils::NavigateToURL(browser(), test_url); + ui_test_utils::NavigateToURL(browser(), GURL("chrome://flags")); ui::InputMethod* input_method = browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod(); @@ -166,20 +155,13 @@ ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_; - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - url::Origin origin(web_contents->GetLastCommittedURL()); + std::vector<std::unique_ptr<ui::KeyEvent>> key_events; + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE))); + key_events.push_back(std::unique_ptr<ui::KeyEvent>( + new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE))); - // Don't check events if the url has not been correctly set. - if (url::Origin(test_url).IsSameOriginWith(origin)) { - std::vector<std::unique_ptr<ui::KeyEvent>> key_events; - key_events.push_back(std::unique_ptr<ui::KeyEvent>( - new ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE))); - key_events.push_back(std::unique_ptr<ui::KeyEvent>( - new ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE))); - - EXPECT_TRUE(CompareKeyEvents(key_events, input_method)); - } + EXPECT_TRUE(CompareKeyEvents(key_events, input_method)); input_method->DetachTextInputClient(client.get()); }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 7885a46..6c192ae 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -734,7 +734,7 @@ do_move = false; } if (do_move) { - WebContents* last_contents = drag_data_[drag_data_.size() - 1].contents; + WebContents* last_contents = drag_data_.back().contents; int index_of_last_item = attached_model->GetIndexOfWebContents(last_contents); if (initial_move_) {
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc index dc935b4..94955902 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc
@@ -6,14 +6,13 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/run_loop.h" #include "chrome/browser/ui/website_settings/mock_permission_bubble_view.h" #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" MockPermissionBubbleFactory::MockPermissionBubbleFactory( - bool is_browser_test, PermissionBubbleManager* manager) - : is_browser_test_(is_browser_test), - can_update_ui_(false), + : can_update_ui_(false), show_count_(0), requests_count_(0), total_requests_count_(0), @@ -35,7 +34,7 @@ std::unique_ptr<PermissionBubbleView> MockPermissionBubbleFactory::Create( Browser* browser) { MockPermissionBubbleView* view = - new MockPermissionBubbleView(this, manager_, is_browser_test_); + new MockPermissionBubbleView(this, manager_); view->can_update_ui_ = can_update_ui_; return base::WrapUnique(view); } @@ -64,12 +63,22 @@ return false; } +void MockPermissionBubbleFactory::WaitForPermissionBubble() { + if (is_visible()) + return; + DCHECK(show_bubble_quit_closure_.is_null()); + base::RunLoop loop; + show_bubble_quit_closure_ = loop.QuitClosure(); + loop.Run(); + show_bubble_quit_closure_ = base::Closure(); +} + // static std::unique_ptr<PermissionBubbleView> MockPermissionBubbleFactory::DoNotCreate( Browser* browser) { NOTREACHED(); return base::WrapUnique( - new MockPermissionBubbleView(nullptr, nullptr, false)); + new MockPermissionBubbleView(nullptr, nullptr)); } void MockPermissionBubbleFactory::UpdateResponseType() { @@ -83,6 +92,9 @@ return; } views_.push_back(view); + + if (!show_bubble_quit_closure_.is_null()) + show_bubble_quit_closure_.Run(); } void MockPermissionBubbleFactory::HideView(MockPermissionBubbleView* view) {
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h index d3572d3a..471039f 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h
@@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/callback.h" #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" class Browser; @@ -21,10 +22,7 @@ // chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc class MockPermissionBubbleFactory { public: - // Set |is_browser_test| if in a browser test in order to interact with the - // message loop. That shouldn't be done in unit tests. - MockPermissionBubbleFactory(bool is_browser_test, - PermissionBubbleManager* manager); + explicit MockPermissionBubbleFactory(PermissionBubbleManager* manager); ~MockPermissionBubbleFactory(); // Create method called by the PBM to show a bubble. @@ -49,6 +47,8 @@ // Number of requests seen. int total_request_count() { return total_requests_count_; } + void WaitForPermissionBubble(); + private: friend class MockPermissionBubbleView; @@ -60,7 +60,6 @@ void ShowView(MockPermissionBubbleView* view); void HideView(MockPermissionBubbleView* view); - bool is_browser_test_; bool can_update_ui_; int show_count_; int requests_count_; @@ -68,6 +67,8 @@ std::vector<MockPermissionBubbleView*> views_; PermissionBubbleManager::AutoResponseType response_type_; + base::Closure show_bubble_quit_closure_; + // The bubble manager that will be associated with this factory. PermissionBubbleManager* manager_;
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc b/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc index 631cb35..470ac0a4 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc
@@ -22,9 +22,6 @@ factory_->total_requests_count_ += manager_->requests_.size(); factory_->UpdateResponseType(); is_visible_ = true; - - if (browser_test_) - base::MessageLoopForUI::current()->QuitWhenIdle(); } bool MockPermissionBubbleView::CanAcceptRequestUpdate() { @@ -51,10 +48,8 @@ MockPermissionBubbleView::MockPermissionBubbleView( MockPermissionBubbleFactory* factory, - PermissionBubbleManager* manager, - bool browser_test) + PermissionBubbleManager* manager) : factory_(factory), manager_(manager), - browser_test_(browser_test), can_update_ui_(true), is_visible_(false) {}
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_view.h b/chrome/browser/ui/website_settings/mock_permission_bubble_view.h index 980d9083..2a27f997 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_view.h +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_view.h
@@ -32,12 +32,10 @@ friend class MockPermissionBubbleFactory; MockPermissionBubbleView(MockPermissionBubbleFactory* factory, - PermissionBubbleManager* manager, - bool browser_test); + PermissionBubbleManager* manager); MockPermissionBubbleFactory* factory_; PermissionBubbleManager* manager_; - bool browser_test_; bool can_update_ui_; bool is_visible_; };
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc b/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc index 9e2436c..01155cb 100644 --- a/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc +++ b/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc
@@ -37,7 +37,7 @@ InProcessBrowserTest::SetUpOnMainThread(); PermissionBubbleManager* manager = GetPermissionBubbleManager(); mock_permission_bubble_factory_.reset( - new MockPermissionBubbleFactory(true, manager)); + new MockPermissionBubbleFactory(manager)); manager->DisplayPendingRequests(); } @@ -51,12 +51,6 @@ browser()->tab_strip_model()->GetActiveWebContents()); } - void WaitForPermissionBubble() { - if (bubble_factory()->is_visible()) - return; - content::RunMessageLoop(); - } - MockPermissionBubbleFactory* bubble_factory() { return mock_permission_bubble_factory_.get(); } @@ -86,7 +80,7 @@ browser(), embedded_test_server()->GetURL("/permissions/requests-before-load.html"), 1); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); EXPECT_EQ(2, bubble_factory()->total_request_count()); @@ -102,7 +96,7 @@ embedded_test_server()->GetURL( "/permissions/requests-before-after-load.html"), 1); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); EXPECT_EQ(1, bubble_factory()->total_request_count()); @@ -123,13 +117,13 @@ browser(), embedded_test_server()->GetURL("/permissions/requests-before-load.html"), 1); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( browser(), embedded_test_server()->GetURL("/permissions/requests-before-load.html"), 1); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(2, bubble_factory()->show_count()); EXPECT_EQ(4, bubble_factory()->total_request_count()); @@ -151,14 +145,14 @@ browser(), embedded_test_server()->GetURL("/permissions/requests-before-load.html"), 1); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( browser(), embedded_test_server()->GetURL( "/permissions/requests-before-load.html#0"), 1); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); EXPECT_EQ(2, bubble_factory()->total_request_count()); @@ -182,7 +176,7 @@ ExecuteScriptAndGetValue( browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), "navigator.geolocation.getCurrentPosition(function(){});"); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); EXPECT_EQ(1, bubble_factory()->total_request_count()); @@ -219,7 +213,7 @@ embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); EXPECT_TRUE(content::ExecuteScript(web_contents, "requestGeolocation();")); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); EXPECT_EQ(1, bubble_factory()->total_request_count()); } @@ -249,7 +243,7 @@ variations::testing::ClearAllVariationParams(); EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); - WaitForPermissionBubble(); + bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); EXPECT_EQ(1, bubble_factory()->total_request_count()); }
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc b/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc index e2bf89d..a75aab1 100644 --- a/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc +++ b/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc
@@ -36,7 +36,7 @@ NavigateAndCommit(GURL("http://www.google.com")); manager_.reset(new PermissionBubbleManager(web_contents())); - view_factory_.reset(new MockPermissionBubbleFactory(false, manager_.get())); + view_factory_.reset(new MockPermissionBubbleFactory(manager_.get())); } void TearDown() override {
diff --git a/chrome/browser/ui/webui/browsing_history_handler.cc b/chrome/browser/ui/webui/browsing_history_handler.cc index 82fd5d3..338e1a6 100644 --- a/chrome/browser/ui/webui/browsing_history_handler.cc +++ b/chrome/browser/ui/webui/browsing_history_handler.cc
@@ -905,7 +905,10 @@ exploded.day_of_month = 1; if (offset == 0) { - options->begin_time = base::Time::FromLocalExploded(exploded); + if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) { + // TODO(maksims): implement errors handling here. + NOTIMPLEMENTED(); + } // Set the end time of this first search to null (which will // show results from the future, should the user's clock have @@ -919,12 +922,18 @@ exploded.month -= offset - 1; // Set the correct year. NormalizeMonths(&exploded); - options->end_time = base::Time::FromLocalExploded(exploded); + if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) { + // TODO(maksims): implement errors handling here. + NOTIMPLEMENTED(); + } exploded.month -= 1; // Set the correct year NormalizeMonths(&exploded); - options->begin_time = base::Time::FromLocalExploded(exploded); + if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) { + // TODO(maksims): implement errors handling here. + NOTIMPLEMENTED(); + } } }
diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc index 5e0ec9e..c80543e 100644 --- a/chrome/browser/ui/webui/history_ui.cc +++ b/chrome/browser/ui/webui/history_ui.cc
@@ -101,13 +101,8 @@ source->AddLocalizedString("clearAllHistory", IDS_HISTORY_OPEN_CLEAR_BROWSING_DATA_DIALOG); - auto availability = IncognitoModePrefs::GetAvailability(profile->GetPrefs()); - base::string16 delete_warning = availability == IncognitoModePrefs::ENABLED ? - l10n_util::GetStringFUTF16(IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING, - base::UTF8ToUTF16(kIncognitoModeShortcut)) : - l10n_util::GetStringUTF16( - IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING_NO_INCOGNITO); - source->AddString("deleteWarning", delete_warning); + source->AddString("deleteWarning", + HistoryUI::GetDeleteWarningString(profile)); source->AddLocalizedString("removeBookmark", IDS_HISTORY_REMOVE_BOOKMARK); source->AddLocalizedString("actionMenuDescription", @@ -204,3 +199,14 @@ return ResourceBundle::GetSharedInstance(). LoadDataResourceBytesForScale(IDR_HISTORY_FAVICON, scale_factor); } + +// static +base::string16 HistoryUI::GetDeleteWarningString(Profile* profile) { + auto availability = IncognitoModePrefs::GetAvailability(profile->GetPrefs()); + return availability == IncognitoModePrefs::ENABLED + ? l10n_util::GetStringFUTF16( + IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING, + base::UTF8ToUTF16(kIncognitoModeShortcut)) + : l10n_util::GetStringUTF16( + IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING_NO_INCOGNITO); +}
diff --git a/chrome/browser/ui/webui/history_ui.h b/chrome/browser/ui/webui/history_ui.h index 0b576bc8..5f4eb1b 100644 --- a/chrome/browser/ui/webui/history_ui.h +++ b/chrome/browser/ui/webui/history_ui.h
@@ -9,6 +9,8 @@ #include "content/public/browser/web_ui_controller.h" #include "ui/base/layout.h" +class Profile; + namespace base { class RefCountedMemory; } @@ -21,6 +23,10 @@ static base::RefCountedMemory* GetFaviconResourceBytes( ui::ScaleFactor scale_factor); + // Returns a localized string warning about deleting history. Takes into + // account whether or not incognito mode is available. + static base::string16 GetDeleteWarningString(Profile* profile); + private: DISALLOW_COPY_AND_ASSIGN(HistoryUI); };
diff --git a/chrome/browser/ui/webui/md_history_ui.cc b/chrome/browser/ui/webui/md_history_ui.cc index e2dac02..425f197c 100644 --- a/chrome/browser/ui/webui/md_history_ui.cc +++ b/chrome/browser/ui/webui/md_history_ui.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/webui/browsing_history_handler.h" #include "chrome/browser/ui/webui/foreign_session_handler.h" #include "chrome/browser/ui/webui/history_login_handler.h" +#include "chrome/browser/ui/webui/history_ui.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/settings/people_handler.h" #include "chrome/common/chrome_features.h" @@ -43,6 +44,8 @@ IDS_CLEAR_BROWSING_DATA_TITLE); source->AddLocalizedString("clearSearch", IDS_MD_HISTORY_CLEAR_SEARCH); source->AddLocalizedString("delete", IDS_MD_HISTORY_DELETE); + source->AddLocalizedString("deleteConfirm", + IDS_HISTORY_DELETE_PRIOR_VISITS_CONFIRM_BUTTON); source->AddLocalizedString("foundSearchResults", IDS_HISTORY_FOUND_SEARCH_RESULTS); source->AddLocalizedString("historyInterval", IDS_HISTORY_INTERVAL); @@ -68,6 +71,8 @@ source->AddLocalizedString("rangePrevious", IDS_HISTORY_RANGE_PREVIOUS); source->AddLocalizedString("removeBookmark", IDS_HISTORY_REMOVE_BOOKMARK); source->AddLocalizedString("removeFromHistory", IDS_HISTORY_REMOVE_PAGE); + source->AddLocalizedString("removeSelected", + IDS_HISTORY_REMOVE_SELECTED_ITEMS); source->AddLocalizedString("searchPrompt", IDS_MD_HISTORY_SEARCH_PROMPT); source->AddLocalizedString("searchResult", IDS_HISTORY_SEARCH_RESULT); source->AddLocalizedString("searchResults", IDS_HISTORY_SEARCH_RESULTS); @@ -77,6 +82,9 @@ IDS_MD_HISTORY_SIGN_IN_PROMO_DESC); source->AddLocalizedString("title", IDS_HISTORY_TITLE); + source->AddString("deleteWarning", + HistoryUI::GetDeleteWarningString(profile)); + bool allow_deleting_history = prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory); source->AddBoolean("allowDeletingHistory", allow_deleting_history);
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc index e048f3a..03a2524e 100644 --- a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc +++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -181,9 +181,12 @@ double seconds_since_epoch; if (base::StringToDouble(i->local_id, &seconds_since_epoch)) { base::Time capture_time = base::Time::FromDoubleT(seconds_since_epoch); - base::Time::Exploded lower_limit = {2012, 1, 0, 1, 0, 0, 0, 0}; - if (capture_time > base::Time::FromUTCExploded(lower_limit) && - capture_time < base::Time::Now()) { + const base::Time::Exploded lower_limit = {2012, 1, 0, 1, 0, 0, 0, 0}; + base::Time out_time; + bool conversion_success = + base::Time::FromUTCExploded(lower_limit, &out_time); + DCHECK(conversion_success); + if (capture_time > out_time && capture_time < base::Time::Now()) { value_w = base::TimeFormatFriendlyDateAndTime(capture_time); } }
diff --git a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc index f19e8bc..ad698087 100644 --- a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc +++ b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_impl.cc
@@ -40,16 +40,14 @@ using content::WebUIMessageHandler; using ui::WebDialogDelegate; -namespace { -const int kMaxHeight = 2000; -const int kMinHeight = 80; -const int kWidth = 340; -} - namespace media_router { namespace { +constexpr const int kMaxHeight = 2000; +constexpr const int kMinHeight = 80; +constexpr const int kWidth = 340; + // WebDialogDelegate that specifies what the Media Router dialog // will look like. class MediaRouterDialogDelegate : public WebDialogDelegate { @@ -169,7 +167,7 @@ } WebContents* MediaRouterDialogControllerImpl::GetMediaRouterDialog() const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return dialog_observer_.get() ? dialog_observer_->web_contents() : nullptr; } @@ -280,7 +278,7 @@ void MediaRouterDialogControllerImpl::OnDialogNavigated( const content::LoadCommittedDetails& details) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); WebContents* media_router_dialog = GetMediaRouterDialog(); CHECK(media_router_dialog); ui::PageTransition transition_type = details.entry->GetTransitionType(); @@ -301,7 +299,7 @@ void MediaRouterDialogControllerImpl::PopulateDialog( content::WebContents* media_router_dialog) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(media_router_dialog); if (!initiator() || !media_router_dialog->GetWebUI()) { Reset();
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc index 4a8afb4d..6b8fba8 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui.cc +++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -339,7 +339,7 @@ void MediaRouterUI::UpdateCastModes() { // Gets updated cast modes from |query_result_manager_| and forwards it to UI. - query_result_manager_->GetSupportedCastModes(&cast_modes_); + cast_modes_ = query_result_manager_->GetSupportedCastModes(); if (ui_initialized_) { handler_->UpdateCastModes(cast_modes_, GetPresentationRequestSourceName()); }
diff --git a/chrome/browser/ui/webui/media_router/query_result_manager.cc b/chrome/browser/ui/webui/media_router/query_result_manager.cc index e7f76d6d..ba2f04a7 100644 --- a/chrome/browser/ui/webui/media_router/query_result_manager.cc +++ b/chrome/browser/ui/webui/media_router/query_result_manager.cc
@@ -8,6 +8,7 @@ #include "base/stl_util.h" #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_sinks_observer.h" +#include "content/public/browser/browser_thread.h" namespace media_router { @@ -48,9 +49,9 @@ MediaCastMode cast_mode() const { return cast_mode_; } private: - MediaCastMode cast_mode_; + const MediaCastMode cast_mode_; std::vector<MediaSink::Id> latest_sink_ids_; - QueryResultManager* result_manager_; + QueryResultManager* const result_manager_; }; QueryResultManager::QueryResultManager(MediaRouter* router) : router_(router) { @@ -58,17 +59,17 @@ } QueryResultManager::~QueryResultManager() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } void QueryResultManager::AddObserver(Observer* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(observer); observers_.AddObserver(observer); } void QueryResultManager::RemoveObserver(Observer* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(observer); observers_.RemoveObserver(observer); } @@ -76,7 +77,7 @@ void QueryResultManager::StartSinksQuery(MediaCastMode cast_mode, const MediaSource& source, const GURL& origin) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (source.Empty()) { LOG(WARNING) << "StartSinksQuery called with empty source for " << cast_mode; @@ -97,7 +98,7 @@ } void QueryResultManager::StopSinksQuery(MediaCastMode cast_mode) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); RemoveObserverForCastMode(cast_mode); SetSourceForCastMode(cast_mode, MediaSource()); UpdateWithSinksQueryResult(cast_mode, std::vector<MediaSink>()); @@ -106,7 +107,7 @@ void QueryResultManager::SetSourceForCastMode( MediaCastMode cast_mode, const MediaSource& source) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); cast_mode_sources_[cast_mode] = source; } @@ -151,17 +152,16 @@ } } -void QueryResultManager::GetSupportedCastModes(CastModeSet* cast_modes) const { - DCHECK(cast_modes); - cast_modes->clear(); - for (const auto& observer_pair : sinks_observers_) { - cast_modes->insert(observer_pair.first); - } +CastModeSet QueryResultManager::GetSupportedCastModes() const { + CastModeSet modes; + for (const auto& observer_pair : sinks_observers_) + modes.insert(observer_pair.first); + return modes; } MediaSource QueryResultManager::GetSourceForCastMode( MediaCastMode cast_mode) const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto source_it = cast_mode_sources_.find(cast_mode); return source_it == cast_mode_sources_.end() ? MediaSource() : source_it->second;
diff --git a/chrome/browser/ui/webui/media_router/query_result_manager.h b/chrome/browser/ui/webui/media_router/query_result_manager.h index b56211b..ecffaec 100644 --- a/chrome/browser/ui/webui/media_router/query_result_manager.h +++ b/chrome/browser/ui/webui/media_router/query_result_manager.h
@@ -13,7 +13,6 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/observer_list.h" -#include "base/threading/thread_checker.h" #include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/browser/media/router/media_sink.h" #include "chrome/browser/media/router/media_source.h" @@ -47,8 +46,7 @@ // [Updates will be received by observer via OnResultsUpdated()] // ... // [When info on MediaSource is needed, i.e. when requesting route for a mode] -// CastModeSet cast_modes; -// result_manager.GetSupportedCastModes(&cast_modes); +// CastModeSet cast_modes = result_manager.GetSupportedCastModes(); // [Logic to select a MediaCastMode from the set] // MediaSource source = result_manager.GetSourceForCastMode( // MediaCastMode::TAB_MIRROR); @@ -56,7 +54,7 @@ // ... // } // -// Not thread-safe. Must be used on a single thread. +// Not thread-safe. Must be used on the UI thread. class QueryResultManager { public: class Observer { @@ -92,9 +90,8 @@ // Stops notifying observers for |cast_mode|. void StopSinksQuery(MediaCastMode cast_mode); - // Gets the set of cast modes that are being actively queried. |cast_mode_set| - // should be empty. - void GetSupportedCastModes(CastModeSet* cast_modes) const; + // Gets the set of cast modes that are being actively queried. + CastModeSet GetSupportedCastModes() const; // Returns the MediaSource registered for |cast_mode|. Returns an empty // MediaSource if there is none. @@ -140,9 +137,7 @@ base::ObserverList<Observer> observers_; // Not owned by this object. - MediaRouter* router_; - - base::ThreadChecker thread_checker_; + MediaRouter* const router_; DISALLOW_COPY_AND_ASSIGN(QueryResultManager); };
diff --git a/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc b/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc index 5ede9e7..0d580191 100644 --- a/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc +++ b/chrome/browser/ui/webui/media_router/query_result_manager_unittest.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/media/router/media_source_helper.h" #include "chrome/browser/media/router/mock_media_router.h" #include "chrome/browser/ui/webui/media_router/query_result_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -48,6 +49,7 @@ query_result_manager_.StartSinksQuery(cast_mode, source, GURL(kOrigin)); } + content::TestBrowserThreadBundle thread_bundle_; MockMediaRouter mock_router_; QueryResultManager query_result_manager_; MockObserver mock_observer_; @@ -60,7 +62,7 @@ if (expected.size() != arg.size()) { return false; } - for (int i = 0; i < static_cast<int>(expected.size()); i++) { + for (size_t i = 0; i < expected.size(); ++i) { if (!expected[i].Equals(arg[i])) { return false; } @@ -88,9 +90,7 @@ TEST_F(QueryResultManagerTest, StartStopSinksQuery) { GURL origin(kOrigin); - CastModeSet cast_modes; - - query_result_manager_.GetSupportedCastModes(&cast_modes); + CastModeSet cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_TRUE(cast_modes.empty()); MediaSource actual_source = query_result_manager_.GetSourceForCastMode(MediaCastMode::DEFAULT); @@ -101,7 +101,7 @@ .WillOnce(Return(true)); query_result_manager_.StartSinksQuery(MediaCastMode::DEFAULT, source, origin); - query_result_manager_.GetSupportedCastModes(&cast_modes); + cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_EQ(1u, cast_modes.size()); EXPECT_TRUE(ContainsKey(cast_modes, MediaCastMode::DEFAULT)); actual_source = query_result_manager_.GetSourceForCastMode( @@ -116,7 +116,7 @@ query_result_manager_.StartSinksQuery(MediaCastMode::DEFAULT, another_source, origin); - query_result_manager_.GetSupportedCastModes(&cast_modes); + cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_EQ(1u, cast_modes.size()); EXPECT_TRUE(ContainsKey(cast_modes, MediaCastMode::DEFAULT)); actual_source = query_result_manager_.GetSourceForCastMode( @@ -126,7 +126,7 @@ EXPECT_CALL(mock_router_, UnregisterMediaSinksObserver(_)).Times(1); query_result_manager_.StopSinksQuery(MediaCastMode::DEFAULT); - query_result_manager_.GetSupportedCastModes(&cast_modes); + cast_modes = query_result_manager_.GetSupportedCastModes(); EXPECT_TRUE(cast_modes.empty()); actual_source = query_result_manager_.GetSourceForCastMode( MediaCastMode::DEFAULT);
diff --git a/chrome/browser/ui/webui/ntp/OWNERS b/chrome/browser/ui/webui/ntp/OWNERS index 2dcd941..66c06dfd 100644 --- a/chrome/browser/ui/webui/ntp/OWNERS +++ b/chrome/browser/ui/webui/ntp/OWNERS
@@ -2,3 +2,4 @@ dbeam@chromium.org per-file ntp_user_data_logger*=beaudoin@chromium.org +per-file ntp_user_data_logger*=file://chrome/browser/search/OWNERS
diff --git a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc index 7f387ee..8234e141 100644 --- a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc
@@ -11,6 +11,16 @@ #include "base/files/file_util.h" #include "base/sys_info.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/browsing_data/browsing_data_appcache_helper.h" +#include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h" +#include "chrome/browser/browsing_data/browsing_data_cookie_helper.h" +#include "chrome/browser/browsing_data/browsing_data_database_helper.h" +#include "chrome/browser/browsing_data/browsing_data_file_system_helper.h" +#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h" +#include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" +#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h" #include "chrome/browser/chromeos/arc/arc_auth_service.h" #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/file_manager/path_util.h" @@ -23,6 +33,7 @@ #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/storage_partition.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" @@ -50,8 +61,10 @@ } // namespace StorageManagerHandler::StorageManagerHandler() - : browser_cache_size_(0), - browser_site_data_size_(0), + : browser_cache_size_(-1), + has_browser_cache_size_(false), + browser_site_data_size_(-1), + has_browser_site_data_size_(false), weak_ptr_factory_(this) { } @@ -258,6 +271,8 @@ } void StorageManagerHandler::UpdateBrowsingDataSize() { + has_browser_cache_size_ = false; + has_browser_site_data_size_ = false; Profile* const profile = Profile::FromWebUI(web_ui()); // Fetch the size of http cache in browsing data. // StoragePartitionHttpCacheDataRemover deletes itself when it is done. @@ -268,20 +283,54 @@ base::Bind(&StorageManagerHandler::OnGetBrowsingDataSize, weak_ptr_factory_.GetWeakPtr(), false)); - // TODO(fukino): fetch the size of site data in browsing data. + // Fetch the size of site data in browsing data. + if (!site_data_size_collector_.get()) { + content::StoragePartition* storage_partition = + content::BrowserContext::GetDefaultStoragePartition(profile); + site_data_size_collector_.reset(new SiteDataSizeCollector( + storage_partition->GetPath(), + new BrowsingDataCookieHelper(profile->GetRequestContext()), + new BrowsingDataDatabaseHelper(profile), + new BrowsingDataLocalStorageHelper(profile), + new BrowsingDataAppCacheHelper(profile), + new BrowsingDataIndexedDBHelper( + storage_partition->GetIndexedDBContext()), + BrowsingDataFileSystemHelper::Create( + storage_partition->GetFileSystemContext()), + BrowsingDataChannelIDHelper::Create(profile->GetRequestContext()), + new BrowsingDataServiceWorkerHelper( + storage_partition->GetServiceWorkerContext()), + new BrowsingDataCacheStorageHelper( + storage_partition->GetCacheStorageContext()), + BrowsingDataFlashLSOHelper::Create(profile))); + } + site_data_size_collector_->Fetch( + base::Bind(&StorageManagerHandler::OnGetBrowsingDataSize, + weak_ptr_factory_.GetWeakPtr(), true)); } void StorageManagerHandler::OnGetBrowsingDataSize(bool is_site_data, int64_t size) { - if (is_site_data) + if (is_site_data) { + has_browser_site_data_size_ = true; browser_site_data_size_ = size; - else + } else { + has_browser_cache_size_ = true; browser_cache_size_ = size; - - web_ui()->CallJavascriptFunctionUnsafe( - "options.StorageManager.setBrowsingDataSize", - base::StringValue(ui::FormatBytes(static_cast<int64_t>( - browser_cache_size_ + browser_site_data_size_)))); + } + if (has_browser_cache_size_ && has_browser_site_data_size_) { + base::string16 size_string; + if (browser_cache_size_ >= 0 && browser_site_data_size_ >= 0) { + size_string = ui::FormatBytes( + browser_site_data_size_ + browser_cache_size_); + } else { + size_string = l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN); + } + web_ui()->CallJavascriptFunctionUnsafe( + "options.StorageManager.setBrowsingDataSize", + base::StringValue(size_string)); + } } void StorageManagerHandler::UpdateOtherUsersSize() { @@ -303,15 +352,18 @@ void StorageManagerHandler::OnGetOtherUserSize(bool success, int64_t size) { user_sizes_.push_back(success ? size : -1); if (user_sizes_.size() == other_users_.size()) { - base::StringValue other_users_size(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN)); + base::string16 size_string; // If all the requests succeed, shows the total bytes in the UI. if (std::count(user_sizes_.begin(), user_sizes_.end(), -1) == 0) { - other_users_size = base::StringValue(ui::FormatBytes( - std::accumulate(user_sizes_.begin(), user_sizes_.end(), 0LL))); + size_string = ui::FormatBytes( + std::accumulate(user_sizes_.begin(), user_sizes_.end(), 0LL)); + } else { + size_string = l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN); } web_ui()->CallJavascriptFunctionUnsafe( - "options.StorageManager.setOtherUsersSize", other_users_size); + "options.StorageManager.setOtherUsersSize", + base::StringValue(size_string)); } } @@ -341,16 +393,18 @@ void StorageManagerHandler::OnGetArcSize(bool succeeded, arc::mojom::ApplicationsSizePtr size) { - base::StringValue arc_size(l10n_util::GetStringUTF16( - IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN)); + base::string16 size_string; if (succeeded) { uint64_t total_bytes = size->total_code_bytes + size->total_data_bytes + size->total_cache_bytes; - arc_size = base::StringValue(ui::FormatBytes(total_bytes)); + size_string = ui::FormatBytes(total_bytes); + } else { + size_string = l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_STORAGE_SIZE_UNKNOWN); } web_ui()->CallJavascriptFunctionUnsafe("options.StorageManager.setArcSize", - arc_size); + base::StringValue(size_string)); } void StorageManagerHandler::OnClearDriveCacheDone(bool success) {
diff --git a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.h b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.h index c6e1629..6103948 100644 --- a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.h +++ b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.h
@@ -7,10 +7,12 @@ #include <stdint.h> +#include <memory> #include <vector> #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/browsing_data/site_data_size_collector.h" #include "chrome/browser/ui/webui/options/options_ui.h" #include "components/arc/storage_manager/arc_storage_manager.h" #include "components/user_manager/user.h" @@ -88,9 +90,15 @@ // Total size of cache data in browsing data. int64_t browser_cache_size_; + // True if we have already received the size of http cache. + bool has_browser_cache_size_; + // Total size of site data in browsing data. int64_t browser_site_data_size_; + // True if we have already received the size of site data. + bool has_browser_site_data_size_; + // The list of other users whose directory sizes will be accumulated as the // size of "Other users". user_manager::UserList other_users_; @@ -98,6 +106,9 @@ // Fetched sizes of user directories. std::vector<int64_t> user_sizes_; + // Helper to compute the total size of all types of site date. + std::unique_ptr<SiteDataSizeCollector> site_data_size_collector_; + base::WeakPtrFactory<StorageManagerHandler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(StorageManagerHandler);
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index 9dd309b..b2dc9716 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -2,9 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" + +#include "base/run_loop.h" +#include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/signin/signin_promo.h" #include "chrome/browser/signin/signin_tracker_factory.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/signin_view_controller_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/webui/signin/get_auth_frame.h" #include "chrome/test/base/ui_test_utils.h" @@ -95,6 +100,13 @@ scoped_refptr<MessageLoopRunner> message_loop_runner_; }; +void RunLoopFor(base::TimeDelta duration) { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), duration); + run_loop.Run(); +} + } // anonymous namespace @@ -242,4 +254,37 @@ signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT); } +bool TryDismissSyncConfirmationDialog(Browser* browser) { + SigninViewController* signin_view_controller = + browser->signin_view_controller(); + DCHECK_NE(signin_view_controller, nullptr); + SigninViewControllerDelegate* delegate = signin_view_controller->delegate(); + if (delegate == nullptr) + return false; + content::WebContents* dialog_web_contents = + delegate->web_contents_for_testing(); + DCHECK_NE(dialog_web_contents, nullptr); + std::string message; + std::string js = + "if (document.getElementById('confirmButton') == null) {" + " window.domAutomationController.send('NotFound');" + "} else {" + " document.getElementById('confirmButton').click();" + " window.domAutomationController.send('Ok');" + "}"; + EXPECT_TRUE(content::ExecuteScriptAndExtractString(dialog_web_contents, js, + &message)); + return message == "Ok"; +} + +bool DismissSyncConfirmationDialog(Browser* browser, base::TimeDelta timeout) { + const base::Time expire_time = base::Time::Now() + timeout; + while (base::Time::Now() <= expire_time) { + if (TryDismissSyncConfirmationDialog(browser)) + return true; + RunLoopFor(base::TimeDelta::FromMilliseconds(1000)); + } + return false; +} + } // namespace login_ui_test_utils
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.h b/chrome/browser/ui/webui/signin/login_ui_test_utils.h index 6749654d..71c21725 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.h +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/time/time.h" #include "components/signin/core/browser/signin_metrics.h" class Browser; @@ -59,6 +60,11 @@ const std::string& email, const std::string& password); +// Waits for sync confirmation dialog to get displayed, then executes javascript +// to click on confirm button. Returns false if dialog wasn't dismissed before +// |timeout|. +bool DismissSyncConfirmationDialog(Browser* browser, base::TimeDelta timeout); + } // namespace login_ui_test_utils #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_LOGIN_UI_TEST_UTILS_H_
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc index 97712cfb..8c7387c 100644 --- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc +++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -140,16 +140,12 @@ } bool IsGuestModeEnabled() { - if (switches::IsMaterialDesignUserManager()) - return true; PrefService* service = g_browser_process->local_state(); DCHECK(service); return service->GetBoolean(prefs::kBrowserGuestModeEnabled); } bool IsAddPersonEnabled() { - if (switches::IsMaterialDesignUserManager()) - return true; PrefService* service = g_browser_process->local_state(); DCHECK(service); return service->GetBoolean(prefs::kBrowserAddPersonEnabled);
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc index 5a32788d..44c6884f 100644 --- a/chrome/browser/usb/usb_chooser_context.cc +++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -53,7 +53,7 @@ UsbChooserContext::UsbChooserContext(Profile* profile) : ChooserContextBase(profile, CONTENT_SETTINGS_TYPE_USB_CHOOSER_DATA), - is_off_the_record_(profile->IsOffTheRecord()), + is_incognito_(profile->IsOffTheRecord()), observer_(this) { usb_service_ = device::DeviceClient::Get()->GetUsbService(); if (usb_service_) @@ -102,7 +102,7 @@ object.SetString(kGuidKey, device->guid()); objects.push_back(base::WrapUnique(new ChooserContextBase::Object( requesting_origin, embedding_origin, &object, "preference", - is_off_the_record_))); + is_incognito_))); } }
diff --git a/chrome/browser/usb/usb_chooser_context.h b/chrome/browser/usb/usb_chooser_context.h index 39d6605..09b009c0 100644 --- a/chrome/browser/usb/usb_chooser_context.h +++ b/chrome/browser/usb/usb_chooser_context.h
@@ -56,7 +56,7 @@ // device::UsbService::Observer implementation. void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override; - bool is_off_the_record_; + bool is_incognito_; std::map<std::pair<GURL, GURL>, std::set<std::string>> ephemeral_devices_; device::UsbService* usb_service_; ScopedObserver<device::UsbService, device::UsbService::Observer> observer_;
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index ee28b485..aa377066 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc
@@ -437,13 +437,6 @@ file_handlers_info); } -void CreateNonAppShortcut(const ShortcutLocations& locations, - std::unique_ptr<ShortcutInfo> shortcut_info) { - ScheduleCreatePlatformShortcut(SHORTCUT_CREATION_AUTOMATED, locations, - std::move(shortcut_info), - extensions::FileHandlersInfo()); -} - void CreateShortcuts(ShortcutCreationReason reason, const ShortcutLocations& locations, Profile* profile,
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 61d099c..3f28b86 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -187,11 +187,6 @@ std::unique_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info); -// Currently only called by app_list_service_mac to create a shim for the -// app launcher. -void CreateNonAppShortcut(const ShortcutLocations& locations, - std::unique_ptr<ShortcutInfo> shortcut_info); - // Creates shortcuts for an app. This loads the app's icon from disk, and calls // CreateShortcutsWithInfo(). If you already have a ShortcutInfo with the app's // icon loaded, you should use CreateShortcutsWithInfo() directly.
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index fc290659..c452006 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -1501,7 +1501,7 @@ 'browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h', 'browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm', 'browser/ui/cocoa/media_picker/desktop_media_picker_controller_deprecated.h', - 'browser/ui/cocoa/media_picker/desktop_media_picker_controller_deprecated.mm', + 'browser/ui/cocoa/media_picker/desktop_media_picker_controller_deprecated.mm', 'browser/ui/cocoa/media_picker/desktop_media_picker_controller.h', 'browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm', 'browser/ui/cocoa/media_picker/desktop_media_picker_item.h', @@ -2621,12 +2621,8 @@ 'browser/ui/app_list/app_list_prefs_factory.h', 'browser/ui/app_list/app_list_service.cc', 'browser/ui/app_list/app_list_service.h', - 'browser/ui/app_list/app_list_service_cocoa_mac.h', - 'browser/ui/app_list/app_list_service_cocoa_mac.mm', 'browser/ui/app_list/app_list_service_impl.cc', 'browser/ui/app_list/app_list_service_impl.h', - 'browser/ui/app_list/app_list_service_mac.h', - 'browser/ui/app_list/app_list_service_mac.mm', 'browser/ui/app_list/app_list_presenter_delegate.h', 'browser/ui/app_list/app_list_syncable_service.cc', 'browser/ui/app_list/app_list_syncable_service.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 51a8142..7a39751 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -43,8 +43,15 @@ '../extensions/browser/api/display_source/display_source_apitestbase.h', 'browser/extensions/api/display_source/display_source_wifi_display_apitest.cc', ], + # TODO(jbudorick): Move tests here from other lists as Android support is + # implemented. See crbug.com/611756 'chrome_browser_tests_sources': [ - # The list of sources which is only used by chrome browser tests. + # The list of sources which is used by chrome browser tests on all + # platforms. + ], + 'chrome_browser_tests_desktop_only_sources': [ + # The list of sources which is only used by chrome browser tests on + # desktop platforms. '../apps/app_restore_service_browsertest.cc', '../apps/load_and_launch_browsertest.cc', 'app/chrome_command_ids.h', @@ -1018,6 +1025,7 @@ 'test/data/webui/print_preview.js', 'test/data/webui/sandboxstatus_browsertest.js', 'test/data/webui/settings/advanced_page_browsertest.js', + 'test/data/webui/settings/animation_browsertest.js', 'test/data/webui/settings/basic_page_browsertest.js', 'test/data/webui/settings/bluetooth_page_browsertest_chromeos.js', 'test/data/webui/settings/cr_settings_browsertest.js', @@ -1155,7 +1163,6 @@ ], 'chrome_interactive_ui_test_app_list_sources': [ 'browser/ui/app_list/app_list_service_interactive_uitest.cc', - 'browser/ui/app_list/app_list_service_mac_interactive_uitest.mm', ], 'chrome_interactive_ui_test_win_sources': [ '../ui/resources/cursors/aliasb.cur', @@ -2236,6 +2243,7 @@ 'HAS_OUT_OF_PROC_TEST_RUNNER', ], 'sources': [ + '<@(chrome_browser_tests_desktop_only_sources)', '<@(chrome_browser_tests_extensions_sources)', '<@(chrome_browser_tests_sources)', '<@(chrome_browser_tests_webui_js_sources)',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 88c00c9..f9e8296 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -236,8 +236,6 @@ 'browser/service_process/service_process_control_mac_unittest.mm', 'browser/services/gcm/fake_gcm_profile_service.cc', 'browser/services/gcm/fake_gcm_profile_service.h', - 'browser/services/gcm/fake_signin_manager.cc', - 'browser/services/gcm/fake_signin_manager.h', 'browser/sessions/restore_on_startup_policy_handler_unittest.cc', 'browser/shell_integration_win_unittest.cc', 'browser/signin/account_reconcilor_unittest.cc', @@ -1623,7 +1621,6 @@ 'browser/apps/drive/drive_app_mapping_unittest.cc', 'browser/ui/app_list/app_context_menu_unittest.cc', 'browser/ui/app_list/app_list_positioner_unittest.cc', - 'browser/ui/app_list/app_list_service_mac_unittest.mm', 'browser/ui/app_list/app_list_service_unittest.cc', 'browser/ui/app_list/app_list_test_util.cc', 'browser/ui/app_list/app_list_test_util.h',
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 3745c85..f9134ad 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -89,7 +89,7 @@ #if defined(OS_CHROMEOS) // Enables or disables the opt-in IME menu in the language settings page. const base::Feature kOptInImeMenu{"OptInImeMenu", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_CHROMEOS) } // namespace features
diff --git a/chrome/gpu/arc_gpu_video_decode_accelerator.cc b/chrome/gpu/arc_gpu_video_decode_accelerator.cc index 75c60f533..d86aa67 100644 --- a/chrome/gpu/arc_gpu_video_decode_accelerator.cc +++ b/chrome/gpu/arc_gpu_video_decode_accelerator.cc
@@ -181,50 +181,49 @@ input_info->length = length; } -bool ArcGpuVideoDecodeAccelerator::VerifyStride(const base::ScopedFD& dmabuf_fd, - int32_t stride) const { +bool ArcGpuVideoDecodeAccelerator::VerifyDmabuf( + const base::ScopedFD& dmabuf_fd, + const std::vector<DmabufPlane>& dmabuf_planes) const { + size_t num_planes = media::VideoFrame::NumPlanes(output_pixel_format_); + if (dmabuf_planes.size() != num_planes) { + DLOG(ERROR) << "Invalid number of dmabuf planes passed: " + << dmabuf_planes.size() << ", expected: " << num_planes; + return false; + } + off_t size = lseek(dmabuf_fd.get(), 0, SEEK_END); lseek(dmabuf_fd.get(), 0, SEEK_SET); - if (size < 0) { DPLOG(ERROR) << "fail to find the size of dmabuf"; return false; } - int height = coded_size_.height(); - switch (output_pixel_format_) { - case media::PIXEL_FORMAT_I420: - case media::PIXEL_FORMAT_YV12: - case media::PIXEL_FORMAT_NV12: - case media::PIXEL_FORMAT_NV21: - // Adjusts the height for UV plane. - // The coded height should always be even. But for security reason, we - // still round up to two here in case VDA reports an incorrect value. - height += (height + 1) / 2; - break; - case media::PIXEL_FORMAT_ARGB: - // No need to adjust height. - break; - default: - DLOG(ERROR) << "Format not supported: " << output_pixel_format_; - return false; - } - base::CheckedNumeric<off_t> used_bytes(height); - used_bytes *= stride; + size_t i = 0; + for (const auto& plane : dmabuf_planes) { + DVLOG(4) << "Plane " << i << ", offset: " << plane.offset + << ", stride: " << plane.stride; - if (stride < 0 || !used_bytes.IsValid() || used_bytes.ValueOrDie() > size) { - DLOG(ERROR) << "invalid stride: " << stride << ", height: " << height - << ", size of dmabuf: " << size; - return false; + size_t rows = + media::VideoFrame::Rows(i, output_pixel_format_, coded_size_.height()); + base::CheckedNumeric<off_t> current_size(plane.offset); + current_size += plane.stride * rows; + + if (!current_size.IsValid() || current_size.ValueOrDie() > size) { + DLOG(ERROR) << "Invalid strides/offsets"; + return false; + } + + ++i; } return true; } -void ArcGpuVideoDecodeAccelerator::BindDmabuf(PortType port, - uint32_t index, - base::ScopedFD dmabuf_fd, - int32_t stride) { +void ArcGpuVideoDecodeAccelerator::BindDmabuf( + PortType port, + uint32_t index, + base::ScopedFD dmabuf_fd, + const std::vector<DmabufPlane>& dmabuf_planes) { DCHECK(thread_checker_.CalledOnValidThread()); if (!vda_) { @@ -241,14 +240,14 @@ arc_client_->OnError(INVALID_ARGUMENT); return; } - if (!VerifyStride(dmabuf_fd, stride)) { + if (!VerifyDmabuf(dmabuf_fd, dmabuf_planes)) { arc_client_->OnError(INVALID_ARGUMENT); return; } OutputBufferInfo& info = buffers_pending_import_[index]; info.handle = std::move(dmabuf_fd); - info.stride = stride; + info.planes = dmabuf_planes; } void ArcGpuVideoDecodeAccelerator::UseBuffer(PortType port, @@ -294,7 +293,10 @@ #if defined(USE_OZONE) handle.native_pixmap_handle.fds.emplace_back( base::FileDescriptor(info.handle.release(), true)); - handle.native_pixmap_handle.planes.emplace_back(info.stride, 0, 0); + for (const auto& plane : info.planes) { + handle.native_pixmap_handle.planes.emplace_back( + plane.stride, plane.offset, 0); + } #endif vda_->ImportBufferForPicture(index, handle); } else {
diff --git a/chrome/gpu/arc_gpu_video_decode_accelerator.h b/chrome/gpu/arc_gpu_video_decode_accelerator.h index 89ca2d5..57dd2ea 100644 --- a/chrome/gpu/arc_gpu_video_decode_accelerator.h +++ b/chrome/gpu/arc_gpu_video_decode_accelerator.h
@@ -44,7 +44,7 @@ void BindDmabuf(PortType port, uint32_t index, base::ScopedFD dmabuf_fd, - int32_t stride) override; + const std::vector<DmabufPlane>& dmabuf_planes) override; void UseBuffer(PortType port, uint32_t index, const BufferMetadata& metadata) override; @@ -97,7 +97,7 @@ // The information about the dmabuf used as an output buffer. struct OutputBufferInfo { base::ScopedFD handle; - int32_t stride = 0; // In bytes. + std::vector<DmabufPlane> planes; OutputBufferInfo(); OutputBufferInfo(OutputBufferInfo&& other); @@ -107,8 +107,9 @@ // Helper function to validate |port| and |index|. bool ValidatePortAndIndex(PortType port, uint32_t index) const; - // Helper function to verify the length of stride is legal. - bool VerifyStride(const base::ScopedFD& fd, int32_t stride) const; + // Return true if |dmabuf_planes| is valid for a dmabuf |fd|. + bool VerifyDmabuf(const base::ScopedFD& fd, + const std::vector<DmabufPlane>& dmabuf_planes) const; // Creates an InputRecord for the given |bitstream_buffer_id|. The // |buffer_index| is the index of the associated input buffer. The |timestamp|
diff --git a/chrome/gpu/arc_video_accelerator.h b/chrome/gpu/arc_video_accelerator.h index 079edfb..b60619a 100644 --- a/chrome/gpu/arc_video_accelerator.h +++ b/chrome/gpu/arc_video_accelerator.h
@@ -5,6 +5,8 @@ #ifndef CHROME_GPU_ARC_VIDEO_ACCELERATOR_H_ #define CHROME_GPU_ARC_VIDEO_ACCELERATOR_H_ +#include <vector> + #include "base/files/scoped_file.h" namespace chromeos { @@ -74,6 +76,11 @@ // format of each VDA on Chromium is supported. }; + struct DmabufPlane { + int32_t offset; // in bytes + int32_t stride; // in bytes + }; + // The callbacks of the ArcVideoAccelerator. The user of this class should // implement this interface. class Client { @@ -122,12 +129,11 @@ // Assigns a buffer to be used for the accelerator at the specified // port and index. A buffer must be successfully bound before it can be // passed to the accelerator via UseBuffer(). Already bound buffers may be - // reused multiple times without additional bindings. |stride| is counted in - // bytes. + // reused multiple times without additional bindings. virtual void BindDmabuf(PortType port, uint32_t index, base::ScopedFD dmabuf_fd, - int32_t stride) = 0; + const std::vector<DmabufPlane>& dmabuf_planes) = 0; // Passes a buffer to the accelerator. For input buffer, the accelerator // will process it. For output buffer, the accelerator will output content
diff --git a/chrome/gpu/gpu_arc_video_service.cc b/chrome/gpu/gpu_arc_video_service.cc index 70c2b7d..bb20aad 100644 --- a/chrome/gpu/gpu_arc_video_service.cc +++ b/chrome/gpu/gpu_arc_video_service.cc
@@ -109,6 +109,24 @@ } }; +template <> +struct TypeConverter<chromeos::arc::ArcVideoAccelerator::DmabufPlane, + arc::mojom::ArcVideoAcceleratorDmabufPlanePtr> { + static chromeos::arc::ArcVideoAccelerator::DmabufPlane Convert( + const arc::mojom::ArcVideoAcceleratorDmabufPlanePtr& input) { + chromeos::arc::ArcVideoAccelerator::DmabufPlane result = {0}; + if (input->offset < 0 || input->stride < 0) { + DVLOG(1) << "Invalid offset/stride: " << input->offset << "/" + << input->stride; + return result; + } + + result.offset = input->offset; + result.stride = input->stride; + return result; + } +}; + } // namespace mojo namespace chromeos { @@ -241,17 +259,34 @@ std::move(fd), offset, length); } -void GpuArcVideoService::BindDmabuf(::arc::mojom::PortType port, - uint32_t index, - mojo::ScopedHandle dmabuf_handle, - int32_t stride) { +void GpuArcVideoService::DeprecatedBindDmabuf(::arc::mojom::PortType port, + uint32_t index, + mojo::ScopedHandle dmabuf_handle, + int32_t stride) { + mojo::Array<::arc::mojom::ArcVideoAcceleratorDmabufPlanePtr> planes(1); + planes[0]->offset = 0; + planes[0]->stride = stride; + + BindDmabuf(port, index, std::move(dmabuf_handle), std::move(planes)); +} + +void GpuArcVideoService::BindDmabuf( + ::arc::mojom::PortType port, + uint32_t index, + mojo::ScopedHandle dmabuf_handle, + mojo::Array<::arc::mojom::ArcVideoAcceleratorDmabufPlanePtr> + dmabuf_planes) { DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index; base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(dmabuf_handle)); if (!fd.is_valid()) return; + + std::vector<ArcVideoAccelerator::DmabufPlane> converted_planes = + dmabuf_planes.To<std::vector<ArcVideoAccelerator::DmabufPlane>>(); + accelerator_->BindDmabuf(static_cast<PortType>(port), index, std::move(fd), - stride); + std::move(converted_planes)); } void GpuArcVideoService::UseBuffer(::arc::mojom::PortType port,
diff --git a/chrome/gpu/gpu_arc_video_service.h b/chrome/gpu/gpu_arc_video_service.h index fc9b2e00..38fb13e 100644 --- a/chrome/gpu/gpu_arc_video_service.h +++ b/chrome/gpu/gpu_arc_video_service.h
@@ -55,10 +55,15 @@ mojo::ScopedHandle ashmem_handle, uint32_t offset, uint32_t length) override; + void DeprecatedBindDmabuf(::arc::mojom::PortType port, + uint32_t index, + mojo::ScopedHandle dmabuf_handle, + int32_t stride) override; void BindDmabuf(::arc::mojom::PortType port, uint32_t index, mojo::ScopedHandle dmabuf_handle, - int32_t stride) override; + mojo::Array<::arc::mojom::ArcVideoAcceleratorDmabufPlanePtr> + dmabuf_planes) override; void UseBuffer(::arc::mojom::PortType port, uint32_t index, ::arc::mojom::BufferMetadataPtr metadata) override;
diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment.cc b/chrome/installer/gcapi/gcapi_omaha_experiment.cc index 5235afd2..a34a146f 100644 --- a/chrome/installer/gcapi/gcapi_omaha_experiment.cc +++ b/chrome/installer/gcapi/gcapi_omaha_experiment.cc
@@ -18,9 +18,12 @@ // Returns the number of weeks since 2/3/2003. int GetCurrentRlzWeek(const base::Time& current_time) { - base::Time::Exploded february_third_2003_exploded = + const base::Time::Exploded february_third_2003_exploded = {2003, 2, 1, 3, 0, 0, 0, 0}; - base::Time f = base::Time::FromUTCExploded(february_third_2003_exploded); + base::Time f; + bool conversion_success = + base::Time::FromUTCExploded(february_third_2003_exploded, &f); + DCHECK(conversion_success); base::TimeDelta delta = current_time - f; return delta.InDays() / 7; }
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 5f11575..41c306d 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc
@@ -699,7 +699,7 @@ if (installer_state.FindProduct(BrowserDistribution::CHROME_BINARIES)) { // Chrome Binaries should be last; if something else is cancelled, they // should stay. - DCHECK(products[products.size() - 1]->is_chrome_binaries()); + DCHECK(products.back()->is_chrome_binaries()); } installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL;
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc index d9d9faec..1a53a774 100644 --- a/chrome/installer/util/installer_state.cc +++ b/chrome/installer/util/installer_state.cc
@@ -279,17 +279,15 @@ } if (target_path_.empty()) { - if (product_dir == NULL) - target_path_ = GetDefaultProductInstallPath(the_product.distribution()); - else - target_path_ = *product_dir; + target_path_ = product_dir ? *product_dir : GetDefaultProductInstallPath( + the_product.distribution()); } if (state_key_.empty()) state_key_ = the_product.distribution()->GetStateKey(); products_.push_back(product->release()); - return products_[products_.size() - 1]; + return products_.back(); } Product* InstallerState::AddProduct(std::unique_ptr<Product>* product) {
diff --git a/chrome/renderer/autofill/autofill_renderer_browsertest.cc b/chrome/renderer/autofill/autofill_renderer_browsertest.cc index c9d71ed..ead2cf8 100644 --- a/chrome/renderer/autofill/autofill_renderer_browsertest.cc +++ b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
@@ -134,8 +134,8 @@ "newForm.appendChild(newLastname);" "newForm.appendChild(newEmail);" "document.body.appendChild(newForm);"); - base::RunLoop().RunUntilIdle(); + WaitForAutofillDidAssociateFormControl(); message = render_thread_->sink().GetFirstMessageMatching( AutofillHostMsg_FormsSeen::ID); ASSERT_NE(nullptr, message); @@ -212,8 +212,8 @@ render_thread_->sink().ClearMessages(); ExecuteJavaScriptForTests("AddFields()"); - base::RunLoop().RunUntilIdle(); + WaitForAutofillDidAssociateFormControl(); message = render_thread_->sink().GetFirstMessageMatching( AutofillHostMsg_FormsSeen::ID); ASSERT_NE(nullptr, message);
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc index d376f05..30306f0 100644 --- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -503,7 +503,7 @@ "form.appendChild(first_password);" "form.appendChild(second_password);" "document.body.appendChild(form);"); - ProcessPendingMessages(); + WaitForAutofillDidAssociateFormControl(); // This needs to come after the DOM has been modified. SetAccountCreationFormsDetectedMessage(password_generation_,
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc index fc9d263..acb98ccc 100644 --- a/chrome/renderer/net/net_error_helper.cc +++ b/chrome/renderer/net/net_error_helper.cc
@@ -31,6 +31,7 @@ #include "grit/components_resources.h" #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" @@ -315,7 +316,7 @@ blink::WebURLRequest request(page_url); request.setCachePolicy(blink::WebCachePolicy::ReturnCacheDataDontLoad); - + request.setRequestorOrigin(blink::WebSecurityOrigin::createUnique()); web_frame->loadRequest(request); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b62091b0..318e092 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -859,26 +859,157 @@ ":browser_tests", ] } +} - test("browser_tests") { - sources = [ - "base/browser_tests_main.cc", +test("browser_tests") { + sources = [ + "base/browser_tests_main.cc", + ] + sources += rebase_path(chrome_tests_gypi_values.chrome_browser_tests_sources, + ".", + "//chrome") + + configs += [ + "//build/config:precompiled_headers", + "//third_party/WebKit/public:debug_devtools", + ] + + deps = [ + ":test_support", + "//base", + "//sync:test_support_sync_api", + ] + + data_deps = [] + + data = [] + + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + + if (is_win) { + data += [ "$root_out_dir/chrome_200_percent.pak" ] + } + if (is_mac) { + data += [ + "$root_out_dir/chrome_material_100_percent.pak", + "$root_out_dir/chrome_material_200_percent.pak", ] - sources += - rebase_path(chrome_tests_gypi_values.chrome_browser_tests_sources, - ".", - "//chrome") + } + if (is_chromeos) { + data += [ + # TODO(GYP): figure out which of these things are + # actually needed and also which should be pulled in via + # data or data_deps and through which dependencies. + "//chrome/browser/chromeos/login/test/https_forwarder.py", + "//chrome/browser/resources/chromeos/wallpaper_manager/", + "//chromeos/test/data/", + "//components/chrome_apps/webstore_widget/cws_widget/", + "//ui/file_manager/file_manager/", + "//ui/file_manager/gallery/", + "//ui/file_manager/image_loader/", + "//ui/file_manager/integration_tests/", + "//third_party/analytics/", + "//third_party/polymer/v1_0/components-chromium/polymer/", + "$root_out_dir/chromevox_test_data/", + "$root_out_dir/content_shell.pak", + "$root_out_dir/locales/", + "$root_out_dir/resources/chromeos/", + ] + + data_deps += [ "//ui/keyboard:resources" ] + + if (enable_nacl) { + data_deps += [ + "//components/nacl/loader:nacl_helper", + "//ppapi/native_client:irt", + ] + } + } + + # TODO(jbudorick): In progress. See crbug.com/611756 + if (is_android) { + deps += [ + "//chrome/android:chrome_java", + "//v8:v8_external_startup_data_assets", + ] + + enable_multidex = true + } else { sources += rebase_path( - chrome_tests_gypi_values.chrome_browser_extensions_test_support_sources, + chrome_tests_gypi_values.chrome_browser_tests_desktop_only_sources, ".", "//chrome") - configs += [ - "//build/config:precompiled_headers", - "//third_party/WebKit/public:debug_devtools", + deps += [ + ":browser_tests_js_webui", + ":sync_integration_test_support", + ":test_support_ui", + "//base:i18n", + "//base/test:test_support", + "//chrome:browser_tests_pak", + "//chrome:packed_extra_resources", + "//chrome:packed_resources", + "//chrome:resources", + "//chrome:strings", + "//chrome/browser", + "//chrome/browser/resources:extension_resource_demo", + "//chrome/renderer", + "//components/autofill/content/browser:risk_proto", + "//components/autofill/content/renderer:test_support", + "//components/captive_portal:test_support", + "//components/dom_distiller/content/browser", + "//components/dom_distiller/content/renderer", + "//components/dom_distiller/core:test_support", + "//components/guest_view/browser:test_support", + "//components/resources", + "//components/safe_browsing_db:test_database_manager", + "//components/strings", + "//components/translate/core/common", + "//content/public/common:features", + "//content/test:browsertest_base", + "//crypto:platform", + "//crypto:test_support", + "//device/bluetooth:mocks", + "//device/serial:test_support", + "//device/usb:test_support", + "//google_apis:test_support", + "//media", + "//media/base:test_support", + "//media/cast:test_support", + "//net", + "//net:test_support", + "//sdch", + "//skia", + "//sync", + "//testing/gmock", + "//testing/gtest", + "//testing/perf", + "//third_party/cacheinvalidation", + "//third_party/icu", + "//third_party/leveldatabase", + "//third_party/libjingle", + "//third_party/webrtc/modules/desktop_capture", + "//third_party/widevine/cdm:version_h", + "//ui/accessibility:test_support", + "//ui/base:test_support", + "//ui/compositor:test_support", + "//ui/resources", + "//ui/web_dialogs:test_support", + "//v8", ] - data = [ + # Runtime dependencies + data_deps += [ + "//chrome", + "//ppapi:ppapi_tests", + "//ppapi:power_saver_test_plugin", + "//remoting/webapp:browser_test_resources", + "//remoting/webapp:unit_tests", + "//third_party/mesa:osmesa", + "//third_party/widevine/cdm:widevine_test_license_server", + ] + + data += [ "data/", "//chrome/browser/policy/test/asn1der.py", "//chrome/browser/policy/test/policy_testserver.py", @@ -914,136 +1045,12 @@ "$root_out_dir/test_page.css.mock-http-headers", "$root_out_dir/test_url_loader_data/", ] - if (is_win) { - data += [ "$root_out_dir/chrome_200_percent.pak" ] - } - if (is_mac) { - data += [ - "$root_out_dir/chrome_material_100_percent.pak", - "$root_out_dir/chrome_material_200_percent.pak", - ] - } - if (is_chromeos) { - data += [ - # TODO(GYP): figure out which of these things are - # actually needed and also which should be pulled in via - # data or data_deps and through which dependencies. - "//chrome/browser/chromeos/login/test/https_forwarder.py", - "//chrome/browser/resources/chromeos/wallpaper_manager/", - "//chromeos/test/data/", - "//components/chrome_apps/webstore_widget/cws_widget/", - "//ui/file_manager/file_manager/", - "//ui/file_manager/gallery/", - "//ui/file_manager/image_loader/", - "//ui/file_manager/integration_tests/", - "//third_party/analytics/", - "//third_party/polymer/v1_0/components-chromium/polymer/", - "$root_out_dir/chromevox_test_data/", - "$root_out_dir/content_shell.pak", - "$root_out_dir/locales/", - "$root_out_dir/resources/chromeos/", - ] - - data_deps = [ - "//ui/keyboard:resources", - ] - - if (enable_nacl) { - data_deps += [ - "//components/nacl/loader:nacl_helper", - "//ppapi/native_client:irt", - ] - } - } else { - data_deps = [] - } - - deps = [ - ":browser_tests_js_webui", - ":sync_integration_test_support", - ":test_support", - ":test_support_ui", - "//base", - "//base:i18n", - "//base/test:test_support", - "//chrome:browser_tests_pak", - "//chrome:packed_extra_resources", - "//chrome:packed_resources", - "//chrome:resources", - "//chrome:strings", - "//chrome/browser", - "//chrome/browser/resources:extension_resource_demo", - "//chrome/common/extensions/api", - "//chrome/renderer", - "//components/autofill/content/browser:risk_proto", - "//components/autofill/content/renderer:test_support", - "//components/captive_portal:test_support", - "//components/dom_distiller/content/browser", - "//components/dom_distiller/content/renderer", - "//components/dom_distiller/core:test_support", - "//components/guest_view/browser:test_support", - "//components/resources", - "//components/safe_browsing_db:test_database_manager", - "//components/strings", - "//components/translate/core/common", - "//content/public/common:features", - "//content/test:browsertest_base", - "//crypto:platform", - "//crypto:test_support", - "//device/bluetooth:mocks", - "//device/serial:test_support", - "//device/usb:test_support", - "//extensions/common/api", - "//google_apis:test_support", - "//media", - "//media/base:test_support", - "//media/cast:test_support", - "//net", - "//net:test_support", - "//sdch", - "//skia", - "//sync", - "//sync:test_support_sync_api", - "//testing/gmock", - "//testing/gtest", - "//testing/perf", - "//third_party/cacheinvalidation", - "//third_party/icu", - "//third_party/leveldatabase", - "//third_party/libjingle", - "//third_party/webrtc/modules/desktop_capture", - "//third_party/widevine/cdm:version_h", - "//ui/accessibility:test_support", - "//ui/base:test_support", - "//ui/compositor:test_support", - "//ui/resources", - "//ui/web_dialogs:test_support", - "//v8", - ] - - # TODO(rockot) bug 505926: The chrome_extensions_browsertests target should - # be deleted and this line removed. See the chrome_extensions_browsertests - # target for more. - deps += [ "//extensions:chrome_extensions_browsertests" ] - - # Runtime dependencies - data_deps += [ - "//chrome", - "//ppapi:ppapi_tests", - "//ppapi:power_saver_test_plugin", - "//remoting/webapp:browser_test_resources", - "//remoting/webapp:unit_tests", - "//third_party/mesa:osmesa", - "//third_party/widevine/cdm:widevine_test_license_server", - ] if (!is_mac) { data += [ "$root_out_dir/locales/" ] data_deps += [ "//chrome:packed_extra_resources" ] } - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] - if (!enable_one_click_signin) { sources -= [ "../browser/ui/sync/one_click_signin_links_delegate_impl_browsertest.cc" ] } @@ -1096,6 +1103,24 @@ ] } } + + if (enable_extensions) { + sources += rebase_path( + chrome_tests_gypi_values.chrome_browser_extensions_test_support_sources, + ".", + "//chrome") + + deps += [ + "//chrome/common/extensions/api", + + # TODO(rockot) bug 505926: The chrome_extensions_browsertests target + # should be deleted and this line removed. See the + # chrome_extensions_browsertests target for more. + "//extensions:chrome_extensions_browsertests", + "//extensions/common/api", + ] + } + if (use_ash) { sources += rebase_path(chrome_tests_gypi_values.chrome_browser_tests_ash_sources, @@ -1351,14 +1376,6 @@ if (!is_posix || is_chromeos) { sources -= [ "../common/time_format_browsertest.cc" ] } - if (is_android) { - sources -= [ - "../browser/policy/cloud/component_cloud_policy_browsertest.cc", - "../browser/prefs/pref_hash_browsertest.cc", - "../renderer/spellchecker/spellcheck_provider_hunspell_unittest.cc", - "../renderer/spellchecker/spellcheck_unittest.cc", - ] - } if (is_chromeos) { sources += [ "../browser/extensions/api/networking_private/networking_private_apitest.cc", @@ -1450,8 +1467,6 @@ "../renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc", ] } - if (is_android || is_ios) { - } if (enable_remoting) { sources += rebase_path( chrome_tests_gypi_values.chrome_browser_tests_remoting_sources, @@ -1491,7 +1506,9 @@ } } } +} +if (!is_android) { test("sync_integration_tests") { sources = rebase_path(chrome_tests_gypi_values.sync_integration_tests_sources,
diff --git a/chrome/test/base/chrome_render_view_test.cc b/chrome/test/base/chrome_render_view_test.cc index 4496416..acd1492 100644 --- a/chrome/test/base/chrome_render_view_test.cc +++ b/chrome/test/base/chrome_render_view_test.cc
@@ -69,9 +69,25 @@ ~MockAutofillAgent() override {} + void WaitForAutofillDidAssociateFormControl() { + DCHECK(run_loop_ == nullptr); + run_loop_.reset(new base::RunLoop); + run_loop_->Run(); + run_loop_.reset(); + } + MOCK_CONST_METHOD0(IsUserGesture, bool()); private: + void didAssociateFormControls( + const blink::WebVector<blink::WebNode>& nodes) override { + AutofillAgent::didAssociateFormControls(nodes); + if (run_loop_) + run_loop_->Quit(); + } + + std::unique_ptr<base::RunLoop> run_loop_; + DISALLOW_COPY_AND_ASSIGN(MockAutofillAgent); }; @@ -165,3 +181,8 @@ EXPECT_CALL(*(static_cast<MockAutofillAgent*>(autofill_agent_)), IsUserGesture()).WillRepeatedly(Return(false)); } + +void ChromeRenderViewTest::WaitForAutofillDidAssociateFormControl() { + static_cast<MockAutofillAgent*>(autofill_agent_) + ->WaitForAutofillDidAssociateFormControl(); +}
diff --git a/chrome/test/base/chrome_render_view_test.h b/chrome/test/base/chrome_render_view_test.h index 7c579eea..3929c9b 100644 --- a/chrome/test/base/chrome_render_view_test.h +++ b/chrome/test/base/chrome_render_view_test.h
@@ -42,6 +42,7 @@ void EnableUserGestureSimulationForAutofill(); void DisableUserGestureSimulationForAutofill(); + void WaitForAutofillDidAssociateFormControl(); #if defined(ENABLE_EXTENSIONS) std::unique_ptr<extensions::DispatcherDelegate>
diff --git a/chrome/test/base/mash_browser_tests_main.cc b/chrome/test/base/mash_browser_tests_main.cc index 6dea6ad..e23e754 100644 --- a/chrome/test/base/mash_browser_tests_main.cc +++ b/chrome/test/base/mash_browser_tests_main.cc
@@ -17,7 +17,7 @@ #include "content/public/test/test_launcher.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/runner/common/switches.h" #include "services/shell/runner/host/child_process.h" #include "services/shell/runner/init.h" @@ -81,7 +81,7 @@ if (!mojo_test_connector_) { mojo_test_connector_.reset(new MojoTestConnector); service_.reset(new shell::Service); - shell_connection_.reset(new shell::ShellConnection( + shell_connection_.reset(new shell::ServiceContext( service_.get(), mojo_test_connector_->Init())); ConnectToDefaultApps(shell_connection_->connector()); } @@ -99,7 +99,7 @@ std::unique_ptr<MashTestSuite> test_suite_; std::unique_ptr<MojoTestConnector> mojo_test_connector_; std::unique_ptr<shell::Service> service_; - std::unique_ptr<shell::ShellConnection> shell_connection_; + std::unique_ptr<shell::ServiceContext> shell_connection_; DISALLOW_COPY_AND_ASSIGN(MashTestLauncherDelegate); };
diff --git a/chrome/test/base/mojo_test_connector.cc b/chrome/test/base/mojo_test_connector.cc index 30cb63d8..e6428fb 100644 --- a/chrome/test/base/mojo_test_connector.cc +++ b/chrome/test/base/mojo_test_connector.cc
@@ -23,7 +23,7 @@ #include "services/shell/native_runner_delegate.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/runner/common/client_util.h" #include "services/shell/runner/common/switches.h" #include "services/shell/service_manager.h"
diff --git a/chrome/test/base/mojo_test_connector.h b/chrome/test/base/mojo_test_connector.h index a42209e..bd34addf 100644 --- a/chrome/test/base/mojo_test_connector.h +++ b/chrome/test/base/mojo_test_connector.h
@@ -21,11 +21,6 @@ class TestState; } -namespace mojo { -class Service; -class ShellConnection; -} - // MojoTestConnector in responsible for providing the necessary wiring for // test processes to get a mojo channel passed to them. To use this class // call PrepareForTest() prior to launching each test. It is expected
diff --git a/chrome/test/chromedriver/net/adb_client_socket.cc b/chrome/test/chromedriver/net/adb_client_socket.cc index 0a398acf..9a5a672 100644 --- a/chrome/test/chromedriver/net/adb_client_socket.cc +++ b/chrome/test/chromedriver/net/adb_client_socket.cc
@@ -271,7 +271,8 @@ bool is_void = current_query_ < queries_.size() - 1; // The |shell| command is a special case because it is the only command that // doesn't include a length at the beginning of the data stream. - bool has_length = query.find("shell:") != 0; + bool has_length = + !base::StartsWith(query, "shell:", base::CompareCase::SENSITIVE); SendCommand(query, is_void, has_length, base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this))); }
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc index ecfe4a7..48ad77d7 100644 --- a/chrome/test/chromedriver/session_commands.cc +++ b/chrome/test/chromedriver/session_commands.cc
@@ -12,6 +12,7 @@ #include "base/files/file_util.h" #include "base/logging.h" // For CHECK macros. #include "base/memory/ref_counted.h" +#include "base/strings/string_util.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h" @@ -62,10 +63,11 @@ bool WindowHandleToWebViewId(const std::string& window_handle, std::string* web_view_id) { - if (window_handle.find(kWindowHandlePrefix) != 0u) + if (!base::StartsWith(window_handle, kWindowHandlePrefix, + base::CompareCase::SENSITIVE)) { return false; - *web_view_id = window_handle.substr( - std::string(kWindowHandlePrefix).length()); + } + *web_view_id = window_handle.substr(sizeof(kWindowHandlePrefix) - 1); return true; }
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations index 7a2518b..8963d84 100644 --- a/chrome/test/chromedriver/test/test_expectations +++ b/chrome/test/chromedriver/test/test_expectations
@@ -113,6 +113,15 @@ 'CombinedInputActionsTest.testCombiningShiftAndClickResultsInANewWindow', # Flaky: https://code.google.com/p/chromedriver/issues/detail?id=1150 'BasicKeyboardInterfaceTest.testBasicKeyboardInputOnActiveElement', + + # Flaky on Linux32: + # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1418 + 'ClickTest.testShouldOnlyFollowHrefOnce', + 'JavascriptEnabledDriverTest.testShouldFireOnChangeEventWhenSettingAnElementsValue', + 'WindowSwitchingTest.testCanCloseWindowWhenMultipleWindowsAreOpen', + 'WindowSwitchingTest.testCanCallGetWindowHandlesAfterClosingAWindow', + 'WindowSwitchingTest.testCanCloseWindowAndSwitchBackToMainWindow', + 'XPathElementFindingTest.testShouldFindElementsByXPath', ] _OS_NEGATIVE_FILTER['mac'] = [ # https://code.google.com/p/chromedriver/issues/detail?id=26
diff --git a/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/guest.html b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/guest.html new file mode 100644 index 0000000..4de94b45 --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/guest.html
@@ -0,0 +1,16 @@ +<!doctype html> +<!-- + * Copyright 2016 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. +--> +<html id='root'> + <!-- Since the body of an app is not scrollable by default, explicitly + set it to be scrollable. --> + <head> + <script type="text/javascript" src="guest.js"></script> + </head> + <body style="margin: auto"> + Test guest.<br> + </body> +</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/guest.js b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/guest.js new file mode 100644 index 0000000..5a8b67f --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/guest.js
@@ -0,0 +1,25 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var LOG = function(msg) { + window.console.log(msg); +}; + +var embedder; + +function sendMessageToEmbedder(message) { + if (!embedder) { + LOG('no embedder channel to send postMessage'); + return; + } + embedder.postMessage(JSON.stringify([message]), '*'); +} + +window.addEventListener('message', function(e) { + embedder = e.source; + var data = JSON.parse(e.data); + if (data[0] == 'connect') { + sendMessageToEmbedder('connected'); + } +});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/main.html b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/main.html new file mode 100644 index 0000000..298e2a8 --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/main.html
@@ -0,0 +1,17 @@ +<!doctype html> +<!-- + * Copyright 2016 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. +--> +<html> + <body style= + "width: 400px; height: 400px; margin: 0px; padding: 0px;"> + <div> + <input type='text' id='other-focusable-element' + style="position: absolute; left: 5px; top: 5px; width: 10px; height: 10px;"> + </div> + <div id="webview-tag-container"></div> + <script src="main.js"></script> + </body> +</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/main.js b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/main.js new file mode 100644 index 0000000..1a733ac --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/main.js
@@ -0,0 +1,54 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var LOG = function(msg) { + window.console.log(msg); +}; + +var startTest = function() { + document.getElementById('other-focusable-element').onfocus = + function() { + console.log('guest_focus_test: text input got focus.'); + }; + + var webview = document.createElement('webview'); + var onLoadStop = function(e) { + webview.contentWindow.postMessage(JSON.stringify(['connect']),'*'); + }; + + webview.addEventListener('loadstop', onLoadStop); + webview.addEventListener('consolemessage', function(e) { + LOG('g: ' + e.message); + }); + webview.partition = 'partition1'; + webview.style.width = '300px'; + webview.style.height = '200px'; + webview.style.margin = '0px'; + webview.style.padding = '0px'; + webview.style.position = 'absolute'; + webview.style.left = '50px'; + webview.style.top = '100px'; + webview.src = 'guest.html'; + document.querySelector('#webview-tag-container').appendChild(webview); +}; + +window.addEventListener('message', function(e) { + var data = JSON.parse(e.data); + LOG('data: ' + data); + switch (data[0]) { + case 'connected': + chrome.test.sendMessage('WebViewTest.LAUNCHED'); + break; + } +}); + +if (chrome.test !== undefined) { + chrome.test.getConfig(function(config) { + startTest(); + }); +} else { + // Allow interactive debugging. + // Need timeout to allow the WebView prototype to be setup. + window.setTimeout(startTest, 100); +}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/manifest.json new file mode 100644 index 0000000..77c2ec0 --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/manifest.json
@@ -0,0 +1,23 @@ +{ + "name": "<webview> guest focus test.", + "version": "1", + "permissions": [ + "webview" + ], + "app": { + "background": { + "scripts": ["test.js"] + } + }, + "webview": { + "partitions": [ + { + "name": "partition1", + "accessible_resources": [ + "guest.js", + "guest.html" + ] + } + ] + } +}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/test.js b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/test.js new file mode 100644 index 0000000..1515400 --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/guest_focus_test/test.js
@@ -0,0 +1,9 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('main.html', { + bounds: { width: 400, height: 400 } + }, function() {}); +});
diff --git a/chrome/test/data/webrtc/video_extraction.js b/chrome/test/data/webrtc/video_extraction.js index 5bfa923..95f83bd 100644 --- a/chrome/test/data/webrtc/video_extraction.js +++ b/chrome/test/data/webrtc/video_extraction.js
@@ -36,10 +36,9 @@ var gHasThrownAwayFirstTwoFrames = false; /** - * We need this global variable to synchronize with the test how long to run the - * call between the two peers. + * A string to be returned to the test about the current status of capture. */ -var gDoneFrameCapturing = false; +var gCapturingStatus = 'capturing-not-started'; /** * Starts the frame capturing. @@ -55,6 +54,7 @@ inputElement = document.getElementById("local-view"); var width = inputElement.videoWidth; var height = inputElement.videoHeight; + // The WebRTC code is free to start in VGA, so make sure that the output video // tag scales up to whatever the input size is (otherwise the video quality // comparison will go poorly. @@ -62,13 +62,16 @@ videoTag.height = height; if (width == 0 || height == 0) { - throw failTest('Trying to capture from ' + videoTag.id + - ' but it is not playing any video.'); + // Video must be playing at this point since this function is invoked from + // onplay on the <video> tag. See http://crbug.com/625943. + gCapturingStatus = 'failed-video-was-0x0-after-onplay' + return; } console.log('Received width is: ' + width + ', received height is: ' + height + ', capture interval is: ' + gFrameCaptureInterval + ', duration is: ' + gCaptureDuration); + gCapturingStatus = 'still-capturing'; var remoteCanvas = document.createElement('canvas'); remoteCanvas.width = width; @@ -85,11 +88,7 @@ * Queries if we're done with the frame capturing yet. */ function doneFrameCapturing() { - if (gDoneFrameCapturing) { - returnToTest('done-capturing'); - } else { - returnToTest('still-capturing'); - } + returnToTest(gCapturingStatus); } /** @@ -169,7 +168,7 @@ gFrameCaptureInterval - diff); } else { // Done capturing! - gDoneFrameCapturing = true; + gCapturingStatus = 'done-capturing'; prepareProgressBar_(); } }
diff --git a/chrome/test/data/webui/md_history/history_list_test.js b/chrome/test/data/webui/md_history/history_list_test.js index d43bde1..0ccad6a 100644 --- a/chrome/test/data/webui/md_history/history_list_test.js +++ b/chrome/test/data/webui/md_history/history_list_test.js
@@ -196,6 +196,7 @@ }); test('delete items end to end', function(done) { + var listContainer = app.$.history; app.historyResult(createHistoryInfo(), TEST_HISTORY_RESULTS); app.historyResult(createHistoryInfo(), ADDITIONAL_RESULTS); flush().then(function() { @@ -216,11 +217,17 @@ '2016-03-13'); assertEquals(element.historyData_[4].dateRelativeDay, '2016-03-11'); + assertFalse(listContainer.$.dialog.opened); done(); }); }); MockInteractions.tap(app.$.toolbar.$$('#delete-button')); + + // Confirmation dialog should appear. + assertTrue(listContainer.$.dialog.opened); + + MockInteractions.tap(listContainer.$$('.action-button')); }); });
diff --git a/chrome/test/data/webui/md_history/history_overflow_menu_test.js b/chrome/test/data/webui/md_history/history_overflow_menu_test.js index 5fee6506..01836a7f 100644 --- a/chrome/test/data/webui/md_history/history_overflow_menu_test.js +++ b/chrome/test/data/webui/md_history/history_overflow_menu_test.js
@@ -66,7 +66,7 @@ // actual page, it will take two presses to close the menu due to focus. // TODO(yingran): Fix this behavior to only require one key press. element.toggleMenu_(MENU_EVENT); - MockInteractions.pressAndReleaseKeyOn(document, 27); + MockInteractions.pressAndReleaseKeyOn(document.body, 27); assertEquals(false, element.$.sharedMenu.menuOpen); });
diff --git a/chrome/test/data/webui/md_history/history_toolbar_test.js b/chrome/test/data/webui/md_history/history_toolbar_test.js index 86f6f02b4..6eb61f6 100644 --- a/chrome/test/data/webui/md_history/history_toolbar_test.js +++ b/chrome/test/data/webui/md_history/history_toolbar_test.js
@@ -52,6 +52,26 @@ toolbar.$$('cr-toolbar').fire('search-changed', 'Test'); }); + test('shortcuts to open search field', function() { + var field = toolbar.$['main-toolbar'].getSearchField(); + assertFalse(field.showingSearch); + + MockInteractions.pressAndReleaseKeyOn( + document.body, 191, '', '/'); + assertTrue(field.showingSearch); + assertEquals(field.$.searchInput, field.root.activeElement); + + MockInteractions.pressAndReleaseKeyOn( + field.$.searchInput, 27, '', 'Escape'); + assertFalse(field.showingSearch, 'Pressing escape closes field.'); + assertNotEquals(field.$.searchInput, field.root.activeElement); + + MockInteractions.pressAndReleaseKeyOn( + document.body, 70, 'ctrl', 'f'); + assertTrue(field.showingSearch); + assertEquals(field.$.searchInput, field.root.activeElement); + }); + teardown(function() { element.historyData_ = []; element.searchedTerm = '';
diff --git a/chrome/test/data/webui/mocha_adapter.js b/chrome/test/data/webui/mocha_adapter.js index 7e544b47..696d938 100644 --- a/chrome/test/data/webui/mocha_adapter.js +++ b/chrome/test/data/webui/mocha_adapter.js
@@ -35,10 +35,14 @@ var message = 'Mocha test failed: ' + test.fullTitle() + '\n'; // Remove unhelpful mocha lines from stack trace. - var stack = err.stack.split('\n'); - for (var i = 0; i < stack.length; i++) { - if (stack[i].indexOf('mocha.js:') == -1) - message += stack[i] + '\n'; + if (err.stack) { + var stack = err.stack.split('\n'); + for (var i = 0; i < stack.length; i++) { + if (stack[i].indexOf('mocha.js:') == -1) + message += stack[i] + '\n'; + } + } else { + message += err.toString(); } console.error(message);
diff --git a/chrome/test/data/webui/settings/animation_browsertest.js b/chrome/test/data/webui/settings/animation_browsertest.js new file mode 100644 index 0000000..5ee559a --- /dev/null +++ b/chrome/test/data/webui/settings/animation_browsertest.js
@@ -0,0 +1,147 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @fileoverview Tests for settings.animation. */ + +/** @const {string} Path to root from chrome/test/data/webui/settings/. */ +var ROOT_PATH = '../../../../../'; + +/** + * @constructor + * @extends testing.Test +*/ +function SettingsAnimationBrowserTest() {} + +SettingsAnimationBrowserTest.prototype = { + __proto__: testing.Test.prototype, + + /** @override */ + browsePreload: 'chrome://md-settings/animation/animation.html', + + /** @override */ + extraLibraries: [ + ROOT_PATH + 'third_party/mocha/mocha.js', + '../mocha_adapter.js', + ], + + /** @override */ + isAsync: true, + + /** @override */ + runAccessibilityChecks: false, +}; + +TEST_F('SettingsAnimationBrowserTest', 'Animation', function() { + var self = this; + + var Animation = settings.animation.Animation; + + var onFinishBeforePromise = function() { + assertNotReached('Animation fired finish event before resolving promise'); + }; + + var onCancelUnexpectedly = function() { + assertNotReached('Animation should have finished, but fired cancel event'); + }; + + // Register mocha tests. + suite('settings.animation.Animation', function() { + var div; + var keyframes; + var options; + + setup(function() { + keyframes = [{ + height: '100px', + easing: 'ease-in', + }, { + height: '200px', + }]; + + options = { + duration: 1000, + // Use fill: both so we can test the animation start and end states. + fill: 'both', + }; + + div = document.createElement('div'); + document.body.appendChild(div); + }); + + teardown(function() { + div.remove(); + }); + + test('Animation plays', function(done) { + var animation = new Animation(div, keyframes, options); + animation.addEventListener('cancel', onCancelUnexpectedly); + animation.addEventListener('finish', onFinishBeforePromise); + + requestAnimationFrame(function() { + expectEquals(100, div.clientHeight); + + animation.finished.then(function() { + expectEquals(200, div.clientHeight); + animation.removeEventListener('finish', onFinishBeforePromise); + animation.addEventListener('finish', function() { + done(); + }); + }); + }); + }); + + test('Animation finishes', function(done) { + // Absurdly large finite value to ensure we call finish() before the + // animation finishes automatically. + options.duration = Number.MAX_VALUE; + var animation = new Animation(div, keyframes, options); + animation.addEventListener('cancel', onCancelUnexpectedly); + animation.addEventListener('finish', onFinishBeforePromise); + + // TODO(michaelpg): rAF seems more appropriate, but crbug.com/620160. + setTimeout(function() { + expectEquals(100, div.clientHeight); + + animation.finish(); + + // The promise should resolve before the finish event is scheduled. + animation.finished.then(function() { + expectEquals(200, div.clientHeight); + animation.removeEventListener('finish', onFinishBeforePromise); + animation.addEventListener('finish', function() { + done(); + }); + }); + }); + }); + + test('Animation cancels', function(done) { + // Absurdly large finite value to ensure we call cancel() before the + // animation finishes automatically. + options.duration = Number.MAX_VALUE; + var animation = new Animation(div, keyframes, options); + animation.addEventListener('cancel', onCancelUnexpectedly); + animation.addEventListener('finish', onFinishBeforePromise); + + // TODO(michaelpg): rAF seems more appropriate, but crbug.com/620160. + setTimeout(function() { + expectEquals(100, div.clientHeight); + + animation.cancel(); + + // The promise should resolve before the finish event is scheduled. + animation.finished.catch(function() { + expectEquals(0, div.clientHeight); + animation.removeEventListener('cancel', onCancelUnexpectedly); + animation.addEventListener('cancel', function() { + done(); + }); + }); + }); + }); + }); + + // Run all registered tests. + mocha.run(); +});
diff --git a/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js b/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js index ce2a7c9..4afa4250 100644 --- a/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/easy_unlock_browsertest_chromeos.js
@@ -173,6 +173,8 @@ browserProxy.setEnabledStatus(true); document.body.appendChild(page); + var turnOffDialog = null; + return browserProxy.whenCalled('getEnabledStatus').then(function() { assertTrue(page.easyUnlockAllowed_); expectTrue(page.easyUnlockEnabled_); @@ -184,31 +186,30 @@ expectFalse(turnOffButton.hidden) MockInteractions.tap(turnOffButton); - return browserProxy.whenCalled('getTurnOffFlowStatus').then(function() { - Polymer.dom.flush(); + return browserProxy.whenCalled('getTurnOffFlowStatus'); + }).then(function() { + Polymer.dom.flush(); - var turnOffDialog = page.$$('#easyUnlockTurnOffDialog'); - assertTrue(!!turnOffDialog); + turnOffDialog = page.$$('#easyUnlockTurnOffDialog'); + assertTrue(!!turnOffDialog); - var turnOffDialogConfirmButton = turnOffDialog.$$('#turnOff'); - assertTrue(!!turnOffDialogConfirmButton); - expectFalse(turnOffDialogConfirmButton.hidden); + var turnOffDialogConfirmButton = turnOffDialog.$$('#turnOff'); + assertTrue(!!turnOffDialogConfirmButton); + expectFalse(turnOffDialogConfirmButton.hidden); - MockInteractions.tap(turnOffDialogConfirmButton); + MockInteractions.tap(turnOffDialogConfirmButton); - return browserProxy.whenCalled('startTurnOffFlow').then(function() { - // To signal successful turnoff, the enabled status is broadcast - // as false. At that point, the dialog should close and cancel - // any in-progress turnoff flow. The cancellation should be - // a no-op assuming the turnoff originated from this tab. - cr.webUIListenerCallback('easy-unlock-enabled-status', false); - return browserProxy.whenCalled('cancelTurnOffFlow').then( - function() { - Polymer.dom.flush(); - expectFalse(turnOffDialog.$.dialog.opened); - }); - }); - }); + return browserProxy.whenCalled('startTurnOffFlow'); + }).then(function() { + // To signal successful turnoff, the enabled status is broadcast + // as false. At that point, the dialog should close and cancel + // any in-progress turnoff flow. The cancellation should be + // a no-op assuming the turnoff originated from this tab. + cr.webUIListenerCallback('easy-unlock-enabled-status', false); + return browserProxy.whenCalled('cancelTurnOffFlow'); + }).then(function() { + Polymer.dom.flush(); + expectFalse(turnOffDialog.$.dialog.opened); }); }); });
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js index 7492612..51a85f6 100644 --- a/chrome/test/data/webui/settings/people_page_test.js +++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -149,9 +149,10 @@ teardown(function() { peoplePage.remove(); }); test('GetProfileInfo', function() { + var disconnectButton = null; return browserProxy.whenCalled('getSyncStatus').then(function() { Polymer.dom.flush(); - var disconnectButton = peoplePage.$$('#disconnectButton'); + disconnectButton = peoplePage.$$('#disconnectButton'); assertTrue(!!disconnectButton); MockInteractions.tap(disconnectButton); @@ -165,38 +166,36 @@ assertFalse(disconnectConfirm.hidden); MockInteractions.tap(disconnectConfirm); - return browserProxy.whenCalled('signOut').then( - function(deleteProfile) { - Polymer.dom.flush(); + return browserProxy.whenCalled('signOut'); + }).then(function(deleteProfile) { + Polymer.dom.flush(); - assertFalse(deleteProfile); + assertFalse(deleteProfile); - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - domain: 'example.com', - }); - Polymer.dom.flush(); + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + domain: 'example.com', + }); + Polymer.dom.flush(); - assertFalse(peoplePage.$.disconnectDialog.opened); - MockInteractions.tap(disconnectButton); - Polymer.dom.flush(); + assertFalse(peoplePage.$.disconnectDialog.opened); + MockInteractions.tap(disconnectButton); + Polymer.dom.flush(); - assertTrue(peoplePage.$.disconnectDialog.opened); - assertTrue(peoplePage.$.deleteProfile.hidden); + assertTrue(peoplePage.$.disconnectDialog.opened); + assertTrue(peoplePage.$.deleteProfile.hidden); - var disconnectManagedProfileConfirm = - peoplePage.$.disconnectManagedProfileConfirm; - assertTrue(!!disconnectManagedProfileConfirm); - assertFalse(disconnectManagedProfileConfirm.hidden); + var disconnectManagedProfileConfirm = + peoplePage.$.disconnectManagedProfileConfirm; + assertTrue(!!disconnectManagedProfileConfirm); + assertFalse(disconnectManagedProfileConfirm.hidden); - browserProxy.resetResolver('signOut'); - MockInteractions.tap(disconnectManagedProfileConfirm); + browserProxy.resetResolver('signOut'); + MockInteractions.tap(disconnectManagedProfileConfirm); - return browserProxy.whenCalled('signOut').then( - function(deleteProfile) { - assertTrue(deleteProfile); - }); - }); + return browserProxy.whenCalled('signOut'); + }).then(function(deleteProfile) { + assertTrue(deleteProfile); }); }); });
diff --git a/chrome/test/data/webui/settings/reset_page_test.js b/chrome/test/data/webui/settings/reset_page_test.js index 8b6b8c0..befb90e9 100644 --- a/chrome/test/data/webui/settings/reset_page_test.js +++ b/chrome/test/data/webui/settings/reset_page_test.js
@@ -151,43 +151,51 @@ MockInteractions.tap(resetPage.$.resetProfile); var dialog = resetPage.$$('settings-reset-profile-dialog'); assertTrue(!!dialog); + assertTrue(dialog.$.dialog.opened); var onDialogClosed = new Promise( function(resolve, reject) { - dialog.addEventListener('iron-overlay-closed', resolve); + dialog.addEventListener('iron-overlay-closed', function() { + assertFalse(dialog.$.dialog.opened); + resolve(); + }); }); - return resetPageBrowserProxy.whenCalled( - 'onShowResetProfileDialog').then( - function() { + return new Promise(function(resolve, reject) { + resetPageBrowserProxy.whenCalled( + 'onShowResetProfileDialog').then(function() { + // Need to call requestAnimationFrame here, otherwise the dialog has + // not been registered to the IronOverlayManager at the time we + // attempt to close it (which prevents closing by 'esc' key from + // working). + window.requestAnimationFrame(function() { closeDialogFn(dialog); - return Promise.all([ + Promise.all([ onDialogClosed, resetPageBrowserProxy.whenCalled('onHideResetProfileDialog'), - ]); + ]).then(resolve, reject); }); + }); + }); } // Tests that the reset profile dialog opens and closes correctly and that // resetPageBrowserProxy calls are occurring as expected. test(TestNames.ResetProfileDialogOpenClose, function() { - return Promise.all([ + return testOpenCloseResetProfileDialog(function(dialog) { // Test case where the 'cancel' button is clicked. - testOpenCloseResetProfileDialog( - function(dialog) { - MockInteractions.tap(dialog.$.cancel); - }), - // Test case where the 'close' button is clicked. - testOpenCloseResetProfileDialog( - function(dialog) { - MockInteractions.tap(dialog.$.dialog.getCloseButton()); - }), - // Test case where the 'Esc' key is pressed. - testOpenCloseResetProfileDialog( - function(dialog) { - MockInteractions.pressAndReleaseKeyOn( - dialog, 27 /* 'Esc' key code */); - }), - ]); + MockInteractions.tap(dialog.$.cancel); + }).then(function() { + return testOpenCloseResetProfileDialog(function(dialog) { + // Test case where the 'close' button is clicked. + MockInteractions.tap(dialog.$.dialog.getCloseButton()); + }); + }).then(function() { + return testOpenCloseResetProfileDialog(function(dialog) { + // Test case where the 'Esc' key is pressed. + MockInteractions.pressAndReleaseKeyOn( + dialog, 27 /* 'Esc' key code */); + }); + }); }); // Tests that when user request to reset the profile the appropriate
diff --git a/chrome/test/data/webui/settings/site_details_permission_tests.js b/chrome/test/data/webui/settings/site_details_permission_tests.js index 1e4febb..d9ad53f7 100644 --- a/chrome/test/data/webui/settings/site_details_permission_tests.js +++ b/chrome/test/data/webui/settings/site_details_permission_tests.js
@@ -77,7 +77,7 @@ return browserProxy.whenCalled('getExceptionList').then(function() { assertTrue(testElement.$.details.hidden); - }.bind(this)); + }); }); test('camera category', function() { @@ -98,15 +98,14 @@ 'Widget should be labelled correctly'); // Flip the permission and validate that prefs stay in sync. - return validatePermissionFlipWorks(origin, true).then(function() { - browserProxy.resetResolver('setCategoryPermissionForOrigin'); - return validatePermissionFlipWorks(origin, false).then(function() { - browserProxy.resetResolver('setCategoryPermissionForOrigin'); - return validatePermissionFlipWorks(origin, true).then(function() { - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)); + return validatePermissionFlipWorks(origin, true); + }).then(function() { + browserProxy.resetResolver('setCategoryPermissionForOrigin'); + return validatePermissionFlipWorks(origin, false); + }).then(function() { + browserProxy.resetResolver('setCategoryPermissionForOrigin'); + return validatePermissionFlipWorks(origin, true); + }); }); test('disappear on empty', function() { @@ -122,10 +121,10 @@ assertFalse(testElement.$.details.hidden); browserProxy.setPrefs(prefsEmpty); - return browserProxy.whenCalled('getExceptionList').then(function() { - assertTrue(testElement.$.details.hidden); - }.bind(this)); - }.bind(this)); + return browserProxy.whenCalled('getExceptionList'); + }).then(function() { + assertTrue(testElement.$.details.hidden); + }); }); }); }
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js index 22b9cca70..8e48d95 100644 --- a/chrome/test/data/webui/settings/site_list_tests.js +++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -333,12 +333,11 @@ assertFalse(testElement.$.category.hidden); browserProxy.resetResolver('getExceptionList'); testElement.categoryEnabled = false; - return browserProxy.whenCalled('getExceptionList').then( - function(contentType) { - assertFalse(testElement.$.category.hidden); - assertEquals('Exceptions - 0', - testElement.$.header.innerText.trim()); - }); + return browserProxy.whenCalled('getExceptionList'); + }).then(function(contentType) { + assertFalse(testElement.$.category.hidden); + assertEquals('Exceptions - 0', + testElement.$.header.innerText.trim()); }); }); @@ -364,12 +363,11 @@ assertFalse(testElement.$.category.hidden); browserProxy.resetResolver('getExceptionList'); testElement.categoryEnabled = false; - return browserProxy.whenCalled('getExceptionList').then( - function(contentType) { - assertFalse(testElement.$.category.hidden); - assertEquals('Exceptions - 2', - testElement.$.header.innerText.trim()); - }); + return browserProxy.whenCalled('getExceptionList'); + }).then(function(contentType) { + assertFalse(testElement.$.category.hidden); + assertEquals('Exceptions - 2', + testElement.$.header.innerText.trim()); }); }); @@ -395,10 +393,9 @@ assertFalse(testElement.$.category.hidden); browserProxy.resetResolver('getExceptionList'); testElement.categoryEnabled = false; - return browserProxy.whenCalled('getExceptionList').then( - function(contentType) { - assertTrue(testElement.$.category.hidden); - }); + return browserProxy.whenCalled('getExceptionList'); + }).then(function(contentType) { + assertTrue(testElement.$.category.hidden); }); }); @@ -426,12 +423,10 @@ assertFalse(testElement.$.category.hidden); browserProxy.resetResolver('getExceptionList'); testElement.categoryEnabled = false; - return browserProxy.whenCalled('getExceptionList').then( - function(contentType) { - assertFalse(testElement.$.category.hidden); - assertEquals('Clear on exit - 1', - testElement.$.header.innerText); - }); + return browserProxy.whenCalled('getExceptionList'); + }).then(function(contentType) { + assertFalse(testElement.$.category.hidden); + assertEquals('Clear on exit - 1', testElement.$.header.innerText); }); });
diff --git a/chrome/test/data/webui/settings/site_settings_category_tests.js b/chrome/test/data/webui/settings/site_settings_category_tests.js index ed1da65..d926b56d 100644 --- a/chrome/test/data/webui/settings/site_settings_category_tests.js +++ b/chrome/test/data/webui/settings/site_settings_category_tests.js
@@ -79,17 +79,15 @@ settings.ContentSettingsTypes.GEOLOCATION, contentType); assertEquals(enabled, testElement.categoryEnabled); MockInteractions.tap(testElement.$.toggle); - return browserProxy.whenCalled( - 'setDefaultValueForContentType').then( - function(arguments) { - assertEquals( - settings.ContentSettingsTypes.GEOLOCATION, arguments[0]); - assertEquals( - enabled ? settings.PermissionValues.BLOCK : - settings.PermissionValues.ASK, - arguments[1]); - assertNotEquals(enabled, testElement.categoryEnabled); - }); + return browserProxy.whenCalled('setDefaultValueForContentType'); + }).then(function(arguments) { + assertEquals( + settings.ContentSettingsTypes.GEOLOCATION, arguments[0]); + assertEquals( + enabled ? settings.PermissionValues.BLOCK : + settings.PermissionValues.ASK, + arguments[1]); + assertNotEquals(enabled, testElement.categoryEnabled); }); }
diff --git a/chrome/utility/importer/ie_importer_win.cc b/chrome/utility/importer/ie_importer_win.cc index 2ef4b47..aadfd5b 100644 --- a/chrome/utility/importer/ie_importer_win.cc +++ b/chrome/utility/importer/ie_importer_win.cc
@@ -627,9 +627,9 @@ ac.key.erase(i); ac.is_url = (ac.key.find(L"://") != base::string16::npos); ac_list.push_back(ac); - ac_list[ac_list.size() - 1].data = base::SplitString( - data, base::string16(1, '\0'), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + ac_list.back().data = + base::SplitString(data, base::string16(1, '\0'), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); } CoTaskMemFree(buffer); }
diff --git a/chrome/utility/media_galleries/picasa_album_table_reader.cc b/chrome/utility/media_galleries/picasa_album_table_reader.cc index a02b03f..b8b5d9b8 100644 --- a/chrome/utility/media_galleries/picasa_album_table_reader.cc +++ b/chrome/utility/media_galleries/picasa_album_table_reader.cc
@@ -24,7 +24,12 @@ base::TimeDelta variant_delta = base::TimeDelta::FromMicroseconds( static_cast<int64_t>(variant_time * base::Time::kMicrosecondsPerDay)); - return base::Time::FromLocalExploded(kPmpVariantTimeEpoch) + variant_delta; + base::Time out_time; + bool conversion_success = + base::Time::FromLocalExploded(kPmpVariantTimeEpoch, &out_time); + DCHECK(conversion_success); + + return out_time + variant_delta; } } // namespace
diff --git a/chromecast/browser/cast_memory_pressure_monitor.cc b/chromecast/browser/cast_memory_pressure_monitor.cc index 75d8d0e6..ed70148 100644 --- a/chromecast/browser/cast_memory_pressure_monitor.cc +++ b/chromecast/browser/cast_memory_pressure_monitor.cc
@@ -46,6 +46,8 @@ CastMemoryPressureMonitor::CastMemoryPressureMonitor() : current_level_(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), system_reserved_kb_(GetSystemReservedKb()), + dispatch_callback_( + base::Bind(&base::MemoryPressureListener::NotifyMemoryPressure)), weak_ptr_factory_(this) { PollPressureLevel(); } @@ -111,7 +113,7 @@ void CastMemoryPressureMonitor::UpdateMemoryPressureLevel( MemoryPressureLevel new_level) { if (new_level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) - base::MemoryPressureListener::NotifyMemoryPressure(new_level); + dispatch_callback_.Run(new_level); if (new_level == current_level_) return; @@ -121,4 +123,9 @@ "Memory.Pressure.LevelChange", new_level); } +void CastMemoryPressureMonitor::SetDispatchCallback( + const DispatchCallback& callback) { + dispatch_callback_ = callback; +} + } // namespace chromecast
diff --git a/chromecast/browser/cast_memory_pressure_monitor.h b/chromecast/browser/cast_memory_pressure_monitor.h index b24702c..bb6ed92 100644 --- a/chromecast/browser/cast_memory_pressure_monitor.h +++ b/chromecast/browser/cast_memory_pressure_monitor.h
@@ -22,6 +22,7 @@ // base::MemoryPressureMonitor implementation: MemoryPressureLevel GetCurrentPressureLevel() const override; + void SetDispatchCallback(const DispatchCallback& callback) override; private: void PollPressureLevel(); @@ -29,6 +30,7 @@ MemoryPressureLevel current_level_; const int system_reserved_kb_; + DispatchCallback dispatch_callback_; base::WeakPtrFactory<CastMemoryPressureMonitor> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CastMemoryPressureMonitor);
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc index e65aa25..106a25cc 100644 --- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc +++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -168,7 +168,7 @@ class FakeAudioManager : public CastAudioManager { public: FakeAudioManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : CastAudioManager(task_runner, task_runner, nullptr, nullptr), + : CastAudioManager(task_runner, task_runner, nullptr, nullptr, nullptr), media_pipeline_backend_(nullptr) {} ~FakeAudioManager() override {}
diff --git a/chromecast/media/cdm/cast_cdm.cc b/chromecast/media/cdm/cast_cdm.cc index 30965c11..5125648 100644 --- a/chromecast/media/cdm/cast_cdm.cc +++ b/chromecast/media/cdm/cast_cdm.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "chromecast/media/base/decrypt_context_impl.h" #include "chromecast/media/base/media_resource_tracker.h" #include "media/base/cdm_key_information.h" #include "media/base/decryptor.h" @@ -18,10 +19,48 @@ namespace chromecast { namespace media { +namespace { + +class CastCdmContextImpl : public CastCdmContext { + public: + explicit CastCdmContextImpl(CastCdm* cast_cdm) : cast_cdm_(cast_cdm) { + DCHECK(cast_cdm_); + } + ~CastCdmContextImpl() override {} + + // CastCdmContext implementation: + int RegisterPlayer(const base::Closure& new_key_cb, + const base::Closure& cdm_unset_cb) override { + return cast_cdm_->RegisterPlayer(new_key_cb, cdm_unset_cb); + } + + void UnregisterPlayer(int registration_id) override { + cast_cdm_->UnregisterPlayer(registration_id); + } + + std::unique_ptr<DecryptContextImpl> GetDecryptContext( + const std::string& key_id) override { + return cast_cdm_->GetDecryptContext(key_id); + } + + void SetKeyStatus(const std::string& key_id, + CastKeyStatus key_status, + uint32_t system_code) override { + cast_cdm_->SetKeyStatus(key_id, key_status, system_code); + } + + private: + // The CastCdm object which owns |this|. + CastCdm* const cast_cdm_; + + DISALLOW_COPY_AND_ASSIGN(CastCdmContextImpl); +}; + +} // namespace CastCdm::CastCdm(MediaResourceTracker* media_resource_tracker) : media_resource_tracker_(media_resource_tracker), - cast_cdm_context_(new CastCdmContext(this)) { + cast_cdm_context_(new CastCdmContextImpl(this)) { DCHECK(media_resource_tracker); thread_checker_.DetachFromThread(); }
diff --git a/chromecast/media/cdm/cast_cdm_context.cc b/chromecast/media/cdm/cast_cdm_context.cc index 742516ca..949f5da 100644 --- a/chromecast/media/cdm/cast_cdm_context.cc +++ b/chromecast/media/cdm/cast_cdm_context.cc
@@ -4,20 +4,9 @@ #include "chromecast/media/cdm/cast_cdm_context.h" -#include "base/logging.h" -#include "chromecast/media/base/decrypt_context_impl.h" -#include "chromecast/media/cdm/cast_cdm.h" -#include "chromecast/public/media/decrypt_context.h" - namespace chromecast { namespace media { -CastCdmContext::CastCdmContext(CastCdm* cast_cdm) : cast_cdm_(cast_cdm) { - DCHECK(cast_cdm_); -} - -CastCdmContext::~CastCdmContext() {} - ::media::Decryptor* CastCdmContext::GetDecryptor() { // Subclasses providing CdmContext for a ClearKey CDM implementation must // override this method to provide the Decryptor. Subclasses providing DRM @@ -30,25 +19,5 @@ return ::media::CdmContext::kInvalidCdmId; } -int CastCdmContext::RegisterPlayer(const base::Closure& new_key_cb, - const base::Closure& cdm_unset_cb) { - return cast_cdm_->RegisterPlayer(new_key_cb, cdm_unset_cb); -} - -void CastCdmContext::UnregisterPlayer(int registration_id) { - cast_cdm_->UnregisterPlayer(registration_id); -} - -std::unique_ptr<DecryptContextImpl> CastCdmContext::GetDecryptContext( - const std::string& key_id) { - return cast_cdm_->GetDecryptContext(key_id); -} - -void CastCdmContext::SetKeyStatus(const std::string& key_id, - CastKeyStatus key_status, - uint32_t system_code) { - cast_cdm_->SetKeyStatus(key_id, key_status, system_code); -} - } // namespace media } // namespace chromecast
diff --git a/chromecast/media/cdm/cast_cdm_context.h b/chromecast/media/cdm/cast_cdm_context.h index 70fa26ba9..ad98119 100644 --- a/chromecast/media/cdm/cast_cdm_context.h +++ b/chromecast/media/cdm/cast_cdm_context.h
@@ -11,54 +11,40 @@ #include "chromecast/public/media/cast_key_status.h" #include "media/base/cdm_context.h" -namespace media { -class Decryptor; -} - namespace chromecast { namespace media { -class CastCdm; class DecryptContextImpl; -// This class exposes only what's needed by CastRenderer. +// CdmContext implementation + some extra APIs needed by CastRenderer. class CastCdmContext : public ::media::CdmContext { public: - explicit CastCdmContext(CastCdm* cast_cdm); - ~CastCdmContext() override; - // ::media::CdmContext implementation. ::media::Decryptor* GetDecryptor() override; int GetCdmId() const override; // Register a player with this CDM. |new_key_cb| will be called when a new // key is available. |cdm_unset_cb| will be called when the CDM is destroyed. - int RegisterPlayer(const base::Closure& new_key_cb, - const base::Closure& cdm_unset_cb); + virtual int RegisterPlayer(const base::Closure& new_key_cb, + const base::Closure& cdm_unset_cb) = 0; // Unregiester a player with this CDM. |registration_id| should be the id // returned by RegisterPlayer(). - void UnregisterPlayer(int registration_id); + virtual void UnregisterPlayer(int registration_id) = 0; // Returns the decryption context needed to decrypt frames encrypted with // |key_id|. Returns null if |key_id| is not available. - std::unique_ptr<DecryptContextImpl> GetDecryptContext( - const std::string& key_id); + virtual std::unique_ptr<DecryptContextImpl> GetDecryptContext( + const std::string& key_id) = 0; // Notifies that key status has changed (e.g. if expiry is detected by // hardware decoder). - void SetKeyStatus(const std::string& key_id, - CastKeyStatus key_status, - uint32_t system_code); - - private: - // The CastCdm object which owns |this|. - CastCdm* const cast_cdm_; - - DISALLOW_COPY_AND_ASSIGN(CastCdmContext); + virtual void SetKeyStatus(const std::string& key_id, + CastKeyStatus key_status, + uint32_t system_code) = 0; }; } // namespace media } // namespace chromecast -#endif // CHROMECAST_MEDIA_CDM_CAST_CDM_CONTEXT_H_ \ No newline at end of file +#endif // CHROMECAST_MEDIA_CDM_CAST_CDM_CONTEXT_H_
diff --git a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc index 6ea235c..2e186c9 100644 --- a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc +++ b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
@@ -8,6 +8,8 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" +#include "chromecast/media/base/decrypt_context_impl.h" +#include "chromecast/media/cdm/cast_cdm_context.h" #include "chromecast/media/cma/backend/audio_decoder_default.h" #include "chromecast/media/cma/backend/media_pipeline_backend_default.h" #include "chromecast/media/cma/backend/video_decoder_default.h" @@ -19,6 +21,7 @@ #include "media/base/audio_decoder_config.h" #include "media/base/media_util.h" #include "media/base/video_decoder_config.h" +#include "media/cdm/player_tracker_impl.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -33,14 +36,98 @@ namespace chromecast { namespace media { -using AudioVideoTuple = ::testing::tuple<bool, bool>; - -class AudioVideoPipelineImplTest - : public ::testing::TestWithParam<AudioVideoTuple> { +class CastCdmContextForTest : public CastCdmContext { public: - AudioVideoPipelineImplTest() : pipeline_backend_(nullptr) { + CastCdmContextForTest() : license_installed_(false) {} + void SetLicenseInstalled() { + license_installed_ = true; + player_tracker_.NotifyNewKey(); + } + + // CastCdmContext implementation: + int RegisterPlayer(const base::Closure& new_key_cb, + const base::Closure& cdm_unset_cb) override { + return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb); + } + + void UnregisterPlayer(int registration_id) override { + return player_tracker_.UnregisterPlayer(registration_id); + } + + std::unique_ptr<DecryptContextImpl> GetDecryptContext( + const std::string& key_id) override { + if (license_installed_) { + return std::unique_ptr<DecryptContextImpl>( + new DecryptContextImpl(KEY_SYSTEM_CLEAR_KEY)); + } else { + return std::unique_ptr<DecryptContextImpl>(); + } + } + + void SetKeyStatus(const std::string& key_id, + CastKeyStatus key_status, + uint32_t system_code) override {} + + private: + bool license_installed_; + base::Closure new_key_cb_; + ::media::PlayerTrackerImpl player_tracker_; + + DISALLOW_COPY_AND_ASSIGN(CastCdmContextForTest); +}; + +// Helper class for managing pipeline setup, teardown, feeding data, stop/start +// etc in a simple API for tests to use. +class PipelineHelper { + public: + PipelineHelper(scoped_refptr<base::SingleThreadTaskRunner> task_runner, + bool audio, + bool video, + bool encrypted) + : have_audio_(audio), + have_video_(video), + encrypted_(encrypted), + pipeline_backend_(nullptr) { eos_[STREAM_AUDIO] = eos_[STREAM_VIDEO] = false; } + + void Setup() { + if (encrypted_) { + cdm_context_.reset(new CastCdmContextForTest()); + } + std::unique_ptr<MediaPipelineBackendDefault> backend = + base::WrapUnique(new MediaPipelineBackendDefault()); + pipeline_backend_ = backend.get(); + media_pipeline_.Initialize(kLoadTypeURL, std::move(backend)); + + if (have_audio_) { + ::media::AudioDecoderConfig audio_config( + ::media::kCodecMP3, ::media::kSampleFormatS16, + ::media::CHANNEL_LAYOUT_STEREO, 44100, ::media::EmptyExtraData(), + ::media::Unencrypted()); + AvPipelineClient client; + client.eos_cb = base::Bind(&PipelineHelper::OnEos, base::Unretained(this), + STREAM_AUDIO); + ::media::PipelineStatus status = media_pipeline_.InitializeAudio( + audio_config, client, CreateFrameProvider()); + ASSERT_EQ(::media::PIPELINE_OK, status); + } + if (have_video_) { + std::vector<::media::VideoDecoderConfig> video_configs; + video_configs.push_back(::media::VideoDecoderConfig( + ::media::kCodecH264, ::media::H264PROFILE_MAIN, + ::media::PIXEL_FORMAT_I420, ::media::COLOR_SPACE_UNSPECIFIED, + gfx::Size(640, 480), gfx::Rect(0, 0, 640, 480), gfx::Size(640, 480), + ::media::EmptyExtraData(), ::media::EncryptionScheme())); + VideoPipelineClient client; + client.av_pipeline_client.eos_cb = base::Bind( + &PipelineHelper::OnEos, base::Unretained(this), STREAM_VIDEO); + ::media::PipelineStatus status = media_pipeline_.InitializeVideo( + video_configs, client, CreateFrameProvider()); + ASSERT_EQ(::media::PIPELINE_OK, status); + } + } + void Start(const base::Closure& eos_cb) { eos_cb_ = eos_cb; eos_[STREAM_AUDIO] = !media_pipeline_.HasAudio(); @@ -48,55 +135,18 @@ base::TimeDelta start_time = base::TimeDelta::FromMilliseconds(0); media_pipeline_.StartPlayingFrom(start_time); } + void SetCdm() { media_pipeline_.SetCdm(cdm_context_.get()); } void Flush(const base::Closure& flush_cb) { media_pipeline_.Flush(flush_cb); } void Stop() { media_pipeline_.Stop(); base::MessageLoop::current()->QuitWhenIdle(); } + void SetCdmLicenseInstalled() { cdm_context_->SetLicenseInstalled(); } MediaPipelineBackendDefault* pipeline_backend() { return pipeline_backend_; } - protected: - void SetUp() override { - std::unique_ptr<MediaPipelineBackendDefault> backend = - base::WrapUnique(new MediaPipelineBackendDefault()); - pipeline_backend_ = backend.get(); - media_pipeline_.Initialize(kLoadTypeURL, std::move(backend)); - - if (::testing::get<0>(GetParam())) { - ::media::AudioDecoderConfig audio_config( - ::media::kCodecMP3, ::media::kSampleFormatS16, - ::media::CHANNEL_LAYOUT_STEREO, 44100, ::media::EmptyExtraData(), - ::media::Unencrypted()); - AvPipelineClient client; - client.eos_cb = base::Bind(&AudioVideoPipelineImplTest::OnEos, - base::Unretained(this), STREAM_AUDIO); - ::media::PipelineStatus status = media_pipeline_.InitializeAudio( - audio_config, client, CreateFrameProvider()); - ASSERT_EQ(::media::PIPELINE_OK, status); - } - if (::testing::get<1>(GetParam())) { - std::vector<::media::VideoDecoderConfig> video_configs; - video_configs.push_back(::media::VideoDecoderConfig( - ::media::kCodecH264, ::media::H264PROFILE_MAIN, - ::media::PIXEL_FORMAT_I420, ::media::COLOR_SPACE_UNSPECIFIED, - gfx::Size(640, 480), gfx::Rect(0, 0, 640, 480), gfx::Size(640, 480), - ::media::EmptyExtraData(), ::media::Unencrypted())); - VideoPipelineClient client; - client.av_pipeline_client.eos_cb = - base::Bind(&AudioVideoPipelineImplTest::OnEos, base::Unretained(this), - STREAM_VIDEO); - ::media::PipelineStatus status = media_pipeline_.InitializeVideo( - video_configs, client, CreateFrameProvider()); - ASSERT_EQ(::media::PIPELINE_OK, status); - } - } - - base::MessageLoop message_loop_; - private: enum Stream { STREAM_AUDIO, STREAM_VIDEO }; - DISALLOW_COPY_AND_ASSIGN(AudioVideoPipelineImplTest); std::unique_ptr<CodedFrameProvider> CreateFrameProvider() { std::vector<FrameGeneratorForTest::FrameSpec> frame_specs; @@ -106,7 +156,7 @@ frame_specs[k].timestamp = base::TimeDelta::FromMicroseconds(kFrameDurationUs) * k; frame_specs[k].size = kFrameSize; - frame_specs[k].has_decrypt_config = false; + frame_specs[k].has_decrypt_config = encrypted_; } frame_specs[frame_specs.size() - 1].is_eos = true; @@ -129,15 +179,42 @@ eos_cb_.Run(); } + bool have_audio_; + bool have_video_; + bool encrypted_; bool eos_[2]; base::Closure eos_cb_; MediaPipelineImpl media_pipeline_; + std::unique_ptr<CastCdmContextForTest> cdm_context_; MediaPipelineBackendDefault* pipeline_backend_; + + DISALLOW_COPY_AND_ASSIGN(PipelineHelper); }; -static void VerifyPlay(AudioVideoPipelineImplTest* pipeline_test) { +using AudioVideoTuple = ::testing::tuple<bool, bool>; + +class AudioVideoPipelineImplTest + : public ::testing::TestWithParam<AudioVideoTuple> { + public: + AudioVideoPipelineImplTest() {} + + protected: + void SetUp() override { + pipeline_helper_.reset(new PipelineHelper( + message_loop_.task_runner(), ::testing::get<0>(GetParam()), + ::testing::get<1>(GetParam()), false)); + pipeline_helper_->Setup(); + } + + base::MessageLoop message_loop_; + std::unique_ptr<PipelineHelper> pipeline_helper_; + + DISALLOW_COPY_AND_ASSIGN(AudioVideoPipelineImplTest); +}; + +static void VerifyPlay(PipelineHelper* pipeline_helper) { // The backend must still be running. - MediaPipelineBackendDefault* backend = pipeline_test->pipeline_backend(); + MediaPipelineBackendDefault* backend = pipeline_helper->pipeline_backend(); EXPECT_TRUE(backend->running()); // The decoders must have received a few frames. @@ -149,20 +226,22 @@ if (video_decoder) EXPECT_EQ(kLastFrameTimestamp, video_decoder->last_push_pts()); - pipeline_test->Stop(); + pipeline_helper->Stop(); } TEST_P(AudioVideoPipelineImplTest, Play) { - base::Closure verify_task = base::Bind(&VerifyPlay, base::Unretained(this)); - message_loop_.PostTask(FROM_HERE, - base::Bind(&AudioVideoPipelineImplTest::Start, - base::Unretained(this), verify_task)); + base::Closure verify_task = + base::Bind(&VerifyPlay, base::Unretained(pipeline_helper_.get())); + message_loop_.PostTask( + FROM_HERE, + base::Bind(&PipelineHelper::Start, + base::Unretained(pipeline_helper_.get()), verify_task)); message_loop_.Run(); } -static void VerifyFlush(AudioVideoPipelineImplTest* pipeline_test) { +static void VerifyFlush(PipelineHelper* pipeline_helper) { // The backend must have been stopped. - MediaPipelineBackendDefault* backend = pipeline_test->pipeline_backend(); + MediaPipelineBackendDefault* backend = pipeline_helper->pipeline_backend(); EXPECT_FALSE(backend->running()); // The decoders must not have received any frame. @@ -174,7 +253,7 @@ if (video_decoder) EXPECT_LT(video_decoder->last_push_pts(), 0); - pipeline_test->Stop(); + pipeline_helper->Stop(); } static void VerifyNotReached() { @@ -182,27 +261,30 @@ } TEST_P(AudioVideoPipelineImplTest, Flush) { - base::Closure verify_task = base::Bind(&VerifyFlush, base::Unretained(this)); + base::Closure verify_task = + base::Bind(&VerifyFlush, base::Unretained(pipeline_helper_.get())); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::Start, + base::Unretained(pipeline_helper_.get()), + base::Bind(&VerifyNotReached))); message_loop_.PostTask( FROM_HERE, - base::Bind(&AudioVideoPipelineImplTest::Start, base::Unretained(this), - base::Bind(&VerifyNotReached))); - message_loop_.PostTask(FROM_HERE, - base::Bind(&AudioVideoPipelineImplTest::Flush, - base::Unretained(this), verify_task)); + base::Bind(&PipelineHelper::Flush, + base::Unretained(pipeline_helper_.get()), verify_task)); message_loop_.Run(); } TEST_P(AudioVideoPipelineImplTest, FullCycle) { - base::Closure stop_task = - base::Bind(&AudioVideoPipelineImplTest::Stop, base::Unretained(this)); - base::Closure eos_cb = base::Bind(&AudioVideoPipelineImplTest::Flush, - base::Unretained(this), stop_task); + base::Closure stop_task = base::Bind( + &PipelineHelper::Stop, base::Unretained(pipeline_helper_.get())); + base::Closure eos_cb = + base::Bind(&PipelineHelper::Flush, + base::Unretained(pipeline_helper_.get()), stop_task); - message_loop_.PostTask(FROM_HERE, - base::Bind(&AudioVideoPipelineImplTest::Start, - base::Unretained(this), eos_cb)); + message_loop_.PostTask( + FROM_HERE, base::Bind(&PipelineHelper::Start, + base::Unretained(pipeline_helper_.get()), eos_cb)); message_loop_.Run(); }; @@ -214,5 +296,79 @@ AudioVideoTuple(false, true), // Video only. AudioVideoTuple(true, true))); // Audio and Video. +// These tests verify that the pipeline handles encrypted media playback +// events (in particular, CDM and license installation) correctly. +class EncryptedAVPipelineImplTest : public ::testing::Test { + public: + EncryptedAVPipelineImplTest() {} + + protected: + void SetUp() override { + pipeline_helper_.reset( + new PipelineHelper(message_loop_.task_runner(), true, true, true)); + pipeline_helper_->Setup(); + } + + base::MessageLoop message_loop_; + std::unique_ptr<PipelineHelper> pipeline_helper_; + + DISALLOW_COPY_AND_ASSIGN(EncryptedAVPipelineImplTest); +}; + +// Sets a CDM with license already installed before starting the pipeline. +TEST_F(EncryptedAVPipelineImplTest, SetCdmWithLicenseBeforeStart) { + base::Closure verify_task = + base::Bind(&VerifyPlay, base::Unretained(pipeline_helper_.get())); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::SetCdm, + base::Unretained(pipeline_helper_.get()))); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::SetCdmLicenseInstalled, + base::Unretained(pipeline_helper_.get()))); + message_loop_.PostTask( + FROM_HERE, + base::Bind(&PipelineHelper::Start, + base::Unretained(pipeline_helper_.get()), verify_task)); + message_loop_.Run(); +} + +// Start the pipeline, then set a CDM with existing license. +TEST_F(EncryptedAVPipelineImplTest, SetCdmWithLicenseAfterStart) { + base::Closure verify_task = + base::Bind(&VerifyPlay, base::Unretained(pipeline_helper_.get())); + message_loop_.PostTask( + FROM_HERE, + base::Bind(&PipelineHelper::Start, + base::Unretained(pipeline_helper_.get()), verify_task)); + + message_loop_.RunUntilIdle(); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::SetCdmLicenseInstalled, + base::Unretained(pipeline_helper_.get()))); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::SetCdm, + base::Unretained(pipeline_helper_.get()))); + message_loop_.Run(); +} + +// Start the pipeline, set a CDM, and then install the license. +TEST_F(EncryptedAVPipelineImplTest, SetCdmAndInstallLicenseAfterStart) { + base::Closure verify_task = + base::Bind(&VerifyPlay, base::Unretained(pipeline_helper_.get())); + message_loop_.PostTask( + FROM_HERE, + base::Bind(&PipelineHelper::Start, + base::Unretained(pipeline_helper_.get()), verify_task)); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::SetCdm, + base::Unretained(pipeline_helper_.get()))); + + message_loop_.RunUntilIdle(); + message_loop_.PostTask(FROM_HERE, + base::Bind(&PipelineHelper::SetCdmLicenseInstalled, + base::Unretained(pipeline_helper_.get()))); + message_loop_.Run(); +} + } // namespace media } // namespace chromecast
diff --git a/chromeos/settings/timezone_settings.cc b/chromeos/settings/timezone_settings.cc index b8ce973c..dcc9eda 100644 --- a/chromeos/settings/timezone_settings.cc +++ b/chromeos/settings/timezone_settings.cc
@@ -223,7 +223,8 @@ std::string timezone(buf, len); // Remove kTimezoneFilesDir from the beginning. - if (timezone.find(kTimezoneFilesDir) != 0) { + if (!base::StartsWith(timezone, kTimezoneFilesDir, + base::CompareCase::SENSITIVE)) { LOG(ERROR) << "GetTimezoneID: Timezone symlink is wrong " << timezone; return std::string();
diff --git a/components/BUILD.gn b/components/BUILD.gn index abf71d07..75b05aa7 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -483,6 +483,7 @@ "scheduler/base/task_queue_manager_delegate_for_test.cc", "scheduler/base/task_queue_manager_delegate_for_test.h", "scheduler/base/task_queue_manager_perftest.cc", + "scheduler/base/test_task_time_tracker.h", "visitedlink/test/visitedlink_perftest.cc", ]
diff --git a/components/arc/common/app.mojom b/components/arc/common/app.mojom index f9aed0b..d3d3039 100644 --- a/components/arc/common/app.mojom +++ b/components/arc/common/app.mojom
@@ -9,6 +9,14 @@ import "scale_factor.mojom"; import "screen_rect.mojom"; +// Describes OrientationLock request. +[Extensible] +enum OrientationLock { + NONE = 0, + PORTRAIT = 1, + LANDSCAPE = 2, +}; + // Describes ARC app. struct AppInfo { string name; @@ -16,6 +24,7 @@ string activity; [MinVersion=2] bool sticky; // true if the app cannot be uninstalled [MinVersion=7] bool notifications_enabled; + [MinVersion=11] OrientationLock orientation_lock; }; // Describes ARC package. @@ -46,7 +55,7 @@ MANAGE_LINKS = 1, }; -// Next method ID: 12 +// Next method ID: 13 interface AppHost { // Sends newly added ARC app to Chrome. This message is sent when ARC receives // package added notification. Multiple apps may be added in the one package. @@ -96,6 +105,10 @@ // Notifies that an application shortcut needs to be created. [MinVersion=9] OnInstallShortcut@11(ShortcutInfo shortcut); + + // Notifies that task requested orientation lock. + [MinVersion=11] OnTaskOrientationLockRequested@12(int32 task_id, + OrientationLock lock); }; // TODO(lhchavez): Migrate all request/response messages to Mojo.
diff --git a/components/arc/common/video.mojom b/components/arc/common/video.mojom index b371d6d..8b859af 100644 --- a/components/arc/common/video.mojom +++ b/components/arc/common/video.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next MinVersion: 4 +// Next MinVersion: 5 module arc.mojom; @@ -23,7 +23,7 @@ // Requests an IPC channel from Chrome's browser process to bootstrap a new // mojo child process and a token which can be used to create a message pipe // connected to a new VideoAcceleratorFactory. - [MinVersion=3] + [MinVersion=4] OnBootstrapVideoAcceleratorFactory@1() => (handle channel_handle, string token); };
diff --git a/components/arc/common/video_accelerator.mojom b/components/arc/common/video_accelerator.mojom index 6a581dd..2cb1abd 100644 --- a/components/arc/common/video_accelerator.mojom +++ b/components/arc/common/video_accelerator.mojom
@@ -49,6 +49,11 @@ uint32 input_pixel_format; }; +struct ArcVideoAcceleratorDmabufPlane { + int32 offset; + int32 stride; +}; + interface VideoAcceleratorService { enum Result { SUCCESS = 0, @@ -69,7 +74,12 @@ BindSharedMemory@1(PortType port, uint32 index, handle ashmem_fd, uint32 offset, uint32 length); - BindDmabuf@2(PortType port, uint32 index, handle dmabuf_fd, int32 stride); + DeprecatedBindDmabuf@2(PortType port, uint32 index, handle dmabuf_fd, + int32 stride); + + [MinVersion=3] + BindDmabuf@9(PortType port, uint32 index, handle dmabuf_fd, + array<ArcVideoAcceleratorDmabufPlane> dmabuf_planes); UseBuffer@3(PortType port, uint32 index, BufferMetadata metadata);
diff --git a/components/autofill/content/browser/risk/fingerprint.cc b/components/autofill/content/browser/risk/fingerprint.cc index 08ed54e..67d4847 100644 --- a/components/autofill/content/browser/risk/fingerprint.cc +++ b/components/autofill/content/browser/risk/fingerprint.cc
@@ -66,7 +66,11 @@ base::Time::Exploded local; utc.LocalExplode(&local); - return base::Time::FromUTCExploded(local) - utc; + base::Time out_time; + bool conversion_success = base::Time::FromUTCExploded(local, &out_time); + DCHECK(conversion_success); + + return out_time - utc; } // Returns the concatenation of the operating system name and version, e.g.
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 1254112a..44cee7f 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -120,10 +120,8 @@ std::vector<base::string16> parts = base::SplitString( prefix, base::ASCIIToUTF16(","), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - if (!parts.empty()) { - base::TrimWhitespace(parts[parts.size() - 1], base::TRIM_LEADING, - &prefix); - } + if (!parts.empty()) + base::TrimWhitespace(parts.back(), base::TRIM_LEADING, &prefix); } // Prefix filtering. @@ -500,7 +498,7 @@ } } last_part.append(suggested_value); - parts[parts.size() - 1] = last_part; + parts.back() = last_part; new_value = base::JoinString(parts, base::ASCIIToUTF16(",")); }
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index e6863f34..1fa267a1 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -59,6 +59,11 @@ void BindRequest(mojom::AutofillAgentRequest request); + protected: + // blink::WebAutofillClient: + void didAssociateFormControls( + const blink::WebVector<blink::WebNode>& nodes) override; + private: // Functor used as a simplified comparison function for FormData. Only // compares forms at a high level (notably name, origin, action). @@ -156,8 +161,6 @@ const blink::WebInputElement& element, const blink::WebKeyboardEvent& event) override; void setIgnoreTextChanges(bool ignore) override; - void didAssociateFormControls( - const blink::WebVector<blink::WebNode>& nodes) override; void openTextDataListChooser(const blink::WebInputElement& element) override; void dataListOptionsChanged(const blink::WebInputElement& element) override; void firstUserGestureObserved() override;
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 61bcd71..4306f8c3 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -448,10 +448,7 @@ encoded_signatures->push_back(signature); } - if (!encoded_signatures->size()) - return false; - - return true; + return !encoded_signatures->empty(); } // static
diff --git a/components/cast_certificate/cast_cert_validator.cc b/components/cast_certificate/cast_cert_validator.cc index 6a81c84d..ec1fae2e 100644 --- a/components/cast_certificate/cast_cert_validator.cc +++ b/components/cast_certificate/cast_cert_validator.cc
@@ -13,15 +13,16 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" +#include "net/cert/internal/cert_issuer_source_static.h" #include "net/cert/internal/certificate_policies.h" #include "net/cert/internal/extended_key_usage.h" #include "net/cert/internal/parse_certificate.h" #include "net/cert/internal/parse_name.h" #include "net/cert/internal/parsed_certificate.h" +#include "net/cert/internal/path_builder.h" #include "net/cert/internal/signature_algorithm.h" #include "net/cert/internal/signature_policy.h" #include "net/cert/internal/trust_store.h" -#include "net/cert/internal/verify_certificate_chain.h" #include "net/cert/internal/verify_signed_data.h" #include "net/der/input.h" @@ -245,20 +246,6 @@ return result; } -class ScopedCheckUnreferencedCerts { - public: - explicit ScopedCheckUnreferencedCerts( - std::vector<scoped_refptr<net::ParsedCertificate>>* certs) - : certs_(certs) {} - ~ScopedCheckUnreferencedCerts() { - for (const auto& cert : *certs_) - DCHECK(cert->HasOneRef()); - } - - private: - std::vector<scoped_refptr<net::ParsedCertificate>>* certs_; -}; - // Returns the parsing options used for Cast certificates. net::ParseCertificateOptions GetCertParsingOptions() { net::ParseCertificateOptions options; @@ -281,38 +268,46 @@ const base::Time::Exploded& time, std::unique_ptr<CertVerificationContext>* context, CastDeviceCertPolicy* policy) { - // The underlying verification function expects a sequence of - // ParsedCertificate. - std::vector<scoped_refptr<net::ParsedCertificate>> input_chain; - // Verify that nothing saves a reference to the input certs, since the backing - // data will go out of scope when the function finishes. - ScopedCheckUnreferencedCerts ref_checker(&input_chain); + if (certs.empty()) + return false; - for (const auto& cert_der : certs) { - // No reference to the ParsedCertificate is kept past the end of this - // function, so using EXTERNAL_REFERENCE here is safe. - if (!net::ParsedCertificate::CreateAndAddToVector( - reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size(), + // No reference to these ParsedCertificates is kept past the end of this + // function, so using EXTERNAL_REFERENCE here is safe. + scoped_refptr<net::ParsedCertificate> target_cert; + net::CertIssuerSourceStatic intermediate_cert_issuer_source; + for (size_t i = 0; i < certs.size(); ++i) { + scoped_refptr<net::ParsedCertificate> cert( + net::ParsedCertificate::CreateFromCertificateData( + reinterpret_cast<const uint8_t*>(certs[i].data()), certs[i].size(), net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, - GetCertParsingOptions(), &input_chain)) { + GetCertParsingOptions())); + if (!cert) return false; - } + + if (i == 0) + target_cert = std::move(cert); + else + intermediate_cert_issuer_source.AddCert(std::move(cert)); } // Use a signature policy compatible with Cast's PKI. auto signature_policy = CreateCastSignaturePolicy(); - // Do RFC 5280 compatible certificate verification using the two Cast - // trust anchors and Cast signature policy. - if (!net::VerifyCertificateChain(input_chain, CastTrustStore::Get(), - signature_policy.get(), - ConvertExplodedTime(time), nullptr)) { + // Do path building and RFC 5280 compatible certificate verification using the + // two Cast trust anchors and Cast signature policy. + net::CertPathBuilder::Result result; + net::CertPathBuilder path_builder(target_cert.get(), &CastTrustStore::Get(), + signature_policy.get(), + ConvertExplodedTime(time), &result); + path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); + net::CompletionStatus rv = path_builder.Run(base::Closure()); + DCHECK_EQ(rv, net::CompletionStatus::SYNC); + if (!result.is_success()) return false; - } // Check properties of the leaf certificate (key usage, policy), and construct // a CertVerificationContext that uses its public key. - return CheckTargetCertificate(input_chain[0].get(), context, policy); + return CheckTargetCertificate(target_cert.get(), context, policy); } std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest(
diff --git a/components/cast_certificate/cast_cert_validator.h b/components/cast_certificate/cast_cert_validator.h index 1c335ae..23378cb 100644 --- a/components/cast_certificate/cast_cert_validator.h +++ b/components/cast_certificate/cast_cert_validator.h
@@ -54,9 +54,9 @@ // Inputs: // // * |certs| is a chain of DER-encoded certificates: -// * |certs[0]| is the target certificate (i.e. the device certificate) -// * |certs[i]| is the certificate that issued certs[i-1] -// * |certs.back()| must be signed by a trust anchor +// * |certs[0]| is the target certificate (i.e. the device certificate). +// * |certs[1..n-1]| are intermediates certificates to use in path building. +// Their ordering does not matter. // // * |time| is the UTC time to use for determining if the certificate // is expired.
diff --git a/components/certificate_transparency.gypi b/components/certificate_transparency.gypi index 00a6e96..cfdfe4b 100644 --- a/components/certificate_transparency.gypi +++ b/components/certificate_transparency.gypi
@@ -13,6 +13,7 @@ ], 'dependencies': [ '../base/base.gyp:base', + '../components/components.gyp:base32', '../components/components.gyp:safe_json', '../components/components.gyp:url_matcher', '../components/prefs/prefs.gyp:prefs', @@ -23,6 +24,8 @@ 'sources': [ 'certificate_transparency/ct_policy_manager.cc', 'certificate_transparency/ct_policy_manager.h', + 'certificate_transparency/log_dns_client.h', + 'certificate_transparency/log_dns_client.cc', 'certificate_transparency/log_proof_fetcher.h', 'certificate_transparency/log_proof_fetcher.cc', 'certificate_transparency/pref_names.cc',
diff --git a/components/certificate_transparency/BUILD.gn b/components/certificate_transparency/BUILD.gn index 15cb99f..3bba1a1 100644 --- a/components/certificate_transparency/BUILD.gn +++ b/components/certificate_transparency/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "ct_policy_manager.cc", "ct_policy_manager.h", + "log_dns_client.cc", + "log_dns_client.h", "log_proof_fetcher.cc", "log_proof_fetcher.h", "pref_names.cc", @@ -18,6 +20,7 @@ deps = [ "//base", + "//components/base32", "//components/prefs", "//components/safe_json", "//components/url_formatter", @@ -31,6 +34,7 @@ testonly = true sources = [ "ct_policy_manager_unittest.cc", + "log_dns_client_unittest.cc", "log_proof_fetcher_unittest.cc", "single_tree_tracker_unittest.cc", ] @@ -41,6 +45,7 @@ "//components/prefs:test_support", "//components/safe_json:test_support", "//net:test_support", + "//testing/gmock", "//testing/gtest", ] }
diff --git a/components/certificate_transparency/DEPS b/components/certificate_transparency/DEPS index b3d5f275..575b1501 100644 --- a/components/certificate_transparency/DEPS +++ b/components/certificate_transparency/DEPS
@@ -1,7 +1,9 @@ include_rules = [ + "+components/base32", "+components/prefs", "+components/safe_json", "+components/url_formatter", "+components/url_matcher", + "+crypto", "+net", ]
diff --git a/components/certificate_transparency/log_dns_client.cc b/components/certificate_transparency/log_dns_client.cc new file mode 100644 index 0000000..77da9f8 --- /dev/null +++ b/components/certificate_transparency/log_dns_client.cc
@@ -0,0 +1,294 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/certificate_transparency/log_dns_client.h" + +#include <sstream> + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "components/base32/base32.h" +#include "crypto/sha2.h" +#include "net/base/net_errors.h" +#include "net/cert/merkle_audit_proof.h" +#include "net/dns/dns_client.h" +#include "net/dns/dns_protocol.h" +#include "net/dns/dns_response.h" +#include "net/dns/dns_transaction.h" +#include "net/dns/record_parsed.h" +#include "net/dns/record_rdata.h" + +namespace certificate_transparency { + +namespace { + +bool ParseTxtResponse(const net::DnsResponse& response, std::string* txt) { + DCHECK(txt); + + net::DnsRecordParser parser = response.Parser(); + // We don't care about the creation time, since we're going to throw + // |parsed_record| away as soon as we've extracted the payload, so provide + // the "null" time. + auto parsed_record = net::RecordParsed::CreateFrom(&parser, base::Time()); + if (parsed_record == nullptr) + return false; + + auto txt_record = parsed_record->rdata<net::TxtRecordRdata>(); + if (txt_record == nullptr) + return false; + + *txt = base::JoinString(txt_record->texts(), ""); + return true; +} + +bool ParseLeafIndex(const net::DnsResponse& response, uint64_t* index) { + DCHECK(index); + + std::string index_str; + if (!ParseTxtResponse(response, &index_str)) + return false; + + return base::StringToUint64(index_str, index); +} + +bool ParseAuditPath(const net::DnsResponse& response, + net::ct::MerkleAuditProof* proof) { + DCHECK(proof); + + std::string audit_path; + if (!ParseTxtResponse(response, &audit_path)) + return false; + // If empty or not a multiple of the node size, it is considered invalid. + // It's important to consider empty audit paths as invalid, as otherwise an + // infinite loop could occur if the server consistently returned empty + // responses. + if (audit_path.empty() || audit_path.size() % crypto::kSHA256Length != 0) + return false; + + for (size_t i = 0; i < audit_path.size(); i += crypto::kSHA256Length) { + proof->nodes.push_back(audit_path.substr(i, crypto::kSHA256Length)); + } + + return true; +} + +} // namespace + +LogDnsClient::LogDnsClient(std::unique_ptr<net::DnsClient> dns_client, + const net::BoundNetLog& net_log) + : dns_client_(std::move(dns_client)), + net_log_(net_log), + weak_ptr_factory_(this) { + CHECK(dns_client_); +} + +LogDnsClient::~LogDnsClient() {} + +void LogDnsClient::QueryLeafIndex(base::StringPiece domain_for_log, + base::StringPiece leaf_hash, + const LeafIndexCallback& callback) { + if (domain_for_log.empty() || leaf_hash.size() != crypto::kSHA256Length) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, 0)); + return; + } + + std::string encoded_leaf_hash = + base32::Base32Encode(leaf_hash, base32::Base32EncodePolicy::OMIT_PADDING); + DCHECK_EQ(encoded_leaf_hash.size(), 52u); + + net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory(); + if (factory == nullptr) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(callback, net::Error::ERR_NAME_RESOLUTION_FAILED, 0)); + return; + } + + std::ostringstream qname; + qname << encoded_leaf_hash << ".hash." << domain_for_log << "."; + + net::DnsTransactionFactory::CallbackType transaction_callback = base::Bind( + &LogDnsClient::QueryLeafIndexComplete, weak_ptr_factory_.GetWeakPtr()); + + std::unique_ptr<net::DnsTransaction> dns_transaction = + factory->CreateTransaction(qname.str(), net::dns_protocol::kTypeTXT, + transaction_callback, net_log_); + + dns_transaction->Start(); + leaf_index_queries_.push_back({std::move(dns_transaction), callback}); +} + +// The performance of this could be improved by sending all of the expected +// queries up front. Each response can contain a maximum of 7 audit path nodes, +// so for an audit proof of size 20, it could send 3 queries (for nodes 0-6, +// 7-13 and 14-19) immediately. Currently, it sends only the first and then, +// based on the number of nodes received, sends the next query. The complexity +// of the code would increase though, as it would need to detect gaps in the +// audit proof caused by the server not responding with the anticipated number +// of nodes. Ownership of the proof would need to change, as it would be shared +// between simultaneous DNS transactions. +void LogDnsClient::QueryAuditProof(base::StringPiece domain_for_log, + uint64_t leaf_index, + uint64_t tree_size, + const AuditProofCallback& callback) { + if (domain_for_log.empty() || leaf_index >= tree_size) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(callback, net::Error::ERR_INVALID_ARGUMENT, nullptr)); + return; + } + + std::unique_ptr<net::ct::MerkleAuditProof> proof( + new net::ct::MerkleAuditProof); + proof->leaf_index = leaf_index; + // TODO(robpercival): Once a "tree_size" field is added to MerkleAuditProof, + // pass |tree_size| to QueryAuditProofNodes using that. + + // Query for the first batch of audit proof nodes (i.e. starting from 0). + QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, 0, + callback); +} + +void LogDnsClient::QueryLeafIndexComplete(net::DnsTransaction* transaction, + int net_error, + const net::DnsResponse* response) { + auto query_iterator = + std::find_if(leaf_index_queries_.begin(), leaf_index_queries_.end(), + [transaction](const Query<LeafIndexCallback>& query) { + return query.transaction.get() == transaction; + }); + if (query_iterator == leaf_index_queries_.end()) { + NOTREACHED(); + return; + } + const Query<LeafIndexCallback> query = std::move(*query_iterator); + leaf_index_queries_.erase(query_iterator); + + // If we've received no response but no net::error either (shouldn't happen), + // report the response as invalid. + if (response == nullptr && net_error == net::OK) { + net_error = net::ERR_INVALID_RESPONSE; + } + + if (net_error != net::OK) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(query.callback, net_error, 0)); + return; + } + + uint64_t leaf_index; + if (!ParseLeafIndex(*response, &leaf_index)) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(query.callback, net::ERR_DNS_MALFORMED_RESPONSE, 0)); + return; + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(query.callback, net::OK, leaf_index)); +} + +void LogDnsClient::QueryAuditProofNodes( + std::unique_ptr<net::ct::MerkleAuditProof> proof, + base::StringPiece domain_for_log, + uint64_t tree_size, + uint64_t node_index, + const AuditProofCallback& callback) { + // Preconditions that should be guaranteed internally by this class. + DCHECK(proof); + DCHECK(!domain_for_log.empty()); + DCHECK_LT(proof->leaf_index, tree_size); + DCHECK_LT(node_index, + net::ct::CalculateAuditPathLength(proof->leaf_index, tree_size)); + + net::DnsTransactionFactory* factory = dns_client_->GetTransactionFactory(); + if (factory == nullptr) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(callback, net::Error::ERR_NAME_RESOLUTION_FAILED, nullptr)); + return; + } + + std::ostringstream qname; + qname << node_index << "." << proof->leaf_index << "." << tree_size + << ".tree." << domain_for_log << "."; + + net::DnsTransactionFactory::CallbackType transaction_callback = + base::Bind(&LogDnsClient::QueryAuditProofNodesComplete, + weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(proof)), + domain_for_log, tree_size); + + std::unique_ptr<net::DnsTransaction> dns_transaction = + factory->CreateTransaction(qname.str(), net::dns_protocol::kTypeTXT, + transaction_callback, net_log_); + dns_transaction->Start(); + audit_proof_queries_.push_back({std::move(dns_transaction), callback}); +} + +void LogDnsClient::QueryAuditProofNodesComplete( + std::unique_ptr<net::ct::MerkleAuditProof> proof, + base::StringPiece domain_for_log, + uint64_t tree_size, + net::DnsTransaction* transaction, + int net_error, + const net::DnsResponse* response) { + // Preconditions that should be guaranteed internally by this class. + DCHECK(proof); + DCHECK(!domain_for_log.empty()); + + auto query_iterator = + std::find_if(audit_proof_queries_.begin(), audit_proof_queries_.end(), + [transaction](const Query<AuditProofCallback>& query) { + return query.transaction.get() == transaction; + }); + + if (query_iterator == audit_proof_queries_.end()) { + NOTREACHED(); + return; + } + const Query<AuditProofCallback> query = std::move(*query_iterator); + audit_proof_queries_.erase(query_iterator); + + // If we've received no response but no net::error either (shouldn't happen), + // report the response as invalid. + if (response == nullptr && net_error == net::OK) { + net_error = net::ERR_INVALID_RESPONSE; + } + + if (net_error != net::OK) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(query.callback, net_error, nullptr)); + return; + } + + const uint64_t audit_path_length = + net::ct::CalculateAuditPathLength(proof->leaf_index, tree_size); + proof->nodes.reserve(audit_path_length); + + if (!ParseAuditPath(*response, proof.get())) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(query.callback, net::ERR_DNS_MALFORMED_RESPONSE, nullptr)); + return; + } + + const uint64_t audit_path_nodes_received = proof->nodes.size(); + if (audit_path_nodes_received < audit_path_length) { + QueryAuditProofNodes(std::move(proof), domain_for_log, tree_size, + audit_path_nodes_received, query.callback); + return; + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(query.callback, net::OK, base::Passed(std::move(proof)))); +} + +} // namespace certificate_transparency
diff --git a/components/certificate_transparency/log_dns_client.h b/components/certificate_transparency/log_dns_client.h new file mode 100644 index 0000000..e00cefd --- /dev/null +++ b/components/certificate_transparency/log_dns_client.h
@@ -0,0 +1,120 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_LOG_DNS_CLIENT_H_ +#define COMPONENTS_CERTIFICATE_TRANSPARENCY_LOG_DNS_CLIENT_H_ + +#include <stdint.h> + +#include <list> +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/strings/string_piece.h" +#include "net/log/net_log.h" + +namespace net { +class DnsClient; +class DnsResponse; +class DnsTransaction; +namespace ct { +struct MerkleAuditProof; +} // namespace ct +} // namespace net + +namespace certificate_transparency { + +// Queries Certificate Transparency (CT) log servers via DNS. +// All queries are performed asynchronously. +// For more information, see +// https://github.com/google/certificate-transparency-rfcs/blob/master/dns/draft-ct-over-dns.md. +class LogDnsClient { + public: + // Invoked when a leaf index query completes. + // If an error occured, |net_error| will be a net::Error code, otherwise it + // will be net::OK and |leaf_index| will be the leaf index that was received. + using LeafIndexCallback = + base::Callback<void(int net_error, uint64_t leaf_index)>; + // Invoked when an audit proof query completes. + // If an error occurred, |net_error| will be a net::Error code, otherwise it + // will be net::OK and |proof| will be the audit proof that was received. + // The log ID of |proof| will not be set, as that is not known by this class, + // but the leaf index will be set. + using AuditProofCallback = + base::Callback<void(int net_error, + std::unique_ptr<net::ct::MerkleAuditProof> proof)>; + + // Creates a log client that will take ownership of |dns_client| and use it + // to perform DNS queries. Queries will be logged to |net_log|. + LogDnsClient(std::unique_ptr<net::DnsClient> dns_client, + const net::BoundNetLog& net_log); + virtual ~LogDnsClient(); + + // Queries a CT log to discover the index of the leaf with |leaf_hash|. + // The log is identified by |domain_for_log|, which is the DNS name used as a + // suffix for all queries. + // The |leaf_hash| is the SHA-256 hash of a Merkle tree leaf in that log. + // The |callback| is invoked when the query is complete, or an error occurs. + void QueryLeafIndex(base::StringPiece domain_for_log, + base::StringPiece leaf_hash, + const LeafIndexCallback& callback); + + // Queries a CT log to retrieve an audit proof for the leaf at |leaf_index|. + // The size of the CT log tree must be provided in |tree_size|. + // The log is identified by |domain_for_log|, which is the DNS name used as a + // suffix for all queries. + // The |callback| is invoked when the query is complete, or an error occurs. + void QueryAuditProof(base::StringPiece domain_for_log, + uint64_t leaf_index, + uint64_t tree_size, + const AuditProofCallback& callback); + + private: + void QueryLeafIndexComplete(net::DnsTransaction* transaction, + int neterror, + const net::DnsResponse* response); + + // Queries a CT log to retrieve part of an audit |proof|. The |node_index| + // indicates which node of the audit proof/ should be requested. The CT log + // may return up to 7 nodes, starting from |node_index| (this is the maximum + // that will fit in a DNS UDP packet). The nodes will be appended to + // |proof->nodes|. + void QueryAuditProofNodes(std::unique_ptr<net::ct::MerkleAuditProof> proof, + base::StringPiece domain_for_log, + uint64_t tree_size, + uint64_t node_index, + const AuditProofCallback& callback); + + void QueryAuditProofNodesComplete( + std::unique_ptr<net::ct::MerkleAuditProof> proof, + base::StringPiece domain_for_log, + uint64_t tree_size, + net::DnsTransaction* transaction, + int net_error, + const net::DnsResponse* response); + + // A DNS query that is in flight. + template <typename CallbackType> + struct Query { + std::unique_ptr<net::DnsTransaction> transaction; + CallbackType callback; + }; + + // Used to perform DNS queries. + std::unique_ptr<net::DnsClient> dns_client_; + // Passed to the DNS client for logging. + net::BoundNetLog net_log_; + // Leaf index queries that haven't completed yet. + std::list<Query<LeafIndexCallback>> leaf_index_queries_; + // Audit proof queries that haven't completed yet. + std::list<Query<AuditProofCallback>> audit_proof_queries_; + // Creates weak_ptrs to this, for callback purposes. + base::WeakPtrFactory<LogDnsClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(LogDnsClient); +}; + +} // namespace certificate_transparency +#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_LOG_DNS_CLIENT_H_
diff --git a/components/certificate_transparency/log_dns_client_unittest.cc b/components/certificate_transparency/log_dns_client_unittest.cc new file mode 100644 index 0000000..d8f11da --- /dev/null +++ b/components/certificate_transparency/log_dns_client_unittest.cc
@@ -0,0 +1,746 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/certificate_transparency/log_dns_client.h" + +#include <algorithm> +#include <numeric> +#include <utility> +#include <vector> + +#include "base/big_endian.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/sys_byteorder.h" +#include "base/test/test_timeouts.h" +#include "crypto/sha2.h" +#include "net/base/net_errors.h" +#include "net/cert/merkle_audit_proof.h" +#include "net/cert/merkle_tree_leaf.h" +#include "net/cert/signed_certificate_timestamp.h" +#include "net/dns/dns_client.h" +#include "net/dns/dns_config_service.h" +#include "net/dns/dns_protocol.h" +#include "net/log/net_log.h" +#include "net/socket/socket_test_util.h" +#include "net/test/gtest_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace certificate_transparency { +namespace { + +using ::testing::IsNull; +using ::testing::NotNull; +using net::test::IsError; +using net::test::IsOk; + +constexpr char kLeafHash[] = + "\x1f\x25\xe1\xca\xba\x4f\xf9\xb8\x27\x24\x83\x0f\xca\x60\xe4\xc2\xbe\xa8" + "\xc3\xa9\x44\x1c\x27\xb0\xb4\x3e\x6a\x96\x94\xc7\xb8\x04"; + +// Always return min, to simplify testing. +// This should result in the DNS query ID always being 0. +int FakeRandInt(int min, int max) { + return min; +} + +std::vector<char> CreateDnsTxtRequest(base::StringPiece qname) { + std::string encoded_qname; + EXPECT_TRUE(net::DNSDomainFromDot(qname, &encoded_qname)); + + const size_t query_section_size = encoded_qname.size() + 4; + + std::vector<char> request(sizeof(net::dns_protocol::Header) + + query_section_size); + base::BigEndianWriter writer(request.data(), request.size()); + + // Header + net::dns_protocol::Header header = {}; + header.flags = base::HostToNet16(net::dns_protocol::kFlagRD); + header.qdcount = base::HostToNet16(1); + EXPECT_TRUE(writer.WriteBytes(&header, sizeof(header))); + // Query section + EXPECT_TRUE(writer.WriteBytes(encoded_qname.data(), encoded_qname.size())); + EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT)); + EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN)); + EXPECT_EQ(0, writer.remaining()); + + return request; +} + +std::vector<char> CreateDnsTxtResponse(const std::vector<char>& request, + base::StringPiece answer) { + const size_t answers_section_size = 12 + answer.size(); + constexpr uint32_t ttl = 86400; // seconds + + std::vector<char> response(request.size() + answers_section_size); + std::copy(request.begin(), request.end(), response.begin()); + // Modify the header + net::dns_protocol::Header* header = + reinterpret_cast<net::dns_protocol::Header*>(response.data()); + header->ancount = base::HostToNet16(1); + header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse); + + // Write the answer section + base::BigEndianWriter writer(response.data() + request.size(), + response.size() - request.size()); + EXPECT_TRUE(writer.WriteU8(0xc0)); // qname is a pointer + EXPECT_TRUE(writer.WriteU8( + sizeof(*header))); // address of qname (start of query section) + EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kTypeTXT)); + EXPECT_TRUE(writer.WriteU16(net::dns_protocol::kClassIN)); + EXPECT_TRUE(writer.WriteU32(ttl)); + EXPECT_TRUE(writer.WriteU16(answer.size())); + EXPECT_TRUE(writer.WriteBytes(answer.data(), answer.size())); + EXPECT_EQ(0, writer.remaining()); + + return response; +} + +std::vector<char> CreateDnsErrorResponse(const std::vector<char>& request, + uint8_t rcode) { + std::vector<char> response(request); + // Modify the header + net::dns_protocol::Header* header = + reinterpret_cast<net::dns_protocol::Header*>(response.data()); + header->ancount = base::HostToNet16(1); + header->flags |= base::HostToNet16(net::dns_protocol::kFlagResponse | rcode); + + return response; +} + +std::vector<std::string> GetSampleAuditProof(size_t length) { + std::vector<std::string> audit_proof(length); + // Makes each node of the audit proof different, so that tests are able to + // confirm that the audit proof is reconstructed in the correct order. + for (size_t i = 0; i < length; ++i) { + std::string node(crypto::kSHA256Length, '\0'); + // Each node is 32 bytes, with each byte having a different value. + for (size_t j = 0; j < crypto::kSHA256Length; ++j) { + node[j] = static_cast<char>((-127 + i + j) % 128); + } + audit_proof[i].assign(std::move(node)); + } + + return audit_proof; +} + +class MockLeafIndexCallback { + public: + MockLeafIndexCallback() : called_(false) {} + + bool called() const { return called_; } + int net_error() const { return net_error_; } + uint64_t leaf_index() const { return leaf_index_; } + + void Run(int net_error, uint64_t leaf_index) { + EXPECT_TRUE(!called_); + called_ = true; + net_error_ = net_error; + leaf_index_ = leaf_index; + run_loop_.Quit(); + } + + LogDnsClient::LeafIndexCallback AsCallback() { + return base::Bind(&MockLeafIndexCallback::Run, base::Unretained(this)); + } + + void WaitUntilRun() { run_loop_.Run(); } + + private: + bool called_; + int net_error_; + uint64_t leaf_index_; + base::RunLoop run_loop_; +}; + +class MockAuditProofCallback { + public: + MockAuditProofCallback() : called_(false) {} + + bool called() const { return called_; } + int net_error() const { return net_error_; } + const net::ct::MerkleAuditProof* proof() const { return proof_.get(); } + + void Run(int net_error, std::unique_ptr<net::ct::MerkleAuditProof> proof) { + EXPECT_TRUE(!called_); + called_ = true; + net_error_ = net_error; + proof_ = std::move(proof); + run_loop_.Quit(); + } + + LogDnsClient::AuditProofCallback AsCallback() { + return base::Bind(&MockAuditProofCallback::Run, base::Unretained(this)); + } + + void WaitUntilRun() { run_loop_.Run(); } + + private: + bool called_; + int net_error_; + std::unique_ptr<net::ct::MerkleAuditProof> proof_; + base::RunLoop run_loop_; +}; + +// A container for all of the data we need to keep alive for a mock socket. +// This is useful because Mock{Read,Write}, SequencedSocketData and +// MockClientSocketFactory all do not take ownership of or copy their arguments, +// so we have to manage the lifetime of those arguments ourselves. Wrapping all +// of that up in a single class simplifies this. +class MockSocketData { + public: + // A socket that expects one write and one read operation. + MockSocketData(const std::vector<char>& write, const std::vector<char>& read) + : expected_write_payload_(write), + expected_read_payload_(read), + expected_write_(net::SYNCHRONOUS, + expected_write_payload_.data(), + expected_write_payload_.size(), + 0), + expected_reads_{net::MockRead(net::ASYNC, + expected_read_payload_.data(), + expected_read_payload_.size(), + 1), + eof_}, + socket_data_(expected_reads_, 2, &expected_write_, 1) {} + + // A socket that expects one write and a read error. + MockSocketData(const std::vector<char>& write, int net_error) + : expected_write_payload_(write), + expected_write_(net::SYNCHRONOUS, + expected_write_payload_.data(), + expected_write_payload_.size(), + 0), + expected_reads_{net::MockRead(net::ASYNC, net_error, 1), eof_}, + socket_data_(expected_reads_, 2, &expected_write_, 1) {} + + // A socket that expects one write and no response. + explicit MockSocketData(const std::vector<char>& write) + : expected_write_payload_(write), + expected_write_(net::SYNCHRONOUS, + expected_write_payload_.data(), + expected_write_payload_.size(), + 0), + expected_reads_{net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING, 1), + eof_}, + socket_data_(expected_reads_, 2, &expected_write_, 1) {} + + void SetWriteMode(net::IoMode mode) { expected_write_.mode = mode; } + void SetReadMode(net::IoMode mode) { expected_reads_[0].mode = mode; } + + void AddToFactory(net::MockClientSocketFactory* socket_factory) { + socket_factory->AddSocketDataProvider(&socket_data_); + } + + private: + // Prevents read overruns and makes a socket timeout the default behaviour. + static const net::MockRead eof_; + + const std::vector<char> expected_write_payload_; + const std::vector<char> expected_read_payload_; + // Encapsulates the data that is expected to be written to a socket. + net::MockWrite expected_write_; + // Encapsulates the data/error that should be returned when reading from a + // socket. The expected response is followed by |eof_|, to catch further, + // unexpected read attempts. + net::MockRead expected_reads_[2]; + net::SequencedSocketData socket_data_; + + DISALLOW_COPY_AND_ASSIGN(MockSocketData); +}; + +const net::MockRead MockSocketData::eof_(net::SYNCHRONOUS, + net::ERR_IO_PENDING, + 2); + +class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { + protected: + LogDnsClientTest() { + // Use an invalid nameserver address. This prevents the tests accidentally + // sending real DNS queries. The mock sockets don't care that the address + // is invalid. + dns_config_.nameservers.push_back(net::IPEndPoint()); + // Don't attempt retransmissions - just fail. + dns_config_.attempts = 1; + // This ensures timeouts are long enough for memory tests. + dns_config_.timeout = TestTimeouts::action_timeout(); + // Simplify testing - don't require random numbers for the source port. + // This means our FakeRandInt function should only be called to get query + // IDs. + dns_config_.randomize_ports = false; + } + + void ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode) { + std::vector<char> request = CreateDnsTxtRequest(qname); + std::vector<char> response = CreateDnsErrorResponse(request, rcode); + + mock_socket_data_.emplace_back(new MockSocketData(request, response)); + mock_socket_data_.back()->SetReadMode(GetParam()); + mock_socket_data_.back()->AddToFactory(&socket_factory_); + } + + void ExpectRequestAndSocketError(base::StringPiece qname, int net_error) { + std::vector<char> request = CreateDnsTxtRequest(qname); + + mock_socket_data_.emplace_back(new MockSocketData(request, net_error)); + mock_socket_data_.back()->SetReadMode(GetParam()); + mock_socket_data_.back()->AddToFactory(&socket_factory_); + } + + void ExpectRequestAndTimeout(base::StringPiece qname) { + std::vector<char> request = CreateDnsTxtRequest(qname); + + mock_socket_data_.emplace_back(new MockSocketData(request)); + mock_socket_data_.back()->SetReadMode(GetParam()); + mock_socket_data_.back()->AddToFactory(&socket_factory_); + + // Speed up timeout tests. + dns_config_.timeout = TestTimeouts::tiny_timeout(); + } + + void ExpectLeafIndexRequestAndResponse(base::StringPiece qname, + base::StringPiece leaf_index) { + // Prepend size to leaf_index to create the query answer (rdata) + ASSERT_LE(leaf_index.size(), 0xFFul); // size must fit into a single byte + std::string answer = leaf_index.as_string(); + answer.insert(answer.begin(), static_cast<char>(leaf_index.size())); + + ExpectRequestAndResponse(qname, answer); + } + + void ExpectAuditProofRequestAndResponse( + base::StringPiece qname, + std::vector<std::string>::const_iterator audit_path_start, + std::vector<std::string>::const_iterator audit_path_end) { + // Join nodes in the audit path into a single string. + std::string proof = + std::accumulate(audit_path_start, audit_path_end, std::string()); + + // Prepend size to proof to create the query answer (rdata) + ASSERT_LE(proof.size(), 0xFFul); // size must fit into a single byte + proof.insert(proof.begin(), static_cast<char>(proof.size())); + + ExpectRequestAndResponse(qname, proof); + } + + void QueryLeafIndex(base::StringPiece log_domain, + base::StringPiece leaf_hash, + MockLeafIndexCallback* callback) { + std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient(); + LogDnsClient log_client(std::move(dns_client), net::BoundNetLog()); + + log_client.QueryLeafIndex(log_domain, leaf_hash, callback->AsCallback()); + callback->WaitUntilRun(); + } + + void QueryAuditProof(base::StringPiece log_domain, + uint64_t leaf_index, + uint64_t tree_size, + MockAuditProofCallback* callback) { + std::unique_ptr<net::DnsClient> dns_client = CreateDnsClient(); + LogDnsClient log_client(std::move(dns_client), net::BoundNetLog()); + + log_client.QueryAuditProof(log_domain, leaf_index, tree_size, + callback->AsCallback()); + callback->WaitUntilRun(); + } + + private: + std::unique_ptr<net::DnsClient> CreateDnsClient() { + std::unique_ptr<net::DnsClient> client = + net::DnsClient::CreateClientForTesting(nullptr, &socket_factory_, + base::Bind(&FakeRandInt)); + client->SetConfig(dns_config_); + return client; + } + + void ExpectRequestAndResponse(base::StringPiece qname, + base::StringPiece answer) { + std::vector<char> request = CreateDnsTxtRequest(qname); + std::vector<char> response = CreateDnsTxtResponse(request, answer); + + mock_socket_data_.emplace_back(new MockSocketData(request, response)); + mock_socket_data_.back()->SetReadMode(GetParam()); + mock_socket_data_.back()->AddToFactory(&socket_factory_); + } + + net::DnsConfig dns_config_; + base::MessageLoopForIO message_loop_; + std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; + net::MockClientSocketFactory socket_factory_; +}; + +TEST_P(LogDnsClientTest, QueryLeafIndex) { + ExpectLeafIndexRequestAndResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + "123456"); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsOk()); + EXPECT_THAT(callback.leaf_index(), 123456); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsThatLogDomainDoesNotExist) { + ExpectRequestAndErrorResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + net::dns_protocol::kRcodeNXDOMAIN); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerFailure) { + ExpectRequestAndErrorResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + net::dns_protocol::kRcodeSERVFAIL); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsServerRefusal) { + ExpectRequestAndErrorResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + net::dns_protocol::kRcodeREFUSED); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, + QueryLeafIndexReportsMalformedResponseIfLeafIndexIsNotNumeric) { + ExpectLeafIndexRequestAndResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + "foo"); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, + QueryLeafIndexReportsMalformedResponseIfLeafIndexIsFloatingPoint) { + ExpectLeafIndexRequestAndResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + "123456.0"); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, + QueryLeafIndexReportsMalformedResponseIfLeafIndexIsEmpty) { + ExpectLeafIndexRequestAndResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", ""); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, + QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericPrefix) { + ExpectLeafIndexRequestAndResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + "foo123456"); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, + QueryLeafIndexReportsMalformedResponseIfLeafIndexHasNonNumericSuffix) { + ExpectLeafIndexRequestAndResponse( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + "123456foo"); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsEmpty) { + MockLeafIndexCallback callback; + QueryLeafIndex("", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLogDomainIsNull) { + MockLeafIndexCallback callback; + QueryLeafIndex(nullptr, kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsInvalid) { + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", "foo", &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsEmpty) { + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", "", &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsInvalidArgIfLeafHashIsNull) { + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", nullptr, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsSocketError) { + ExpectRequestAndSocketError( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", + net::ERR_CONNECTION_REFUSED); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryLeafIndexReportsTimeout) { + ExpectRequestAndTimeout( + "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test."); + + MockLeafIndexCallback callback; + QueryLeafIndex("ct.test", kLeafHash, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); + EXPECT_THAT(callback.leaf_index(), 0); +} + +TEST_P(LogDnsClientTest, QueryAuditProof) { + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); + + // It should require 3 queries to collect the entire audit proof, as there is + // only space for 7 nodes per UDP packet. + ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", + audit_proof.begin(), + audit_proof.begin() + 7); + ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.", + audit_proof.begin() + 7, + audit_proof.begin() + 14); + ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.", + audit_proof.begin() + 14, + audit_proof.end()); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsOk()); + ASSERT_THAT(callback.proof(), NotNull()); + EXPECT_THAT(callback.proof()->leaf_index, 123456); + // EXPECT_THAT(callback.proof()->tree_size, 999999); + EXPECT_THAT(callback.proof()->nodes, audit_proof); +} + +TEST_P(LogDnsClientTest, QueryAuditProofHandlesResponsesWithShortAuditPaths) { + const std::vector<std::string> audit_proof = GetSampleAuditProof(20); + + // Make some of the responses contain fewer proof nodes than they can hold. + ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", + audit_proof.begin(), + audit_proof.begin() + 1); + ExpectAuditProofRequestAndResponse("1.123456.999999.tree.ct.test.", + audit_proof.begin() + 1, + audit_proof.begin() + 3); + ExpectAuditProofRequestAndResponse("3.123456.999999.tree.ct.test.", + audit_proof.begin() + 3, + audit_proof.begin() + 6); + ExpectAuditProofRequestAndResponse("6.123456.999999.tree.ct.test.", + audit_proof.begin() + 6, + audit_proof.begin() + 10); + ExpectAuditProofRequestAndResponse("10.123456.999999.tree.ct.test.", + audit_proof.begin() + 10, + audit_proof.begin() + 13); + ExpectAuditProofRequestAndResponse("13.123456.999999.tree.ct.test.", + audit_proof.begin() + 13, + audit_proof.end()); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsOk()); + ASSERT_THAT(callback.proof(), NotNull()); + EXPECT_THAT(callback.proof()->leaf_index, 123456); + // EXPECT_THAT(callback.proof()->tree_size, 999999); + EXPECT_THAT(callback.proof()->nodes, audit_proof); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsThatLogDomainDoesNotExist) { + ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", + net::dns_protocol::kRcodeNXDOMAIN); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_NAME_NOT_RESOLVED)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsServerFailure) { + ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", + net::dns_protocol::kRcodeSERVFAIL); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsServerRefusal) { + ExpectRequestAndErrorResponse("0.123456.999999.tree.ct.test.", + net::dns_protocol::kRcodeREFUSED); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_SERVER_FAILED)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, + QueryAuditProofReportsResponseMalformedIfNodeTooShort) { + // node is shorter than a SHA-256 hash (31 vs 32 bytes) + const std::vector<std::string> audit_proof(1, std::string(31, 'a')); + + ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", + audit_proof.begin(), audit_proof.end()); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfNodeTooLong) { + // node is longer than a SHA-256 hash (33 vs 32 bytes) + const std::vector<std::string> audit_proof(1, std::string(33, 'a')); + + ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", + audit_proof.begin(), audit_proof.end()); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsResponseMalformedIfEmpty) { + const std::vector<std::string> audit_proof; + + ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.", + audit_proof.begin(), audit_proof.end()); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_MALFORMED_RESPONSE)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsEmpty) { + MockAuditProofCallback callback; + QueryAuditProof("", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsInvalidArgIfLogDomainIsNull) { + MockAuditProofCallback callback; + QueryAuditProof(nullptr, 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, + QueryAuditProofReportsInvalidArgIfLeafIndexEqualToTreeSize) { + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 123456, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, + QueryAuditProofReportsInvalidArgIfLeafIndexGreaterThanTreeSize) { + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 999999, 123456, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_INVALID_ARGUMENT)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsSocketError) { + ExpectRequestAndSocketError("0.123456.999999.tree.ct.test.", + net::ERR_CONNECTION_REFUSED); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_CONNECTION_REFUSED)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +TEST_P(LogDnsClientTest, QueryAuditProofReportsTimeout) { + ExpectRequestAndTimeout("0.123456.999999.tree.ct.test."); + + MockAuditProofCallback callback; + QueryAuditProof("ct.test", 123456, 999999, &callback); + ASSERT_TRUE(callback.called()); + EXPECT_THAT(callback.net_error(), IsError(net::ERR_DNS_TIMED_OUT)); + EXPECT_THAT(callback.proof(), IsNull()); +} + +INSTANTIATE_TEST_CASE_P(ReadMode, + LogDnsClientTest, + ::testing::Values(net::IoMode::ASYNC, + net::IoMode::SYNCHRONOUS)); + +} // namespace +} // namespace certificate_transparency
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 1830d850..50759fe 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -116,6 +116,7 @@ ], 'certificate_transparency_unittest_sources': [ 'certificate_transparency/ct_policy_manager_unittest.cc', + 'certificate_transparency/log_dns_client_unittest.cc', 'certificate_transparency/log_proof_fetcher_unittest.cc', 'certificate_transparency/single_tree_tracker_unittest.cc', ], @@ -630,7 +631,6 @@ 'proximity_auth/ble/bluetooth_low_energy_connection_unittest.cc', 'proximity_auth/ble/bluetooth_low_energy_device_whitelist_unittest.cc', 'proximity_auth/ble/bluetooth_low_energy_weave_packet_generator_unittest.cc', - 'proximity_auth/ble/bluetooth_low_energy_weave_packet_receiver_unittest.cc', 'proximity_auth/bluetooth_connection_finder_unittest.cc', 'proximity_auth/bluetooth_connection_unittest.cc', 'proximity_auth/bluetooth_throttler_impl_unittest.cc', @@ -708,7 +708,6 @@ 'safe_browsing_db/v4_database_unittest.cc', 'safe_browsing_db/v4_get_hash_protocol_manager_unittest.cc', 'safe_browsing_db/v4_protocol_manager_util_unittest.cc', - 'safe_browsing_db/v4_store_unittest.cc', 'safe_browsing_db/v4_update_protocol_manager_unittest.cc', ], 'safe_json_unittest_sources': [ @@ -716,12 +715,14 @@ 'safe_json/testing_json_parser_unittest.cc', ], 'scheduler_unittest_sources': [ + 'scheduler/base/queueing_time_estimator_unittest.cc', 'scheduler/base/task_queue_manager_delegate_for_test.cc', 'scheduler/base/task_queue_manager_delegate_for_test.h', 'scheduler/base/task_queue_manager_unittest.cc', 'scheduler/base/task_queue_selector_unittest.cc', - 'scheduler/base/test_always_fail_time_source.cc', - 'scheduler/base/test_always_fail_time_source.h', + 'scheduler/base/test_count_uses_time_source.cc', + 'scheduler/base/test_count_uses_time_source.h', + 'scheduler/base/test_task_time_tracker.h', 'scheduler/base/test_time_source.cc', 'scheduler/base/test_time_source.h', 'scheduler/base/time_domain_unittest.cc', @@ -883,8 +884,6 @@ 'tracing/browser/trace_config_file_unittest.cc', 'tracing/common/graphics_memory_dump_provider_android_unittest.cc', 'tracing/common/process_metrics_memory_dump_provider_unittest.cc', - 'tracing/core/trace_ring_buffer_unittest.cc', - 'tracing/core/scattered_stream_writer_unittest.cc', ], 'translate_unittest_sources': [ 'translate/core/browser/language_state_unittest.cc', @@ -1881,6 +1880,7 @@ 'scheduler/base/task_queue_manager_delegate_for_test.cc', 'scheduler/base/task_queue_manager_delegate_for_test.h', 'scheduler/base/task_queue_manager_perftest.cc', + 'scheduler/base/test_task_time_tracker.h', 'visitedlink/test/visitedlink_perftest.cc', ], 'conditions': [
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc index 6b56ae6..3dbb4f5 100644 --- a/components/content_settings/core/browser/host_content_settings_map.cc +++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -497,6 +497,73 @@ } } +void HostContentSettingsMap::MigrateDomainScopedSettings() { + const ContentSettingsType kDomainScopedTypes[] = { + CONTENT_SETTINGS_TYPE_COOKIES, + CONTENT_SETTINGS_TYPE_IMAGES, + CONTENT_SETTINGS_TYPE_PLUGINS, + CONTENT_SETTINGS_TYPE_JAVASCRIPT, + CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, + CONTENT_SETTINGS_TYPE_POPUPS}; + for (const ContentSettingsType& type : kDomainScopedTypes) { + if (!content_settings::ContentSettingsRegistry::GetInstance()->Get(type)) + continue; + ContentSettingsForOneType settings; + GetSettingsForOneType(type, std::string(), &settings); + + for (const ContentSettingPatternSource& setting_entry : settings) { + // Migrate user preference settings only. + if (setting_entry.source != "preference") + continue; + // Migrate ALLOW settings only. + if (setting_entry.setting != CONTENT_SETTING_ALLOW) + continue; + // Skip default settings. + if (setting_entry.primary_pattern == ContentSettingsPattern::Wildcard()) + continue; + + if (setting_entry.secondary_pattern != + ContentSettingsPattern::Wildcard()) { + NOTREACHED(); + continue; + } + + ContentSettingsPattern origin_pattern; + if (!ContentSettingsPattern::MigrateFromDomainToOrigin( + setting_entry.primary_pattern, &origin_pattern)) { + continue; + } + + if (!origin_pattern.IsValid()) + continue; + + GURL origin(origin_pattern.ToString()); + DCHECK(origin.is_valid()); + + // Ensure that the current resolved content setting for this origin is + // allowed. Otherwise we may be overriding some narrower setting which is + // set to block. + ContentSetting origin_setting = + GetContentSetting(origin, origin, type, std::string()); + + // Remove the domain scoped pattern. If |origin_setting| is not + // CONTENT_SETTING_ALLOW it implies there is some narrower pattern in + // effect, so it's still safe to remove the domain-scoped pattern. + SetContentSettingCustomScope(setting_entry.primary_pattern, + setting_entry.secondary_pattern, type, + std::string(), CONTENT_SETTING_DEFAULT); + + // If the current resolved content setting is allowed it's safe to set the + // origin-scoped pattern. + if (origin_setting == CONTENT_SETTING_ALLOW) + SetContentSettingCustomScope( + ContentSettingsPattern::FromURLNoWildcard(origin), + ContentSettingsPattern::Wildcard(), type, std::string(), + CONTENT_SETTING_ALLOW); + } + } +} + void HostContentSettingsMap::RecordNumberOfExceptions() { for (const content_settings::WebsiteSettingsInfo* info : *content_settings::WebsiteSettingsRegistry::GetInstance()) {
diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h index ec33722e..9115c2836 100644 --- a/components/content_settings/core/browser/host_content_settings_map.h +++ b/components/content_settings/core/browser/host_content_settings_map.h
@@ -280,6 +280,7 @@ private: friend class base::RefCountedThreadSafe<HostContentSettingsMap>; + friend class HostContentSettingsMapTest_MigrateDomainScopedSettings_Test; friend class HostContentSettingsMapTest_MigrateKeygenSettings_Test; friend class content_settings::TestUtils; @@ -311,6 +312,14 @@ // leave in some code to remove old-format settings for a long time. void MigrateKeygenSettings(); + // Migrate old domain scoped ALLOW settings to be origin scoped for + // ContentSettingsTypes which are domain scoped. Only narrow down ALLOW + // domain settings to origins so that this will not cause privacy/security + // issues. + // TODO(lshang): https://crbug.com/621398 Remove this when clients have + // migrated (~M56). + void MigrateDomainScopedSettings(); + // Collect UMA data about the number of exceptions. void RecordNumberOfExceptions();
diff --git a/components/content_settings/core/common/content_settings_pattern.cc b/components/content_settings/core/common/content_settings_pattern.cc index 74a9ffa..d6dd272 100644 --- a/components/content_settings/core/common/content_settings_pattern.cc +++ b/components/content_settings/core/common/content_settings_pattern.cc
@@ -439,6 +439,60 @@ } // static +bool ContentSettingsPattern::MigrateFromDomainToOrigin( + const ContentSettingsPattern& domain_pattern, + ContentSettingsPattern* origin_pattern) { + DCHECK(origin_pattern); + + // Generated patterns with ::FromURL (which we want to migrate) must either + // have a scheme wildcard or be https. + if (domain_pattern.parts_.scheme != url::kHttpsScheme && + !domain_pattern.parts_.is_scheme_wildcard) { + return false; + } + + // Generated patterns using ::FromURL with the HTTPs scheme can not have a + // port wildcard. + if (domain_pattern.parts_.is_port_wildcard && + domain_pattern.parts_.scheme == url::kHttpsScheme) { + return false; + } + + // Patterns generated with ::FromURL will always have a domain wildcard. Those + // generated with ::FromURLNoWildcard don't. + if (!domain_pattern.parts_.has_domain_wildcard) + return false; + + // Generated patterns with ::FromURL will always have a host. + if (domain_pattern.parts_.host.empty()) + return false; + + std::unique_ptr<ContentSettingsPattern::BuilderInterface> builder( + ContentSettingsPattern::CreateBuilder(false)); + + if (domain_pattern.parts_.is_scheme_wildcard) + builder->WithScheme(url::kHttpScheme); + else + builder->WithScheme(domain_pattern.parts_.scheme); + + builder->WithHost(domain_pattern.parts_.host); + + if (domain_pattern.parts_.is_port_wildcard) { + if (domain_pattern.parts_.scheme == url::kHttpsScheme) { + builder->WithPort(GetDefaultPort(url::kHttpsScheme)); + } else { + builder->WithPort(GetDefaultPort(url::kHttpScheme)); + } + } else { + builder->WithPort(domain_pattern.parts_.port); + } + + *origin_pattern = builder->Build(); + + return true; +} + +// static void ContentSettingsPattern::SetNonWildcardDomainNonPortScheme( const char* scheme) { DCHECK(scheme);
diff --git a/components/content_settings/core/common/content_settings_pattern.h b/components/content_settings/core/common/content_settings_pattern.h index f85c648b..b5b8352 100644 --- a/components/content_settings/core/common/content_settings_pattern.h +++ b/components/content_settings/core/common/content_settings_pattern.h
@@ -129,6 +129,7 @@ // Returns a pattern that matches the scheme and host of this URL, as well as // all subdomains and ports. + // TODO(lshang): Remove this when crbug.com/604612 is done. static ContentSettingsPattern FromURL(const GURL& url); // Returns a pattern that matches exactly this URL. @@ -145,6 +146,13 @@ // - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip) static ContentSettingsPattern FromString(const std::string& pattern_spec); + // Migrate domain scoped settings generated using FromURL() to be origin + // scoped. Return false if domain_pattern is not generated using FromURL(). + // TODO(lshang): Remove this when migration is done. https://crbug.com/604612 + static bool MigrateFromDomainToOrigin( + const ContentSettingsPattern& domain_pattern, + ContentSettingsPattern* origin_pattern); + // Sets the scheme that doesn't support domain wildcard and port. // Needs to be called by the embedder before using ContentSettingsPattern. // |scheme| can't be NULL, and the pointed string must remain alive until the
diff --git a/components/content_settings/core/common/content_settings_pattern_unittest.cc b/components/content_settings/core/common/content_settings_pattern_unittest.cc index 74e6019..38125c4 100644 --- a/components/content_settings/core/common/content_settings_pattern_unittest.cc +++ b/components/content_settings/core/common/content_settings_pattern_unittest.cc
@@ -720,3 +720,92 @@ EXPECT_STREQ("", Pattern("*\xC4\x87ira.com").ToString().c_str()); EXPECT_STREQ("", Pattern("\xC4\x87ira.*").ToString().c_str()); } + +TEST(ContentSettingsPatternTest, MigrateFromDomainToOrigin) { + ContentSettingsPattern origin_pattern; + // Http scheme patterns. + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("http://[*.]example.com"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("http://[*.]example.com:80"), + &origin_pattern)); + + // Https patterns with port wildcard. + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("https://www.google.com"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("https://[*.]google.com"), + &origin_pattern)); + + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("www.google.com"), &origin_pattern)); + + // Patterns with no domain wildcard. + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("*://www.google.com:8080"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("www.example.com:8080"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("www.google.com/*"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("google"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("https://www.google.com:443"), + &origin_pattern)); + + // Patterns with empty host. + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("*"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("[*.]"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("http://*"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("http://*:8080"), &origin_pattern)); + + // Other schemes and IP address patterns won't be migrated. + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("192.168.0.1"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("https://127.0.0.1"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("http://[::1]"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("[::1]"), &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("file:///foo/bar.html"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString( + "filesystem:http://www.google.com/temporary/"), + &origin_pattern)); + EXPECT_FALSE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString( + "chrome-extension://peoadpeiejnhkmpaakpnompolbglelel/"), + &origin_pattern)); + + // These are pattern styles which might be generated using FromURL(). + EXPECT_TRUE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("[*.]example.com"), &origin_pattern)); + EXPECT_EQ("http://example.com:80", origin_pattern.ToString()); + + EXPECT_TRUE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("[*.]google.com:80"), + &origin_pattern)); + EXPECT_EQ("http://google.com:80", origin_pattern.ToString()); + + EXPECT_TRUE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("[*.]example.com:123"), + &origin_pattern)); + EXPECT_EQ("http://example.com:123", origin_pattern.ToString()); + + EXPECT_TRUE(ContentSettingsPattern::MigrateFromDomainToOrigin( + ContentSettingsPattern::FromString("https://[*.]google.com:443"), + &origin_pattern)); + EXPECT_EQ("https://google.com:443", origin_pattern.ToString()); +} \ No newline at end of file
diff --git a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java index f3638a2..17b5b7d 100644 --- a/components/cronet/android/api/src/org/chromium/net/CronetEngine.java +++ b/components/cronet/android/api/src/org/chromium/net/CronetEngine.java
@@ -122,6 +122,7 @@ private String mExperimentalOptions; private long mMockCertVerifier; private boolean mNetworkQualityEstimatorEnabled; + private String mCertVerifierData; /** * Default config enables SPDY, disables QUIC, SDCH and HTTP cache. @@ -658,6 +659,22 @@ } /** + * Initializes CachingCertVerifier's cache with certVerifierData which has + * the results of certificate verification. + * @param certVerifierData a serialized representation of certificate + * verification results. + * @return the builder to facilitate chaining. + */ + public Builder setCertVerifierData(String certVerifierData) { + mCertVerifierData = certVerifierData; + return this; + } + + String certVerifierData() { + return mCertVerifierData; + } + + /** * Returns {@link Context} for builder. * * @return {@link Context} for builder. @@ -833,6 +850,19 @@ public abstract void stopNetLog(); /** + * Returns serialized representation of certificate verifier's cache + * which contains the list of hosts/certificates and the certificate + * verification results. May block until data is received from the network + * thread (will timeout after the specified timeout). In case of timeout, it + * returns the previous saved value. + * + * @param timeout in milliseconds. If timeout is 0, it will use default value. + * @return serialized representation of certificate verification results + * data. + */ + public abstract String getCertVerifierData(long timeout); + + /** * Returns differences in metrics collected by Cronet since the last call to * {@link #getGlobalMetricsDeltas}. * <p>
diff --git a/components/cronet/android/api/src/org/chromium/net/JavaCronetEngine.java b/components/cronet/android/api/src/org/chromium/net/JavaCronetEngine.java index e5b781d..9a94454 100644 --- a/components/cronet/android/api/src/org/chromium/net/JavaCronetEngine.java +++ b/components/cronet/android/api/src/org/chromium/net/JavaCronetEngine.java
@@ -93,6 +93,11 @@ public void stopNetLog() {} @Override + public String getCertVerifierData(long timeout) { + return ""; + } + + @Override public byte[] getGlobalMetricsDeltas() { return new byte[0]; }
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc index 118ce78d..91267ab 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.cc +++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -14,6 +14,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" +#include "base/base64.h" #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -28,6 +29,8 @@ #include "base/single_thread_task_runner.h" #include "base/time/time.h" #include "base/values.h" +#include "components/cronet/android/cert/cert_verifier_cache_serializer.h" +#include "components/cronet/android/cert/proto/cert_verification.pb.h" #include "components/cronet/histogram_manager.h" #include "components/cronet/url_request_context_config.h" #include "components/prefs/pref_change_registrar.h" @@ -41,6 +44,7 @@ #include "net/base/net_errors.h" #include "net/base/network_delegate_impl.h" #include "net/base/url_util.h" +#include "net/cert/caching_cert_verifier.h" #include "net/cert/cert_verifier.h" #include "net/cookies/cookie_monster.h" #include "net/http/http_auth_handler_factory.h" @@ -678,6 +682,19 @@ } } + // If there is a cert_verifier, then populate its cache with + // |cert_verifier_data|. + if (!config->cert_verifier_data.empty() && context_->cert_verifier()) { + std::string data; + cronet_pb::CertVerificationCache cert_verification_cache; + if (base::Base64Decode(config->cert_verifier_data, &data) && + cert_verification_cache.ParseFromString(data)) { + DeserializeCertVerifierCache(cert_verification_cache, + reinterpret_cast<net::CachingCertVerifier*>( + context_->cert_verifier())); + } + } + // Iterate through PKP configuration for every host. for (const auto& pkp : config->pkp_list) { // Add the host pinning. @@ -788,6 +805,33 @@ StopNetLogHelper(); } +void CronetURLRequestContextAdapter::GetCertVerifierData( + JNIEnv* env, + const JavaParamRef<jobject>& jcaller) { + PostTaskToNetworkThread( + FROM_HERE, + base::Bind( + &CronetURLRequestContextAdapter::GetCertVerifierDataOnNetworkThread, + base::Unretained(this))); +} + +void CronetURLRequestContextAdapter::GetCertVerifierDataOnNetworkThread() { + DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); + std::string encoded_data; + if (is_context_initialized_ && context_->cert_verifier()) { + std::string data; + cronet_pb::CertVerificationCache cert_cache = + SerializeCertVerifierCache(*reinterpret_cast<net::CachingCertVerifier*>( + context_->cert_verifier())); + cert_cache.SerializeToString(&data); + base::Base64Encode(data, &encoded_data); + } + JNIEnv* env = base::android::AttachCurrentThread(); + Java_CronetUrlRequestContext_onGetCertVerifierData( + env, jcronet_url_request_context_.obj(), + base::android::ConvertUTF8ToJavaString(env, encoded_data).obj()); +} + base::Thread* CronetURLRequestContextAdapter::GetFileThread() { DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); if (!file_thread_) { @@ -845,7 +889,8 @@ const JavaParamRef<jstring>& jexperimental_quic_connection_options, jlong jmock_cert_verifier, jboolean jenable_network_quality_estimator, - jboolean jbypass_public_key_pinning_for_local_trust_anchors) { + jboolean jbypass_public_key_pinning_for_local_trust_anchors, + const JavaParamRef<jstring>& jcert_verifier_data) { return reinterpret_cast<jlong>(new URLRequestContextConfig( jquic_enabled, ConvertNullableJavaStringToUTF8(env, jquic_default_user_agent_id), @@ -865,7 +910,8 @@ base::WrapUnique( reinterpret_cast<net::CertVerifier*>(jmock_cert_verifier)), jenable_network_quality_estimator, - jbypass_public_key_pinning_for_local_trust_anchors)); + jbypass_public_key_pinning_for_local_trust_anchors, + ConvertNullableJavaStringToUTF8(env, jcert_verifier_data))); } // Add a QUIC hint to a URLRequestContextConfig.
diff --git a/components/cronet/android/cronet_url_request_context_adapter.h b/components/cronet/android/cronet_url_request_context_adapter.h index 7b76431..95ee713 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.h +++ b/components/cronet/android/cronet_url_request_context_adapter.h
@@ -87,6 +87,11 @@ void StopNetLog(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); + // Posts a task to Network thread to get serialized results of certificate + // verifications of |context_|'s |cert_verifier|. + void GetCertVerifierData(JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller); + // Default net::LOAD flags used to create requests. int default_load_flags() const { return default_load_flags_; } @@ -133,6 +138,10 @@ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const; + // Serializes results of certificate verifications of |context_|'s + // |cert_verifier| on the Network thread. + void GetCertVerifierDataOnNetworkThread(); + // Gets the file thread. Create one if there is none. base::Thread* GetFileThread();
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java index 3e4a3113..60ca98c 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
@@ -75,6 +75,14 @@ private final ObserverList<RequestFinishedListener> mFinishedListenerList = new ObserverList<RequestFinishedListener>(); + /** + * Synchronize access to mCertVerifierData. + */ + private ConditionVariable mWaitGetCertVerifierDataComplete = new ConditionVariable(); + + /** Holds CertVerifier data. */ + private String mCertVerifierData; + @UsedByReflection("CronetEngine.java") public CronetUrlRequestContext(final CronetEngine.Builder builder) { CronetLibraryLoader.ensureInitialized(builder.getContext(), builder); @@ -119,7 +127,8 @@ builder.dataReductionProxySecureProxyCheckUrl(), builder.cacheDisabled(), builder.httpCacheMode(), builder.httpCacheMaxSize(), builder.experimentalOptions(), builder.mockCertVerifier(), builder.networkQualityEstimatorEnabled(), - builder.publicKeyPinningBypassForLocalTrustAnchorsEnabled()); + builder.publicKeyPinningBypassForLocalTrustAnchorsEnabled(), + builder.certVerifierData()); for (Builder.QuicHint quicHint : builder.quicHints()) { nativeAddQuicHint(urlRequestContextConfig, quicHint.mHost, quicHint.mPort, quicHint.mAlternatePort); @@ -217,6 +226,22 @@ } } + @Override + public String getCertVerifierData(long timeout) { + if (timeout < 0) { + throw new IllegalArgumentException("timeout must be a positive value"); + } else if (timeout == 0) { + timeout = 100; + } + mWaitGetCertVerifierDataComplete.close(); + synchronized (mLock) { + checkHaveAdapter(); + nativeGetCertVerifierData(mUrlRequestContextAdapter); + } + mWaitGetCertVerifierDataComplete.block(timeout); + return mCertVerifierData; + } + // This method is intentionally non-static to ensure Cronet native library // is loaded by class constructor. @Override @@ -500,6 +525,13 @@ } } + @SuppressWarnings("unused") + @CalledByNative + private void onGetCertVerifierData(String certVerifierData) { + mCertVerifierData = certVerifierData; + mWaitGetCertVerifierDataComplete.open(); + } + void reportFinished(final CronetUrlRequest request) { if (!mNetworkQualityEstimatorEnabled) { return; @@ -544,7 +576,7 @@ String dataReductionProxySecureProxyCheckUrl, boolean disableCache, int httpCacheMode, long httpCacheMaxSize, String experimentalOptions, long mockCertVerifier, boolean enableNetworkQualityEstimator, - boolean bypassPublicKeyPinningForLocalTrustAnchors); + boolean bypassPublicKeyPinningForLocalTrustAnchors, String certVerifierData); private static native void nativeAddQuicHint( long urlRequestContextConfig, String host, int port, int alternatePort); @@ -569,6 +601,9 @@ private native void nativeStopNetLog(long nativePtr); @NativeClassQualifiedName("CronetURLRequestContextAdapter") + private native void nativeGetCertVerifierData(long nativePtr); + + @NativeClassQualifiedName("CronetURLRequestContextAdapter") private native void nativeInitRequestContextOnMainThread(long nativePtr); @NativeClassQualifiedName("CronetURLRequestContextAdapter")
diff --git a/components/cronet/android/test/cronet_url_request_context_config_test.cc b/components/cronet/android/test/cronet_url_request_context_config_test.cc index 5920aaf..2112077 100644 --- a/components/cronet/android/test/cronet_url_request_context_config_test.cc +++ b/components/cronet/android/test/cronet_url_request_context_config_test.cc
@@ -37,6 +37,7 @@ CHECK_NE(config->quic_user_agent_id.find("Cronet/" CRONET_VERSION), std::string::npos); CHECK_EQ(config->load_disable_cache, false); + CHECK_EQ(config->cert_verifier_data, "test_cert_verifier_data"); CHECK_EQ(config->http_cache, URLRequestContextConfig::HttpCacheType::MEMORY); CHECK_EQ(config->http_cache_max_size, 54321); CHECK_EQ(config->data_reduction_proxy_key, "abcd");
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java index c323f87..b0a7a09 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/BidirectionalStreamQuicTest.java
@@ -315,4 +315,40 @@ assertTrue(NetError.ERR_QUIC_PROTOCOL_ERROR == callback.mError.getCronetInternalErrorCode() || NetError.ERR_CONNECTION_REFUSED == callback.mError.getCronetInternalErrorCode()); } + + @SmallTest + @Feature({"Cronet"}) + @OnlyRunNativeCronet + // Test that certificate verify results are serialized and deserialized correctly. + public void testSerializeDeserialize() throws Exception { + setUp(QuicBidirectionalStreams.ENABLED); + String path = "/simple.txt"; + String quicURL = QuicTestServer.getServerURL() + path; + TestBidirectionalStreamCallback callback = new TestBidirectionalStreamCallback(); + BidirectionalStream stream = new BidirectionalStream + .Builder(quicURL, callback, callback.getExecutor(), + mTestFramework.mCronetEngine) + .setHttpMethod("GET") + .build(); + stream.start(); + callback.blockForDone(); + assertTrue(stream.isDone()); + assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); + assertEquals("This is a simple text file served by QUIC.\n", callback.mResponseAsString); + assertEquals("quic/1+spdy/3", callback.mResponseInfo.getNegotiatedProtocol()); + + String serialized_data = mTestFramework.mCronetEngine.getCertVerifierData(100); + assertFalse(serialized_data.isEmpty()); + + // Create a new builder and verify that the |serialized_data| is deserialized correctly. + CronetEngine.Builder builder = new CronetEngine.Builder(getContext()); + builder.enableQUIC(true); + builder.setMockCertVerifierForTesting(QuicTestServer.createMockCertVerifier()); + builder.setCertVerifierData(serialized_data); + + CronetTestFramework testFramework = + startCronetTestFrameworkWithUrlAndCronetEngineBuilder(null, builder); + String deserialized_data = testFramework.mCronetEngine.getCertVerifierData(100); + assertEquals(deserialized_data, serialized_data); + } }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java index 2ce466f..ee00041 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -1159,6 +1159,31 @@ @SmallTest @Feature({"Cronet"}) + public void testEmptyGetCertVerifierData() { + CronetTestFramework testFramework = startCronetTestFrameworkAndSkipLibraryInit(); + + // Immediately make a request after initializing the engine. + CronetEngine cronetEngine = testFramework.initCronetEngine(); + TestUrlRequestCallback callback = new TestUrlRequestCallback(); + UrlRequest.Builder urlRequestBuilder = + new UrlRequest.Builder(mUrl, callback, callback.getExecutor(), cronetEngine); + urlRequestBuilder.build().start(); + callback.blockForDone(); + assertEquals(200, callback.mResponseInfo.getHttpStatusCode()); + + try { + cronetEngine.getCertVerifierData(-1); + fail("Should throw an exception"); + } catch (Exception e) { + assertEquals("timeout must be a positive value", e.getMessage()); + } + // Because mUrl is http, getCertVerifierData() will return empty data. + String data = cronetEngine.getCertVerifierData(100); + assertTrue(data.isEmpty()); + } + + @SmallTest + @Feature({"Cronet"}) public void testInitEngineStartTwoRequests() throws Exception { CronetTestFramework testFramework = startCronetTestFrameworkAndSkipLibraryInit(); @@ -1260,6 +1285,7 @@ builder.enableQUIC(true); builder.enableSDCH(true); builder.addQuicHint("example.com", 12, 34); + builder.setCertVerifierData("test_cert_verifier_data"); builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_IN_MEMORY, 54321); builder.enableDataReductionProxy("abcd"); builder.setUserAgent("efgh");
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java index c47c96c..ec7d461 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/QuicTest.java
@@ -54,7 +54,6 @@ .put("migrate_sessions_early", true); JSONObject experimentalOptions = new JSONObject().put("QUIC", quicParams); mBuilder.setExperimentalOptions(experimentalOptions.toString()); - mBuilder.setMockCertVerifierForTesting(QuicTestServer.createMockCertVerifier()); mBuilder.setStoragePath(CronetTestFramework.getTestStorage(getContext())); mBuilder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK_NO_HTTP, 1000 * 1024);
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 3878536..fa080d2d 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -8,12 +8,16 @@ #include "base/json/json_reader.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/values.h" +#include "net/cert/caching_cert_verifier.h" #include "net/cert/cert_verifier.h" +#include "net/cert/cert_verify_proc.h" +#include "net/cert/multi_threaded_cert_verifier.h" #include "net/dns/host_resolver.h" #include "net/http/http_server_properties.h" #include "net/quic/quic_protocol.h" @@ -251,7 +255,8 @@ const std::string& data_reduction_secure_proxy_check_url, std::unique_ptr<net::CertVerifier> mock_cert_verifier, bool enable_network_quality_estimator, - bool bypass_public_key_pinning_for_local_trust_anchors) + bool bypass_public_key_pinning_for_local_trust_anchors, + const std::string& cert_verifier_data) : enable_quic(enable_quic), quic_user_agent_id(quic_user_agent_id), enable_spdy(enable_spdy), @@ -270,7 +275,8 @@ mock_cert_verifier(std::move(mock_cert_verifier)), enable_network_quality_estimator(enable_network_quality_estimator), bypass_public_key_pinning_for_local_trust_anchors( - bypass_public_key_pinning_for_local_trust_anchors) {} + bypass_public_key_pinning_for_local_trust_anchors), + cert_verifier_data(cert_verifier_data) {} URLRequestContextConfig::~URLRequestContextConfig() {} @@ -304,8 +310,17 @@ ParseAndSetExperimentalOptions(experimental_options, context_builder, net_log, file_task_runner); - if (mock_cert_verifier) - context_builder->SetCertVerifier(std::move(mock_cert_verifier)); + std::unique_ptr<net::CertVerifier> cert_verifier; + if (mock_cert_verifier) { + // Because |context_builder| expects CachingCertVerifier, wrap + // |mock_cert_verifier| into a CachingCertVerifier. + cert_verifier = base::MakeUnique<net::CachingCertVerifier>( + std::move(mock_cert_verifier)); + } else { + // net::CertVerifier::CreateDefault() returns a CachingCertVerifier. + cert_verifier = net::CertVerifier::CreateDefault(); + } + context_builder->SetCertVerifier(std::move(cert_verifier)); // TODO(mef): Use |config| to set cookies. }
diff --git a/components/cronet/url_request_context_config.h b/components/cronet/url_request_context_config.h index 2a00cf1..5ede832 100644 --- a/components/cronet/url_request_context_config.h +++ b/components/cronet/url_request_context_config.h
@@ -111,7 +111,9 @@ // Enable network quality estimator. bool enable_network_quality_estimator, // Enable bypassing of public key pinning for local trust anchors - bool bypass_public_key_pinning_for_local_trust_anchors); + bool bypass_public_key_pinning_for_local_trust_anchors, + // Certificate verifier cache data. + const std::string& cert_verifier_data); ~URLRequestContextConfig(); // Configure |context_builder| based on |this|. @@ -161,6 +163,9 @@ // Enable public key pinning bypass for local trust anchors. const bool bypass_public_key_pinning_for_local_trust_anchors; + // Data to populte CertVerifierCache. + const std::string cert_verifier_data; + // App-provided list of servers that support QUIC. ScopedVector<QuicHint> quic_hints;
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index 56025cd..a0cef2a 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -61,7 +61,9 @@ // Enable network quality estimator. false, // Enable Public Key Pinning bypass for local trust anchors. - true); + true, + // Certificate verifier cache data. + ""); net::URLRequestContextBuilder builder; net::NetLog net_log; @@ -142,7 +144,9 @@ // Enable network quality estimator. false, // Enable Public Key Pinning bypass for local trust anchors. - true); + true, + // Certificate verifier cache data. + ""); net::URLRequestContextBuilder builder; net::NetLog net_log;
diff --git a/components/data_reduction_proxy/core/browser/data_usage_store.cc b/components/data_reduction_proxy/core/browser/data_usage_store.cc index 220231b..80f4ff2 100644 --- a/components/data_reduction_proxy/core/browser/data_usage_store.cc +++ b/components/data_reduction_proxy/core/browser/data_usage_store.cc
@@ -56,7 +56,11 @@ exploded.minute -= exploded.minute % kDataUsageBucketLengthInMinutes; exploded.second = 0; exploded.millisecond = 0; - return base::Time::FromUTCExploded(exploded); + + base::Time out_time; + bool conversion_success = base::Time::FromUTCExploded(exploded, &out_time); + DCHECK(conversion_success); + return out_time; } } // namespace
diff --git a/components/data_reduction_proxy/core/browser/data_usage_store_unittest.cc b/components/data_reduction_proxy/core/browser/data_usage_store_unittest.cc index 8a4e640..6dc60c8 100644 --- a/components/data_reduction_proxy/core/browser/data_usage_store_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_usage_store_unittest.cc
@@ -65,7 +65,8 @@ void PopulateStore() { base::Time::Exploded exploded = TestExplodedTime(); - base::Time current_time = base::Time::FromUTCExploded(exploded); + base::Time current_time; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, ¤t_time)); DataUsageBucket current_bucket; current_bucket.set_last_updated_timestamp(current_time.ToInternalValue()); @@ -144,12 +145,14 @@ exploded.minute = 0; exploded.second = 0; exploded.millisecond = 0; - base::Time time1 = base::Time::FromUTCExploded(exploded); + base::Time time1; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time1)); exploded.minute = 14; exploded.second = 59; exploded.millisecond = 999; - base::Time time2 = base::Time::FromUTCExploded(exploded); + base::Time time2; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time2)); DataUsageBucket bucket; data_usage_store()->LoadCurrentDataUsageBucket(&bucket); @@ -180,12 +183,14 @@ exploded.minute = 0; exploded.second = 59; exploded.millisecond = 999; - base::Time time1 = base::Time::FromUTCExploded(exploded); + base::Time time1; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time1)); exploded.minute = 15; exploded.second = 0; exploded.millisecond = 0; - base::Time time2 = base::Time::FromUTCExploded(exploded); + base::Time time2; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time2)); DataUsageBucket bucket; data_usage_store()->LoadCurrentDataUsageBucket(&bucket); @@ -308,25 +313,32 @@ TEST_F(DataUsageStoreTest, BucketOverlapsInterval) { base::Time::Exploded exploded = TestExplodedTime(); - base::Time time1 = base::Time::FromUTCExploded(exploded); + base::Time time1; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time1)); exploded.minute = 16; - base::Time time16 = base::Time::FromUTCExploded(exploded); + base::Time time16; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time16)); exploded.minute = 17; - base::Time time17 = base::Time::FromUTCExploded(exploded); + base::Time time17; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time17)); exploded.minute = 18; - base::Time time18 = base::Time::FromUTCExploded(exploded); + base::Time time18; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time18)); exploded.minute = 33; - base::Time time33 = base::Time::FromUTCExploded(exploded); + base::Time time33; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time33)); exploded.minute = 34; - base::Time time34 = base::Time::FromUTCExploded(exploded); + base::Time time34; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time34)); exploded.minute = 46; - base::Time time46 = base::Time::FromUTCExploded(exploded); + base::Time time46; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &time46)); ASSERT_FALSE(DataUsageStore::BucketOverlapsInterval(time1, time17, time33)); ASSERT_TRUE(DataUsageStore::BucketOverlapsInterval(time16, time17, time33)); @@ -343,45 +355,53 @@ DataUsageBucket current_bucket; data_usage_store()->LoadCurrentDataUsageBucket(¤t_bucket); + base::Time out_time; + exploded.minute = 0; - ASSERT_EQ(kTestCurrentBucketIndex, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); + ASSERT_EQ(kTestCurrentBucketIndex, ComputeBucketIndex(out_time)); + exploded.minute = 14; - ASSERT_EQ(kTestCurrentBucketIndex, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); + ASSERT_EQ(kTestCurrentBucketIndex, ComputeBucketIndex(out_time)); exploded.minute = 15; - ASSERT_EQ(kTestCurrentBucketIndex + 1, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); + ASSERT_EQ(kTestCurrentBucketIndex + 1, ComputeBucketIndex(out_time)); exploded.hour = 11; exploded.minute = 59; - ASSERT_EQ(kTestCurrentBucketIndex - 1, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); + ASSERT_EQ(kTestCurrentBucketIndex - 1, ComputeBucketIndex(out_time)); exploded.minute = 0; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); ASSERT_EQ(kTestCurrentBucketIndex - kBucketsInHour, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + ComputeBucketIndex(out_time)); exploded.hour = 1; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); ASSERT_EQ(kTestCurrentBucketIndex - kBucketsInHour * 11, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + ComputeBucketIndex(out_time)); exploded.day_of_month = 1; exploded.hour = 12; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); ASSERT_EQ(kTestCurrentBucketIndex - kBucketsInHour * 30 * 24, - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + ComputeBucketIndex(out_time)); exploded.hour = 11; exploded.minute = 45; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); ASSERT_EQ(kTestCurrentBucketIndex - kBucketsInHour * 30 * 24 - 1 + static_cast<int>(kNumExpectedBuckets), - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + ComputeBucketIndex(out_time)); exploded.minute = 30; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); ASSERT_EQ(kTestCurrentBucketIndex - kBucketsInHour * 30 * 24 - 2 + static_cast<int>(kNumExpectedBuckets), - ComputeBucketIndex(base::Time::FromUTCExploded(exploded))); + ComputeBucketIndex(out_time)); } TEST_F(DataUsageStoreTest, DeleteBrowsingHistory) { @@ -393,7 +413,8 @@ base::Time::Exploded exploded = TestExplodedTime(); exploded.minute = 0; - base::Time now = base::Time::FromUTCExploded(exploded); + base::Time now; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &now)); base::Time fifteen_mins_from_now = now + base::TimeDelta::FromMinutes(15); // Deleting browsing from the future should be a no-op. data_usage_store()->DeleteBrowsingHistory(fifteen_mins_from_now,
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc index f821a88..5937da70 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.cc
@@ -59,7 +59,7 @@ base::StringPiece action_prefix) { DCHECK(!action_prefix.empty()); // A valid action does not include a trailing '='. - DCHECK(action_prefix[action_prefix.size() - 1] != kActionValueDelimiter); + DCHECK(action_prefix.back() != kActionValueDelimiter); return header_value.size() > action_prefix.size() + 1 && header_value[action_prefix.size()] == kActionValueDelimiter &&
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc index c176f87..6742221 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -94,18 +94,21 @@ } bool IsIncludedInLoFiEnabledFieldTrial() { - return FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kEnabled) == - 0; + return !IsLoFiOnViaFlags() && !IsLoFiDisabledViaFlags() && + FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kEnabled) == + 0; } bool IsIncludedInLoFiControlFieldTrial() { - return FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kControl) == - 0; + return !IsLoFiOnViaFlags() && !IsLoFiDisabledViaFlags() && + FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kControl) == + 0; } bool IsIncludedInLoFiPreviewFieldTrial() { - return FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kPreview) == - 0; + return !IsLoFiOnViaFlags() && !IsLoFiDisabledViaFlags() && + FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kPreview) == + 0; } bool IsIncludedInServerExperimentsFieldTrial() {
diff --git a/components/devtools_discovery/devtools_discovery_manager.cc b/components/devtools_discovery/devtools_discovery_manager.cc index aaa998c..3233085a 100644 --- a/components/devtools_discovery/devtools_discovery_manager.cc +++ b/components/devtools_discovery/devtools_discovery_manager.cc
@@ -62,4 +62,31 @@ return result; } +std::unique_ptr<base::DictionaryValue> +DevToolsDiscoveryManager::HandleNewTargetCommand( + base::DictionaryValue* command_dict) { + int id; + std::string method; + std::string initial_url; + const base::DictionaryValue* params_dict = nullptr; + if (command_dict->GetInteger("id", &id) && + command_dict->GetString("method", &method) && + method == "Browser.newPage" && + command_dict->GetDictionary("params", ¶ms_dict) && + params_dict->GetString("initialUrl", &initial_url)) { + std::unique_ptr<devtools_discovery::DevToolsTargetDescriptor> descriptor = + CreateNew(GURL(initial_url)); + if (!descriptor) + return nullptr; + std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + result->SetInteger("id", id); + std::unique_ptr<base::DictionaryValue> cmd_result( + new base::DictionaryValue()); + cmd_result->SetString("pageId", descriptor->GetId()); + result->Set("result", std::move(cmd_result)); + return result; + } + return nullptr; +} + } // namespace devtools_discovery
diff --git a/components/devtools_discovery/devtools_discovery_manager.h b/components/devtools_discovery/devtools_discovery_manager.h index 75657d4..023e067 100644 --- a/components/devtools_discovery/devtools_discovery_manager.h +++ b/components/devtools_discovery/devtools_discovery_manager.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/singleton.h" +#include "base/values.h" #include "components/devtools_discovery/devtools_target_descriptor.h" namespace devtools_discovery { @@ -39,6 +40,10 @@ DevToolsTargetDescriptor::List GetDescriptors(); std::unique_ptr<DevToolsTargetDescriptor> CreateNew(const GURL& url); + // Handles Browser.newPage only. + std::unique_ptr<base::DictionaryValue> HandleNewTargetCommand( + base::DictionaryValue* command_dict); + private: friend struct base::DefaultSingletonTraits<DevToolsDiscoveryManager>;
diff --git a/components/devtools_http_handler/devtools_http_handler.cc b/components/devtools_http_handler/devtools_http_handler.cc index 38f32dc..48f5811 100644 --- a/components/devtools_http_handler/devtools_http_handler.cc +++ b/components/devtools_http_handler/devtools_http_handler.cc
@@ -395,7 +395,7 @@ const net::HttpServerRequestInfo& info) { server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools); - if (info.path.find("/json") == 0) { + if (base::StartsWith(info.path, "/json", base::CompareCase::SENSITIVE)) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, @@ -406,7 +406,8 @@ return; } - if (info.path.find(kThumbUrlPrefix) == 0) { + if (base::StartsWith(info.path, kThumbUrlPrefix, + base::CompareCase::SENSITIVE)) { // Thumbnail request. const std::string target_id = info.path.substr(strlen(kThumbUrlPrefix)); BrowserThread::PostTask( @@ -430,7 +431,8 @@ return; } - if (info.path.find("/devtools/") != 0) { + if (!base::StartsWith(info.path, "/devtools/", + base::CompareCase::SENSITIVE)) { server_->Send404(connection_id); return; } @@ -517,7 +519,7 @@ return true; } - if (path.find("/") != 0) { + if (!base::StartsWith(path, "/", base::CompareCase::SENSITIVE)) { // Malformed command. return false; } @@ -696,8 +698,8 @@ return; std::string browser_prefix = "/devtools/browser"; - size_t browser_pos = request.path.find(browser_prefix); - if (browser_pos == 0) { + if (base::StartsWith(request.path, browser_prefix, + base::CompareCase::SENSITIVE)) { scoped_refptr<DevToolsAgentHost> browser_agent = DevToolsAgentHost::CreateForBrowser( thread_->task_runner(), @@ -721,8 +723,8 @@ return; } - size_t pos = request.path.find(kPageUrlPrefix); - if (pos != 0) { + if (!base::StartsWith(request.path, kPageUrlPrefix, + base::CompareCase::SENSITIVE)) { Send404(connection_id); return; }
diff --git a/components/display_compositor/gl_helper_unittest.cc b/components/display_compositor/gl_helper_unittest.cc index 44fe991..d456630 100644 --- a/components/display_compositor/gl_helper_unittest.cc +++ b/components/display_compositor/gl_helper_unittest.cc
@@ -258,10 +258,8 @@ } // Check the output size matches the destination of the last stage - EXPECT_EQ(scaler_stages[scaler_stages.size() - 1].dst_size.width(), - dst_size.width()); - EXPECT_EQ(scaler_stages[scaler_stages.size() - 1].dst_size.height(), - dst_size.height()); + EXPECT_EQ(scaler_stages.back().dst_size.width(), dst_size.width()); + EXPECT_EQ(scaler_stages.back().dst_size.height(), dst_size.height()); // Used to verify that up-scales are not attempted after some // other scale.
diff --git a/components/drive/file_system/touch_operation_unittest.cc b/components/drive/file_system/touch_operation_unittest.cc index 8c15010a..49bbbe5 100644 --- a/components/drive/file_system/touch_operation_unittest.cc +++ b/components/drive/file_system/touch_operation_unittest.cc
@@ -32,19 +32,22 @@ }; FileError error = FILE_ERROR_FAILED; - operation.TouchFile( - kTestPath, - base::Time::FromUTCExploded(kLastAccessTime), - base::Time::FromUTCExploded(kLastModifiedTime), - google_apis::test_util::CreateCopyResultCallback(&error)); + base::Time last_access_time_utc; + base::Time last_modified_time_utc; + EXPECT_TRUE( + base::Time::FromUTCExploded(kLastAccessTime, &last_access_time_utc)); + EXPECT_TRUE( + base::Time::FromUTCExploded(kLastModifiedTime, &last_modified_time_utc)); + operation.TouchFile(kTestPath, last_access_time_utc, last_modified_time_utc, + google_apis::test_util::CreateCopyResultCallback(&error)); content::RunAllBlockingPoolTasksUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ResourceEntry entry; EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kTestPath, &entry)); - EXPECT_EQ(base::Time::FromUTCExploded(kLastAccessTime), + EXPECT_EQ(last_access_time_utc, base::Time::FromInternalValue(entry.file_info().last_accessed())); - EXPECT_EQ(base::Time::FromUTCExploded(kLastModifiedTime), + EXPECT_EQ(last_modified_time_utc, base::Time::FromInternalValue(entry.file_info().last_modified())); EXPECT_EQ(ResourceEntry::DIRTY, entry.metadata_edit_state());
diff --git a/components/drive/resource_entry_conversion_unittest.cc b/components/drive/resource_entry_conversion_unittest.cc index ef1bd4f..5891d91671 100644 --- a/components/drive/resource_entry_conversion_unittest.cc +++ b/components/drive/resource_entry_conversion_unittest.cc
@@ -26,7 +26,9 @@ exploded.minute = 40; exploded.second = 47; exploded.millisecond = 330; - return base::Time::FromUTCExploded(exploded); + base::Time out_time; + EXPECT_TRUE(base::Time::FromUTCExploded(exploded, &out_time)); + return out_time; } } // namespace
diff --git a/components/drive/service/fake_drive_service_unittest.cc b/components/drive/service/fake_drive_service_unittest.cc index bc6667a3..eae7f435 100644 --- a/components/drive/service/fake_drive_service_unittest.cc +++ b/components/drive/service/fake_drive_service_unittest.cc
@@ -1066,11 +1066,10 @@ const std::string kParentResourceId = "2_folder_resource_id"; DriveApiErrorCode error = DRIVE_OTHER_ERROR; std::unique_ptr<FileResource> entry; + base::Time modified_date_utc; + EXPECT_TRUE(base::Time::FromUTCExploded(kModifiedDate, &modified_date_utc)); fake_service_.CopyResource( - kResourceId, - kParentResourceId, - "new title", - base::Time::FromUTCExploded(kModifiedDate), + kResourceId, kParentResourceId, "new title", modified_date_utc, test_util::CreateCopyResultCallback(&error, &entry)); base::RunLoop().RunUntilIdle(); @@ -1079,7 +1078,7 @@ // The copied entry should have the new resource ID and the title. EXPECT_NE(kResourceId, entry->file_id()); EXPECT_EQ("new title", entry->title()); - EXPECT_EQ(base::Time::FromUTCExploded(kModifiedDate), entry->modified_date()); + EXPECT_EQ(modified_date_utc, entry->modified_date()); EXPECT_TRUE(HasParent(entry->file_id(), kParentResourceId)); // Should be incremented as a new hosted document was created. EXPECT_EQ(old_largest_change_id + 1, @@ -1163,11 +1162,14 @@ const std::string kParentResourceId = "2_folder_resource_id"; DriveApiErrorCode error = DRIVE_OTHER_ERROR; std::unique_ptr<FileResource> entry; + base::Time modified_date_utc; + base::Time viewed_date_utc; + EXPECT_TRUE(base::Time::FromUTCExploded(kModifiedDate, &modified_date_utc)); + EXPECT_TRUE(base::Time::FromUTCExploded(kViewedDate, &viewed_date_utc)); + fake_service_.UpdateResource( - kResourceId, kParentResourceId, "new title", - base::Time::FromUTCExploded(kModifiedDate), - base::Time::FromUTCExploded(kViewedDate), - google_apis::drive::Properties(), + kResourceId, kParentResourceId, "new title", modified_date_utc, + viewed_date_utc, google_apis::drive::Properties(), test_util::CreateCopyResultCallback(&error, &entry)); base::RunLoop().RunUntilIdle(); @@ -1176,10 +1178,8 @@ // The updated entry should have the new title. EXPECT_EQ(kResourceId, entry->file_id()); EXPECT_EQ("new title", entry->title()); - EXPECT_EQ(base::Time::FromUTCExploded(kModifiedDate), - entry->modified_date()); - EXPECT_EQ(base::Time::FromUTCExploded(kViewedDate), - entry->last_viewed_by_me_date()); + EXPECT_EQ(modified_date_utc, entry->modified_date()); + EXPECT_EQ(viewed_date_utc, entry->last_viewed_by_me_date()); EXPECT_TRUE(HasParent(kResourceId, kParentResourceId)); // Should be incremented as a new hosted document was created. EXPECT_EQ(old_largest_change_id + 1,
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 9d01332..0e7e730a 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -37,8 +37,10 @@ #include "base/macros.h" #include "base/memory/free_deleter.h" #include "base/memory/ptr_util.h" +#include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_task_runner_handle.h" #include "components/exo/buffer.h" #include "components/exo/display.h" #include "components/exo/keyboard.h" @@ -87,6 +89,10 @@ namespace wayland { namespace { +// We don't send configure immediately after tablet mode switch +// because layout can change due to orientation lock state or accelerometer. +const int kConfigureDelayAfterLayoutSwitchMs = 300; + // Default wayland socket name. const base::FilePath::CharType kSocketName[] = FILE_PATH_LITERAL("wayland-0"); @@ -1547,7 +1553,8 @@ wl_resource* remote_shell_resource) : display_(display), display_id_(display_id), - remote_shell_resource_(remote_shell_resource) { + remote_shell_resource_(remote_shell_resource), + weak_ptr_factory_(this) { ash::WmShell::Get()->AddShellObserver(this); ash::Shell* shell = ash::Shell::GetInstance(); shell->activation_client()->AddObserver(this); @@ -1585,9 +1592,19 @@ void OnDisplayWorkAreaInsetsChanged() override { SendConfigure(); } void OnMaximizeModeStarted() override { SendLayoutModeChange(ZWP_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET); + send_configure_after_layout_change_ = true; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&WaylandRemoteShell::MaybeSendConfigure, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(kConfigureDelayAfterLayoutSwitchMs)); } void OnMaximizeModeEnded() override { SendLayoutModeChange(ZWP_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED); + send_configure_after_layout_change_ = true; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&WaylandRemoteShell::MaybeSendConfigure, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(kConfigureDelayAfterLayoutSwitchMs)); } // Overridden from aura::client::ActivationChangeObserver: @@ -1599,7 +1616,13 @@ } private: + void MaybeSendConfigure() { + if (send_configure_after_layout_change_) + SendConfigure(); + } + void SendConfigure() { + send_configure_after_layout_change_ = false; const display::Display& display = ash::Shell::GetInstance()->display_manager()->GetDisplayForId( display_id_); @@ -1611,7 +1634,7 @@ wl_client_flush(wl_resource_get_client(remote_shell_resource_)); } - void SendLayoutModeChange(int mode) { + void SendLayoutModeChange(uint32_t mode) { if (wl_resource_get_version(remote_shell_resource_) < 8) return; zwp_remote_shell_v1_send_layout_mode_changed(remote_shell_resource_, mode); @@ -1660,6 +1683,10 @@ // The remote shell resource associated with observer. wl_resource* const remote_shell_resource_; + bool send_configure_after_layout_change_ = false; + + base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(WaylandRemoteShell); };
diff --git a/components/filesystem/BUILD.gn b/components/filesystem/BUILD.gn index c35762c2..67f6234 100644 --- a/components/filesystem/BUILD.gn +++ b/components/filesystem/BUILD.gn
@@ -76,7 +76,7 @@ "//mojo/common", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/cpp/test:run_all_shelltests", ]
diff --git a/components/filesystem/files_test_base.cc b/components/filesystem/files_test_base.cc index c1a6d8b..b8a4d08 100644 --- a/components/filesystem/files_test_base.cc +++ b/components/filesystem/files_test_base.cc
@@ -12,14 +12,15 @@ namespace filesystem { -FilesTestBase::FilesTestBase() : ShellTest("exe:filesystem_service_unittests") { +FilesTestBase::FilesTestBase() + : ServiceTest("exe:filesystem_service_unittests") { } FilesTestBase::~FilesTestBase() { } void FilesTestBase::SetUp() { - ShellTest::SetUp(); + ServiceTest::SetUp(); connector()->ConnectToInterface("mojo:filesystem", &files_); }
diff --git a/components/filesystem/files_test_base.h b/components/filesystem/files_test_base.h index fc594b0..8712a6c 100644 --- a/components/filesystem/files_test_base.h +++ b/components/filesystem/files_test_base.h
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "components/filesystem/public/interfaces/file_system.mojom.h" #include "mojo/public/cpp/bindings/binding.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" namespace filesystem { @@ -37,12 +37,12 @@ return base::Bind(&DoCaptures<T1, T2, T3>, t1, t2, t3); } -class FilesTestBase : public shell::test::ShellTest { +class FilesTestBase : public shell::test::ServiceTest { public: FilesTestBase(); ~FilesTestBase() override; - // Overridden from shell::test::ShellTest: + // Overridden from shell::test::ServiceTest: void SetUp() override; protected:
diff --git a/components/gcm_driver/crypto/gcm_encryption_provider.cc b/components/gcm_driver/crypto/gcm_encryption_provider.cc index 9532d3b..fb3fd9ae 100644 --- a/components/gcm_driver/crypto/gcm_encryption_provider.cc +++ b/components/gcm_driver/crypto/gcm_encryption_provider.cc
@@ -31,7 +31,7 @@ std::string GCMEncryptionProvider::ToDecryptionResultDetailsString( DecryptionResult result) { - switch(result) { + switch (result) { case DECRYPTION_RESULT_UNENCRYPTED: return "Message was not encrypted"; case DECRYPTION_RESULT_DECRYPTED:
diff --git a/components/history/core/browser/android/android_urls_sql_handler.cc b/components/history/core/browser/android/android_urls_sql_handler.cc index e7552919..31d2299 100644 --- a/components/history/core/browser/android/android_urls_sql_handler.cc +++ b/components/history/core/browser/android/android_urls_sql_handler.cc
@@ -51,14 +51,9 @@ bool AndroidURLsSQLHandler::Delete(const TableIDRows& ids_set) { std::vector<URLID> ids; - for (TableIDRows::const_iterator id = ids_set.begin(); - id != ids_set.end(); ++id) - ids.push_back(id->url_id); - - if (!ids.size()) - return true; - - return android_urls_db_->DeleteAndroidURLRows(ids); + for (const auto& id : ids_set) + ids.push_back(id.url_id); + return ids.empty() || android_urls_db_->DeleteAndroidURLRows(ids); } } // namespace history.
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 42732d85..4ca3a34 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -102,7 +102,7 @@ mv.redirects.push_back(mv.url); } else { mv.redirects = redirects; - if (mv.redirects[mv.redirects.size() - 1] != mv.url) { + if (mv.redirects.back() != mv.url) { // The last url must be the target url. mv.redirects.push_back(mv.url); }
diff --git a/components/history/core/browser/url_database.cc b/components/history/core/browser/url_database.cc index 3b4cb27..5558457 100644 --- a/components/history/core/browser/url_database.cc +++ b/components/history/core/browser/url_database.cc
@@ -528,8 +528,7 @@ base::string16 lower_prefix = base::i18n::ToLower(prefix); // This magic gives us a prefix search. base::string16 next_prefix = lower_prefix; - next_prefix[next_prefix.size() - 1] = - next_prefix[next_prefix.size() - 1] + 1; + next_prefix.back() = next_prefix.back() + 1; statement.BindInt64(0, keyword_id); statement.BindString16(1, lower_prefix); statement.BindString16(2, next_prefix);
diff --git a/components/leveldb/BUILD.gn b/components/leveldb/BUILD.gn index fb7068f9..012155f 100644 --- a/components/leveldb/BUILD.gn +++ b/components/leveldb/BUILD.gn
@@ -70,7 +70,7 @@ "//mojo/common", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/cpp/test:run_all_shelltests", "//third_party/leveldatabase",
diff --git a/components/leveldb/env_mojo.cc b/components/leveldb/env_mojo.cc index 54681d0d..233a0cd 100644 --- a/components/leveldb/env_mojo.cc +++ b/components/leveldb/env_mojo.cc
@@ -8,6 +8,7 @@ #include <memory> +#include "base/strings/string_util.h" #include "base/trace_event/trace_event.h" #include "third_party/leveldatabase/chromium_logger.h" #include "third_party/leveldatabase/src/include/leveldb/status.h" @@ -137,10 +138,12 @@ dir_(dir), thread_(thread) { base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); - if (path.BaseName().AsUTF8Unsafe().find("MANIFEST") == 0) + if (base::StartsWith(path.BaseName().AsUTF8Unsafe(), "MANIFEST", + base::CompareCase::SENSITIVE)) { file_type_ = kManifest; - else if (path.MatchesExtension(table_extension)) + } else if (path.MatchesExtension(table_extension)) { file_type_ = kTable; + } parent_dir_ = base::FilePath::FromUTF8Unsafe(fname).DirName().AsUTF8Unsafe(); }
diff --git a/components/leveldb/leveldb_service_unittest.cc b/components/leveldb/leveldb_service_unittest.cc index 893ea6f..f6160c0 100644 --- a/components/leveldb/leveldb_service_unittest.cc +++ b/components/leveldb/leveldb_service_unittest.cc
@@ -10,8 +10,8 @@ #include "components/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/common/common_type_converters.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "services/shell/public/cpp/shell_connection.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_context.h" +#include "services/shell/public/cpp/service_test.h" using filesystem::mojom::FileError; @@ -35,15 +35,15 @@ return base::Bind(&DoCaptures<T1, T2>, t1, t2); } -class LevelDBServiceTest : public shell::test::ShellTest { +class LevelDBServiceTest : public shell::test::ServiceTest { public: - LevelDBServiceTest() : ShellTest("exe:leveldb_service_unittests") {} + LevelDBServiceTest() : ServiceTest("exe:leveldb_service_unittests") {} ~LevelDBServiceTest() override {} protected: // Overridden from mojo::test::ApplicationTestBase: void SetUp() override { - ShellTest::SetUp(); + ServiceTest::SetUp(); connector()->ConnectToInterface("mojo:filesystem", &files_); connector()->ConnectToInterface("mojo:leveldb", &leveldb_); } @@ -51,7 +51,7 @@ void TearDown() override { leveldb_.reset(); files_.reset(); - ShellTest::TearDown(); + ServiceTest::TearDown(); } // Note: This has an out parameter rather than returning the |DirectoryPtr|,
diff --git a/components/leveldb/remote_iterator_unittest.cc b/components/leveldb/remote_iterator_unittest.cc index bd61679..884915b 100644 --- a/components/leveldb/remote_iterator_unittest.cc +++ b/components/leveldb/remote_iterator_unittest.cc
@@ -8,8 +8,8 @@ #include "components/leveldb/public/cpp/remote_iterator.h" #include "components/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/common/common_type_converters.h" -#include "services/shell/public/cpp/shell_connection.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_context.h" +#include "services/shell/public/cpp/service_test.h" namespace leveldb { namespace { @@ -22,15 +22,15 @@ return base::Bind(&DoCapture<T1>, t1); } -class RemoteIteratorTest : public shell::test::ShellTest { +class RemoteIteratorTest : public shell::test::ServiceTest { public: - RemoteIteratorTest() : ShellTest("exe:leveldb_service_unittests") {} + RemoteIteratorTest() : ServiceTest("exe:leveldb_service_unittests") {} ~RemoteIteratorTest() override {} protected: // Overridden from mojo::test::ApplicationTestBase: void SetUp() override { - ShellTest::SetUp(); + ServiceTest::SetUp(); connector()->ConnectToInterface("mojo:leveldb", &leveldb_); mojom::DatabaseError error; @@ -53,7 +53,7 @@ void TearDown() override { leveldb_.reset(); - ShellTest::TearDown(); + ServiceTest::TearDown(); } mojom::LevelDBServicePtr& leveldb() { return leveldb_; }
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc index bca6885..f2f70aef 100644 --- a/components/network_session_configurator/network_session_configurator.cc +++ b/components/network_session_configurator/network_session_configurator.cc
@@ -45,11 +45,6 @@ const char kSpdyFieldTrialSpdy4GroupNamePrefix[] = "Spdy4Enabled"; const char kSpdyFieldTrialParametrizedPrefix[] = "Parametrized"; -// Field trial for NPN. -const char kNpnTrialName[] = "NPN"; -const char kNpnTrialEnabledGroupNamePrefix[] = "Enable"; -const char kNpnTrialDisabledGroupNamePrefix[] = "Disable"; - // Field trial for priority dependencies. const char kSpdyDependenciesFieldTrial[] = "SpdyEnableDependencies"; const char kSpdyDependenciesFieldTrialEnable[] = "Enable"; @@ -140,16 +135,6 @@ } } -void ConfigureNPNParams(const base::CommandLine& command_line, - base::StringPiece npn_trial_group, - net::HttpNetworkSession::Params* params) { - if (npn_trial_group.starts_with(kNpnTrialEnabledGroupNamePrefix)) { - params->enable_npn = true; - } else if (npn_trial_group.starts_with(kNpnTrialDisabledGroupNamePrefix)) { - params->enable_npn = false; - } -} - void ConfigurePriorityDependencies( base::StringPiece priority_dependencies_trial_group, net::HttpNetworkSession::Params* params) { @@ -548,10 +533,6 @@ base::FieldTrialList::FindFullName(kTCPFastOpenFieldTrialName); ConfigureTCPFastOpenParams(tfo_trial_group, params); - std::string npn_trial_group = - base::FieldTrialList::FindFullName(kNpnTrialName); - ConfigureNPNParams(command_line, npn_trial_group, params); - std::string priority_dependencies_trial_group = base::FieldTrialList::FindFullName(kSpdyDependenciesFieldTrial); ConfigurePriorityDependencies(priority_dependencies_trial_group, params);
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc index df8a77c..604c0461 100644 --- a/components/network_session_configurator/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -58,7 +58,6 @@ EXPECT_TRUE(params_.enable_http2); EXPECT_FALSE(params_.enable_tcp_fast_open_for_ssl); EXPECT_TRUE(params_.enable_quic_alternative_service_with_different_host); - EXPECT_FALSE(params_.enable_npn); EXPECT_TRUE(params_.enable_priority_dependencies); EXPECT_FALSE(params_.enable_quic); } @@ -145,22 +144,6 @@ EXPECT_TRUE(params_.enable_http2); } -TEST_F(NetworkSessionConfiguratorTest, NPNFieldTrialEnabled) { - base::FieldTrialList::CreateFieldTrial("NPN", "Enable-experiment"); - - ParseFieldTrials(); - - EXPECT_TRUE(params_.enable_npn); -} - -TEST_F(NetworkSessionConfiguratorTest, NPNFieldTrialDisabled) { - base::FieldTrialList::CreateFieldTrial("NPN", "Disable-holdback"); - - ParseFieldTrials(); - - EXPECT_FALSE(params_.enable_npn); -} - TEST_F(NetworkSessionConfiguratorTest, PriorityDependenciesTrialEnabled) { base::FieldTrialList::CreateFieldTrial("SpdyEnableDependencies", "Enable-experiment");
diff --git a/components/ntp_snippets/ntp_snippets_service.cc b/components/ntp_snippets/ntp_snippets_service.cc index 08f4203..4b18a58 100644 --- a/components/ntp_snippets/ntp_snippets_service.cc +++ b/components/ntp_snippets/ntp_snippets_service.cc
@@ -139,7 +139,11 @@ exploded.minute = 0; exploded.second = 0; exploded.millisecond = 0; - base::Time reschedule = base::Time::FromLocalExploded(exploded); + base::Time reschedule; + if (!base::Time::FromLocalExploded(exploded, &reschedule)) { + return GetRescheduleTime(now + base::TimeDelta::FromDays(1)); + } + if (next_day) reschedule += base::TimeDelta::FromDays(1);
diff --git a/components/ntp_snippets/ntp_snippets_service_unittest.cc b/components/ntp_snippets/ntp_snippets_service_unittest.cc index 2b87e730..9ba767d 100644 --- a/components/ntp_snippets/ntp_snippets_service_unittest.cc +++ b/components/ntp_snippets/ntp_snippets_service_unittest.cc
@@ -67,7 +67,9 @@ const float kSnippetScore = 5.0; base::Time GetDefaultCreationTime() { - return base::Time::FromUTCExploded(kDefaultCreationTime); + base::Time out_time; + EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time)); + return out_time; } base::Time GetDefaultExpirationTime() {
diff --git a/components/offline_pages/offline_page_model_impl.cc b/components/offline_pages/offline_page_model_impl.cc index 78cf6eb..8642ab13 100644 --- a/components/offline_pages/offline_page_model_impl.cc +++ b/components/offline_pages/offline_page_model_impl.cc
@@ -740,8 +740,13 @@ } InformSavePageDone(callback, result, offline_page.client_id, offline_page.offline_id); - DeletePendingArchiver(archiver); + if (result == SavePageResult::SUCCESS) { + DeleteExistingPagesWithSameURL(offline_page); + } else { + PostClearStorageIfNeededTask(); + } + DeletePendingArchiver(archiver); FOR_EACH_OBSERVER(Observer, observers_, OfflinePageModelChanged(this)); } @@ -808,30 +813,31 @@ ReportSavePageResultHistogramAfterSave(client_id, result); archive_manager_->GetStorageStats( base::Bind(&ReportStorageHistogramsAfterSave)); - // Remove existing pages generated by the same policy and with same url. - size_t pages_allowed = - policy_controller_->GetPolicy(client_id.name_space).pages_allowed_per_url; - if (result == SavePageResult::SUCCESS && pages_allowed != kUnlimitedPages) { - GetPagesByOnlineURL( - offline_pages_[offline_id].url, - base::Bind(&OfflinePageModelImpl::OnPagesFoundWithSameURL, - weak_ptr_factory_.GetWeakPtr(), client_id, offline_id, - pages_allowed)); - } else { - PostClearStorageIfNeededTask(); - } callback.Run(result, offline_id); } +void OfflinePageModelImpl::DeleteExistingPagesWithSameURL( + const OfflinePageItem& offline_page) { + // Remove existing pages generated by the same policy and with same url. + size_t pages_allowed = + policy_controller_->GetPolicy(offline_page.client_id.name_space) + .pages_allowed_per_url; + if (pages_allowed == kUnlimitedPages) + return; + GetPagesByOnlineURL( + offline_page.url, + base::Bind(&OfflinePageModelImpl::OnPagesFoundWithSameURL, + weak_ptr_factory_.GetWeakPtr(), offline_page, pages_allowed)); +} + void OfflinePageModelImpl::OnPagesFoundWithSameURL( - const ClientId& client_id, - int64_t offline_id, + const OfflinePageItem& offline_page, size_t pages_allowed, const MultipleOfflinePageItemResult& items) { std::vector<OfflinePageItem> pages_to_delete; for (const auto& item : items) { - if (item.offline_id != offline_id && - item.client_id.name_space == client_id.name_space) { + if (item.offline_id != offline_page.offline_id && + item.client_id.name_space == offline_page.client_id.name_space) { pages_to_delete.push_back(item); } }
diff --git a/components/offline_pages/offline_page_model_impl.h b/components/offline_pages/offline_page_model_impl.h index afda58c..1efb687 100644 --- a/components/offline_pages/offline_page_model_impl.h +++ b/components/offline_pages/offline_page_model_impl.h
@@ -214,8 +214,8 @@ bool success); // Callbacks for deleting pages with same URL when saving pages. - void OnPagesFoundWithSameURL(const ClientId& client_id, - int64_t offline_id, + void DeleteExistingPagesWithSameURL(const OfflinePageItem& offline_page); + void OnPagesFoundWithSameURL(const OfflinePageItem& offline_page, size_t pages_allowed, const MultipleOfflinePageItemResult& items); void OnDeleteOldPagesWithSameURL(DeletePageResult result);
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index ae8f2c8c..cea5a58c 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -227,12 +227,26 @@ std::string demotion_rule = OmniboxFieldTrial::GetValueForRuleInContext( kDemoteByTypeRule, current_page_classification); // If there is no demotion rule for this context, then use the default - // value for that context. At the moment the default value is non-empty - // only for the fakebox-focus context. - if (demotion_rule.empty() && - (current_page_classification == - OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS)) - demotion_rule = "1:61,2:61,3:61,4:61,16:61"; + // value for that context. + if (demotion_rule.empty()) { + // This rule demotes URLs as strongly as possible without violating user + // expectations. In particular, for URL-seeking inputs, if the user would + // likely expect a URL first (i.e., it would be inline autocompleted), then + // that URL will still score strongly enough to be first. This is done + // using a demotion multipler of 0.61. If a URL would get a score high + // enough to be inline autocompleted (1400+), even after demotion it will + // score above 850 ( 1400 * 0.61 > 850). 850 is the maximum score for + // queries when the input has been detected as URL-seeking. + constexpr char kDemoteURLs[] = "1:61,2:61,3:61,4:61,16:61"; +#if defined(OS_ANDROID) + if (current_page_classification == OmniboxEventProto:: + SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT) + demotion_rule = kDemoteURLs; +#endif + if (current_page_classification == + OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) + demotion_rule = kDemoteURLs; + } // The value of the DemoteByType rule is a comma-separated list of // {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType::
diff --git a/components/os_crypt/os_crypt_posix.cc b/components/os_crypt/os_crypt_posix.cc index 44f04b3..24a411e 100644 --- a/components/os_crypt/os_crypt_posix.cc +++ b/components/os_crypt/os_crypt_posix.cc
@@ -9,6 +9,7 @@ #include <memory> #include "base/logging.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "crypto/encryptor.h" #include "crypto/symmetric_key.h" @@ -118,7 +119,8 @@ // old data saved as clear text and we'll return it directly. // Credit card numbers are current legacy data, so false match with prefix // won't happen. - if (ciphertext.find(kObfuscationPrefix) != 0) { + if (!base::StartsWith(ciphertext, kObfuscationPrefix, + base::CompareCase::SENSITIVE)) { *plaintext = ciphertext; return true; }
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 9842dc2..1ffb69d 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -177,7 +177,11 @@ form.signon_realm == "https://www.google.com/")) { static const base::Time::Exploded exploded_cutoff = { 2012, 1, 0, 1, 0, 0, 0, 0 }; // 00:00 Jan 1 2012 - ignore_logins_cutoff = base::Time::FromUTCExploded(exploded_cutoff); + base::Time out_time; + bool conversion_success = + base::Time::FromUTCExploded(exploded_cutoff, &out_time); + DCHECK(conversion_success); + ignore_logins_cutoff = out_time; } std::unique_ptr<GetLoginsRequest> request(new GetLoginsRequest(consumer)); request->set_ignore_logins_cutoff(ignore_logins_cutoff);
diff --git a/components/password_manager/core/browser/password_store_change.cc b/components/password_manager/core/browser/password_store_change.cc index 950f55c..c5c82e08 100644 --- a/components/password_manager/core/browser/password_store_change.cc +++ b/components/password_manager/core/browser/password_store_change.cc
@@ -9,7 +9,7 @@ std::ostream& operator<<(std::ostream& os, const PasswordStoreChange& password_store_change) { return os << "type: " << password_store_change.type() - << "password form: " << password_store_change.form(); + << ", password form: " << password_store_change.form(); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_change.h b/components/password_manager/core/browser/password_store_change.h index 90211ef..0d37f9d 100644 --- a/components/password_manager/core/browser/password_store_change.h +++ b/components/password_manager/core/browser/password_store_change.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CHANGE_H__ #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_STORE_CHANGE_H__ +#include <ostream> #include <vector> #include "components/autofill/core/common/password_form.h"
diff --git a/components/password_manager/core/browser/password_store_default_unittest.cc b/components/password_manager/core/browser/password_store_default_unittest.cc index 9648d2a..884adda 100644 --- a/components/password_manager/core/browser/password_store_default_unittest.cc +++ b/components/password_manager/core/browser/password_store_default_unittest.cc
@@ -61,20 +61,18 @@ }; PasswordFormData CreateTestPasswordFormData() { - PasswordFormData data = { - PasswordForm::SCHEME_HTML, - "http://bar.example.com", - "http://bar.example.com/origin", - "http://bar.example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"username_value", - L"password_value", - true, - false, - 1 - }; + PasswordFormData data = {PasswordForm::SCHEME_HTML, + "http://bar.example.com", + "http://bar.example.com/origin", + "http://bar.example.com/action", + L"submit_element", + L"username_element", + L"password_element", + L"username_value", + L"password_value", + true, + false, + 1}; return data; } @@ -168,16 +166,10 @@ // Some non-ASCII password form data. static const PasswordFormData form_data[] = { - { PasswordForm::SCHEME_HTML, - "http://foo.example.com", - "http://foo.example.com/origin", - "http://foo.example.com/action", - L"มีสีสัน", - L"お元気ですか?", - L"盆栽", - L"أحب كرة", - L"£éä국수çà", - true, false, 1 }, + {PasswordForm::SCHEME_HTML, "http://foo.example.com", + "http://foo.example.com/origin", "http://foo.example.com/action", + L"มีสีสัน", L"お元気ですか?", L"盆栽", L"أحب كرة", L"£éä국수çà", true, + false, 1}, }; // Build the expected forms vector and add the forms to the store. @@ -212,7 +204,7 @@ store->AddObserver(&observer); const PasswordStoreChange expected_add_changes[] = { - PasswordStoreChange(PasswordStoreChange::ADD, *form), + PasswordStoreChange(PasswordStoreChange::ADD, *form), }; EXPECT_CALL(observer, @@ -226,7 +218,7 @@ form->password_value = base::ASCIIToUTF16("a different password"); const PasswordStoreChange expected_update_changes[] = { - PasswordStoreChange(PasswordStoreChange::UPDATE, *form), + PasswordStoreChange(PasswordStoreChange::UPDATE, *form), }; EXPECT_CALL(observer, @@ -237,7 +229,7 @@ base::RunLoop().RunUntilIdle(); const PasswordStoreChange expected_delete_changes[] = { - PasswordStoreChange(PasswordStoreChange::REMOVE, *form), + PasswordStoreChange(PasswordStoreChange::REMOVE, *form), }; EXPECT_CALL(observer,
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index c2b44a4..ac22a33 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -87,9 +87,7 @@ class PasswordStoreTest : public testing::Test { protected: - void SetUp() override { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - } + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } void TearDown() override { ASSERT_TRUE(temp_dir_.Delete()); } @@ -113,61 +111,34 @@ const time_t cutoff = 1325376000; // 00:00 Jan 1 2012 UTC static const PasswordFormData form_data[] = { - // A form on https://www.google.com/ older than the cutoff. Will be ignored. - { PasswordForm::SCHEME_HTML, - "https://www.google.com", - "https://www.google.com/origin", - "https://www.google.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"username_value_1", - L"", - true, true, cutoff - 1 }, - // A form on https://www.google.com/ older than the cutoff. Will be ignored. - { PasswordForm::SCHEME_HTML, - "https://www.google.com", - "https://www.google.com/origin", - "https://www.google.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"username_value_2", - L"", - true, true, cutoff - 1 }, - // A form on https://www.google.com/ newer than the cutoff. - { PasswordForm::SCHEME_HTML, - "https://www.google.com", - "https://www.google.com/origin", - "https://www.google.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"username_value_3", - L"", - true, true, cutoff + 1 }, - // A form on https://accounts.google.com/ older than the cutoff. - { PasswordForm::SCHEME_HTML, - "https://accounts.google.com", - "https://accounts.google.com/origin", - "https://accounts.google.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"username_value", - L"", - true, true, cutoff - 1 }, - // A form on http://bar.example.com/ older than the cutoff. - { PasswordForm::SCHEME_HTML, - "http://bar.example.com", - "http://bar.example.com/origin", - "http://bar.example.com/action", - L"submit_element", - L"username_element", - L"password_element", - L"username_value", - L"", - true, false, cutoff - 1 }, + // A form on https://www.google.com/ older than the cutoff. Will be + // ignored. + {PasswordForm::SCHEME_HTML, "https://www.google.com", + "https://www.google.com/origin", "https://www.google.com/action", + L"submit_element", L"username_element", L"password_element", + L"username_value_1", L"", true, true, cutoff - 1}, + // A form on https://www.google.com/ older than the cutoff. Will be + // ignored. + {PasswordForm::SCHEME_HTML, "https://www.google.com", + "https://www.google.com/origin", "https://www.google.com/action", + L"submit_element", L"username_element", L"password_element", + L"username_value_2", L"", true, true, cutoff - 1}, + // A form on https://www.google.com/ newer than the cutoff. + {PasswordForm::SCHEME_HTML, "https://www.google.com", + "https://www.google.com/origin", "https://www.google.com/action", + L"submit_element", L"username_element", L"password_element", + L"username_value_3", L"", true, true, cutoff + 1}, + // A form on https://accounts.google.com/ older than the cutoff. + {PasswordForm::SCHEME_HTML, "https://accounts.google.com", + "https://accounts.google.com/origin", + "https://accounts.google.com/action", L"submit_element", + L"username_element", L"password_element", L"username_value", L"", true, + true, cutoff - 1}, + // A form on http://bar.example.com/ older than the cutoff. + {PasswordForm::SCHEME_HTML, "http://bar.example.com", + "http://bar.example.com/origin", "http://bar.example.com/action", + L"submit_element", L"username_element", L"password_element", + L"username_value", L"", true, false, cutoff - 1}, }; // Build the forms vector and add the forms to the store.
diff --git a/components/policy/BUILD.gn b/components/policy/BUILD.gn index c2c7ea51..312d048 100644 --- a/components/policy/BUILD.gn +++ b/components/policy/BUILD.gn
@@ -330,7 +330,6 @@ ] args = [ - "xcrun", "plutil", "-convert", "xml1",
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.cc b/components/policy/core/common/cloud/cloud_policy_constants.cc index be383dbf..46ecf6b 100644 --- a/components/policy/core/common/cloud/cloud_policy_constants.cc +++ b/components/policy/core/common/cloud/cloud_policy_constants.cc
@@ -93,8 +93,6 @@ const char kPolicyVerificationKeyHash[] = "1:356l7w"; std::string GetPolicyVerificationKey() { - // Disable key verification by default until production servers generate - // the proper signatures. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kDisablePolicyKeyVerification)) { return std::string();
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index 33fd48a..683bf39 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -32,6 +32,7 @@ #include "printing/metafile_skia_wrapper.h" #include "printing/pdf_metafile_skia.h" #include "printing/units.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/web/WebConsoleMessage.h" @@ -751,7 +752,9 @@ // When loading is done this will call didStopLoading() and that will do the // actual printing. - frame()->loadRequest(blink::WebURLRequest(GURL(url_str))); + blink::WebURLRequest request = blink::WebURLRequest(GURL(url_str)); + request.setRequestorOrigin(blink::WebSecurityOrigin::createUnique()); + frame()->loadRequest(request); } bool PrepareFrameAndViewForPrint::allowsBrokenNullLayerTreeView() const {
diff --git a/components/proximity_auth/remote_device_loader.cc b/components/proximity_auth/remote_device_loader.cc index efb9fc9..7fe98c7 100644 --- a/components/proximity_auth/remote_device_loader.cc +++ b/components/proximity_auth/remote_device_loader.cc
@@ -88,7 +88,7 @@ user_id_, unlock_key.friendly_device_name(), unlock_key.public_key(), bluetooth_type, bluetooth_address, psk, std::string())); - if (!remaining_unlock_keys_.size()) + if (remaining_unlock_keys_.empty()) callback_.Run(remote_devices_); }
diff --git a/components/safe_browsing_db/util.cc b/components/safe_browsing_db/util.cc index 3289aaae..74eb45e4 100644 --- a/components/safe_browsing_db/util.cc +++ b/components/safe_browsing_db/util.cc
@@ -403,8 +403,7 @@ // We may have /foo as path-prefix in the whitelist which should // also match with /foo/bar and /foo?bar. Hence, for every path // that ends in '/' we also add the path without the slash. - if (include_whitelist_hashes && path.size() > 1 && - path[path.size() - 1] == '/') { + if (include_whitelist_hashes && path.size() > 1 && path.back() == '/') { full_hashes->push_back(SBFullHashForString( host + path.substr(0, path.size() - 1))); }
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc index 0920f2b..2ef5c03 100644 --- a/components/safe_browsing_db/v4_store.cc +++ b/components/safe_browsing_db/v4_store.cc
@@ -67,8 +67,8 @@ std::string state_base64; base::Base64Encode(state_, &state_base64); - return base::StringPrintf("path: %s; state: %s", store_path_.value().c_str(), - state_base64.c_str()); + return base::StringPrintf("path: %" PRIsFP "; state: %s", + store_path_.value().c_str(), state_base64.c_str()); } bool V4Store::Reset() {
diff --git a/components/scheduler/BUILD.gn b/components/scheduler/BUILD.gn index 35138e7..236b9a436 100644 --- a/components/scheduler/BUILD.gn +++ b/components/scheduler/BUILD.gn
@@ -13,6 +13,8 @@ "base/lazy_now.h", "base/pollable_thread_safe_flag.cc", "base/pollable_thread_safe_flag.h", + "base/queueing_time_estimator.cc", + "base/queueing_time_estimator.h", "base/real_time_domain.cc", "base/real_time_domain.h", "base/task_queue.h", @@ -23,6 +25,7 @@ "base/task_queue_manager_delegate.h", "base/task_queue_selector.cc", "base/task_queue_selector.h", + "base/task_time_tracker.h", "base/time_domain.cc", "base/time_domain.h", "base/virtual_time_domain.cc", @@ -119,12 +122,14 @@ testonly = true sources = [ + "base/queueing_time_estimator_unittest.cc", "base/task_queue_manager_delegate_for_test.cc", "base/task_queue_manager_delegate_for_test.h", "base/task_queue_manager_unittest.cc", "base/task_queue_selector_unittest.cc", - "base/test_always_fail_time_source.cc", - "base/test_always_fail_time_source.h", + "base/test_count_uses_time_source.cc", + "base/test_count_uses_time_source.h", + "base/test_task_time_tracker.h", "base/test_time_source.cc", "base/test_time_source.h", "base/time_domain_unittest.cc",
diff --git a/components/scheduler/base/queueing_time_estimator.cc b/components/scheduler/base/queueing_time_estimator.cc new file mode 100644 index 0000000..1402380 --- /dev/null +++ b/components/scheduler/base/queueing_time_estimator.cc
@@ -0,0 +1,87 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/scheduler/base/queueing_time_estimator.h" + +#include "base/time/default_tick_clock.h" + +namespace scheduler { + +namespace { + +// This method computes the expected queueing time of a randomly distributed +// task R within a window containing a single task T. Let T' be the time range +// for which T overlaps the window. We first compute the probability that R will +// start within T'. We then compute the expected queueing duration if R does +// start within this range. Since the start time of R is uniformly distributed +// within the window, this is equal to the average of the queueing times if R +// started at the beginning or end of T'. The expected queueing time of T is the +// probability that R will start within T', multiplied by the expected queueing +// duration if R does fall in this range. +base::TimeDelta ExpectedQueueingTimeFromTask(base::TimeTicks task_start, + base::TimeTicks task_end, + base::TimeTicks window_start, + base::TimeTicks window_end) { + DCHECK(task_start <= task_end); + DCHECK(task_start <= window_end); + DCHECK(window_start < window_end); + DCHECK(task_end >= window_start); + base::TimeTicks task_in_window_start_time = + std::max(task_start, window_start); + base::TimeTicks task_in_window_end_time = + std::min(task_end, window_end); + DCHECK(task_in_window_end_time <= task_in_window_end_time); + + double probability_of_this_task = + static_cast<double>((task_in_window_end_time - task_in_window_start_time) + .InMicroseconds()) / + (window_end - window_start).InMicroseconds(); + + base::TimeDelta expected_queueing_duration_within_task = + ((task_end - task_in_window_start_time) + + (task_end - task_in_window_end_time)) / + 2; + + return base::TimeDelta::FromMillisecondsD( + probability_of_this_task * + expected_queueing_duration_within_task.InMillisecondsF()); +} + +} // namespace + +QueueingTimeEstimator::QueueingTimeEstimator( + QueueingTimeEstimator::Client* client, + base::TimeDelta window_duration) + : client_(client), + window_duration_(window_duration), + window_start_time_() {} + +void QueueingTimeEstimator::OnToplevelTaskCompleted( + base::TimeTicks task_start_time, + base::TimeTicks task_end_time) { + if (window_start_time_.is_null()) + window_start_time_ = task_start_time; + + while (TimePastWindowEnd(task_end_time)) { + if (!TimePastWindowEnd(task_start_time)) { + // Include the current task in this window. + current_expected_queueing_time_ += ExpectedQueueingTimeFromTask( + task_start_time, task_end_time, window_start_time_, + window_start_time_ + window_duration_); + } + client_->OnQueueingTimeForWindowEstimated(current_expected_queueing_time_); + window_start_time_ += window_duration_; + current_expected_queueing_time_ = base::TimeDelta(); + } + + current_expected_queueing_time_ += ExpectedQueueingTimeFromTask( + task_start_time, task_end_time, window_start_time_, + window_start_time_ + window_duration_); +} + +bool QueueingTimeEstimator::TimePastWindowEnd(base::TimeTicks time) { + return time > window_start_time_ + window_duration_; +} + +} // namespace scheduler
diff --git a/components/scheduler/base/queueing_time_estimator.h b/components/scheduler/base/queueing_time_estimator.h new file mode 100644 index 0000000..2d302ea --- /dev/null +++ b/components/scheduler/base/queueing_time_estimator.h
@@ -0,0 +1,53 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SCHEDULER_RENDERER_QUEUEING_TIME_ESTIMATOR_H_ +#define COMPONENTS_SCHEDULER_RENDERER_QUEUEING_TIME_ESTIMATOR_H_ + +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/time/time.h" +#include "components/scheduler/scheduler_export.h" + +namespace base { +class TickClock; +} + +namespace scheduler { + +// Records the expected queueing time for a high priority task occurring +// randomly during each interval of length |window_duration|. +class SCHEDULER_EXPORT QueueingTimeEstimator { + public: + class SCHEDULER_EXPORT Client { + public: + virtual void OnQueueingTimeForWindowEstimated( + base::TimeDelta queueing_time) = 0; + Client() {} + virtual ~Client() {} + + private: + DISALLOW_COPY_AND_ASSIGN(Client); + }; + + QueueingTimeEstimator(Client* client, + base::TimeDelta window_duration); + + void OnToplevelTaskCompleted(base::TimeTicks task_start_time, + base::TimeTicks task_end_time); + + private: + bool TimePastWindowEnd(base::TimeTicks task_end_time); + Client* client_; // NOT OWNED. + + base::TimeDelta current_expected_queueing_time_; + base::TimeDelta window_duration_; + base::TimeTicks window_start_time_; + + DISALLOW_COPY_AND_ASSIGN(QueueingTimeEstimator); +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_RENDERER_QUEUEING_TIME_ESTIMATOR_H_
diff --git a/components/scheduler/base/queueing_time_estimator_unittest.cc b/components/scheduler/base/queueing_time_estimator_unittest.cc new file mode 100644 index 0000000..c9df20b29 --- /dev/null +++ b/components/scheduler/base/queueing_time_estimator_unittest.cc
@@ -0,0 +1,94 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/scheduler/base/queueing_time_estimator.h" +#include "components/scheduler/base/test_time_source.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace scheduler { + +using QueueingTimeEstimatorTest = testing::Test; + +class TestQueueingTimeEstimatorClient + : public QueueingTimeEstimator::Client { + public: + void OnQueueingTimeForWindowEstimated( + base::TimeDelta queueing_time) override { + expected_queueing_times_.push_back(queueing_time); + } + const std::vector<base::TimeDelta>& expected_queueing_times() { + return expected_queueing_times_; + } + + private: + std::vector<base::TimeDelta> expected_queueing_times_; +}; + +class QueueingTimeEstimatorForTest : public QueueingTimeEstimator { + public: + QueueingTimeEstimatorForTest(TestQueueingTimeEstimatorClient* client, + base::TimeDelta window_duration) + : QueueingTimeEstimator(client, window_duration) {} +}; + +// Three tasks of one second each, all within a 5 second window. Expected +// queueing time is the probability of falling into one of these tasks (3/5), +// multiplied by the expected queueing time within a task (0.5 seconds). Thus we +// expect a queueing time of 0.3 seconds. +TEST_F(QueueingTimeEstimatorTest, AllTasksWithinWindow) { + base::TimeTicks time; + TestQueueingTimeEstimatorClient client; + QueueingTimeEstimatorForTest estimator(&client, + base::TimeDelta::FromSeconds(5)); + for (int i = 0; i < 3; ++i) { + estimator.OnToplevelTaskCompleted( + time, time + base::TimeDelta::FromMilliseconds(1000)); + time += base::TimeDelta::FromMilliseconds(1500); + } + + // Flush the data by adding a task in the next window. + time += base::TimeDelta::FromMilliseconds(5000); + estimator.OnToplevelTaskCompleted( + time, time + base::TimeDelta::FromMilliseconds(500)); + + EXPECT_THAT(client.expected_queueing_times(), + testing::ElementsAre(base::TimeDelta::FromMilliseconds(300))); +} + +// One 20 second long task, starting 3 seconds into the first window. +// Window 1: Probability of being within task = 2/5. Expected delay within task: +// avg(20, 18). Total expected queueing time = 7.6s. +// Window 2: Probability of being within task = 1. Expected delay within task: +// avg(18, 13). Total expected queueing time = 15.5s. +// Window 5: Probability of being within task = 3/5. Expected delay within task: +// avg(3, 0). Total expected queueing time = 0.9s. +TEST_F(QueueingTimeEstimatorTest, MultiWindowTask) { + TestQueueingTimeEstimatorClient client; + QueueingTimeEstimatorForTest estimator(&client, + base::TimeDelta::FromSeconds(5)); + base::TimeTicks time; + time += base::TimeDelta::FromMilliseconds(5000); + estimator.OnToplevelTaskCompleted(time, time); + + time += base::TimeDelta::FromMilliseconds(3000); + + estimator.OnToplevelTaskCompleted( + time, time + base::TimeDelta::FromMilliseconds(20000)); + + // Flush the data by adding a task in the next window. + time += base::TimeDelta::FromMilliseconds(25000); + + estimator.OnToplevelTaskCompleted( + time, time + base::TimeDelta::FromMilliseconds(500)); + + EXPECT_THAT(client.expected_queueing_times(), + testing::ElementsAre(base::TimeDelta::FromMilliseconds(7600), + base::TimeDelta::FromMilliseconds(15500), + base::TimeDelta::FromMilliseconds(10500), + base::TimeDelta::FromMilliseconds(5500), + base::TimeDelta::FromMilliseconds(900))); +} + +} // namespace scheduler
diff --git a/components/scheduler/base/task_queue_impl.cc b/components/scheduler/base/task_queue_impl.cc index c3f1d8a..c8ce1e9 100644 --- a/components/scheduler/base/task_queue_impl.cc +++ b/components/scheduler/base/task_queue_impl.cc
@@ -219,32 +219,32 @@ } void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( - const Task& pending_task, + Task pending_task, base::TimeTicks now) { main_thread_only().task_queue_manager->DidQueueTask(pending_task); // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. - main_thread_only().delayed_incoming_queue.push(pending_task); + base::TimeTicks delayed_run_time = pending_task.delayed_run_time; + main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); main_thread_only().time_domain->ScheduleDelayedWork( - this, pending_task.delayed_run_time, now); + this, delayed_run_time, now); TraceQueueSize(false); } -void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked( - const Task& pending_task) { +void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { any_thread().task_queue_manager->DidQueueTask(pending_task); int thread_hop_task_sequence_number = any_thread().task_queue_manager->GetNextSequenceNumber(); PushOntoImmediateIncomingQueueLocked(Task( FROM_HERE, - base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, pending_task), + base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, + base::Passed(&pending_task)), base::TimeTicks(), thread_hop_task_sequence_number, false, thread_hop_task_sequence_number)); } -void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( - const Task& pending_task) { +void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { if (any_thread().immediate_incoming_queue.empty()) any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); if (any_thread().pump_policy == PumpPolicy::AUTO && @@ -252,15 +252,16 @@ any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); } any_thread().task_queue_manager->DidQueueTask(pending_task); - any_thread().immediate_incoming_queue.push(pending_task); + any_thread().immediate_incoming_queue.push(std::move(pending_task)); TraceQueueSize(true); } -void TaskQueueImpl::ScheduleDelayedWorkTask(const Task& pending_task) { +void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { DCHECK(main_thread_checker_.CalledOnValidThread()); - main_thread_only().delayed_incoming_queue.push(pending_task); + base::TimeTicks delayed_run_time = pending_task.delayed_run_time; + main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); main_thread_only().time_domain->ScheduleDelayedWork( - this, pending_task.delayed_run_time, + this, delayed_run_time, main_thread_only().time_domain->Now()); } @@ -667,21 +668,32 @@ // static void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, base::trace_event::TracedValue* state) { - std::queue<Task> queue_copy(queue); - while (!queue_copy.empty()) { - TaskAsValueInto(queue_copy.front(), state); - queue_copy.pop(); + // Remove const to search |queue| in the destructive manner. Restore the + // content from |visited| later. + std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue); + std::queue<Task> visited; + while (!mutable_queue->empty()) { + TaskAsValueInto(mutable_queue->front(), state); + visited.push(std::move(mutable_queue->front())); + mutable_queue->pop(); } + *mutable_queue = std::move(visited); } // static void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, base::trace_event::TracedValue* state) { - std::priority_queue<Task> queue_copy(queue); - while (!queue_copy.empty()) { - TaskAsValueInto(queue_copy.top(), state); - queue_copy.pop(); + // Remove const to search |queue| in the destructive manner. Restore the + // content from |visited| later. + std::priority_queue<Task>* mutable_queue = + const_cast<std::priority_queue<Task>*>(&queue); + std::priority_queue<Task> visited; + while (!mutable_queue->empty()) { + TaskAsValueInto(mutable_queue->top(), state); + visited.push(std::move(const_cast<Task&>(mutable_queue->top()))); + mutable_queue->pop(); } + *mutable_queue = std::move(visited); } // static
diff --git a/components/scheduler/base/task_queue_impl.h b/components/scheduler/base/task_queue_impl.h index 69fd02e..3508c623 100644 --- a/components/scheduler/base/task_queue_impl.h +++ b/components/scheduler/base/task_queue_impl.h
@@ -220,14 +220,14 @@ // Push the task onto the |delayed_incoming_queue|. Lock-free main thread // only fast path. - void PushOntoDelayedIncomingQueueFromMainThread(const Task& pending_task, + void PushOntoDelayedIncomingQueueFromMainThread(Task pending_task, base::TimeTicks now); // Push the task onto the |delayed_incoming_queue|. Slow path from other // threads. - void PushOntoDelayedIncomingQueueLocked(const Task& pending_task); + void PushOntoDelayedIncomingQueueLocked(Task pending_task); - void ScheduleDelayedWorkTask(const Task& pending_task); + void ScheduleDelayedWorkTask(Task pending_task); // Enqueues any delayed tasks which should be run now on the // |delayed_work_queue|. Must be called from the main thread. @@ -257,7 +257,7 @@ // Push the task onto the |immediate_incoming_queue| and for auto pumped // queues it calls MaybePostDoWorkOnMainRunner if the Incoming queue was // empty. - void PushOntoImmediateIncomingQueueLocked(const Task& pending_task); + void PushOntoImmediateIncomingQueueLocked(Task pending_task); void TraceQueueSize(bool is_locked) const; static void QueueAsValueInto(const std::queue<Task>& queue,
diff --git a/components/scheduler/base/task_queue_manager.cc b/components/scheduler/base/task_queue_manager.cc index 36f08de..9b1c1a6 100644 --- a/components/scheduler/base/task_queue_manager.cc +++ b/components/scheduler/base/task_queue_manager.cc
@@ -14,6 +14,7 @@ #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_manager_delegate.h" #include "components/scheduler/base/task_queue_selector.h" +#include "components/scheduler/base/task_time_tracker.h" #include "components/scheduler/base/work_queue.h" #include "components/scheduler/base/work_queue_sets.h" @@ -44,6 +45,7 @@ task_was_run_on_quiescence_monitored_queue_(false), work_batch_size_(1), task_count_(0), + task_time_tracker_(nullptr), tracing_category_(tracing_category), disabled_by_default_tracing_category_( disabled_by_default_tracing_category), @@ -128,12 +130,17 @@ void TaskQueueManager::UpdateWorkQueues( bool should_trigger_wakeup, - const internal::TaskQueueImpl::Task* previous_task) { + const internal::TaskQueueImpl::Task* previous_task, + LazyNow lazy_now) { TRACE_EVENT0(disabled_by_default_tracing_category_, "TaskQueueManager::UpdateWorkQueues"); for (TimeDomain* time_domain : time_domains_) { - time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task); + LazyNow lazy_now_in_domain = time_domain == real_time_domain_.get() + ? lazy_now + : time_domain->CreateLazyNow(); + time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task, + lazy_now_in_domain); } } @@ -187,11 +194,18 @@ if (!delegate_->IsNested()) queues_to_delete_.clear(); + LazyNow lazy_now(real_time_domain()->CreateLazyNow()); + base::TimeTicks task_start_time; + + if (!delegate_->IsNested() && task_time_tracker_) + task_start_time = lazy_now.Now(); + // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a // pump-after-wakeup queue. - UpdateWorkQueues(false, nullptr); + UpdateWorkQueues(false, nullptr, lazy_now); internal::TaskQueueImpl::Task previous_task; + for (int i = 0; i < work_batch_size_; i++) { internal::WorkQueue* work_queue; if (!SelectWorkQueueToService(&work_queue)) { @@ -200,6 +214,7 @@ bool should_trigger_wakeup = work_queue->task_queue()->wakeup_policy() == TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES; + switch (ProcessTaskFromWorkQueue(work_queue, &previous_task)) { case ProcessTaskResult::DEFERRED: // If a task was deferred, try again with another task. Note that this @@ -211,9 +226,18 @@ case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: return; // The TaskQueueManager got deleted, we must bail out. } + + lazy_now = real_time_domain()->CreateLazyNow(); + if (!delegate_->IsNested() && task_time_tracker_) { + // Only report top level task durations. + base::TimeTicks task_end_time = lazy_now.Now(); + task_time_tracker_->ReportTaskTime(task_start_time, task_end_time); + task_start_time = task_end_time; + } + work_queue = nullptr; // The queue may have been unregistered. - UpdateWorkQueues(should_trigger_wakeup, &previous_task); + UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); // Only run a single task per batch in nested run loops so that we can // properly exit the nested loop when someone calls RunLoop::Quit(). @@ -304,7 +328,7 @@ } pending_task.task.Reset(); - *out_previous_task = pending_task; + *out_previous_task = std::move(pending_task); return ProcessTaskResult::EXECUTED; }
diff --git a/components/scheduler/base/task_queue_manager.h b/components/scheduler/base/task_queue_manager.h index 1e9eef4..bb938ad 100644 --- a/components/scheduler/base/task_queue_manager.h +++ b/components/scheduler/base/task_queue_manager.h
@@ -38,6 +38,7 @@ class RealTimeDomain; class TimeDomain; class TaskQueueManagerDelegate; +class TaskTimeTracker; // The task queue manager provides N task queues and a selector interface for // choosing which task queue to service next. Each task queue consists of two @@ -82,6 +83,13 @@ // tasks posted to the main loop. The batch size is 1 by default. void SetWorkBatchSize(int work_batch_size); + // When given a non-null TaskTimeTracker, the TaskQueueManager calls its + // ReportTaskTime method for every top level task. The task_time_tracker must + // outlive this object, or be removed via SetTaskTimeTracker(nullptr). + void SetTaskTimeTracker(TaskTimeTracker* task_time_tracker) { + task_time_tracker_ = task_time_tracker; + } + // These functions can only be called on the same thread that the task queue // manager executes its tasks on. void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer); @@ -167,7 +175,8 @@ // run and |should_trigger_wakeup|. Call with an empty |previous_task| if no // task was just run. void UpdateWorkQueues(bool should_trigger_wakeup, - const internal::TaskQueueImpl::Task* previous_task); + const internal::TaskQueueImpl::Task* previous_task, + LazyNow lazy_now); // Chooses the next work queue to service. Returns true if |out_queue| // indicates the queue from which the next task should be run, false to @@ -226,7 +235,7 @@ bool task_was_run_on_quiescence_monitored_queue_; - // To reduce locking overhead we track pending calls to DoWork seperatly for + // To reduce locking overhead we track pending calls to DoWork separately for // the main thread and other threads. std::set<base::TimeTicks> main_thread_pending_wakeups_; @@ -239,6 +248,8 @@ base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; + TaskTimeTracker* task_time_tracker_; // NOT OWNED + const char* tracing_category_; const char* disabled_by_default_tracing_category_; const char* disabled_by_default_verbose_tracing_category_;
diff --git a/components/scheduler/base/task_queue_manager_perftest.cc b/components/scheduler/base/task_queue_manager_perftest.cc index a81fea32..c62ba467 100644 --- a/components/scheduler/base/task_queue_manager_perftest.cc +++ b/components/scheduler/base/task_queue_manager_perftest.cc
@@ -13,6 +13,7 @@ #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_manager_delegate_for_test.h" #include "components/scheduler/base/task_queue_selector.h" +#include "components/scheduler/base/test_task_time_tracker.h" #include "components/scheduler/base/work_queue_sets.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" @@ -41,6 +42,7 @@ message_loop_->task_runner(), base::WrapUnique(new base::DefaultTickClock())), "fake.category", "fake.category", "fake.category.debug")); + manager_->SetTaskTimeTracker(&test_task_time_tracker_); for (size_t i = 0; i < num_queues; i++) queues_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test"))); } @@ -111,6 +113,9 @@ std::unique_ptr<TaskQueueManager> manager_; std::unique_ptr<base::MessageLoop> message_loop_; std::vector<scoped_refptr<base::SingleThreadTaskRunner>> queues_; + // TODO(alexclarke): parameterize so we can measure with and without a + // TaskTimeTracker. + TestTaskTimeTracker test_task_time_tracker_; }; TEST_F(TaskQueueManagerPerfTest, RunTenThousandDelayedTasks_OneQueue) {
diff --git a/components/scheduler/base/task_queue_manager_unittest.cc b/components/scheduler/base/task_queue_manager_unittest.cc index 39baad3..89493b12 100644 --- a/components/scheduler/base/task_queue_manager_unittest.cc +++ b/components/scheduler/base/task_queue_manager_unittest.cc
@@ -23,7 +23,8 @@ #include "components/scheduler/base/task_queue_impl.h" #include "components/scheduler/base/task_queue_manager_delegate_for_test.h" #include "components/scheduler/base/task_queue_selector.h" -#include "components/scheduler/base/test_always_fail_time_source.h" +#include "components/scheduler/base/test_count_uses_time_source.h" +#include "components/scheduler/base/test_task_time_tracker.h" #include "components/scheduler/base/test_time_source.h" #include "components/scheduler/base/virtual_time_domain.h" #include "components/scheduler/base/work_queue.h" @@ -59,6 +60,7 @@ class TaskQueueManagerTest : public testing::Test { public: + TaskQueueManagerTest() {} void DeleteTaskQueueManager() { manager_.reset(); } protected: @@ -69,9 +71,11 @@ main_task_runner_ = TaskQueueManagerDelegateForTest::Create( test_task_runner_.get(), base::WrapUnique(new TestTimeSource(now_src_.get()))); - manager_ = base::WrapUnique( - new TaskQueueManager(main_task_runner_, "test.scheduler", - "test.scheduler", "test.scheduler.debug")); + + manager_ = base::WrapUnique(new TaskQueueManager( + main_task_runner_, "test.scheduler", "test.scheduler", + "test.scheduler.debug")); + manager_->SetTaskTimeTracker(&test_task_time_tracker_); for (size_t i = 0; i < num_queues; i++) runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); @@ -87,10 +91,13 @@ void InitializeWithRealMessageLoop(size_t num_queues) { now_src_.reset(new base::SimpleTestTickClock()); message_loop_.reset(new base::MessageLoop()); + // A null clock triggers some assertions. + now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); manager_ = base::WrapUnique(new TaskQueueManager( MessageLoopTaskRunner::Create( base::WrapUnique(new TestTimeSource(now_src_.get()))), "test.scheduler", "test.scheduler", "test.scheduler.debug")); + manager_->SetTaskTimeTracker(&test_task_time_tracker_); for (size_t i = 0; i < num_queues; i++) runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); @@ -102,6 +109,7 @@ scoped_refptr<cc::OrderedSimpleTaskRunner> test_task_runner_; std::unique_ptr<TaskQueueManager> manager_; std::vector<scoped_refptr<internal::TaskQueueImpl>> runners_; + TestTaskTimeTracker test_task_time_tracker_; }; void PostFromNestedRunloop(base::MessageLoop* message_loop, @@ -120,12 +128,20 @@ void NopTask() {} -TEST_F(TaskQueueManagerTest, NowNotCalledWhenThereAreNoDelayedTasks) { +TEST_F(TaskQueueManagerTest, + NowCalledMinimumNumberOfTimesToComputeTaskDurations) { message_loop_.reset(new base::MessageLoop()); + // This memory is managed by the TaskQueueManager, but we need to hold a + // pointer to this object to read out how many times Now was called. + TestCountUsesTimeSource* test_count_uses_time_source = + new TestCountUsesTimeSource(); + manager_ = base::WrapUnique(new TaskQueueManager( MessageLoopTaskRunner::Create( - base::WrapUnique(new TestAlwaysFailTimeSource())), + base::WrapUnique(test_count_uses_time_source)), "test.scheduler", "test.scheduler", "test.scheduler.debug")); + manager_->SetWorkBatchSize(6); + manager_->SetTaskTimeTracker(&test_task_time_tracker_); for (size_t i = 0; i < 3; i++) runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); @@ -138,6 +154,44 @@ runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); message_loop_->RunUntilIdle(); + // We need to call Now for the beginning of the first task, and then the end + // of every task after. We reuse the end time of one task for the start time + // of the next task. In this case, there were 6 tasks, so we expect 7 calls to + // Now. + EXPECT_EQ(7, test_count_uses_time_source->now_calls_count()); +} + +TEST_F(TaskQueueManagerTest, + NowNotCalledForNestedTasks) { + message_loop_.reset(new base::MessageLoop()); + // This memory is managed by the TaskQueueManager, but we need to hold a + // pointer to this object to read out how many times Now was called. + TestCountUsesTimeSource* test_count_uses_time_source = + new TestCountUsesTimeSource(); + + manager_ = base::WrapUnique(new TaskQueueManager( + MessageLoopTaskRunner::Create( + base::WrapUnique(test_count_uses_time_source)), + "test.scheduler", "test.scheduler", "test.scheduler.debug")); + manager_->SetTaskTimeTracker(&test_task_time_tracker_); + + runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); + + std::vector<std::pair<base::Closure, bool>> tasks_to_post_from_nested_loop; + for (int i = 0; i <= 6; ++i) { + tasks_to_post_from_nested_loop.push_back( + std::make_pair(base::Bind(&NopTask), true)); + } + + runners_[0]->PostTask( + FROM_HERE, base::Bind(&PostFromNestedRunloop, message_loop_.get(), + base::RetainedRef(runners_[0]), + base::Unretained(&tasks_to_post_from_nested_loop))); + + message_loop_->RunUntilIdle(); + // We need to call Now twice, to measure the start and end of the outermost + // task. We shouldn't call it for any of the nested tasks. + EXPECT_EQ(2, test_count_uses_time_source->now_calls_count()); } void NullTask() {}
diff --git a/components/scheduler/base/task_time_tracker.h b/components/scheduler/base/task_time_tracker.h new file mode 100644 index 0000000..8546229 --- /dev/null +++ b/components/scheduler/base/task_time_tracker.h
@@ -0,0 +1,26 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_SCHEDULER_BASE_TASK_TIME_TRACKER_H_ +#define CONTENT_RENDERER_SCHEDULER_BASE_TASK_TIME_TRACKER_H_ + +#include "base/time/time.h" +#include "components/scheduler/scheduler_export.h" + +namespace scheduler { + +class SCHEDULER_EXPORT TaskTimeTracker { + public: + TaskTimeTracker() {} + virtual ~TaskTimeTracker() {} + + virtual void ReportTaskTime(base::TimeTicks startTime, + base::TimeTicks endTime) = 0; + private: + DISALLOW_COPY_AND_ASSIGN(TaskTimeTracker); +}; + +} // namespace scheduler + +#endif // CONTENT_RENDERER_SCHEDULER_BASE_TASK_TIME_TRACKER_H_
diff --git a/components/scheduler/base/test_always_fail_time_source.cc b/components/scheduler/base/test_always_fail_time_source.cc deleted file mode 100644 index 25429845..0000000 --- a/components/scheduler/base/test_always_fail_time_source.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/scheduler/base/test_always_fail_time_source.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace scheduler { - -TestAlwaysFailTimeSource::TestAlwaysFailTimeSource() { -} - -TestAlwaysFailTimeSource::~TestAlwaysFailTimeSource() { -} - -base::TimeTicks TestAlwaysFailTimeSource::NowTicks() { - ADD_FAILURE() << "NowTicks() was called!"; - return base::TimeTicks(); -} - -} // namespace scheduler
diff --git a/components/scheduler/base/test_always_fail_time_source.h b/components/scheduler/base/test_always_fail_time_source.h deleted file mode 100644 index ec6e73d..0000000 --- a/components/scheduler/base/test_always_fail_time_source.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SCHEDULER_BASE_TEST_ALWAYS_FAIL_TIME_SOURCE_H_ -#define COMPONENTS_SCHEDULER_BASE_TEST_ALWAYS_FAIL_TIME_SOURCE_H_ - -#include "base/macros.h" -#include "base/time/tick_clock.h" - -namespace scheduler { - -class TestAlwaysFailTimeSource : public base::TickClock { - public: - explicit TestAlwaysFailTimeSource(); - ~TestAlwaysFailTimeSource() override; - - base::TimeTicks NowTicks() override; - - private: - DISALLOW_COPY_AND_ASSIGN(TestAlwaysFailTimeSource); -}; - -} // namespace scheduler - -#endif // COMPONENTS_SCHEDULER_BASE_TEST_ALWAYS_FAIL_TIME_SOURCE_H_
diff --git a/components/scheduler/base/test_count_uses_time_source.cc b/components/scheduler/base/test_count_uses_time_source.cc new file mode 100644 index 0000000..4175d1aa2 --- /dev/null +++ b/components/scheduler/base/test_count_uses_time_source.cc
@@ -0,0 +1,21 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/scheduler/base/test_count_uses_time_source.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace scheduler { + +TestCountUsesTimeSource::TestCountUsesTimeSource() : now_calls_count_(0) {} + +TestCountUsesTimeSource::~TestCountUsesTimeSource() { +} + +base::TimeTicks TestCountUsesTimeSource::NowTicks() { + now_calls_count_++; + // Don't return 0, as it triggers some assertions. + return base::TimeTicks() + base::TimeDelta::FromSeconds(1); +} + +} // namespace scheduler
diff --git a/components/scheduler/base/test_count_uses_time_source.h b/components/scheduler/base/test_count_uses_time_source.h new file mode 100644 index 0000000..92dbc19 --- /dev/null +++ b/components/scheduler/base/test_count_uses_time_source.h
@@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SCHEDULER_BASE_TEST_COUNT_USES_TIME_SOURCE_H_ +#define COMPONENTS_SCHEDULER_BASE_TEST_COUNT_USES_TIME_SOURCE_H_ + +#include "base/macros.h" +#include "base/time/tick_clock.h" + +namespace scheduler { + +class TestCountUsesTimeSource : public base::TickClock { + public: + explicit TestCountUsesTimeSource(); + ~TestCountUsesTimeSource() override; + + base::TimeTicks NowTicks() override; + int now_calls_count() { return now_calls_count_; } + + private: + DISALLOW_COPY_AND_ASSIGN(TestCountUsesTimeSource); + + int now_calls_count_; +}; + +} // namespace scheduler + +#endif // COMPONENTS_SCHEDULER_BASE_TEST_COUNT_USES_TIME_SOURCE_H_
diff --git a/components/scheduler/base/test_task_time_tracker.h b/components/scheduler/base/test_task_time_tracker.h new file mode 100644 index 0000000..7703e8f --- /dev/null +++ b/components/scheduler/base/test_task_time_tracker.h
@@ -0,0 +1,21 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_SCHEDULER_BASE_TEST_TASK_TIME_TRACKER_H_ +#define CONTENT_RENDERER_SCHEDULER_BASE_TEST_TASK_TIME_TRACKER_H_ + +#include "base/time/time.h" +#include "components/scheduler/base/task_time_tracker.h" + +namespace scheduler { + +class TestTaskTimeTracker : public TaskTimeTracker { + public: + void ReportTaskTime(base::TimeTicks startTime, + base::TimeTicks endTime) override {} +}; + +} // namespace scheduler + +#endif // CONTENT_RENDERER_SCHEDULER_BASE_TEST_TASK_TIME_TRACKER_H_
diff --git a/components/scheduler/base/time_domain.cc b/components/scheduler/base/time_domain.cc index 61851c53..510ad796 100644 --- a/components/scheduler/base/time_domain.cc +++ b/components/scheduler/base/time_domain.cc
@@ -110,9 +110,9 @@ void TimeDomain::UpdateWorkQueues( bool should_trigger_wakeup, - const internal::TaskQueueImpl::Task* previous_task) { + const internal::TaskQueueImpl::Task* previous_task, + LazyNow lazy_now) { DCHECK(main_thread_checker_.CalledOnValidThread()); - LazyNow lazy_now(CreateLazyNow()); // Move any ready delayed tasks into the Incoming queues. WakeupReadyDelayedQueues(&lazy_now, should_trigger_wakeup, previous_task);
diff --git a/components/scheduler/base/time_domain.h b/components/scheduler/base/time_domain.h index 3938891..3b8db03e 100644 --- a/components/scheduler/base/time_domain.h +++ b/components/scheduler/base/time_domain.h
@@ -104,7 +104,8 @@ // Updates active queues associated with this TimeDomain. void UpdateWorkQueues(bool should_trigger_wakeup, - const internal::TaskQueueImpl::Task* previous_task); + const internal::TaskQueueImpl::Task* previous_task, + LazyNow lazy_now); // Called by the TaskQueueManager when the TimeDomain is registered. virtual void OnRegisterWithTaskQueueManager(
diff --git a/components/scheduler/base/time_domain_unittest.cc b/components/scheduler/base/time_domain_unittest.cc index 7f422883..1d9fdcd 100644 --- a/components/scheduler/base/time_domain_unittest.cc +++ b/components/scheduler/base/time_domain_unittest.cc
@@ -164,12 +164,14 @@ ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time)); EXPECT_EQ(delayed_runtime, next_run_time); - time_domain_->UpdateWorkQueues(false, nullptr); + LazyNow lazy_now = time_domain_->CreateLazyNow(); + time_domain_->UpdateWorkQueues(false, nullptr, lazy_now); ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time)); EXPECT_EQ(delayed_runtime, next_run_time); time_domain_->SetNow(delayed_runtime); - time_domain_->UpdateWorkQueues(false, nullptr); + lazy_now = time_domain_->CreateLazyNow(); + time_domain_->UpdateWorkQueues(false, nullptr, lazy_now); ASSERT_FALSE(time_domain_->NextScheduledRunTime(&next_run_time)); }
diff --git a/components/scheduler/base/work_queue.cc b/components/scheduler/base/work_queue.cc index 313baa9..ec770cb 100644 --- a/components/scheduler/base/work_queue.cc +++ b/components/scheduler/base/work_queue.cc
@@ -16,11 +16,17 @@ name_(name) {} void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const { - std::queue<TaskQueueImpl::Task> queue_copy(work_queue_); - while (!queue_copy.empty()) { - TaskQueueImpl::TaskAsValueInto(queue_copy.front(), state); - queue_copy.pop(); + // Remove const to search |work_queue_| in the destructive manner. Restore the + // content from |visited| later. + std::queue<TaskQueueImpl::Task>* mutable_queue = + const_cast<std::queue<TaskQueueImpl::Task>*>(&work_queue_); + std::queue<TaskQueueImpl::Task> visited; + while (!mutable_queue->empty()) { + TaskQueueImpl::TaskAsValueInto(mutable_queue->front(), state); + visited.push(std::move(mutable_queue->front())); + mutable_queue->pop(); } + *mutable_queue = std::move(visited); } WorkQueue::~WorkQueue() { @@ -41,17 +47,17 @@ return true; } -void WorkQueue::Push(const TaskQueueImpl::Task& task) { +void WorkQueue::Push(TaskQueueImpl::Task task) { bool was_empty = work_queue_.empty(); - work_queue_.push(task); + work_queue_.push(std::move(task)); if (was_empty && work_queue_sets_) work_queue_sets_->OnPushQueue(this); } -void WorkQueue::PushAndSetEnqueueOrder(const TaskQueueImpl::Task& task, +void WorkQueue::PushAndSetEnqueueOrder(TaskQueueImpl::Task task, EnqueueOrder enqueue_order) { bool was_empty = work_queue_.empty(); - work_queue_.push(task); + work_queue_.push(std::move(task)); work_queue_.back().set_enqueue_order(enqueue_order); if (was_empty && work_queue_sets_)
diff --git a/components/scheduler/base/work_queue.h b/components/scheduler/base/work_queue.h index 9ff919d7..c97c34c6 100644 --- a/components/scheduler/base/work_queue.h +++ b/components/scheduler/base/work_queue.h
@@ -49,11 +49,11 @@ // Pushes the task onto the |work_queue_| and informs the WorkQueueSets if // the head changed. - void Push(const TaskQueueImpl::Task& task); + void Push(TaskQueueImpl::Task task); // Pushes the task onto the |work_queue_|, sets the |enqueue_order| and // informs the WorkQueueSets if the head changed. - void PushAndSetEnqueueOrder(const TaskQueueImpl::Task& task, + void PushAndSetEnqueueOrder(TaskQueueImpl::Task task, EnqueueOrder enqueue_order); // Swap the |work_queue_| with |incoming_queue| and informs the @@ -88,6 +88,8 @@ TaskQueueImpl* task_queue_; // NOT OWNED. size_t work_queue_set_index_; const char* name_; + + DISALLOW_COPY_AND_ASSIGN(WorkQueue); }; } // namespace internal
diff --git a/components/scheduler/child/scheduler_helper.cc b/components/scheduler/child/scheduler_helper.cc index 43944359..57cbbc38 100644 --- a/components/scheduler/child/scheduler_helper.cc +++ b/components/scheduler/child/scheduler_helper.cc
@@ -32,8 +32,8 @@ .SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP) .SetWakeupPolicy(TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES) .SetShouldNotifyObservers(false))), - default_task_runner_(NewTaskQueue(TaskQueue::Spec("default_tq") - .SetShouldMonitorQuiescence(true))), + default_task_runner_(NewTaskQueue( + TaskQueue::Spec("default_tq").SetShouldMonitorQuiescence(true))), observer_(nullptr), tracing_category_(tracing_category), disabled_by_default_tracing_category_(
diff --git a/components/scheduler/child/scheduler_helper.h b/components/scheduler/child/scheduler_helper.h index 0348a6808..c19f023 100644 --- a/components/scheduler/child/scheduler_helper.h +++ b/components/scheduler/child/scheduler_helper.h
@@ -22,7 +22,8 @@ class SchedulerTqmDelegate; // Common scheduler functionality for default tasks. -class SCHEDULER_EXPORT SchedulerHelper : public TaskQueueManager::Observer { +class SCHEDULER_EXPORT SchedulerHelper + : public TaskQueueManager::Observer { public: // Category strings must have application lifetime (statics or // literals). They may not include " chars. @@ -57,6 +58,11 @@ void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer); void RemoveTaskObserver(base::MessageLoop::TaskObserver* task_observer); + void SetTaskTimeTracker(TaskTimeTracker* task_time_tracker) { + if (task_queue_manager_) + task_queue_manager_->SetTaskTimeTracker(task_time_tracker); + } + // Shuts down the scheduler by dropping any remaining pending work in the work // queues. After this call any work posted to the task runners will be // silently dropped.
diff --git a/components/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc b/components/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc index 578c8f7f..3ce01a71 100644 --- a/components/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc +++ b/components/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/simple_test_tick_clock.h" #include "cc/test/ordered_simple_task_runner.h" #include "components/scheduler/base/task_queue_manager.h" +#include "components/scheduler/base/test_task_time_tracker.h" #include "components/scheduler/base/test_time_source.h" #include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,9 +30,11 @@ new cc::OrderedSimpleTaskRunner(clock_.get(), false)); main_task_runner_ = SchedulerTqmDelegateForTest::Create( mock_task_runner_, base::WrapUnique(new TestTimeSource(clock_.get()))); - manager_ = base::WrapUnique( - new TaskQueueManager(main_task_runner_, "test.scheduler", - "test.scheduler", "test.scheduler.debug")); + + manager_ = base::WrapUnique(new TaskQueueManager( + main_task_runner_, "test.scheduler", "test.scheduler", + "test.scheduler.debug")); + manager_->SetTaskTimeTracker(&test_task_time_tracker_); task_runner_ = manager_->NewTaskQueue(TaskQueue::Spec("test_task_queue")); initial_time_= clock_->NowTicks(); @@ -54,6 +57,7 @@ std::unique_ptr<TaskQueueManager> manager_; scoped_refptr<TaskQueue> task_runner_; std::unique_ptr<AutoAdvancingVirtualTimeDomain> auto_advancing_time_domain_; + TestTaskTimeTracker test_task_time_tracker_; }; namespace {
diff --git a/components/scheduler/renderer/idle_time_estimator_unittest.cc b/components/scheduler/renderer/idle_time_estimator_unittest.cc index c50ad83..d7d67a8 100644 --- a/components/scheduler/renderer/idle_time_estimator_unittest.cc +++ b/components/scheduler/renderer/idle_time_estimator_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/simple_test_tick_clock.h" #include "cc/test/ordered_simple_task_runner.h" #include "components/scheduler/base/task_queue_manager.h" +#include "components/scheduler/base/test_task_time_tracker.h" #include "components/scheduler/base/test_time_source.h" #include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "testing/gmock/include/gmock/gmock.h" @@ -42,10 +43,10 @@ mock_task_runner_ = make_scoped_refptr( new cc::OrderedSimpleTaskRunner(clock_.get(), false)); main_task_runner_ = SchedulerTqmDelegateForTest::Create( - mock_task_runner_, base::WrapUnique(new TestTimeSource(clock_.get()))); - manager_ = base::WrapUnique( - new TaskQueueManager(main_task_runner_, "test.scheduler", - "test.scheduler", "test.scheduler.debug")); + mock_task_runner_, base::MakeUnique<TestTimeSource>(clock_.get())); + manager_ = base::MakeUnique<TaskQueueManager>( + main_task_runner_, "test.scheduler", "test.scheduler", + "test.scheduler.debug"); compositor_task_runner_ = manager_->NewTaskQueue(TaskQueue::Spec("compositor_tq")); estimator_.reset(new IdleTimeEstimatorForTest( @@ -92,6 +93,7 @@ scoped_refptr<TaskQueue> compositor_task_runner_; std::unique_ptr<IdleTimeEstimatorForTest> estimator_; const base::TimeDelta frame_length_; + TestTaskTimeTracker test_task_time_tracker_; }; TEST_F(IdleTimeEstimatorTest, InitialTimeEstimateWithNoData) {
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc index c02624ef..209e563 100644 --- a/components/scheduler/renderer/renderer_scheduler_impl.cc +++ b/components/scheduler/renderer/renderer_scheduler_impl.cc
@@ -8,6 +8,7 @@ #include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/output/begin_frame_args.h" @@ -22,7 +23,7 @@ namespace { // The run time of loading tasks is strongly bimodal. The vast majority are // very cheap, but there are usually a handful of very expensive tasks (e.g ~1 -// second on a mobile device) so we take a very pesimistic view when estimating +// second on a mobile device) so we take a very pessimistic view when estimating // the cost of loading tasks. const int kLoadingTaskEstimationSampleCount = 1000; const double kLoadingTaskEstimationPercentile = 99; @@ -49,14 +50,14 @@ base::TimeDelta()), render_widget_scheduler_signals_(this), control_task_runner_(helper_.ControlTaskRunner()), - compositor_task_runner_( - helper_.NewTaskQueue(TaskQueue::Spec("compositor_tq") - .SetShouldMonitorQuiescence(true))), + compositor_task_runner_(helper_.NewTaskQueue( + TaskQueue::Spec("compositor_tq").SetShouldMonitorQuiescence(true))), delayed_update_policy_runner_( base::Bind(&RendererSchedulerImpl::UpdatePolicy, base::Unretained(this)), helper_.ControlTaskRunner()), - main_thread_only_(compositor_task_runner_, + main_thread_only_(this, + compositor_task_runner_, helper_.scheduler_tqm_delegate().get()), policy_may_need_update_(&any_thread_lock_), weak_factory_(this) { @@ -78,6 +79,7 @@ this); helper_.SetObserver(this); + helper_.SetTaskTimeTracker(this); } RendererSchedulerImpl::~RendererSchedulerImpl() { @@ -101,6 +103,7 @@ } RendererSchedulerImpl::MainThreadOnly::MainThreadOnly( + RendererSchedulerImpl* renderer_scheduler_impl, const scoped_refptr<TaskQueue>& compositor_task_runner, base::TickClock* time_source) : loading_task_cost_estimator(time_source, @@ -109,6 +112,8 @@ timer_task_cost_estimator(time_source, kTimerTaskEstimationSampleCount, kTimerTaskEstimationPercentile), + queueing_time_estimator(renderer_scheduler_impl, + base::TimeDelta::FromSeconds(1)), idle_time_estimator(compositor_task_runner, time_source, kShortIdlePeriodDurationSampleCount, @@ -1383,6 +1388,21 @@ } } +void RendererSchedulerImpl::ReportTaskTime(base::TimeTicks start_time, + base::TimeTicks end_time) { + MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted(start_time, + end_time); +} + +void RendererSchedulerImpl::OnQueueingTimeForWindowEstimated( + base::TimeDelta queueing_time) { + UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration", + queueing_time); + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), + "estimated_queueing_time_for_window", + queueing_time.InMillisecondsF()); +} + // static const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { switch (use_case) {
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.h b/components/scheduler/renderer/renderer_scheduler_impl.h index 0f9d623b..e35ee15a 100644 --- a/components/scheduler/renderer/renderer_scheduler_impl.h +++ b/components/scheduler/renderer/renderer_scheduler_impl.h
@@ -9,6 +9,8 @@ #include "base/macros.h" #include "base/synchronization/lock.h" #include "components/scheduler/base/pollable_thread_safe_flag.h" +#include "components/scheduler/base/queueing_time_estimator.h" +#include "components/scheduler/base/task_time_tracker.h" #include "components/scheduler/child/idle_helper.h" #include "components/scheduler/child/scheduler_helper.h" #include "components/scheduler/renderer/deadline_task_runner.h" @@ -36,7 +38,9 @@ : public RendererScheduler, public IdleHelper::Delegate, public SchedulerHelper::Observer, - public RenderWidgetSignals::Observer { + public RenderWidgetSignals::Observer, + public TaskTimeTracker, + public QueueingTimeEstimator::Client { public: // Keep RendererScheduler::UseCaseToString in sync with this enum. enum class UseCase { @@ -126,6 +130,13 @@ void OnTriedToExecuteBlockedTask(const TaskQueue& queue, const base::PendingTask& task) override; + // TaskTimeTracker implementation: + void ReportTaskTime(base::TimeTicks start_time, + base::TimeTicks end_time) override; + + // QueueingTimeEstimator::Client implementation: + void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time) override; + // Returns a task runner where tasks run at the highest possible priority. scoped_refptr<TaskQueue> ControlTaskRunner(); @@ -352,12 +363,14 @@ // (the accessors) for the following data members. struct MainThreadOnly { - MainThreadOnly(const scoped_refptr<TaskQueue>& compositor_task_runner, + MainThreadOnly(RendererSchedulerImpl* renderer_scheduler_impl, + const scoped_refptr<TaskQueue>& compositor_task_runner, base::TickClock* time_source); ~MainThreadOnly(); TaskCostEstimator loading_task_cost_estimator; TaskCostEstimator timer_task_cost_estimator; + QueueingTimeEstimator queueing_time_estimator; IdleTimeEstimator idle_time_estimator; UseCase current_use_case; Policy current_policy;
diff --git a/components/scheduler/renderer/web_frame_scheduler_impl.cc b/components/scheduler/renderer/web_frame_scheduler_impl.cc index 495a1db3..44cdf203 100644 --- a/components/scheduler/renderer/web_frame_scheduler_impl.cc +++ b/components/scheduler/renderer/web_frame_scheduler_impl.cc
@@ -108,14 +108,14 @@ return parent_web_view_scheduler_; } -void WebFrameSchedulerImpl::incrementPendingResourceLoadCount() { +void WebFrameSchedulerImpl::didStartLoading(unsigned long identifier) { if (parent_web_view_scheduler_) - parent_web_view_scheduler_->incrementPendingResourceLoadCount(); + parent_web_view_scheduler_->DidStartLoading(identifier); } -void WebFrameSchedulerImpl::decrementPendingResourceLoadCount() { +void WebFrameSchedulerImpl::didStopLoading(unsigned long identifier) { if (parent_web_view_scheduler_) - parent_web_view_scheduler_->decrementPendingResourceLoadCount(); + parent_web_view_scheduler_->DidStopLoading(identifier); } void WebFrameSchedulerImpl::setPageVisible(bool page_visible) {
diff --git a/components/scheduler/renderer/web_frame_scheduler_impl.h b/components/scheduler/renderer/web_frame_scheduler_impl.h index 0500ba3..367340d6 100644 --- a/components/scheduler/renderer/web_frame_scheduler_impl.h +++ b/components/scheduler/renderer/web_frame_scheduler_impl.h
@@ -44,8 +44,8 @@ blink::WebTaskRunner* timerTaskRunner() override; blink::WebTaskRunner* unthrottledTaskRunner() override; blink::WebViewScheduler* webViewScheduler() override; - void incrementPendingResourceLoadCount() override; - void decrementPendingResourceLoadCount() override; + void didStartLoading(unsigned long identifier) override; + void didStopLoading(unsigned long identifier) override; void OnVirtualTimeDomainChanged();
diff --git a/components/scheduler/renderer/web_view_scheduler_impl.cc b/components/scheduler/renderer/web_view_scheduler_impl.cc index 48f565c..da4e80b3 100644 --- a/components/scheduler/renderer/web_view_scheduler_impl.cc +++ b/components/scheduler/renderer/web_view_scheduler_impl.cc
@@ -24,7 +24,6 @@ : virtual_time_pump_policy_(TaskQueue::PumpPolicy::AUTO), web_view_(web_view), renderer_scheduler_(renderer_scheduler), - pending_resource_load_count_(0), virtual_time_policy_(VirtualTimePolicy::ADVANCE), page_visible_(true), disable_background_timer_throttling_(disable_background_timer_throttling), @@ -118,28 +117,27 @@ return allow_virtual_time_to_advance_; } -void WebViewSchedulerImpl::incrementPendingResourceLoadCount() { - pending_resource_load_count_++; +void WebViewSchedulerImpl::DidStartLoading(unsigned long identifier) { + pending_loads_.insert(identifier); if (virtual_time_policy_ != VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING) { return; } - if (pending_resource_load_count_ == 1) + if (pending_loads_.size() == 1u) setAllowVirtualTimeToAdvance(false); } -void WebViewSchedulerImpl::decrementPendingResourceLoadCount() { - pending_resource_load_count_--; - DCHECK_GE(pending_resource_load_count_, 0); +void WebViewSchedulerImpl::DidStopLoading(unsigned long identifier) { + pending_loads_.erase(identifier); if (virtual_time_policy_ != VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING) { return; } - if (pending_resource_load_count_ == 0) + if (pending_loads_.size() == 0) setAllowVirtualTimeToAdvance(true); } @@ -156,7 +154,7 @@ break; case VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING: - setAllowVirtualTimeToAdvance(pending_resource_load_count_ == 0); + setAllowVirtualTimeToAdvance(pending_loads_.size() == 0); break; } }
diff --git a/components/scheduler/renderer/web_view_scheduler_impl.h b/components/scheduler/renderer/web_view_scheduler_impl.h index 233c1dc2..019696c8 100644 --- a/components/scheduler/renderer/web_view_scheduler_impl.h +++ b/components/scheduler/renderer/web_view_scheduler_impl.h
@@ -53,8 +53,8 @@ std::unique_ptr<WebFrameSchedulerImpl> createWebFrameSchedulerImpl( base::trace_event::BlameContext* blame_context); - void incrementPendingResourceLoadCount(); - void decrementPendingResourceLoadCount(); + void DidStartLoading(unsigned long identifier); + void DidStopLoading(unsigned long identifier); private: friend class WebFrameSchedulerImpl; @@ -68,11 +68,11 @@ void setAllowVirtualTimeToAdvance(bool allow_virtual_time_to_advance); std::set<WebFrameSchedulerImpl*> frame_schedulers_; + std::set<unsigned long> pending_loads_; std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_; TaskQueue::PumpPolicy virtual_time_pump_policy_; blink::WebView* web_view_; RendererSchedulerImpl* renderer_scheduler_; - int pending_resource_load_count_; VirtualTimePolicy virtual_time_policy_; bool page_visible_; bool disable_background_timer_throttling_;
diff --git a/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc index 5a3d5475..49bed4d 100644 --- a/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc +++ b/components/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -508,22 +508,45 @@ VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING); EXPECT_TRUE(web_view_scheduler_->virtualTimeAllowedToAdvance()); - web_view_scheduler_->incrementPendingResourceLoadCount(); + web_view_scheduler_->DidStartLoading(1u); EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); - web_view_scheduler_->incrementPendingResourceLoadCount(); + web_view_scheduler_->DidStartLoading(2u); EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); - web_view_scheduler_->decrementPendingResourceLoadCount(); + web_view_scheduler_->DidStopLoading(2u); EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); - web_view_scheduler_->incrementPendingResourceLoadCount(); + web_view_scheduler_->DidStartLoading(3u); EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); - web_view_scheduler_->decrementPendingResourceLoadCount(); + web_view_scheduler_->DidStopLoading(1u); EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); - web_view_scheduler_->decrementPendingResourceLoadCount(); + web_view_scheduler_->DidStopLoading(3u); + EXPECT_TRUE(web_view_scheduler_->virtualTimeAllowedToAdvance()); +} + +TEST_F(WebViewSchedulerImplTest, RedundantDidStopLoadingCallsAreHarmless) { + web_view_scheduler_->setVirtualTimePolicy( + VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING); + + web_view_scheduler_->DidStartLoading(1u); + EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); + + web_view_scheduler_->DidStopLoading(1u); + EXPECT_TRUE(web_view_scheduler_->virtualTimeAllowedToAdvance()); + + web_view_scheduler_->DidStopLoading(1u); + EXPECT_TRUE(web_view_scheduler_->virtualTimeAllowedToAdvance()); + + web_view_scheduler_->DidStopLoading(1u); + EXPECT_TRUE(web_view_scheduler_->virtualTimeAllowedToAdvance()); + + web_view_scheduler_->DidStartLoading(2u); + EXPECT_FALSE(web_view_scheduler_->virtualTimeAllowedToAdvance()); + + web_view_scheduler_->DidStopLoading(2u); EXPECT_TRUE(web_view_scheduler_->virtualTimeAllowedToAdvance()); }
diff --git a/components/scheduler/scheduler.gypi b/components/scheduler/scheduler.gypi index dbcfefd..4bc63988 100644 --- a/components/scheduler/scheduler.gypi +++ b/components/scheduler/scheduler.gypi
@@ -15,6 +15,8 @@ 'base/cancelable_closure_holder.h', 'base/lazy_now.cc', 'base/lazy_now.h', + 'base/queueing_time_estimator.cc', + 'base/queueing_time_estimator.h', 'base/real_time_domain.cc', 'base/real_time_domain.h', 'base/task_queue.h', @@ -25,6 +27,7 @@ 'base/task_queue_manager_delegate.h', 'base/task_queue_selector.cc', 'base/task_queue_selector.h', + 'base/task_time_tracker.h', 'base/time_domain.cc', 'base/time_domain.h', 'base/work_queue.cc',
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc index f89946f2..73a4c72 100644 --- a/components/sessions/core/tab_restore_service_helper.cc +++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -138,22 +138,21 @@ LiveTabContext* context) { if (entries_.empty()) return std::vector<LiveTab*>(); - return RestoreEntryById(context, entries_.front()->id, UNKNOWN); } TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById( SessionID::id_type id) { - Entries::iterator i = GetEntryIteratorById(id); - if (i == entries_.end()) - return NULL; + Entries::iterator it = GetEntryIteratorById(id); + if (it == entries_.end()) + return nullptr; - Entry* entry = *i; + Entry* entry = *it; if (entry->type != TabRestoreService::TAB) - return NULL; + return nullptr; Tab* tab = static_cast<Tab*>(entry); - entries_.erase(i); + entries_.erase(it); return tab; } @@ -162,9 +161,10 @@ SessionID::id_type id, WindowOpenDisposition disposition) { Entries::iterator entry_iterator = GetEntryIteratorById(id); - if (entry_iterator == entries_.end()) + if (entry_iterator == entries_.end()) { // Don't hoark here, we allow an invalid id. return std::vector<LiveTab*>(); + } if (observer_) observer_->OnRestoreEntryById(id, entry_iterator); @@ -186,7 +186,7 @@ std::vector<LiveTab*> live_tabs; if (entry->type == TabRestoreService::TAB) { Tab* tab = static_cast<Tab*>(entry); - LiveTab* restored_tab = NULL; + LiveTab* restored_tab = nullptr; context = RestoreTab(*tab, context, disposition, &restored_tab); live_tabs.push_back(restored_tab); context->ShowBrowserWindow(); @@ -225,28 +225,27 @@ for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); tab_i != window->tabs.end(); ++tab_i) { const Tab& tab = *tab_i; - if (tab.id == id) { - LiveTab* restored_tab = NULL; - context = RestoreTab(tab, context, disposition, &restored_tab); - live_tabs.push_back(restored_tab); - window->tabs.erase(tab_i); - // If restoring the tab leaves the window with nothing else, delete it - // as well. - if (!window->tabs.size()) { - entries_.erase(entry_iterator); - delete entry; - } else { - // Update the browser ID of the rest of the tabs in the window so if - // any one is restored, it goes into the same window as the tab - // being restored now. - UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); - for (std::vector<Tab>::iterator tab_j = window->tabs.begin(); - tab_j != window->tabs.end(); ++tab_j) { - (*tab_j).browser_id = context->GetSessionID().id(); - } - } - break; + if (tab.id != id) + continue; + + LiveTab* restored_tab = nullptr; + context = RestoreTab(tab, context, disposition, &restored_tab); + live_tabs.push_back(restored_tab); + window->tabs.erase(tab_i); + // If restoring the tab leaves the window with nothing else, delete it + // as well. + if (window->tabs.empty()) { + entries_.erase(entry_iterator); + delete entry; + } else { + // Update the browser ID of the rest of the tabs in the window so if + // any one is restored, it goes into the same window as the tab + // being restored now. + UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); + for (Tab& tab_j : window->tabs) + tab_j.browser_id = context->GetSessionID().id(); } + break; } } context->ShowBrowserWindow();
diff --git a/components/signin.gypi b/components/signin.gypi index 049ab5a4..1a00eb8 100644 --- a/components/signin.gypi +++ b/components/signin.gypi
@@ -256,8 +256,6 @@ ], 'sources': [ # Note: file list duplicated in GN build. - 'signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.h', - 'signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.mm', 'signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h', 'signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.mm', ],
diff --git a/components/signin/ios/browser/BUILD.gn b/components/signin/ios/browser/BUILD.gn index 9d1572b3..c0a9f35 100644 --- a/components/signin/ios/browser/BUILD.gn +++ b/components/signin/ios/browser/BUILD.gn
@@ -35,8 +35,6 @@ source_set("test_support") { testonly = true sources = [ - "fake_profile_oauth2_token_service_ios_delegate.h", - "fake_profile_oauth2_token_service_ios_delegate.mm", "fake_profile_oauth2_token_service_ios_provider.h", "fake_profile_oauth2_token_service_ios_provider.mm", ]
diff --git a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.h b/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.h deleted file mode 100644 index ed5c5a15..0000000 --- a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SIGNIN_IOS_BROWSER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_DELEGATE_H_ -#define COMPONENTS_SIGNIN_IOS_BROWSER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_DELEGATE_H_ - -#include "base/macros.h" -#include "base/threading/thread_checker.h" -#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h" - -class FakeProfileOAuth2TokenServiceIOSDelegate - : public ProfileOAuth2TokenServiceIOSDelegate { - public: - FakeProfileOAuth2TokenServiceIOSDelegate( - SigninClient* client, - std::unique_ptr<ProfileOAuth2TokenServiceIOSProvider> provider, - AccountTrackerService* account_tracker_service, - SigninErrorController* signin_error_controller); - ~FakeProfileOAuth2TokenServiceIOSDelegate() override; - - OAuth2AccessTokenFetcher* CreateAccessTokenFetcher( - const std::string& account_id, - net::URLRequestContextGetter* getter, - OAuth2AccessTokenConsumer* consumer) override; - - bool RefreshTokenIsAvailable(const std::string& account_id) const override; - bool RefreshTokenHasError(const std::string& account_id) const override; - void UpdateAuthError(const std::string& account_id, - const GoogleServiceAuthError& error) override; - - std::vector<std::string> GetAccounts() override; - void RevokeAllCredentials() override; - - void LoadCredentials(const std::string& primary_account_id) override; - - void UpdateCredentials(const std::string& account_id, - const std::string& refresh_token) override; - void RevokeCredentials(const std::string& account_id) override; - void AddOrUpdateAccount(const std::string& account_id) override; - void RemoveAccount(const std::string& account_id) override; - - private: - void IssueRefreshTokenForUser(const std::string& account_id, - const std::string& token); - std::string GetRefreshToken(const std::string& account_id) const; - - // Calls to this class are expected to be made from the browser UI thread. - // The purpose of this checker is to detect access to - // ProfileOAuth2TokenService from multiple threads in upstream code. - base::ThreadChecker thread_checker_; - - // Maps account ids to their refresh token strings. - std::map<std::string, std::string> refresh_tokens_; - // Maps account ids to their auth errors. - std::map<std::string, GoogleServiceAuthError> auth_errors_; - - DISALLOW_COPY_AND_ASSIGN(FakeProfileOAuth2TokenServiceIOSDelegate); -}; - -#endif // COMPONENTS_SIGNIN_IOS_BROWSER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_IOS_DELEGATE_H_
diff --git a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.mm b/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.mm deleted file mode 100644 index 51421524..0000000 --- a/components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.mm +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.h" - -#include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h" -#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" - -FakeProfileOAuth2TokenServiceIOSDelegate:: - FakeProfileOAuth2TokenServiceIOSDelegate( - SigninClient* client, - std::unique_ptr<ProfileOAuth2TokenServiceIOSProvider> provider, - AccountTrackerService* account_tracker_service, - SigninErrorController* signin_error_controller) - : ProfileOAuth2TokenServiceIOSDelegate(client, - std::move(provider), - account_tracker_service, - signin_error_controller) {} - -FakeProfileOAuth2TokenServiceIOSDelegate:: - ~FakeProfileOAuth2TokenServiceIOSDelegate() {} - -OAuth2AccessTokenFetcher* -FakeProfileOAuth2TokenServiceIOSDelegate::CreateAccessTokenFetcher( - const std::string& account_id, - net::URLRequestContextGetter* getter, - OAuth2AccessTokenConsumer* consumer) { - std::map<std::string, std::string>::const_iterator it = - refresh_tokens_.find(account_id); - DCHECK(it != refresh_tokens_.end()); - std::string refresh_token(it->second); - return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token); -} - -bool FakeProfileOAuth2TokenServiceIOSDelegate::RefreshTokenIsAvailable( - const std::string& account_id) const { - DCHECK(thread_checker_.CalledOnValidThread()); - - return !GetRefreshToken(account_id).empty(); -} - -bool FakeProfileOAuth2TokenServiceIOSDelegate::RefreshTokenHasError( - const std::string& account_id) const { - DCHECK(thread_checker_.CalledOnValidThread()); - auto it = auth_errors_.find(account_id); - return it != auth_errors_.end() && IsError(it->second); -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::UpdateAuthError( - const std::string& account_id, - const GoogleServiceAuthError& error) { - DCHECK(thread_checker_.CalledOnValidThread()); - auth_errors_.erase(account_id); - auth_errors_.emplace(account_id, error); -} - -std::string FakeProfileOAuth2TokenServiceIOSDelegate::GetRefreshToken( - const std::string& account_id) const { - std::map<std::string, std::string>::const_iterator it = - refresh_tokens_.find(account_id); - if (it != refresh_tokens_.end()) - return it->second; - return std::string(); -} - -std::vector<std::string> -FakeProfileOAuth2TokenServiceIOSDelegate::GetAccounts() { - std::vector<std::string> account_ids; - for (std::map<std::string, std::string>::const_iterator iter = - refresh_tokens_.begin(); - iter != refresh_tokens_.end(); ++iter) { - account_ids.push_back(iter->first); - } - return account_ids; -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::RevokeAllCredentials() { - DCHECK(thread_checker_.CalledOnValidThread()); - - std::vector<std::string> account_ids = GetAccounts(); - for (std::vector<std::string>::const_iterator it = account_ids.begin(); - it != account_ids.end(); it++) { - RevokeCredentials(*it); - } -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::LoadCredentials( - const std::string& primary_account_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - FireRefreshTokensLoaded(); -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::UpdateCredentials( - const std::string& account_id, - const std::string& refresh_token) { - IssueRefreshTokenForUser(account_id, refresh_token); -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::AddOrUpdateAccount( - const std::string& account_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - - UpdateCredentials(account_id, "fake_refresh_token"); -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::RemoveAccount( - const std::string& account_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!account_id.empty()); - - IssueRefreshTokenForUser(account_id, ""); -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::IssueRefreshTokenForUser( - const std::string& account_id, - const std::string& token) { - ScopedBatchChange batch(this); - if (token.empty()) { - refresh_tokens_.erase(account_id); - auth_errors_.erase(account_id); - FireRefreshTokenRevoked(account_id); - } else { - refresh_tokens_[account_id] = token; - auth_errors_.emplace(account_id, - GoogleServiceAuthError(GoogleServiceAuthError::NONE)); - FireRefreshTokenAvailable(account_id); - } -} - -void FakeProfileOAuth2TokenServiceIOSDelegate::RevokeCredentials( - const std::string& account_id) { - IssueRefreshTokenForUser(account_id, std::string()); -}
diff --git a/components/sync_sessions/favicon_cache_unittest.cc b/components/sync_sessions/favicon_cache_unittest.cc index 0eb2092..b2aac8cae 100644 --- a/components/sync_sessions/favicon_cache_unittest.cc +++ b/components/sync_sessions/favicon_cache_unittest.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "sync/api/attachments/attachment_id.h" @@ -244,7 +245,7 @@ std::string tag = syncer::SyncDataLocal(change.sync_data()).GetTag(); const std::string kPrefix = "http://bla.com/"; const std::string kSuffix = ".ico"; - if (tag.find(kPrefix) != 0) + if (!base::StartsWith(tag, kPrefix, base::CompareCase::SENSITIVE)) return -1; std::string temp = tag.substr(kPrefix.length()); if (temp.rfind(kSuffix) <= 0)
diff --git a/components/sync_sessions/synced_session_tracker.cc b/components/sync_sessions/synced_session_tracker.cc index abff52e7..527c5a3 100644 --- a/components/sync_sessions/synced_session_tracker.cc +++ b/components/sync_sessions/synced_session_tracker.cc
@@ -215,39 +215,36 @@ bool SyncedSessionTracker::DeleteOldSessionWindowIfNecessary( const SessionWindowWrapper& window_wrapper) { - if (!window_wrapper.owned) { - DVLOG(1) << "Deleting closed window " - << window_wrapper.window_ptr->window_id.id(); - // Clear the tabs first, since we don't want the destructor to destroy - // them. Their deletion will be handled by DeleteOldSessionTabIfNecessary. - window_wrapper.window_ptr->tabs.clear(); - delete window_wrapper.window_ptr; - return true; - } - return false; + if (window_wrapper.owned) + return false; + + DVLOG(1) << "Deleting closed window " + << window_wrapper.window_ptr->window_id.id(); + // Clear the tabs first, since we don't want the destructor to destroy + // them. Their deletion will be handled by DeleteOldSessionTabIfNecessary. + window_wrapper.window_ptr->tabs.clear(); + delete window_wrapper.window_ptr; + return true; } bool SyncedSessionTracker::DeleteOldSessionTabIfNecessary( const SessionTabWrapper& tab_wrapper) { - if (!tab_wrapper.owned) { - if (VLOG_IS_ON(1)) { - sessions::SessionTab* tab_ptr = tab_wrapper.tab_ptr; - std::string title; - if (tab_ptr->navigations.size() > 0) { - title = - " (" + - base::UTF16ToUTF8( - tab_ptr->navigations[tab_ptr->navigations.size() - 1].title()) + - ")"; - } - DVLOG(1) << "Deleting closed tab " << tab_ptr->tab_id.id() << title - << " from window " << tab_ptr->window_id.id(); + if (tab_wrapper.owned) + return false; + + if (VLOG_IS_ON(1)) { + sessions::SessionTab* tab_ptr = tab_wrapper.tab_ptr; + std::string title; + if (!tab_ptr->navigations.empty()) { + title = + " (" + base::UTF16ToUTF8(tab_ptr->navigations.back().title()) + ")"; } - unmapped_tabs_.erase(tab_wrapper.tab_ptr); - delete tab_wrapper.tab_ptr; - return true; + DVLOG(1) << "Deleting closed tab " << tab_ptr->tab_id.id() << title + << " from window " << tab_ptr->window_id.id(); } - return false; + unmapped_tabs_.erase(tab_wrapper.tab_ptr); + delete tab_wrapper.tab_ptr; + return true; } void SyncedSessionTracker::CleanupSession(const std::string& session_tag) { @@ -400,15 +397,12 @@ std::string title; if (tab_ptr->navigations.size() > 0) { title = - " (" + - base::UTF16ToUTF8( - tab_ptr->navigations[tab_ptr->navigations.size() - 1].title()) + - ")"; + " (" + base::UTF16ToUTF8(tab_ptr->navigations.back().title()) + ")"; } DVLOG(1) << "Getting " << (session_tag == local_session_tag_ ? "local session" : session_tag) - << "'s seen tab " << tab_id << " at " << tab_ptr << title; + << "'s seen tab " << tab_id << " at " << tab_ptr << " " << title; } } else { tab_ptr = new sessions::SessionTab();
diff --git a/components/url_matcher/url_matcher.cc b/components/url_matcher/url_matcher.cc index 91cd15b..b4a9d21 100644 --- a/components/url_matcher/url_matcher.cc +++ b/components/url_matcher/url_matcher.cc
@@ -513,30 +513,26 @@ PatternSingletons::const_iterator iter = pattern_singletons->find(&search_pattern); - if (iter != pattern_singletons->end()) { + if (iter != pattern_singletons->end()) return URLMatcherCondition(criterion, *iter); - } else { - StringPattern* new_pattern = - new StringPattern(pattern, id_counter_++); - pattern_singletons->insert(new_pattern); - return URLMatcherCondition(criterion, new_pattern); - } + + StringPattern* new_pattern = new StringPattern(pattern, id_counter_++); + pattern_singletons->insert(new_pattern); + return URLMatcherCondition(criterion, new_pattern); } std::string URLMatcherConditionFactory::CanonicalizeHostSuffix( const std::string& suffix) const { - if (!suffix.empty() && suffix[suffix.size() - 1] == '.') - return suffix; - else - return suffix + "."; + if (suffix.empty()) + return "."; + return suffix.back() == '.' ? suffix : suffix + "."; } std::string URLMatcherConditionFactory::CanonicalizeHostPrefix( const std::string& prefix) const { - if (!prefix.empty() && prefix[0] == '.') - return prefix; - else - return "." + prefix; + if (prefix.empty()) + return "."; + return prefix[0] == '.' ? prefix : "." + prefix; } std::string URLMatcherConditionFactory::CanonicalizeHostname(
diff --git a/components/variations/variations_seed_store.cc b/components/variations/variations_seed_store.cc index 65b1efd..8067651 100644 --- a/components/variations/variations_seed_store.cc +++ b/components/variations/variations_seed_store.cc
@@ -112,7 +112,10 @@ exploded.second = 0; exploded.millisecond = 0; - return base::Time::FromUTCExploded(exploded); + base::Time out_time; + bool conversion_success = base::Time::FromUTCExploded(exploded, &out_time); + DCHECK(conversion_success); + return out_time; } VariationsSeedDateChangeState GetSeedDateChangeState(
diff --git a/components/webcrypto/algorithms/ecdh_unittest.cc b/components/webcrypto/algorithms/ecdh_unittest.cc index 5faccbd..387b16a 100644 --- a/components/webcrypto/algorithms/ecdh_unittest.cc +++ b/components/webcrypto/algorithms/ecdh_unittest.cc
@@ -219,7 +219,7 @@ ExportKey(blink::WebCryptoKeyFormatRaw, derived_key, &raw_key)); EXPECT_EQ(3u, raw_key.size()); // The last 7 bits of the key should be zero. - EXPECT_EQ(0, raw_key[raw_key.size() - 1] & 0x1f); + EXPECT_EQ(0, raw_key.back() & 0x1f); } // Derive an HMAC key with no specified length (just the hash of SHA-256).
diff --git a/components/webcrypto/algorithms/util.cc b/components/webcrypto/algorithms/util.cc index 4a3b747..f8eb6ae 100644 --- a/components/webcrypto/algorithms/util.cc +++ b/components/webcrypto/algorithms/util.cc
@@ -47,7 +47,7 @@ // Zero any "unused bits" in the final byte. if (remainder_bits) - (*bytes)[bytes->size() - 1] &= ~((0xFF) >> remainder_bits); + bytes->back() &= ~((0xFF) >> remainder_bits); } Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages,
diff --git a/content/browser/android/java/java_bridge_thread.cc b/content/browser/android/java/java_bridge_thread.cc index 6c69bc0..4c8b24ed 100644 --- a/content/browser/android/java/java_bridge_thread.cc +++ b/content/browser/android/java/java_bridge_thread.cc
@@ -6,6 +6,7 @@ #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" +#include "base/single_thread_task_runner.h" #include "base/task_runner_util.h" #include "build/build_config.h" @@ -33,8 +34,10 @@ // static bool JavaBridgeThread::CurrentlyOn() { - return base::MessageLoop::current() == - g_background_thread.Get().message_loop(); + return g_background_thread.Get() + .message_loop() + ->task_runner() + ->BelongsToCurrentThread(); } // static
diff --git a/content/browser/appcache/appcache_request_handler_unittest.cc b/content/browser/appcache/appcache_request_handler_unittest.cc index ffb58da60..f90f48e 100644 --- a/content/browser/appcache/appcache_request_handler_unittest.cc +++ b/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -195,7 +195,7 @@ } void SetUpTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); mock_service_.reset(new MockAppCacheService); mock_service_->set_request_context(&empty_context_); mock_policy_.reset(new MockAppCachePolicy); @@ -212,7 +212,7 @@ } void TearDownTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); job_ = NULL; handler_.reset(); request_.reset(); @@ -227,7 +227,7 @@ void TestFinished() { // We unwind the stack prior to finishing up to let stack // based objects get deleted. - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&AppCacheRequestHandlerTest::TestFinishedUnwound, base::Unretained(this))); @@ -243,7 +243,7 @@ } void ScheduleNextTask() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); if (task_stack_.empty()) { TestFinished(); return;
diff --git a/content/browser/appcache/appcache_response_unittest.cc b/content/browser/appcache/appcache_response_unittest.cc index 9c279d3..8e633c1f 100644 --- a/content/browser/appcache/appcache_response_unittest.cc +++ b/content/browser/appcache/appcache_response_unittest.cc
@@ -91,7 +91,7 @@ } void SetUpTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); DCHECK(task_stack_.empty()); storage_delegate_.reset(new MockStorageDelegate(this)); service_.reset(new MockAppCacheService()); @@ -107,7 +107,7 @@ } void TearDownTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); while (!task_stack_.empty()) task_stack_.pop(); @@ -124,7 +124,7 @@ void TestFinished() { // We unwind the stack prior to finishing up to let stack // based objects get deleted. - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&AppCacheResponseTest::TestFinishedUnwound, base::Unretained(this))); @@ -144,7 +144,7 @@ } void ScheduleNextTask() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); if (task_stack_.empty()) { TestFinished(); return;
diff --git a/content/browser/appcache/appcache_storage_impl_unittest.cc b/content/browser/appcache/appcache_storage_impl_unittest.cc index 85725b4..a59be1c7 100644 --- a/content/browser/appcache/appcache_storage_impl_unittest.cc +++ b/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -410,7 +410,7 @@ } void SetUpTest() { - DCHECK(base::MessageLoop::current() == io_thread->message_loop()); + DCHECK(io_thread->task_runner()->BelongsToCurrentThread()); service_.reset(new AppCacheServiceImpl(NULL)); service_->Initialize(base::FilePath(), db_thread->task_runner(), NULL); mock_quota_manager_proxy_ = new MockQuotaManagerProxy(); @@ -419,7 +419,7 @@ } void TearDownTest() { - DCHECK(base::MessageLoop::current() == io_thread->message_loop()); + DCHECK(io_thread->task_runner()->BelongsToCurrentThread()); storage()->CancelDelegateCallbacks(delegate()); group_ = NULL; cache_ = NULL; @@ -433,7 +433,7 @@ void TestFinished() { // We unwind the stack prior to finishing up to let stack // based objects get deleted. - DCHECK(base::MessageLoop::current() == io_thread->message_loop()); + DCHECK(io_thread->task_runner()->BelongsToCurrentThread()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&AppCacheStorageImplTest::TestFinishedUnwound, base::Unretained(this))); @@ -449,7 +449,7 @@ } void ScheduleNextTask() { - DCHECK(base::MessageLoop::current() == io_thread->message_loop()); + DCHECK(io_thread->task_runner()->BelongsToCurrentThread()); if (task_stack_.empty()) { return; }
diff --git a/content/browser/appcache/appcache_url_request_job_unittest.cc b/content/browser/appcache/appcache_url_request_job_unittest.cc index dbce38dd..8cde90b1 100644 --- a/content/browser/appcache/appcache_url_request_job_unittest.cc +++ b/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -248,7 +248,7 @@ } void SetUpTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); DCHECK(task_stack_.empty()); storage_delegate_.reset(new MockStorageDelegate(this)); @@ -268,7 +268,7 @@ } void TearDownTest() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); request_.reset(); while (!task_stack_.empty()) @@ -292,7 +292,7 @@ void TestFinished() { // We unwind the stack prior to finishing up to let stack // based objects get deleted. - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&AppCacheURLRequestJobTest::TestFinishedUnwound, base::Unretained(this))); @@ -312,7 +312,7 @@ } void ScheduleNextTask() { - DCHECK(base::MessageLoop::current() == io_thread_->message_loop()); + DCHECK(io_thread_->task_runner()->BelongsToCurrentThread()); if (task_stack_.empty()) { TestFinished(); return;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index d5faefd0..94ee2c3 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -192,11 +192,6 @@ #include "gpu/vulkan/vulkan_implementation.h" #endif -#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA) -#include "services/ui/common/gpu_service.h" // nogncheck -#endif - - // One of the linux specific headers defines this as a macro. #ifdef DestroyAll #undef DestroyAll @@ -1162,28 +1157,27 @@ // Bring up Mojo IPC and shell as early as possible. - // Disallow mojo sync call in the browser process. - bool sync_call_allowed = false; - MojoResult result = mojo::edk::SetProperty( - MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, &sync_call_allowed); - DCHECK_EQ(MOJO_RESULT_OK, result); + if (!parsed_command_line_.HasSwitch(switches::kSingleProcess)) { + // Disallow mojo sync calls in the browser process. Note that we allow sync + // calls in single-process mode since renderer IPCs are made from a browser + // thread. + bool sync_call_allowed = false; + MojoResult result = mojo::edk::SetProperty( + MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, &sync_call_allowed); + DCHECK_EQ(MOJO_RESULT_OK, result); + } mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport( BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) ->task_runner())); mojo_shell_context_.reset(new MojoShellContext); - if (shell::ShellIsRemote()) { #if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA) - // TODO(rockot): Remove the blocking wait for init. - // http://crbug.com/594852. - auto connection = MojoShellConnection::GetForProcess(); - if (connection) { - WaitForMojoShellInitialize(); - ui::GpuService::Initialize(connection->GetConnector()); - } + // TODO(rockot): Remove the blocking wait for init. + // http://crbug.com/594852. + if (shell::ShellIsRemote() && MojoShellConnection::GetForProcess()) + WaitForMojoShellInitialize(); #endif - } #if defined(OS_MACOSX) mojo::edk::SetMachPortProvider(MachBroker::GetInstance());
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc index e0e491627..4cbd80dfa 100644 --- a/content/browser/compositor/surface_utils.cc +++ b/content/browser/compositor/surface_utils.cc
@@ -76,7 +76,7 @@ if (!bitmap->tryAllocPixels(SkImageInfo::Make( dst_size_in_pixel.width(), dst_size_in_pixel.height(), color_type, kOpaque_SkAlphaType))) { - scoped_callback_runner.Reset(base::Bind( + scoped_callback_runner.ReplaceClosure(base::Bind( callback, SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE)); return; }
diff --git a/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc b/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc index 581f10c7..11adcda 100644 --- a/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc +++ b/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/process/process_handle.h" +#include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "content/common/device_sensors/device_light_hardware_buffer.h" @@ -273,7 +274,8 @@ ~FakePollingDataFetcher() override {} bool Start(ConsumerType consumer_type, void* buffer) override { - EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop()); + EXPECT_TRUE( + GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); Init(consumer_type, buffer); switch (consumer_type) { @@ -296,7 +298,8 @@ } bool Stop(ConsumerType consumer_type) override { - EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop()); + EXPECT_TRUE( + GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); switch (consumer_type) { case CONSUMER_TYPE_MOTION: @@ -318,7 +321,8 @@ } void Fetch(unsigned consumer_bitmask) override { - EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop()); + EXPECT_TRUE( + GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); EXPECT_TRUE(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || consumer_bitmask & CONSUMER_TYPE_ORIENTATION_ABSOLUTE || consumer_bitmask & CONSUMER_TYPE_MOTION || @@ -346,7 +350,8 @@ ~FakeZeroDelayPollingDataFetcher() override {} bool Start(ConsumerType consumer_type, void* buffer) override { - EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop()); + EXPECT_TRUE( + GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); Init(consumer_type, buffer); switch (consumer_type) { @@ -369,7 +374,8 @@ } bool Stop(ConsumerType consumer_type) override { - EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop()); + EXPECT_TRUE( + GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); switch (consumer_type) { case CONSUMER_TYPE_MOTION:
diff --git a/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc b/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc index 1af22c3..b3334ad 100644 --- a/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc +++ b/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/metrics/histogram.h" +#include "base/single_thread_task_runner.h" #include "content/browser/device_sensors/ambient_light_mac.h" #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h" @@ -141,7 +142,7 @@ } void DataFetcherSharedMemory::Fetch(unsigned consumer_bitmask) { - DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); + DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); DCHECK(consumer_bitmask & CONSUMER_TYPE_ORIENTATION || consumer_bitmask & CONSUMER_TYPE_MOTION || consumer_bitmask & CONSUMER_TYPE_LIGHT); @@ -159,7 +160,7 @@ } bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) { - DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); + DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); DCHECK(buffer); switch (consumer_type) { @@ -235,7 +236,7 @@ } bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) { - DCHECK(base::MessageLoop::current() == GetPollingMessageLoop()); + DCHECK(GetPollingMessageLoop()->task_runner()->BelongsToCurrentThread()); switch (consumer_type) { case CONSUMER_TYPE_MOTION:
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index da789a4a..68d4bd1 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -43,10 +43,8 @@ "devtools_protocol_handler_generator.py" blink_protocol = "$root_gen_dir/blink/core/inspector/protocol.json" - browser_protocol = "browser_protocol.json" inputs = [ blink_protocol, - browser_protocol, ] outputs = [
diff --git a/content/browser/devtools/browser_protocol.json b/content/browser/devtools/browser_protocol.json deleted file mode 100644 index 1152ca7..0000000 --- a/content/browser/devtools/browser_protocol.json +++ /dev/null
@@ -1,81 +0,0 @@ -{ - "version": { "major": "1", "minor": "0" }, - "domains": [{ - "domain": "SystemInfo", - "description": "The SystemInfo domain defines methods and events for querying low-level system information.", - "hidden": true, - "types": [ - { - "id": "GPUDevice", - "type": "object", - "properties": [ - { "name": "vendorId", "type": "number", "description": "PCI ID of the GPU vendor, if available; 0 otherwise." }, - { "name": "deviceId", "type": "number", "description": "PCI ID of the GPU device, if available; 0 otherwise." }, - { "name": "vendorString", "type": "string", "description": "String description of the GPU vendor, if the PCI ID is not available." }, - { "name": "deviceString", "type": "string", "description": "String description of the GPU device, if the PCI ID is not available." } - ], - "description": "Describes a single graphics processor (GPU)." - }, - { - "id": "GPUInfo", - "type": "object", - "properties": [ - { "name": "devices", "type": "array", "items": { "$ref": "GPUDevice" }, "description": "The graphics devices on the system. Element 0 is the primary GPU." }, - { "name": "auxAttributes", "type": "object", "optional": "true", "description": "An optional dictionary of additional GPU related attributes." }, - { "name": "featureStatus", "type": "object", "optional": "true", "description": "An optional dictionary of graphics features and their status." }, - { "name": "driverBugWorkarounds", "type": "array", "items": { "type": "string" }, "description": "An optional array of GPU driver bug workarounds." } - ], - "description": "Provides information about the GPU(s) on the system." - } - ], - "commands": [ - { - "name": "getInfo", - "async": true, - "description": "Returns information about the system.", - "returns": [ - { "name": "gpu", "$ref": "GPUInfo", "description": "Information about the GPUs on the system." }, - { "name": "modelName", "type": "string", "description": "A platform-dependent description of the model of the machine. On Mac OS, this is, for example, 'MacBookPro'. Will be the empty string if not supported." }, - { "name": "modelVersion", "type": "string", "description": "A platform-dependent description of the version of the machine. On Mac OS, this is, for example, '10.1'. Will be the empty string if not supported." } - ], - "handlers": ["browser"] - } - ] - }, - { - "domain": "Tethering", - "description": "The Tethering domain defines methods and events for browser port binding.", - "hidden": true, - "commands": [ - { - "name": "bind", - "async": true, - "description": "Request browser port binding.", - "parameters": [ - { "name": "port", "type": "integer", "description": "Port number to bind." } - ], - "handlers": ["browser"] - }, - { - "name": "unbind", - "async": true, - "description": "Request browser port unbinding.", - "parameters": [ - { "name": "port", "type": "integer", "description": "Port number to unbind." } - ], - "handlers": ["browser"] - } - ], - "events": [ - { - "name": "accepted", - "description": "Informs that port was successfully bound and got a specified connection id.", - "parameters": [ - {"name": "port", "type": "integer", "description": "Port number that was successfully bound." }, - {"name": "connectionId", "type": "string", "description": "Connection id to be used." } - ], - "handlers": ["browser"] - } - ] - }] -}
diff --git a/content/browser/devtools/devtools.gyp b/content/browser/devtools/devtools.gyp index 33c99b1e..fc1a8a41 100644 --- a/content/browser/devtools/devtools.gyp +++ b/content/browser/devtools/devtools.gyp
@@ -15,14 +15,12 @@ 'action_name': 'devtools_protocol_handler', 'variables': { 'blink_protocol': '<(SHARED_INTERMEDIATE_DIR)/blink/core/inspector/protocol.json', - 'browser_protocol': 'browser_protocol.json', 'generator': 'protocol/devtools_protocol_handler_generator.py', 'output_cc': '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_dispatcher.cc', 'output_h': '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_dispatcher.h', }, 'inputs': [ '<(blink_protocol)', - '<(browser_protocol)', '<(generator)', ], 'outputs': [ @@ -33,11 +31,10 @@ 'python', '<(generator)', '<(blink_protocol)', - '<(browser_protocol)', '<(output_cc)', '<(output_h)', ], - 'message': 'Generating DevTools protocol browser-side handlers from <(blink_protocol) and <(browser_protocol)' + 'message': 'Generating DevTools protocol browser-side handlers from <(blink_protocol)' }, ], 'direct_dependent_settings': {
diff --git a/content/browser/devtools/protocol/browser_handler.cc b/content/browser/devtools/protocol/browser_handler.cc index ac575f6..83fd95f 100644 --- a/content/browser/devtools/protocol/browser_handler.cc +++ b/content/browser/devtools/protocol/browser_handler.cc
@@ -43,6 +43,39 @@ } } +Response BrowserHandler::CreateBrowserContext(std::string* out_context_id) { + // For layering reasons this needs to be handled by + // DevToolsManagerDelegate::HandleCommand. + return Response::ServerError("Not supported"); +} + +Response BrowserHandler::DisposeBrowserContext(const std::string& context_id, + bool* out_success) { + // For layering reasons this needs to be handled by + // DevToolsManagerDelegate::HandleCommand. + return Response::ServerError("Not supported"); +} + +Response BrowserHandler::CreateTarget(const std::string& initial_url, + const int* width, + const int* height, + const std::string* context_id, + std::string* out_target_id) { + // For layering reasons this needs to be handled by + // DevToolsManagerDelegate::HandleCommand. + return Response::ServerError("Not supported"); +} + +Response BrowserHandler::CloseTarget(const std::string& target_id, + bool* out_success) { + scoped_refptr<DevToolsAgentHost> agent_host = + DevToolsAgentHost::GetForId(target_id); + if (!agent_host) + return Response::ServerError("No target with given id found"); + *out_success = agent_host->Close(); + return Response::OK(); +} + Response BrowserHandler::GetTargets(TargetInfos* infos) { DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll(); for (DevToolsAgentHost::List::iterator it = agents.begin();
diff --git a/content/browser/devtools/protocol/browser_handler.h b/content/browser/devtools/protocol/browser_handler.h index d4135bc1..3cf34de7 100644 --- a/content/browser/devtools/protocol/browser_handler.h +++ b/content/browser/devtools/protocol/browser_handler.h
@@ -33,6 +33,16 @@ void SetClient(std::unique_ptr<Client> client); using TargetInfos = std::vector<scoped_refptr<devtools::browser::TargetInfo>>; + + Response CreateBrowserContext(std::string* out_context_id); + Response DisposeBrowserContext(const std::string& context_id, + bool* out_success); + Response CreateTarget(const std::string& initial_url, + const int* width, + const int* height, + const std::string* context_id, + std::string* out_targetId); + Response CloseTarget(const std::string& targetId, bool* out_success); Response GetTargets(TargetInfos* infos); Response Attach(const std::string& targetId); Response Detach(const std::string& targetId);
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 1e554763..e6e8357 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -587,4 +587,14 @@ dialog_manager.Handle(); } +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserNewPage) { + NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1); + Attach(); + EXPECT_EQ(1u, shell()->windows().size()); + std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); + params->SetString("initialUrl", "about:blank"); + SendCommand("Browser.newPage", std::move(params), true); + EXPECT_EQ(2u, shell()->windows().size()); +} + } // namespace content
diff --git a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py index f9cb63ce..1697708f 100755 --- a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py +++ b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -8,9 +8,8 @@ import json blink_protocol_path = sys.argv[1] -browser_protocol_path = sys.argv[2] -output_cc_path = sys.argv[3] -output_h_path = sys.argv[4] +output_cc_path = sys.argv[2] +output_h_path = sys.argv[3] header = """\ // Copyright 2014 The Chromium Authors. All rights reserved. @@ -21,7 +20,6 @@ // Generated by // content/public/browser/devtools_protocol_handler_generator.py from // gen/blink/core/inspector/protocol.json and -// content/browser/devtools/browser_protocol.json """ template_h = string.Template(header + """\ @@ -454,7 +452,6 @@ types = {} blink_protocol = json.loads(open(blink_protocol_path, "r").read()) -browser_protocol = json.loads(open(browser_protocol_path, "r").read()) type_decls = [] type_impls = [] handler_methods = [] @@ -462,7 +459,7 @@ domain_maps = [] redirects = {} -all_domains = blink_protocol["domains"] + browser_protocol["domains"] +all_domains = blink_protocol["domains"] for json_domain in all_domains: if "types" in json_domain:
diff --git a/content/browser/devtools/protocol/security_handler.cc b/content/browser/devtools/protocol/security_handler.cc index 913602e..4a2bce8 100644 --- a/content/browser/devtools/protocol/security_handler.cc +++ b/content/browser/devtools/protocol/security_handler.cc
@@ -105,6 +105,8 @@ AddExplanations(kSecurityStateSecure, security_style_explanations.secure_explanations, &explanations); + AddExplanations(kSecurityStateInfo, + security_style_explanations.info_explanations, &explanations); scoped_refptr<MixedContentStatus> mixed_content_status = MixedContentStatus::Create()
diff --git a/content/browser/dom_storage/session_storage_database.cc b/content/browser/dom_storage/session_storage_database.cc index 3a9457121..f3ac14d 100644 --- a/content/browser/dom_storage/session_storage_database.cc +++ b/content/browser/dom_storage/session_storage_database.cc
@@ -298,7 +298,8 @@ std::string current_namespace_id; for (it->Next(); it->Valid(); it->Next()) { std::string key = it->key().ToString(); - if (key.find(namespace_prefix) != 0) { + if (!base::StartsWith(key, namespace_prefix, + base::CompareCase::SENSITIVE)) { // Iterated past the "namespace-" keys. break; } @@ -497,7 +498,8 @@ // Skip the dummy entry "namespace-<namespaceid>-" and iterate the origins. for (it->Next(); it->Valid(); it->Next()) { std::string key = it->key().ToString(); - if (key.find(namespace_start_key) != 0) { + if (!base::StartsWith(key, namespace_start_key, + base::CompareCase::SENSITIVE)) { // Iterated past the origins for this namespace. break; } @@ -549,7 +551,7 @@ if (!it->Valid()) return true; std::string key = it->key().ToString(); - if (key.find(namespace_start_key) != 0) + if (!base::StartsWith(key, namespace_start_key, base::CompareCase::SENSITIVE)) batch->Delete(namespace_start_key); return true; } @@ -608,7 +610,7 @@ // Skip the dummy entry "map-<mapid>-". for (it->Next(); it->Valid(); it->Next()) { std::string key = it->key().ToString(); - if (key.find(map_start_key) != 0) { + if (!base::StartsWith(key, map_start_key, base::CompareCase::SENSITIVE)) { // Iterated past the keys in this map. break; }
diff --git a/content/browser/dom_storage/session_storage_database_unittest.cc b/content/browser/dom_storage/session_storage_database_unittest.cc index 9440e0d..bc6a5fdd 100644 --- a/content/browser/dom_storage/session_storage_database_unittest.cc +++ b/content/browser/dom_storage/session_storage_database_unittest.cc
@@ -17,6 +17,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/common/dom_storage/dom_storage_types.h" #include "testing/gtest/include/gtest/gtest.h" @@ -113,7 +114,7 @@ bool SessionStorageDatabaseTest::IsNamespaceKey(const std::string& key, std::string* namespace_id) { std::string namespace_prefix = SessionStorageDatabase::NamespacePrefix(); - if (key.find(namespace_prefix) != 0) + if (!base::StartsWith(key, namespace_prefix, base::CompareCase::SENSITIVE)) return false; if (key == namespace_prefix) return false; @@ -134,7 +135,7 @@ const std::string& key, std::string* namespace_id) { std::string namespace_prefix = SessionStorageDatabase::NamespacePrefix(); - if (key.find(namespace_prefix) != 0) + if (!base::StartsWith(key, namespace_prefix, base::CompareCase::SENSITIVE)) return false; size_t second_dash = key.find('-', namespace_prefix.length()); if (second_dash == std::string::npos || second_dash == key.length() - 1) @@ -152,7 +153,7 @@ bool SessionStorageDatabaseTest::IsMapRefCountKey(const std::string& key, int64_t* map_id) { std::string map_prefix = "map-"; - if (key.find(map_prefix) != 0) + if (!base::StartsWith(key, map_prefix, base::CompareCase::SENSITIVE)) return false; size_t second_dash = key.find('-', map_prefix.length()); if (second_dash != key.length() - 1) @@ -169,7 +170,7 @@ bool SessionStorageDatabaseTest::IsMapValueKey(const std::string& key, int64_t* map_id) { std::string map_prefix = "map-"; - if (key.find(map_prefix) != 0) + if (!base::StartsWith(key, map_prefix, base::CompareCase::SENSITIVE)) return false; size_t second_dash = key.find('-', map_prefix.length()); if (second_dash == std::string::npos || second_dash == key.length() - 1)
diff --git a/content/browser/download/drag_download_file.cc b/content/browser/download/drag_download_file.cc index cd68969..94725a67 100644 --- a/content/browser/download/drag_download_file.cc +++ b/content/browser/download/drag_download_file.cc
@@ -11,6 +11,7 @@ #include "base/location.h" #include "base/macros.h" #include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "content/browser/download/download_stats.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -37,13 +38,14 @@ // anyway. class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer { public: - DragDownloadFileUI(const GURL& url, - const Referrer& referrer, - const std::string& referrer_encoding, - WebContents* web_contents, - base::MessageLoop* on_completed_loop, - const OnCompleted& on_completed) - : on_completed_loop_(on_completed_loop), + DragDownloadFileUI( + const GURL& url, + const Referrer& referrer, + const std::string& referrer_encoding, + WebContents* web_contents, + scoped_refptr<base::SingleThreadTaskRunner> on_completed_task_runner, + const OnCompleted& on_completed) + : on_completed_task_runner_(on_completed_task_runner), on_completed_(on_completed), url_(url), referrer_(referrer), @@ -51,7 +53,7 @@ web_contents_(web_contents), download_item_(NULL), weak_ptr_factory_(this) { - DCHECK(on_completed_loop_); + DCHECK(on_completed_task_runner_); DCHECK(!on_completed_.is_null()); DCHECK(web_contents_); // May be called on any thread. @@ -102,8 +104,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!item || item->GetState() != DownloadItem::IN_PROGRESS) { DCHECK(!item || item->GetLastReason() != DOWNLOAD_INTERRUPT_REASON_NONE); - on_completed_loop_->task_runner()->PostTask( - FROM_HERE, base::Bind(on_completed_, false)); + on_completed_task_runner_->PostTask(FROM_HERE, + base::Bind(on_completed_, false)); return; } DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); @@ -120,7 +122,7 @@ state == DownloadItem::CANCELLED || state == DownloadItem::INTERRUPTED) { if (!on_completed_.is_null()) { - on_completed_loop_->task_runner()->PostTask( + on_completed_task_runner_->PostTask( FROM_HERE, base::Bind(on_completed_, state == DownloadItem::COMPLETE)); on_completed_.Reset(); @@ -137,7 +139,7 @@ if (!on_completed_.is_null()) { const bool is_complete = download_item_->GetState() == DownloadItem::COMPLETE; - on_completed_loop_->task_runner()->PostTask( + on_completed_task_runner_->PostTask( FROM_HERE, base::Bind(on_completed_, is_complete)); on_completed_.Reset(); } @@ -145,7 +147,7 @@ download_item_ = NULL; } - base::MessageLoop* on_completed_loop_; + scoped_refptr<base::SingleThreadTaskRunner> const on_completed_task_runner_; OnCompleted on_completed_; GURL url_; Referrer referrer_; @@ -167,16 +169,12 @@ WebContents* web_contents) : file_path_(file_path), file_(std::move(file)), - drag_message_loop_(base::MessageLoop::current()), + drag_task_runner_(base::ThreadTaskRunnerHandle::Get()), state_(INITIALIZED), drag_ui_(NULL), weak_ptr_factory_(this) { drag_ui_ = new DragDownloadFileUI( - url, - referrer, - referrer_encoding, - web_contents, - drag_message_loop_, + url, referrer, referrer_encoding, web_contents, drag_task_runner_, base::Bind(&DragDownloadFile::DownloadCompleted, weak_ptr_factory_.GetWeakPtr())); DCHECK(!file_path_.empty()); @@ -244,7 +242,7 @@ void DragDownloadFile::CheckThread() { #if defined(OS_WIN) - DCHECK(drag_message_loop_ == base::MessageLoop::current()); + DCHECK(drag_task_runner_->BelongsToCurrentThread()); #else DCHECK_CURRENTLY_ON(BrowserThread::UI); #endif
diff --git a/content/browser/download/drag_download_file.h b/content/browser/download/drag_download_file.h index f6c12f6a..4e2a8216 100644 --- a/content/browser/download/drag_download_file.h +++ b/content/browser/download/drag_download_file.h
@@ -11,8 +11,10 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" +#include "base/single_thread_task_runner.h" #include "content/browser/download/download_file.h" #include "content/common/content_export.h" #include "content/public/browser/download_item.h" @@ -59,7 +61,7 @@ base::FilePath file_path_; base::File file_; - base::MessageLoop* drag_message_loop_; + const scoped_refptr<base::SingleThreadTaskRunner> drag_task_runner_; State state_; scoped_refptr<ui::DownloadFileObserver> observer_; base::RunLoop nested_loop_;
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc index d869f06a..6b8bc12 100644 --- a/content/browser/frame_host/navigator_impl_unittest.cc +++ b/content/browser/frame_host/navigator_impl_unittest.cc
@@ -4,6 +4,7 @@ #include <stdint.h> +#include "base/feature_list.h" #include "base/macros.h" #include "base/time/time.h" #include "build/build_config.h" @@ -21,6 +22,7 @@ #include "content/common/site_isolation_policy.h" #include "content/public/browser/navigation_data.h" #include "content/public/browser/stream_handle.h" +#include "content/public/common/content_features.h" #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "content/public/test/mock_render_process_host.h" @@ -832,8 +834,15 @@ // A NavigationRequest should have been generated. NavigationRequest* main_request = node->navigation_request(); ASSERT_TRUE(main_request != NULL); - EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD, - main_request->common_params().navigation_type); + // TODO(toyoshim): Modify following checks once the feature is enabled. + if (base::FeatureList::IsEnabled( + features::kNonValidatingReloadOnNormalReload)) { + EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_MAIN_RESOURCE, + main_request->common_params().navigation_type); + } else { + EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD, + main_request->common_params().navigation_type); + } main_test_rfh()->PrepareForCommit(); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc index e3a0361..cfea857 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -297,10 +297,6 @@ const gfx::Range& range) { } -void RenderWidgetHostViewChildFrame::SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) { -} - void RenderWidgetHostViewChildFrame::LockCompositingSurface() { NOTIMPLEMENTED(); } @@ -352,6 +348,7 @@ cc::SurfaceDrawStatus drawn) { cc::CompositorFrameAck ack; DCHECK_GT(ack_pending_count_, 0U); + if (!surface_returned_resources_.empty()) ack.resources.swap(surface_returned_resources_); if (host_) {
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h index 67f11be..a569b9c 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.h +++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -106,8 +106,6 @@ void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) override; - void SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) override; void CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size,
diff --git a/content/browser/geolocation/geolocation_provider_impl.cc b/content/browser/geolocation/geolocation_provider_impl.cc index df8fd63..2343fa7d 100644 --- a/content/browser/geolocation/geolocation_provider_impl.cc +++ b/content/browser/geolocation/geolocation_provider_impl.cc
@@ -94,7 +94,7 @@ } bool GeolocationProviderImpl::OnGeolocationThread() const { - return base::MessageLoop::current() == message_loop(); + return task_runner()->BelongsToCurrentThread(); } void GeolocationProviderImpl::OnClientsChanged() {
diff --git a/content/browser/geolocation/geolocation_provider_impl_unittest.cc b/content/browser/geolocation/geolocation_provider_impl_unittest.cc index d9b30b8..62506f9 100644 --- a/content/browser/geolocation/geolocation_provider_impl_unittest.cc +++ b/content/browser/geolocation/geolocation_provider_impl_unittest.cc
@@ -157,7 +157,7 @@ } void GeolocationProviderTest::GetProvidersStarted(bool* started) { - DCHECK(base::MessageLoop::current() == provider_->message_loop()); + DCHECK(provider_->task_runner()->BelongsToCurrentThread()); *started = provider_->mock_arbitrator()->providers_started(); }
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index 0d45e84..8263e0f6 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc
@@ -190,10 +190,6 @@ } bool IsPartialRasterEnabled() { - // Zero copy currently doesn't take advantage of partial raster. - if (IsZeroCopyUploadEnabled()) - return false; - const auto& command_line = *base::CommandLine::ForCurrentProcess(); return !command_line.HasSwitch(switches::kDisablePartialRaster); }
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 9cb3b2a..dc270709 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -552,9 +552,8 @@ TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess", TRACE_EVENT_SCOPE_THREAD); - const std::string mojo_channel_token = - process_->GetHost()->CreateChannelMojo(child_token_); - if (mojo_channel_token.empty()) + std::string channel_id = process_->GetHost()->CreateChannel(); + if (channel_id.empty()) return false; DCHECK(!mojo_child_connection_); @@ -570,8 +569,8 @@ DCHECK(g_gpu_main_thread_factory); in_process_gpu_thread_.reset(g_gpu_main_thread_factory( InProcessChildThreadParams( - std::string(), base::ThreadTaskRunnerHandle::Get(), - mojo_channel_token, mojo_child_connection_->service_token()), + channel_id, base::ThreadTaskRunnerHandle::Get(), std::string(), + mojo_child_connection_->service_token()), gpu_preferences)); base::Thread::Options options; #if defined(OS_WIN) @@ -584,7 +583,7 @@ in_process_gpu_thread_->StartWithOptions(options); OnProcessLaunched(); // Fake a callback that the process is ready. - } else if (!LaunchGpuProcess(mojo_channel_token, &gpu_preferences)) { + } else if (!LaunchGpuProcess(channel_id, &gpu_preferences)) { return false; } @@ -957,7 +956,7 @@ Send(new GpuMsg_Finalize()); } -bool GpuProcessHost::LaunchGpuProcess(const std::string& mojo_channel_token, +bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id, gpu::GpuPreferences* gpu_preferences) { if (!(gpu_enabled_ && GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) && @@ -993,7 +992,7 @@ base::CommandLine* cmd_line = new base::CommandLine(exe_path); #endif cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); - cmd_line->AppendSwitchASCII(switches::kMojoChannelToken, mojo_channel_token); + cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); cmd_line->AppendSwitchASCII(switches::kMojoApplicationChannelToken, mojo_child_connection_->service_token()); BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line);
diff --git a/content/browser/iframe_zoom_browsertest.cc b/content/browser/iframe_zoom_browsertest.cc index b74135c..80ba2665 100644 --- a/content/browser/iframe_zoom_browsertest.cc +++ b/content/browser/iframe_zoom_browsertest.cc
@@ -4,6 +4,7 @@ #include <vector> +#include "base/strings/string_util.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -121,7 +122,7 @@ } void Check(const std::string& status_msg) { - if (status_msg.find(msg_label) != 0) + if (!base::StartsWith(status_msg, msg_label, base::CompareCase::SENSITIVE)) return; double inner_width = std::stod(status_msg.substr(msg_label.length() + 1));
diff --git a/content/browser/indexed_db/indexed_db_class_factory.cc b/content/browser/indexed_db/indexed_db_class_factory.cc index 71c30fd..3189b2d 100644 --- a/content/browser/indexed_db/indexed_db_class_factory.cc +++ b/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -37,12 +37,11 @@ IndexedDBTransaction* IndexedDBClassFactory::CreateIndexedDBTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& scope, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* db, IndexedDBBackingStore::Transaction* backing_store_transaction) { - return new IndexedDBTransaction(id, callbacks, scope, mode, db, + return new IndexedDBTransaction(id, std::move(connection), scope, mode, backing_store_transaction); }
diff --git a/content/browser/indexed_db/indexed_db_class_factory.h b/content/browser/indexed_db/indexed_db_class_factory.h index 2f8521032..fb4f1d7e 100644 --- a/content/browser/indexed_db/indexed_db_class_factory.h +++ b/content/browser/indexed_db/indexed_db_class_factory.h
@@ -23,6 +23,7 @@ namespace content { class IndexedDBBackingStore; +class IndexedDBConnection; class IndexedDBDatabaseCallbacks; class IndexedDBFactory; class IndexedDBTransaction; @@ -48,10 +49,9 @@ virtual IndexedDBTransaction* CreateIndexedDBTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& scope, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* db, IndexedDBBackingStore::Transaction* backing_store_transaction); virtual LevelDBIteratorImpl* CreateIteratorImpl(
diff --git a/content/browser/indexed_db/indexed_db_connection.cc b/content/browser/indexed_db/indexed_db_connection.cc index f7133a6..c2c7ebd 100644 --- a/content/browser/indexed_db/indexed_db_connection.cc +++ b/content/browser/indexed_db/indexed_db_connection.cc
@@ -4,6 +4,9 @@ #include "content/browser/indexed_db/indexed_db_connection.h" +#include "base/logging.h" +#include "base/stl_util.h" + namespace content { IndexedDBConnection::IndexedDBConnection( @@ -21,6 +24,7 @@ if (this_obj) { database_ = nullptr; callbacks_ = nullptr; + active_observers_.clear(); } } @@ -35,6 +39,7 @@ if (this_obj) { database_ = nullptr; callbacks_ = nullptr; + active_observers_.clear(); } callbacks->OnForcedClose(); } @@ -49,4 +54,31 @@ return database_.get() != NULL; } +// The observers begin listening to changes only once they are activated. +void IndexedDBConnection::ActivatePendingObservers( + std::vector<std::unique_ptr<IndexedDBObserver>> pending_observers) { + for (auto& observer : pending_observers) { + active_observers_.push_back(std::move(observer)); + } + pending_observers.clear(); +} + +void IndexedDBConnection::RemoveObservers( + const std::vector<int32_t>& observer_ids_to_remove) { + std::vector<int32_t> pending_observer_ids; + for (int32_t id_to_remove : observer_ids_to_remove) { + const auto& it = std::find_if( + active_observers_.begin(), active_observers_.end(), + [&id_to_remove](const std::unique_ptr<IndexedDBObserver>& o) { + return o->id() == id_to_remove; + }); + if (it != active_observers_.end()) + active_observers_.erase(it); + else + pending_observer_ids.push_back(id_to_remove); + } + if (!pending_observer_ids.empty()) + database_->RemovePendingObservers(this, pending_observer_ids); +} + } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_connection.h b/content/browser/indexed_db/indexed_db_connection.h index 4d828e5..3c305f3 100644 --- a/content/browser/indexed_db/indexed_db_connection.h +++ b/content/browser/indexed_db/indexed_db_connection.h
@@ -10,9 +10,9 @@ #include "base/memory/weak_ptr.h" #include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database_callbacks.h" +#include "content/browser/indexed_db/indexed_db_observer.h" namespace content { -class IndexedDBCallbacks; class IndexedDBDatabaseError; class CONTENT_EXPORT IndexedDBConnection { @@ -28,8 +28,22 @@ void VersionChangeIgnored(); + virtual void ActivatePendingObservers( + std::vector<std::unique_ptr<IndexedDBObserver>> pending_observers); + // Removes observer listed in |remove_observer_ids| from active_observer of + // connection or pending_observer of transactions associated with this + // connection. + virtual void RemoveObservers(const std::vector<int32_t>& remove_observer_ids); + IndexedDBDatabase* database() const { return database_.get(); } IndexedDBDatabaseCallbacks* callbacks() const { return callbacks_.get(); } + const std::vector<std::unique_ptr<IndexedDBObserver>>& active_observers() + const { + return active_observers_; + } + base::WeakPtr<IndexedDBConnection> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } private: // NULL in some unit tests, and after the connection is closed. @@ -38,7 +52,7 @@ // The callbacks_ member is cleared when the connection is closed. // May be NULL in unit tests. scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_; - + std::vector<std::unique_ptr<IndexedDBObserver>> active_observers_; base::WeakPtrFactory<IndexedDBConnection> weak_factory_; DISALLOW_COPY_AND_ASSIGN(IndexedDBConnection);
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 6d104a5..a73ba29 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -541,6 +541,26 @@ transaction->Abort(error); } +void IndexedDBDatabase::AddPendingObserver(int64_t transaction_id, + int32_t observer_id) { + IndexedDBTransaction* transaction = GetTransaction(transaction_id); + if (!transaction) + return; + transaction->AddPendingObserver(observer_id); +} + +void IndexedDBDatabase::RemovePendingObservers( + IndexedDBConnection* connection, + const std::vector<int32_t>& pending_observer_ids) { + TransactionMap::iterator it; + for (it = transactions_.begin(); it != transactions_.end(); it++) { + // Avoid call to RemovePendingObservers for transactions on other + // connections. + if (it->second->connection() == connection) + it->second->RemovePendingObservers(pending_observer_ids); + } +} + void IndexedDBDatabase::GetAll(int64_t transaction_id, int64_t object_store_id, int64_t index_id, @@ -1665,9 +1685,9 @@ // The transaction will add itself to this database's coordinator, which // manages the lifetime of the object. TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( - transaction_id, connection->callbacks(), + transaction_id, connection->GetWeakPtr(), std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, - this, new IndexedDBBackingStore::Transaction(backing_store_.get()))); + new IndexedDBBackingStore::Transaction(backing_store_.get()))); } void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { @@ -1905,7 +1925,7 @@ { TransactionMap transactions(transactions_); for (const auto& it : transactions) { - if (it.second->connection() == connection->callbacks()) + if (it.second->callbacks() == connection->callbacks()) it.second->Abort( IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, "Connection is closing."));
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h index bcbdb53..527b516 100644 --- a/content/browser/indexed_db/indexed_db_database.h +++ b/content/browser/indexed_db/indexed_db_database.h
@@ -125,6 +125,10 @@ // Called by transactions to report failure committing to the backing store. void TransactionCommitFailed(const leveldb::Status& status); + void AddPendingObserver(int64_t transaction_id, int32_t observer_id); + void RemovePendingObservers(IndexedDBConnection* connection, + const std::vector<int32_t>& pending_observer_ids); + void Get(int64_t transaction_id, int64_t object_store_id, int64_t index_id,
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc index f01c413e1..1ade60316 100644 --- a/content/browser/indexed_db/indexed_db_database_unittest.cc +++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -11,6 +11,7 @@ #include "base/auto_reset.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" @@ -238,9 +239,11 @@ IndexedDBDatabaseMetadata::DEFAULT_VERSION)); EXPECT_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version); + connection_ = base::WrapUnique(new IndexedDBConnection(db_, callbacks_)); transaction_ = IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( - transaction_id, callbacks_, std::set<int64_t>() /*scope*/, - blink::WebIDBTransactionModeVersionChange, db_.get(), + transaction_id, connection_->GetWeakPtr(), + std::set<int64_t>() /*scope*/, + blink::WebIDBTransactionModeVersionChange, new IndexedDBFakeBackingStore::FakeTransaction(commit_success_)); db_->TransactionCreated(transaction_.get()); @@ -258,6 +261,7 @@ scoped_refptr<MockIndexedDBCallbacks> request_; scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks_; scoped_refptr<IndexedDBTransaction> transaction_; + std::unique_ptr<IndexedDBConnection> connection_; leveldb::Status commit_success_;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc index 96cad054..aac0dd93 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -520,6 +520,8 @@ IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseVersionChangeIgnored, OnVersionChangeIgnored) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed) + IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseObserve, OnObserve) + IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseUnobserve, OnUnobserve) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGetAll, OnGetAll) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPutWrapper) @@ -629,6 +631,31 @@ parent_->DestroyObject(&map_, ipc_object_id); } +void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnObserve( + int32_t ipc_database_id, + int64_t transaction_id, + int32_t observer_id) { + DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); + IndexedDBConnection* connection = + parent_->GetOrTerminateProcess(&map_, ipc_database_id); + if (!connection || !connection->IsConnected()) + return; + connection->database()->AddPendingObserver( + parent_->HostTransactionId(transaction_id), observer_id); +} + +void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnUnobserve( + int32_t ipc_database_id, + const std::vector<int32_t>& observer_ids_to_remove) { + DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread()); + DCHECK(!observer_ids_to_remove.empty()); + IndexedDBConnection* connection = + parent_->GetOrTerminateProcess(&map_, ipc_database_id); + if (!connection || !connection->IsConnected()) + return; + connection->RemoveObservers(observer_ids_to_remove); +} + void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet( const IndexedDBHostMsg_DatabaseGet_Params& params) { DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h index ba7a65f..524c68e 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.h +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -174,6 +174,12 @@ void OnVersionChangeIgnored(int32_t ipc_database_id); void OnDestroyed(int32_t ipc_database_id); + void OnObserve(int32_t ipc_database_id, + int64_t transaction_id, + int32_t observer_id); + void OnUnobserve(int32_t ipc_database_id, + const std::vector<int32_t>& observer_ids_to_remove); + void OnGet(const IndexedDBHostMsg_DatabaseGet_Params& params); void OnGetAll(const IndexedDBHostMsg_DatabaseGetAll_Params& params); // OnPutWrapper starts on the IO thread so that it can grab BlobDataHandles
diff --git a/content/browser/indexed_db/indexed_db_observer.cc b/content/browser/indexed_db/indexed_db_observer.cc new file mode 100644 index 0000000..56d53eb --- /dev/null +++ b/content/browser/indexed_db/indexed_db_observer.cc
@@ -0,0 +1,14 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/indexed_db/indexed_db_observer.h" + +namespace content { + +IndexedDBObserver::IndexedDBObserver(int32_t observer_id) + : observer_id_(observer_id) {} + +IndexedDBObserver::~IndexedDBObserver() {} + +} // namespace content
diff --git a/content/browser/indexed_db/indexed_db_observer.h b/content/browser/indexed_db/indexed_db_observer.h new file mode 100644 index 0000000..f7bd959 --- /dev/null +++ b/content/browser/indexed_db/indexed_db_observer.h
@@ -0,0 +1,31 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_OBSERVER_H_ +#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_OBSERVER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "base/macros.h" +#include "content/common/content_export.h" + +namespace content { + +class CONTENT_EXPORT IndexedDBObserver { + public: + IndexedDBObserver(int32_t observer_id); + ~IndexedDBObserver(); + + int32_t id() const { return observer_id_; } + + private: + int32_t observer_id_; + + DISALLOW_COPY_AND_ASSIGN(IndexedDBObserver); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_OBSERVER_H_
diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc index 768cf1d..5de620d 100644 --- a/content/browser/indexed_db/indexed_db_transaction.cc +++ b/content/browser/indexed_db/indexed_db_transaction.cc
@@ -7,13 +7,16 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" +#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_cursor.h" #include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database_callbacks.h" +#include "content/browser/indexed_db/indexed_db_observer.h" #include "content/browser/indexed_db/indexed_db_tracing.h" #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h" #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h" @@ -66,10 +69,9 @@ IndexedDBTransaction::IndexedDBTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& object_store_ids, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* database, IndexedDBBackingStore::Transaction* backing_store_transaction) : id_(id), object_store_ids_(object_store_ids), @@ -77,12 +79,14 @@ used_(false), state_(CREATED), commit_pending_(false), - callbacks_(callbacks), - database_(database), + connection_(std::move(connection)), transaction_(backing_store_transaction), backing_store_transaction_begun_(false), should_process_queue_(false), pending_preemptive_events_(0) { + callbacks_ = connection_->callbacks(); + database_ = connection_->database(); + database_->transaction_coordinator().DidCreateTransaction(this); diagnostics_.tasks_scheduled = 0; @@ -98,6 +102,7 @@ DCHECK_EQ(pending_preemptive_events_, 0); DCHECK(task_queue_.empty()); DCHECK(abort_task_stack_.empty()); + DCHECK(pending_observers_.empty()); } void IndexedDBTransaction::ScheduleTask(blink::WebIDBTaskType type, @@ -191,6 +196,8 @@ database_->TransactionFinished(this, false); database_ = NULL; + connection_ = nullptr; + pending_observers_.clear(); } bool IndexedDBTransaction::IsTaskQueueEmpty() const { @@ -339,6 +346,9 @@ database_->transaction_coordinator().DidFinishTransaction(this); if (committed) { + // TODO (palakj) : Send Observations to observers + if (!pending_observers_.empty() && connection_) + connection_->ActivatePendingObservers(std::move(pending_observers_)); abort_task_stack_.clear(); { IDB_TRACE1( @@ -445,4 +455,20 @@ open_cursors_.clear(); } +void IndexedDBTransaction::AddPendingObserver(int32_t observer_id) { + pending_observers_.push_back( + base::WrapUnique(new IndexedDBObserver(observer_id))); +} + +void IndexedDBTransaction::RemovePendingObservers( + const std::vector<int32_t>& pending_observer_ids) { + const auto& it = std::remove_if( + pending_observers_.begin(), pending_observers_.end(), + [&pending_observer_ids](const std::unique_ptr<IndexedDBObserver>& o) { + return ContainsValue(pending_observer_ids, o->id()); + }); + if (it != pending_observers_.end()) + pending_observers_.erase(it, pending_observers_.end()); +} + } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h index ae1863b..e889d438 100644 --- a/content/browser/indexed_db/indexed_db_transaction.h +++ b/content/browser/indexed_db/indexed_db_transaction.h
@@ -18,6 +18,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" +#include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database_error.h" #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h" @@ -27,6 +28,7 @@ class BlobWriteCallbackImpl; class IndexedDBCursor; class IndexedDBDatabaseCallbacks; +class IndexedDBObserver; class CONTENT_EXPORT IndexedDBTransaction : public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) { @@ -63,13 +65,18 @@ pending_preemptive_events_--; DCHECK_GE(pending_preemptive_events_, 0); } + void AddPendingObserver(int32_t observer_id); + // Delete pending observers with ID's listed in |pending_observer_ids|. + void RemovePendingObservers(const std::vector<int32_t>& pending_observer_ids); + IndexedDBBackingStore::Transaction* BackingStoreTransaction() { return transaction_.get(); } int64_t id() const { return id_; } IndexedDBDatabase* database() const { return database_.get(); } - IndexedDBDatabaseCallbacks* connection() const { return callbacks_.get(); } + IndexedDBDatabaseCallbacks* callbacks() const { return callbacks_.get(); } + IndexedDBConnection* connection() const { return connection_.get(); } State state() const { return state_; } bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); } @@ -88,10 +95,9 @@ // IndexedDBClassFactory. IndexedDBTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& object_store_ids, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* db, IndexedDBBackingStore::Transaction* backing_store_transaction); virtual ~IndexedDBTransaction(); @@ -111,6 +117,7 @@ FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode, ScheduleNormalTask); FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest, Timeout); + FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest, IndexedDBObserver); void RunTasksIfStarted(); @@ -130,9 +137,13 @@ bool used_; State state_; bool commit_pending_; + base::WeakPtr<IndexedDBConnection> connection_; scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_; scoped_refptr<IndexedDBDatabase> database_; + // Observers in pending queue do not listen to changes until activated. + std::vector<std::unique_ptr<IndexedDBObserver>> pending_observers_; + class TaskQueue { public: TaskQueue();
diff --git a/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/content/browser/indexed_db/indexed_db_transaction_unittest.cc index 632b1ee..935aa167 100644 --- a/content/browser/indexed_db/indexed_db_transaction_unittest.cc +++ b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -12,6 +12,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" +#include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_fake_backing_store.h" #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" #include "content/browser/indexed_db/mock_indexed_db_factory.h" @@ -86,12 +87,11 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( - id, - new MockIndexedDBDatabaseCallbacks(), - scope, + id, connection->GetWeakPtr(), scope, blink::WebIDBTransactionModeReadWrite, - db_.get(), new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); db_->TransactionCreated(transaction.get()); @@ -130,12 +130,10 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( - id, - new MockIndexedDBDatabaseCallbacks(), - scope, - blink::WebIDBTransactionModeReadOnly, - db_.get(), + id, connection->GetWeakPtr(), scope, blink::WebIDBTransactionModeReadOnly, new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); db_->TransactionCreated(transaction.get()); @@ -162,12 +160,10 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( - id, - new MockIndexedDBDatabaseCallbacks(), - scope, - GetParam(), - db_.get(), + id, connection->GetWeakPtr(), scope, GetParam(), new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); EXPECT_FALSE(transaction->HasPendingTasks()); @@ -224,12 +220,11 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_failure = leveldb::Status::Corruption("Ouch."); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( - id, - new MockIndexedDBDatabaseCallbacks(), - scope, + id, connection->GetWeakPtr(), scope, blink::WebIDBTransactionModeVersionChange, - db_.get(), new IndexedDBFakeBackingStore::FakeTransaction(commit_failure)); EXPECT_FALSE(transaction->HasPendingTasks()); @@ -285,12 +280,10 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_failure = leveldb::Status::Corruption("Ouch."); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( - id, - new MockIndexedDBDatabaseCallbacks(), - scope, - GetParam(), - db_.get(), + id, connection->GetWeakPtr(), scope, GetParam(), new IndexedDBFakeBackingStore::FakeTransaction(commit_failure)); db_->TransactionCreated(transaction.get()); @@ -315,12 +308,10 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( - id, - new MockIndexedDBDatabaseCallbacks(), - scope, - GetParam(), - db_.get(), + id, connection->GetWeakPtr(), scope, GetParam(), new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); db_->TransactionCreated(transaction.get()); @@ -362,6 +353,49 @@ transaction->diagnostics().tasks_scheduled); } +TEST_F(IndexedDBTransactionTest, IndexedDBObserver) { + const int64_t id = 0; + const std::set<int64_t> scope; + const leveldb::Status commit_success = leveldb::Status::OK(); + std::unique_ptr<IndexedDBConnection> connection( + new IndexedDBConnection(db_, new MockIndexedDBDatabaseCallbacks())); + scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( + id, connection->GetWeakPtr(), scope, + blink::WebIDBTransactionModeReadWrite, + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); + db_->TransactionCreated(transaction.get()); + + EXPECT_EQ(0UL, transaction->pending_observers_.size()); + EXPECT_EQ(0UL, connection->active_observers().size()); + + // Add observers to pending observer list. + const int32_t observer_id1 = 1, observer_id2 = 2; + transaction->AddPendingObserver(observer_id1); + transaction->AddPendingObserver(observer_id2); + EXPECT_EQ(2UL, transaction->pending_observers_.size()); + EXPECT_EQ(0UL, connection->active_observers().size()); + + // Before commit, observer would be in pending list of transaction. + std::vector<int32_t> observer_to_remove1 = {observer_id1}; + connection->RemoveObservers(observer_to_remove1); + EXPECT_EQ(1UL, transaction->pending_observers_.size()); + EXPECT_EQ(0UL, connection->active_observers().size()); + + // After commit, observer moved to connection's active observer. + transaction->Commit(); + EXPECT_EQ(0UL, transaction->pending_observers_.size()); + EXPECT_EQ(1UL, connection->active_observers().size()); + + // Observer does not exist, so no change to active_observers. + connection->RemoveObservers(observer_to_remove1); + EXPECT_EQ(1UL, connection->active_observers().size()); + + // Observer removed from connection's active observer. + std::vector<int32_t> observer_to_remove2 = {observer_id2}; + connection->RemoveObservers(observer_to_remove2); + EXPECT_EQ(0UL, connection->active_observers().size()); +} + static const blink::WebIDBTransactionMode kTestModes[] = { blink::WebIDBTransactionModeReadOnly, blink::WebIDBTransactionModeReadWrite, blink::WebIDBTransactionModeVersionChange};
diff --git a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc index 51edd56..ec3ef6d 100644 --- a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc +++ b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
@@ -64,16 +64,14 @@ public: IndexedDBTestTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& scope, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* db, IndexedDBBackingStore::Transaction* backing_store_transaction) : IndexedDBTransaction(id, - callbacks, + std::move(connection), scope, mode, - db, backing_store_transaction) {} protected: @@ -267,12 +265,11 @@ IndexedDBTransaction* MockBrowserTestIndexedDBClassFactory::CreateIndexedDBTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& scope, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* db, IndexedDBBackingStore::Transaction* backing_store_transaction) { - return new IndexedDBTestTransaction(id, callbacks, scope, mode, db, + return new IndexedDBTestTransaction(id, std::move(connection), scope, mode, backing_store_transaction); }
diff --git a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h index 8011e72..2f91516 100644 --- a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h +++ b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
@@ -18,6 +18,7 @@ namespace content { +class IndexedDBConnection; class LevelDBTransaction; class LevelDBDatabase; @@ -47,10 +48,9 @@ const IndexedDBDatabase::Identifier& unique_identifier) override; IndexedDBTransaction* CreateIndexedDBTransaction( int64_t id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + base::WeakPtr<IndexedDBConnection> connection, const std::set<int64_t>& scope, blink::WebIDBTransactionMode mode, - IndexedDBDatabase* db, IndexedDBBackingStore::Transaction* backing_store_transaction) override; LevelDBTransaction* CreateLevelDBTransaction(LevelDBDatabase* db) override; LevelDBIteratorImpl* CreateIteratorImpl(
diff --git a/content/browser/loader/reload_cache_control_browsertest.cc b/content/browser/loader/reload_cache_control_browsertest.cc index 3858676..2ab56cad 100644 --- a/content/browser/loader/reload_cache_control_browsertest.cc +++ b/content/browser/loader/reload_cache_control_browsertest.cc
@@ -43,6 +43,18 @@ ~ReloadCacheControlBrowserTest() override = default; void SetUpOnMainThread() override { + // TODO(toyoshim): Tests in this file depend on current reload behavior, + // and should be modified when we enable the new reload behavior. + base::FeatureList::ClearInstanceForTesting(); + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine( + std::string(), features::kNonValidatingReloadOnNormalReload.name); + base::FeatureList::SetInstance(std::move(feature_list)); + + SetUpTestServerOnMainThread(); + } + + void SetUpTestServerOnMainThread() { // ContentBrowserTest creates embedded_test_server instance with // a registered HandleFileRequest for "content/test/data". // Because the handler is registered as the first handler, MonitorHandler @@ -83,7 +95,7 @@ features::kNonValidatingReloadOnNormalReload.name, std::string()); base::FeatureList::SetInstance(std::move(feature_list)); - ReloadCacheControlBrowserTest::SetUpOnMainThread(); + SetUpTestServerOnMainThread(); } DISALLOW_COPY_AND_ASSIGN(ReloadCacheControlWithAnExperimentBrowserTest);
diff --git a/content/browser/media/android/browser_media_session_manager.cc b/content/browser/media/android/browser_media_session_manager.cc index a7e5fd5b..80d3173a 100644 --- a/content/browser/media/android/browser_media_session_manager.cc +++ b/content/browser/media/android/browser_media_session_manager.cc
@@ -4,6 +4,9 @@ #include "content/browser/media/android/browser_media_session_manager.h" +#include "content/browser/media/session/media_session.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/media/media_metadata_sanitizer.h" #include "content/common/media/media_session_messages_android.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -30,15 +33,7 @@ const MediaMetadata& insecure_metadata) { // When receiving a MediaMetadata, the browser process can't trust that it is // coming from a known and secure source. It must be processed accordingly. - MediaMetadata metadata; - metadata.title = - insecure_metadata.title.substr(0, MediaMetadata::kMaxIPCStringLength); - metadata.artist = - insecure_metadata.artist.substr(0, MediaMetadata::kMaxIPCStringLength); - metadata.album = - insecure_metadata.album.substr(0, MediaMetadata::kMaxIPCStringLength); - - if (metadata != insecure_metadata) { + if (!MediaMetadataSanitizer::CheckSanity(insecure_metadata)) { render_frame_host_->GetProcess()->ShutdownForBadMessage(); return; }
diff --git a/content/browser/media/android/browser_media_session_manager.h b/content/browser/media/android/browser_media_session_manager.h index b936ba0..cd92bdc 100644 --- a/content/browser/media/android/browser_media_session_manager.h +++ b/content/browser/media/android/browser_media_session_manager.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_SESSION_MANAGER_H_ #include "base/macros.h" +#include "content/common/content_export.h" namespace IPC { class Message; @@ -16,14 +17,14 @@ class RenderFrameHost; struct MediaMetadata; -class BrowserMediaSessionManager { +class CONTENT_EXPORT BrowserMediaSessionManager { public: - BrowserMediaSessionManager(RenderFrameHost* render_frame_host); + explicit BrowserMediaSessionManager(RenderFrameHost* render_frame_host); // Message handlers. - void OnActivate(int session_id, int request_id); - void OnDeactivate(int session_id, int request_id); - void OnSetMetadata(int session_id, const MediaMetadata& metadata); + virtual void OnActivate(int session_id, int request_id); + virtual void OnDeactivate(int session_id, int request_id); + virtual void OnSetMetadata(int session_id, const MediaMetadata& metadata); int GetRoutingID() const;
diff --git a/content/browser/media/android/browser_media_session_manager_browsertest.cc b/content/browser/media/android/browser_media_session_manager_browsertest.cc new file mode 100644 index 0000000..f98d73f --- /dev/null +++ b/content/browser/media/android/browser_media_session_manager_browsertest.cc
@@ -0,0 +1,209 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/media/android/browser_media_session_manager.h" + +#include <iostream> +#include <sstream> +#include <utility> + +#include "base/command_line.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "content/browser/media/android/media_web_contents_observer_android.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/test_utils.h" +#include "content/shell/browser/shell.h" +#include "testing/gmock/include/gmock/gmock.h" + +using ::testing::_; +using ::testing::InSequence; +using ::testing::InvokeWithoutArgs; +using ::testing::Ne; + +namespace content { + +namespace { + +// Helper function for build test javascripts. +std::string BuildSetMetadataScript(const MediaMetadata& metadata) { + std::ostringstream generated_script; + + generated_script << "var audio = document.createElement(\'audio\');" + << "audio.session = new MediaSession();" + << "audio.session.metadata = new MediaMetadata({" + << "title: \"" << metadata.title << "\", " + << "artist: \"" << metadata.artist << "\", " + << "album: \"" << metadata.album << "\", " + << "artwork: ["; + + std::string artwork_separator = ""; + for (const auto& artwork : metadata.artwork) { + generated_script << artwork_separator << "{" + << "src: \"" << artwork.src.spec() << "\", " + << "type: \"" << artwork.type.string() << "\", " + << "sizes: \""; + for (const auto& size : artwork.sizes) { + generated_script << size.width() << "x" << size.height() << " "; + } + generated_script << "\"}"; + artwork_separator = ", "; + } + generated_script << "]});"; + + return generated_script.str(); +} + +} // anonymous namespace + +// Helper function to be pretty-print error messages by GMock. +void PrintTo(const MediaMetadata& metadata, std::ostream* os) { + *os << "{ title=" << metadata.title << ", "; + *os << "artist=" << metadata.artist << ", "; + *os << "album=" << metadata.album << ", "; + *os << "artwork=["; + for (const auto& artwork : metadata.artwork) { + *os << "{ src=" << artwork.src.spec() << ", "; + *os << "type=" << artwork.type.string() << ", "; + *os << "sizes=["; + for (const auto& size : artwork.sizes) { + *os << size.width() << "x" << size.height() << " "; + } + *os << "]}"; + } + *os << "]}"; +} + +class MockBrowserMediaSessionManager : public BrowserMediaSessionManager { + public: + explicit MockBrowserMediaSessionManager(RenderFrameHost* render_frame_host) + : BrowserMediaSessionManager(render_frame_host) {} + + MOCK_METHOD2(OnActiveate, void(int session_id, int request_id)); + MOCK_METHOD2(OnDeactiveate, void(int session_id, int request_id)); + MOCK_METHOD2(OnSetMetadata, void(int session_id, + const MediaMetadata& metadata)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockBrowserMediaSessionManager); +}; + +class BrowserMediaSessionManagerBrowserTest : public ContentBrowserTest { + public: + BrowserMediaSessionManagerBrowserTest() = default; + ~BrowserMediaSessionManagerBrowserTest() override = default; + + protected: + void SetUpOnMainThread() override { + ContentBrowserTest::SetUpOnMainThread(); + web_contents_ = shell()->web_contents(); + + std::unique_ptr<MockBrowserMediaSessionManager> manager( + new MockBrowserMediaSessionManager(web_contents_->GetMainFrame())); + browser_media_session_manager_ = manager.get(); + MediaWebContentsObserverAndroid::FromWebContents(web_contents_) + ->SetMediaSessionManagerForTest( + web_contents_->GetMainFrame(), std::move(manager)); + + shell()->LoadURL(GURL("about:blank")); + + ON_CALL(*browser_media_session_manager_, OnSetMetadata(_, _)) + .WillByDefault(InvokeWithoutArgs([&]{ + message_loop_runner_->Quit(); + })); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII( + switches::kEnableBlinkFeatures, "MediaSession"); + } + + WebContents* web_contents_; + MockBrowserMediaSessionManager* browser_media_session_manager_; + scoped_refptr<MessageLoopRunner> message_loop_runner_; +}; + +IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest, + TestMetadataPropagated) { + MediaMetadata expected; + expected.title = base::ASCIIToUTF16("title1"); + expected.artist = base::ASCIIToUTF16("artist1"); + expected.album = base::ASCIIToUTF16("album1"); + MediaMetadata::Artwork artwork; + artwork.src = GURL("http://foo.com/bar.png"); + artwork.type = base::NullableString16(base::ASCIIToUTF16("image/png"), false); + artwork.sizes.push_back(gfx::Size(128, 128)); + expected.artwork.push_back(artwork); + + message_loop_runner_ = new MessageLoopRunner(); + EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected)) + .Times(1); + ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), + BuildSetMetadataScript(expected))); + message_loop_runner_->Run(); +} + +IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest, + TestSetMetadataTwice) { + // Make expectations ordered. + InSequence s; + + MediaMetadata dont_care_metadata; + + MediaMetadata expected; + expected.title = base::ASCIIToUTF16("title2"); + expected.artist = base::ASCIIToUTF16("artist2"); + expected.album = base::ASCIIToUTF16("album2"); + MediaMetadata::Artwork artwork; + artwork.src = GURL("http://foo.com/bar.jpg"); + artwork.type = base::NullableString16( + base::ASCIIToUTF16("image/jpeg"), false); + artwork.sizes.push_back(gfx::Size(256, 256)); + expected.artwork.push_back(artwork); + + // Set metadata for the first time. + message_loop_runner_ = new MessageLoopRunner(); + EXPECT_CALL(*browser_media_session_manager_, + OnSetMetadata(_, dont_care_metadata)) + .Times(1); + ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), + BuildSetMetadataScript(dont_care_metadata))); + message_loop_runner_->Run(); + + // Set metadata for the second time. + message_loop_runner_ = new MessageLoopRunner(); + EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected)) + .Times(1); + ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), + BuildSetMetadataScript(expected))); + message_loop_runner_->Run(); +} + +IN_PROC_BROWSER_TEST_F(BrowserMediaSessionManagerBrowserTest, + TestFileArtworkRemoved) { + // Make expectations ordered. + InSequence s; + + MediaMetadata dirty_metadata; + MediaMetadata::Artwork file_artwork; + file_artwork.src = GURL("file:///foo/bar.jpg"); + file_artwork.type = base::NullableString16( + base::ASCIIToUTF16("image/jpeg"), false); + dirty_metadata.artwork.push_back(file_artwork); + + MediaMetadata expected; + + // Set metadata for the first time. + message_loop_runner_ = new MessageLoopRunner(); + EXPECT_CALL(*browser_media_session_manager_, OnSetMetadata(_, expected)) + .Times(1); + ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), + BuildSetMetadataScript(dirty_metadata))); + message_loop_runner_->Run(); +} + +} // namespace content
diff --git a/content/browser/media/android/media_web_contents_observer_android.cc b/content/browser/media/android/media_web_contents_observer_android.cc index 5a6c451f..3912563 100644 --- a/content/browser/media/android/media_web_contents_observer_android.cc +++ b/content/browser/media/android/media_web_contents_observer_android.cc
@@ -4,6 +4,8 @@ #include "content/browser/media/android/media_web_contents_observer_android.h" +#include <utility> + #include "base/memory/ptr_util.h" #include "content/browser/media/android/browser_media_player_manager.h" #include "content/browser/media/android/browser_media_session_manager.h" @@ -80,6 +82,12 @@ return manager; } +void MediaWebContentsObserverAndroid::SetMediaSessionManagerForTest( + RenderFrameHost* render_frame_host, + std::unique_ptr<BrowserMediaSessionManager> manager) { + media_session_managers_.set(render_frame_host, std::move(manager)); +} + void MediaWebContentsObserverAndroid::SuspendAllMediaPlayers() { web_contents()->ForEachFrame( base::Bind(&SuspendAllMediaPlayersInRenderFrame));
diff --git a/content/browser/media/android/media_web_contents_observer_android.h b/content/browser/media/android/media_web_contents_observer_android.h index 0f3a2a9..2531fe0 100644 --- a/content/browser/media/android/media_web_contents_observer_android.h +++ b/content/browser/media/android/media_web_contents_observer_android.h
@@ -42,6 +42,12 @@ BrowserSurfaceViewManager* GetSurfaceViewManager( RenderFrameHost* render_frame_host); + // Sets or overrides the BrowserMediaSessionManager for the given + // |render_frame_host|. + void SetMediaSessionManagerForTest( + RenderFrameHost* render_frame_host, + std::unique_ptr<BrowserMediaSessionManager> manager); + // Called by the WebContents when a tab has been closed but may still be // available for "undo" -- indicates that all media players (even audio only // players typically allowed background audio) bound to this WebContents must
diff --git a/content/browser/media/session/media_session.cc b/content/browser/media/session/media_session.cc index 5c63545..33fa652 100644 --- a/content/browser/media/session/media_session.cc +++ b/content/browser/media/session/media_session.cc
@@ -58,6 +58,14 @@ DCHECK(audio_focus_state_ == State::INACTIVE); } +void MediaSession::SetMetadata(const MediaMetadata& metadata) { + metadata_ = metadata; + // TODO(zqzhang): On Android, the metadata is sent though JNI everytime the + // media session play/pause state changes. Need to find a way to seprate the + // state change and Metadata update. See https://crbug.com/621855. + static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged(); +} + bool MediaSession::AddPlayer(MediaSessionObserver* observer, int player_id, Type type) {
diff --git a/content/browser/media/session/media_session.h b/content/browser/media/session/media_session.h index 3c0cf159..9e961f4 100644 --- a/content/browser/media/session/media_session.h +++ b/content/browser/media/session/media_session.h
@@ -62,9 +62,7 @@ ~MediaSession() override; - void setMetadata(const MediaMetadata& metadata) { - metadata_ = metadata; - } + void SetMetadata(const MediaMetadata& metadata); const MediaMetadata& metadata() const { return metadata_; } // Adds the given player to the current media session. Returns whether the
diff --git a/content/browser/media/webrtc/webrtc_eventlog_host.cc b/content/browser/media/webrtc/webrtc_eventlog_host.cc new file mode 100644 index 0000000..279ed48 --- /dev/null +++ b/content/browser/media/webrtc/webrtc_eventlog_host.cc
@@ -0,0 +1,157 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/media/webrtc/webrtc_eventlog_host.h" + +#include <algorithm> +#include <string> + +#include "base/files/file_util.h" +#include "base/strings/string_number_conversions.h" +#include "content/browser/media/webrtc/webrtc_internals.h" +#include "content/common/media/peer_connection_tracker_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" + +#if defined(OS_WIN) +#define IntToStringType base::IntToString16 +#else +#define IntToStringType base::IntToString +#endif + +namespace content { + +int WebRTCEventLogHost::number_active_log_files_ = 0; + +namespace { + +// In addition to the limit to the number of files given below, the size of the +// files is also capped, see content/renderer/media/peer_connection_tracker.cc. +#if defined(OS_ANDROID) +const int kMaxNumberLogFiles = 3; +#else +const int kMaxNumberLogFiles = 5; +#endif + +// Appends the IDs to the RTC event log file name. +base::FilePath GetWebRtcEventLogPath(const base::FilePath& base_file, + int render_process_id, + int connection_id) { + return base_file.AddExtension(IntToStringType(render_process_id)) + .AddExtension(IntToStringType(connection_id)); +} + +// Opens a logfile to pass on to the renderer. +IPC::PlatformFileForTransit CreateFileForProcess( + const base::FilePath& base_path, + int render_process_id, + int connection_id) { + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + base::FilePath file_path = + GetWebRtcEventLogPath(base_path, render_process_id, connection_id); + base::File event_log_file( + file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + if (!event_log_file.IsValid()) { + PLOG(ERROR) << "Could not open WebRTC event log file, error=" + << event_log_file.error_details(); + return IPC::InvalidPlatformFileForTransit(); + } + return IPC::TakePlatformFileForTransit(std::move(event_log_file)); +} + +} // namespace + +WebRTCEventLogHost::WebRTCEventLogHost(int render_process_id) + : render_process_id_(render_process_id), + rtc_event_logging_enabled_(false), + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto webrtc_internals = WebRTCInternals::GetInstance(); + if (webrtc_internals->IsEventLogRecordingsEnabled()) + StartWebRTCEventLog(webrtc_internals->GetEventLogFilePath()); +} + +WebRTCEventLogHost::~WebRTCEventLogHost() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); +} + +void WebRTCEventLogHost::PeerConnectionAdded(int peer_connection_local_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(std::find(active_peer_connection_local_ids_.begin(), + active_peer_connection_local_ids_.end(), + peer_connection_local_id) == + active_peer_connection_local_ids_.end()); + active_peer_connection_local_ids_.push_back(peer_connection_local_id); + if (rtc_event_logging_enabled_ && + number_active_log_files_ < kMaxNumberLogFiles) { + StartEventLogForPeerConnection(peer_connection_local_id); + } +} + +void WebRTCEventLogHost::PeerConnectionRemoved(int peer_connection_local_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + const auto found = std::find(active_peer_connection_local_ids_.begin(), + active_peer_connection_local_ids_.end(), + peer_connection_local_id); + DCHECK(found != active_peer_connection_local_ids_.end()); + active_peer_connection_local_ids_.erase(found); +} + +bool WebRTCEventLogHost::StartWebRTCEventLog(const base::FilePath& file_path) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (rtc_event_logging_enabled_) + return false; + rtc_event_logging_enabled_ = true; + base_file_path_ = file_path; + for (int local_id : active_peer_connection_local_ids_) + StartEventLogForPeerConnection(local_id); + return true; +} + +bool WebRTCEventLogHost::StopWebRTCEventLog() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!rtc_event_logging_enabled_) + return false; + number_active_log_files_ = 0; + rtc_event_logging_enabled_ = false; + RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_); + if (host) { + for (int local_id : active_peer_connection_local_ids_) + host->Send(new PeerConnectionTracker_StopEventLog(local_id)); + } + return true; +} + +bool WebRTCEventLogHost::StartEventLogForPeerConnection( + int peer_connection_local_id) { + if (number_active_log_files_ < kMaxNumberLogFiles) { + ++number_active_log_files_; + BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::FILE, FROM_HERE, + base::Bind(&CreateFileForProcess, base_file_path_, render_process_id_, + peer_connection_local_id), + base::Bind(&WebRTCEventLogHost::SendEventLogFileToRenderer, + weak_ptr_factory_.GetWeakPtr(), peer_connection_local_id)); + } + return true; +} + +void WebRTCEventLogHost::SendEventLogFileToRenderer( + int peer_connection_local_id, + IPC::PlatformFileForTransit file_for_transit) { + if (file_for_transit == IPC::InvalidPlatformFileForTransit()) { + --number_active_log_files_; + return; + } + RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id_); + if (rph) { + rph->Send(new PeerConnectionTracker_StartEventLog(peer_connection_local_id, + file_for_transit)); + } else { + --number_active_log_files_; + IPC::PlatformFileForTransitToFile(file_for_transit).Close(); + } +} + +} // namespace content
diff --git a/content/browser/media/webrtc/webrtc_eventlog_host.h b/content/browser/media/webrtc/webrtc_eventlog_host.h new file mode 100644 index 0000000..8c3377a --- /dev/null +++ b/content/browser/media/webrtc/webrtc_eventlog_host.h
@@ -0,0 +1,75 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENTLOG_HOST_H_ +#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENTLOG_HOST_H_ + +#include <vector> + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" +#include "ipc/ipc_platform_file.h" + +namespace content { + +// This class is used to enable and disable WebRTC event logs on each of the +// PeerConnections in the render process. This class and all its members should +// only be accessed from the Browser UI thread. +class CONTENT_EXPORT WebRTCEventLogHost { + public: + explicit WebRTCEventLogHost(int render_process_id); + ~WebRTCEventLogHost(); + + // Starts an RTC event log for all current and future PeerConnections on the + // render process. A base file_path can be supplied, which will be extended to + // include several identifiers to ensure uniqueness. If a recording was + // already in progress, this call will return false and have no other effect. + bool StartWebRTCEventLog(const base::FilePath& file_path); + + // Stops recording an RTC event log for each PeerConnection on the render + // process. If no recording was in progress, this call will return false. + bool StopWebRTCEventLog(); + + // This function should be used to notify the WebRTCEventLogHost object that a + // PeerConnection was created in the corresponding render process. + void PeerConnectionAdded(int peer_connection_local_id); + + // This function should be used to notify the WebRTCEventLogHost object that a + // PeerConnection was removed in the corresponding render process. + void PeerConnectionRemoved(int peer_connection_local_id); + + private: + // Actually start the eventlog for a single PeerConnection using the path + // stored in base_file_path_. + bool StartEventLogForPeerConnection(int peer_connection_local_id); + + // Send the platform file to the render process using an IPC message. + void SendEventLogFileToRenderer(int peer_connection_local_id, + IPC::PlatformFileForTransit file_for_transit); + + // The render process ID that this object is associated with. + const int render_process_id_; + + // In case new PeerConnections are created during logging, the path is needed + // to enable logging for them. + base::FilePath base_file_path_; + + // The local identifiers of all the currently active PeerConnections. + std::vector<int> active_peer_connection_local_ids_; + + // Number of active log files that have been opened. + static int number_active_log_files_; + + // Track if the RTC event log is currently active. + bool rtc_event_logging_enabled_; + + base::WeakPtrFactory<WebRTCEventLogHost> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(WebRTCEventLogHost); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENTLOG_HOST_H_
diff --git a/content/browser/media/webrtc/webrtc_eventlog_host_unittest.cc b/content/browser/media/webrtc/webrtc_eventlog_host_unittest.cc new file mode 100644 index 0000000..c8d73a09 --- /dev/null +++ b/content/browser/media/webrtc/webrtc_eventlog_host_unittest.cc
@@ -0,0 +1,268 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/media/webrtc/webrtc_eventlog_host.h" + +#include <tuple> + +#include "base/files/file.h" +#include "base/files/file_util.h" +#include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" +#include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/common/media/peer_connection_tracker_messages.h" +#include "content/public/browser/browser_context.h" +#include "content/public/test/mock_render_process_host.h" +#include "content/public/test/test_browser_context.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if defined(OS_WIN) +#define IntToStringType base::IntToString16 +#else +#define IntToStringType base::IntToString +#endif + +namespace content { + +namespace { + +// Get the expected Rtc eventlog file name. The name will be +// <temporary path>.<render process id>.<peer connection local id> +base::FilePath GetExpectedEventLogFileName(const base::FilePath& base_file, + int render_process_id, + int peer_connection_local_id) { + return base_file.AddExtension(IntToStringType(render_process_id)) + .AddExtension(IntToStringType(peer_connection_local_id)); +} + +} // namespace + +class WebRtcEventlogHostTest : public testing::Test { + public: + WebRtcEventlogHostTest() + : mock_render_process_host_(static_cast<MockRenderProcessHost*>( + mock_render_process_factory_.CreateRenderProcessHost( + &test_browser_context_, + nullptr))), + render_id_(mock_render_process_host_->GetID()), + event_log_host_(render_id_) {} + TestBrowserThreadBundle thread_bundle_; + MockRenderProcessHostFactory mock_render_process_factory_; + TestBrowserContext test_browser_context_; + std::unique_ptr<MockRenderProcessHost> mock_render_process_host_; + const int render_id_; + WebRTCEventLogHost event_log_host_; + base::FilePath base_file_; + + void StartLogging() { + ASSERT_TRUE(base::CreateTemporaryFile(&base_file_)); + EXPECT_TRUE(base::DeleteFile(base_file_, false)); + EXPECT_FALSE(base::PathExists(base_file_)); + EXPECT_TRUE(event_log_host_.StartWebRTCEventLog(base_file_)); + base::RunLoop().RunUntilIdle(); + } + + void StopLogging() { + EXPECT_TRUE(event_log_host_.StopWebRTCEventLog()); + base::RunLoop().RunUntilIdle(); + } + + void ValidateStartIPCMessageAndCloseFile(const IPC::Message* msg, + const int peer_connection_id) { + ASSERT_TRUE(msg); + std::tuple<int, IPC::PlatformFileForTransit> start_params; + PeerConnectionTracker_StartEventLog::Read(msg, &start_params); + EXPECT_EQ(peer_connection_id, std::get<0>(start_params)); + ASSERT_NE(IPC::InvalidPlatformFileForTransit(), std::get<1>(start_params)); + IPC::PlatformFileForTransitToFile(std::get<1>(start_params)).Close(); + } + + void ValidateStopIPCMessage(const IPC::Message* msg, + const int peer_connection_id) { + ASSERT_TRUE(msg); + std::tuple<int> stop_params; + PeerConnectionTracker_StopEventLog::Read(msg, &stop_params); + EXPECT_EQ(peer_connection_id, std::get<0>(stop_params)); + } +}; + +// This test calls StartWebRTCEventLog() and StopWebRTCEventLog() without having +// added any PeerConnections. It is expected that no IPC messages will be sent. +TEST_F(WebRtcEventlogHostTest, NoPeerConnectionTest) { + mock_render_process_host_->sink().ClearMessages(); + + // Start logging and check that no IPC messages were sent. + StartLogging(); + EXPECT_EQ(size_t(0), mock_render_process_host_->sink().message_count()); + + // Stop logging and check that no IPC messages were sent. + StopLogging(); + EXPECT_EQ(size_t(0), mock_render_process_host_->sink().message_count()); +} + +// This test calls StartWebRTCEventLog() and StopWebRTCEventLog() after adding a +// single PeerConnection. It is expected that one IPC message will be sent for +// each of the Start and Stop calls, and that a logfile is created. +TEST_F(WebRtcEventlogHostTest, OnePeerConnectionTest) { + const int kTestPeerConnectionId = 123; + mock_render_process_host_->sink().ClearMessages(); + + // Add a PeerConnection and start logging. + event_log_host_.PeerConnectionAdded(kTestPeerConnectionId); + StartLogging(); + + // Check that the correct IPC message was sent. + EXPECT_EQ(size_t(1), mock_render_process_host_->sink().message_count()); + const IPC::Message* start_msg = + mock_render_process_host_->sink().GetMessageAt(0); + ValidateStartIPCMessageAndCloseFile(start_msg, kTestPeerConnectionId); + + // Stop logging. + mock_render_process_host_->sink().ClearMessages(); + StopLogging(); + + // Check that the correct IPC message was sent. + EXPECT_EQ(size_t(1), mock_render_process_host_->sink().message_count()); + const IPC::Message* stop_msg = + mock_render_process_host_->sink().GetMessageAt(0); + ValidateStopIPCMessage(stop_msg, kTestPeerConnectionId); + + // Clean up the logfile. + base::FilePath expected_file = GetExpectedEventLogFileName( + base_file_, render_id_, kTestPeerConnectionId); + ASSERT_TRUE(base::PathExists(expected_file)); + EXPECT_TRUE(base::DeleteFile(expected_file, false)); +} + +// This test calls StartWebRTCEventLog() and StopWebRTCEventLog() after adding +// two PeerConnections. It is expected that two IPC messages will be sent for +// each of the Start and Stop calls, and that a file is created for both +// PeerConnections. +TEST_F(WebRtcEventlogHostTest, TwoPeerConnectionsTest) { + const int kTestPeerConnectionId1 = 123; + const int kTestPeerConnectionId2 = 321; + mock_render_process_host_->sink().ClearMessages(); + + // Add two PeerConnections and start logging. + event_log_host_.PeerConnectionAdded(kTestPeerConnectionId1); + event_log_host_.PeerConnectionAdded(kTestPeerConnectionId2); + StartLogging(); + + // Check that the correct IPC messages were sent. + EXPECT_EQ(size_t(2), mock_render_process_host_->sink().message_count()); + const IPC::Message* start_msg1 = + mock_render_process_host_->sink().GetMessageAt(0); + ValidateStartIPCMessageAndCloseFile(start_msg1, kTestPeerConnectionId1); + const IPC::Message* start_msg2 = + mock_render_process_host_->sink().GetMessageAt(1); + ValidateStartIPCMessageAndCloseFile(start_msg2, kTestPeerConnectionId2); + + // Stop logging. + mock_render_process_host_->sink().ClearMessages(); + StopLogging(); + + // Check that the correct IPC messages were sent. + EXPECT_EQ(size_t(2), mock_render_process_host_->sink().message_count()); + const IPC::Message* stop_msg1 = + mock_render_process_host_->sink().GetMessageAt(0); + ValidateStopIPCMessage(stop_msg1, kTestPeerConnectionId1); + const IPC::Message* stop_msg2 = + mock_render_process_host_->sink().GetMessageAt(1); + ValidateStopIPCMessage(stop_msg2, kTestPeerConnectionId2); + + // Clean up the logfiles. + base::FilePath expected_file1 = GetExpectedEventLogFileName( + base_file_, render_id_, kTestPeerConnectionId1); + base::FilePath expected_file2 = GetExpectedEventLogFileName( + base_file_, render_id_, kTestPeerConnectionId2); + ASSERT_TRUE(base::PathExists(expected_file1)); + EXPECT_TRUE(base::DeleteFile(expected_file1, false)); + ASSERT_TRUE(base::PathExists(expected_file2)); + EXPECT_TRUE(base::DeleteFile(expected_file2, false)); +} + +// This test calls StartWebRTCEventLog() and StopWebRTCEventLog() after adding +// more PeerConnections than the maximum allowed. It is expected that only the +// maximum allowed number of IPC messages and log files will be opened, but we +// expect the number of stop IPC messages to be equal to the actual number of +// PeerConnections. +TEST_F(WebRtcEventlogHostTest, ExceedMaxPeerConnectionsTest) { +#if defined(OS_ANDROID) + const int kMaxNumberLogFiles = 3; +#else + const int kMaxNumberLogFiles = 5; +#endif + const int kNumberOfPeerConnections = kMaxNumberLogFiles + 1; + mock_render_process_host_->sink().ClearMessages(); + + // Add the maximum number + 1 PeerConnections and start logging. + for (int i = 0; i < kNumberOfPeerConnections; ++i) + event_log_host_.PeerConnectionAdded(i); + StartLogging(); + + // Check that the correct IPC messages were sent. + ASSERT_EQ(size_t(kMaxNumberLogFiles), + mock_render_process_host_->sink().message_count()); + for (int i = 0; i < kMaxNumberLogFiles; ++i) { + const IPC::Message* start_msg = + mock_render_process_host_->sink().GetMessageAt(i); + ValidateStartIPCMessageAndCloseFile(start_msg, i); + } + + // Stop logging. + mock_render_process_host_->sink().ClearMessages(); + StopLogging(); + + // Check that the correct IPC messages were sent. + ASSERT_EQ(size_t(kNumberOfPeerConnections), + mock_render_process_host_->sink().message_count()); + for (int i = 0; i < kNumberOfPeerConnections; ++i) { + const IPC::Message* stop_msg = + mock_render_process_host_->sink().GetMessageAt(i); + ValidateStopIPCMessage(stop_msg, i); + } + + // Clean up the logfiles. + for (int i = 0; i < kMaxNumberLogFiles; ++i) { + base::FilePath expected_file = + GetExpectedEventLogFileName(base_file_, render_id_, i); + ASSERT_TRUE(base::PathExists(expected_file)); + EXPECT_TRUE(base::DeleteFile(expected_file, false)); + } + + // Check that not too many files were created. + for (int i = kMaxNumberLogFiles; i < kNumberOfPeerConnections; ++i) { + base::FilePath expected_file = + GetExpectedEventLogFileName(base_file_, render_id_, i); + EXPECT_FALSE(base::PathExists(expected_file)); + } +} + +// This test calls StartWebRTCEventLog() and StopWebRTCEventLog() after first +// adding and then removing a single PeerConnection. It is expected that no IPC +// message will be sent. +TEST_F(WebRtcEventlogHostTest, AddRemovePeerConnectionTest) { + const int kTestPeerConnectionId = 123; + mock_render_process_host_->sink().ClearMessages(); + + // Add and immediately remove a PeerConnection. + event_log_host_.PeerConnectionAdded(kTestPeerConnectionId); + event_log_host_.PeerConnectionRemoved(kTestPeerConnectionId); + + // Start logging and check that no IPC messages were sent. + StartLogging(); + EXPECT_EQ(size_t(0), mock_render_process_host_->sink().message_count()); + + // Stop logging and check that no IPC messages were sent. + StopLogging(); + EXPECT_EQ(size_t(0), mock_render_process_host_->sink().message_count()); + + // Check that no logfile was created. + base::FilePath expected_file = GetExpectedEventLogFileName( + base_file_, render_id_, kTestPeerConnectionId); + ASSERT_FALSE(base::PathExists(expected_file)); +} + +} // namespace content
diff --git a/content/browser/media/webrtc/webrtc_internals.cc b/content/browser/media/webrtc/webrtc_internals.cc index 1a1d57f1..070dfb3 100644 --- a/content/browser/media/webrtc/webrtc_internals.cc +++ b/content/browser/media/webrtc/webrtc_internals.cc
@@ -9,12 +9,19 @@ #include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "content/browser/media/webrtc/webrtc_internals_ui_observer.h" +#include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/web_contents/web_contents_view.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "device/power_save_blocker/power_save_blocker.h" +#include "ipc/ipc_platform_file.h" + +#if defined(OS_WIN) +#define IntToStringType base::IntToString16 +#else +#define IntToStringType base::IntToString +#endif using base::ProcessId; using std::string; @@ -252,10 +259,13 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); observers_.RemoveObserver(observer); - // Disables audio debug recordings if it is enabled and the last + // Disables event log and audio debug recordings if enabled and the last // webrtc-internals page is going away. - if (audio_debug_recordings_ && !observers_.might_have_observers()) - DisableAudioDebugRecordings(); + if (!observers_.might_have_observers()) { + if (audio_debug_recordings_) + DisableAudioDebugRecordings(); + DisableEventLogRecordings(); + } } void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) { @@ -318,37 +328,34 @@ return audio_debug_recordings_file_path_; } -void WebRTCInternals::SetEventLogRecordings( - bool enable, +void WebRTCInternals::EnableEventLogRecordings( content::WebContents* web_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(ENABLE_WEBRTC) - if (enable) { #if defined(OS_ANDROID) - EnableEventLogRecordingsOnAllRenderProcessHosts(); + EnableEventLogRecordingsOnAllRenderProcessHosts(); #else - DCHECK(web_contents); - DCHECK(!select_file_dialog_); - selecting_event_log_ = true; - select_file_dialog_ = ui::SelectFileDialog::Create(this, nullptr); - select_file_dialog_->SelectFile( - ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), - event_log_recordings_file_path_, nullptr, 0, FILE_PATH_LITERAL(""), - web_contents->GetTopLevelNativeWindow(), nullptr); + DCHECK(web_contents); + DCHECK(!select_file_dialog_); + selecting_event_log_ = true; + select_file_dialog_ = ui::SelectFileDialog::Create(this, nullptr); + select_file_dialog_->SelectFile( + ui::SelectFileDialog::SELECT_SAVEAS_FILE, base::string16(), + event_log_recordings_file_path_, nullptr, 0, FILE_PATH_LITERAL(""), + web_contents->GetTopLevelNativeWindow(), nullptr); #endif - } else { - event_log_recordings_ = false; - // Tear down the dialog since the user has unchecked the audio debug - // recordings box. - select_file_dialog_ = nullptr; - DCHECK(select_file_dialog_->HasOneRef()); +#endif +} - for (RenderProcessHost::iterator i( - content::RenderProcessHost::AllHostsIterator()); - !i.IsAtEnd(); i.Advance()) { - i.GetCurrentValue()->DisableEventLogRecordings(); - } - } +void WebRTCInternals::DisableEventLogRecordings() { +#if defined(ENABLE_WEBRTC) + event_log_recordings_ = false; + // Tear down the dialog since the user has unchecked the event log checkbox. + select_file_dialog_ = nullptr; + for (RenderProcessHost::iterator i( + content::RenderProcessHost::AllHostsIterator()); + !i.IsAtEnd(); i.Advance()) + i.GetCurrentValue()->StopWebRTCEventLog(); #endif } @@ -357,7 +364,7 @@ return event_log_recordings_; } -const base::FilePath& WebRTCInternals::GetEventLogRecordingsFilePath() const { +const base::FilePath& WebRTCInternals::GetEventLogFilePath() const { DCHECK_CURRENTLY_ON(BrowserThread::UI); return event_log_recordings_file_path_; } @@ -483,10 +490,8 @@ event_log_recordings_ = true; for (RenderProcessHost::iterator i( content::RenderProcessHost::AllHostsIterator()); - !i.IsAtEnd(); i.Advance()) { - i.GetCurrentValue()->EnableEventLogRecordings( - event_log_recordings_file_path_); - } + !i.IsAtEnd(); i.Advance()) + i.GetCurrentValue()->StartWebRTCEventLog(event_log_recordings_file_path_); } #endif
diff --git a/content/browser/media/webrtc/webrtc_internals.h b/content/browser/media/webrtc/webrtc_internals.h index ddcb671..35a1d89 100644 --- a/content/browser/media/webrtc/webrtc_internals.h +++ b/content/browser/media/webrtc/webrtc_internals.h
@@ -102,10 +102,11 @@ const base::FilePath& GetAudioDebugRecordingsFilePath() const; // Enables or disables diagnostic event log. - void SetEventLogRecordings(bool enable, content::WebContents* web_contents); + void EnableEventLogRecordings(content::WebContents* web_contents); + void DisableEventLogRecordings(); bool IsEventLogRecordingsEnabled() const; - const base::FilePath& GetEventLogRecordingsFilePath() const; + const base::FilePath& GetEventLogFilePath() const; protected: // Constructor/Destructor are protected to allow tests to derive from the
diff --git a/content/browser/media/webrtc/webrtc_internals_message_handler.cc b/content/browser/media/webrtc/webrtc_internals_message_handler.cc index eaaea95a..ea74c5b 100644 --- a/content/browser/media/webrtc/webrtc_internals_message_handler.cc +++ b/content/browser/media/webrtc/webrtc_internals_message_handler.cc
@@ -94,8 +94,12 @@ void WebRTCInternalsMessageHandler::OnSetEventLogRecordingsEnabled( bool enable, const base::ListValue* /* unused_list */) { - WebRTCInternals::GetInstance()->SetEventLogRecordings( - enable, enable ? web_ui()->GetWebContents() : nullptr); + if (enable) { + WebRTCInternals::GetInstance()->EnableEventLogRecordings( + web_ui()->GetWebContents()); + } else { + WebRTCInternals::GetInstance()->DisableEventLogRecordings(); + } } void WebRTCInternalsMessageHandler::OnDOMLoadDone(
diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc index 7f4177f..a7148d1 100644 --- a/content/browser/mojo/mojo_shell_context.cc +++ b/content/browser/mojo/mojo_shell_context.cc
@@ -267,11 +267,10 @@ mojo::edk::SetParentPipeHandleFromCommandLine(); request = shell::GetServiceRequestFromCommandLine(); } else { - service_manager_.reset( - new shell::ServiceManager(std::move(native_runner_factory), - catalog_->TakeService())); - request = service_manager_->StartEmbedderService( - kBrowserMojoApplicationName); + service_manager_.reset(new shell::ServiceManager( + std::move(native_runner_factory), catalog_->TakeService())); + request = + service_manager_->StartEmbedderService(kBrowserMojoApplicationName); } MojoShellConnection::SetForProcess( MojoShellConnection::Create(std::move(request)));
diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc index b7f0a6c..6d572ab 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc +++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -15,6 +15,7 @@ #include "base/callback_helpers.h" #include "base/i18n/case_conversion.h" #include "base/logging.h" +#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string16.h" #include "base/strings/string_util.h" @@ -42,11 +43,40 @@ FONT_LOADER_TYPE_MAX_VALUE }; +// This enum is used to define the buckets for an enumerated UMA histogram. +// Hence, +// (a) existing enumerated constants should never be deleted or reordered, and +// (b) new constants should only be appended at the end of the enumeration. +enum MessageFilterError { + LAST_RESORT_FONT_GET_FONT_FAILED = 0, + LAST_RESORT_FONT_ADD_FILES_FAILED = 1, + LAST_RESORT_FONT_GET_FAMILY_FAILED = 2, + ERROR_NO_COLLECTION = 3, + MAP_CHARACTERS_NO_FAMILY = 4, + + MESSAGE_FILTER_ERROR_MAX_VALUE +}; + void LogLoaderType(DirectWriteFontLoaderType loader_type) { UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoaderType", loader_type, FONT_LOADER_TYPE_MAX_VALUE); } +void LogLastResortFontCount(size_t count) { + UMA_HISTOGRAM_COUNTS_100("DirectWrite.Fonts.Proxy.LastResortFontCount", + count); +} + +void LogLastResortFontFileCount(size_t count) { + UMA_HISTOGRAM_COUNTS_100("DirectWrite.Fonts.Proxy.LastResortFontFileCount", + count); +} + +void LogMessageFilterError(MessageFilterError error) { + UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.MessageFilterError", error, + MESSAGE_FILTER_ERROR_MAX_VALUE); +} + const wchar_t* kFontsToIgnore[] = { // "Gill Sans Ultra Bold" turns into an Ultra Bold weight "Gill Sans" in // DirectWrite, but most users don't have any other weights. The regular @@ -75,6 +105,11 @@ return base::i18n::FoldCase(font_path_chars.data()); } +// These are the fonts that Blink tries to load in getLastResortFallbackFont, +// and will crash if none can be loaded. +const wchar_t* kLastResortFontNames[] = {L"Sans", L"Arial", L"MS UI Gothic", + L"Microsoft Sans Serif"}; + } // namespace DWriteFontProxyMessageFilter::DWriteFontProxyMessageFilter() @@ -203,6 +238,8 @@ mswr::ComPtr<IDWriteFontFamily> family; HRESULT hr = collection_->GetFontFamily(family_index, &family); if (FAILED(hr)) { + if (IsLastResortFallbackFont(family_index)) + LogMessageFilterError(LAST_RESORT_FONT_GET_FAMILY_FAILED); return; } @@ -216,13 +253,19 @@ mswr::ComPtr<IDWriteFont> font; hr = family->GetFont(font_index, &font); if (FAILED(hr)) { + if (IsLastResortFallbackFont(family_index)) + LogMessageFilterError(LAST_RESORT_FONT_GET_FONT_FAILED); return; } - AddFilesForFont(&path_set, font.Get()); + if (!AddFilesForFont(&path_set, font.Get())) { + if (IsLastResortFallbackFont(family_index)) + LogMessageFilterError(LAST_RESORT_FONT_ADD_FILES_FAILED); + } } file_paths->assign(path_set.begin(), path_set.end()); + LogLastResortFontFileCount(file_paths->size()); } void DWriteFontProxyMessageFilter::OnMapCharacters( @@ -318,8 +361,7 @@ return; } // Could not find a matching family - // TODO(kulshin): log UMA that we matched a font, but could not locate the - // family + LogMessageFilterError(MAP_CHARACTERS_NO_FAMILY); DCHECK_EQ(result->family_index, UINT32_MAX); DCHECK_GT(result->mapped_length, 0u); } @@ -344,6 +386,23 @@ HRESULT hr = factory->GetSystemFontCollection(&collection_); DCHECK(SUCCEEDED(hr)); + + if (!collection_) { + LogMessageFilterError(ERROR_NO_COLLECTION); + return; + } + + // Temp code to help track down crbug.com/561873 + for (size_t font = 0; font < arraysize(kLastResortFontNames); font++) { + uint32_t font_index = 0; + BOOL exists = FALSE; + if (SUCCEEDED(collection_->FindFamilyName(kLastResortFontNames[font], + &font_index, &exists)) && + exists && font_index != UINT32_MAX) { + last_resort_fonts_.push_back(font_index); + } + } + LogLastResortFontCount(last_resort_fonts_.size()); } bool DWriteFontProxyMessageFilter::AddFilesForFont( @@ -471,4 +530,14 @@ return true; } +bool DWriteFontProxyMessageFilter::IsLastResortFallbackFont( + uint32_t font_index) { + for (auto iter = last_resort_fonts_.begin(); iter != last_resort_fonts_.end(); + ++iter) { + if (*iter == font_index) + return true; + } + return false; +} + } // namespace content
diff --git a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h index c105f4d0..7539ff16 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h +++ b/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h
@@ -62,6 +62,8 @@ IDWriteLocalFontFileLoader* local_loader, IDWriteFontFile* font_file); + bool IsLastResortFallbackFont(uint32_t font_index); + private: bool direct_write_initialized_ = false; Microsoft::WRL::ComPtr<IDWriteFontCollection> collection_; @@ -69,6 +71,9 @@ Microsoft::WRL::ComPtr<IDWriteFontFallback> font_fallback_; base::string16 windows_fonts_path_; + // Temp code to help track down crbug.com/561873 + std::vector<uint32_t> last_resort_fonts_; + DISALLOW_COPY_AND_ASSIGN(DWriteFontProxyMessageFilter); };
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/content/browser/renderer_host/media/peer_connection_tracker_host.cc index 12f6edc..9fceb42 100644 --- a/content/browser/renderer_host/media/peer_connection_tracker_host.cc +++ b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -4,15 +4,20 @@ #include "content/browser/renderer_host/media/peer_connection_tracker_host.h" #include "base/power_monitor/power_monitor.h" +#include "content/browser/media/webrtc/webrtc_eventlog_host.h" #include "content/browser/media/webrtc/webrtc_internals.h" +#include "content/browser/renderer_host/render_process_host_impl.h" #include "content/common/media/peer_connection_tracker_messages.h" -#include "content/public/browser/render_process_host.h" namespace content { -PeerConnectionTrackerHost::PeerConnectionTrackerHost(int render_process_id) +PeerConnectionTrackerHost::PeerConnectionTrackerHost( + int render_process_id, + WebRTCEventLogHost* event_log_host) : BrowserMessageFilter(PeerConnectionTrackerMsgStart), - render_process_id_(render_process_id) { + render_process_id_(render_process_id), + event_log_host_(event_log_host) { + DCHECK(event_log_host); } bool PeerConnectionTrackerHost::OnMessageReceived(const IPC::Message& message) { @@ -71,10 +76,12 @@ info.url, info.rtc_configuration, info.constraints); + event_log_host_->PeerConnectionAdded(info.lid); } void PeerConnectionTrackerHost::OnRemovePeerConnection(int lid) { WebRTCInternals::GetInstance()->OnRemovePeerConnection(peer_pid(), lid); + event_log_host_->PeerConnectionRemoved(lid); } void PeerConnectionTrackerHost::OnUpdatePeerConnection(
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.h b/content/browser/renderer_host/media/peer_connection_tracker_host.h index 53a9630..53926f8 100644 --- a/content/browser/renderer_host/media/peer_connection_tracker_host.h +++ b/content/browser/renderer_host/media/peer_connection_tracker_host.h
@@ -19,6 +19,8 @@ namespace content { +class WebRTCEventLogHost; + // This class is the host for PeerConnectionTracker in the browser process // managed by RenderProcessHostImpl. It receives PeerConnection events from // PeerConnectionTracker as IPC messages that it forwards to WebRTCInternals. @@ -26,7 +28,8 @@ class PeerConnectionTrackerHost : public BrowserMessageFilter, public base::PowerObserver { public: - explicit PeerConnectionTrackerHost(int render_process_id); + PeerConnectionTrackerHost(int render_process_id, + WebRTCEventLogHost* event_log_host); // content::BrowserMessageFilter override. bool OnMessageReceived(const IPC::Message& message) override; @@ -57,6 +60,8 @@ int render_process_id_; + WebRTCEventLogHost* const event_log_host_; + DISALLOW_COPY_AND_ASSIGN(PeerConnectionTrackerHost); };
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index b20943e..77e6b662 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -248,8 +248,6 @@ #ifdef ENABLE_WEBRTC const base::FilePath::CharType kAecDumpFileNameAddition[] = FILE_PATH_LITERAL("aec_dump"); -const base::FilePath::CharType kEventLogFileNameAddition[] = - FILE_PATH_LITERAL("event_log"); #endif void CacheShaderInfo(int32_t id, base::FilePath path) { @@ -553,6 +551,9 @@ delayed_cleanup_needed_(false), within_process_died_observer_(false), power_monitor_broadcaster_(this), +#if defined(ENABLE_WEBRTC) + webrtc_eventlog_host_(id_), +#endif worker_ref_count_(0), max_worker_count_(0), permission_service_context_(new PermissionServiceContext(this)), @@ -932,7 +933,8 @@ blob_storage_context.get())); #if defined(ENABLE_WEBRTC) - peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID()); + peer_connection_tracker_host_ = + new PeerConnectionTrackerHost(GetID(), &webrtc_eventlog_host_); AddFilter(peer_connection_tracker_host_.get()); AddFilter(new MediaStreamDispatcherHost( GetID(), browser_context->GetResourceContext()->GetMediaDeviceIDSalt(), @@ -1408,6 +1410,7 @@ switches::kDisableMediaSuspend, switches::kDisableNotifications, switches::kDisableOverlayScrollbar, + switches::kDisablePepper3DImageChromium, switches::kDisablePermissionsAPI, switches::kDisablePresentationAPI, switches::kDisablePinch, @@ -1757,12 +1760,8 @@ #if defined(ENABLE_WEBRTC) IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer, OnRegisterAecDumpConsumer) - IPC_MESSAGE_HANDLER(WebRTCEventLogMsg_RegisterEventLogConsumer, - OnRegisterEventLogConsumer) IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer, OnUnregisterAecDumpConsumer) - IPC_MESSAGE_HANDLER(WebRTCEventLogMsg_UnregisterEventLogConsumer, - OnUnregisterEventLogConsumer) #endif // Adding single handlers for your service here is fine, but once your // service needs more than one handler, please extract them into a new @@ -2021,26 +2020,13 @@ } } -void RenderProcessHostImpl::EnableEventLogRecordings( - const base::FilePath& file) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // Enable Event log for each registered consumer. - base::FilePath file_with_extensions = GetEventLogFilePathWithExtensions(file); - for (int id : aec_dump_consumers_) - EnableEventLogForId(file_with_extensions, id); +bool RenderProcessHostImpl::StartWebRTCEventLog( + const base::FilePath& file_path) { + return webrtc_eventlog_host_.StartWebRTCEventLog(file_path); } -void RenderProcessHostImpl::DisableEventLogRecordings() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // Posting on the FILE thread and then replying back on the UI thread is only - // for avoiding races between enable and disable. Nothing is done on the FILE - // thread. - BrowserThread::PostTaskAndReply( - BrowserThread::FILE, FROM_HERE, base::Bind(&base::DoNothing), - base::Bind(&RenderProcessHostImpl::SendDisableEventLogToRenderer, - weak_factory_.GetWeakPtr())); +bool RenderProcessHostImpl::StopWebRTCEventLog() { + return webrtc_eventlog_host_.StopWebRTCEventLog(); } void RenderProcessHostImpl::SetWebRtcLogMessageCallback( @@ -2682,13 +2668,6 @@ weak_factory_.GetWeakPtr(), id)); } -void RenderProcessHostImpl::OnRegisterEventLogConsumer(int id) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&RenderProcessHostImpl::RegisterEventLogConsumerOnUIThread, - weak_factory_.GetWeakPtr(), id)); -} - void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, @@ -2696,13 +2675,6 @@ weak_factory_.GetWeakPtr(), id)); } -void RenderProcessHostImpl::OnUnregisterEventLogConsumer(int id) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&RenderProcessHostImpl::UnregisterEventLogConsumerOnUIThread, - weak_factory_.GetWeakPtr(), id)); -} - void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); aec_dump_consumers_.push_back(id); @@ -2714,17 +2686,6 @@ } } -void RenderProcessHostImpl::RegisterEventLogConsumerOnUIThread(int id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - aec_dump_consumers_.push_back(id); - - if (WebRTCInternals::GetInstance()->IsEventLogRecordingsEnabled()) { - base::FilePath file_with_extensions = GetEventLogFilePathWithExtensions( - WebRTCInternals::GetInstance()->GetEventLogRecordingsFilePath()); - EnableEventLogForId(file_with_extensions, id); - } -} - void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); @@ -2736,17 +2697,6 @@ } } -void RenderProcessHostImpl::UnregisterEventLogConsumerOnUIThread(int id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); - it != aec_dump_consumers_.end(); ++it) { - if (*it == id) { - aec_dump_consumers_.erase(it); - break; - } - } -} - void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file, int id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -2757,16 +2707,6 @@ weak_factory_.GetWeakPtr(), id)); } -void RenderProcessHostImpl::EnableEventLogForId(const base::FilePath& file, - int id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - BrowserThread::PostTaskAndReplyWithResult( - BrowserThread::FILE, FROM_HERE, - base::Bind(&CreateFileForProcess, file.AddExtension(IntToStringType(id))), - base::Bind(&RenderProcessHostImpl::SendEventLogFileToRenderer, - weak_factory_.GetWeakPtr(), id)); -} - void RenderProcessHostImpl::SendAecDumpFileToRenderer( int id, IPC::PlatformFileForTransit file_for_transit) { @@ -2775,33 +2715,15 @@ Send(new AecDumpMsg_EnableAecDump(id, file_for_transit)); } -void RenderProcessHostImpl::SendEventLogFileToRenderer( - int id, - IPC::PlatformFileForTransit file_for_transit) { - if (file_for_transit == IPC::InvalidPlatformFileForTransit()) - return; - Send(new WebRTCEventLogMsg_EnableEventLog(id, file_for_transit)); -} - void RenderProcessHostImpl::SendDisableAecDumpToRenderer() { Send(new AecDumpMsg_DisableAecDump()); } -void RenderProcessHostImpl::SendDisableEventLogToRenderer() { - Send(new WebRTCEventLogMsg_DisableEventLog()); -} - base::FilePath RenderProcessHostImpl::GetAecDumpFilePathWithExtensions( const base::FilePath& file) { return file.AddExtension(IntToStringType(base::GetProcId(GetHandle()))) .AddExtension(kAecDumpFileNameAddition); } - -base::FilePath RenderProcessHostImpl::GetEventLogFilePathWithExtensions( - const base::FilePath& file) { - return file.AddExtension(IntToStringType(base::GetProcId(GetHandle()))) - .AddExtension(kEventLogFileNameAddition); -} #endif // defined(ENABLE_WEBRTC) void RenderProcessHostImpl::GetAudioOutputControllers(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 72f2995..18b9386 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -23,6 +23,7 @@ #include "content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h" #include "content/browser/child_process_launcher.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" +#include "content/browser/media/webrtc/webrtc_eventlog_host.h" #include "content/browser/power_monitor_message_broadcaster.h" #include "content/common/content_export.h" #include "content/public/browser/render_process_host.h" @@ -143,8 +144,8 @@ #if defined(ENABLE_WEBRTC) void EnableAudioDebugRecordings(const base::FilePath& file) override; void DisableAudioDebugRecordings() override; - void EnableEventLogRecordings(const base::FilePath& file) override; - void DisableEventLogRecordings() override; + bool StartWebRTCEventLog(const base::FilePath& file_path) override; + bool StopWebRTCEventLog() override; void SetWebRtcLogMessageCallback( base::Callback<void(const std::string&)> callback) override; void ClearWebRtcLogMessageCallback() override; @@ -343,24 +344,15 @@ #if defined(ENABLE_WEBRTC) void OnRegisterAecDumpConsumer(int id); - void OnRegisterEventLogConsumer(int id); void OnUnregisterAecDumpConsumer(int id); - void OnUnregisterEventLogConsumer(int id); void RegisterAecDumpConsumerOnUIThread(int id); - void RegisterEventLogConsumerOnUIThread(int id); void UnregisterAecDumpConsumerOnUIThread(int id); - void UnregisterEventLogConsumerOnUIThread(int id); void EnableAecDumpForId(const base::FilePath& file, int id); - void EnableEventLogForId(const base::FilePath& file, int id); // Sends |file_for_transit| to the render process. void SendAecDumpFileToRenderer(int id, IPC::PlatformFileForTransit file_for_transit); - void SendEventLogFileToRenderer(int id, - IPC::PlatformFileForTransit file_for_transit); void SendDisableAecDumpToRenderer(); - void SendDisableEventLogToRenderer(); base::FilePath GetAecDumpFilePathWithExtensions(const base::FilePath& file); - base::FilePath GetEventLogFilePathWithExtensions(const base::FilePath& file); #endif static void OnMojoError( @@ -488,6 +480,8 @@ std::vector<int> aec_dump_consumers_; WebRtcStopRtpDumpCallback stop_rtp_dump_callback_; + + WebRTCEventLogHost webrtc_eventlog_host_; #endif int worker_ref_count_;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 46129fb..55216b1c 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1908,7 +1908,7 @@ output_size_in_pixel.height(), color_type, kOpaque_SkAlphaType))) { - scoped_callback_runner.Reset( + scoped_callback_runner.ReplaceClosure( base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE)); return; }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index b2bd30b0..7940896 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1041,46 +1041,6 @@ return delegated_frame_host_->GetRequestedRendererSize(); } -void RenderWidgetHostViewAura::SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) { - gfx::SelectionBound anchor_bound, focus_bound; - anchor_bound.SetEdge(gfx::PointF(params.anchor_rect.origin()), - gfx::PointF(params.anchor_rect.bottom_left())); - focus_bound.SetEdge(gfx::PointF(params.focus_rect.origin()), - gfx::PointF(params.focus_rect.bottom_left())); - - if (params.anchor_rect == params.focus_rect) { - anchor_bound.set_type(gfx::SelectionBound::CENTER); - focus_bound.set_type(gfx::SelectionBound::CENTER); - } else { - // Whether text is LTR at the anchor handle. - bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight; - // Whether text is LTR at the focus handle. - bool focus_LTR = params.focus_dir == blink::WebTextDirectionLeftToRight; - - if ((params.is_anchor_first && anchor_LTR) || - (!params.is_anchor_first && !anchor_LTR)) { - anchor_bound.set_type(gfx::SelectionBound::LEFT); - } else { - anchor_bound.set_type(gfx::SelectionBound::RIGHT); - } - if ((params.is_anchor_first && focus_LTR) || - (!params.is_anchor_first && !focus_LTR)) { - focus_bound.set_type(gfx::SelectionBound::RIGHT); - } else { - focus_bound.set_type(gfx::SelectionBound::LEFT); - } - } - - if (anchor_bound == selection_anchor_ && focus_bound == selection_focus_) - return; - - selection_anchor_ = anchor_bound; - selection_focus_ = focus_bound; - if (GetInputMethod()) - GetInputMethod()->OnCaretBoundsChanged(this); -} - void RenderWidgetHostViewAura::CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size, @@ -1564,8 +1524,9 @@ } gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const { - return ConvertRectToScreen( - gfx::RectBetweenSelectionBounds(selection_anchor_, selection_focus_)); + if (!text_input_manager_ || !text_input_manager_->GetActiveWidget()) + return gfx::Rect(); + return ConvertRectToScreen(text_input_manager_->GetSelectionBoundsRect()); } bool RenderWidgetHostViewAura::GetCompositionCharacterBounds( @@ -3031,6 +2992,13 @@ has_composition_text_ = false; } +void RenderWidgetHostViewAura::OnSelectionBoundsChanged( + TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view) { + if (GetInputMethod()) + GetInputMethod()->OnCaretBoundsChanged(this); +} + //////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewBase, public:
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 0be92468..b71e90c 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -153,8 +153,6 @@ size_t offset, const gfx::Range& range) override; gfx::Size GetRequestedRendererSize() const override; - void SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) override; void CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size, @@ -349,7 +347,7 @@ const ui::MotionEventAura& pointer_state() const { return pointer_state_; } private: - friend class InputMethodResultAuraTest; + friend class InputMethodAuraTestBase; friend class RenderWidgetHostViewAuraCopyRequestTest; friend class TestInputMethodObserver; FRIEND_TEST_ALL_PREFIXES(InputMethodResultAuraTest, @@ -475,6 +473,9 @@ bool did_update_state) override; void OnImeCancelComposition(TextInputManager* text_input_manager, RenderWidgetHostViewBase* updated_view) override; + void OnSelectionBoundsChanged( + TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view) override; // cc::BeginFrameObserver implementation. void OnBeginFrame(const cc::BeginFrameArgs& args) override; @@ -585,10 +586,6 @@ // object. ui::MotionEventAura pointer_state_; - // Bounds for the selection. - gfx::SelectionBound selection_anchor_; - gfx::SelectionBound selection_focus_; - // The current composition character bounds. std::vector<gfx::Rect> composition_character_bounds_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 8b213136..30defc8 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -87,6 +87,8 @@ #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/selection_bound.h" #include "ui/wm/core/default_activation_client.h" #include "ui/wm/core/default_screen_position_client.h" #include "ui/wm/core/window_util.h" @@ -4031,19 +4033,13 @@ // ---------------------------------------------------------------------------- // TextInputManager and IME-Related Tests -// A group of tests which verify that the IME method results are routed to the -// right RenderWidget in the OOPIF structure. +// The test class for OOPIF IME related unit tests in RenderWidgetHostViewAura. // In each test, 3 views are created where one is in process with main frame and -// the other two are in distinct processes (this makes a total of 4 RWHVs). Then -// each test will verify the correctness of routing for one of the IME result -// methods. The method is called on ui::TextInputClient (i.e., RWHV for the tab -// in aura) and then the test verifies that the IPC is routed to the -// RenderWidget corresponding to the active view (i.e., the RenderWidget -// with focused <input>). -class InputMethodResultAuraTest : public RenderWidgetHostViewAuraTest { +// the other two are in distinct processes (this makes a total of 4 RWHVs). +class InputMethodAuraTestBase : public RenderWidgetHostViewAuraTest { public: - InputMethodResultAuraTest() {} - ~InputMethodResultAuraTest() override {} + InputMethodAuraTestBase() {} + ~InputMethodAuraTestBase() override {} void SetUp() override { RenderWidgetHostViewAuraTest::SetUp(); @@ -4087,14 +4083,6 @@ } protected: - const IPC::Message* RunAndReturnIPCSent(const base::Closure closure, - MockRenderProcessHost* process, - int32_t message_id) { - process->sink().ClearMessages(); - closure.Run(); - return process->sink().GetFirstMessageMatching(message_id); - } - MockRenderWidgetHostDelegate* render_widget_host_delegate() const { return delegates_.back().get(); } @@ -4157,6 +4145,31 @@ MockRenderProcessHost* third_process_host_; TestRenderWidgetHostView* view_for_third_process_; + DISALLOW_COPY_AND_ASSIGN(InputMethodAuraTestBase); +}; + +// A group of tests which verify that the IME method results are routed to the +// right RenderWidget when there are multiple RenderWidgetHostViews on tab. Each +// test will verify the correctness of routing for one of the IME result +// methods. The method is called on ui::TextInputClient (i.e., RWHV for the tab +// in aura) and then the test verifies that the IPC is routed to the +// RenderWidget corresponding to the active view (i.e., the RenderWidget +// with focused <input>). +class InputMethodResultAuraTest : public InputMethodAuraTestBase { + public: + InputMethodResultAuraTest() {} + ~InputMethodResultAuraTest() override {} + + protected: + const IPC::Message* RunAndReturnIPCSent(const base::Closure closure, + MockRenderProcessHost* process, + int32_t message_id) { + process->sink().ClearMessages(); + closure.Run(); + return process->sink().GetFirstMessageMatching(message_id); + } + + private: DISALLOW_COPY_AND_ASSIGN(InputMethodResultAuraTest); }; @@ -4217,9 +4230,9 @@ } } -// This test makes a specific child frame's view active and then forces the -// tab's view end the current IME composition session by sending out an IME -// IPC to confirm composition. The test then verifies that the message is sent +// This test makes a specific view active and then forces the tab's view end the +// current IME composition session by sending out an IME IPC to confirm +// composition. The test then verifies that the message is sent // to the active widget's process. TEST_F(InputMethodResultAuraTest, FinishImeCompositionSession) { base::Closure ime_finish_session_call = @@ -4234,4 +4247,57 @@ } } +// A class of tests which verify the correctness of some tracked IME related +// state at the browser side, e.g., caret bounds. +class InputMethodStateAuraTest : public InputMethodAuraTestBase { + public: + InputMethodStateAuraTest() {} + ~InputMethodStateAuraTest() override {} + + protected: + gfx::SelectionBound GetSelectionBoundFromRect(const gfx::Rect& rect) { + gfx::SelectionBound bound; + bound.SetEdge(gfx::PointF(rect.origin()), gfx::PointF(rect.bottom_left())); + return bound; + } + + gfx::Rect TransformRectToViewsRootCoordSpace(const gfx::Rect rect, + RenderWidgetHostView* view) { + return gfx::Rect(view->TransformPointToRootCoordSpace(rect.origin()), + rect.size()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(InputMethodStateAuraTest); +}; + +// This test activates the views on the tab according to a predefined order and +// for each tab, simulates a selection bounds changed call. Then it verifies +// that the caret bounds reported by the TextInputClient match those reported +// for the active view. +TEST_F(InputMethodStateAuraTest, GetCaretBounds) { + ViewHostMsg_SelectionBounds_Params params; + params.is_anchor_first = true; + params.anchor_dir = blink::WebTextDirectionLeftToRight; + params.focus_dir = blink::WebTextDirectionLeftToRight; + params.anchor_rect = gfx::Rect(0, 0, 10, 10); + for (auto index : active_view_sequence_) { + ActivateViewForTextInputManager(views_[index], ui::TEXT_INPUT_TYPE_TEXT); + params.focus_rect = gfx::Rect(10 + index, 10 + index, 10, 10); + views_[index]->SelectionBoundsChanged(params); + + // Calculate the bounds. + gfx::SelectionBound anchor_bound = GetSelectionBoundFromRect( + TransformRectToViewsRootCoordSpace(params.anchor_rect, views_[index])); + gfx::SelectionBound focus_bound = GetSelectionBoundFromRect( + TransformRectToViewsRootCoordSpace(params.focus_rect, views_[index])); + anchor_bound.set_type(gfx::SelectionBound::LEFT); + focus_bound.set_type(gfx::SelectionBound::RIGHT); + gfx::Rect measured_rect = + gfx::RectBetweenSelectionBounds(anchor_bound, focus_bound); + + EXPECT_EQ(measured_rect, text_input_client()->GetCaretBounds()); + } +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index 0b34ce0..41724ea 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -102,6 +102,12 @@ return 0.f; } +void RenderWidgetHostViewBase::SelectionBoundsChanged( + const ViewHostMsg_SelectionBounds_Params& params) { + if (GetTextInputManager()) + GetTextInputManager()->SelectionBoundsChanged(this, params); +} + void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) {
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index f6a25c17c..756a7d8 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -251,18 +251,27 @@ cc::SurfaceId original_surface, gfx::Point* transformed_point); + //---------------------------------------------------------------------------- + // The following methods are related to IME. + // TODO(ekaramad): Most of the IME methods should not stay virtual after IME + // is implemented for OOPIF. After fixing IME, mark the corresponding methods + // non-virtual (https://crbug.com/578168). + // Updates the state of the input method attached to the view. - // TODO(ekaramad): This method will not stay virtual. It will be moved up top - // with the other non-virtual methods after TextInputState tracking is fixed - // on all platforms (https://crbug.com/578168). virtual void TextInputStateChanged(const TextInputState& text_input_state); // Cancel the ongoing composition of the input method attached to the view. - // TODO(ekaramad): This method will not stay virtual. It will be moved up top - // with the other non-virtual methods after IME is fixed on all platforms. - // (https://crbug.com/578168). virtual void ImeCancelComposition(); + // Notifies the view that the renderer selection bounds has changed. + // Selection bounds are described as a focus bound which is the current + // position of caret on the screen, as well as the anchor bound which is the + // starting position of the selection. The coordinates are with respect to + // RenderWidget's window's origin. Focus and anchor bound are represented as + // gfx::Rect. + virtual void SelectionBoundsChanged( + const ViewHostMsg_SelectionBounds_Params& params); + //---------------------------------------------------------------------------- // The following static methods are implemented by each platform. @@ -299,13 +308,6 @@ // the page has changed. virtual void SetTooltipText(const base::string16& tooltip_text) = 0; - // Notifies the View that the renderer selection bounds has changed. - // |start_rect| and |end_rect| are the bounds end of the selection in the - // coordinate system of the render view. |start_direction| and |end_direction| - // indicates the direction at which the selection was made on touch devices. - virtual void SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) = 0; - // Copies the contents of the compositing surface, providing a new SkBitmap // result via an asynchronously-run |callback|. |src_subrect| is specified in // layer space coordinates for the current platform (e.g., DIP for Aura/Mac,
diff --git a/content/browser/renderer_host/text_input_manager.cc b/content/browser/renderer_host/text_input_manager.cc index 903c471b..3029d93 100644 --- a/content/browser/renderer_host/text_input_manager.cc +++ b/content/browser/renderer_host/text_input_manager.cc
@@ -6,6 +6,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/common/view_messages.h" namespace content { @@ -54,6 +55,15 @@ : nullptr; } +gfx::Rect TextInputManager::GetSelectionBoundsRect() { + if (!active_view_) + return gfx::Rect(); + + return gfx::RectBetweenSelectionBounds( + selection_region_map_[active_view_].anchor, + selection_region_map_[active_view_].focus); +} + void TextInputManager::UpdateTextInputState( RenderWidgetHostViewBase* view, const TextInputState& text_input_state) { @@ -84,6 +94,60 @@ OnImeCancelComposition(this, view)); } +void TextInputManager::SelectionBoundsChanged( + RenderWidgetHostViewBase* view, + const ViewHostMsg_SelectionBounds_Params& params) { + DCHECK(IsRegistered(view)); + +// TODO(ekaramad): Implement the logic for other platforms (crbug.com/578168). +#if defined(USE_AURA) + gfx::SelectionBound anchor_bound, focus_bound; + // Converting the points to the |view|'s root coordinate space (for child + // frame views). + anchor_bound.SetEdge(gfx::PointF(view->TransformPointToRootCoordSpace( + params.anchor_rect.origin())), + gfx::PointF(view->TransformPointToRootCoordSpace( + params.anchor_rect.bottom_left()))); + focus_bound.SetEdge(gfx::PointF(view->TransformPointToRootCoordSpace( + params.focus_rect.origin())), + gfx::PointF(view->TransformPointToRootCoordSpace( + params.focus_rect.bottom_left()))); + + if (params.anchor_rect == params.focus_rect) { + anchor_bound.set_type(gfx::SelectionBound::CENTER); + focus_bound.set_type(gfx::SelectionBound::CENTER); + } else { + // Whether text is LTR at the anchor handle. + bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight; + // Whether text is LTR at the focus handle. + bool focus_LTR = params.focus_dir == blink::WebTextDirectionLeftToRight; + + if ((params.is_anchor_first && anchor_LTR) || + (!params.is_anchor_first && !anchor_LTR)) { + anchor_bound.set_type(gfx::SelectionBound::LEFT); + } else { + anchor_bound.set_type(gfx::SelectionBound::RIGHT); + } + if ((params.is_anchor_first && focus_LTR) || + (!params.is_anchor_first && !focus_LTR)) { + focus_bound.set_type(gfx::SelectionBound::RIGHT); + } else { + focus_bound.set_type(gfx::SelectionBound::LEFT); + } + } + + if (anchor_bound == selection_region_map_[view].anchor && + focus_bound == selection_region_map_[view].focus) + return; + + selection_region_map_[view].anchor = anchor_bound; + selection_region_map_[view].focus = focus_bound; + + FOR_EACH_OBSERVER(Observer, observer_list_, + OnSelectionBoundsChanged(this, view)); +#endif +} + void TextInputManager::Register(RenderWidgetHostViewBase* view) { DCHECK(!IsRegistered(view)); @@ -131,4 +195,9 @@ OnUpdateTextInputStateCalled(this, updated_view, did_update_state)); } +TextInputManager::SelectionRegion::SelectionRegion() {} + +TextInputManager::SelectionRegion::SelectionRegion( + const SelectionRegion& other) = default; + } // namespace content \ No newline at end of file
diff --git a/content/browser/renderer_host/text_input_manager.h b/content/browser/renderer_host/text_input_manager.h index 2bb4c16d..f240a1b 100644 --- a/content/browser/renderer_host/text_input_manager.h +++ b/content/browser/renderer_host/text_input_manager.h
@@ -6,13 +6,17 @@ #define CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__ #include <unordered_map> +#include <utility> #include "base/observer_list.h" #include "content/common/content_export.h" #include "content/common/text_input_state.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/selection_bound.h" + +struct ViewHostMsg_SelectionBounds_Params; namespace content { - class RenderWidgetHostImpl; class RenderWidgetHostView; class RenderWidgetHostViewBase; @@ -41,6 +45,10 @@ virtual void OnImeCancelComposition( TextInputManager* text_input_manager, RenderWidgetHostViewBase* updated_view) {} + // Called when the selection bounds for the |updated_view| has changed. + virtual void OnSelectionBoundsChanged( + TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view) {} }; TextInputManager(); @@ -59,6 +67,9 @@ // dangling if the TextInputManager or |active_view_| might go away. const TextInputState* GetTextInputState(); + // Returns the rect between selection bounds for the |active_view_|. + gfx::Rect GetSelectionBoundsRect(); + // --------------------------------------------------------------------------- // The following methods are called by RWHVs on the tab to update their IME- // related state. @@ -71,6 +82,12 @@ // the widget corresponding to |view|. void ImeCancelComposition(RenderWidgetHostViewBase* view); + // Updates the selection bounds for the |view|. In Aura, selection bounds are + // used to provide the InputMethod with the position of the caret, e.g., in + // setting the position of the ui::ImeWindow. + void SelectionBoundsChanged(RenderWidgetHostViewBase* view, + const ViewHostMsg_SelectionBounds_Params& params); + // Registers the given |view| for tracking its TextInputState. This is called // by any view which has updates in its TextInputState (whether tab's RWHV or // that of a child frame). The |view| must unregister itself before being @@ -100,6 +117,23 @@ RenderWidgetHostViewBase* view); private: + // Text selection bounds. + struct SelectionRegion { + SelectionRegion(); + SelectionRegion(const SelectionRegion& other); + + // The begining of the selection region. + gfx::SelectionBound anchor; + // The end of the selection region (caret position). + gfx::SelectionBound focus; + }; + + // This class is used to create maps which hold specific IME state for a + // view. + template <class Value> + class ViewMap : public std::unordered_map<RenderWidgetHostViewBase*, Value> { + }; + void NotifyObserversAboutInputStateUpdate(RenderWidgetHostViewBase* view, bool did_update_state); @@ -108,8 +142,10 @@ // cannot have a |TextInputState.type| of ui::TEXT_INPUT_TYPE_NONE. RenderWidgetHostViewBase* active_view_; - std::unordered_map<RenderWidgetHostViewBase*, TextInputState> - text_input_state_map_; + ViewMap<TextInputState> text_input_state_map_; + + // Text selection bounds information for registered views. + ViewMap<SelectionRegion> selection_region_map_; base::ObserverList<Observer> observer_list_;
diff --git a/content/browser/resources/media/dump_creator.js b/content/browser/resources/media/dump_creator.js index c8f53df..29f053f 100644 --- a/content/browser/resources/media/dump_creator.js +++ b/content/browser/resources/media/dump_creator.js
@@ -33,12 +33,12 @@ '</button></a></div>' + '<p><label><input type=checkbox>' + 'Enable diagnostic audio recordings</label></p>' + - '<p class=audio-recordings-info>A diagnostic audio recording is used' + - ' for analyzing audio problems. It consists of two files and contains' + - ' the audio played out from the speaker and recorded from the' + - ' microphone and is saved to the local disk. Checking this box will' + - ' enable the recording for ongoing WebRTC calls and for future WebRTC' + - ' calls. When the box is unchecked or this page is closed, all' + + '<p class=audio-diagnostic-dumps-info>A diagnostic audio recording is' + + ' used for analyzing audio problems. It consists of two files and' + + ' contains the audio played out from the speaker and recorded from' + + ' the microphone and is saved to the local disk. Checking this box' + + ' will enable the recording for ongoing WebRTC calls and for future' + + ' WebRTC calls. When the box is unchecked or this page is closed, all' + ' ongoing recordings will be stopped and this recording' + ' functionality will be disabled for future WebRTC calls. Recordings' + ' in multiple tabs are supported as well as multiple recordings in' + @@ -48,26 +48,37 @@ '.aec_dump.<recording ID></div>' + '<div><base filename>.<render process ID>' + '.source_input.<stream ID>.wav</div></p>' + - '<p class=audio-recordings-info>If recordings are disabled and then' + - ' enabled using the same base filename, the microphone recording file' + - ' will be overwritten, and the AEC dump file will be appended to and' + - ' may become invalid. It is recommended to choose a new base filename' + - ' each time or move the produced files before enabling again.</p>' + + '<p class=audio-diagnostic-dumps-info>If recordings are disabled and' + + ' then enabled using the same base filename, the microphone recording' + + ' file will be overwritten, and the AEC dump file will be appended to' + + ' and may become invalid. It is recommended to choose a new base' + + ' filename each time or move the produced files before enabling' + + ' again.</p>' + '<p><label><input type=checkbox>' + 'Enable diagnostic packet and event recording</label></p>' + - '<p class=audio-recordings-info>A diagnostic packet and event' + + '<p class=audio-diagnostic-dumps-info>A diagnostic packet and event' + ' recording can be used for analyzing various issues related to' + ' thread starvation, jitter buffers or bandwidth estimation. Two' + ' types of data are logged. First, incoming and outgoing RTP headers' + ' and RTCP packets are logged. These do not include any audio or' + ' video information, nor any other types of personally identifiable' + ' information (so no IP addresses or URLs). Checking this box will' + - ' enable the recording for currently ongoing WebRTC calls. When' + - ' the box is unchecked or this page is closed, all active recordings' + - ' will be stopped. Recording in multiple tabs or multiple recordings' + - ' in the same tab is currently not supported. When enabling, a' + - ' filename for the recording can be selected. If an existing file is' + - ' selected, it will be overwritten. </p>'; + ' enable the recording for ongoing WebRTC calls and for future' + + ' WebRTC calls. When the box is unchecked or this page is closed,' + + ' all ongoing recordings will be stopped and this recording' + + ' functionality will be disabled for future WebRTC calls. Recording' + + ' in multiple tabs or multiple recordings in the same tab will cause' + + ' multiple log files to be created. When enabling, a filename for the' + + ' recording can be entered. The entered filename is used as a' + + ' base, to which the following suffixes will be appended.</p>' + + ' <p><base filename>.<render process ID>' + + '.<recording ID></p>' + + '<p class=audio-diagnostic-dumps-info>If a file with the same name' + + ' already exists, it will be overwritten. No more than 5 logfiles ' + + ' will be created, and each of them is limited to 60MB of storage. ' + + ' On Android these limits are 3 files of at most 10MB each. ' + + ' When the limit is reached, the checkbox must be unchecked and ' + + ' rechecked to resume logging.</p>'; content.getElementsByTagName('a')[0].addEventListener( 'click', this.onDownloadData_.bind(this)); content.getElementsByTagName('input')[0].addEventListener(
diff --git a/content/browser/resources/media/webrtc_internals.css b/content/browser/resources/media/webrtc_internals.css index 54eec7e..cf6f31a 100644 --- a/content/browser/resources/media/webrtc_internals.css +++ b/content/browser/resources/media/webrtc_internals.css
@@ -118,6 +118,6 @@ margin: 5px 0 5px 0; } -.audio-recordings-info { +.audio-diagnostic-dumps-info { max-width: 60em; }
diff --git a/content/browser/service_worker/service_worker_registration_status.cc b/content/browser/service_worker/service_worker_registration_status.cc index 46ff019b..e404eadd 100644 --- a/content/browser/service_worker/service_worker_registration_status.cc +++ b/content/browser/service_worker/service_worker_registration_status.cc
@@ -31,7 +31,6 @@ case SERVICE_WORKER_ERROR_START_WORKER_FAILED: case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED: case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND: - case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: case SERVICE_WORKER_ERROR_REDUNDANT: case SERVICE_WORKER_ERROR_DISALLOWED: *error_type = WebServiceWorkerError::ErrorTypeInstall; @@ -45,6 +44,10 @@ *error_type = WebServiceWorkerError::ErrorTypeNetwork; return; + case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: + *error_type = WebServiceWorkerError::ErrorTypeScriptEvaluateFailed; + return; + case SERVICE_WORKER_ERROR_SECURITY: *error_type = WebServiceWorkerError::ErrorTypeSecurity; return;
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index a81f6968..326e3ef 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -250,10 +250,29 @@ void ServiceWorkerURLRequestJob::FallbackToNetwork() { DCHECK_EQ(NOT_DETERMINED, response_type_); + // TODO(shimazu): Remove the condition of FOREIGN_FETCH after figuring out + // what to do about CORS preflight and fallbacks for foreign fetch events. + // http://crbug.com/604084 + DCHECK(!IsFallbackToRendererNeeded() || + (fetch_type_ == ServiceWorkerFetchType::FOREIGN_FETCH)); response_type_ = FALLBACK_TO_NETWORK; MaybeStartRequest(); } +void ServiceWorkerURLRequestJob::FallbackToNetworkOrRenderer() { + DCHECK_EQ(NOT_DETERMINED, response_type_); + // TODO(shimazu): Remove the condition of FOREIGN_FETCH after figuring out + // what to do about CORS preflight and fallbacks for foreign fetch events. + // http://crbug.com/604084 + DCHECK_NE(ServiceWorkerFetchType::FOREIGN_FETCH, fetch_type_); + if (IsFallbackToRendererNeeded()) { + response_type_ = FALLBACK_TO_RENDERER; + } else { + response_type_ = FALLBACK_TO_NETWORK; + } + MaybeStartRequest(); +} + void ServiceWorkerURLRequestJob::ForwardToServiceWorker() { DCHECK_EQ(NOT_DETERMINED, response_type_); response_type_ = FORWARD_TO_SERVICE_WORKER; @@ -499,10 +518,11 @@ return; case FALLBACK_TO_NETWORK: - // Restart the request to create a new job. Our request handler will - // return nullptr, and the default job (which will hit network) should be - // created. - NotifyRestartRequired(); + FinalizeFallbackToNetwork(); + return; + + case FALLBACK_TO_RENDERER: + FinalizeFallbackToRenderer(); return; case FORWARD_TO_SERVICE_WORKER: @@ -698,8 +718,7 @@ if (IsMainResourceLoad()) { // Using the service worker failed, so fallback to network. delegate_->MainResourceLoadFailed(); - response_type_ = FALLBACK_TO_NETWORK; - NotifyRestartRequired(); + FinalizeFallbackToNetwork(); } else { DeliverErrorResponse(); } @@ -708,30 +727,11 @@ if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) { ServiceWorkerMetrics::RecordFallbackedRequestMode(request_mode_); - // When the request_mode is |CORS| or |CORS-with-forced-preflight| and the - // origin of the request URL is different from the security origin of the - // document, we can't simply fallback to the network in the browser process. - // It is because the CORS preflight logic is implemented in the renderer. So - // we returns a fall_back_required response to the renderer. - if ((request_mode_ == FETCH_REQUEST_MODE_CORS || - request_mode_ == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT) && - !request()->initiator().IsSameOriginWith( - url::Origin(request()->url()))) { - // TODO(mek): http://crbug.com/604084 Figure out what to do about CORS - // preflight and fallbacks for foreign fetch events. - fall_back_required_ = - fetch_type_ != ServiceWorkerFetchType::FOREIGN_FETCH; - RecordResult(ServiceWorkerMetrics::REQUEST_JOB_FALLBACK_FOR_CORS); - CreateResponseHeader( - 400, "Service Worker Fallback Required", ServiceWorkerHeaderMap()); - CommitResponseHeader(); - return; + if (IsFallbackToRendererNeeded()) { + FinalizeFallbackToRenderer(); + } else { + FinalizeFallbackToNetwork(); } - // Change the response type and restart the request to fallback to - // the network. - RecordResult(ServiceWorkerMetrics::REQUEST_JOB_FALLBACK_RESPONSE); - response_type_ = FALLBACK_TO_NETWORK; - NotifyRestartRequired(); return; } @@ -866,6 +866,43 @@ CommitResponseHeader(); } +void ServiceWorkerURLRequestJob::FinalizeFallbackToNetwork() { + // Restart this request to create a new job. The default job (which will hit + // network) will be created in the next time because our request handler will + // return nullptr after restarting and this means our interceptor does not + // intercept. + if (ShouldRecordResult()) + RecordResult(ServiceWorkerMetrics::REQUEST_JOB_FALLBACK_RESPONSE); + response_type_ = FALLBACK_TO_NETWORK; + NotifyRestartRequired(); + return; +} + +void ServiceWorkerURLRequestJob::FinalizeFallbackToRenderer() { + // TODO(mek): http://crbug.com/604084 Figure out what to do about CORS + // preflight and fallbacks for foreign fetch events. + fall_back_required_ = fetch_type_ != ServiceWorkerFetchType::FOREIGN_FETCH; + if (ShouldRecordResult()) + RecordResult(ServiceWorkerMetrics::REQUEST_JOB_FALLBACK_FOR_CORS); + CreateResponseHeader(400, "Service Worker Fallback Required", + ServiceWorkerHeaderMap()); + response_type_ = FALLBACK_TO_RENDERER; + CommitResponseHeader(); +} + +bool ServiceWorkerURLRequestJob::IsFallbackToRendererNeeded() const { + // When the request_mode is |CORS| or |CORS-with-forced-preflight| and the + // origin of the request URL is different from the security origin of the + // document, we can't simply fallback to the network in the browser process. + // It is because the CORS preflight logic is implemented in the renderer. So + // we return a fall_back_required response to the renderer. + return !IsMainResourceLoad() && + (request_mode_ == FETCH_REQUEST_MODE_CORS || + request_mode_ == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT) && + !request()->initiator().IsSameOriginWith( + url::Origin(request()->url())); +} + void ServiceWorkerURLRequestJob::SetResponseBodyType(ResponseBodyType type) { DCHECK_EQ(response_body_type_, UNKNOWN); DCHECK_NE(type, UNKNOWN); @@ -941,7 +978,8 @@ } void ServiceWorkerURLRequestJob::OnStartCompleted() const { - if (response_type_ != FORWARD_TO_SERVICE_WORKER) { + if (response_type_ != FORWARD_TO_SERVICE_WORKER && + response_type_ != FALLBACK_TO_RENDERER) { ServiceWorkerResponseInfo::ForRequest(request_, true) ->OnStartCompleted( false /* was_fetched_via_service_worker */,
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h index 029871bed..f77ff43 100644 --- a/content/browser/service_worker/service_worker_url_request_job.h +++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -103,7 +103,16 @@ ~ServiceWorkerURLRequestJob() override; // Sets the response type. + // When an in-flight request possibly needs CORS check, use + // FallbackToNetworkOrRenderer. This method will decide whether the request + // can directly go to the network or should fallback to a renderer to send + // CORS preflight. You can use FallbackToNetwork only when, like main resource + // or foreign fetch cases, it's apparent that the request should go to the + // network directly. + // TODO(shimazu): Update the comment when what should we do at foreign fetch + // fallback is determined: crbug.com/604084 void FallbackToNetwork(); + void FallbackToNetworkOrRenderer(); void ForwardToServiceWorker(); bool ShouldFallbackToNetwork() const { @@ -156,6 +165,7 @@ enum ResponseType { NOT_DETERMINED, FALLBACK_TO_NETWORK, + FALLBACK_TO_RENDERER, // Use this when falling back with CORS check FORWARD_TO_SERVICE_WORKER, }; @@ -199,6 +209,19 @@ // Creates and commits a response header indicating error. void DeliverErrorResponse(); + // Restarts this job to fallback to network. + // This can be called after StartRequest. + void FinalizeFallbackToNetwork(); + + // Sends back a response with fall_back_required set as true to trigger + // subsequent network requests with CORS checking. + // This can be called after StartRequest. + void FinalizeFallbackToRenderer(); + + // True if need to send back a response with fall_back_required set as true to + // trigger subsequent network requests with CORS checking. + bool IsFallbackToRendererNeeded() const; + // For UMA. void SetResponseBodyType(ResponseBodyType type); bool ShouldRecordResult();
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index 0833357..1c769daa 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1167,4 +1167,62 @@ EXPECT_EQ(web_ui_url, entry->GetURL()); } +namespace { + +class DownloadImageObserver { + public: + MOCK_METHOD5(OnFinishDownloadImage, void( + int id, + int status_code, + const GURL& image_url, + const std::vector<SkBitmap>& bitmap, + const std::vector<gfx::Size>& sizes)); + ~DownloadImageObserver() = default; +}; + +void DownloadImageTestInternal(Shell* shell, + const GURL &image_url, + int expected_http_status) { + using ::testing::_; + using ::testing::InvokeWithoutArgs; + + // Set up everything. + DownloadImageObserver download_image_observer; + scoped_refptr<MessageLoopRunner> loop_runner = + new MessageLoopRunner(); + + // Set up expectation and stub. + EXPECT_CALL(download_image_observer, + OnFinishDownloadImage(_, expected_http_status, _, _, _)); + ON_CALL(download_image_observer, OnFinishDownloadImage(_, _, _, _, _)) + .WillByDefault( + InvokeWithoutArgs(loop_runner.get(), &MessageLoopRunner::Quit)); + + shell->LoadURL(GURL("about:blank")); + shell->web_contents()->DownloadImage( + image_url, false, 1024, false, + base::Bind(&DownloadImageObserver::OnFinishDownloadImage, + base::Unretained(&download_image_observer))); + + // Wait for response. + loop_runner->Run(); +} + +} // anonymous namespace + +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + DownloadImage_HttpImage) { + ASSERT_TRUE(embedded_test_server()->Start()); + const GURL kImageUrl = + embedded_test_server()->GetURL("/image.jpg"); + DownloadImageTestInternal(shell(), kImageUrl, 200); +} + +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + DownloadImage_Deny_FileImage) { + const GURL kImageUrl = + GetTestUrl("", "image.jpg"); + DownloadImageTestInternal(shell(), kImageUrl, 0); +} + } // namespace content
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index 77d2c5f..8c326e0c 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -198,7 +198,7 @@ } void WebContentsViewAndroid::UpdateDragCursor(blink::WebDragOperation op) { - NOTIMPLEMENTED(); + // Intentional no-op because Android does not have cursor. } void WebContentsViewAndroid::OnDragEntered(
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc index 7e5baf3..d715569 100644 --- a/content/browser/webui/shared_resources_data_source.cc +++ b/content/browser/webui/shared_resources_data_source.cc
@@ -160,8 +160,10 @@ // back. std::string allowed_origin_prefix = kChromeUIScheme; allowed_origin_prefix += "://"; - if (origin.find(allowed_origin_prefix) != 0) + if (!base::StartsWith(origin, allowed_origin_prefix, + base::CompareCase::SENSITIVE)) { return "null"; + } return origin; }
diff --git a/content/child/child_process.cc b/content/child/child_process.cc index 8411653a..9805c06 100644 --- a/content/child/child_process.cc +++ b/content/child/child_process.cc
@@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/statistics_recorder.h" #include "base/process/process_handle.h" +#include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread.h" @@ -87,13 +88,13 @@ void ChildProcess::AddRefProcess() { DCHECK(!main_thread_.get() || // null in unittests. - base::MessageLoop::current() == main_thread_->message_loop()); + main_thread_->message_loop()->task_runner()->BelongsToCurrentThread()); ref_count_++; } void ChildProcess::ReleaseProcess() { DCHECK(!main_thread_.get() || // null in unittests. - base::MessageLoop::current() == main_thread_->message_loop()); + main_thread_->message_loop()->task_runner()->BelongsToCurrentThread()); DCHECK(ref_count_); if (--ref_count_) return;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index f5290ff..3bac8ae 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -565,7 +565,7 @@ } bool ChildThreadImpl::Send(IPC::Message* msg) { - DCHECK(base::MessageLoop::current() == message_loop()); + DCHECK(message_loop_->task_runner()->BelongsToCurrentThread()); if (!channel_) { delete msg; return false; @@ -617,13 +617,13 @@ } IPC::MessageRouter* ChildThreadImpl::GetRouter() { - DCHECK(base::MessageLoop::current() == message_loop()); + DCHECK(message_loop_->task_runner()->BelongsToCurrentThread()); return &router_; } std::unique_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory( size_t buf_size) { - DCHECK(base::MessageLoop::current() == message_loop()); + DCHECK(message_loop_->task_runner()->BelongsToCurrentThread()); return AllocateSharedMemory(buf_size, this, nullptr); }
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc index d91cf32..887f9974 100644 --- a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc +++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -40,6 +40,21 @@ LOAD_FAMILY_MAX_VALUE }; +// This enum is used to define the buckets for an enumerated UMA histogram. +// Hence, +// (a) existing enumerated constants should never be deleted or reordered, and +// (b) new constants should only be appended at the end of the enumeration. +enum FontProxyError { + FIND_FAMILY_SEND_FAILED = 0, + GET_FAMILY_COUNT_SEND_FAILED = 1, + COLLECTION_KEY_INVALID = 2, + FAMILY_INDEX_OUT_OF_RANGE = 3, + GET_FONT_FILES_SEND_FAILED = 4, + MAPPED_FILE_FAILED = 5, + + FONT_PROXY_ERROR_MAX_VALUE +}; + const char kFontKeyName[] = "font_key_name"; void LogLoadFamilyResult(DirectWriteLoadFamilyResult result) { @@ -47,6 +62,15 @@ LOAD_FAMILY_MAX_VALUE); } +void LogFamilyCount(uint32_t count) { + UMA_HISTOGRAM_COUNTS_1000("DirectWrite.Fonts.Proxy.FamilyCount", count); +} + +void LogFontProxyError(FontProxyError error) { + UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.FontProxyError", error, + FONT_PROXY_ERROR_MAX_VALUE); +} + } // namespace DWriteFontCollectionProxy::DWriteFontCollectionProxy() = default; @@ -73,6 +97,7 @@ if (!GetSender()->Send( new DWriteFontProxyMsg_FindFamily(name, &family_index))) { + LogFontProxyError(FIND_FAMILY_SEND_FAILED); return E_FAIL; } @@ -117,8 +142,11 @@ uint32_t family_count = 0; if (!GetSender()->Send( new DWriteFontProxyMsg_GetFamilyCount(&family_count))) { + LogFontProxyError(GET_FAMILY_COUNT_SEND_FAILED); return 0; } + + LogFamilyCount(family_count); family_count_ = family_count; return family_count; } @@ -146,6 +174,7 @@ UINT32 collection_key_size, IDWriteFontFileEnumerator** font_file_enumerator) { if (!collection_key || collection_key_size != sizeof(uint32_t)) { + LogFontProxyError(COLLECTION_KEY_INVALID); return E_INVALIDARG; } @@ -155,6 +184,7 @@ reinterpret_cast<const uint32_t*>(collection_key); if (*family_index >= GetFontFamilyCount()) { + LogFontProxyError(FAMILY_INDEX_OUT_OF_RANGE); return E_INVALIDARG; } @@ -164,6 +194,7 @@ std::vector<base::string16> file_names; if (!GetSender()->Send( new DWriteFontProxyMsg_GetFontFiles(*family_index, &file_names))) { + LogFontProxyError(GET_FONT_FILES_SEND_FAILED); return E_FAIL; } @@ -552,8 +583,10 @@ HRESULT FontFileStream::RuntimeClassInitialize( const base::string16& file_name) { data_.Initialize(base::FilePath(file_name)); - if (!data_.IsValid()) + if (!data_.IsValid()) { + LogFontProxyError(MAPPED_FILE_FAILED); return E_FAIL; + } return S_OK; }
diff --git a/content/child/indexed_db/indexed_db_dispatcher.cc b/content/child/indexed_db/indexed_db_dispatcher.cc index aa40cca..7d6196c6 100644 --- a/content/child/indexed_db/indexed_db_dispatcher.cc +++ b/content/child/indexed_db/indexed_db_dispatcher.cc
@@ -30,6 +30,7 @@ using blink::WebIDBDatabaseError; using blink::WebIDBKey; using blink::WebIDBMetadata; +using blink::WebIDBObserver; using blink::WebIDBValue; using blink::WebString; using blink::WebVector; @@ -167,6 +168,32 @@ return thread_safe_sender_->Send(msg); } +int32_t IndexedDBDispatcher::AddIDBObserver( + int32_t ipc_database_id, + int64_t transaction_id, + std::unique_ptr<WebIDBObserver> observer) { + int32_t observer_id = observers_.Add(observer.release()); + Send(new IndexedDBHostMsg_DatabaseObserve(ipc_database_id, transaction_id, + observer_id)); + return observer_id; +} + +void IndexedDBDispatcher::RemoveIDBObserversFromDatabase( + int32_t ipc_database_id, + const std::vector<int32_t>& observer_ids_to_remove) { + for (int32_t id_to_remove : observer_ids_to_remove) { + observers_.Remove(id_to_remove); + } + Send(new IndexedDBHostMsg_DatabaseUnobserve(ipc_database_id, + observer_ids_to_remove)); +} + +void IndexedDBDispatcher::RemoveIDBObservers( + const std::set<int32_t>& observer_ids_to_remove) { + for (int32_t id : observer_ids_to_remove) + observers_.Remove(id); +} + void IndexedDBDispatcher::RequestIDBCursorAdvance( unsigned long count, WebIDBCallbacks* callbacks_ptr,
diff --git a/content/child/indexed_db/indexed_db_dispatcher.h b/content/child/indexed_db/indexed_db_dispatcher.h index 9e5068d..bb1d3b6 100644 --- a/content/child/indexed_db/indexed_db_dispatcher.h +++ b/content/child/indexed_db/indexed_db_dispatcher.h
@@ -24,6 +24,7 @@ #include "third_party/WebKit/public/platform/WebBlobInfo.h" #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h" #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseCallbacks.h" +#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBObserver.h" #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h" #include "url/origin.h" @@ -74,6 +75,21 @@ // This method is virtual so it can be overridden in unit tests. virtual bool Send(IPC::Message* msg); + int32_t AddIDBObserver(int32_t ipc_database_id, + int64_t transaction_id, + std::unique_ptr<blink::WebIDBObserver> observer); + + // The observer with ID's in |observer_ids_to_remove| observe the + // |ipc_database_id|. + // We remove our local references to these observer objects, and send an IPC + // to clean up the observers from the backend. + void RemoveIDBObserversFromDatabase( + int32_t ipc_database_id, + const std::vector<int32_t>& observer_ids_to_remove); + + // Removes observers from our local map observers_ . No IPC message generated. + void RemoveIDBObservers(const std::set<int32_t>& observer_ids_to_remove); + void RequestIDBFactoryGetDatabaseNames(blink::WebIDBCallbacks* callbacks, const url::Origin& origin); @@ -264,6 +280,7 @@ IDMap<blink::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_; IDMap<blink::WebIDBDatabaseCallbacks, IDMapOwnPointer> pending_database_callbacks_; + IDMap<blink::WebIDBObserver, IDMapOwnPointer> observers_; // Maps the ipc_callback_id from an open cursor request to the request's // transaction_id. Used to assign the transaction_id to the WebIDBCursorImpl
diff --git a/content/child/indexed_db/webidbdatabase_impl.cc b/content/child/indexed_db/webidbdatabase_impl.cc index fedb0e7..1895b5af 100644 --- a/content/child/indexed_db/webidbdatabase_impl.cc +++ b/content/child/indexed_db/webidbdatabase_impl.cc
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/stl_util.h" #include "content/child/indexed_db/indexed_db_dispatcher.h" #include "content/child/indexed_db/indexed_db_key_builders.h" #include "content/child/thread_safe_sender.h" @@ -29,6 +30,7 @@ using blink::WebIDBKey; using blink::WebIDBKeyPath; using blink::WebIDBKeyRange; +using blink::WebIDBObserver; using blink::WebString; using blink::WebVector; @@ -90,6 +92,7 @@ void WebIDBDatabaseImpl::close() { IndexedDBDispatcher* dispatcher = IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); + dispatcher->RemoveIDBObservers(observer_ids_); dispatcher->RequestIDBDatabaseClose(ipc_database_id_, ipc_database_callbacks_id_); } @@ -100,6 +103,33 @@ dispatcher->NotifyIDBDatabaseVersionChangeIgnored(ipc_database_id_); } +int32_t WebIDBDatabaseImpl::addObserver( + std::unique_ptr<WebIDBObserver> observer, + long long transaction_id) { + IndexedDBDispatcher* dispatcher = + IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); + + int32_t observer_id = dispatcher->AddIDBObserver( + ipc_database_id_, transaction_id, std::move(observer)); + observer_ids_.insert(observer_id); + return observer_id; +} + +bool WebIDBDatabaseImpl::containsObserverId(int32_t id) const { + return ContainsValue(observer_ids_, id); +} + +void WebIDBDatabaseImpl::removeObservers( + const std::vector<int32_t>& observer_ids_to_remove) { + for (int32_t id : observer_ids_to_remove) + observer_ids_.erase(id); + + IndexedDBDispatcher* dispatcher = + IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get()); + dispatcher->RemoveIDBObserversFromDatabase(ipc_database_id_, + observer_ids_to_remove); +} + void WebIDBDatabaseImpl::get(long long transaction_id, long long object_store_id, long long index_id,
diff --git a/content/child/indexed_db/webidbdatabase_impl.h b/content/child/indexed_db/webidbdatabase_impl.h index 7d214bb..2be351f 100644 --- a/content/child/indexed_db/webidbdatabase_impl.h +++ b/content/child/indexed_db/webidbdatabase_impl.h
@@ -16,6 +16,7 @@ class WebBlobInfo; class WebIDBCallbacks; class WebIDBDatabaseCallbacks; +class WebIDBObserver; class WebString; } @@ -45,6 +46,12 @@ void close() override; void versionChangeIgnored() override; + int32_t addObserver(std::unique_ptr<blink::WebIDBObserver>, + long long transactionId) override; + bool containsObserverId(int32_t id) const override; + void removeObservers( + const std::vector<int32_t>& observer_ids_to_remove) override; + void get(long long transactionId, long long objectStoreId, long long indexId, @@ -113,6 +120,7 @@ private: int32_t ipc_database_id_; int32_t ipc_database_callbacks_id_; + std::set<int32_t> observer_ids_; scoped_refptr<ThreadSafeSender> thread_safe_sender_; };
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 66c8556f..9c508f7e 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -232,8 +232,8 @@ if (base::FeatureList::IsEnabled(features::kPointerEvents)) WebRuntimeFeatures::enablePointerEvent(true); - WebRuntimeFeatures::enablePassiveDocumentEventListeners( - base::FeatureList::IsEnabled(features::kPassiveDocumentEventListeners)); + if (base::FeatureList::IsEnabled(features::kPassiveDocumentEventListeners)) + WebRuntimeFeatures::enablePassiveDocumentEventListeners(true); WebRuntimeFeatures::enableFeatureFromString( "FontCacheScaling",
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index 7f2fcf3..b3b2cdaf 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -603,7 +603,6 @@ this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); WebURLResponse response; - response.initialize(); PopulateURLResponse(request_.url(), info, &response, request_.reportRawHeaders()); @@ -654,7 +653,6 @@ } WebURLResponse response; - response.initialize(); PopulateURLResponse(request_.url(), info, &response, request_.reportRawHeaders());
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc index 9a4c2d7..d71e1aa 100644 --- a/content/child/web_url_loader_impl_unittest.cc +++ b/content/child/web_url_loader_impl_unittest.cc
@@ -670,7 +670,6 @@ content::ResourceResponseInfo info; info.socket_address = net::HostPortPair(test.ip, 443); blink::WebURLResponse response; - response.initialize(); WebURLLoaderImpl::PopulateURLResponse(url, info, &response, true); EXPECT_EQ(test.expected, response.remoteIPAddress().utf8()); };
diff --git a/content/common/android/media_metadata_android.cc b/content/common/android/media_metadata_android.cc index 0bd1563..4e2228b 100644 --- a/content/common/android/media_metadata_android.cc +++ b/content/common/android/media_metadata_android.cc
@@ -4,12 +4,30 @@ #include "content/common/android/media_metadata_android.h" +#include <string> +#include <vector> + +#include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "content/public/common/media_metadata.h" #include "jni/MediaMetadata_jni.h" namespace content { +namespace { + +std::vector<int> GetFlattenedSizeArray(const std::vector<gfx::Size>& sizes) { + std::vector<int> flattened_array; + flattened_array.reserve(2 * sizes.size()); + for (const auto& size : sizes) { + flattened_array.push_back(size.width()); + flattened_array.push_back(size.height()); + } + return flattened_array; +} + +} // anonymous namespace + // static base::android::ScopedJavaLocalRef<jobject> MediaMetadataAndroid::CreateJavaObject( @@ -21,8 +39,26 @@ ScopedJavaLocalRef<jstring> j_album( base::android::ConvertUTF16ToJavaString(env, metadata.album)); - return Java_MediaMetadata_create( + ScopedJavaLocalRef<jobject> j_metadata = Java_MediaMetadata_create( env, j_title.obj(), j_artist.obj(), j_album.obj()); + + for (const auto& artwork : metadata.artwork) { + std::string src = artwork.src.spec(); + base::string16 type = artwork.type.is_null() ? + base::string16() : artwork.type.string(); + ScopedJavaLocalRef<jstring> j_src( + base::android::ConvertUTF8ToJavaString(env, src)); + ScopedJavaLocalRef<jstring> j_type( + base::android::ConvertUTF16ToJavaString(env, type)); + ScopedJavaLocalRef<jintArray> j_sizes( + base::android::ToJavaIntArray( + env, GetFlattenedSizeArray(artwork.sizes))); + + Java_MediaMetadata_createAndAddArtwork( + env, j_metadata.obj(), j_src.obj(), j_type.obj(), j_sizes.obj()); + } + + return j_metadata; } // static
diff --git a/content/common/indexed_db/indexed_db_messages.h b/content/common/indexed_db/indexed_db_messages.h index 68af020..977bb658 100644 --- a/content/common/indexed_db/indexed_db_messages.h +++ b/content/common/indexed_db/indexed_db_messages.h
@@ -485,6 +485,17 @@ IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_AckReceivedBlobs, std::vector<std::string>) /* uuids */ +// WebIDBDatabase::observe() message. +IPC_MESSAGE_CONTROL3(IndexedDBHostMsg_DatabaseObserve, + int32_t, /* ipc_database_id */ + int64_t, /* transaction_id */ + int32_t) /* observer_id */ + +// WebIDBDatabase::unobserve() message. +IPC_MESSAGE_CONTROL2(IndexedDBHostMsg_DatabaseUnobserve, + int32_t, /* ipc_database_id */ + std::vector<int32_t>) /* list of observer_id */ + // WebIDBDatabase::createObjectStore() message. IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseCreateObjectStore, IndexedDBHostMsg_DatabaseCreateObjectStore_Params)
diff --git a/content/common/manifest_manager_messages.h b/content/common/manifest_manager_messages.h index 6bdb98f..c052f27 100644 --- a/content/common/manifest_manager_messages.h +++ b/content/common/manifest_manager_messages.h
@@ -30,6 +30,7 @@ IPC_STRUCT_TRAITS_MEMBER(name) IPC_STRUCT_TRAITS_MEMBER(short_name) IPC_STRUCT_TRAITS_MEMBER(start_url) + IPC_STRUCT_TRAITS_MEMBER(scope) IPC_STRUCT_TRAITS_MEMBER(display) IPC_STRUCT_TRAITS_MEMBER(orientation) IPC_STRUCT_TRAITS_MEMBER(icons)
diff --git a/content/common/media/aec_dump_messages.h b/content/common/media/aec_dump_messages.h index f6031d0..0f98f27 100644 --- a/content/common/media/aec_dump_messages.h +++ b/content/common/media/aec_dump_messages.h
@@ -21,18 +21,9 @@ int /* id */, IPC::PlatformFileForTransit /* file_handle */) -// The browser hands over a file handle to the consumer in the renderer -// identified by |id| to use for the event log. -IPC_MESSAGE_CONTROL2(WebRTCEventLogMsg_EnableEventLog, - int /* id */, - IPC::PlatformFileForTransit /* file_handle */) - // Tell the renderer to disable AEC dump in all consumers. IPC_MESSAGE_CONTROL0(AecDumpMsg_DisableAecDump) -// Tell the renderer to disable event log in all consumers. -IPC_MESSAGE_CONTROL0(WebRTCEventLogMsg_DisableEventLog) - // Messages sent from the renderer to the browser. // Registers a consumer with the browser. The consumer will then get a file @@ -40,13 +31,6 @@ IPC_MESSAGE_CONTROL1(AecDumpMsg_RegisterAecDumpConsumer, int /* id */) -// Registers a consumer with the browser. The consumer will then get a file -// handle when the dump is enabled. -IPC_MESSAGE_CONTROL1(WebRTCEventLogMsg_RegisterEventLogConsumer, int /* id */) - // Unregisters a consumer with the browser. IPC_MESSAGE_CONTROL1(AecDumpMsg_UnregisterAecDumpConsumer, int /* id */) - -// Unregisters a consumer with the browser. -IPC_MESSAGE_CONTROL1(WebRTCEventLogMsg_UnregisterEventLogConsumer, int /* id */)
diff --git a/content/common/media/media_metadata_sanitizer.cc b/content/common/media/media_metadata_sanitizer.cc new file mode 100644 index 0000000..ad3bf02 --- /dev/null +++ b/content/common/media/media_metadata_sanitizer.cc
@@ -0,0 +1,113 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/common/media/media_metadata_sanitizer.h" + +#include <algorithm> +#include <string> + +namespace content { + +namespace { + +// Maximum length for all the strings inside the MediaMetadata when it is sent +// over IPC. The renderer process should truncate the strings before sending +// the MediaMetadata and the browser process must do the same when receiving +// it. +const size_t kMaxIPCStringLength = 4 * 1024; + +// Maximum type length of Artwork, which conforms to RFC 4288 +// (https://tools.ietf.org/html/rfc4288). +const size_t kMaxArtworkTypeLength = 2 * 127 + 1; + +// Maximum number of artwork images inside the MediaMetadata. +const size_t kMaxNumberOfArtworkImages = 10; + +// Maximum of sizes in an artwork image. +const size_t kMaxNumberOfArtworkSizes = 10; + +bool CheckArtworkSrcSanity(const GURL& src) { + if (!src.is_valid()) + return false; + if (!src.SchemeIsHTTPOrHTTPS() && !src.SchemeIs(url::kDataScheme)) + return false; + if (src.spec().size() > url::kMaxURLChars) + return false; + + return true; +} + +bool CheckArtworkSanity(const MediaMetadata::Artwork& artwork) { + if (!CheckArtworkSrcSanity(artwork.src)) + return false; + if (artwork.type.is_null()) + return false; + if (artwork.type.string().size() > kMaxArtworkTypeLength) + return false; + if (artwork.sizes.size() > kMaxNumberOfArtworkSizes) + return false; + + return true; +} + +// Sanitize artwork. The method should not be called if |artwork.src| is bad. +MediaMetadata::Artwork SanitizeArtwork(const MediaMetadata::Artwork& artwork) { + MediaMetadata::Artwork sanitized_artwork; + + sanitized_artwork.src = artwork.src; + sanitized_artwork.type = artwork.type.is_null() ? + base::NullableString16() : + base::NullableString16( + artwork.type.string().substr(0, kMaxArtworkTypeLength), false); + for (const auto& size : artwork.sizes) { + sanitized_artwork.sizes.push_back(size); + if (sanitized_artwork.sizes.size() == kMaxNumberOfArtworkSizes) + break; + } + + return sanitized_artwork; +} + +} // anonymous namespace + +bool MediaMetadataSanitizer::CheckSanity(const MediaMetadata& metadata) { + if (metadata.title.size() > kMaxIPCStringLength) + return false; + if (metadata.artist.size() > kMaxIPCStringLength) + return false; + if (metadata.album.size() > kMaxIPCStringLength) + return false; + if (metadata.artwork.size() > kMaxNumberOfArtworkImages) + return false; + + for (const auto& artwork : metadata.artwork) { + if (!CheckArtworkSanity(artwork)) + return false; + } + + return true; +} + +MediaMetadata MediaMetadataSanitizer::Sanitize(const MediaMetadata& metadata) { + MediaMetadata sanitized_metadata; + + sanitized_metadata.title = metadata.title.substr(0, kMaxIPCStringLength); + sanitized_metadata.artist = metadata.artist.substr(0, kMaxIPCStringLength); + sanitized_metadata.album = metadata.album.substr(0, kMaxIPCStringLength); + + for (const auto& artwork : metadata.artwork) { + if (!CheckArtworkSrcSanity(artwork.src)) + continue; + + sanitized_metadata.artwork.push_back( + CheckArtworkSanity(artwork) ? artwork : SanitizeArtwork(artwork)); + + if (sanitized_metadata.artwork.size() == kMaxNumberOfArtworkImages) + break; + } + + return sanitized_metadata; +} + +} // namespace content
diff --git a/content/common/media/media_metadata_sanitizer.h b/content/common/media/media_metadata_sanitizer.h new file mode 100644 index 0000000..fa08ebb7 --- /dev/null +++ b/content/common/media/media_metadata_sanitizer.h
@@ -0,0 +1,23 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_COMMON_MEDIA_MEDIA_METADATA_SANITIZER_H_ +#define CONTENT_COMMON_MEDIA_MEDIA_METADATA_SANITIZER_H_ + +#include "content/public/common/media_metadata.h" + +namespace content { + +class MediaMetadataSanitizer { + public: + // Check the sanity of |metadata|. + static bool CheckSanity(const MediaMetadata& metadata); + + // Sanitizes |metadata| and return the result. + static MediaMetadata Sanitize(const MediaMetadata& metadata); +}; + +} // namespace content + +#endif // CONTENT_COMMON_MEDIA_MEDIA_METADATA_SANITIZER_H_
diff --git a/content/common/media/media_session_messages_android.h b/content/common/media/media_session_messages_android.h index 266ee27..7e951d13 100644 --- a/content/common/media/media_session_messages_android.h +++ b/content/common/media/media_session_messages_android.h
@@ -18,6 +18,7 @@ IPC_STRUCT_TRAITS_MEMBER(title) IPC_STRUCT_TRAITS_MEMBER(artist) IPC_STRUCT_TRAITS_MEMBER(album) + IPC_STRUCT_TRAITS_MEMBER(artwork) IPC_STRUCT_TRAITS_END() // Messages for notifying the render process of media session status -------
diff --git a/content/common/media/peer_connection_tracker_messages.h b/content/common/media/peer_connection_tracker_messages.h index cd774bea..130f3b6 100644 --- a/content/common/media/peer_connection_tracker_messages.h +++ b/content/common/media/peer_connection_tracker_messages.h
@@ -5,6 +5,7 @@ #include "base/values.h" #include "content/common/content_export.h" #include "ipc/ipc_message_macros.h" +#include "ipc/ipc_platform_file.h" #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT CONTENT_EXPORT @@ -41,3 +42,8 @@ // Messages sent to PeerConnectionTracker. IPC_MESSAGE_CONTROL0(PeerConnectionTracker_GetAllStats) IPC_MESSAGE_CONTROL0(PeerConnectionTracker_OnSuspend) +IPC_MESSAGE_CONTROL2(PeerConnectionTracker_StartEventLog, + int /* peer_connection_local_id */, + IPC::PlatformFileForTransit /* file */) +IPC_MESSAGE_CONTROL1(PeerConnectionTracker_StopEventLog, + int /* peer_connection_local_id */)
diff --git a/content/common/mojo/embedded_application_runner.cc b/content/common/mojo/embedded_application_runner.cc index 39a5eb13..c0257e1 100644 --- a/content/common/mojo/embedded_application_runner.cc +++ b/content/common/mojo/embedded_application_runner.cc
@@ -13,7 +13,7 @@ #include "base/threading/thread.h" #include "base/threading/thread_checker.h" #include "base/threading/thread_task_runner_handle.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" namespace content { @@ -68,8 +68,8 @@ base::Bind(&Instance::Quit, base::Unretained(this))); } - shell::ShellConnection* new_connection = - new shell::ShellConnection(service_.get(), std::move(request)); + shell::ServiceContext* new_connection = + new shell::ServiceContext(service_.get(), std::move(request)); shell_connections_.push_back(base::WrapUnique(new_connection)); new_connection->SetConnectionLostClosure( base::Bind(&Instance::OnStop, base::Unretained(this), @@ -85,7 +85,7 @@ DCHECK(!thread_); } - void OnStop(shell::ShellConnection* connection) { + void OnStop(shell::ServiceContext* connection) { DCHECK(application_task_runner_->BelongsToCurrentThread()); for (auto it = shell_connections_.begin(); it != shell_connections_.end(); @@ -130,7 +130,7 @@ // the destructor which may run on either the runner thread or the application // thread. std::unique_ptr<shell::Service> service_; - std::vector<std::unique_ptr<shell::ShellConnection>> shell_connections_; + std::vector<std::unique_ptr<shell::ServiceContext>> shell_connections_; DISALLOW_COPY_AND_ASSIGN(Instance); };
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc index 86bb712..5311ba6c 100644 --- a/content/common/mojo/mojo_shell_connection_impl.cc +++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -10,7 +10,7 @@ #include "base/threading/thread_local.h" #include "content/common/mojo/embedded_application_runner.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/runner/common/client_util.h" namespace content { @@ -70,7 +70,7 @@ MojoShellConnectionImpl::MojoShellConnectionImpl( shell::mojom::ServiceRequest request) - : shell_connection_(new shell::ShellConnection(this, std::move(request))) {} + : shell_connection_(new shell::ServiceContext(this, std::move(request))) {} MojoShellConnectionImpl::~MojoShellConnectionImpl() {} @@ -150,7 +150,7 @@ //////////////////////////////////////////////////////////////////////////////// // MojoShellConnectionImpl, MojoShellConnection implementation: -shell::ShellConnection* MojoShellConnectionImpl::GetShellConnection() { +shell::ServiceContext* MojoShellConnectionImpl::GetShellConnection() { return shell_connection_.get(); }
diff --git a/content/common/mojo/mojo_shell_connection_impl.h b/content/common/mojo/mojo_shell_connection_impl.h index c47961d..6a6882413 100644 --- a/content/common/mojo/mojo_shell_connection_impl.h +++ b/content/common/mojo/mojo_shell_connection_impl.h
@@ -13,7 +13,7 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/system/message_pipe.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/public/interfaces/service_factory.mojom.h" namespace content { @@ -32,7 +32,7 @@ private: // MojoShellConnection: - shell::ShellConnection* GetShellConnection() override; + shell::ServiceContext* GetShellConnection() override; shell::Connector* GetConnector() override; const shell::Identity& GetIdentity() const override; void SetConnectionLostClosure(const base::Closure& closure) override; @@ -60,7 +60,7 @@ void CreateService(shell::mojom::ServiceRequest request, const mojo::String& name) override; - std::unique_ptr<shell::ShellConnection> shell_connection_; + std::unique_ptr<shell::ServiceContext> shell_connection_; mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; std::vector<shell::Service*> embedded_services_; std::vector<std::unique_ptr<shell::Service>> owned_services_;
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 33d7c73..7aa2ca6 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -917,6 +917,8 @@ 'browser/indexed_db/indexed_db_leveldb_coding.h', 'browser/indexed_db/indexed_db_metadata.cc', 'browser/indexed_db/indexed_db_metadata.h', + 'browser/indexed_db/indexed_db_observer.cc', + 'browser/indexed_db/indexed_db_observer.h', 'browser/indexed_db/indexed_db_pending_connection.cc', 'browser/indexed_db/indexed_db_pending_connection.h', 'browser/indexed_db/indexed_db_quota_client.cc', @@ -1693,6 +1695,8 @@ 'browser/accessibility/browser_accessibility_manager_auralinux.h', ], 'webrtc_browser_sources': [ + 'browser/media/webrtc/webrtc_eventlog_host.cc', + 'browser/media/webrtc/webrtc_eventlog_host.h', 'browser/media/webrtc/webrtc_internals.cc', 'browser/media/webrtc/webrtc_internals.h', 'browser/media/webrtc/webrtc_internals_message_handler.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi index d867849..10cc09f7 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi
@@ -411,6 +411,8 @@ 'common/media/cdm_info.cc', 'common/media/cdm_messages.h', 'common/media/cdm_messages_enums.h', + 'common/media/media_metadata_sanitizer.cc', + 'common/media/media_metadata_sanitizer.h', 'common/media/media_player_delegate_messages.h', 'common/media/media_player_messages_android.h', 'common/media/media_session_messages_android.h',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index d7e3f627..1d634bc 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -248,6 +248,7 @@ 'browser/media/media_redirect_browsertest.cc', 'browser/media/media_source_browsertest.cc', 'browser/media/midi_browsertest.cc', + 'browser/media/android/browser_media_session_manager_browsertest.cc', 'browser/media/session/media_session_browsertest.cc', 'browser/media/session/media_session_delegate_default_browsertest.cc', 'browser/media/session/media_session_visibility_browsertest.cc', @@ -774,6 +775,7 @@ # WebRTC-specific sources. Put WebRTC plugin-related stuff further below. 'content_unittests_webrtc_sources': [ 'browser/media/webrtc/webrtc_internals_unittest.cc', + 'browser/media/webrtc/webrtc_eventlog_host_unittest.cc', 'browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc', 'browser/renderer_host/p2p/socket_host_tcp_unittest.cc', 'browser/renderer_host/p2p/socket_host_test_utils.cc',
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index 993265e..af207ab 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc
@@ -173,7 +173,6 @@ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory) : ChildThreadImpl(ChildThreadImpl::Options::Builder() .InBrowserProcess(params) - .UseMojoChannel(true) .AddStartupFilter(new GpuMemoryBufferMessageFilter( gpu_memory_buffer_factory)) .Build()),
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index ea5e4bc..a32122d 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -18,6 +18,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" #include "base/rand_util.h" +#include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/platform_thread.h" @@ -149,7 +150,7 @@ bool PpapiThread::Send(IPC::Message* msg) { // Allow access from multiple threads. - if (base::MessageLoop::current() == message_loop()) + if (message_loop()->task_runner()->BelongsToCurrentThread()) return ChildThreadImpl::Send(msg); return sync_message_filter()->Send(msg);
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java index f1f2720..0886e4cb 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
@@ -11,6 +11,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.view.DragEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -146,6 +147,11 @@ } @Override + public boolean onDragEvent(DragEvent event) { + return mContentViewCore.onDragEvent(event); + } + + @Override public boolean onTouchEvent(MotionEvent event) { return mContentViewCore.onTouchEvent(event); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index 561c165..0fe099be 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -1793,12 +1793,13 @@ } /** - * Sets the current amount to offset incoming touch events by. This is used to handle content - * moving and not lining up properly with the android input system. + * Sets the current amount to offset incoming touch events by (including MotionEvent and + * DragEvent). This is used to handle content moving and not lining up properly with the + * android input system. * @param dx The X offset in pixels to shift touch events. * @param dy The Y offset in pixels to shift touch events. */ - public void setCurrentMotionEventOffsets(float dx, float dy) { + public void setCurrentTouchEventOffsets(float dx, float dy) { mCurrentTouchOffsetX = dx; mCurrentTouchOffsetY = dy; } @@ -3312,17 +3313,19 @@ } } - float scale = (float) DeviceDisplayInfo.create(mContainerView.getContext()).getDIPScale(); int[] locationOnScreen = new int[2]; mContainerView.getLocationOnScreen(locationOnScreen); - int x = (int) (event.getX() / scale); - int y = (int) (event.getY() / scale); - int screenX = (int) ((event.getX() + locationOnScreen[0]) / scale); - int screenY = (int) ((event.getY() + locationOnScreen[1]) / scale); + float xPix = event.getX() + mRenderCoordinates.getScrollXPixInt() + mCurrentTouchOffsetX; + float yPix = event.getY() + mRenderCoordinates.getScrollYPixInt() + mCurrentTouchOffsetY; - nativeOnDragEvent(mNativeContentViewCore, event.getAction(), x, y, screenX, screenY, - mimeTypes, content.toString()); + int xCss = (int) mRenderCoordinates.fromPixToLocalCss(xPix); + int yCss = (int) mRenderCoordinates.fromPixToLocalCss(yPix); + int screenXCss = (int) mRenderCoordinates.fromPixToLocalCss(xPix + locationOnScreen[0]); + int screenYCss = (int) mRenderCoordinates.fromPixToLocalCss(yPix + locationOnScreen[1]); + + nativeOnDragEvent(mNativeContentViewCore, event.getAction(), xCss, yCss, screenXCss, + screenYCss, mimeTypes, content.toString()); return true; }
diff --git a/content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java b/content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java index a1e9828..9303347 100644 --- a/content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java +++ b/content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java
@@ -4,18 +4,87 @@ package org.chromium.content_public.common; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.text.TextUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import java.util.ArrayList; +import java.util.List; + /** * The MediaMetadata class carries information related to a media session. It is * the Java counterpart of content::MediaMetadata. */ @JNINamespace("content") public class MediaMetadata { + /** + * The Artwork class carries the artwork information in MediaMetadata. It is the Java + * counterpart of content::MediaMetadata::Artwork. + */ + public static class Artwork { + @NonNull + private String mSrc; + + private String mType; + + @NonNull + private List<Rect> mSizes = new ArrayList<Rect>(); + + /** + * Creates a new Artwork. + */ + public Artwork(@NonNull String src, String type, List<Rect> sizes) { + mSrc = src; + mType = type; + mSizes = sizes; + } + + /** + * Returns the URL of this Artwork. + */ + @NonNull + public String getSrc() { + return mSrc; + } + + /** + * Returns the MIME type of this Artwork. + */ + public String getType() { + return mType; + } + + /** + * Returns the hinted sizes of this Artwork. + */ + public List<Rect> getSizes() { + return mSizes; + } + + /** + * Sets the URL of this Artwork. + */ + public void setSrc(String src) { + mSrc = src; + } + + /** + * Sets the MIME type of this Artwork. + */ + public void setType(String type) { + mType = type; + } + + /** + * Sets the sizes of this Artwork. + */ + public void setSizes(List<Rect> sizes) { + mSizes = sizes; + } + } @NonNull private String mTitle; @@ -26,6 +95,9 @@ @NonNull private String mAlbum; + @NonNull + private List<Artwork> mArtwork = new ArrayList<Artwork>(); + /** * Returns the title associated with the media session. */ @@ -47,6 +119,10 @@ return mAlbum; } + public List<Artwork> getArtwork() { + return mArtwork; + } + /** * Sets the title associated with the media session. * @param title The title to use for the media session. @@ -72,6 +148,23 @@ } /** + * Create a new MediaArtwork from the C++ code, and add it to the Metadata. + * @param src The URL of the artwork. + * @param type The MIME type of the artwork. + * @param flattenedSizes The flattened array of Artwork sizes. In native code, it is of type + * `std::vector<gfx::Size>` before flattening. + */ + @CalledByNative + private void createAndAddArtwork(String src, String type, int[] flattenedSizes) { + assert (flattenedSizes.length % 2) == 0; + List<Rect> sizes = new ArrayList<Rect>(); + for (int i = 0; (i + 1) < flattenedSizes.length; i += 2) { + sizes.add(new Rect(0, 0, flattenedSizes[i], flattenedSizes[i + 1])); + } + mArtwork.add(new Artwork(src, type, sizes)); + } + + /** * Creates a new MediaMetadata from the C++ code. This is exactly like the * constructor below apart that it can be called by native code. */
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index cb4418c0..8526ef7e 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -220,8 +220,15 @@ virtual void EnableAudioDebugRecordings(const base::FilePath& file) = 0; virtual void DisableAudioDebugRecordings() = 0; - virtual void EnableEventLogRecordings(const base::FilePath& file) = 0; - virtual void DisableEventLogRecordings() = 0; + // Starts a WebRTC event log for each peerconnection on the render process. + // A base file_path can be supplied, which will be extended to include several + // identifiers to ensure uniqueness. If a recording was already in progress, + // this call will return false and have no other effect. + virtual bool StartWebRTCEventLog(const base::FilePath& file_path) = 0; + + // Stops recording a WebRTC event log for each peerconnection on the render + // process. If no recording was in progress, this call will return false. + virtual bool StopWebRTCEventLog() = 0; // When set, |callback| receives log messages regarding, for example, media // devices (webcams, mics, etc) that were initially requested in the render
diff --git a/content/public/browser/security_style_explanations.h b/content/public/browser/security_style_explanations.h index adba598e..3b8a28d5 100644 --- a/content/public/browser/security_style_explanations.h +++ b/content/public/browser/security_style_explanations.h
@@ -23,7 +23,7 @@ // SecurityStyleExplanation is a single security property of a page (for // example, an expired certificate, a valid certificate, or the presence // of a deprecated crypto algorithm). A single site may have multiple -// different explanations of "secure", "warning", and "broken" severity +// different explanations of "secure", "warning", "broken", and "info" severity // levels. struct SecurityStyleExplanations { CONTENT_EXPORT SecurityStyleExplanations(); @@ -49,9 +49,12 @@ // True if PKP was bypassed due to a local trust anchor. bool pkp_bypassed; + // Explanations corresponding to each security level. The embedder should + // display explanations in the order: broken, unauthenticated, secure, info. std::vector<SecurityStyleExplanation> secure_explanations; std::vector<SecurityStyleExplanation> unauthenticated_explanations; std::vector<SecurityStyleExplanation> broken_explanations; + std::vector<SecurityStyleExplanation> info_explanations; }; } // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 72da725..06b7faab 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -65,8 +65,7 @@ // Non-validating reload for desktop. // See https://crbug.com/591245 const base::Feature kNonValidatingReloadOnNormalReload{ - "NonValidatingReloadOnNormalReload", - base::FEATURE_DISABLED_BY_DEFAULT}; + "NonValidatingReloadOnNormalReload", base::FEATURE_ENABLED_BY_DEFAULT}; // Non-validating reload on reload-to-refresh-content (e.g. pull-to-refresh). // See https://crbug.com/591245
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 4383bb3..2521300 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -243,6 +243,9 @@ // Disables the Permissions API. const char kDisablePermissionsAPI[] = "disable-permissions-api"; +// Disable Image Chromium for Pepper 3d. +const char kDisablePepper3DImageChromium[] = "disable-pepper-3d-image-chromium"; + // Disables compositor-accelerated touch-screen pinch gestures. const char kDisablePinch[] = "disable-pinch";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 75cc469..a5fa59c 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -79,6 +79,7 @@ CONTENT_EXPORT extern const char kDisablePartialRaster[]; CONTENT_EXPORT extern const char kEnablePartialRaster[]; extern const char kDisablePepper3d[]; +CONTENT_EXPORT extern const char kDisablePepper3DImageChromium[]; CONTENT_EXPORT extern const char kDisablePermissionsAPI[]; CONTENT_EXPORT extern const char kDisablePinch[]; CONTENT_EXPORT extern const char kDisablePresentationAPI[];
diff --git a/content/public/common/manifest.cc b/content/public/common/manifest.cc index cde3498f..8e09aad2 100644 --- a/content/public/common/manifest.cc +++ b/content/public/common/manifest.cc
@@ -21,6 +21,10 @@ Manifest::Icon::~Icon() { } +bool Manifest::Icon::operator==(const Manifest::Icon& other) const { + return src == other.src && type == other.type && sizes == other.sizes; +} + Manifest::RelatedApplication::RelatedApplication() { }
diff --git a/content/public/common/manifest.h b/content/public/common/manifest.h index 2fba5d4e..71e8f605 100644 --- a/content/public/common/manifest.h +++ b/content/public/common/manifest.h
@@ -30,6 +30,8 @@ Icon(const Icon& other); ~Icon(); + bool operator==(const Icon& other) const; + // MUST be a valid url. If an icon doesn't have a valid URL, it will not be // successfully parsed, thus will not be represented in the Manifest. GURL src;
diff --git a/content/public/common/media_metadata.cc b/content/public/common/media_metadata.cc index dc3824c2..32b353a5 100644 --- a/content/public/common/media_metadata.cc +++ b/content/public/common/media_metadata.cc
@@ -4,16 +4,20 @@ #include "content/public/common/media_metadata.h" -namespace content { +#include <algorithm> +#include <iterator> -const size_t MediaMetadata::kMaxIPCStringLength = 4 * 1024; +namespace content { MediaMetadata::MediaMetadata() = default; MediaMetadata::~MediaMetadata() = default; +MediaMetadata::MediaMetadata(const MediaMetadata& other) = default; + bool MediaMetadata::operator==(const MediaMetadata& other) const { - return title == other.title && artist == other.artist && album == other.album; + return title == other.title && artist == other.artist && + album == other.album && artwork == other.artwork; } bool MediaMetadata::operator!=(const MediaMetadata& other) const {
diff --git a/content/public/common/media_metadata.h b/content/public/common/media_metadata.h index 3d7f13c..6cd662a 100644 --- a/content/public/common/media_metadata.h +++ b/content/public/common/media_metadata.h
@@ -5,17 +5,26 @@ #ifndef CONTENT_PUBLIC_COMMON_MEDIA_METADATA_H_ #define CONTENT_PUBLIC_COMMON_MEDIA_METADATA_H_ +#include <vector> + #include "base/strings/string16.h" #include "content/common/content_export.h" +#include "content/public/common/manifest.h" namespace content { // The MediaMetadata is a structure carrying information associated to a // content::MediaSession. struct CONTENT_EXPORT MediaMetadata { + // TODO(zqzhang): move |Manifest::Icon| to a common place. See + // https://crbug.com/621859. + using Artwork = Manifest::Icon; + MediaMetadata(); ~MediaMetadata(); + MediaMetadata(const MediaMetadata& other); + bool operator==(const MediaMetadata& other) const; bool operator!=(const MediaMetadata& other) const; @@ -28,11 +37,8 @@ // Album associated to the MediaSession. base::string16 album; - // Maximum length for all the strings inside the MediaMetadata when it is sent - // over IPC. The renderer process should truncate the strings before sending - // the MediaMetadata and the browser process must do the same when receiving - // it. - static const size_t kMaxIPCStringLength; + // Artwork associated to the MediaSession. + std::vector<Artwork> artwork; }; } // namespace content
diff --git a/content/public/common/mojo_shell_connection.h b/content/public/common/mojo_shell_connection.h index 63428b4..7014034 100644 --- a/content/public/common/mojo_shell_connection.h +++ b/content/public/common/mojo_shell_connection.h
@@ -16,13 +16,13 @@ namespace shell { class Connection; class Connector; -class ShellConnection; +class ServiceContext; } namespace content { // Encapsulates a connection to a //services/shell. -// Access a global instance on the thread the ShellConnection was bound by +// Access a global instance on the thread the ServiceContext was bound by // calling Holder::Get(). // Clients can add shell::Service implementations whose exposed interfaces // will be exposed to inbound connections to this object's Service. @@ -59,9 +59,9 @@ static std::unique_ptr<MojoShellConnection> Create( shell::mojom::ServiceRequest request); - // Returns the bound shell::ShellConnection object. + // Returns the bound shell::ServiceContext object. // TODO(rockot): remove. - virtual shell::ShellConnection* GetShellConnection() = 0; + virtual shell::ServiceContext* GetShellConnection() = 0; // Returns the shell::Connector received via this connection's Service // implementation. Use this to initiate connections as this object's Identity.
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 873a153..4cf34819 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -22,11 +22,17 @@ #include "base/test/test_timeouts.h" #include "base/values.h" #include "build/build_config.h" +#include "cc/surfaces/surface.h" +#include "cc/surfaces/surface_manager.h" #include "content/browser/accessibility/accessibility_mode_helper.h" #include "content/browser/accessibility/browser_accessibility.h" #include "content/browser/accessibility/browser_accessibility_manager.h" +#include "content/browser/browser_plugin/browser_plugin_guest.h" +#include "content/browser/compositor/surface_utils.h" +#include "content/browser/frame_host/cross_process_frame_connector.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/frame_host/render_widget_host_view_child_frame.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_view.h" @@ -1002,6 +1008,90 @@ return manager->SnapshotAXTreeForTesting(); } +bool IsWebContentsBrowserPluginFocused(content::WebContents* web_contents) { + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(web_contents); + BrowserPluginGuest* browser_plugin_guest = + web_contents_impl->GetBrowserPluginGuest(); + return browser_plugin_guest ? browser_plugin_guest->focused() : false; +} + +#if defined(USE_AURA) +void SendRoutedTouchTapSequence(content::WebContents* web_contents, + gfx::Point point) { + RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( + web_contents->GetRenderWidgetHostView()); + ui::TouchEvent touch_start(ui::ET_TOUCH_PRESSED, point, 0, + base::TimeTicks::Now()); + rwhva->OnTouchEvent(&touch_start); + ui::TouchEvent touch_end(ui::ET_TOUCH_RELEASED, point, 0, + base::TimeTicks::Now()); + rwhva->OnTouchEvent(&touch_end); +} + +void SendRoutedGestureTapSequence(content::WebContents* web_contents, + gfx::Point point) { + RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>( + web_contents->GetRenderWidgetHostView()); + ui::GestureEventDetails gesture_tap_down_details(ui::ET_GESTURE_TAP_DOWN); + gesture_tap_down_details.set_device_type( + ui::GestureDeviceType::DEVICE_TOUCHSCREEN); + ui::GestureEvent gesture_tap_down(point.x(), point.y(), 0, + base::TimeTicks::Now(), + gesture_tap_down_details); + rwhva->OnGestureEvent(&gesture_tap_down); + ui::GestureEventDetails gesture_tap_details(ui::ET_GESTURE_TAP); + gesture_tap_details.set_device_type( + ui::GestureDeviceType::DEVICE_TOUCHSCREEN); + gesture_tap_details.set_tap_count(1); + ui::GestureEvent gesture_tap(point.x(), point.y(), 0, base::TimeTicks::Now(), + gesture_tap_details); + rwhva->OnGestureEvent(&gesture_tap); +} + +// TODO(wjmaclean): The next two functions are a modified version of +// SurfaceHitTestReadyNotifier that (1) works for BrowserPlugin-based guests, +// and (2) links outside of content-browsertests. At some point in time we +// should probably merge these. +namespace { + +bool ContainsSurfaceId(cc::SurfaceId container_surface_id, + RenderWidgetHostViewChildFrame* target_view) { + if (container_surface_id.is_null()) + return false; + for (cc::SurfaceId id : + GetSurfaceManager()->GetSurfaceForId(container_surface_id) + ->referenced_surfaces()) { + if (id == target_view->SurfaceIdForTesting() || + ContainsSurfaceId(id, target_view)) + return true; + } + return false; +} + +} // namespace + +void WaitForGuestSurfaceReady(content::WebContents* guest_web_contents) { + RenderWidgetHostViewChildFrame* child_view = + static_cast<RenderWidgetHostViewChildFrame*>( + guest_web_contents->GetRenderWidgetHostView()); + + cc::SurfaceId root_surface_id = + static_cast<RenderWidgetHostViewAura*>( + static_cast<content::WebContentsImpl*>(guest_web_contents) + ->GetOuterWebContents() + ->GetRenderWidgetHostView()) + ->SurfaceIdForTesting(); + + while (!ContainsSurfaceId(root_surface_id, child_view)) { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout()); + run_loop.Run(); + } +} +#endif + TitleWatcher::TitleWatcher(WebContents* web_contents, const base::string16& expected_title) : WebContentsObserver(web_contents),
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 52c44381..3793c11 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -310,6 +310,33 @@ // Get a snapshot of a web page's accessibility tree. ui::AXTreeUpdate GetAccessibilityTreeSnapshot(WebContents* web_contents); +// Find out if the BrowserPlugin for a guest WebContents is focused. Returns +// false if the WebContents isn't a guest with a BrowserPlugin. +bool IsWebContentsBrowserPluginFocused(content::WebContents* web_contents); + +#if defined(USE_AURA) +// The following two methods allow a test to send a touch tap sequence, and +// a corresponding gesture tap sequence, by sending it to the top-level +// WebContents for the page. + +// Send a TouchStart/End sequence routed via the main frame's +// RenderWidgetHostViewAura. +void SendRoutedTouchTapSequence(content::WebContents* web_contents, + gfx::Point point); + +// Send a GestureTapDown/GestureTap sequence routed via the main frame's +// RenderWidgetHostViewAura. +void SendRoutedGestureTapSequence(content::WebContents* web_contents, + gfx::Point point); +// +// Waits until the cc::Surface associated with a guest/cross-process-iframe +// has been drawn for the first time. Once this method returns it should be +// safe to assume that events sent to the top-level RenderWidgetHostView can +// be expected to properly hit-test to this surface, if appropriate. +void WaitForGuestSurfaceReady(content::WebContents* web_contents); + +#endif + // Watches title changes on a WebContents, blocking until an expected title is // set. class TitleWatcher : public WebContentsObserver {
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 4eed8a7..a75a3f9 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -317,10 +317,14 @@ void MockRenderProcessHost::DisableAudioDebugRecordings() {} -void MockRenderProcessHost::EnableEventLogRecordings( - const base::FilePath& file) {} +bool MockRenderProcessHost::StartWebRTCEventLog( + const base::FilePath& file_path) { + return false; +} -void MockRenderProcessHost::DisableEventLogRecordings() {} +bool MockRenderProcessHost::StopWebRTCEventLog() { + return false; +} void MockRenderProcessHost::SetWebRtcLogMessageCallback( base::Callback<void(const std::string&)> callback) {
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 8b14db91..38030657 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -82,8 +82,8 @@ #if defined(ENABLE_WEBRTC) void EnableAudioDebugRecordings(const base::FilePath& file) override; void DisableAudioDebugRecordings() override; - void EnableEventLogRecordings(const base::FilePath& file) override; - void DisableEventLogRecordings() override; + bool StartWebRTCEventLog(const base::FilePath& file_path) override; + bool StopWebRTCEventLog() override; void SetWebRtcLogMessageCallback( base::Callback<void(const std::string&)> callback) override; void ClearWebRtcLogMessageCallback() override;
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index 932c42e..72c1e356 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -38,6 +38,7 @@ #include "content/test/test_content_client.h" #include "content/test/test_render_frame.h" #include "third_party/WebKit/public/platform/WebScreenInfo.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebHistoryItem.h" @@ -186,6 +187,7 @@ url_string.append(html); GURL url(url_string); WebURLRequest request(url); + request.setRequestorOrigin(blink::WebSecurityOrigin::createUnique()); request.setCheckForBrowserSideNavigation(false); GetMainFrame()->loadRequest(request); // The load actually happens asynchronously, so we pump messages to process
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc index ed3e7483..594c4be 100644 --- a/content/public/test/text_input_test_utils.cc +++ b/content/public/test/text_input_test_utils.cc
@@ -13,6 +13,7 @@ #include "content/browser/renderer_host/text_input_manager.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/text_input_state.h" +#include "content/common/view_messages.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" @@ -35,7 +36,6 @@ public: InternalObserver(WebContents* web_contents, TextInputManagerTester* tester) : WebContentsObserver(web_contents), - tester_(tester), updated_view_(nullptr), text_input_state_changed_(false) { text_input_manager_ = @@ -50,10 +50,14 @@ } void set_update_text_input_state_called_callback( - const TextInputManagerTester::Callback& callback) { + const base::Closure& callback) { update_text_input_state_callback_ = callback; } + void set_on_selection_bounds_changed_callback(const base::Closure& callback) { + on_selection_bounds_changed_callback_ = callback; + } + const RenderWidgetHostView* GetUpdatedView() const { return updated_view_; } bool text_input_state_changed() const { return text_input_state_changed_; } @@ -68,18 +72,27 @@ return; text_input_state_changed_ = did_change_state; updated_view_ = updated_view; - update_text_input_state_callback_.Run(tester_); + if (!update_text_input_state_callback_.is_null()) + update_text_input_state_callback_.Run(); + } + + void OnSelectionBoundsChanged( + TextInputManager* text_input_manager_, + RenderWidgetHostViewBase* updated_view) override { + updated_view_ = updated_view; + if (!on_selection_bounds_changed_callback_.is_null()) + on_selection_bounds_changed_callback_.Run(); } // WebContentsObserver implementation. void WebContentsDestroyed() override { text_input_manager_ = nullptr; } private: - TextInputManagerTester* tester_; TextInputManager* text_input_manager_; RenderWidgetHostViewBase* updated_view_; bool text_input_state_changed_; - TextInputManagerTester::Callback update_text_input_state_callback_; + base::Closure update_text_input_state_callback_; + base::Closure on_selection_bounds_changed_callback_; DISALLOW_COPY_AND_ASSIGN(InternalObserver); }; @@ -222,10 +235,15 @@ TextInputManagerTester::~TextInputManagerTester() {} void TextInputManagerTester::SetUpdateTextInputStateCalledCallback( - const Callback& callback) { + const base::Closure& callback) { observer_->set_update_text_input_state_called_callback(callback); } +void TextInputManagerTester::SetOnSelectionBoundsChangedCallback( + const base::Closure& callback) { + observer_->set_on_selection_bounds_changed_callback(callback); +} + bool TextInputManagerTester::GetTextInputType(ui::TextInputType* type) { DCHECK(observer_->text_input_manager()); const TextInputState* state =
diff --git a/content/public/test/text_input_test_utils.h b/content/public/test/text_input_test_utils.h index 92be4ae..f87e9fe 100644 --- a/content/public/test/text_input_test_utils.h +++ b/content/public/test/text_input_test_utils.h
@@ -42,14 +42,16 @@ // observing the TextInputManager for WebContents. class TextInputManagerTester { public: - using Callback = base::Callback<void(TextInputManagerTester*)>; - TextInputManagerTester(WebContents* web_contents); virtual ~TextInputManagerTester(); // Sets a callback which is invoked when a RWHV calls UpdateTextInputState // on the TextInputManager which is being observed. - void SetUpdateTextInputStateCalledCallback(const Callback& callback); + void SetUpdateTextInputStateCalledCallback(const base::Closure& callback); + + // Sets a callback which is invoked when a RWHV calls SelectionBoundsChanged + // on the TextInputManager which is being observed. + void SetOnSelectionBoundsChangedCallback(const base::Closure& callback); // Returns true if there is a focused <input> and populates |type| with // |TextInputState.type| of the TextInputManager. @@ -63,9 +65,8 @@ // if none exists. const RenderWidgetHostView* GetActiveView(); - // Returns the RenderWidgetHostView which has most recently called - // TextInputManager::UpdateTextInputState on the TextInputManager which is - // being observed. + // Returns the RenderWidgetHostView which has most recently updated any of its + // state (e.g., TextInputState or otherwise). const RenderWidgetHostView* GetUpdatedView(); // Returns true if a call to TextInputManager::UpdateTextInputState has led
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc index 37d3a23..7919e83a 100644 --- a/content/renderer/android/synchronous_compositor_output_surface.cc +++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -16,7 +16,13 @@ #include "cc/output/compositor_frame.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface_client.h" +#include "cc/output/renderer_settings.h" #include "cc/output/software_output_device.h" +#include "cc/output/texture_mailbox_deleter.h" +#include "cc/surfaces/display.h" +#include "cc/surfaces/surface_factory.h" +#include "cc/surfaces/surface_id_allocator.h" +#include "cc/surfaces/surface_manager.h" #include "content/common/android/sync_compositor_messages.h" #include "content/renderer/android/synchronous_compositor_filter.h" #include "content/renderer/android/synchronous_compositor_registry.h" @@ -38,39 +44,42 @@ namespace { const int64_t kFallbackTickTimeoutInMilliseconds = 100; +const uint32_t kCompositorSurfaceNamespace = 1; // Do not limit number of resources, so use an unrealistically high value. const size_t kNumResourcesLimit = 10 * 1000 * 1000; } // namespace -class SynchronousCompositorOutputSurface::SoftwareDevice - : public cc::SoftwareOutputDevice { +class SoftwareDevice : public cc::SoftwareOutputDevice { public: - SoftwareDevice(SynchronousCompositorOutputSurface* surface) - : surface_(surface) { - } + SoftwareDevice(SkCanvas** canvas) : canvas_(canvas) {} + void Resize(const gfx::Size& pixel_size, float scale_factor) override { // Intentional no-op: canvas size is controlled by the embedder. } SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override { - if (!surface_->current_sw_canvas_) { - NOTREACHED() << "BeginPaint with no canvas set"; - return &null_canvas_; - } - LOG_IF(WARNING, surface_->did_swap_) - << "Mutliple calls to BeginPaint per frame"; - return surface_->current_sw_canvas_; + DCHECK(*canvas_) << "BeginPaint with no canvas set"; + return *canvas_; } void EndPaint() override {} private: - SynchronousCompositorOutputSurface* surface_; - SkCanvas null_canvas_; + SkCanvas** canvas_; DISALLOW_COPY_AND_ASSIGN(SoftwareDevice); }; +class SoftwareOutputSurface : public cc::OutputSurface { + public: + SoftwareOutputSurface(std::unique_ptr<SoftwareDevice> software_device) + : cc::OutputSurface(nullptr, nullptr, std::move(software_device)) {} + + // cc::OutputSurface implementation. + uint32_t GetFramebufferCopyTextureFormat() override { return 0; } + void SwapBuffers(cc::CompositorFrame frame) override {} +}; + SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( scoped_refptr<cc::ContextProvider> context_provider, scoped_refptr<cc::ContextProvider> worker_context_provider, @@ -80,19 +89,17 @@ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue) : cc::OutputSurface(std::move(context_provider), std::move(worker_context_provider), - base::MakeUnique<SoftwareDevice>(this)), + nullptr), routing_id_(routing_id), output_surface_id_(output_surface_id), registry_(registry), sender_(RenderThreadImpl::current()->sync_compositor_message_filter()), - registered_(false), - sync_client_(nullptr), - current_sw_canvas_(nullptr), memory_policy_(0u), - did_swap_(false), frame_swap_message_queue_(frame_swap_message_queue), - fallback_tick_pending_(false), - fallback_tick_running_(false) { + surface_manager_(new cc::SurfaceManager), + surface_id_allocator_( + new cc::SurfaceIdAllocator(kCompositorSurfaceNamespace)), + surface_factory_(new cc::SurfaceFactory(surface_manager_.get(), this)) { DCHECK(registry_); DCHECK(sender_); thread_checker_.DetachFromThread(); @@ -100,6 +107,7 @@ capabilities_.delegated_rendering = true; memory_policy_.priority_cutoff_when_visible = gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; + surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get()); } SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {} @@ -135,6 +143,24 @@ base::Unretained(this))); registry_->RegisterOutputSurface(routing_id_, this); registered_ = true; + + surface_manager_->RegisterSurfaceFactoryClient( + surface_id_allocator_->id_namespace(), this); + + cc::RendererSettings software_renderer_settings; + + // The shared_bitmap_manager and gpu_memory_buffer_manager here are null as + // this Display is only used for resourcesless software draws, where no + // resources are included in the frame swapped from the compositor. So there + // is no need for these. + display_.reset(new cc::Display( + surface_manager_.get(), nullptr /* shared_bitmap_manager */, + nullptr /* gpu_memory_buffer_manager */, software_renderer_settings, + surface_id_allocator_->id_namespace(), nullptr /* begin_frame_source */, + base::MakeUnique<SoftwareOutputSurface>( + base::MakeUnique<SoftwareDevice>(¤t_sw_canvas_)), + nullptr /* scheduler */, nullptr /* texture_mailbox_deleter */)); + display_->Initialize(&display_client_); return true; } @@ -144,6 +170,14 @@ registry_->UnregisterOutputSurface(routing_id_, this); } client_->SetTreeActivationCallback(base::Closure()); + if (!delegated_surface_id_.is_null()) + surface_factory_->Destroy(delegated_surface_id_); + surface_manager_->UnregisterSurfaceFactoryClient( + surface_id_allocator_->id_namespace()); + display_ = nullptr; + surface_factory_ = nullptr; + surface_id_allocator_ = nullptr; + surface_manager_ = nullptr; cc::OutputSurface::DetachFromClient(); CancelFallbackTick(); } @@ -156,14 +190,52 @@ // Intentional no-op: surface size is controlled by the embedder. } +static void NoOpDrawCallback(cc::SurfaceDrawStatus s) {} + void SynchronousCompositorOutputSurface::SwapBuffers( cc::CompositorFrame frame) { DCHECK(CalledOnValidThread()); DCHECK(sync_client_); - if (!fallback_tick_running_) { - sync_client_->SwapBuffers(output_surface_id_, std::move(frame)); - DeliverMessages(); + + if (fallback_tick_running_) { + client_->DidSwapBuffers(); + client_->DidSwapBuffersComplete(); + DCHECK(frame.delegated_frame_data->resource_list.empty()); + cc::ReturnedResourceArray return_resources; + ReturnResources(return_resources); + return; } + + cc::CompositorFrame swap_frame; + + if (in_software_draw_) { + // The frame we send to the client is actually just the metadata. Preserve + // the |frame| for the software path below. + swap_frame.metadata = frame.metadata.Clone(); + + if (delegated_surface_id_.is_null()) { + delegated_surface_id_ = surface_id_allocator_->GenerateId(); + surface_factory_->Create(delegated_surface_id_); + } + + display_->SetSurfaceId(delegated_surface_id_, + frame.metadata.device_scale_factor); + + gfx::Size frame_size = + frame.delegated_frame_data->render_pass_list.back()->output_rect.size(); + display_->Resize(frame_size); + + surface_factory_->SubmitCompositorFrame( + delegated_surface_id_, std::move(frame), base::Bind(&NoOpDrawCallback)); + display_->DrawAndSwap(); + } else { + // For hardware draws we send the whole frame to the client so it can draw + // the content in it. + swap_frame = std::move(frame); + } + + sync_client_->SwapBuffers(output_surface_id_, std::move(swap_frame)); + DeliverMessages(); client_->DidSwapBuffers(); did_swap_ = true; } @@ -228,8 +300,7 @@ surface_size_ = surface_size; client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority, transform_for_tile_priority); - const bool software_draw = false; - InvokeComposite(transform, viewport, clip, software_draw); + InvokeComposite(transform, viewport, clip); } void SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { @@ -249,19 +320,18 @@ surface_size_ = gfx::Size(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height()); - const bool software_draw = true; - InvokeComposite(transform, clip, clip, software_draw); + base::AutoReset<bool> set_in_software_draw(&in_software_draw_, true); + InvokeComposite(transform, clip, clip); } void SynchronousCompositorOutputSurface::InvokeComposite( const gfx::Transform& transform, const gfx::Rect& viewport, - const gfx::Rect& clip, - bool software_draw) { + const gfx::Rect& clip) { gfx::Transform adjusted_transform = transform; adjusted_transform.matrix().postTranslate(-viewport.x(), -viewport.y(), 0); did_swap_ = false; - client_->OnDraw(adjusted_transform, viewport, clip, software_draw); + client_->OnDraw(adjusted_transform, viewport, clip, in_software_draw_); if (did_swap_) client_->DidSwapBuffersComplete(); @@ -325,4 +395,17 @@ return thread_checker_.CalledOnValidThread(); } +void SynchronousCompositorOutputSurface::ReturnResources( + const cc::ReturnedResourceArray& resources) { + DCHECK(resources.empty()); + cc::CompositorFrameAck ack; + client_->ReclaimResources(&ack); +} + +void SynchronousCompositorOutputSurface::SetBeginFrameSource( + cc::BeginFrameSource* begin_frame_source) { + // Software output is synchronous and doesn't use a BeginFrameSource. + NOTREACHED(); +} + } // namespace content
diff --git a/content/renderer/android/synchronous_compositor_output_surface.h b/content/renderer/android/synchronous_compositor_output_surface.h index 0972094..b26e18ac 100644 --- a/content/renderer/android/synchronous_compositor_output_surface.h +++ b/content/renderer/android/synchronous_compositor_output_surface.h
@@ -18,12 +18,18 @@ #include "cc/output/compositor_frame.h" #include "cc/output/managed_memory_policy.h" #include "cc/output/output_surface.h" +#include "cc/surfaces/display_client.h" +#include "cc/surfaces/surface_factory_client.h" #include "ipc/ipc_message.h" #include "ui/gfx/transform.h" namespace cc { class ContextProvider; class CompositorFrameMetadata; +class Display; +class SurfaceFactory; +class SurfaceIdAllocator; +class SurfaceManager; } namespace IPC { @@ -57,7 +63,8 @@ // This class can be created only on the main thread, but then becomes pinned // to a fixed thread when BindToClient is called. class SynchronousCompositorOutputSurface - : NON_EXPORTED_BASE(public cc::OutputSurface) { + : NON_EXPORTED_BASE(public cc::OutputSurface), + public cc::SurfaceFactoryClient { public: SynchronousCompositorOutputSurface( scoped_refptr<cc::ContextProvider> context_provider, @@ -92,14 +99,14 @@ const gfx::Transform& transform_for_tile_priority); void DemandDrawSw(SkCanvas* canvas); - private: - class SoftwareDevice; - friend class SoftwareDevice; + // SurfaceFactoryClient implementation. + void ReturnResources(const cc::ReturnedResourceArray& resources) override; + void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override; + private: void InvokeComposite(const gfx::Transform& transform, const gfx::Rect& viewport, - const gfx::Rect& clip, - bool hardware_draw); + const gfx::Rect& clip); bool Send(IPC::Message* message); void DidActivatePendingTree(); void DeliverMessages(); @@ -117,21 +124,39 @@ const uint32_t output_surface_id_; SynchronousCompositorRegistry* const registry_; // Not owned. IPC::Sender* const sender_; // Not owned. - bool registered_; + bool registered_ = false; // Not owned. - SynchronousCompositorOutputSurfaceClient* sync_client_; + SynchronousCompositorOutputSurfaceClient* sync_client_ = nullptr; // Only valid (non-NULL) during a DemandDrawSw() call. - SkCanvas* current_sw_canvas_; + SkCanvas* current_sw_canvas_ = nullptr; cc::ManagedMemoryPolicy memory_policy_; - bool did_swap_; + bool in_software_draw_ = false; + bool did_swap_ = false; scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_; base::CancelableClosure fallback_tick_; - bool fallback_tick_pending_; - bool fallback_tick_running_; + bool fallback_tick_pending_ = false; + bool fallback_tick_running_ = false; + + class StubDisplayClient : public cc::DisplayClient { + void DisplayOutputSurfaceLost() override {} + void DisplaySetMemoryPolicy( + const cc::ManagedMemoryPolicy& policy) override {} + }; + + // TODO(danakj): These don't to be stored in unique_ptrs when OutputSurface + // is owned/destroyed on the compositor thread. + std::unique_ptr<cc::SurfaceManager> surface_manager_; + std::unique_ptr<cc::SurfaceIdAllocator> surface_id_allocator_; + cc::SurfaceId delegated_surface_id_; + // Uses surface_manager_. + std::unique_ptr<cc::SurfaceFactory> surface_factory_; + StubDisplayClient display_client_; + // Uses surface_manager_. + std::unique_ptr<cc::Display> display_; base::ThreadChecker thread_checker_;
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc index 9dcd5904..066f0bb 100644 --- a/content/renderer/devtools/devtools_agent.cc +++ b/content/renderer/devtools/devtools_agent.cc
@@ -13,6 +13,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/threading/non_thread_safe.h" #include "base/trace_event/trace_event.h" #include "content/common/devtools_messages.h" #include "content/common/frame_messages.h" @@ -23,6 +24,7 @@ #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_widget.h" #include "ipc/ipc_channel.h" +#include "third_party/WebKit/public/platform/WebFloatRect.h" #include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDevToolsAgent.h" @@ -43,20 +45,34 @@ const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; const char kPageGetAppManifest[] = "Page.getAppManifest"; - class WebKitClientMessageLoopImpl - : public WebDevToolsAgentClient::WebKitClientMessageLoop { + : public WebDevToolsAgentClient::WebKitClientMessageLoop, + public base::NonThreadSafe { public: - WebKitClientMessageLoopImpl() : message_loop_(base::MessageLoop::current()) {} - ~WebKitClientMessageLoopImpl() override { message_loop_ = NULL; } + WebKitClientMessageLoopImpl() = default; + ~WebKitClientMessageLoopImpl() override { DCHECK(CalledOnValidThread()); } void run() override { - base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_); - base::RunLoop().Run(); + DCHECK(CalledOnValidThread()); + + base::RunLoop* const previous_run_loop = run_loop_; + base::RunLoop run_loop; + run_loop_ = &run_loop; + + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + run_loop.Run(); + + run_loop_ = previous_run_loop; } - void quitNow() override { message_loop_->QuitNow(); } + void quitNow() override { + DCHECK(CalledOnValidThread()); + DCHECK(run_loop_); + + run_loop_->Quit(); + } private: - base::MessageLoop* message_loop_; + base::RunLoop* run_loop_ = nullptr; }; typedef std::map<int, DevToolsAgent*> IdToAgentMap; @@ -263,7 +279,9 @@ } void DevToolsAgent::OnInspectElement(int x, int y) { - GetWebAgent()->inspectElementAt(WebPoint(x, y)); + blink::WebFloatRect point_rect(x, y, 0, 0); + frame_->GetRenderWidget()->convertWindowToViewport(&point_rect); + GetWebAgent()->inspectElementAt(WebPoint(point_rect.x, point_rect.y)); } void DevToolsAgent::OnRequestNewWindowACK(bool success) {
diff --git a/content/renderer/devtools/devtools_agent_filter.cc b/content/renderer/devtools/devtools_agent_filter.cc index 1e015f79..f84b56d 100644 --- a/content/renderer/devtools/devtools_agent_filter.cc +++ b/content/renderer/devtools/devtools_agent_filter.cc
@@ -5,7 +5,6 @@ #include "content/renderer/devtools/devtools_agent_filter.h" #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "content/child/child_process.h" #include "content/common/devtools_messages.h" #include "content/renderer/devtools/devtools_agent.h" @@ -48,10 +47,8 @@ } // namespace DevToolsAgentFilter::DevToolsAgentFilter() - : render_thread_loop_(base::MessageLoop::current()), - io_task_runner_(ChildProcess::current()->io_task_runner()), - current_routing_id_(0) { -} + : io_task_runner_(ChildProcess::current()->io_task_runner()), + current_routing_id_(0) {} bool DevToolsAgentFilter::OnMessageReceived(const IPC::Message& message) { // Dispatch debugger commands directly from IO.
diff --git a/content/renderer/devtools/devtools_agent_filter.h b/content/renderer/devtools/devtools_agent_filter.h index 899bad74..69fcb29e4 100644 --- a/content/renderer/devtools/devtools_agent_filter.h +++ b/content/renderer/devtools/devtools_agent_filter.h
@@ -16,7 +16,6 @@ struct DevToolsMessageData; namespace base { -class MessageLoop; class SingleThreadTaskRunner; } @@ -56,7 +55,6 @@ void AddEmbeddedWorkerRoute(int32_t routing_id); void RemoveEmbeddedWorkerRoute(int32_t routing_id); - base::MessageLoop* render_thread_loop_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; int current_routing_id_;
diff --git a/content/renderer/media/aec_dump_message_filter.cc b/content/renderer/media/aec_dump_message_filter.cc index 01a6d0b..1d6ac4b 100644 --- a/content/renderer/media/aec_dump_message_filter.cc +++ b/content/renderer/media/aec_dump_message_filter.cc
@@ -6,7 +6,6 @@ #include "base/single_thread_task_runner.h" #include "content/common/media/aec_dump_messages.h" -#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc_logging.h" #include "ipc/ipc_logging.h" #include "ipc/ipc_sender.h" @@ -21,13 +20,11 @@ AecDumpMessageFilter::AecDumpMessageFilter( const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, - PeerConnectionDependencyFactory* peerconnection_dependency_factory) + const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) : sender_(NULL), delegate_id_counter_(1), io_task_runner_(io_task_runner), - main_task_runner_(main_task_runner), - peerconnection_dependency_factory_(peerconnection_dependency_factory) { + main_task_runner_(main_task_runner) { DCHECK(!g_filter); g_filter = this; } @@ -91,9 +88,7 @@ bool handled = true; IPC_BEGIN_MESSAGE_MAP(AecDumpMessageFilter, message) IPC_MESSAGE_HANDLER(AecDumpMsg_EnableAecDump, OnEnableAecDump) - IPC_MESSAGE_HANDLER(WebRTCEventLogMsg_EnableEventLog, OnEnableEventLog) IPC_MESSAGE_HANDLER(AecDumpMsg_DisableAecDump, OnDisableAecDump) - IPC_MESSAGE_HANDLER(WebRTCEventLogMsg_DisableEventLog, OnDisableEventLog) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -129,27 +124,12 @@ file_handle)); } -void AecDumpMessageFilter::OnEnableEventLog( - int id, - IPC::PlatformFileForTransit file_handle) { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - main_task_runner_->PostTask( - FROM_HERE, base::Bind(&AecDumpMessageFilter::DoEnableEventLog, this, id, - file_handle)); -} - void AecDumpMessageFilter::OnDisableAecDump() { DCHECK(io_task_runner_->BelongsToCurrentThread()); main_task_runner_->PostTask( FROM_HERE, base::Bind(&AecDumpMessageFilter::DoDisableAecDump, this)); } -void AecDumpMessageFilter::OnDisableEventLog() { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - main_task_runner_->PostTask( - FROM_HERE, base::Bind(&AecDumpMessageFilter::DoDisableEventLog, this)); -} - void AecDumpMessageFilter::DoEnableAecDump( int id, IPC::PlatformFileForTransit file_handle) { @@ -165,14 +145,6 @@ } } -void AecDumpMessageFilter::DoEnableEventLog( - int id, - IPC::PlatformFileForTransit file_handle) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - peerconnection_dependency_factory_->StartRtcEventLog( - IPC::PlatformFileForTransitToPlatformFile(file_handle)); -} - void AecDumpMessageFilter::DoDisableAecDump() { DCHECK(main_task_runner_->BelongsToCurrentThread()); for (DelegateMap::iterator it = delegates_.begin(); @@ -181,11 +153,6 @@ } } -void AecDumpMessageFilter::DoDisableEventLog() { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - peerconnection_dependency_factory_->StopRtcEventLog(); -} - void AecDumpMessageFilter::DoChannelClosingOnDelegates() { DCHECK(main_task_runner_->BelongsToCurrentThread()); for (DelegateMap::iterator it = delegates_.begin();
diff --git a/content/renderer/media/aec_dump_message_filter.h b/content/renderer/media/aec_dump_message_filter.h index a211a8ae..f0bccc6b 100644 --- a/content/renderer/media/aec_dump_message_filter.h +++ b/content/renderer/media/aec_dump_message_filter.h
@@ -33,8 +33,7 @@ AecDumpMessageFilter( const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, - PeerConnectionDependencyFactory* peerconnection_dependency_factory); + const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner); // Getter for the one AecDumpMessageFilter object. static scoped_refptr<AecDumpMessageFilter> Get(); @@ -73,15 +72,11 @@ // Accessed on |io_task_runner_|. void OnEnableAecDump(int id, IPC::PlatformFileForTransit file_handle); - void OnEnableEventLog(int id, IPC::PlatformFileForTransit file_handle); void OnDisableAecDump(); - void OnDisableEventLog(); // Accessed on |main_task_runner_|. void DoEnableAecDump(int id, IPC::PlatformFileForTransit file_handle); - void DoEnableEventLog(int id, IPC::PlatformFileForTransit file_handle); void DoDisableAecDump(); - void DoDisableEventLog(); void DoChannelClosingOnDelegates(); int GetIdForDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate); @@ -106,9 +101,6 @@ // The singleton instance for this filter. static AecDumpMessageFilter* g_filter; - // This pointer is used for calls to enable/disable the RTC event log. - PeerConnectionDependencyFactory* const peerconnection_dependency_factory_; - DISALLOW_COPY_AND_ASSIGN(AecDumpMessageFilter); };
diff --git a/content/renderer/media/android/renderer_media_session_manager.cc b/content/renderer/media/android/renderer_media_session_manager.cc index b5331c7..da956ece 100644 --- a/content/renderer/media/android/renderer_media_session_manager.cc +++ b/content/renderer/media/android/renderer_media_session_manager.cc
@@ -5,6 +5,7 @@ #include "content/renderer/media/android/renderer_media_session_manager.h" #include "base/logging.h" +#include "content/common/media/media_metadata_sanitizer.h" #include "content/common/media/media_session_messages_android.h" #include "content/public/common/media_metadata.h" #include "content/public/renderer/render_thread.h" @@ -65,18 +66,13 @@ void RendererMediaSessionManager::SetMetadata( int session_id, const MediaMetadata& metadata) { - // Apply some sanity checks on the MediaMetadata before sending over IPC. - MediaMetadata ipc_metadata; - ipc_metadata.title = - metadata.title.substr(0, MediaMetadata::kMaxIPCStringLength); - ipc_metadata.artist = - metadata.artist.substr(0, MediaMetadata::kMaxIPCStringLength); - ipc_metadata.album = - metadata.album.substr(0, MediaMetadata::kMaxIPCStringLength); - Send(new MediaSessionHostMsg_SetMetadata(routing_id(), - session_id, - ipc_metadata)); + // TODO(zqzhang): print a console warning when metadata is dirty. See + // https://crbug.com/625244. + Send(new MediaSessionHostMsg_SetMetadata( + routing_id(), session_id, + MediaMetadataSanitizer::CheckSanity(metadata) ? + metadata : MediaMetadataSanitizer::Sanitize(metadata))); } void RendererMediaSessionManager::OnDidActivate(int request_id, bool success) {
diff --git a/content/renderer/media/android/webmediasession_android.cc b/content/renderer/media/android/webmediasession_android.cc index c1a936d..3601d7f4 100644 --- a/content/renderer/media/android/webmediasession_android.cc +++ b/content/renderer/media/android/webmediasession_android.cc
@@ -10,6 +10,8 @@ #include "base/memory/ptr_util.h" #include "content/public/common/media_metadata.h" #include "content/renderer/media/android/renderer_media_session_manager.h" +#include "third_party/WebKit/public/platform/WebIconSizesParser.h" +#include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/modules/mediasession/WebMediaMetadata.h" namespace content { @@ -42,6 +44,17 @@ metadata.title = web_metadata->title; metadata.artist = web_metadata->artist; metadata.album = web_metadata->album; + for (const auto& web_artwork : web_metadata->artwork) { + MediaMetadata::Artwork artwork; + artwork.src = GURL(base::string16(web_artwork.src)); + artwork.type = web_artwork.type; + blink::WebVector<blink::WebSize> web_sizes = + blink::WebIconSizesParser::parseIconSizes(web_artwork.sizes); + artwork.sizes.insert(artwork.sizes.end(), + web_sizes.begin(), + web_sizes.end()); + metadata.artwork.push_back(artwork); + } } session_manager_->SetMetadata(media_session_id_, metadata);
diff --git a/content/renderer/media/gpu/rtc_video_decoder.cc b/content/renderer/media/gpu/rtc_video_decoder.cc index 1729882..78528311 100644 --- a/content/renderer/media/gpu/rtc_video_decoder.cc +++ b/content/renderer/media/gpu/rtc_video_decoder.cc
@@ -35,7 +35,14 @@ const int32_t RTCVideoDecoder::ID_LAST = 0x3FFFFFFF; const int32_t RTCVideoDecoder::ID_HALF = 0x20000000; const int32_t RTCVideoDecoder::ID_INVALID = -1; + +// Android vp8, vp9 decoders are quite finicky and often out of date, so give +// them much less leeway on errors than other platforms. +#if defined(OS_ANDROID) +const uint32_t kNumVDAErrorsBeforeSWFallback = 5; +#else const uint32_t kNumVDAErrorsBeforeSWFallback = 50; +#endif // Maximum number of concurrent VDA::Decode() operations RVD will maintain. // Higher values allow better pipelining in the GPU, but also require more
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.cc b/content/renderer/media/gpu/rtc_video_encoder_factory.cc index 9295464..6734d45 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_factory.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_factory.cc
@@ -33,13 +33,18 @@ webrtc::kVideoCodecVP8, "VP8", width, height, fps)); } else if (profile.profile >= media::H264PROFILE_MIN && profile.profile <= media::H264PROFILE_MAX) { - bool webrtc_h264_enabled = false; -#if BUILDFLAG(RTC_USE_H264) && defined(OS_MACOSX) - webrtc_h264_enabled = + // Enable H264 HW encode for WebRTC when SW fallback is available, which is + // checked by kWebRtcH264WithOpenH264FFmpeg flag. This check should be + // removed when SW implementation is fully enabled. + // kEnableWebRtcHWH264Encoding flag is only enabled for extensions, and + // can be used without SW fallback. + bool webrtc_h264_sw_enabled = false; +#if BUILDFLAG(RTC_USE_H264) + webrtc_h264_sw_enabled = base::FeatureList::IsEnabled(kWebRtcH264WithOpenH264FFmpeg); -#endif // BUILDFLAG(RTC_USE_H264) && defined(OS_MACOSX) +#endif // BUILDFLAG(RTC_USE_H264) if (cmd_line->HasSwitch(switches::kEnableWebRtcHWH264Encoding) || - webrtc_h264_enabled) { + webrtc_h264_sw_enabled) { codecs->push_back(cricket::WebRtcVideoEncoderFactory::VideoCodec( webrtc::kVideoCodecH264, "H264", width, height, fps)); }
diff --git a/content/renderer/media/media_stream_audio_processor_unittest.cc b/content/renderer/media/media_stream_audio_processor_unittest.cc index 0b5e138e..2b96d745 100644 --- a/content/renderer/media/media_stream_audio_processor_unittest.cc +++ b/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -483,7 +483,7 @@ base::MessageLoopForUI message_loop; scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_( new AecDumpMessageFilter(message_loop.task_runner(), - message_loop.task_runner(), nullptr)); + message_loop.task_runner())); MockConstraintFactory constraint_factory; scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
diff --git a/content/renderer/media/mock_peer_connection_impl.h b/content/renderer/media/mock_peer_connection_impl.h index da60d59..c6a1d19 100644 --- a/content/renderer/media/mock_peer_connection_impl.h +++ b/content/renderer/media/mock_peer_connection_impl.h
@@ -62,6 +62,13 @@ return PeerConnectionInterface::kIceGatheringNew; } + bool StartRtcEventLog(rtc::PlatformFile file, + int64_t max_size_bytes) override { + NOTIMPLEMENTED(); + return false; + } + void StopRtcEventLog() override { NOTIMPLEMENTED(); } + MOCK_METHOD0(Close, void()); const webrtc::SessionDescriptionInterface* local_description() const override;
diff --git a/content/renderer/media/peer_connection_tracker.cc b/content/renderer/media/peer_connection_tracker.cc index efeb029e..c76674b 100644 --- a/content/renderer/media/peer_connection_tracker.cc +++ b/content/renderer/media/peer_connection_tracker.cc
@@ -343,6 +343,8 @@ IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message) IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats) IPC_MESSAGE_HANDLER(PeerConnectionTracker_OnSuspend, OnSuspend) + IPC_MESSAGE_HANDLER(PeerConnectionTracker_StartEventLog, OnStartEventLog) + IPC_MESSAGE_HANDLER(PeerConnectionTracker_StopEventLog, OnStopEventLog) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -380,6 +382,36 @@ } } +void PeerConnectionTracker::OnStartEventLog(int peer_connection_id, + IPC::PlatformFileForTransit file) { + DCHECK(main_thread_.CalledOnValidThread()); + for (auto& it : peer_connection_id_map_) { + if (it.second == peer_connection_id) { +#if defined(OS_ANDROID) + // A lower maximum filesize is used on Android because storage space is + // more scarce on mobile. This upper limit applies to each peerconnection + // individually, so the total amount of used storage can be a multiple of + // this. + const int64_t kMaxFilesizeBytes = 10000000; +#else + const int64_t kMaxFilesizeBytes = 60000000; +#endif + it.first->StartEventLog(file, kMaxFilesizeBytes); + return; + } + } +} + +void PeerConnectionTracker::OnStopEventLog(int peer_connection_id) { + DCHECK(main_thread_.CalledOnValidThread()); + for (auto& it : peer_connection_id_map_) { + if (it.second == peer_connection_id) { + it.first->StopEventLog(); + return; + } + } +} + void PeerConnectionTracker::RegisterPeerConnection( RTCPeerConnectionHandler* pc_handler, const webrtc::PeerConnectionInterface::RTCConfiguration& config,
diff --git a/content/renderer/media/peer_connection_tracker.h b/content/renderer/media/peer_connection_tracker.h index 679ca45..6cc19999 100644 --- a/content/renderer/media/peer_connection_tracker.h +++ b/content/renderer/media/peer_connection_tracker.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "content/public/renderer/render_thread_observer.h" +#include "ipc/ipc_platform_file.h" #include "third_party/WebKit/public/platform/WebMediaStream.h" #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h" #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h" @@ -186,6 +187,13 @@ // Called when the browser process reports a suspend event from the OS. void OnSuspend(); + // IPC Message handler for starting event log. + void OnStartEventLog(int peer_connection_id, + IPC::PlatformFileForTransit file); + + // IPC Message handler for stopping event log. + void OnStopEventLog(int peer_connection_id); + // Called to deliver an update to the host (PeerConnectionTrackerHost). // |local_id| - The id of the registered RTCPeerConnectionHandler. // Using an id instead of the hander pointer is done on purpose
diff --git a/content/renderer/media/rtc_peer_connection_handler.cc b/content/renderer/media/rtc_peer_connection_handler.cc index 361948c..fcf1b82 100644 --- a/content/renderer/media/rtc_peer_connection_handler.cc +++ b/content/renderer/media/rtc_peer_connection_handler.cc
@@ -1437,6 +1437,19 @@ client_->closePeerConnection(); } +void RTCPeerConnectionHandler::StartEventLog(IPC::PlatformFileForTransit file, + int64_t max_file_size_bytes) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(file != IPC::InvalidPlatformFileForTransit()); + native_peer_connection_->StartRtcEventLog( + IPC::PlatformFileForTransitToPlatformFile(file), max_file_size_bytes); +} + +void RTCPeerConnectionHandler::StopEventLog() { + DCHECK(thread_checker_.CalledOnValidThread()); + native_peer_connection_->StopRtcEventLog(); +} + blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel( const blink::WebString& label, const blink::WebRTCDataChannelInit& init) { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/content/renderer/media/rtc_peer_connection_handler.h b/content/renderer/media/rtc_peer_connection_handler.h index 04941df..93ad683 100644 --- a/content/renderer/media/rtc_peer_connection_handler.h +++ b/content/renderer/media/rtc_peer_connection_handler.h
@@ -20,6 +20,7 @@ #include "base/threading/thread_checker.h" #include "content/common/content_export.h" #include "content/renderer/media/webrtc/media_stream_track_metrics.h" +#include "ipc/ipc_platform_file.h" #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandler.h" #include "third_party/WebKit/public/platform/WebRTCStatsRequest.h" @@ -168,6 +169,12 @@ // Tells the |client_| to close RTCPeerConnection. void CloseClientPeerConnection(); + // Start recording an event log. + void StartEventLog(IPC::PlatformFileForTransit file, + int64_t max_file_size_bytes); + // Stop recording an event log. + void StopEventLog(); + protected: webrtc::PeerConnectionInterface* native_peer_connection() { return native_peer_connection_.get();
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc index b03fedd..d437247 100644 --- a/content/renderer/media/webmediaplayer_ms.cc +++ b/content/renderer/media/webmediaplayer_ms.cc
@@ -152,8 +152,8 @@ } if (video_frame_provider_) video_frame_provider_->Start(); - if (audio_renderer_) { - // Do not wait for first video frame to start playing + if (audio_renderer_ && !video_frame_provider_) { + // This is audio-only mode. SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); } @@ -488,10 +488,8 @@ if (!received_first_frame_) { received_first_frame_ = true; - if (getReadyState() < WebMediaPlayer::ReadyStateHaveEnoughData) { - SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); - SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); - } + SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); + SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); if (video_frame_provider_.get()) { video_weblayer_.reset(new cc_blink::WebLayerImpl(
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc index 631ea1c4..4e9da8b9 100644 --- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc +++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -453,15 +453,6 @@ return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp, nullptr); } -bool PeerConnectionDependencyFactory::StartRtcEventLog( - base::PlatformFile file) { - return GetPcFactory()->StartRtcEventLog(file); -} - -void PeerConnectionDependencyFactory::StopRtcEventLog() { - GetPcFactory()->StopRtcEventLog(); -} - WebRtcAudioDeviceImpl* PeerConnectionDependencyFactory::GetWebRtcAudioDevice() { DCHECK(CalledOnValidThread());
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/content/renderer/media/webrtc/peer_connection_dependency_factory.h index fc69d22..0486380 100644 --- a/content/renderer/media/webrtc/peer_connection_dependency_factory.h +++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -108,12 +108,6 @@ int sdp_mline_index, const std::string& sdp); - // Starts recording an RTC event log. - virtual bool StartRtcEventLog(base::PlatformFile file); - - // Starts recording an RTC event log. - virtual void StopRtcEventLog(); - WebRtcAudioDeviceImpl* GetWebRtcAudioDevice(); void EnsureInitialized();
diff --git a/content/renderer/media/webrtc_local_audio_source_provider.cc b/content/renderer/media/webrtc_local_audio_source_provider.cc index af46501..72166ddb 100644 --- a/content/renderer/media/webrtc_local_audio_source_provider.cc +++ b/content/renderer/media/webrtc_local_audio_source_provider.cc
@@ -5,11 +5,13 @@ #include "content/renderer/media/webrtc_local_audio_source_provider.h" #include "base/logging.h" -#include "content/renderer/render_thread_impl.h" +#include "content/public/renderer/render_frame.h" +#include "content/renderer/media/audio_device_factory.h" #include "media/base/audio_fifo.h" -#include "media/base/audio_hardware_config.h" #include "media/base/audio_parameters.h" #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" using blink::WebVector; @@ -28,17 +30,21 @@ track_(track), track_stopped_(false) { // Get the native audio output hardware sample-rate for the sink. - // We need to check if RenderThreadImpl is valid here since the unittests + // We need to check if there is a valid frame since the unittests // do not have one and they will inject their own |sink_params_| for testing. - if (RenderThreadImpl::current()) { - media::AudioHardwareConfig* hardware_config = - RenderThreadImpl::current()->GetAudioHardwareConfig(); - int sample_rate = hardware_config->GetOutputSampleRate(); + blink::WebLocalFrame* const web_frame = + blink::WebLocalFrame::frameForCurrentContext(); + RenderFrame* const render_frame = RenderFrame::FromWebFrame(web_frame); + if (render_frame) { + int sample_rate = AudioDeviceFactory::GetOutputDeviceInfo( + render_frame->GetRoutingID(), 0, std::string(), + web_frame->getSecurityOrigin()) + .output_params() + .sample_rate(); sink_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, sample_rate, 16, kWebAudioRenderBufferSize); } - // Connect the source provider to the track as a sink. MediaStreamAudioSink::AddToAudioTrack(this, track_); }
diff --git a/content/renderer/p2p/ipc_socket_factory.cc b/content/renderer/p2p/ipc_socket_factory.cc index e0d93d34..4563aa3 100644 --- a/content/renderer/p2p/ipc_socket_factory.cc +++ b/content/renderer/p2p/ipc_socket_factory.cc
@@ -10,13 +10,14 @@ #include <list> #include "base/compiler_specific.h" +#include "base/logging.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/threading/non_thread_safe.h" +#include "base/threading/thread_checker.h" #include "base/trace_event/trace_event.h" #include "content/renderer/media/webrtc_logging.h" #include "content/renderer/p2p/host_address_request.h" @@ -155,8 +156,8 @@ P2PSocketType type_; - // Message loop on which this socket was created and being used. - base::MessageLoop* message_loop_; + // Used to verify that a method runs on the thread that created this socket. + base::ThreadChecker thread_checker_; // Corresponding P2P socket client. scoped_refptr<P2PSocketClient> client_; @@ -232,7 +233,6 @@ IpcPacketSocket::IpcPacketSocket() : type_(P2P_SOCKET_UDP), - message_loop_(base::MessageLoop::current()), state_(IS_UNINITIALIZED), send_bytes_available_(kMaximumInFlightBytes), writable_signal_expected_(false), @@ -293,7 +293,7 @@ P2PSocketClientImpl* client, const rtc::SocketAddress& local_address, const rtc::SocketAddress& remote_address) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, IS_UNINITIALIZED); type_ = type; @@ -341,7 +341,7 @@ P2PSocketClient* client, const rtc::SocketAddress& local_address, const rtc::SocketAddress& remote_address) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, IS_UNINITIALIZED); client_ = client; @@ -354,25 +354,25 @@ // rtc::AsyncPacketSocket interface. rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); return local_address_; } rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); return remote_address_; } int IpcPacketSocket::Send(const void *data, size_t data_size, const rtc::PacketOptions& options) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); return SendTo(data, data_size, remote_address_, options); } int IpcPacketSocket::SendTo(const void *data, size_t data_size, const rtc::SocketAddress& address, const rtc::PacketOptions& options) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); switch (state_) { case IS_UNINITIALIZED: @@ -453,7 +453,7 @@ } int IpcPacketSocket::Close() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); client_->Close(); state_ = IS_CLOSED; @@ -462,7 +462,7 @@ } rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); switch (state_) { case IS_UNINITIALIZED: @@ -500,7 +500,7 @@ } int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX; if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) { @@ -518,7 +518,7 @@ } int IpcPacketSocket::DoSetOption(P2PSocketOption option, int value) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(state_, IS_OPEN); client_->SetOption(option, value); @@ -526,18 +526,18 @@ } int IpcPacketSocket::GetError() const { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); return error_; } void IpcPacketSocket::SetError(int error) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); error_ = error; } void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address, const net::IPEndPoint& remote_address) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); if (!jingle_glue::IPEndPointToSocketAddress(local_address, &local_address_)) { // Always expect correct IPv4 address to be allocated. @@ -581,7 +581,7 @@ void IpcPacketSocket::OnIncomingTcpConnection( const net::IPEndPoint& address, P2PSocketClient* client) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); @@ -595,7 +595,7 @@ } void IpcPacketSocket::OnSendComplete(const P2PSendPacketMetrics& send_metrics) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); CHECK(!in_flight_packet_records_.empty()); @@ -632,7 +632,7 @@ } void IpcPacketSocket::OnError() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED); state_ = IS_ERROR; error_ = ECONNABORTED; @@ -644,7 +644,7 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, const std::vector<char>& data, const base::TimeTicks& timestamp) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_); + DCHECK(thread_checker_.CalledOnValidThread()); rtc::SocketAddress address_lj;
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index 5e0b5f3..927d10b 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -18,6 +18,7 @@ #include "content/renderer/pepper/plugin_module.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" +#include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/ipc/client/command_buffer_proxy_impl.h" #include "gpu/ipc/client/gpu_channel_host.h" @@ -44,7 +45,18 @@ bound_to_instance_(false), commit_pending_(false), has_alpha_(false), - weak_ptr_factory_(this) {} + use_image_chromium_(false), + weak_ptr_factory_(this) { +#if defined(OS_MACOSX) + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + bool use_image_chromium = + !command_line->HasSwitch(switches::kDisablePepper3DImageChromium); + use_image_chromium_ = use_image_chromium; + + // TODO(erikchen): Remove this line to enable the feature. + use_image_chromium_ = false; +#endif +} PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() { // Unset the client before the command_buffer_ is destroyed, similar to how @@ -158,7 +170,9 @@ return command_buffer_.get(); } -int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token) { +int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) { DCHECK(command_buffer_); if (taken_front_buffer_.IsZero()) { DLOG(ERROR) << "TakeFrontBuffer should be called before DoSwapBuffers"; @@ -173,8 +187,16 @@ // // Don't need to check for NULL from GetPluginInstance since when we're // bound, we know our instance is valid. - cc::TextureMailbox texture_mailbox(taken_front_buffer_, sync_token, - GL_TEXTURE_2D); + if (width < 0 || height < 0) { + width = original_width_; + height = original_height_; + } + bool is_overlay_candidate = use_image_chromium_; + GLenum target = + is_overlay_candidate ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D; + cc::TextureMailbox texture_mailbox(taken_front_buffer_, sync_token, target, + gfx::Size(width, height), + is_overlay_candidate, false); taken_front_buffer_.SetZero(); HostGlobals::Get() ->GetInstance(pp_instance()) @@ -260,6 +282,7 @@ } if (!attrib_helper.Parse(attribs)) return false; + attrib_helper.should_use_native_gmb_for_backbuffer = use_image_chromium_; gpu::CommandBufferProxyImpl* share_buffer = NULL; if (share_context) { @@ -272,6 +295,8 @@ std::move(channel), gpu::kNullSurfaceHandle, share_buffer, gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::NORMAL, attrib_helper, GURL::EmptyGURL(), base::ThreadTaskRunnerHandle::Get()); + original_width_ = attrib_helper.offscreen_framebuffer_size.width(); + original_height_ = attrib_helper.offscreen_framebuffer_size.height(); if (!command_buffer_) return false;
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.h b/content/renderer/pepper/ppb_graphics_3d_impl.h index abafd2c..5d926ec1 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.h +++ b/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -70,7 +70,9 @@ // ppapi::PPB_Graphics3D_Shared overrides. gpu::CommandBuffer* GetCommandBuffer() override; gpu::GpuControl* GetGpuControl() override; - int32_t DoSwapBuffers(const gpu::SyncToken& sync_token) override; + int32_t DoSwapBuffers(const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) override; private: explicit PPB_Graphics3D_Impl(PP_Instance instance); @@ -110,7 +112,14 @@ bool lost_context_ = false; #endif + // The width and height of the command buffer back buffer are first sized from + // this process, but then resized by the pepper process. Cache the original + // size. + int32_t original_width_ = 0; + int32_t original_height_ = 0; + bool has_alpha_; + bool use_image_chromium_; std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_; base::WeakPtrFactory<PPB_Graphics3D_Impl> weak_ptr_factory_;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 304c589e..0845883 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -692,8 +692,7 @@ new PeerConnectionDependencyFactory(p2p_socket_dispatcher_.get())); aec_dump_message_filter_ = new AecDumpMessageFilter( - GetIOMessageLoopProxy(), message_loop()->task_runner(), - peer_connection_factory_.get()); + GetIOMessageLoopProxy(), message_loop()->task_runner()); AddFilter(aec_dump_message_filter_.get()); @@ -2057,7 +2056,7 @@ scoped_refptr<base::SingleThreadTaskRunner> RenderThreadImpl::GetFileThreadMessageLoopProxy() { - DCHECK(message_loop() == base::MessageLoop::current()); + DCHECK(message_loop()->task_runner()->BelongsToCurrentThread()); if (!file_thread_) { file_thread_.reset(new base::Thread("Renderer::FILE")); file_thread_->Start(); @@ -2067,7 +2066,7 @@ scoped_refptr<base::SingleThreadTaskRunner> RenderThreadImpl::GetMediaThreadTaskRunner() { - DCHECK(message_loop() == base::MessageLoop::current()); + DCHECK(message_loop()->task_runner()->BelongsToCurrentThread()); if (!media_thread_) { media_thread_.reset(new base::Thread("Media")); media_thread_->Start();
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 57747020..91080b1 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -1900,7 +1900,6 @@ #endif TEST_F(RendererErrorPageTest, MAYBE_HttpStatusCodeErrorWithEmptyBody) { blink::WebURLResponse response; - response.initialize(); response.setHTTPStatusCode(503); WebLocalFrame* web_frame = GetMainFrame();
diff --git a/content/shell/browser/shell_devtools_manager_delegate.cc b/content/shell/browser/shell_devtools_manager_delegate.cc index c360d97..9361e9a5 100644 --- a/content/shell/browser/shell_devtools_manager_delegate.cc +++ b/content/shell/browser/shell_devtools_manager_delegate.cc
@@ -229,8 +229,11 @@ base::DictionaryValue* ShellDevToolsManagerDelegate::HandleCommand( DevToolsAgentHost* agent_host, - base::DictionaryValue* command) { - return NULL; + base::DictionaryValue* command_dict) { + std::unique_ptr<base::DictionaryValue> result = + devtools_discovery::DevToolsDiscoveryManager::GetInstance() + ->HandleNewTargetCommand(command_dict); + return result.release(); // Caller takes ownership. } } // namespace content
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc index 327d40d..d40068a 100644 --- a/content/shell/renderer/layout_test/blink_test_runner.cc +++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -64,6 +64,7 @@ #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/platform/WebRect.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebTaskRunner.h" @@ -982,8 +983,9 @@ Reset(true /* for_new_test */); // Navigating to about:blank will make sure that no new loads are initiated // by the renderer. - render_view()->GetWebView()->mainFrame()->loadRequest( - WebURLRequest(GURL(url::kAboutBlankURL))); + WebURLRequest request = WebURLRequest(GURL(url::kAboutBlankURL)); + request.setRequestorOrigin(blink::WebSecurityOrigin::createUnique()); + render_view()->GetWebView()->mainFrame()->loadRequest(request); Send(new ShellViewHostMsg_ResetDone(routing_id())); }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index d84f743..bab905c 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -928,4 +928,5 @@ ":test_support", "//content/shell:content_shell_lib", ] + dict = "data/fuzzer_dictionaries/renderer_fuzzer.dict" }
diff --git a/content/test/data/fuzzer_dictionaries/renderer_fuzzer.dict b/content/test/data/fuzzer_dictionaries/renderer_fuzzer.dict new file mode 100644 index 0000000..5fd1dc44 --- /dev/null +++ b/content/test/data/fuzzer_dictionaries/renderer_fuzzer.dict
@@ -0,0 +1,2079 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file has been generated with testing/libfuzzer/dictionary_generator.py +# using renderer_fuzzer binary and RFC 1866. +"limited" +"all" +"consider" +"forbidden" +"lack" +"aring" +"GRPGTCNT" +"four" +"prefix" +"consists" +"follow" +"integrity" +"REV=...>" +"whose" +"2.0//EN'" +"2.0//EN\"" +"(for" +"NUMERIC" +"Heading" +"to" +"tail" +"Western" +"TAB" +"TEXT" +"ACTION" +"Oacute" +"presentation" +"(STD" +"COMPACT" +"returned" +"Keyword" +"</BODY></HTML>" +"far" +"activation" +"(URI)," +"splitting" +"cedil" +"handling" +"updates" +"N=Z27>" +"[MIME])" +"2//EN\"" +"<LINK>" +"1//EN\">" +"(IRV)//ESC" +"Reference" +"WIDTH" +"--" +"cause" +"(`</DT>')," +"list" +"present." +"present," +"large" +"contexts" +"TYPE=TEXT" +"TYPE=SUBMIT>" +"small" +"->" +"ASCII" +"heading" +"allowed:" +"[IMEDIA]." +"direction." +"Otilde" +"tag:" +"Number" +"translating" +"second" +"Version" +"allowed." +"query" +"tag." +"implemented" +"even" +"material" +"errors" +"MINIMIZE" +"EMPTY>" +"specification" +"selected" +"contributed" +"nested." +"KBD" +"decoding" +"characters." +"characters," +"item." +"above" +"new" +"method" +"edited" +"full" +"escaping" +"(aka" +"	" +"WWW." +"THORN" +"\"SDAPREF" +"component" +"here" +"According" +"H1)" +"(SDA)" +"General" +"represented" +"100" +"strong" +"placeholder" +"WWW:" +"obtained" +"UNUSED" +"Aring" +"646:1983//CHARSET" +"-(A)>" +"items" +"[RELURL]." +"allows" +"monospaced" +"CONTROLS" +"PUBLIC" +"prior" +"amount" +"Agrave" +"METHOD=POST\"." +"action" +"suitable" +"iuml" +"SEPCHAR" +"</OL>" +"via" +"Group" +"divide" +"family" +"Support" +"REV" +"replace" +"C.," +"visible" +"\"H6\"" +"MULTIPLE>" +"REL" +"Basic" +"support" +"ICADD" +"select" +"Elements" +"CAPACITY" +"takes" +"would" +"distinct" +"beginning" +"used:" +"contains" +"June" +"two" +"ACTION=\"...\">" +"UCNMCHAR" +"9]" +"Block" +"6" +"HTML\")" +"DOCUMENT" +"type" +"HTML\"." +"used." +"more" +"`GET'." +"successful" +"level," +"`MIDDLE'" +"ENTCAP" +"text," +"`TYPE=IMAGE'" +"icirc" +"..." +"known" +"Representation" +"documents." +"Uniform" +"<DIR" +"<input" +"must" +"parse" +"none" +"word" +"SCOPE" +"Strict" +"Text" +"work" +"doctype" +"<STRIKE>" +"paragraph" +"indicating" +"(`</P>')," +"example" +"def" +"history" +"type," +"type." +"\"BLOCKQUOTE\">" +"CHARSET" +"table" +"1//EN\"" +"accept" +"currency" +"</SELECT>" +"interpreted" +"sharp" +"unordered" +"simple" +"absolute" +"LF" +"information" +"end" +"`METHOD=GET'." +"quot" +"provide" +"\"H4\"" +"breaking" +"feature" +"LI" +"how" +"<DT>" +"<OPTION>" +"A" +"HEAD" +"description" +"FORM" +"Ccedil" +"typed" +"number," +"earlier" +"List" +"mapping" +"reflect" +"catalog" +"OTHER" +"horizontal" +"SYNTAX" +"response" +"types" +"a" +" " +"short" +"attempt" +"SUBDOC" +"third" +"sets" +"(HREF)>\"" +"U.S.A." +"documentation" +"MENU" +")" +"maintain" +"Comma" +"sect" +"HTTP-EQUIV" +"map:" +"BASE?" +"order" +"oacute" +"checkbox" +"Imported" +"help" +"<!SGML" +"ograve" +"over" +"vary" +"installed" +"circumflex" +"\"REL" +"through" +"<html>" +"`<BLOCKQUOTE>'," +"its" +"\\-EM" +"before" +"PRE" +"25" +"style" +"March" +"21" +"fit" +"[IMEDIA]" +"28" +"otilde" +"2:" +"writing" +"L.," +"parts" +"font," +"font." +"2," +"hidden" +"might" +"</DL>" +"then" +"them" +"good" +"</UL>" +"combination" +"fragment" +"2]" +"URN" +"URI" +"number" +"break" +"9" +"effects" +"they" +"nested" +"finite" +"grammar" +"\"ISO" +"cell" +"Permission" +"2//EN\">" +"acirc" +"micro" +"token" +"each" +"types." +"<BODY>" +"Content-Type" +"Check" +"referred" +"ordinal" +"<B>" +"schemes" +"Specification" +"reduce" +"numeric" +"szlig" +"<P>" +"CERN</ADDRESS>" +"Handling" +"HTTP/1.0\"," +"combining" +"<H5>" +"TAGLVL" +"Entity" +"Type" +"message" +"COLS=64>" +"is:" +"PILEN" +"network" +"since" +"DL," +"content" +"message." +"(e.g.," +"#REQUIRED" +"7" +"print" +"plusmn" +"H3)," +"EM" +"HTML+" +"University" +"ICADD22//EN\"." +"given" +"standard" +"base" +"\"SDA\"" +"put" +"POST" +"Registration" +"Soft" +"generate" +"scheme." +"Superscript" +"conform" +"definition" +"pairs" +"</ADDRESS>" +"<TT>" +"created" +"September" +"starts" +"(URL)\"," +"Its" +"MIT" +"`HEAD'" +"BASESET" +"signature" +"HIDDEN" +"`ISO-2022-JP'" +"+=" +"user" +"[URL];" +"features" +"render" +"encoding" +"*" +"Please" +"token." +"LCNMSTRT" +"Maps" +"CODE" +"construct" +"another" +"blank" +"SRC" +"NAMING" +"\"" +"service" +"their" +"leading" +"top" +"least" +"ignored." +"too" +"passed" +"scheme" +"listed" +"B" +"option" +"Language" +"instance." +"tokens" +"part" +"selected." +"feature." +"translation" +"DTD" +"information." +"information," +"#FIXED\"" +"begins" +"<!ENTITY" +"Set" +"Consider" +"body." +"double" +"instruction" +"tree" +"zero" +"<HEAD>" +"See" +"determined" +"similar" +"treated" +"minus" +"Exclamation" +"ISMAP>" +"navigate" +"<CITE>" +"-->" +"A.8," +"(<PRE>," +"METHOD=GET" +"null" +"TYPE=...>" +"contents" +"(MULTIPLE)" +"data," +"data." +"providers" +"on," +"TYPE=SUBMIT" +"Uacute" +"-(INPUT|SELECT|TEXTAREA)>" +"-" +"<BASE" +"indexes" +"also" +"recommended" +"internal" +"window." +"They" +"7]" +"brace" +"CHECKED>" +"content," +"play" +"content." +"macr" +"supported." +"quote" +"newline" +"ordm" +"PLAINTEXT?\">" +"most" +"regular" +"letter" +"entry" +"nothing" +"The" +"Charset" +"[MIME]" +"grave" +"(e.g." +"up" +"clear" +"flow" +"Sample" +"PLAINTEXT" +"bracket" +"\"-//IETF//DTD" +"in-line" +"(`</LI>')," +"parenthesis" +"<CODE>" +"If" +"+" +"dot" +"\"MIME" +"Caret" +"THORN," +"BR\">" +"SHUNCHAR" +"syntax" +"Ntilde" +"radio" +"Atilde" +"font" +" " +"DESCSET" +"European" +"access" +"</DIR>" +"layout" +"quoted" +"copyright" +"preformatted" +"implementation" +"menu" +"explain" +"yen" +"Iuml" +"<body>" +"version" +"specify" +"Eacute" +"<PRE" +"METHOD" +"columns" +"resources." +"(LI)+>" +"etc.)" +"notation" +"wide" +"capital" +"preferred" +"Variable" +"Copyright" +"ROWS" +"<IMG>" +"during" +"body," +"bar" +"Attributes" +"fields" +"01234<BR>" +"public" +"J." +"protocols" +"common" +"Ucirc" +"x" +"<OL>" +"Universal" +"DTD\"" +"set" +"mandatory" +"Auml" +"reference" +"(underscore)" +"Internet" +"DTD," +"DTD." +"\"INCLUDE\"" +"Entities" +"depends" +"individual" +"1//EN//HTML\">" +"result" +"\\-BODY" +"2.0" +"TEXTAREA" +"OMITTAG" +"subject" +"<EM>" +"TYPE=PASSWORD" +"iexcl" +"GET" +"Registered" +"tags" +"<IMG" +"request:" +"various" +"atilde" +"consecutive" +"numerous" +"preserve" +"latin" +"terms" +"responses" +"extend" +"missing" +"description." +"modify" +"ISOlat1" +"<NEXTID" +"identical" +"`TYPE=SUBMIT'" +"`METHOD=GET'" +"ALIGN" +"title." +"interface" +"news" +"<MENU" +"[SGML]" +"both" +"ALIGN=...>" +"reverse" +"hyperlink" +"Ugrave" +"N}" +"context" +"Query" +"requests" +"browser" +"whole" +"Compact" +"LISTING\">" +"Egrave" +"(SGML)." +"\"SGML" +"point" +"sign," +"Initial" +"igrave" +"Strict//EN\"" +"active" +"[ISO-10646]" +")," +"TYPE=CHECKBOX" +"`TOP'" +"ETH" +"throughout" +"Method" +"SHORTREF" +"described" +"+(INPUT|SELECT|TEXTAREA)>" +"Position" +"Tags" +"create" +"Processing" +"Oslash" +"three" +"been" +"16]" +"much" +"non-breaking" +"entered" +"empty" +"Quotation" +"digits" +"anchors" +"agent." +"search" +"N" +"understand" +"CR" +"XMP" +"CT" +"-(FORM)" +"has" +"NAME" +"ccedil" +"ROWS=...>" +"1//EN//HTML\"" +"particular," +"while" +"replaced" +"behavior" +"applies" +"voice" +"anchor" +"1//EN." +"City" +"concurrently" +"pound" +"<DD>" +"played" +"Menu" +"is" +"character." +"multi-line" +"it" +"(see" +"HTML//EN\"" +"itself" +"MIME" +"in" +"\\-</EM>" +"mouse" +"use:" +"if" +"containing" +"\"H1|H2|H3|H4|H5|H6\">" +"ISO/IEC" +"baseline" +":" +"make" +"H3." +"\\-TITLE" +"linked" +"[URL].." +"\"P" +"<H1>" +"widely" +"Address" +"modification" +"several" +"[ISO-8859-1]," +"HTML\"" +"used" +"Presentation" +"[ISO-8859-1]." +"HTML," +"HTML." +"hand" +"Item" +"levels" +"uses" +"purpose" +"characters" +"<a" +"along" +"\">" +"nickname" +"NEXTID?\">" +"recent" +"lower" +"Latin" +"database" +"Technology" +"</a>" +"items." +"\"SDASUSP" +"[" +"+(META|LINK)>" +"Names" +"<A" +"y" +"Table" +"the" +"left" +"QUANTITY" +"Status" +"O," +"protocol" +"proposed" +"sentence" +"HTML</TITLE>" +"<UL" +"MAXLENGTH" +"%SDASUFF;" +"quotes" +"Permanent" +"identify" +"(OPTION+)" +"tilde" +"followed" +"alternative" +"yet" +"alignment" +"previous" +"$" +"(CHECKED)" +"regarded" +"BODY," +"character" +"ideal" +"source" +"<P><INPUT" +"input" +"save" +"---------" +"transformation" +"yacute" +"Reset" +"On" +"usable" +"Graphic" +"format" +"quote." +"possible" +"required." +"URI:" +"</HEAD><BODY>" +"30" +"integer" +"bit" +"formal" +"[DEXTER]" +"[IANA]" +"OL" +"TOTALCAP" +"submission" +"laquo" +"signal" +"Encoding" +"specific" +"destination" +"<OPTION" +"prologue" +"security" +"\\-</TITLE>" +"right" +"old" +"methods" +"truncated" +"HR" +"some" +"<!ELEMENT" +"HT" +"Application" +"added" +"3.2" +"Igrave" +"Italic" +"apply" +"unless" +"[ISO-10646]." +"ignore" +"and/or" +"CONCUR" +"for" +"bottom" +"REF" +"[ISO-10646]," +"LISTING\"." +"comments" +"<BR>" +"<P" +"Let" +"Broken" +"integer." +"METHOD=POST" +"8879-1986//ENTITIES" +"be" +"usage:" +"bold" +"example," +"no-break" +"`CHECKED'," +"<A>" +"O" +"\"IGNORE\">" +"\"J&D\"" +"<STRONG>" +"method." +"<HTML>" +"by" +"SIZE" +"Comment" +"[ISO-10646];" +"Square" +"#IMPLIED" +"Communications" +"\"PRE" +"H3" +"Image" +"H1" +"UL," +"(DIR|MENU)" +"H4" +"H5" +"range" +"<MENU>" +"plus" +"ATTSPLEN" +"value." +"(HTML" +"book" +"block" +"Use" +"eth," +"-(META|LINK)>" +"into" +"within" +"parsing" +"rendering" +"appropriate" +"NET" +"reducing" +"file." +"\\-<TITLE>" +"often" +"rows" +"sup1" +"sup2" +"sup3" +"question" +"transform" +"Lists" +"behavior." +"fields:" +"width" +"\"SDARULE" +"CDATA," +"<" +"way" +"Typewriter" +"translate" +"was" +"(i.e." +"PASSWORD" +"teletype" +"head" +"form" +"registered" +"Declaration" +"Most" +"feminine" +"state" +"link" +"UCNMSTRT" +"atom" +"encoded" +"</PRE>" +"Left" +"reset" +"[URI]" +"Office" +"Ograve" +"Attribute" +"inside" +"declarations" +"maximum" +"...," +"META" +"<INPUT>" +"8-bit" +"etc." +"called" +"Numeric" +"(URN)" +"150" +"ordered" +"semicolon" +"computing" +"Introduction" +"Some" +"specified" +"influence" +"NUMBER" +"To" +"single" +"initial" +"METHOD=GET\"" +"element," +"check" +"element." +"defines" +"Euml" +"%" +"Iacute" +"no" +"Fragment" +"TT" +"when" +"A," +"application" +"role" +"SHORTTAG" +"undeclared" +"test" +"NAME=...>" +"[ISO-646]" +"Markup" +"elements" +"AE" +"frac14" +"Double" +"asterisk" +"aacute" +"Definition" +"T." +"generated" +"eacute" +"\"H5\"" +"IMPLICIT" +"structure" +"<!--" +"TITLE" +"\"GET" +"<SAMP>" +"ending" +"document," +"code:" +"frac12" +"`BOTTOM'" +"pilcrow" +"<DL>" +"An" +"NOTE" +"As" +"presenting" +"time" +"Open" +"TAGLEN" +"code," +"scroll" +"others" +"code" +"Title" +"SIMPLE" +"skip" +"global" +"activated" +"results" +"\"H2\"" +"existing" +"documents," +"BLOCKQUOTE" +"Yacute" +"100//CHARSET" +"text;" +"digits," +"ALT" +"compact" +"`GET'" +"Bold" +"TYPE=IMAGE" +"[URL]" +"name:" +"\"HEAD," +"RCDATA" +"Standard" +"languages" +"0" +"does" +"position." +"Icirc" +"masculine" +"Not" +"(code" +"include" +"resources" +"(TITLE)" +"string" +"outside" +"choice" +"P" +"Plus" +"entries" +"VAR" +"Multiple" +"AElig" +"exact" +"`%HH'," +"entire" +"resource." +"Protocol" +"immediately" +"level" +"mark," +"gender" +"button" +"SIZE=...>" +"fewer" +"standards" +"leave" +"item" +"section" +"Select" +"prevent" +"</FORM>" +"SP" +"HTTP" +"3]" +"(OL|UL)" +"M." +"discover" +"sign" +"[ISO-8859-1]" +"CHECKBOX" +"Orange" +"<TEXTAREA>" +"METHODS=\"...\">" +"SELECT" +"MIT/W3C" +"index" +"egrave" +"set," +"appear" +"Form" +"giving" +"ordf" +"J.R." +"EXPLICIT" +"Public" +"current" +"ntilde" +"HTML" +"Link" +"template" +"large." +"RADIO" +"Line" +"<LI>" +"body" +"C," +"<TEXTAREA>)," +"processing" +"submitted" +"degree" +"<BLOCKQUOTE>" +"NCSA" +"generic" +"address" +"ecirc" +"Distribution" +"implicit" +"set." +"box" +"Selection" +"MA" +"parameters" +"DT," +"32" +"31" +"larger" +"36" +"[ISO-646]." +"delimiter" +"resulting" +"User" +"........................................." +"usually" +"however," +"J.," +"navigation" +"CONTENT=\"...\">" +"named" +"RFC1521)" +"useful" +"FEATURES" +"extra" +"URL" +"MAXLENGTH=...>" +"[SGML])." +"</HEAD>" +"When" +"\",<P>,\"" +"marked" +"\"&#RE;\"" +"boolean" +"names" +"form's" +"Input" +"\"B\"" +"GENERAL" +"<DFN>" +"are" +"use" +"from" +"working" +"&" +"positive" +"value," +"next" +"few" +"Base" +"attribute" +"encode" +"scope" +"associated" +"selects" +"value:" +"%SDAPREF;" +"October" +"N=...>" +"src" +"These" +"appending" +"name," +"Required" +"name)" +"CONTENT" +"uuml" +"fixed" +"`-//IETF//DTD" +"8" +"rendered" +"NEXTID" +"Expression" +"behalf" +"Constraints" +"Strong" +"HTML//EN\">" +"indicates" +"this" +"Hyphen" +"Period" +"Syntax" +"H2" +"values" +"can" +"December" +"following" +"`%0D%0A'." +"closing" +"Abstract" +"something" +"control" +"reserved" +"e.g." +"do" +"process" +"Media" +"\\-HEAD" +"agent" +"escaped" +"tag" +"specification." +"allowed" +"CHECKED" +"occur" +"UL" +"IMAGE" +"charset" +"1" +"line." +"<UL>." +"pair" +"SELECTED>" +"s," +"Text:" +"ensure" +"</MENU>" +"encoded." +"SDASUFF" +"attributes," +"STD" +"map" +"may" +"`TEXT'," +"Request" +"collection" +"11]" +"produce" +"such" +"data" +"compatibility" +"ROWS=6" +"`TYPE=RESET'" +"Y." +"CERN" +"bind" +"parameter" +"Format" +"explicit" +"One" +"rather" +"MIT," +"Paragraph" +"so" +"<OL" +"allow" +"representation" +"<LISTING>" +"instead," +"superscript" +"RESET" +"valid" +"Zip" +"move" +"below." +"entity" +"<KBD>" +"referenced" +"including" +"nbsp" +"differs" +"White" +"`INCLUDE'." +"<meta" +"Body" +"<PLAINTEXT>" +"group" +"auml" +"curly" +"maps" +"Rules" +"<META>" +"H5." +"Ouml" +"<LI>A-H<LI>I-M" +"coordinates" +"<H3>" +"forms" +"platform" +"window" +"choose" +"listing" +"Multiply" +"mail" +"main" +"defining" +"<" +"`<BR>'" +"greater" +"<PRE>" +"views" +"uacute" +"option." +"`<IMG" +"Maximum" +"METHOD=...>" +"Option" +"BASE" +"Extensions" +"half" +"not" +"sorted" +"However," +"superset" +"quote," +"cedilla" +">" +"term" +"SDA" +"name" +"edit" +"plus-or-minus" +"form." +"mode" +"(WWW)" +"<H4>" +"identifier" +"|" +"constraints" +"subset" +"domain" +"square" +"Network" +"8," +"TYPE" +"Generic" +"ISINDEX" +"HTTP-EQUIV=...>" +"COLS" +"related" +"Next" +"fraction" +"agrave" +"Ocirc" +"SDAPREF" +"Parameter" +"ALT=\"...\">" +"special" +"out" +"exclamation" +"Added" +"container" +"space" +"GRPCNT" +"SGML" +"Uuml" +"contained" +"<META" +"<LINK" +"\\-P" +"supports" +"reg" +"DATATAG" +"FUNCTION" +"<H6>," +"mandatory." +"older" +"This" +"derived" +"mapped" +"DTD)." +"<img" +"state." +"RFC" +"ECMA-94" +"N.," +"conflicts" +"Security" +"[IANA]." +"YES" +"<!ATTLIST" +"advance" +"interaction" +"indent" +"REFERENCE" +"language" +"deprecated" +"area" +"times" +"ENCTYPE=\"...\">" +"length" +"place" +"\"VERSION" +"hexadecimal" +"TITLE=\"...\">" +"Eric" +"<LI>M-R<LI>S-Z" +"first" +"\"(TEXT" +"suspend" +"suffix" +"(RFC" +"ignored" +"<I>" +"There" +"1]" +"one" +"CHAR" +"list." +"ISO" +"submit" +"directly" +"representations" +"\"INCLUDE\">" +"ring" +"STRONG" +"open" +"size" +"city" +"little" +"long" +"sheet" +"For" +"Vertical" +"strict" +"unknown" +"<FORM>" +"frac34" +"Commercial" +"system" +"unspecified" +"indicate" +"2" +"IGNORE;" +"\"&#RE;&#RE;\"" +"DTD)" +"DTD\"." +"white" +"Data" +"gives" +"\\-<P>" +"iacute" +"IMG" +"that" +"completed" +"exactly" +"REV=\"X\"." +"released" +"(DT" +"copy" +"\"BLOCKQUOTE" +"than" +"Inc." +"Y," +"11" +"structure." +"13" +"12" +"15" +"14" +"16" +"require" +"see" +"accesses" +"(COMPACT)" +"\\-</P>" +"future" +"BODY\">" +"were" +"1)" +"ENCTYPE" +"1," +"1." +"and" +"Information" +"DL" +"1.1" +"1.2" +"aelig" +"lines" +"DD" +"(ICADD)" +"`ISO-10646-UCS-2'" +"(and" +"<TITLE>HTML" +"Field" +"say" +"HREF" +"have" +"need" +"Mail" +"DT" +"element" +"any" +"'>'" +"<INPUT" +"documents" +"angle" +"NAME=\"...\">" +"URN=\"...\">" +"database." +"SELECTED" +"able" +"mechanism" +"iquest" +"note" +"instance" +"emphasis" +"<ADDRESS>" +"which" +"ICADD:" +"[HTTP]" +"inverted" +"=" +"cases." +"<XMP>," +"begin" +"sure" +"multiple" +"Name" +"`TYPE=CHECKBOX'" +"normal" +"track" +"deprecated." +"who" +"Enter" +"multiply" +"TYPE=RADIO" +"middot" +"<U>" +"icon" +"D." +"SAMP" +"Part" +"#FIXED" +"document:" +"request" +"raquo" +"8879:1986//ENTITIES" +"<BASE>" +"not." +"typically" +"CITE" +"document." +"Web" +"selection" +"YES," +"text" +"supported" +"Character" +"SGML." +"Width" +"SGML," +"spaces" +"Test" +"MULTIPLE" +"WIDTH=...>" +"Document" +"line" +"FORMAL" +"TYPE=RESET>" +"based" +"title" +"(" +"3" +"(#PCDATA)*>" +"should" +"buttons" +"hierarchy" +"only" +"explicitly" +"<!DOCTYPE" +"GMT" +"POST\"" +"get" +"=>" +"space," +"cannot" +"\"TITLE" +"words" +"127" +"128" +"ENTITY" +"scrolling" +"Once" +"processes" +"Right" +"resource" +"W." +"ISMAP" +"<DIR>" +"subtype" +"GLYPH" +"W3" +"contain" +"</BODY>" +"LINK" +"\"SDAFORM" +"At" +"where" +"view" +"available" +"declared" +"<SELECT" +"exists" +"brvbar" +"(HTML)" +"ismap" +"relative" +"Source" +"</TEXTAREA>" +"computer" +"SUBMIT" +"Fraction" +"LISTING" +"PARC," +"(XMP|LISTING)" +"attribute." +"attribute," +"macron" +"`TYPE=PASSWORD'" +"label" +"boundaries" +"written" +"<TEXTAREA" +"enumerated" +"between" +"progress" +"reading" +"across" +"ends" +"ability" +"vertical" +"yuml" +"para" +"REL=\"X\"" +"Directory" +"20" +"Identifier" +"optional" +"Anchor" +"exclusion" +"observable" +"WWW" +"SGMLREF" +"limits" +"many" +"taking" +"RS" +"according" +"HREF=\"...\">" +"present" +"way." +"<UL>" +"attributes" +"expression" +"values," +"Contents" +"otherwise" +"comment" +"among" +"protocol." +"World" +"`ISO-8859-1'" +"BODY" +"DELIM" +"hyphen" +"29" +"Note" +"63" +"64" +"66" +"INPUT" +"constant" +"allocated" +"ISINDEX\">" +"DTD\")." +"RE" +"parsed" +"curren" +"Aacute" +"cent" +"mark" +"defined" +"literal" +"`ISO" +"combined" +"(`</DD>')" +"SRC=\"...\">" +"Horizontal" +"GMT\">" +">" +"name." +"euml" +"optionally" +"controlled" +"\"#PCDATA" +"CHARACTER" +"sequence." +"SDARULE" +"[RELURL]" +"CERN," +"[SQ91]" +"external" +"declaration" +"<XMP>" +"an" +"2." +"those" +"quotation" +"case" +"[SGML])" +"[SGML]." +"indicator," +"these" +"plain" +"means" +"(LI)+" +""" +"value" +"pixel" +"will" +"(UCS)" +"SIZE=\"42\">" +"\"CDATA\"" +"COLS=...>" +"E," +"Level" +"SDAFORM" +"margin" +"6]" +"`<EM/.../';" +"LITLEN" +"ucirc" +"thus" +"(DT)" +"equal" +"Content" +"middle" +"ugrave" +"`METHOD=POST'" +"`TYPE=HIDDEN'" +"ADDRESS)*\">" +"You" +"DIR" +"<DL" +"<TITLE>," +"different" +"Return" +"COMPACT>" +"perhaps" +"media" +"granted" +"`GET'," +"REL=...>" +"same" +"Acirc" +"strings." +"\"IGNORE\"" +"html" +"identifier," +"I," +"identifier." +"Oxford" +"document" +"%SDAFORM;" +"infer" +"</html>" +"status" +"extended" +"Resource" +"I" +"effect" +"\"H3\"" +"frequently" +"validate" +"ACM," +"ID" +"H6\")," +"transaction" +"VALUE=\"...\">" +"center" +"NAMELEN" +"markup" +"identifiers" +"It" +"object" +"Track" +"without" +"extensible" +"In" +"very" +"position" +"model" +"values." +"dimension" +"bodies" +"Specifying" +"<H2>" +"less" +"being" +"percent" +"obtain" +"1521[MIME])" +"Access" +"sources" +"stored" +"BR" +"positions" +"Scope" +"`US-ASCII'" +"4." +"Button:" +"hint" +"<TITLE>" +"except" +"capabilities" +"reasons" +"terminating" +"4" +"Although" +"\\-<EM>" +"coded" +"XMP," +"resolved" +"aspects" +"around" +"read" +"Many" +"CRLF," +"source." +"Recording" +"\"BQ\"" +"makes" +"nor" +"using" +"[ISO" +"left-hand" +"descendant" +"oslash" +"acute" +"IMG\")." +"like" +"text/html" +"header" +"serves" +"server" +"<LISTING>," +"(or" +"either" +"soft" +"page" +"specifies" +"because" +"couldn't" +"sequence" +"Section" +"Since" +"\"HTML" +"U," +"4]" +"respect" +"images" +"International" +"matching" +"glyph" +"nonzero" +"provided" +"entities" +"SPACE" +"Catalog" +"critical" +"`PASSWORD'" +"\"NAMES\">" +"ocirc" +"URI." +"<SELECT>" +"refer" +"locate" +"Term" +"accessing" +"1//ESC" +"`NAMELEN'" +"equivalent" +"Official" +"PRE\")" +"broken" +"(SELECTED)" +"A-Z" +"VALUE" +"\"H1\"" +"\"SDASUFF" +"</BLOCKQUOTE>" +"&" +"includes" +"2.0//EN\">" +"after" +"on" +"about" +"actual" +"H6" +"column" +"of" +"R.," +"recognized" +"side" +"TYPE=RESET" +"addition" +"statement" +"URI," +"mixed" +"Message" +"introduced" +"<H6>" +"or" +"UC" +"software" +"(DTD)" +"document's" +"letters" +"OPTION" +"accent" +"`&'." +"image" +"RANK" +"due" +"HTTP-EQUIV." +"activate" +"references" +"renderer" +"determine" +"<ISINDEX>" +"names." +"your" +"summary." +"per" +"CGI" +"terminated" +"APPINFO" +"[GOLD90]" +"<NEXTID>" +"additional" +"<FORM" +"NO" +"transfer" +"there" +"Unused" +"start" +"describes" +"italic" +"\"-//EC-USA-CDA/ICADD//DTD" +"November" +"context." +"function" +"`TYPE=RADIO'" +"METHOD=\"POST\"" +"N," +"complete" +"N." +"enough" +"<HR>" +"INPUT\")" +"compatible)" +"but" +"SDASUSP" +"Error" +"Small" +"DD)+>" +"(C)" +"with" +"1024" +"made" +"arranged" +"(HTML)." +"embedded" +"default" +"A\")." +"robustness" +"[HTTP]." +"record" +"below" +"ISINDEX?" +"limit" +"CDATA" +"H4." +"`IGNORE'" +"define" +"are:" +"display" +"specified." +"Field:" +"METHODS" +"required" +"ae" +"Space" +"(ISMAP)" +"certain" +"moved" +"NAMES" +"<VAR>" +"general" +"as" +"(#PCDATA)*" +"at" +"file" +"\"HTML\"" +"format." +"TYPE=HIDDEN" +"fill" +"string." +"again" +"beyond" +"(SGML)," +"variety" +"ADDRESS" +"storage" +"detail" +"40" +"NAMECASE" +"details." +"field" +"other" +"5" +"details" +"LCNMCHAR" +"Ecirc" +"you" +"`POST'," +"`POST'." +"10" +"Wide" +"Any" +"kinds" +"separate" +"SMTP" +"symbol" +"numbers." +"Element" +"chance" +"important" +"H." +"URLs" +"<div" +"included" +"T.," +"`INCLUDE'" +"attributes." +"text:" +"DESCRIPTION" +"\"EM" +"resolution" +"thorn" +"ouml" +"persistent" +"rule" +"\"PRE\">" +"directory" +"GRPCAP" +"validation" +"starting" +"strings" +"'" +
diff --git a/content/test/data/media/getusermedia.html b/content/test/data/media/getusermedia.html index a54ba7f..f066a8a 100644 --- a/content/test/data/media/getusermedia.html +++ b/content/test/data/media/getusermedia.html
@@ -461,16 +461,8 @@ var detectorFunction = function() { var width = videoElement.videoWidth; var height = videoElement.videoHeight; - if (width == 0 || height == 0) { - if (++attempt > maxAttempts) { - clearInterval(detectorInterval); - failTest("VideoElement width or height set to 0."); - } - else { - // We have zero size now; give a chance to shape up. - return; - } - } + if (width == 0 || height == 0) + failTest("VideoElement width and height set to 0."); canvas.width = width; canvas.height = height;
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index eb168a64..14ccb117 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -496,8 +496,6 @@ ['mac', 'intel'], bug=483282) # Linux only. - self.Fail('deqp/data/gles3/shaders/functions.html', - ['linux'], bug=483282) self.Fail('conformance2/glsl3/vector-dynamic-indexing.html', ['linux'], bug=483282) self.Fail('deqp/functional/gles3/fbodepthbuffer.html', @@ -506,24 +504,23 @@ # Behavior difference between GL compatibility profile and ES3. self.Fail('conformance2/rendering/draw-buffers.html', ['linux'], bug=617410) - - self.Skip('deqp/data/gles3/shaders/qualification_order.html', - ['linux', 'amd', 'intel'], bug=483282) - self.Fail('deqp/functional/gles3/clipping.html', - ['linux', 'amd', 'intel'], bug=483282) - - self.Flaky('deqp/functional/gles3/texturespecification/' + - 'random_teximage2d_2d.html', - ['linux'], bug=618447) self.Fail('deqp/functional/gles3/texturespecification/' + 'random_teximage2d_cube.html', ['linux'], bug=483282) self.Fail('deqp/functional/gles3/fboinvalidate/whole.html', ['linux'], bug=624506) + self.Fail('deqp/data/gles3/shaders/functions.html', + ['linux', 'amd', 'intel'], bug=483282) + self.Skip('deqp/data/gles3/shaders/qualification_order.html', + ['linux', 'amd', 'intel'], bug=483282) + self.Fail('deqp/functional/gles3/clipping.html', + ['linux', 'amd', 'intel'], bug=483282) + self.Flaky('deqp/functional/gles3/texturespecification/' + + 'random_teximage2d_2d.html', + ['linux', 'amd', 'intel'], bug=618447) + # Linux NVIDIA only. - self.Fail('conformance2/glsl3/array-complex-indexing.html', - ['linux', 'nvidia', 'no_angle'], bug=606498) self.Fail('deqp/functional/gles3/uniformapi/random.html', ['linux', 'nvidia'], bug=621178)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 7de93d4d..53a2f39 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -116,8 +116,6 @@ ['android', ('qualcomm', 'Adreno (TM) 330')], bug=611943) self.Fail('conformance/state/state-uneffected-after-compositing.html', ['android', ('qualcomm', 'Adreno (TM) 330')], bug=611943) - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['android', ('qualcomm', 'Adreno (TM) 330')], bug=611943) # Nexus 5X self.Fail('conformance/extensions/oes-texture-float-with-image-data.html', @@ -299,8 +297,6 @@ ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) self.Fail('conformance/uniforms/uniform-samplers-test.html', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951) # Nexus 6 (Adreno 420) and 6P (Adreno 430) self.Fail('WebglExtension.EXT_sRGB', @@ -514,10 +510,6 @@ self.Fail('conformance/textures/image_bitmap_from_image_bitmap/' + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', ['android', ('qualcomm', 'Adreno (TM) 430')], bug=611945) - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['android', - ('qualcomm', 'Adreno (TM) 420'), - ('qualcomm', 'Adreno (TM) 430')], bug=611945) self.Fail('conformance/glsl/misc/shader-with-_webgl-identifier.vert.html', ['android', ('qualcomm', 'Adreno (TM) 420')], bug=611945) @@ -550,6 +542,7 @@ bug=625363) # Fails on multiple platforms + self.Skip('deqp/data/gles2/shaders/preprocessor.html', bug=625363) # OpenGL / NVIDIA failures self.Fail('conformance/attribs/gl-disabled-vertex-attrib.html', @@ -626,8 +619,6 @@ ['win', 'amd', 'opengl'], bug=1007) # angle bug ID self.Fail('conformance/glsl/misc/struct-nesting-of-variable-names.html', ['win', 'amd', 'opengl'], bug=1007) # angle bug ID - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['win', 'amd', 'opengl'], bug=478572) # Win / OpenGL / Intel failures self.Fail('conformance/glsl/functions/glsl-function-normalize.html', @@ -640,8 +631,6 @@ # Mac failures self.Fail('conformance/glsl/misc/shaders-with-invariance.html', ['mac'], bug=421710) - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['mac'], bug=478572) self.Fail('deqp/data/gles2/shaders/scoping.html', ['mac'], bug=478572) @@ -670,8 +659,6 @@ # AMD self.Flaky('conformance/more/functions/uniformi.html', ['linux', 'amd'], bug=550989) - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['linux', 'amd'], bug=478572) # AMD Radeon 6450 self.Fail('conformance/extensions/angle-instanced-arrays.html', @@ -717,8 +704,6 @@ ['linux', 'intel', 'opengl'], bug=1312) # ANGLE bug id self.Fail('deqp/data/gles2/shaders/linkage.html', ['linux', 'intel'], bug=540543) - self.Fail('deqp/data/gles2/shaders/preprocessor.html', - ['linux', 'intel'], bug=1312) # ANGLE bug id. See also 598910 # The Mesa Intel driver has a scoping bug, see # https://bugs.freedesktop.org/show_bug.cgi?id=95184 self.Fail('deqp/data/gles2/shaders/scoping.html',
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index 29654bbd..b467c0e 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -108,8 +108,6 @@ int error_code) override; void Destroy() override; void SetTooltipText(const base::string16& tooltip_text) override {} - void SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) override {} void CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size,
diff --git a/device/gamepad/gamepad.gyp b/device/gamepad/gamepad.gyp index f82c5048..792843c 100644 --- a/device/gamepad/gamepad.gyp +++ b/device/gamepad/gamepad.gyp
@@ -51,10 +51,23 @@ ['OS=="win"', { 'msvs_disabled_warnings': [4267, ], }], + ['OS=="linux" and use_udev==1', { + 'dependencies': [ + '../udev_linux/udev.gyp:udev_linux', + ] + }], ['OS!="win" and OS!="mac" and OS!="android" and (OS!="linux" or use_udev==0)', { 'sources': [ 'gamepad_platform_data_fetcher.cc', - ] + ], + 'sources!': [ + 'gamepad_platform_data_fetcher_linux.cc', + ], + }], + ['use_udev == 1', { + 'dependencies': [ + '<(DEPTH)/device/udev_linux/udev.gyp:udev_linux', + ], }], ], },
diff --git a/device/gamepad/gamepad_provider.cc b/device/gamepad/gamepad_provider.cc index dded267..c37c38a 100644 --- a/device/gamepad/gamepad_provider.cc +++ b/device/gamepad/gamepad_provider.cc
@@ -159,7 +159,7 @@ void GamepadProvider::DoInitializePollingThread( std::unique_ptr<GamepadDataFetcher> fetcher) { - DCHECK(base::MessageLoop::current() == polling_thread_->message_loop()); + DCHECK(polling_thread_->task_runner()->BelongsToCurrentThread()); DCHECK(!data_fetcher_.get()); // Should only initialize once. if (!fetcher) @@ -168,7 +168,7 @@ } void GamepadProvider::SendPauseHint(bool paused) { - DCHECK(base::MessageLoop::current() == polling_thread_->message_loop()); + DCHECK(polling_thread_->task_runner()->BelongsToCurrentThread()); if (data_fetcher_) data_fetcher_->PauseHint(paused); } @@ -207,7 +207,7 @@ } void GamepadProvider::DoPoll() { - DCHECK(base::MessageLoop::current() == polling_thread_->message_loop()); + DCHECK(polling_thread_->task_runner()->BelongsToCurrentThread()); DCHECK(have_scheduled_do_poll_); have_scheduled_do_poll_ = false; @@ -256,7 +256,7 @@ } void GamepadProvider::ScheduleDoPoll() { - DCHECK(base::MessageLoop::current() == polling_thread_->message_loop()); + DCHECK(polling_thread_->task_runner()->BelongsToCurrentThread()); if (have_scheduled_do_poll_) return;
diff --git a/extensions/renderer/resources/guest_view/guest_view_container.js b/extensions/renderer/resources/guest_view/guest_view_container.js index acba9fb..8cfc8cb 100644 --- a/extensions/renderer/resources/guest_view/guest_view_container.js +++ b/extensions/renderer/resources/guest_view/guest_view_container.js
@@ -101,14 +101,6 @@ // See http://crbug.com/231664. this.element.setAttribute('tabIndex', -1); } - this.element.addEventListener('focus', this.weakWrapper(function(e) { - // Focus the BrowserPlugin when the GuestViewContainer takes focus. - privates(this).internalElement.focus(); - })); - this.element.addEventListener('blur', this.weakWrapper(function(e) { - // Blur the BrowserPlugin when the GuestViewContainer loses focus. - privates(this).internalElement.blur(); - })); }; GuestViewContainer.prototype.focus = function() {
diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc index ad20e41..2462384b 100644 --- a/gpu/command_buffer/common/capabilities.cc +++ b/gpu/command_buffer/common/capabilities.cc
@@ -84,7 +84,7 @@ surfaceless(false), flips_vertically(false), msaa_is_slow(false), - disable_webgl_multisampling_color_mask_usage(false), + disable_multisampling_color_mask_usage(false), disable_webgl_rgb_multisampling_usage(false), chromium_image_rgb_emulation(false), emulate_rgb_buffer_with_rgba(false),
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h index 4443e61c..a3d1ffe 100644 --- a/gpu/command_buffer/common/capabilities.h +++ b/gpu/command_buffer/common/capabilities.h
@@ -144,7 +144,7 @@ bool surfaceless; bool flips_vertically; bool msaa_is_slow; - bool disable_webgl_multisampling_color_mask_usage; + bool disable_multisampling_color_mask_usage; bool disable_webgl_rgb_multisampling_usage; // When this parameter is true, a CHROMIUM image created with RGB format will
diff --git a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc index ab46ede0..500dd09 100644 --- a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc +++ b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
@@ -348,8 +348,7 @@ { glUseProgram(edges0_shader_); - glUniform1f(0, 1.0f); - glUniform2f(1, 1.0f / width_, 1.0f / height_); + glUniform2f(0, 1.0f / width_, 1.0f / height_); glDepthMask(GL_TRUE); glDepthFunc(GL_ALWAYS); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -378,8 +377,7 @@ // image2D g_resultTexture edge_texture_b image0 { glUseProgram(edges1_shader_); - glUniform1f(0, 0.0f); - glUniform2f(1, 1.0f / width_, 1.0f / height_); + glUniform2f(0, 1.0f / width_, 1.0f / height_); glDepthMask(GL_FALSE); glDepthFunc(GL_LESS); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -399,9 +397,7 @@ } // - Combine RightBottom (.xy) edges from previous pass into - // RightBottomLeftTop (.xyzw) edges and output it into the mask (have to - // fill in the whole buffer including empty ones for the line length - // detection to work correctly). + // RightBottomLeftTop (.xyzw) edges and output it into the mask. // - On all pixels with any edge, input buffer into a temporary color buffer // needed for correct blending in the next pass (other pixels not needed // so not copied to avoid bandwidth use). @@ -415,13 +411,12 @@ // gl_FragDepth mini4_edge_texture_ fbo.depth { // Combine edges: each pixel will now contain info on all (top, right, - // bottom, left) edges; also create depth mask as above depth and mark - // potential Z sAND also copy source color data but only on edge pixels + // bottom, left) edges; also mark depth 1 value on all pixels with any edge + // and also copy source color data but only on edge pixels glUseProgram(edges_combine_shader_); - glUniform1f(0, 1.0f); - glUniform2f(1, 1.0f / width_, 1.0f / height_); + glUniform2f(0, 1.0f / width_, 1.0f / height_); glDepthMask(GL_TRUE); - glDepthFunc(GL_ALWAYS); + glDepthFunc(GL_LESS); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); if (!is_gles31_compatible_) { @@ -455,8 +450,7 @@ // gl_FragDepth mini4_edge_texture_ fbo.depth { glUseProgram(process_and_apply_shader_); - glUniform1f(0, 0.0f); - glUniform2f(1, 1.0f / width_, 1.0f / height_); + glUniform2f(0, 1.0f / width_, 1.0f / height_); glDepthMask(GL_FALSE); glDepthFunc(GL_LESS); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -690,7 +684,6 @@ const char ApplyFramebufferAttachmentCMAAINTELResourceManager::vert_str_[] = SHADER( precision highp float; - layout(location = 0) uniform float g_Depth; // No input data. // Verts are autogenerated. // @@ -703,7 +696,7 @@ { float x = -1.0 + float((gl_VertexID & 1) << 2); float y = -1.0 + float((gl_VertexID & 2) << 1); - gl_Position = vec4(x, y, g_Depth, 1.0); + gl_Position = vec4(x, y, 0.0, 1.0); } ); @@ -716,12 +709,10 @@ \n#define EDGE_DETECT_THRESHOLD 13.0f\n \n#define saturate(x) clamp((x), 0.0, 1.0)\n - // bind to location 0 - layout(location = 0) uniform float g_Depth; // bind to a uniform buffer bind point 0 - layout(location = 1) uniform vec2 g_OneOverScreenSize; + layout(location = 0) uniform vec2 g_OneOverScreenSize; \n#ifndef EDGE_DETECT_THRESHOLD\n - layout(location = 2) uniform float g_ColorThreshold; + layout(location = 1) uniform float g_ColorThreshold; \n#endif\n \n#ifdef SUPPORTS_USAMPLER2D\n
diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc index d42dd195..6a21c49fd 100644 --- a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc +++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc
@@ -56,10 +56,9 @@ namespace gpu { ClearFramebufferResourceManager::ClearFramebufferResourceManager( - const gles2::GLES2Decoder* decoder, - const gles2::FeatureInfo::FeatureFlags& feature_flags) - : initialized_(false), program_(0u), vao_(0), buffer_id_(0u) { - Initialize(decoder, feature_flags); + const gles2::GLES2Decoder* decoder) + : initialized_(false), program_(0u), buffer_id_(0u) { + Initialize(decoder); } ClearFramebufferResourceManager::~ClearFramebufferResourceManager() { @@ -68,13 +67,12 @@ } void ClearFramebufferResourceManager::Initialize( - const gles2::GLES2Decoder* decoder, - const gles2::FeatureInfo::FeatureFlags& feature_flags) { + const gles2::GLES2Decoder* decoder) { static_assert( kVertexPositionAttrib == 0u, "kVertexPositionAttrib must be 0"); - DCHECK(!buffer_id_); + glGenBuffersARB(1, &buffer_id_); glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); const GLfloat kQuadVertices[] = {-1.0f, -1.0f, @@ -83,19 +81,6 @@ -1.0f, 1.0f}; glBufferData( GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW); - - DCHECK(!vao_); - - if (feature_flags.native_vertex_array_object) { - glGenVertexArraysOES(1, &vao_); - - glBindVertexArrayOES(vao_); - glEnableVertexAttribArray(kVertexPositionAttrib); - glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); - - decoder->RestoreAllAttributes(); - } - decoder->RestoreBufferBindings(); initialized_ = true; } @@ -105,12 +90,6 @@ return; glDeleteProgram(program_); - - if (vao_ != 0) { - glDeleteVertexArraysOES(1, &vao_); - vao_ = 0; - } - glDeleteBuffersARB(1, &buffer_id_); buffer_id_ = 0; } @@ -161,14 +140,11 @@ DLOG(ERROR) << "Invalid shader."; #endif - if (vao_) { - glBindVertexArrayOES(vao_); - } else { - decoder->ClearAllAttributes(); - glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); - glEnableVertexAttribArray(kVertexPositionAttrib); - glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); - } + decoder->ClearAllAttributes(); + glEnableVertexAttribArray(kVertexPositionAttrib); + + glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); + glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); glUniform1f(depth_handle_, clear_depth_value); glUniform4f(color_handle_, clear_color_red, clear_color_green, @@ -203,11 +179,9 @@ glViewport(0, 0, framebuffer_size.width(), framebuffer_size.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - if (vao_ == 0) { - decoder->RestoreBufferBindings(); - } decoder->RestoreAllAttributes(); decoder->RestoreProgramBindings(); + decoder->RestoreBufferBindings(); decoder->RestoreGlobalState(); }
diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h index 2095d80..750b0d68 100644 --- a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h +++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h
@@ -6,7 +6,6 @@ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_CLEAR_FRAMEBUFFER_H_ #include "base/macros.h" -#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_export.h" @@ -21,9 +20,7 @@ class GPU_EXPORT ClearFramebufferResourceManager { public: - ClearFramebufferResourceManager( - const gles2::GLES2Decoder* decoder, - const gles2::FeatureInfo::FeatureFlags& feature_flags); + ClearFramebufferResourceManager(const gles2::GLES2Decoder* decoder); ~ClearFramebufferResourceManager(); @@ -38,8 +35,7 @@ GLint clear_stencil_value); private: - void Initialize(const gles2::GLES2Decoder* decoder, - const gles2::FeatureInfo::FeatureFlags& feature_flags); + void Initialize(const gles2::GLES2Decoder* decoder); void Destroy(); // The attributes used during invocation of the extension. @@ -47,7 +43,6 @@ bool initialized_; GLuint program_; - GLuint vao_; GLuint depth_handle_; GLuint color_handle_; GLuint buffer_id_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 90f897b..6df7f6a2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2371,13 +2371,28 @@ enforce_internal_framebuffer)); if (!resolve_and_bind_) return; - - // TODO(erikchen): On old AMD GPUs on macOS, glColorMask doesn't work - // correctly for multisampled renderbuffers and the alpha channel can be - // overwritten. Add a workaround to clear the alpha channel before resolving. - // https://crbug.com/602484. ScopedGLErrorSuppressor suppressor( "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState()); + + // On old AMD GPUs on macOS, glColorMask doesn't work correctly for + // multisampled renderbuffers and the alpha channel can be overwritten. This + // workaround clears the alpha channel before resolving. + bool alpha_channel_needs_clear = + decoder_->should_use_native_gmb_for_backbuffer_ && + !decoder_->offscreen_buffer_should_have_alpha_ && + decoder_->ChromiumImageNeedsRGBEmulation() && + decoder_->feature_info_->workarounds() + .disable_multisampling_color_mask_usage; + if (alpha_channel_needs_clear) { + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, + decoder_->offscreen_target_frame_buffer_->id()); + decoder_->state_.SetDeviceColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + decoder_->RestoreClearState(); + } + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, decoder_->offscreen_target_frame_buffer_->id()); GLuint targetid; @@ -3400,8 +3415,7 @@ if (workarounds().gl_clear_broken) { DCHECK(!clear_framebuffer_blit_.get()); LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit"); - clear_framebuffer_blit_.reset( - new ClearFramebufferResourceManager(this, features())); + clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this)); if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR) return false; } @@ -3558,8 +3572,8 @@ feature_info_->feature_flags().occlusion_query_boolean; caps.timer_queries = query_manager_->GPUTimingAvailable(); - caps.disable_webgl_multisampling_color_mask_usage = - feature_info_->workarounds().disable_webgl_multisampling_color_mask_usage; + caps.disable_multisampling_color_mask_usage = + feature_info_->workarounds().disable_multisampling_color_mask_usage; caps.disable_webgl_rgb_multisampling_usage = feature_info_->workarounds().disable_webgl_rgb_multisampling_usage; caps.emulate_rgb_buffer_with_rgba = @@ -14397,15 +14411,19 @@ // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA, // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not // renderable on some platforms. - bool valid_dest_format = dest_internal_format == GL_RGB || - dest_internal_format == GL_RGBA || - dest_internal_format == GL_BGRA_EXT; + bool valid_dest_format = + dest_internal_format == GL_RGB || dest_internal_format == GL_RGBA || + dest_internal_format == GL_RGB8 || dest_internal_format == GL_RGBA8 || + dest_internal_format == GL_BGRA_EXT || + dest_internal_format == GL_BGRA8_EXT; bool valid_source_format = source_internal_format == GL_RED || source_internal_format == GL_ALPHA || source_internal_format == GL_RGB || source_internal_format == GL_RGBA || + source_internal_format == GL_RGB8 || source_internal_format == GL_RGBA8 || source_internal_format == GL_LUMINANCE || source_internal_format == GL_LUMINANCE_ALPHA || source_internal_format == GL_BGRA_EXT || + source_internal_format == GL_BGRA8_EXT || source_internal_format == GL_RGB_YCBCR_420V_CHROMIUM || source_internal_format == GL_RGB_YCBCR_422_CHROMIUM; if (!valid_source_format || !valid_dest_format) {
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 99c9538..f6a75dd 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -124,111 +124,111 @@ FormatTypeValidator() { static const FormatType kSupportedFormatTypes[] = { // ES2. - { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE }, - { GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, - { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE }, - { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE }, - { GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE }, + {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE}, + {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, + {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}, + {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, + {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, + {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE}, + {GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE}, + {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE}, // Exposed by GL_OES_texture_float and GL_OES_texture_half_float - { GL_RGB, GL_RGB, GL_FLOAT }, - { GL_RGBA, GL_RGBA, GL_FLOAT }, - { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT }, - { GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT }, - { GL_ALPHA, GL_ALPHA, GL_FLOAT }, - { GL_RGB, GL_RGB, GL_HALF_FLOAT_OES }, - { GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES }, - { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES }, - { GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES }, - { GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES }, + {GL_RGB, GL_RGB, GL_FLOAT}, + {GL_RGBA, GL_RGBA, GL_FLOAT}, + {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT}, + {GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT}, + {GL_ALPHA, GL_ALPHA, GL_FLOAT}, + {GL_RGB, GL_RGB, GL_HALF_FLOAT_OES}, + {GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES}, + {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES}, + {GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES}, + {GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES}, // Exposed by GL_ANGLE_depth_texture - { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, - { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, - { GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, + {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, + {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, + {GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // Exposed by GL_EXT_sRGB - { GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE }, - { GL_SRGB_ALPHA, GL_SRGB_ALPHA, GL_UNSIGNED_BYTE }, + {GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE}, + {GL_SRGB_ALPHA, GL_SRGB_ALPHA, GL_UNSIGNED_BYTE}, // Exposed by GL_EXT_texture_format_BGRA8888 - { GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE }, + {GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE}, // Exposed by GL_EXT_texture_rg - { GL_RED, GL_RED, GL_UNSIGNED_BYTE }, - { GL_RG, GL_RG, GL_UNSIGNED_BYTE }, - { GL_RED, GL_RED, GL_FLOAT }, - { GL_RG, GL_RG, GL_FLOAT }, - { GL_RED, GL_RED, GL_HALF_FLOAT_OES }, - { GL_RG, GL_RG, GL_HALF_FLOAT_OES }, + {GL_RED, GL_RED, GL_UNSIGNED_BYTE}, + {GL_RG, GL_RG, GL_UNSIGNED_BYTE}, + {GL_RED, GL_RED, GL_FLOAT}, + {GL_RG, GL_RG, GL_FLOAT}, + {GL_RED, GL_RED, GL_HALF_FLOAT_OES}, + {GL_RG, GL_RG, GL_HALF_FLOAT_OES}, // ES3. - { GL_R8, GL_RED, GL_UNSIGNED_BYTE }, - { GL_R8_SNORM, GL_RED, GL_BYTE }, - { GL_R16F, GL_RED, GL_HALF_FLOAT }, - { GL_R16F, GL_RED, GL_FLOAT }, - { GL_R32F, GL_RED, GL_FLOAT }, - { GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE }, - { GL_R8I, GL_RED_INTEGER, GL_BYTE }, - { GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT }, - { GL_R16I, GL_RED_INTEGER, GL_SHORT }, - { GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT }, - { GL_R32I, GL_RED_INTEGER, GL_INT }, - { GL_RG8, GL_RG, GL_UNSIGNED_BYTE }, - { GL_RG8_SNORM, GL_RG, GL_BYTE }, - { GL_RG16F, GL_RG, GL_HALF_FLOAT }, - { GL_RG16F, GL_RG, GL_FLOAT }, - { GL_RG32F, GL_RG, GL_FLOAT }, - { GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE }, - { GL_RG8I, GL_RG_INTEGER, GL_BYTE }, - { GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT }, - { GL_RG16I, GL_RG_INTEGER, GL_SHORT }, - { GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT }, - { GL_RG32I, GL_RG_INTEGER, GL_INT }, - { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE }, - { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE }, - { GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE, }, - { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, - { GL_RGB8_SNORM, GL_RGB, GL_BYTE }, - { GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV }, - { GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT }, - { GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT }, - { GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV }, - { GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT }, - { GL_RGB9_E5, GL_RGB, GL_FLOAT }, - { GL_RGB16F, GL_RGB, GL_HALF_FLOAT }, - { GL_RGB16F, GL_RGB, GL_FLOAT }, - { GL_RGB32F, GL_RGB, GL_FLOAT }, - { GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE }, - { GL_RGB8I, GL_RGB_INTEGER, GL_BYTE }, - { GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT }, - { GL_RGB16I, GL_RGB_INTEGER, GL_SHORT }, - { GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT }, - { GL_RGB32I, GL_RGB_INTEGER, GL_INT }, - { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, - { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE }, - { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE }, - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE }, - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, - { GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE }, - { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, - { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, - { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, - { GL_RGBA16F, GL_RGBA, GL_FLOAT }, - { GL_RGBA32F, GL_RGBA, GL_FLOAT }, - { GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE }, - { GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE }, - { GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV }, - { GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT }, - { GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT }, - { GL_RGBA32I, GL_RGBA_INTEGER, GL_INT }, - { GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT }, - { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, - { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, - { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, - { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT }, - { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, - { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, - GL_FLOAT_32_UNSIGNED_INT_24_8_REV }, + {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, + {GL_R8_SNORM, GL_RED, GL_BYTE}, + {GL_R16F, GL_RED, GL_HALF_FLOAT}, + {GL_R16F, GL_RED, GL_FLOAT}, + {GL_R32F, GL_RED, GL_FLOAT}, + {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, + {GL_R8I, GL_RED_INTEGER, GL_BYTE}, + {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, + {GL_R16I, GL_RED_INTEGER, GL_SHORT}, + {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, + {GL_R32I, GL_RED_INTEGER, GL_INT}, + {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, + {GL_RG8_SNORM, GL_RG, GL_BYTE}, + {GL_RG16F, GL_RG, GL_HALF_FLOAT}, + {GL_RG16F, GL_RG, GL_FLOAT}, + {GL_RG32F, GL_RG, GL_FLOAT}, + {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, + {GL_RG8I, GL_RG_INTEGER, GL_BYTE}, + {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, + {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, + {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, + {GL_RG32I, GL_RG_INTEGER, GL_INT}, + {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE}, + {GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE}, + {GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE}, + {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, + {GL_RGB8_SNORM, GL_RGB, GL_BYTE}, + {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, + {GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT}, + {GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT}, + {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, + {GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT}, + {GL_RGB9_E5, GL_RGB, GL_FLOAT}, + {GL_RGB16F, GL_RGB, GL_HALF_FLOAT}, + {GL_RGB16F, GL_RGB, GL_FLOAT}, + {GL_RGB32F, GL_RGB, GL_FLOAT}, + {GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE}, + {GL_RGB8I, GL_RGB_INTEGER, GL_BYTE}, + {GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT}, + {GL_RGB16I, GL_RGB_INTEGER, GL_SHORT}, + {GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT}, + {GL_RGB32I, GL_RGB_INTEGER, GL_INT}, + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}, + {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE}, + {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, + {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE}, + {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, + {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, + {GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE}, + {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, + {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, + {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, + {GL_RGBA16F, GL_RGBA, GL_FLOAT}, + {GL_RGBA32F, GL_RGBA, GL_FLOAT}, + {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, + {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, + {GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV}, + {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, + {GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, + {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, + {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, + {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, + {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, + {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, + {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, + {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, + {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, }; for (size_t ii = 0; ii < arraysize(kSupportedFormatTypes); ++ii) {
diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc index 4b8fa4a5..44701c96 100644 --- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc +++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -73,6 +73,20 @@ } } + GLenum ExtractFormatFrom(GLenum internalformat) { + switch (internalformat) { + case GL_RGBA8_OES: + return GL_RGBA; + case GL_RGB8_OES: + return GL_RGB; + case GL_BGRA8_EXT: + return GL_BGRA_EXT; + default: + NOTREACHED(); + return GL_NONE; + } + } + GLManager gl_; GLuint textures_[2]; GLuint framebuffer_id_; @@ -124,41 +138,53 @@ return; } CopyType copy_type = GetParam(); + GLenum src_internal_formats[] = {GL_RGB8_OES, GL_RGBA8_OES, GL_BGRA8_EXT}; + GLenum dest_internal_formats[] = {GL_RGB8_OES, GL_RGBA8_OES, GL_BGRA8_EXT}; - uint8_t pixels[1 * 4] = {255u, 0u, 0u, 255u}; + uint8_t pixels[1 * 4] = {255u, 0u, 255u, 255u}; - glBindTexture(GL_TEXTURE_2D, textures_[0]); - glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, - pixels); + for (auto src_internal_format : src_internal_formats) { + for (auto dest_internal_format : dest_internal_formats) { + glDeleteTextures(2, textures_); + glDeleteFramebuffers(1, &framebuffer_id_); + CreateAndBindDestinationTextureAndFBO(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, textures_[1]); - glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - textures_[1], 0); - EXPECT_TRUE(glGetError() == GL_NO_ERROR); + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, src_internal_format, 1, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, + ExtractFormatFrom(src_internal_format), GL_UNSIGNED_BYTE, + pixels); - if (copy_type == TexImage) { - glCopyTextureCHROMIUM(textures_[0], textures_[1], GL_RGBA, - GL_UNSIGNED_BYTE, false, false, false); - EXPECT_TRUE(glGetError() == GL_INVALID_OPERATION); - } else { - glCopySubTextureCHROMIUM(textures_[0], textures_[1], 0, 0, 0, - 0, 1, 1, false, false, false); - EXPECT_TRUE(glGetError() == GL_NO_ERROR); + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, dest_internal_format, 1, 1); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, textures_[1], 0); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); - // Check the FB is still bound. - GLint value = 0; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value); - GLuint fb_id = value; - EXPECT_EQ(framebuffer_id_, fb_id); + if (copy_type == TexImage) { + glCopyTextureCHROMIUM(textures_[0], textures_[1], + ExtractFormatFrom(dest_internal_format), + GL_UNSIGNED_BYTE, false, false, false); + EXPECT_TRUE(glGetError() == GL_INVALID_OPERATION); + } else { + glCopySubTextureCHROMIUM(textures_[0], textures_[1], 0, 0, 0, 0, 1, 1, + false, false, false); + EXPECT_TRUE(glGetError() == GL_NO_ERROR); - // Check that FB is complete. - EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), - glCheckFramebufferStatus(GL_FRAMEBUFFER)); + // Check the FB is still bound. + GLint value = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &value); + GLuint fb_id = value; + EXPECT_EQ(framebuffer_id_, fb_id); - GLTestHelper::CheckPixels(0, 0, 1, 1, 0, pixels); - EXPECT_TRUE(GL_NO_ERROR == glGetError()); + // Check that FB is complete. + EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), + glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + GLTestHelper::CheckPixels(0, 0, 1, 1, 0, pixels); + EXPECT_TRUE(GL_NO_ERROR == glGetError()); + } + } } }
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 03a8dd06..8b81fa8 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -1754,7 +1754,7 @@ "vendor_id": "0x1002", "device_id": ["0x68b8"], "features": [ - "disable_webgl_multisampling_color_mask_usage" + "disable_multisampling_color_mask_usage" ] }, {
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h index 2f1f865f..4b59789 100644 --- a/gpu/config/gpu_driver_bug_workaround_type.h +++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -65,8 +65,8 @@ disable_texture_storage) \ GPU_OP(DISABLE_TIMESTAMP_QUERIES, \ disable_timestamp_queries) \ - GPU_OP(DISABLE_WEBGL_MULTISAMPLING_COLOR_MASK_USAGE, \ - disable_webgl_multisampling_color_mask_usage) \ + GPU_OP(DISABLE_MULTISAMPLING_COLOR_MASK_USAGE, \ + disable_multisampling_color_mask_usage) \ GPU_OP(DISABLE_WEBGL_RGB_MULTISAMPLING_USAGE, \ disable_webgl_rgb_multisampling_usage) \ GPU_OP(ETC1_POWER_OF_TWO_ONLY, \
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h index 78cd98e..4994e42 100644 --- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -111,7 +111,7 @@ IPC_STRUCT_TRAITS_MEMBER(timer_queries) IPC_STRUCT_TRAITS_MEMBER(surfaceless) IPC_STRUCT_TRAITS_MEMBER(flips_vertically) - IPC_STRUCT_TRAITS_MEMBER(disable_webgl_multisampling_color_mask_usage) + IPC_STRUCT_TRAITS_MEMBER(disable_multisampling_color_mask_usage) IPC_STRUCT_TRAITS_MEMBER(disable_webgl_rgb_multisampling_usage) IPC_STRUCT_TRAITS_MEMBER(msaa_is_slow) IPC_STRUCT_TRAITS_MEMBER(chromium_image_rgb_emulation)
diff --git a/gpu/ipc/common/gpu_param_traits_macros.h b/gpu/ipc/common/gpu_param_traits_macros.h index 514f464..971c38f 100644 --- a/gpu/ipc/common/gpu_param_traits_macros.h +++ b/gpu/ipc/common/gpu_param_traits_macros.h
@@ -129,6 +129,7 @@ IPC_STRUCT_TRAITS_MEMBER(fail_if_major_perf_caveat) IPC_STRUCT_TRAITS_MEMBER(lose_context_when_out_of_memory) IPC_STRUCT_TRAITS_MEMBER(context_type) + IPC_STRUCT_TRAITS_MEMBER(should_use_native_gmb_for_backbuffer) IPC_STRUCT_TRAITS_END()
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index d142d15c..40e3230 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -74,6 +74,8 @@ "$target_gen_dir/public/domains/animation.h", "$target_gen_dir/public/domains/application_cache.cc", "$target_gen_dir/public/domains/application_cache.h", + "$target_gen_dir/public/domains/browser.cc", + "$target_gen_dir/public/domains/browser.h", "$target_gen_dir/public/domains/cache_storage.cc", "$target_gen_dir/public/domains/cache_storage.h", "$target_gen_dir/public/domains/console.cc", @@ -155,6 +157,8 @@ "$target_gen_dir/public/domains/animation.h", "$target_gen_dir/public/domains/application_cache.cc", "$target_gen_dir/public/domains/application_cache.h", + "$target_gen_dir/public/domains/browser.cc", + "$target_gen_dir/public/domains/browser.h", "$target_gen_dir/public/domains/cache_storage.cc", "$target_gen_dir/public/domains/cache_storage.h", "$target_gen_dir/public/domains/console.cc", @@ -222,6 +226,8 @@ "lib/browser/headless_devtools.h", "lib/browser/headless_devtools_client_impl.cc", "lib/browser/headless_devtools_client_impl.h", + "lib/browser/headless_devtools_manager_delegate.cc", + "lib/browser/headless_devtools_manager_delegate.h", "lib/browser/headless_screen.cc", "lib/browser/headless_screen.h", "lib/browser/headless_url_request_context_getter.cc",
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc index a3eb1ba..04ce85f 100644 --- a/headless/lib/browser/headless_browser_impl.cc +++ b/headless/lib/browser/headless_browser_impl.cc
@@ -105,10 +105,10 @@ std::vector<HeadlessWebContents*> HeadlessBrowserImpl::GetAllWebContents() { std::vector<HeadlessWebContents*> result; - result.reserve(web_contents_.size()); + result.reserve(web_contents_map_.size()); - for (const auto& web_contents_pair : web_contents_) { - result.push_back(web_contents_pair.first); + for (const auto& web_contents_pair : web_contents_map_) { + result.push_back(web_contents_pair.second.get()); } return result; @@ -144,15 +144,24 @@ std::unique_ptr<HeadlessWebContentsImpl> web_contents) { DCHECK(web_contents); HeadlessWebContentsImpl* unowned_web_contents = web_contents.get(); - web_contents_[unowned_web_contents] = std::move(web_contents); + web_contents_map_[unowned_web_contents->GetDevtoolsAgentHostId()] = + std::move(web_contents); return unowned_web_contents; } void HeadlessBrowserImpl::DestroyWebContents( HeadlessWebContentsImpl* web_contents) { - auto it = web_contents_.find(web_contents); - DCHECK(it != web_contents_.end()); - web_contents_.erase(it); + auto it = web_contents_map_.find(web_contents->GetDevtoolsAgentHostId()); + DCHECK(it != web_contents_map_.end()); + web_contents_map_.erase(it); +} + +HeadlessWebContents* HeadlessBrowserImpl::GetWebContentsForDevtoolsAgentHostId( + const std::string& devtools_agent_host_id) { + auto it = web_contents_map_.find(devtools_agent_host_id); + if (it == web_contents_map_.end()) + return nullptr; + return it->second.get(); } void HeadlessBrowserImpl::SetOptionsForTesting(
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h index 68dc676e..50d59848 100644 --- a/headless/lib/browser/headless_browser_impl.h +++ b/headless/lib/browser/headless_browser_impl.h
@@ -46,6 +46,8 @@ void Shutdown() override; std::vector<HeadlessWebContents*> GetAllWebContents() override; + HeadlessWebContents* GetWebContentsForDevtoolsAgentHostId( + const std::string& devtools_agent_host_id) override; void set_browser_main_parts(HeadlessBrowserMainParts* browser_main_parts); HeadlessBrowserMainParts* browser_main_parts() const; @@ -73,8 +75,8 @@ std::unique_ptr<aura::WindowTreeHost> window_tree_host_; std::unique_ptr<aura::client::WindowTreeClient> window_tree_client_; - std::unordered_map<HeadlessWebContents*, std::unique_ptr<HeadlessWebContents>> - web_contents_; + std::unordered_map<std::string, std::unique_ptr<HeadlessWebContents>> + web_contents_map_; private: DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserImpl);
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc index a56a1fe..23ddee0 100644 --- a/headless/lib/browser/headless_content_browser_client.cc +++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -10,6 +10,7 @@ #include "content/public/browser/browser_thread.h" #include "headless/lib/browser/headless_browser_impl.h" #include "headless/lib/browser/headless_browser_main_parts.h" +#include "headless/lib/browser/headless_devtools_manager_delegate.h" namespace headless { @@ -27,4 +28,9 @@ return browser_main_parts.release(); } +content::DevToolsManagerDelegate* +HeadlessContentBrowserClient::GetDevToolsManagerDelegate() { + return new HeadlessDevToolsManagerDelegate(browser_); +} + } // namespace headless
diff --git a/headless/lib/browser/headless_content_browser_client.h b/headless/lib/browser/headless_content_browser_client.h index 16d9ef3..222c3d7 100644 --- a/headless/lib/browser/headless_content_browser_client.h +++ b/headless/lib/browser/headless_content_browser_client.h
@@ -11,6 +11,7 @@ class HeadlessBrowserImpl; class HeadlessBrowserMainParts; +class HeadlessDevToolsManagerDelegate; class HeadlessContentBrowserClient : public content::ContentBrowserClient { public: @@ -21,6 +22,8 @@ content::BrowserMainParts* CreateBrowserMainParts( const content::MainFunctionParams&) override; + content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override; + private: HeadlessBrowserImpl* browser_; // Not owned.
diff --git a/headless/lib/browser/headless_devtools_client_impl.cc b/headless/lib/browser/headless_devtools_client_impl.cc index 41aa4fc..a00aa7e 100644 --- a/headless/lib/browser/headless_devtools_client_impl.cc +++ b/headless/lib/browser/headless_devtools_client_impl.cc
@@ -33,6 +33,7 @@ accessibility_domain_(this), animation_domain_(this), application_cache_domain_(this), + browser_domain_(this), cache_storage_domain_(this), console_domain_(this), css_domain_(this), @@ -158,6 +159,10 @@ return &application_cache_domain_; } +browser::Domain* HeadlessDevToolsClientImpl::GetBrowser() { + return &browser_domain_; +} + cache_storage::Domain* HeadlessDevToolsClientImpl::GetCacheStorage() { return &cache_storage_domain_; }
diff --git a/headless/lib/browser/headless_devtools_client_impl.h b/headless/lib/browser/headless_devtools_client_impl.h index c7dbb52..fed7050 100644 --- a/headless/lib/browser/headless_devtools_client_impl.h +++ b/headless/lib/browser/headless_devtools_client_impl.h
@@ -11,6 +11,7 @@ #include "headless/public/domains/accessibility.h" #include "headless/public/domains/animation.h" #include "headless/public/domains/application_cache.h" +#include "headless/public/domains/browser.h" #include "headless/public/domains/cache_storage.h" #include "headless/public/domains/console.h" #include "headless/public/domains/css.h" @@ -63,6 +64,7 @@ accessibility::Domain* GetAccessibility() override; animation::Domain* GetAnimation() override; application_cache::Domain* GetApplicationCache() override; + browser::Domain* GetBrowser() override; cache_storage::Domain* GetCacheStorage() override; console::Domain* GetConsole() override; css::Domain* GetCSS() override; @@ -154,6 +156,7 @@ accessibility::ExperimentalDomain accessibility_domain_; animation::ExperimentalDomain animation_domain_; application_cache::ExperimentalDomain application_cache_domain_; + browser::ExperimentalDomain browser_domain_; cache_storage::ExperimentalDomain cache_storage_domain_; console::ExperimentalDomain console_domain_; css::ExperimentalDomain css_domain_;
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.cc b/headless/lib/browser/headless_devtools_manager_delegate.cc new file mode 100644 index 0000000..5c4f962 --- /dev/null +++ b/headless/lib/browser/headless_devtools_manager_delegate.cc
@@ -0,0 +1,154 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "headless/lib/browser/headless_devtools_manager_delegate.h" + +#include <string> + +#include "base/guid.h" +#include "content/public/browser/web_contents.h" +#include "headless/lib/browser/headless_browser_context_impl.h" +#include "headless/lib/browser/headless_browser_impl.h" +#include "headless/lib/browser/headless_web_contents_impl.h" +#include "headless/public/domains/browser.h" + +namespace headless { + +HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate( + HeadlessBrowserImpl* browser) + : browser_(browser) { + command_map_["Browser.createTarget"] = + &HeadlessDevToolsManagerDelegate::CreateTarget; + command_map_["Browser.closeTarget"] = + &HeadlessDevToolsManagerDelegate::CloseTarget; + command_map_["Browser.createBrowserContext"] = + &HeadlessDevToolsManagerDelegate::CreateBrowserContext; + command_map_["Browser.disposeBrowserContext"] = + &HeadlessDevToolsManagerDelegate::DisposeBrowserContext; +} + +HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() {} + +base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand( + content::DevToolsAgentHost* agent_host, + base::DictionaryValue* command) { + int id; + std::string method; + const base::DictionaryValue* params = nullptr; + if (!command->GetInteger("id", &id) || + !command->GetString("method", &method) || + !command->GetDictionary("params", ¶ms)) { + return nullptr; + } + auto find_it = command_map_.find(method); + if (find_it == command_map_.end()) + return nullptr; + CommandMemberFnPtr command_fn_ptr = find_it->second; + std::unique_ptr<base::Value> cmd_result(((this)->*command_fn_ptr)(params)); + if (!cmd_result) + return nullptr; + + std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + result->SetInteger("id", id); + result->Set("result", std::move(cmd_result)); + return result.release(); +} + +std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CreateTarget( + const base::DictionaryValue* params) { + std::string initial_url; + std::string browser_context_id; + int width = 800; + int height = 600; + params->GetString("initialUrl", &initial_url); + params->GetString("browserContextId", &browser_context_id); + params->GetInteger("width", &width); + params->GetInteger("height", &height); + HeadlessWebContentsImpl* web_contents_impl; + auto find_it = browser_context_map_.find(browser_context_id); + if (find_it != browser_context_map_.end()) { + web_contents_impl = HeadlessWebContentsImpl::From( + browser_->CreateWebContentsBuilder() + .SetInitialURL(GURL(initial_url)) + .SetWindowSize(gfx::Size(width, height)) + .SetBrowserContext(find_it->second.get()) + .Build()); + } else { + web_contents_impl = HeadlessWebContentsImpl::From( + browser_->CreateWebContentsBuilder() + .SetInitialURL(GURL(initial_url)) + .SetWindowSize(gfx::Size(width, height)) + .Build()); + } + return browser::CreateTargetResult::Builder() + .SetTargetId(web_contents_impl->GetDevtoolsAgentHostId()) + .Build() + ->Serialize(); +} + +std::unique_ptr<base::Value> HeadlessDevToolsManagerDelegate::CloseTarget( + const base::DictionaryValue* params) { + std::string target_id; + if (!params->GetString("targetId", &target_id)) { + return nullptr; + } + HeadlessWebContents* web_contents = + browser_->GetWebContentsForDevtoolsAgentHostId(target_id); + bool success = false; + if (web_contents) { + web_contents->Close(); + success = true; + } + return browser::CloseTargetResult::Builder() + .SetSuccess(success) + .Build() + ->Serialize(); +} + +std::unique_ptr<base::Value> +HeadlessDevToolsManagerDelegate::CreateBrowserContext( + const base::DictionaryValue* params) { + std::string browser_context_id = base::GenerateGUID(); + browser_context_map_[browser_context_id] = + browser_->CreateBrowserContextBuilder().Build(); + std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + return browser::CreateBrowserContextResult::Builder() + .SetBrowserContextId(browser_context_id) + .Build() + ->Serialize(); +} + +std::unique_ptr<base::Value> +HeadlessDevToolsManagerDelegate::DisposeBrowserContext( + const base::DictionaryValue* params) { + std::string browser_context_id; + if (!params->GetString("browserContextId", &browser_context_id)) { + return nullptr; + } + auto find_it = browser_context_map_.find(browser_context_id); + bool success = false; + if (find_it != browser_context_map_.end()) { + success = true; + HeadlessBrowserContextImpl* headless_browser_context = + HeadlessBrowserContextImpl::From(find_it->second.get()); + // Make sure |headless_browser_context| isn't in use! + for (HeadlessWebContents* headless_web_contents : + browser_->GetAllWebContents()) { + content::WebContents* web_contents = + HeadlessWebContentsImpl::From(headless_web_contents)->web_contents(); + if (web_contents->GetBrowserContext() == headless_browser_context) { + success = false; + break; + } + } + if (success) + browser_context_map_.erase(find_it); + } + return browser::DisposeBrowserContextResult::Builder() + .SetSuccess(success) + .Build() + ->Serialize(); +} + +} // namespace headless
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.h b/headless/lib/browser/headless_devtools_manager_delegate.h new file mode 100644 index 0000000..fa4cd17 --- /dev/null +++ b/headless/lib/browser/headless_devtools_manager_delegate.h
@@ -0,0 +1,56 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_MANAGER_DELEGATE_H_ +#define HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_MANAGER_DELEGATE_H_ + +#include "content/public/browser/devtools_manager_delegate.h" + +#include <map> +#include <memory> +#include <string> + +#include "base/values.h" + +namespace headless { +class HeadlessBrowserImpl; +class HeadlessBrowserContext; +class HeadlessWebContentsImpl; + +class HeadlessDevToolsManagerDelegate + : public content::DevToolsManagerDelegate { + public: + explicit HeadlessDevToolsManagerDelegate(HeadlessBrowserImpl* browser); + ~HeadlessDevToolsManagerDelegate() override; + + // DevToolsManagerDelegate implementation: + void Inspect(content::BrowserContext* browser_context, + content::DevToolsAgentHost* agent_host) override {} + void DevToolsAgentStateChanged(content::DevToolsAgentHost* agent_host, + bool attached) override{}; + base::DictionaryValue* HandleCommand(content::DevToolsAgentHost* agent_host, + base::DictionaryValue* command) override; + + private: + std::unique_ptr<base::Value> CreateTarget( + const base::DictionaryValue* params); + std::unique_ptr<base::Value> CloseTarget(const base::DictionaryValue* params); + std::unique_ptr<base::Value> CreateBrowserContext( + const base::DictionaryValue* params); + std::unique_ptr<base::Value> DisposeBrowserContext( + const base::DictionaryValue* params); + + HeadlessBrowserImpl* browser_; // Not owned. + std::map<std::string, std::unique_ptr<HeadlessBrowserContext>> + browser_context_map_; + + using CommandMemberFnPtr = std::unique_ptr<base::Value> ( + HeadlessDevToolsManagerDelegate::*)(const base::DictionaryValue* params); + + std::map<std::string, CommandMemberFnPtr> command_map_; +}; + +} // namespace headless + +#endif // HEADLESS_LIB_BROWSER_HEADLESS_DEVTOOLS_MANAGER_DELEGATE_H_
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc index b07cb2c..0b10161f 100644 --- a/headless/lib/browser/headless_web_contents_impl.cc +++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -27,6 +27,14 @@ namespace headless { +// static +HeadlessWebContentsImpl* HeadlessWebContentsImpl::From( + HeadlessWebContents* web_contents) { + // This downcast is safe because there is only one implementation of + // HeadlessWebContents. + return static_cast<HeadlessWebContentsImpl*>(web_contents); +} + class WebContentsObserverAdapter : public content::WebContentsObserver { public: WebContentsObserverAdapter(content::WebContents* web_contents, @@ -114,6 +122,7 @@ HeadlessBrowserImpl* browser) : web_contents_delegate_(new HeadlessWebContentsImpl::Delegate(browser)), web_contents_(web_contents), + agent_host_(content::DevToolsAgentHost::GetOrCreateFor(web_contents)), browser_(browser) { web_contents_->SetDelegate(web_contents_delegate_.get()); } @@ -137,6 +146,10 @@ browser_->DestroyWebContents(this); } +std::string HeadlessWebContentsImpl::GetDevtoolsAgentHostId() { + return agent_host_->GetId(); +} + void HeadlessWebContentsImpl::AddObserver(Observer* observer) { DCHECK(observer_map_.find(observer) == observer_map_.end()); observer_map_[observer] = base::WrapUnique( @@ -154,8 +167,6 @@ } void HeadlessWebContentsImpl::AttachClient(HeadlessDevToolsClient* client) { - if (!agent_host_) - agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(web_contents()); HeadlessDevToolsClientImpl::From(client)->AttachToHost(agent_host_.get()); }
diff --git a/headless/lib/browser/headless_web_contents_impl.h b/headless/lib/browser/headless_web_contents_impl.h index e0eec04..dde41581d 100644 --- a/headless/lib/browser/headless_web_contents_impl.h +++ b/headless/lib/browser/headless_web_contents_impl.h
@@ -35,6 +35,8 @@ public: ~HeadlessWebContentsImpl() override; + static HeadlessWebContentsImpl* From(HeadlessWebContents* web_contents); + static std::unique_ptr<HeadlessWebContentsImpl> Create( HeadlessWebContents::Builder* builder, aura::Window* parent_window, @@ -59,6 +61,8 @@ void Close() override; + std::string GetDevtoolsAgentHostId(); + private: // Takes ownership of |web_contents|. HeadlessWebContentsImpl(content::WebContents* web_contents,
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc index 8b51fec..daceba5d 100644 --- a/headless/lib/headless_devtools_client_browsertest.cc +++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -4,7 +4,9 @@ #include <memory> +#include "base/json/json_reader.h" #include "content/public/test/browser_test.h" +#include "headless/public/domains/browser.h" #include "headless/public/domains/network.h" #include "headless/public/domains/page.h" #include "headless/public/domains/runtime.h" @@ -172,4 +174,324 @@ HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessDevToolsClientExperimentalTest); +class BrowserDomainCreateAndDeletePageTest + : public HeadlessAsyncDevTooledBrowserTest { + void RunDevTooledTest() override { + EXPECT_TRUE(embedded_test_server()->Start()); + + EXPECT_EQ(1u, browser()->GetAllWebContents().size()); + + devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( + browser::CreateTargetParams::Builder() + .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetWidth(1) + .SetHeight(1) + .Build(), + base::Bind(&BrowserDomainCreateAndDeletePageTest::OnCreateTargetResult, + base::Unretained(this))); + } + + void OnCreateTargetResult( + std::unique_ptr<browser::CreateTargetResult> result) { + EXPECT_EQ(2u, browser()->GetAllWebContents().size()); + + devtools_client_->GetBrowser()->GetExperimental()->CloseTarget( + browser::CloseTargetParams::Builder() + .SetTargetId(result->GetTargetId()) + .Build(), + base::Bind(&BrowserDomainCreateAndDeletePageTest::OnCloseTargetResult, + base::Unretained(this))); + } + + void OnCloseTargetResult(std::unique_ptr<browser::CloseTargetResult> result) { + EXPECT_EQ(1u, browser()->GetAllWebContents().size()); + FinishAsynchronousTest(); + } +}; + +HEADLESS_ASYNC_DEVTOOLED_TEST_F(BrowserDomainCreateAndDeletePageTest); + +class BrowserDomainDisposeContextFailsIfInUse + : public HeadlessAsyncDevTooledBrowserTest { + void RunDevTooledTest() override { + EXPECT_TRUE(embedded_test_server()->Start()); + + EXPECT_EQ(1u, browser()->GetAllWebContents().size()); + devtools_client_->GetBrowser()->GetExperimental()->CreateBrowserContext( + browser::CreateBrowserContextParams::Builder().Build(), + base::Bind(&BrowserDomainDisposeContextFailsIfInUse::OnContextCreated, + base::Unretained(this))); + } + + void OnContextCreated( + std::unique_ptr<browser::CreateBrowserContextResult> result) { + context_id_ = result->GetBrowserContextId(); + + devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( + browser::CreateTargetParams::Builder() + .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetBrowserContextId(context_id_) + .Build(), + base::Bind( + &BrowserDomainDisposeContextFailsIfInUse::OnCreateTargetResult, + base::Unretained(this))); + } + + void OnCreateTargetResult( + std::unique_ptr<browser::CreateTargetResult> result) { + page_id_ = result->GetTargetId(); + + devtools_client_->GetBrowser()->GetExperimental()->DisposeBrowserContext( + browser::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_) + .Build(), + base::Bind(&BrowserDomainDisposeContextFailsIfInUse:: + OnDisposeBrowserContextResult, + base::Unretained(this))); + } + + void OnDisposeBrowserContextResult( + std::unique_ptr<browser::DisposeBrowserContextResult> result) { + EXPECT_FALSE(result->GetSuccess()); + + // Close the page and try again. + devtools_client_->GetBrowser()->GetExperimental()->CloseTarget( + browser::CloseTargetParams::Builder().SetTargetId(page_id_).Build(), + base::Bind( + &BrowserDomainDisposeContextFailsIfInUse::OnCloseTargetResult, + base::Unretained(this))); + } + + void OnCloseTargetResult(std::unique_ptr<browser::CloseTargetResult> result) { + EXPECT_TRUE(result->GetSuccess()); + + devtools_client_->GetBrowser()->GetExperimental()->DisposeBrowserContext( + browser::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_) + .Build(), + base::Bind(&BrowserDomainDisposeContextFailsIfInUse:: + OnDisposeBrowserContextResult2, + base::Unretained(this))); + } + + void OnDisposeBrowserContextResult2( + std::unique_ptr<browser::DisposeBrowserContextResult> result) { + EXPECT_TRUE(result->GetSuccess()); + FinishAsynchronousTest(); + } + + private: + std::string context_id_; + std::string page_id_; +}; + +HEADLESS_ASYNC_DEVTOOLED_TEST_F(BrowserDomainDisposeContextFailsIfInUse); + +class BrowserDomainCreateTwoContexts : public HeadlessAsyncDevTooledBrowserTest, + public browser::ExperimentalObserver { + public: + void RunDevTooledTest() override { + EXPECT_TRUE(embedded_test_server()->Start()); + + devtools_client_->GetBrowser()->GetExperimental()->AddObserver(this); + devtools_client_->GetBrowser()->GetExperimental()->CreateBrowserContext( + browser::CreateBrowserContextParams::Builder().Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnContextOneCreated, + base::Unretained(this))); + + devtools_client_->GetBrowser()->GetExperimental()->CreateBrowserContext( + browser::CreateBrowserContextParams::Builder().Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnContextTwoCreated, + base::Unretained(this))); + } + + void OnContextOneCreated( + std::unique_ptr<browser::CreateBrowserContextResult> result) { + context_id_one_ = result->GetBrowserContextId(); + MaybeCreatePages(); + } + + void OnContextTwoCreated( + std::unique_ptr<browser::CreateBrowserContextResult> result) { + context_id_two_ = result->GetBrowserContextId(); + MaybeCreatePages(); + } + + void MaybeCreatePages() { + if (context_id_one_.empty() || context_id_two_.empty()) + return; + + devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( + browser::CreateTargetParams::Builder() + .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetBrowserContextId(context_id_one_) + .Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnCreateTargetOneResult, + base::Unretained(this))); + + devtools_client_->GetBrowser()->GetExperimental()->CreateTarget( + browser::CreateTargetParams::Builder() + .SetInitialUrl(embedded_test_server()->GetURL("/hello.html").spec()) + .SetBrowserContextId(context_id_two_) + .Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnCreateTargetTwoResult, + base::Unretained(this))); + } + + void OnCreateTargetOneResult( + std::unique_ptr<browser::CreateTargetResult> result) { + page_id_one_ = result->GetTargetId(); + MaybeTestIsolation(); + } + + void OnCreateTargetTwoResult( + std::unique_ptr<browser::CreateTargetResult> result) { + page_id_two_ = result->GetTargetId(); + MaybeTestIsolation(); + } + + void MaybeTestIsolation() { + if (page_id_one_.empty() || page_id_two_.empty()) + return; + + devtools_client_->GetBrowser()->GetExperimental()->Attach( + browser::AttachParams::Builder().SetTargetId(page_id_one_).Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnAttachedOne, + base::Unretained(this))); + + devtools_client_->GetBrowser()->GetExperimental()->Attach( + browser::AttachParams::Builder().SetTargetId(page_id_two_).Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnAttachedTwo, + base::Unretained(this))); + } + + void OnAttachedOne(std::unique_ptr<browser::AttachResult> result) { + devtools_client_->GetBrowser()->GetExperimental()->SendMessage( + browser::SendMessageParams::Builder() + .SetTargetId(page_id_one_) + .SetMessage("{\"id\":101, \"method\": \"Page.enable\"}") + .Build()); + } + + void OnAttachedTwo(std::unique_ptr<browser::AttachResult> result) { + devtools_client_->GetBrowser()->GetExperimental()->SendMessage( + browser::SendMessageParams::Builder() + .SetTargetId(page_id_two_) + .SetMessage("{\"id\":102, \"method\": \"Page.enable\"}") + .Build()); + } + + void MaybeSetCookieOnPageOne() { + if (!page_one_loaded_ || !page_two_loaded_) + return; + + devtools_client_->GetBrowser()->GetExperimental()->SendMessage( + browser::SendMessageParams::Builder() + .SetTargetId(page_id_one_) + .SetMessage("{\"id\":201, \"method\": \"Runtime.evaluate\", " + "\"params\": {\"expression\": " + "\"document.cookie = 'foo=bar';\"}}") + .Build()); + } + + void OnDispatchMessage( + const browser::DispatchMessageParams& params) override { + std::unique_ptr<base::Value> message = + base::JSONReader::Read(params.GetMessage(), base::JSON_PARSE_RFC); + const base::DictionaryValue* message_dict; + if (!message || !message->GetAsDictionary(&message_dict)) { + return; + } + std::string method; + if (message_dict->GetString("method", &method) && + method == "Page.loadEventFired") { + if (params.GetTargetId() == page_id_one_) { + page_one_loaded_ = true; + } else if (params.GetTargetId() == page_id_two_) { + page_two_loaded_ = true; + } + MaybeSetCookieOnPageOne(); + return; + } + const base::DictionaryValue* result_dict; + if (message_dict->GetDictionary("result", &result_dict)) { + // There's a nested result. We want the inner one. + if (!result_dict->GetDictionary("result", &result_dict)) + return; + std::string value; + if (params.GetTargetId() == page_id_one_) { + // TODO(alexclarke): Make some better bindings for Browser.sendMessage. + devtools_client_->GetBrowser()->GetExperimental()->SendMessage( + browser::SendMessageParams::Builder() + .SetTargetId(page_id_two_) + .SetMessage("{\"id\":202, \"method\": \"Runtime.evaluate\", " + "\"params\": {\"expression\": " + "\"document.cookie;\"}}") + .Build()); + } else if (params.GetTargetId() == page_id_two_ && + result_dict->GetString("value", &value)) { + EXPECT_EQ("", value) << "Page 2 should not share cookies from page one"; + + devtools_client_->GetBrowser()->GetExperimental()->CloseTarget( + browser::CloseTargetParams::Builder() + .SetTargetId(page_id_one_) + .Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnCloseTarget, + base::Unretained(this))); + + devtools_client_->GetBrowser()->GetExperimental()->CloseTarget( + browser::CloseTargetParams::Builder() + .SetTargetId(page_id_two_) + .Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnCloseTarget, + base::Unretained(this))); + + devtools_client_->GetBrowser()->GetExperimental()->RemoveObserver(this); + } + } + } + + void OnCloseTarget(std::unique_ptr<browser::CloseTargetResult> result) { + page_close_count_++; + + if (page_close_count_ < 2) + return; + + devtools_client_->GetBrowser()->GetExperimental()->DisposeBrowserContext( + browser::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_one_) + .Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnCloseContext, + base::Unretained(this))); + + devtools_client_->GetBrowser()->GetExperimental()->DisposeBrowserContext( + browser::DisposeBrowserContextParams::Builder() + .SetBrowserContextId(context_id_two_) + .Build(), + base::Bind(&BrowserDomainCreateTwoContexts::OnCloseContext, + base::Unretained(this))); + } + + void OnCloseContext( + std::unique_ptr<browser::DisposeBrowserContextResult> result) { + EXPECT_TRUE(result->GetSuccess()); + if (++context_closed_count_ < 2) + return; + + FinishAsynchronousTest(); + } + + private: + std::string context_id_one_; + std::string context_id_two_; + std::string page_id_one_; + std::string page_id_two_; + bool page_one_loaded_ = false; + bool page_two_loaded_ = false; + int page_close_count_ = 0; + int context_closed_count_ = 0; +}; + +HEADLESS_ASYNC_DEVTOOLED_TEST_F(BrowserDomainCreateTwoContexts); + } // namespace headless
diff --git a/headless/public/headless_browser.h b/headless/public/headless_browser.h index 2e9145153..b98a40a 100644 --- a/headless/public/headless_browser.h +++ b/headless/public/headless_browser.h
@@ -48,6 +48,11 @@ virtual std::vector<HeadlessWebContents*> GetAllWebContents() = 0; + // Returns the HeadlessWebContents associated with the + // |devtools_agent_host_id| if any. Otherwise returns null. + virtual HeadlessWebContents* GetWebContentsForDevtoolsAgentHostId( + const std::string& devtools_agent_host_id) = 0; + // Returns a task runner for submitting work to the browser main thread. virtual scoped_refptr<base::SingleThreadTaskRunner> BrowserMainThread() const = 0;
diff --git a/headless/public/headless_devtools_client.h b/headless/public/headless_devtools_client.h index a71ce657..89d686c 100644 --- a/headless/public/headless_devtools_client.h +++ b/headless/public/headless_devtools_client.h
@@ -21,6 +21,9 @@ namespace application_cache { class Domain; } +namespace browser { +class Domain; +} namespace cache_storage { class Domain; } @@ -115,6 +118,7 @@ virtual accessibility::Domain* GetAccessibility() = 0; virtual animation::Domain* GetAnimation() = 0; virtual application_cache::Domain* GetApplicationCache() = 0; + virtual browser::Domain* GetBrowser() = 0; virtual cache_storage::Domain* GetCacheStorage() = 0; virtual console::Domain* GetConsole() = 0; virtual css::Domain* GetCSS() = 0;
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 65f3348..841960b8 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -65,7 +65,10 @@ builders { name: "ios-simulator" } builders { name: "ios-simulator-gn" } builders { name: "mac_chromium_compile_dbg_ng" } - builders { name: "mac_chromium_gyp_rel" } + builders { + name: "mac_chromium_gyp_rel" + experiment_percentage: 10 + } builders { name: "mac_chromium_rel_ng" } builders { name: "mac_chromium_10.10_rel_ng" @@ -81,7 +84,7 @@ builders { name: "win_chromium_compile_dbg_ng" } builders { name: "win8_chromium_gyp_rel" - experiment_percentage: 50 + experiment_percentage: 10 } builders { name: "win_chromium_rel_ng" } builders { name: "win_chromium_x64_rel_ng" }
diff --git a/ios/chrome/browser/signin/fake_oauth2_token_service_builder.mm b/ios/chrome/browser/signin/fake_oauth2_token_service_builder.mm index a7735d82d..5d90b36 100644 --- a/ios/chrome/browser/signin/fake_oauth2_token_service_builder.mm +++ b/ios/chrome/browser/signin/fake_oauth2_token_service_builder.mm
@@ -6,10 +6,10 @@ #include "base/memory/ptr_util.h" #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" -#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_delegate.h" -#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h" +#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/signin/account_tracker_service_factory.h" +#include "ios/chrome/browser/signin/profile_oauth2_token_service_ios_provider_impl.h" #include "ios/chrome/browser/signin/signin_client_factory.h" #include "ios/chrome/browser/signin/signin_error_controller_factory.h" @@ -18,9 +18,9 @@ ios::ChromeBrowserState* browser_state = ios::ChromeBrowserState::FromBrowserState(context); OAuth2TokenServiceDelegate* delegate = - new FakeProfileOAuth2TokenServiceIOSDelegate( + new ProfileOAuth2TokenServiceIOSDelegate( SigninClientFactory::GetForBrowserState(browser_state), - base::MakeUnique<FakeProfileOAuth2TokenServiceIOSProvider>(), + base::MakeUnique<ProfileOAuth2TokenServiceIOSProviderImpl>(), ios::AccountTrackerServiceFactory::GetForBrowserState(browser_state), ios::SigninErrorControllerFactory::GetForBrowserState(browser_state)); return base::WrapUnique(new FakeProfileOAuth2TokenService(delegate));
diff --git a/ios/chrome/browser/ui/webui/history/browsing_history_handler.cc b/ios/chrome/browser/ui/webui/history/browsing_history_handler.cc index 5b5b8d5..ff0cf8e 100644 --- a/ios/chrome/browser/ui/webui/history/browsing_history_handler.cc +++ b/ios/chrome/browser/ui/webui/history/browsing_history_handler.cc
@@ -801,7 +801,11 @@ exploded.day_of_month = 1; if (offset == 0) { - options->begin_time = base::Time::FromLocalExploded(exploded); + if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) { + // This file will be deprecated soon. No need to implement failure + // handling here. + NOTIMPLEMENTED(); + } // Set the end time of this first search to null (which will // show results from the future, should the user's clock have @@ -815,12 +819,20 @@ exploded.month -= offset - 1; // Set the correct year. NormalizeMonths(&exploded); - options->end_time = base::Time::FromLocalExploded(exploded); + if (!base::Time::FromLocalExploded(exploded, &options->end_time)) { + // This file will be deprecated soon. No need to implement failure + // handling here. + NOTIMPLEMENTED(); + } exploded.month -= 1; // Set the correct year NormalizeMonths(&exploded); - options->begin_time = base::Time::FromLocalExploded(exploded); + if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) { + // This file will be deprecated soon. No need to implement failure + // handling here. + NOTIMPLEMENTED(); + } } }
diff --git a/ios/chrome/tools/strings/generate_localizable_strings.mm b/ios/chrome/tools/strings/generate_localizable_strings.mm index 95e733f..cec1154 100644 --- a/ios/chrome/tools/strings/generate_localizable_strings.mm +++ b/ios/chrome/tools/strings/generate_localizable_strings.mm
@@ -88,22 +88,15 @@ return nil; } -NSString* EscapeStringForLocalizableStrings(NSString* string) { - NSString* slashEscapedString = - [string stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; - return [slashEscapedString stringByReplacingOccurrencesOfString:@"\"" - withString:@"\\\""]; -} - -// Generate the content of the Localizable.string file for |locale| from the -// resource data pack |data_pack|. The content should have the format of: -// "IDS_PRINT_TO_PHONE" = "Print to phone jobs are available."; -// "IDS_SNAPSHOTS" = "Snapshots are available."; -NSString* GenerateLocalizableStringsFileContent(const ui::DataPack& data_pack, - const char* locale, - NSArray* resources, - NSDictionary* resources_ids) { - NSMutableString* localizable_strings = [NSMutableString string]; +// Generates a NSDictionary mapping string IDs to localized strings. The +// dictionary can be written as a Property List (only contains types that +// are valid in Propery Lists). +NSDictionary* GenerateLocalizableStringsDictionary( + const ui::DataPack& data_pack, + const char* locale, + NSArray* resources, + NSDictionary* resources_ids) { + NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; for (id resource : resources) { NSString* resource_name = nil; NSString* resource_output_name = nil; @@ -128,10 +121,7 @@ [[resources_ids objectForKey:resource_name] integerValue]; NSString* string = GetStringFromDataPack(data_pack, resource_id); if (string) { - const char* output_string_name = [resource_output_name UTF8String]; - [localizable_strings - appendFormat:@" \"%s\" = \"%@\";\n", output_string_name, - EscapeStringForLocalizableStrings(string)]; + [dictionary setObject:string forKey:resource_output_name]; } else { fprintf(stderr, "ERROR: fail to load string '%s' for locale '%s'\n", [resource_name UTF8String], locale); @@ -139,7 +129,7 @@ } } - return localizable_strings; + return dictionary; } NSDictionary* LoadResourcesListFromHeaders(NSArray* header_list, @@ -199,12 +189,12 @@ return resources_ids; } -// Save |localizable_strings| with |locale| to -// |output_dir|/|locale|.lproj/|output_filename|. -bool SaveLocalizableFile(NSString* localizable_strings, - NSString* locale, - NSString* output_dir, - NSString* output_filename) { +// Save |dictionary| as a Property List file (in binary1 encoding) +// with |locale| to |output_dir|/|locale|.lproj/|output_filename|. +bool SavePropertyList(NSDictionary* dictionary, + NSString* locale, + NSString* output_dir, + NSString* output_filename) { // Compute the path to the output directory with locale. NSString* output_path = [output_dir stringByAppendingPathComponent:[NSString @@ -222,12 +212,22 @@ return false; } + // Convert to property list in binary format. + NSError* error = nil; + NSData* data = [NSPropertyListSerialization + dataWithPropertyList:dictionary + format:NSPropertyListBinaryFormat_v1_0 + options:0 + error:&error]; + if (!data) { + fprintf(stderr, "ERROR: conversion to property list failed: %s\n", + [[error localizedDescription] UTF8String]); + return false; + } + // Save the strings to the disk. output_path = [output_path stringByAppendingPathComponent:output_filename]; - if (![localizable_strings writeToFile:output_path - atomically:YES - encoding:NSUTF16StringEncoding - error:nil]) { + if (![data writeToFile:output_path atomically:YES]) { fprintf(stderr, "ERROR: Failed to write out '%s'\n", [output_filename UTF8String]); return false; @@ -358,11 +358,10 @@ exit(1); } - NSString* localizable_strings = GenerateLocalizableStringsFileContent( + NSDictionary* dictionary = GenerateLocalizableStringsDictionary( *data_pack, [locale UTF8String], output_strings, resources_ids); - if (localizable_strings) { - SaveLocalizableFile(localizable_strings, locale, output_dir, - output_name); + if (dictionary) { + SavePropertyList(dictionary, locale, output_dir, output_name); } else { fprintf(stderr, "ERROR: Unable to create %s.\n", [output_name UTF8String]);
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc index fe2b61b..e8eeec6d 100644 --- a/ipc/ipc_sync_channel.cc +++ b/ipc/ipc_sync_channel.cc
@@ -13,10 +13,10 @@ #include "base/lazy_instance.h" #include "base/location.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" -#include "base/synchronization/waitable_event_watcher.h" #include "base/threading/thread_local.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" @@ -24,12 +24,49 @@ #include "ipc/ipc_logging.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_sync_message.h" +#include "ipc/mojo_event.h" +#include "mojo/public/cpp/bindings/sync_handle_registry.h" -using base::TimeDelta; -using base::TimeTicks; using base::WaitableEvent; namespace IPC { + +namespace { + +// A generic callback used when watching handles synchronously. Sets |*signal| +// to true. Also sets |*error| to true in case of an error. +void OnSyncHandleReady(bool* signal, bool* error, MojoResult result) { + *signal = true; + *error = result != MOJO_RESULT_OK; +} + +// A ReadyCallback for use with mojo::Watcher. Ignores the result (DCHECKs, but +// is only used in cases where failure should be impossible) and runs +// |callback|. +void RunOnHandleReady(const base::Closure& callback, MojoResult result) { + DCHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_ABORTED); + if (result == MOJO_RESULT_OK) + callback.Run(); +} + +class PumpMessagesEvent { + public: + PumpMessagesEvent() { event_.Signal(); } + ~PumpMessagesEvent() {} + + const MojoEvent* event() const { return &event_; } + + private: + MojoEvent event_; + + DISALLOW_COPY_AND_ASSIGN(PumpMessagesEvent); +}; + +base::LazyInstance<PumpMessagesEvent>::Leaky g_pump_messages_event = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + // When we're blocked in a Send(), we need to process incoming synchronous // messages right away because it could be blocking our reply (either // directly from the same object we're calling, or indirectly through one or @@ -156,7 +193,7 @@ } } - WaitableEvent* dispatch_event() { return &dispatch_event_; } + MojoEvent* dispatch_event() { return &dispatch_event_; } base::SingleThreadTaskRunner* listener_task_runner() { return listener_task_runner_.get(); } @@ -178,11 +215,11 @@ } } - base::WaitableEventWatcher* top_send_done_watcher() { + mojo::Watcher* top_send_done_watcher() { return top_send_done_watcher_; } - void set_top_send_done_watcher(base::WaitableEventWatcher* watcher) { + void set_top_send_done_watcher(mojo::Watcher* watcher) { top_send_done_watcher_ = watcher; } @@ -193,8 +230,6 @@ // as manual reset. ReceivedSyncMsgQueue() : message_queue_version_(0), - dispatch_event_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), listener_task_runner_(base::ThreadTaskRunnerHandle::Get()), task_pending_(false), listener_count_(0), @@ -215,19 +250,19 @@ std::vector<QueuedMessage> received_replies_; - // Set when we got a synchronous message that we must respond to as the + // Signaled when we get a synchronous message that we must respond to, as the // sender needs its reply before it can reply to our original synchronous // message. - WaitableEvent dispatch_event_; + MojoEvent dispatch_event_; scoped_refptr<base::SingleThreadTaskRunner> listener_task_runner_; base::Lock message_lock_; bool task_pending_; int listener_count_; - // The current send done event watcher for this thread. Used to maintain - // a local global stack of send done watchers to ensure that nested sync + // The current send done handle watcher for this thread. Used to maintain + // a thread-local stack of send done watchers to ensure that nested sync // message loops complete correctly. - base::WaitableEventWatcher* top_send_done_watcher_; + mojo::Watcher* top_send_done_watcher_; }; base::LazyInstance<base::ThreadLocalPointer<SyncChannel::ReceivedSyncMsgQueue> > @@ -250,9 +285,9 @@ } // Adds information about an outgoing sync message to the context so that -// we know how to deserialize the reply. Returns a handle that's set when -// the reply has arrived. -void SyncChannel::SyncContext::Push(SyncMessage* sync_msg) { +// we know how to deserialize the reply. Returns |true| if the message was added +// to the context or |false| if it was rejected (e.g. due to shutdown.) +bool SyncChannel::SyncContext::Push(SyncMessage* sync_msg) { // Create the tracking information for this message. This object is stored // by value since all members are pointers that are cheap to copy. These // pointers are cleaned up in the Pop() function. @@ -261,12 +296,14 @@ // OnObjectSignalled, another Send can happen which would stop the watcher // from being called. The event would get watched later, when the nested // Send completes, so the event will need to remain set. + base::AutoLock auto_lock(deserializers_lock_); + if (reject_new_deserializers_) + return false; PendingSyncMsg pending( SyncMessage::GetMessageId(*sync_msg), sync_msg->GetReplyDeserializer(), - new WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED)); - base::AutoLock auto_lock(deserializers_lock_); + new MojoEvent); deserializers_.push_back(pending); + return true; } bool SyncChannel::SyncContext::Pop() { @@ -276,7 +313,7 @@ PendingSyncMsg msg = deserializers_.back(); delete msg.deserializer; delete msg.done_event; - msg.done_event = NULL; + msg.done_event = nullptr; deserializers_.pop_back(); result = msg.send_result; } @@ -293,12 +330,12 @@ return result; } -WaitableEvent* SyncChannel::SyncContext::GetSendDoneEvent() { +MojoEvent* SyncChannel::SyncContext::GetSendDoneEvent() { base::AutoLock auto_lock(deserializers_lock_); return deserializers_.back().done_event; } -WaitableEvent* SyncChannel::SyncContext::GetDispatchEvent() { +MojoEvent* SyncChannel::SyncContext::GetDispatchEvent() { return received_sync_msgs_->dispatch_event(); } @@ -322,7 +359,7 @@ DVLOG(1) << "Received error reply"; } - base::WaitableEvent* done_event = deserializers_.back().done_event; + MojoEvent* done_event = deserializers_.back().done_event; TRACE_EVENT_FLOW_BEGIN0( TRACE_DISABLED_BY_DEFAULT("ipc.flow"), "SyncChannel::SyncContext::TryToUnblockListener", done_event); @@ -368,7 +405,7 @@ void SyncChannel::SyncContext::OnChannelOpened() { shutdown_watcher_.StartWatching( shutdown_event_, - base::Bind(&SyncChannel::SyncContext::OnWaitableEventSignaled, + base::Bind(&SyncChannel::SyncContext::OnShutdownEventSignaled, base::Unretained(this))); Context::OnChannelOpened(); } @@ -381,6 +418,7 @@ void SyncChannel::SyncContext::CancelPendingSends() { base::AutoLock auto_lock(deserializers_lock_); + reject_new_deserializers_ = true; PendingSyncMessageQueue::iterator iter; DVLOG(1) << "Canceling pending sends"; for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) { @@ -391,21 +429,12 @@ } } -void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) { - if (event == shutdown_event_) { - // Process shut down before we can get a reply to a synchronous message. - // Cancel pending Send calls, which will end up setting the send done event. - CancelPendingSends(); - } else { - // We got the reply, timed out or the process shutdown. - DCHECK_EQ(GetSendDoneEvent(), event); - base::MessageLoop::current()->QuitNow(); - } -} +void SyncChannel::SyncContext::OnShutdownEventSignaled(WaitableEvent* event) { + DCHECK_EQ(event, shutdown_event_); -base::WaitableEventWatcher::EventCallback - SyncChannel::SyncContext::MakeWaitableEventCallback() { - return base::Bind(&SyncChannel::SyncContext::OnWaitableEventSignaled, this); + // Process shut down before we can get a reply to a synchronous message. + // Cancel pending Send calls, which will end up setting the send done event. + CancelPendingSends(); } // static @@ -448,7 +477,8 @@ Listener* listener, const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, WaitableEvent* shutdown_event) - : ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)) { + : ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)), + sync_handle_registry_(mojo::SyncHandleRegistry::current()) { // The current (listener) thread must be distinct from the IPC thread, or else // sending synchronous messages will deadlock. DCHECK_NE(ipc_task_runner.get(), base::ThreadTaskRunnerHandle::Get().get()); @@ -487,23 +517,23 @@ return true; } + SyncMessage* sync_msg = static_cast<SyncMessage*>(message); + bool pump_messages = sync_msg->ShouldPumpMessages(); + // *this* might get deleted in WaitForReply. scoped_refptr<SyncContext> context(sync_context()); - if (context->shutdown_event()->IsSignaled()) { - DVLOG(1) << "shutdown event is signaled"; + if (!context->Push(sync_msg)) { + DVLOG(1) << "Channel is shutting down. Dropping sync message."; delete message; return false; } - SyncMessage* sync_msg = static_cast<SyncMessage*>(message); - context->Push(sync_msg); - WaitableEvent* pump_messages_event = sync_msg->pump_messages_event(); - ChannelProxy::Send(message); // Wait for reply, or for any other incoming synchronous messages. // *this* might get deleted, so only call static functions at this point. - WaitForReply(context.get(), pump_messages_event); + scoped_refptr<mojo::SyncHandleRegistry> registry = sync_handle_registry_; + WaitForReply(registry.get(), context.get(), pump_messages); TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), "SyncChannel::Send", context->GetSendDoneEvent()); @@ -511,19 +541,43 @@ return context->Pop(); } -void SyncChannel::WaitForReply( - SyncContext* context, WaitableEvent* pump_messages_event) { +void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry, + SyncContext* context, + bool pump_messages) { context->DispatchMessages(); - while (true) { - WaitableEvent* objects[] = { - context->GetDispatchEvent(), - context->GetSendDoneEvent(), - pump_messages_event - }; - unsigned count = pump_messages_event ? 3: 2; - size_t result = WaitableEvent::WaitMany(objects, count); - if (result == 0 /* dispatch event */) { + const MojoEvent* pump_messages_event = nullptr; + if (pump_messages) + pump_messages_event = g_pump_messages_event.Get().event(); + + while (true) { + bool dispatch = false; + bool send_done = false; + bool should_pump_messages = false; + bool error = false; + registry->RegisterHandle(context->GetDispatchEvent()->GetHandle(), + MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&OnSyncHandleReady, &dispatch, &error)); + registry->RegisterHandle( + context->GetSendDoneEvent()->GetHandle(), + MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&OnSyncHandleReady, &send_done, &error)); + if (pump_messages_event) { + registry->RegisterHandle( + pump_messages_event->GetHandle(), MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&OnSyncHandleReady, &should_pump_messages, &error)); + } + + const bool* stop_flags[] = { &dispatch, &send_done, &should_pump_messages }; + registry->WatchAllHandles(stop_flags, 3); + DCHECK(!error); + + registry->UnregisterHandle(context->GetDispatchEvent()->GetHandle()); + registry->UnregisterHandle(context->GetSendDoneEvent()->GetHandle()); + if (pump_messages_event) + registry->UnregisterHandle(pump_messages_event->GetHandle()); + + if (dispatch) { // We're waiting for a reply, but we received a blocking synchronous // call. We must process it or otherwise a deadlock might occur. context->GetDispatchEvent()->Reset(); @@ -531,7 +585,7 @@ continue; } - if (result == 2 /* pump_messages_event */) + if (should_pump_messages) WaitForReplyWithNestedMessageLoop(context); // Run a nested message loop. break; @@ -539,64 +593,59 @@ } void SyncChannel::WaitForReplyWithNestedMessageLoop(SyncContext* context) { - base::WaitableEventWatcher send_done_watcher; + mojo::Watcher send_done_watcher; ReceivedSyncMsgQueue* sync_msg_queue = context->received_sync_msgs(); - DCHECK(sync_msg_queue != NULL); + DCHECK_NE(sync_msg_queue, nullptr); - base::WaitableEventWatcher* old_send_done_event_watcher = - sync_msg_queue->top_send_done_watcher(); + mojo::Watcher* old_watcher = sync_msg_queue->top_send_done_watcher(); + mojo::Handle old_handle(mojo::kInvalidHandleValue); + mojo::Watcher::ReadyCallback old_callback; - base::WaitableEventWatcher::EventCallback old_callback; - base::WaitableEvent* old_event = NULL; - - // Maintain a local global stack of send done delegates to ensure that - // nested sync calls complete in the correct sequence, i.e. the - // outermost call completes first, etc. - if (old_send_done_event_watcher) { - old_callback = old_send_done_event_watcher->callback(); - old_event = old_send_done_event_watcher->GetWatchedEvent(); - old_send_done_event_watcher->StopWatching(); + // Maintain a thread-local stack of watchers to ensure nested calls complete + // in the correct sequence, i.e. the outermost call completes first, etc. + if (old_watcher) { + old_callback = old_watcher->ready_callback(); + old_handle = old_watcher->handle(); + old_watcher->Cancel(); } sync_msg_queue->set_top_send_done_watcher(&send_done_watcher); - send_done_watcher.StartWatching(context->GetSendDoneEvent(), - context->MakeWaitableEventCallback()); - { + base::RunLoop nested_loop; + send_done_watcher.Start( + context->GetSendDoneEvent()->GetHandle(), MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&RunOnHandleReady, nested_loop.QuitClosure())); + base::MessageLoop::ScopedNestableTaskAllower allow( base::MessageLoop::current()); - base::RunLoop().Run(); + nested_loop.Run(); + send_done_watcher.Cancel(); } - sync_msg_queue->set_top_send_done_watcher(old_send_done_event_watcher); - if (old_send_done_event_watcher && old_event) { - old_send_done_event_watcher->StartWatching(old_event, old_callback); - } + sync_msg_queue->set_top_send_done_watcher(old_watcher); + if (old_watcher) + old_watcher->Start(old_handle, MOJO_HANDLE_SIGNAL_READABLE, old_callback); } -void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) { - DCHECK(event == sync_context()->GetDispatchEvent()); - // The call to DispatchMessages might delete this object, so reregister - // the object watcher first. - event->Reset(); - dispatch_watcher_.StartWatching(event, dispatch_watcher_callback_); - sync_context()->DispatchMessages(); +void SyncChannel::OnDispatchHandleReady(MojoResult result) { + DCHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_ABORTED); + if (result == MOJO_RESULT_OK) { + sync_context()->GetDispatchEvent()->Reset(); + sync_context()->DispatchMessages(); + } } void SyncChannel::StartWatching() { // Ideally we only want to watch this object when running a nested message // loop. However, we don't know when it exits if there's another nested // message loop running under it or not, so we wouldn't know whether to - // stop or keep watching. So we always watch it, and create the event as - // manual reset since the object watcher might otherwise reset the event - // when we're doing a WaitMany. - dispatch_watcher_callback_ = - base::Bind(&SyncChannel::OnWaitableEventSignaled, - base::Unretained(this)); - dispatch_watcher_.StartWatching(sync_context()->GetDispatchEvent(), - dispatch_watcher_callback_); + // stop or keep watching. So we always watch it. + dispatch_watcher_.Start(sync_context()->GetDispatchEvent()->GetHandle(), + MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&SyncChannel::OnDispatchHandleReady, + base::Unretained(this))); } void SyncChannel::OnChannelInit() {
diff --git a/ipc/ipc_sync_channel.h b/ipc/ipc_sync_channel.h index 103925a..e8c96d20 100644 --- a/ipc/ipc_sync_channel.h +++ b/ipc/ipc_sync_channel.h
@@ -18,15 +18,23 @@ #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_sync_message.h" #include "ipc/ipc_sync_message_filter.h" +#include "mojo/public/c/system/types.h" +#include "mojo/public/cpp/system/watcher.h" namespace base { class WaitableEvent; }; +namespace mojo { +class SyncHandleRegistry; +class Watcher; +} + namespace IPC { -class SyncMessage; class ChannelFactory; +class MojoEvent; +class SyncMessage; // This is similar to ChannelProxy, with the added feature of supporting sending // synchronous messages. @@ -136,19 +144,19 @@ // Adds information about an outgoing sync message to the context so that // we know how to deserialize the reply. - void Push(SyncMessage* sync_msg); + bool Push(SyncMessage* sync_msg); // Cleanly remove the top deserializer (and throw it away). Returns the // result of the Send call for that message. bool Pop(); - // Returns an event that's set when the send is complete, timed out or the - // process shut down. - base::WaitableEvent* GetSendDoneEvent(); + // Returns a Mojo Event that signals when a sync send is complete or timed + // out or the process shut down. + MojoEvent* GetSendDoneEvent(); - // Returns an event that's set when an incoming message that's not the reply - // needs to get dispatched (by calling SyncContext::DispatchMessages). - base::WaitableEvent* GetDispatchEvent(); + // Returns a Mojo Event that signals when an incoming message that's not the + // pending reply needs to get dispatched (by calling DispatchMessages.) + MojoEvent* GetDispatchEvent(); void DispatchMessages(); @@ -171,8 +179,6 @@ return restrict_dispatch_group_; } - base::WaitableEventWatcher::EventCallback MakeWaitableEventCallback(); - private: ~SyncContext() override; // ChannelProxy methods that we override. @@ -189,10 +195,11 @@ // Cancels all pending Send calls. void CancelPendingSends(); - void OnWaitableEventSignaled(base::WaitableEvent* event); + void OnShutdownEventSignaled(base::WaitableEvent* event); typedef std::deque<PendingSyncMsg> PendingSyncMessageQueue; PendingSyncMessageQueue deserializers_; + bool reject_new_deserializers_ = false; base::Lock deserializers_lock_; scoped_refptr<ReceivedSyncMsgQueue> received_sync_msgs_; @@ -209,7 +216,7 @@ const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, base::WaitableEvent* shutdown_event); - void OnWaitableEventSignaled(base::WaitableEvent* arg); + void OnDispatchHandleReady(MojoResult result); SyncContext* sync_context() { return reinterpret_cast<SyncContext*>(context()); @@ -217,8 +224,9 @@ // Both these functions wait for a reply, timeout or process shutdown. The // latter one also runs a nested message loop in the meantime. - static void WaitForReply( - SyncContext* context, base::WaitableEvent* pump_messages_event); + static void WaitForReply(mojo::SyncHandleRegistry* registry, + SyncContext* context, + bool pump_messages); // Runs a nested message loop until a reply arrives, times out, or the process // shuts down. @@ -230,9 +238,10 @@ // ChannelProxy overrides: void OnChannelInit() override; + scoped_refptr<mojo::SyncHandleRegistry> sync_handle_registry_; + // Used to signal events between the IPC and listener threads. - base::WaitableEventWatcher dispatch_watcher_; - base::WaitableEventWatcher::EventCallback dispatch_watcher_callback_; + mojo::Watcher dispatch_watcher_; // Tracks SyncMessageFilters created before complete channel initialization. std::vector<scoped_refptr<SyncMessageFilter>> pre_init_sync_message_filters_;
diff --git a/ipc/ipc_sync_message.cc b/ipc/ipc_sync_message.cc index 7f9df7bd..ba87de8 100644 --- a/ipc/ipc_sync_message.cc +++ b/ipc/ipc_sync_message.cc
@@ -9,26 +9,11 @@ #include <stack> #include "base/atomic_sequence_num.h" -#include "base/lazy_instance.h" #include "base/logging.h" -#include "base/synchronization/waitable_event.h" #include "build/build_config.h" namespace { -struct WaitableEventLazyInstanceTraits - : public base::DefaultLazyInstanceTraits<base::WaitableEvent> { - static base::WaitableEvent* New(void* instance) { - // Use placement new to initialize our instance in our preallocated space. - return new (instance) - base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::SIGNALED); - } -}; - -base::LazyInstance<base::WaitableEvent, WaitableEventLazyInstanceTraits> - dummy_event = LAZY_INSTANCE_INITIALIZER; - base::StaticAtomicSequenceNumber g_next_id; } // namespace @@ -42,8 +27,7 @@ PriorityValue priority, MessageReplyDeserializer* deserializer) : Message(routing_id, type, priority), - deserializer_(deserializer), - pump_messages_event_(NULL) { + deserializer_(deserializer) { set_sync(); set_unblock(true); @@ -61,11 +45,6 @@ return deserializer_.release(); } -void SyncMessage::EnableMessagePumping() { - DCHECK(!pump_messages_event_); - set_pump_messages_event(dummy_event.Pointer()); -} - bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) { if (!msg.is_reply()) return false;
diff --git a/ipc/ipc_sync_message.h b/ipc/ipc_sync_message.h index cb259b1..ed5204f 100644 --- a/ipc/ipc_sync_message.h +++ b/ipc/ipc_sync_message.h
@@ -17,13 +17,10 @@ #include "build/build_config.h" #include "ipc/ipc_message.h" -namespace base { -class WaitableEvent; -} - namespace IPC { class MessageReplyDeserializer; +class MojoEvent; class IPC_EXPORT SyncMessage : public Message { public: @@ -41,24 +38,16 @@ // If this message can cause the receiver to block while waiting for user // input (i.e. by calling MessageBox), then the caller needs to pump window // messages and dispatch asynchronous messages while waiting for the reply. - // If this event is passed in, then window messages will start being pumped - // when it's set. Note that this behavior will continue even if the event is - // later reset. The event must be valid until after the Send call returns. - void set_pump_messages_event(base::WaitableEvent* event) { - pump_messages_event_ = event; - if (event) { - header()->flags |= PUMPING_MSGS_BIT; - } else { - header()->flags &= ~PUMPING_MSGS_BIT; - } + // This call enables message pumping behavior while waiting for a reply to + // this message. + void EnableMessagePumping() { + header()->flags |= PUMPING_MSGS_BIT; } - // Call this if you always want to pump messages. You can call this method - // or set_pump_messages_event but not both. - void EnableMessagePumping(); - - base::WaitableEvent* pump_messages_event() const { - return pump_messages_event_; + // Indicates whether window messages should be pumped while waiting for a + // reply to this message. + bool ShouldPumpMessages() const { + return (header()->flags & PUMPING_MSGS_BIT) != 0; } // Returns true if the message is a reply to the given request id. @@ -84,7 +73,6 @@ static bool WriteSyncHeader(Message* msg, const SyncHeader& header); std::unique_ptr<MessageReplyDeserializer> deserializer_; - base::WaitableEvent* pump_messages_event_; }; // Used to deserialize parameters from a reply to a synchronous message @@ -102,13 +90,12 @@ // When sending a synchronous message, this structure contains an object // that knows how to deserialize the response. struct PendingSyncMsg { - PendingSyncMsg(int id, - MessageReplyDeserializer* d, - base::WaitableEvent* e) + PendingSyncMsg(int id, MessageReplyDeserializer* d, MojoEvent* e) : id(id), deserializer(d), done_event(e), send_result(false) { } + int id; MessageReplyDeserializer* deserializer; - base::WaitableEvent* done_event; + MojoEvent* done_event; bool send_result; };
diff --git a/ipc/ipc_sync_message_filter.cc b/ipc/ipc_sync_message_filter.cc index 1d17432..53ead2c 100644 --- a/ipc/ipc_sync_message_filter.cc +++ b/ipc/ipc_sync_message_filter.cc
@@ -7,14 +7,94 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_sync_message.h" +#include "ipc/mojo_event.h" +#include "mojo/public/cpp/bindings/sync_handle_registry.h" namespace IPC { +namespace { + +// A generic callback used when watching handles synchronously. Sets |*signal| +// to true. Also sets |*error| to true in case of an error. +void OnSyncHandleReady(bool* signal, bool* error, MojoResult result) { + *signal = true; + *error = result != MOJO_RESULT_OK; +} + +} // namespace + +// A helper class created by SyncMessageFilter to watch the lifetime of the IO +// MessageLoop. This holds a weak ref to the SyncMessageFilter and notifies it +// on its own thread if the SyncMessageFilter is still alive at the time of +// IO MessageLoop destruction. +class SyncMessageFilter::IOMessageLoopObserver + : public base::MessageLoop::DestructionObserver, + public base::RefCountedThreadSafe<IOMessageLoopObserver> { + public: + IOMessageLoopObserver( + base::WeakPtr<SyncMessageFilter> weak_filter, + scoped_refptr<base::SingleThreadTaskRunner> filter_task_runner) + : weak_filter_(weak_filter), filter_task_runner_(filter_task_runner) {} + + void StartOnIOThread() { + DCHECK(!watching_); + watching_ = true; + io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + base::MessageLoop::current()->AddDestructionObserver(this); + } + + void Stop() { + if (!io_task_runner_) + return; + + if (io_task_runner_->BelongsToCurrentThread()) { + StopOnIOThread(); + } else { + io_task_runner_->PostTask( + FROM_HERE, base::Bind(&IOMessageLoopObserver::StopOnIOThread, this)); + } + } + + private: + void StopOnIOThread() { + DCHECK(io_task_runner_->BelongsToCurrentThread()); + if (!watching_) + return; + watching_ = false; + base::MessageLoop::current()->RemoveDestructionObserver(this); + } + + // base::MessageLoop::DestructionObserver: + void WillDestroyCurrentMessageLoop() override { + DCHECK(io_task_runner_ && io_task_runner_->BelongsToCurrentThread()); + DCHECK(watching_); + StopOnIOThread(); + filter_task_runner_->PostTask( + FROM_HERE, + base::Bind(&SyncMessageFilter::OnIOMessageLoopDestroyed, weak_filter_)); + } + + friend class base::RefCountedThreadSafe<IOMessageLoopObserver>; + + ~IOMessageLoopObserver() override {} + + bool watching_ = false; + base::WeakPtr<SyncMessageFilter> weak_filter_; + scoped_refptr<base::SingleThreadTaskRunner> filter_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(IOMessageLoopObserver); +}; + bool SyncMessageFilter::Send(Message* message) { if (!message->is_sync()) { { @@ -23,7 +103,7 @@ sender_->Send(message); return true; } else if (!io_task_runner_.get()) { - pending_messages_.push_back(message); + pending_messages_.emplace_back(base::WrapUnique(message)); return true; } } @@ -33,9 +113,7 @@ return true; } - base::WaitableEvent done_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); + MojoEvent done_event; PendingSyncMsg pending_message( SyncMessage::GetMessageId(*message), static_cast<SyncMessage*>(message)->GetReplyDeserializer(), @@ -56,15 +134,32 @@ FROM_HERE, base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); } else { - pending_messages_.push_back(message); + pending_messages_.emplace_back(base::WrapUnique(message)); } } - base::WaitableEvent* events[2] = { shutdown_event_, &done_event }; - if (base::WaitableEvent::WaitMany(events, 2) == 1) { + bool done = false; + bool shutdown = false; + bool error = false; + scoped_refptr<mojo::SyncHandleRegistry> registry = + mojo::SyncHandleRegistry::current(); + registry->RegisterHandle(shutdown_mojo_event_.GetHandle(), + MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&OnSyncHandleReady, &shutdown, &error)); + registry->RegisterHandle(done_event.GetHandle(), + MOJO_HANDLE_SIGNAL_READABLE, + base::Bind(&OnSyncHandleReady, &done, &error)); + + const bool* stop_flags[] = { &done, &shutdown }; + registry->WatchAllHandles(stop_flags, 2); + DCHECK(!error); + + if (done) { TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), "SyncMessageFilter::Send", &done_event); } + registry->UnregisterHandle(shutdown_mojo_event_.GetHandle()); + registry->UnregisterHandle(done_event.GetHandle()); { base::AutoLock auto_lock(lock_); @@ -76,26 +171,32 @@ } void SyncMessageFilter::OnFilterAdded(Sender* sender) { - std::vector<Message*> pending_messages; + std::vector<std::unique_ptr<Message>> pending_messages; { base::AutoLock auto_lock(lock_); sender_ = sender; io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - pending_messages_.release(&pending_messages); + shutdown_watcher_.StartWatching( + shutdown_event_, + base::Bind(&SyncMessageFilter::OnShutdownEventSignaled, this)); + io_message_loop_observer_->StartOnIOThread(); + std::swap(pending_messages_, pending_messages); } - for (auto* msg : pending_messages) - SendOnIOThread(msg); + for (auto& msg : pending_messages) + SendOnIOThread(msg.release()); } void SyncMessageFilter::OnChannelError() { base::AutoLock auto_lock(lock_); sender_ = NULL; + shutdown_watcher_.StopWatching(); SignalAllEvents(); } void SyncMessageFilter::OnChannelClosing() { base::AutoLock auto_lock(lock_); sender_ = NULL; + shutdown_watcher_.StopWatching(); SignalAllEvents(); } @@ -124,10 +225,14 @@ : sender_(NULL), is_channel_send_thread_safe_(is_channel_send_thread_safe), listener_task_runner_(base::ThreadTaskRunnerHandle::Get()), - shutdown_event_(shutdown_event) { + shutdown_event_(shutdown_event), + weak_factory_(this) { + io_message_loop_observer_ = new IOMessageLoopObserver( + weak_factory_.GetWeakPtr(), listener_task_runner_); } SyncMessageFilter::~SyncMessageFilter() { + io_message_loop_observer_->Stop(); } void SyncMessageFilter::SendOnIOThread(Message* message) { @@ -157,4 +262,17 @@ } } +void SyncMessageFilter::OnShutdownEventSignaled(base::WaitableEvent* event) { + DCHECK_EQ(event, shutdown_event_); + shutdown_mojo_event_.Signal(); +} + +void SyncMessageFilter::OnIOMessageLoopDestroyed() { + // Since we use an async WaitableEventWatcher to watch the shutdown event + // from the IO thread, we can't forward the shutdown signal after the IO + // message loop is destroyed. Since that destruction indicates shutdown + // anyway, we manually signal the shutdown event in this case. + shutdown_mojo_event_.Signal(); +} + } // namespace IPC
diff --git a/ipc/ipc_sync_message_filter.h b/ipc/ipc_sync_message_filter.h index 27584359..dead5b32 100644 --- a/ipc/ipc_sync_message_filter.h +++ b/ipc/ipc_sync_message_filter.h
@@ -6,14 +6,17 @@ #define IPC_IPC_SYNC_MESSAGE_FILTER_H_ #include <set> +#include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" +#include "base/synchronization/waitable_event_watcher.h" #include "ipc/ipc_sender.h" #include "ipc/ipc_sync_message.h" #include "ipc/message_filter.h" +#include "ipc/mojo_event.h" namespace base { class SingleThreadTaskRunner; @@ -46,7 +49,10 @@ ~SyncMessageFilter() override; private: + class IOMessageLoopObserver; + friend class SyncChannel; + friend class IOMessageLoopObserver; void set_is_channel_send_thread_safe(bool is_channel_send_thread_safe) { is_channel_send_thread_safe_ = is_channel_send_thread_safe; @@ -56,6 +62,9 @@ // Signal all the pending sends as done, used in an error condition. void SignalAllEvents(); + void OnShutdownEventSignaled(base::WaitableEvent* event); + void OnIOMessageLoopDestroyed(); + // The channel to which this filter was added. Sender* sender_; @@ -72,12 +81,24 @@ PendingSyncMessages pending_sync_messages_; // Messages waiting to be delivered after IO initialization. - ScopedVector<Message> pending_messages_; + std::vector<std::unique_ptr<Message>> pending_messages_; // Locks data members above. base::Lock lock_; - base::WaitableEvent* shutdown_event_; + base::WaitableEvent* const shutdown_event_; + + // Used to asynchronously watch |shutdown_event_| on the IO thread and forward + // to |shutdown_mojo_event_| (see below.) + base::WaitableEventWatcher shutdown_watcher_; + + // A Mojo event which can be watched for shutdown. Signals are forwarded to + // this event asynchronously from |shutdown_event_|. + MojoEvent shutdown_mojo_event_; + + scoped_refptr<IOMessageLoopObserver> io_message_loop_observer_; + + base::WeakPtrFactory<SyncMessageFilter> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SyncMessageFilter); };
diff --git a/mash/example/common/mus_views_init.h b/mash/example/common/mus_views_init.h index f92e703..a37d7b86 100644 --- a/mash/example/common/mus_views_init.h +++ b/mash/example/common/mus_views_init.h
@@ -13,8 +13,8 @@ #include "ui/views/mus/aura_init.h" #include "ui/views/views_delegate.h" -namespace mojo { -class ShellConnection; +namespace shell { +class ServiceContext; } namespace views { @@ -25,7 +25,7 @@ class MUSViewsInit : public views::ViewsDelegate, public ui::WindowTreeClientDelegate { public: - explicit MUSViewsInit(shell::ShellConnection* app); + explicit MUSViewsInit(shell::ServiceContext* app); ~MUSViewsInit() override; private: @@ -45,7 +45,7 @@ HICON GetSmallWindowIcon() const override; #endif - shell::ShellConnection* app_; + shell::ServiceContext* app_; std::unique_ptr<views::AuraInit> aura_init_; ui::mojom::WindowManagerPtr window_manager_;
diff --git a/mash/example/window_type_launcher/main.cc b/mash/example/window_type_launcher/main.cc index 170dc80..69097738 100644 --- a/mash/example/window_type_launcher/main.cc +++ b/mash/example/window_type_launcher/main.cc
@@ -16,7 +16,7 @@ #include "mash/example/window_type_launcher/window_type_launcher.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/process_delegate.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/public/interfaces/service.mojom.h" #include "services/shell/runner/common/client_util.h" #include "services/shell/runner/init.h" @@ -65,7 +65,7 @@ base::MessageLoop loop; WindowTypeLauncher delegate; - shell::ShellConnection impl(&delegate, + shell::ServiceContext impl(&delegate, shell::GetServiceRequestFromCommandLine()); loop.Run();
diff --git a/mash/quick_launch/quick_launch_application.cc b/mash/quick_launch/quick_launch_application.cc index f93baa2a..4db711cc 100644 --- a/mash/quick_launch/quick_launch_application.cc +++ b/mash/quick_launch/quick_launch_application.cc
@@ -16,7 +16,6 @@ #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" #include "services/tracing/public/cpp/tracing_impl.h" -#include "services/ui/common/gpu_service.h" #include "ui/views/background.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/controls/textfield/textfield_controller.h" @@ -168,7 +167,6 @@ const shell::Identity& identity, uint32_t id) { connector_ = connector; - ui::GpuService::Initialize(connector); tracing_.Initialize(connector, identity.name()); aura_init_.reset(new views::AuraInit(connector, "views_mus_resources.pak"));
diff --git a/media/blink/buffered_resource_loader.cc b/media/blink/buffered_resource_loader.cc index b608884..bb946cc 100644 --- a/media/blink/buffered_resource_loader.cc +++ b/media/blink/buffered_resource_loader.cc
@@ -728,8 +728,10 @@ int64_t* last_byte_position, int64_t* instance_size) { const std::string kUpThroughBytesUnit = "bytes "; - if (content_range_str.find(kUpThroughBytesUnit) != 0) + if (!base::StartsWith(content_range_str, kUpThroughBytesUnit, + base::CompareCase::SENSITIVE)) { return false; + } std::string range_spec = content_range_str.substr(kUpThroughBytesUnit.length()); size_t dash_offset = range_spec.find("-");
diff --git a/media/blink/cache_util_unittest.cc b/media/blink/cache_util_unittest.cc index a9c409e..1e7d45f 100644 --- a/media/blink/cache_util_unittest.cc +++ b/media/blink/cache_util_unittest.cc
@@ -35,7 +35,6 @@ // Create a new WebURLResponse object. static WebURLResponse CreateResponse(const GRFUTestCase& test) { WebURLResponse response; - response.initialize(); response.setHTTPVersion(test.version); response.setHTTPStatusCode(test.status_code); for (const std::string& line :
diff --git a/media/blink/resource_multibuffer_data_provider.cc b/media/blink/resource_multibuffer_data_provider.cc index e107270..d8f3458 100644 --- a/media/blink/resource_multibuffer_data_provider.cc +++ b/media/blink/resource_multibuffer_data_provider.cc
@@ -14,6 +14,7 @@ #include "base/metrics/histogram.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "media/blink/active_loader.h" #include "media/blink/cache_util.h" @@ -461,11 +462,13 @@ int64_t* first_byte_position, int64_t* last_byte_position, int64_t* instance_size) { - const std::string kUpThroughBytesUnit = "bytes "; - if (content_range_str.find(kUpThroughBytesUnit) != 0) + const char kUpThroughBytesUnit[] = "bytes "; + if (!base::StartsWith(content_range_str, kUpThroughBytesUnit, + base::CompareCase::SENSITIVE)) { return false; + } std::string range_spec = - content_range_str.substr(kUpThroughBytesUnit.length()); + content_range_str.substr(sizeof(kUpThroughBytesUnit) - 1); size_t dash_offset = range_spec.find("-"); size_t slash_offset = range_spec.find("/");
diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc index 35d8421bd..5b8c8567 100644 --- a/media/gpu/android_video_decode_accelerator.cc +++ b/media/gpu/android_video_decode_accelerator.cc
@@ -509,9 +509,7 @@ // Only use MediaCodec for VP8/9 if it's likely backed by hardware // or if the stream is encrypted. - if ((codec_config_->codec_ == kCodecVP8 || - codec_config_->codec_ == kCodecVP9) && - !config_.is_encrypted && + if (IsMediaCodecSoftwareDecodingForbidden() && VideoCodecBridge::IsKnownUnaccelerated(codec_config_->codec_, MEDIA_CODEC_DECODER)) { DVLOG(1) << "Initialization failed: " @@ -1097,6 +1095,15 @@ // outgoing codec for ReleaseMediaCodec(). codec_config_->allow_autodetection_ = g_avda_timer.Pointer()->IsCodecAutodetectionProbablySafe(); + + // If autodetection is disallowed, fall back to Chrome's software decoders + // instead of using the software decoders provided by MediaCodec. + if (!codec_config_->allow_autodetection_ && + IsMediaCodecSoftwareDecodingForbidden()) { + OnCodecConfigured(nullptr); + return; + } + codec_config_->notify_completion_ = codec_config_->allow_autodetection_; if (codec_config_->allow_autodetection_) g_avda_timer.Pointer()->OnAsyncCodecAutodetectionStarted(); @@ -1771,4 +1778,12 @@ return capabilities; } +bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() + const { + // Prevent MediaCodec from using its internal software decoders when we have + // more secure and up to date versions in the renderer process. + return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 || + codec_config_->codec_ == media::kCodecVP9); +} + } // namespace media
diff --git a/media/gpu/android_video_decode_accelerator.h b/media/gpu/android_video_decode_accelerator.h index 658c230..fd99ebc0 100644 --- a/media/gpu/android_video_decode_accelerator.h +++ b/media/gpu/android_video_decode_accelerator.h
@@ -367,6 +367,10 @@ static bool UseTextureCopyForDeferredStrategy( const gpu::GpuPreferences& gpu_preferences); + // Indicates if MediaCodec should not be used for software decoding since we + // have safer versions elsewhere. + bool IsMediaCodecSoftwareDecodingForbidden() const; + // Used to DCHECK that we are called on the correct thread. base::ThreadChecker thread_checker_;
diff --git a/media/gpu/vaapi_drm_picture.cc b/media/gpu/vaapi_drm_picture.cc index 4d547df..3de36d3 100644 --- a/media/gpu/vaapi_drm_picture.cc +++ b/media/gpu/vaapi_drm_picture.cc
@@ -43,6 +43,20 @@ } } +static unsigned BufferFormatToInternalFormat(gfx::BufferFormat format) { + switch (format) { + case gfx::BufferFormat::BGRA_8888: + return GL_BGRA_EXT; + + case gfx::BufferFormat::YVU_420: + return GL_RGB_YCRCB_420_CHROMIUM; + + default: + NOTREACHED(); + return GL_BGRA_EXT; + } +} + bool VaapiDrmPicture::Initialize() { DCHECK(pixmap_); @@ -61,9 +75,13 @@ gl::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES, texture_id_); + + gfx::BufferFormat format = pixmap_->GetBufferFormat(); + scoped_refptr<gl::GLImageOzoneNativePixmap> image( - new gl::GLImageOzoneNativePixmap(size_, GL_BGRA_EXT)); - if (!image->Initialize(pixmap_.get(), pixmap_->GetBufferFormat())) { + new gl::GLImageOzoneNativePixmap(size_, + BufferFormatToInternalFormat(format))); + if (!image->Initialize(pixmap_.get(), format)) { LOG(ERROR) << "Failed to create GLImage"; return false; }
diff --git a/media/gpu/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi_video_decode_accelerator.cc index 3d162ae..a92e757 100644 --- a/media/gpu/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi_video_decode_accelerator.cc
@@ -41,7 +41,8 @@ // Buffer format to use for output buffers backing PictureBuffers. This is the // format decoded frames in VASurfaces are converted into. -const gfx::BufferFormat kOutputPictureFormat = gfx::BufferFormat::BGRA_8888; +const gfx::BufferFormat kAllocatePictureFormat = gfx::BufferFormat::BGRA_8888; +const gfx::BufferFormat kImportPictureFormat = gfx::BufferFormat::YVU_420; } static void ReportToUMA(VAVDADecoderFailure failure) { @@ -310,6 +311,7 @@ finish_flush_pending_(false), awaiting_va_surfaces_recycle_(false), requested_num_pics_(0), + output_format_(kAllocatePictureFormat), make_context_current_cb_(make_context_current_cb), bind_image_cb_(bind_image_cb), weak_this_factory_(this) { @@ -331,9 +333,18 @@ return false; } - if (config.output_mode != Config::OutputMode::ALLOCATE && - config.output_mode != Config::OutputMode::IMPORT) { - NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; + switch (config.output_mode) { + case Config::OutputMode::ALLOCATE: + output_format_ = kAllocatePictureFormat; + break; + + case Config::OutputMode::IMPORT: + output_format_ = kImportPictureFormat; + break; + + default: + NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; + return false; } client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); @@ -642,6 +653,9 @@ case gfx::BufferFormat::BGRA_8888: return PIXEL_FORMAT_ARGB; + case gfx::BufferFormat::YVU_420: + return PIXEL_FORMAT_YV12; + default: LOG(FATAL) << "Add more cases as needed"; return PIXEL_FORMAT_UNKNOWN; @@ -687,8 +701,7 @@ DVLOG(1) << "Requesting " << requested_num_pics_ << " pictures of size: " << requested_pic_size_.ToString(); - VideoPixelFormat format = - BufferFormatToVideoPixelFormat(kOutputPictureFormat); + VideoPixelFormat format = BufferFormatToVideoPixelFormat(output_format_); task_runner_->PostTask( FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_, format, 1, requested_pic_size_, @@ -789,7 +802,7 @@ if (output_mode_ == Config::OutputMode::ALLOCATE) { RETURN_AND_NOTIFY_ON_FAILURE( - picture->Allocate(kOutputPictureFormat), + picture->Allocate(output_format_), "Failed to allocate memory for a VaapiPicture", PLATFORM_FAILURE, ); output_buffers_.push(buffers[i].id()); } @@ -827,13 +840,6 @@ return; } - if (gpu_memory_buffer_handle.native_pixmap_handle.fds.size() != 1) { - CloseGpuMemoryBufferHandle(gpu_memory_buffer_handle); - LOG(ERROR) << "Handles backed by multple fds unsupported"; - NotifyError(INVALID_ARGUMENT); - return; - } - VaapiPicture* picture = PictureById(picture_buffer_id); if (!picture) { CloseGpuMemoryBufferHandle(gpu_memory_buffer_handle); @@ -847,7 +853,7 @@ return; } - if (!picture->ImportGpuMemoryBufferHandle(kOutputPictureFormat, + if (!picture->ImportGpuMemoryBufferHandle(output_format_, gpu_memory_buffer_handle)) { // ImportGpuMemoryBufferHandle will close the handles even on failure, so // we don't need to do this ourselves.
diff --git a/media/gpu/vaapi_video_decode_accelerator.h b/media/gpu/vaapi_video_decode_accelerator.h index 819537f..8228a928 100644 --- a/media/gpu/vaapi_video_decode_accelerator.h +++ b/media/gpu/vaapi_video_decode_accelerator.h
@@ -305,9 +305,11 @@ // to be returned before we can free them. bool awaiting_va_surfaces_recycle_; - // Last requested number/resolution of output picture buffers. + // Last requested number/resolution of output picture buffers and their + // format. size_t requested_num_pics_; gfx::Size requested_pic_size_; + gfx::BufferFormat output_format_; // Callback to make GL context current. MakeGLContextCurrentCallback make_context_current_cb_;
diff --git a/media/gpu/vaapi_wrapper.cc b/media/gpu/vaapi_wrapper.cc index fa4a1c8..dcec8b9 100644 --- a/media/gpu/vaapi_wrapper.cc +++ b/media/gpu/vaapi_wrapper.cc
@@ -27,6 +27,7 @@ #elif defined(USE_OZONE) #include "third_party/libva/va/drm/va_drm.h" #include "third_party/libva/va/va_drmcommon.h" +#include "ui/gfx/buffer_format_util.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/surface_factory_ozone.h" #endif // USE_X11 @@ -71,6 +72,8 @@ return VA_FOURCC_BGRA; case gfx::BufferFormat::UYVY_422: return VA_FOURCC_UYVY; + case gfx::BufferFormat::YVU_420: + return VA_FOURCC_YV12; default: NOTREACHED(); return 0; @@ -84,6 +87,8 @@ case gfx::BufferFormat::BGRX_8888: case gfx::BufferFormat::BGRA_8888: return VA_RT_FORMAT_RGB32; + case gfx::BufferFormat::YVU_420: + return VA_RT_FORMAT_YUV420; default: NOTREACHED(); return 0; @@ -614,33 +619,49 @@ #if defined(USE_OZONE) scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap( const scoped_refptr<ui::NativePixmap>& pixmap) { - // Get the dmabuf of the created buffer. - int dmabuf_fd = pixmap->GetDmaBufFd(0); - if (dmabuf_fd < 0) { - LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; - return nullptr; - } - int dmabuf_pitch = pixmap->GetDmaBufPitch(0); - gfx::Size pixmap_size = pixmap->GetBufferSize(); - - // Create a VASurface out of the created buffer using the dmabuf. + // Create a VASurface for a NativePixmap by importing the underlying dmabufs. VASurfaceAttribExternalBuffers va_attrib_extbuf; memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf)); + va_attrib_extbuf.pixel_format = BufferFormatToVAFourCC(pixmap->GetBufferFormat()); - va_attrib_extbuf.width = pixmap_size.width(); - va_attrib_extbuf.height = pixmap_size.height(); - va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch; - va_attrib_extbuf.num_planes = 1; - va_attrib_extbuf.pitches[0] = dmabuf_pitch; - va_attrib_extbuf.offsets[0] = 0; - va_attrib_extbuf.buffers = reinterpret_cast<unsigned long*>(&dmabuf_fd); - va_attrib_extbuf.num_buffers = 1; + gfx::Size size = pixmap->GetBufferSize(); + va_attrib_extbuf.width = size.width(); + va_attrib_extbuf.height = size.height(); + + size_t num_fds = pixmap->GetDmaBufFdCount(); + size_t num_planes = + gfx::NumberOfPlanesForBufferFormat(pixmap->GetBufferFormat()); + if (num_fds == 0 || num_fds > num_planes) { + LOG(ERROR) << "Invalid number of dmabuf fds: " << num_fds + << " , planes: " << num_planes; + return nullptr; + } + + for (size_t i = 0; i < num_planes; ++i) { + va_attrib_extbuf.pitches[i] = pixmap->GetDmaBufPitch(i); + va_attrib_extbuf.offsets[i] = pixmap->GetDmaBufOffset(i); + DVLOG(4) << "plane " << i << ": pitch: " << va_attrib_extbuf.pitches[i] + << " offset: " << va_attrib_extbuf.offsets[i]; + } + va_attrib_extbuf.num_planes = num_planes; + + std::vector<unsigned long> fds(num_fds); + for (size_t i = 0; i < num_fds; ++i) { + int dmabuf_fd = pixmap->GetDmaBufFd(i); + if (dmabuf_fd < 0) { + LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; + return nullptr; + } + fds[i] = dmabuf_fd; + } + va_attrib_extbuf.buffers = fds.data(); + va_attrib_extbuf.num_buffers = fds.size(); + va_attrib_extbuf.flags = 0; va_attrib_extbuf.private_data = NULL; - std::vector<VASurfaceAttrib> va_attribs; - va_attribs.resize(2); + std::vector<VASurfaceAttrib> va_attribs(2); va_attribs[0].type = VASurfaceAttribMemoryType; va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; @@ -652,9 +673,8 @@ va_attribs[1].value.type = VAGenericValueTypePointer; va_attribs[1].value.value.p = &va_attrib_extbuf; - scoped_refptr<VASurface> va_surface = - CreateUnownedSurface(BufferFormatToVARTFormat(pixmap->GetBufferFormat()), - pixmap_size, va_attribs); + scoped_refptr<VASurface> va_surface = CreateUnownedSurface( + BufferFormatToVARTFormat(pixmap->GetBufferFormat()), size, va_attribs); if (!va_surface) { LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap"; return nullptr;
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc index 751b736..9dc0582 100644 --- a/media/midi/midi_manager_alsa.cc +++ b/media/midi/midi_manager_alsa.cc
@@ -269,7 +269,7 @@ out_client_.reset(out_client.release()); decoder_.reset(decoder.release()); udev_.reset(udev.release()); - udev_monitor_.reset(udev_monitor_.release()); + udev_monitor_.reset(udev_monitor.release()); // Generate hotplug events for existing ports. // TODO(agoode): Check the return value for failure.
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index ca03efc..dfe7bd1 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -160,7 +160,7 @@ "//media/mojo/clients", "//media/mojo/common", "//media/mojo/interfaces", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp/test:run_all_shelltests", "//testing/gmock", "//testing/gtest",
diff --git a/media/mojo/services/media_mojo_unittest.cc b/media/mojo/services/media_mojo_unittest.cc index db87a1f7..e9079e6 100644 --- a/media/mojo/services/media_mojo_unittest.cc +++ b/media/mojo/services/media_mojo_unittest.cc
@@ -20,7 +20,7 @@ #include "media/mojo/interfaces/decryptor.mojom.h" #include "media/mojo/interfaces/renderer.mojom.h" #include "media/mojo/interfaces/service_factory.mojom.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "testing/gmock/include/gmock/gmock.h" using testing::Exactly; @@ -54,20 +54,20 @@ DISALLOW_COPY_AND_ASSIGN(MockRendererClient); }; -class MediaShellTest : public shell::test::ShellTest { +class MediaServiceTest : public shell::test::ServiceTest { public: - MediaShellTest() - : ShellTest("exe:media_mojo_unittests"), + MediaServiceTest() + : ServiceTest("exe:media_mojo_unittests"), renderer_client_binding_(&renderer_client_), video_stream_(DemuxerStream::VIDEO) {} - ~MediaShellTest() override {} + ~MediaServiceTest() override {} void SetUp() override { - ShellTest::SetUp(); + ServiceTest::SetUp(); connection_ = connector()->Connect("mojo:media"); - connection_->SetConnectionLostClosure( - base::Bind(&MediaShellTest::ConnectionClosed, base::Unretained(this))); + connection_->SetConnectionLostClosure(base::Bind( + &MediaServiceTest::ConnectionClosed, base::Unretained(this))); connection_->GetInterface(&service_factory_); @@ -91,9 +91,10 @@ EXPECT_CALL(*this, OnCdmInitializedInternal(expected_result, cdm_id)) .Times(Exactly(1)) .WillOnce(InvokeWithoutArgs(run_loop_.get(), &base::RunLoop::Quit)); - cdm_->Initialize( - key_system, kSecurityOrigin, mojom::CdmConfig::From(CdmConfig()), - base::Bind(&MediaShellTest::OnCdmInitialized, base::Unretained(this))); + cdm_->Initialize(key_system, kSecurityOrigin, + mojom::CdmConfig::From(CdmConfig()), + base::Bind(&MediaServiceTest::OnCdmInitialized, + base::Unretained(this))); } MOCK_METHOD1(OnRendererInitialized, void(bool)); @@ -113,7 +114,7 @@ .WillOnce(InvokeWithoutArgs(run_loop_.get(), &base::RunLoop::Quit)); renderer_->Initialize(renderer_client_binding_.CreateInterfacePtrAndBind(), nullptr, std::move(video_stream_proxy), - base::Bind(&MediaShellTest::OnRendererInitialized, + base::Bind(&MediaServiceTest::OnRendererInitialized, base::Unretained(this))); } @@ -135,7 +136,7 @@ private: std::unique_ptr<shell::Connection> connection_; - DISALLOW_COPY_AND_ASSIGN(MediaShellTest); + DISALLOW_COPY_AND_ASSIGN(MediaServiceTest); }; } // namespace @@ -144,12 +145,12 @@ // even when the loop is idle, we may still have pending events in the pipe. #if defined(ENABLE_MOJO_CDM) -TEST_F(MediaShellTest, InitializeCdm_Success) { +TEST_F(MediaServiceTest, InitializeCdm_Success) { InitializeCdm(kClearKeyKeySystem, true, 1); run_loop_->Run(); } -TEST_F(MediaShellTest, InitializeCdm_InvalidKeySystem) { +TEST_F(MediaServiceTest, InitializeCdm_InvalidKeySystem) { InitializeCdm(kInvalidKeySystem, false, 0); run_loop_->Run(); } @@ -163,18 +164,18 @@ #define MAYBE_InitializeRenderer_Success InitializeRenderer_Success #endif -TEST_F(MediaShellTest, MAYBE_InitializeRenderer_Success) { +TEST_F(MediaServiceTest, MAYBE_InitializeRenderer_Success) { InitializeRenderer(TestVideoConfig::Normal(), true); run_loop_->Run(); } -TEST_F(MediaShellTest, InitializeRenderer_InvalidConfig) { +TEST_F(MediaServiceTest, InitializeRenderer_InvalidConfig) { InitializeRenderer(TestVideoConfig::Invalid(), false); run_loop_->Run(); } #endif // defined(ENABLE_MOJO_RENDERER) -TEST_F(MediaShellTest, Lifetime) { +TEST_F(MediaServiceTest, Lifetime) { // Disconnecting CDM and Renderer services doesn't terminate the app. cdm_.reset(); renderer_.reset();
diff --git a/media/mojo/services/mojo_media_application.h b/media/mojo/services/mojo_media_application.h index 7533fcb6..1c093a3 100644 --- a/media/mojo/services/mojo_media_application.h +++ b/media/mojo/services/mojo_media_application.h
@@ -16,7 +16,7 @@ #include "media/mojo/services/media_mojo_export.h" #include "services/shell/public/cpp/interface_factory.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection_ref.h" +#include "services/shell/public/cpp/service_context_ref.h" #include "url/gurl.h" namespace media { @@ -51,7 +51,7 @@ shell::Connector* connector_; scoped_refptr<MediaLog> media_log_; - shell::ShellConnectionRefFactory ref_factory_; + shell::ServiceContextRefFactory ref_factory_; }; } // namespace media
diff --git a/media/mojo/services/service_factory_impl.cc b/media/mojo/services/service_factory_impl.cc index adc5107..433a8a9b 100644 --- a/media/mojo/services/service_factory_impl.cc +++ b/media/mojo/services/service_factory_impl.cc
@@ -34,7 +34,7 @@ mojo::InterfaceRequest<mojom::ServiceFactory> request, shell::mojom::InterfaceProvider* interfaces, scoped_refptr<MediaLog> media_log, - std::unique_ptr<shell::ShellConnectionRef> connection_ref, + std::unique_ptr<shell::ServiceContextRef> connection_ref, MojoMediaClient* mojo_media_client) : binding_(this, std::move(request)), #if defined(ENABLE_MOJO_CDM)
diff --git a/media/mojo/services/service_factory_impl.h b/media/mojo/services/service_factory_impl.h index 8053571..19a1e74 100644 --- a/media/mojo/services/service_factory_impl.h +++ b/media/mojo/services/service_factory_impl.h
@@ -12,7 +12,7 @@ #include "media/mojo/services/mojo_cdm_service_context.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/shell/public/cpp/connector.h" -#include "services/shell/public/cpp/shell_connection_ref.h" +#include "services/shell/public/cpp/service_context_ref.h" namespace shell { namespace mojom { @@ -32,7 +32,7 @@ ServiceFactoryImpl(mojo::InterfaceRequest<mojom::ServiceFactory> request, shell::mojom::InterfaceProvider* interfaces, scoped_refptr<MediaLog> media_log, - std::unique_ptr<shell::ShellConnectionRef> connection_ref, + std::unique_ptr<shell::ServiceContextRef> connection_ref, MojoMediaClient* mojo_media_client); ~ServiceFactoryImpl() final; @@ -62,7 +62,7 @@ #endif scoped_refptr<MediaLog> media_log_; - std::unique_ptr<shell::ShellConnectionRef> connection_ref_; + std::unique_ptr<shell::ServiceContextRef> connection_ref_; MojoMediaClient* mojo_media_client_; DISALLOW_COPY_AND_ASSIGN(ServiceFactoryImpl);
diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc index df59249..74e72bc 100644 --- a/media/renderers/skcanvas_video_renderer.cc +++ b/media/renderers/skcanvas_video_renderer.cc
@@ -109,9 +109,9 @@ source_textures[i].fTarget = mailbox_holder.texture_target; // TODO(dcastagna): avoid this copy once Skia supports native textures - // with a texture target different than TEXTURE_2D. + // with a GL_TEXTURE_RECTANGLE_ARB texture target. // crbug.com/505026 - if (mailbox_holder.texture_target != GL_TEXTURE_2D) { + if (mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB) { unsigned texture_copy = 0; gl->GenTextures(1, &texture_copy); DCHECK(texture_copy);
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn index 1bedb1f..ca6ea349 100644 --- a/media/test/BUILD.gn +++ b/media/test/BUILD.gn
@@ -99,7 +99,7 @@ "//media/mojo/clients", "//media/mojo/interfaces", "//media/mojo/services", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//testing/gtest", "//ui/gfx:test_support", "//ui/gfx/geometry",
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index 42c80892..e244dde2 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -43,7 +43,7 @@ #include "media/mojo/interfaces/renderer.mojom.h" #include "media/mojo/interfaces/service_factory.mojom.h" #include "services/shell/public/cpp/connect.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" // TODO(dalecurtis): The mojo renderer is in another process, so we have no way // currently to get hashes for video and audio samples. This also means that @@ -700,14 +700,14 @@ // preferably by eliminating multiple inheritance here which is // banned by Google C++ style. #if defined(MOJO_RENDERER) && defined(ENABLE_MOJO_PIPELINE_INTEGRATION_TEST) -class PipelineIntegrationTestHost : public shell::test::ShellTest, +class PipelineIntegrationTestHost : public shell::test::ServiceTest, public PipelineIntegrationTestBase { public: PipelineIntegrationTestHost() - : shell::test::ShellTest("exe:media_pipeline_integration_shelltests") {} + : shell::test::ServiceTest("exe:media_pipeline_integration_shelltests") {} void SetUp() override { - ShellTest::SetUp(); + ServiceTest::SetUp(); InitializeMediaLibrary(); }
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc index 5fc55f5..a7f247a 100644 --- a/mojo/edk/system/node_controller.cc +++ b/mojo/edk/system/node_controller.cc
@@ -23,6 +23,7 @@ #include "mojo/edk/system/broker_host.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/ports_message.h" +#include "mojo/edk/system/request_context.h" #if defined(OS_MACOSX) && !defined(OS_IOS) #include "mojo/edk/system/mach_port_relay.h" @@ -545,6 +546,8 @@ node_->ClosePort(port); node_->LostConnectionToNode(name); + + AcceptIncomingMessages(); } void NodeController::SendPeerMessage(const ports::NodeName& name, @@ -646,6 +649,11 @@ AttemptShutdownIfRequested(); } +void NodeController::ProcessIncomingMessages() { + RequestContext request_context(RequestContext::Source::SYSTEM); + AcceptIncomingMessages(); +} + void NodeController::DropAllPeers() { DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); @@ -693,17 +701,39 @@ void NodeController::ForwardMessage(const ports::NodeName& node, ports::ScopedMessage message) { DCHECK(message); + bool schedule_pump_task = false; if (node == name_) { // NOTE: We need to avoid re-entering the Node instance within // ForwardMessage. Because ForwardMessage is only ever called // (synchronously) in response to Node's ClosePort, SendMessage, or // AcceptMessage, we flush the queue after calling any of those methods. base::AutoLock lock(messages_lock_); + schedule_pump_task = incoming_messages_.empty(); incoming_messages_.emplace(std::move(message)); incoming_messages_flag_.Set(true); } else { SendPeerMessage(node, std::move(message)); } + + // |io_task_runner_| may be null in tests or processes that don't require + // multi-process Mojo. + if (schedule_pump_task && io_task_runner_) { + // Normally, the queue is processed after the action that added the local + // message is done (i.e. SendMessage, ClosePort, etc). However, it's also + // possible for a local message to be added as a result of a remote message, + // and OnChannelMessage() doesn't process this queue (although + // OnPortsMessage() does). There may also be other code paths, now or added + // in the future, which cause local messages to be added but don't process + // this message queue. + // + // Instead of adding a call to AcceptIncomingMessages() on every possible + // code path, post a task to the IO thread to process the queue. If the + // current call stack processes the queue, this may end up doing nothing. + io_task_runner_->PostTask( + FROM_HERE, + base::Bind(&NodeController::ProcessIncomingMessages, + base::Unretained(this))); + } } void NodeController::BroadcastMessage(ports::ScopedMessage message) { @@ -740,14 +770,16 @@ scoped_refptr<NodeChannel> parent; { base::AutoLock lock(parent_lock_); - if (!bootstrap_parent_channel_ || parent_name_ != ports::kInvalidNodeName) { - DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node; - DropPeer(from_node); - return; + if (bootstrap_parent_channel_ && parent_name_ == ports::kInvalidNodeName) { + parent_name_ = parent_name; + parent = bootstrap_parent_channel_; } + } - parent_name_ = parent_name; - parent = bootstrap_parent_channel_; + if (!parent) { + DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node; + DropPeer(from_node); + return; } parent->SetRemoteNodeName(parent_name); @@ -996,6 +1028,8 @@ int rv = node_->MergePorts(local_port, from_node, connector_port_name); if (rv != ports::OK) DLOG(ERROR) << "MergePorts failed: " << rv; + + AcceptIncomingMessages(); } void NodeController::OnRequestIntroduction(const ports::NodeName& from_node,
diff --git a/mojo/edk/system/node_controller.h b/mojo/edk/system/node_controller.h index d0f3d6a7..c96b4f44 100644 --- a/mojo/edk/system/node_controller.h +++ b/mojo/edk/system/node_controller.h
@@ -157,6 +157,7 @@ void SendPeerMessage(const ports::NodeName& name, ports::ScopedMessage message); void AcceptIncomingMessages(); + void ProcessIncomingMessages(); void DropAllPeers(); // ports::NodeDelegate:
diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h index a976f2c..4550526 100644 --- a/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h +++ b/mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h
@@ -101,8 +101,8 @@ // Fields in test::PassByValueStructWithTraits. // See src/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom. - static ScopedHandle& f_handle(test::PassByValueStructWithTraitsImpl& value) { - return value.get_mutable_handle(); + static ScopedHandle f_handle(test::PassByValueStructWithTraitsImpl& value) { + return std::move(value.get_mutable_handle()); } };
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl index f95b33d4..c59f3178 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -66,13 +66,17 @@ {%- set name = pf.field.name %} {%- set kind = pf.field.kind %} {%- set serializer_type = kind|unmapped_type_for_serializer %} -{%- if kind|is_object_kind %} + +{%- if kind|is_object_kind or kind|is_any_handle_or_interface_kind %} {%- set original_input_field = input_field_pattern|format(name) %} {%- set input_field = "in_%s"|format(name) if input_may_be_temp else original_input_field %} {%- if input_may_be_temp %} decltype({{original_input_field}}) in_{{name}} = {{original_input_field}}; {%- endif %} +{%- endif %} + +{%- if kind|is_object_kind %} {%- if kind|is_array_kind or kind|is_map_kind %} typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr; const mojo::internal::ContainerValidateParams {{name}}_validate_params(
diff --git a/net/BUILD.gn b/net/BUILD.gn index b17c8ad..2623fc4 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -263,10 +263,6 @@ "dns/mdns_client.h", "dns/mdns_client_impl.cc", "dns/mdns_client_impl.h", - "dns/record_parsed.cc", - "dns/record_parsed.h", - "dns/record_rdata.cc", - "dns/record_rdata.h", ] } @@ -1597,8 +1593,6 @@ sources -= [ "dns/mdns_cache_unittest.cc", "dns/mdns_client_unittest.cc", - "dns/record_parsed_unittest.cc", - "dns/record_rdata_unittest.cc", ] } @@ -1795,6 +1789,7 @@ "//base", "//net", ] + dict = "data/fuzzer_dictionaries/net_mime_sniffer_fuzzer.dict" } fuzzer_test("net_parse_proxy_list_pac_fuzzer") { @@ -1846,6 +1841,7 @@ "//base", "//net", ] + dict = "data/fuzzer_dictionaries/net_parse_data_url_fuzzer.dict" } fuzzer_test("net_parse_ip_pattern_fuzzer") { @@ -1867,6 +1863,7 @@ "//base", "//net", ] + dict = "data/fuzzer_dictionaries/net_get_domain_and_registry_fuzzer.dict" } fuzzer_test("net_cert_verify_name_match_fuzzer") { @@ -1930,6 +1927,7 @@ "//base", "//net", ] + dict = "data/fuzzer_dictionaries/net_dns_record_fuzzer.dict" } fuzzer_test("net_dns_hosts_parse_fuzzer") { @@ -1941,6 +1939,7 @@ "//base", "//net", ] + dict = "data/fuzzer_dictionaries/net_dns_hosts_parse_fuzzer.dict" } fuzzer_test("net_host_resolver_impl_fuzzer") { @@ -1955,7 +1954,7 @@ "//base", "//net", ] - dict = "data/dns/dns.dict" + dict = "data/fuzzer_dictionaries/net_host_resolver_impl_fuzzer.dict" } fuzzer_test("net_http_stream_parser_fuzzer") { @@ -1968,7 +1967,7 @@ "//base", "//net", ] - dict = "data/http/http.dict" + dict = "data/fuzzer_dictionaries/net_http_stream_parser_fuzzer.dict" } fuzzer_test("net_ftp_ctrl_response_fuzzer") { @@ -2014,6 +2013,7 @@ ":net_fuzzer_test_support", "//net", ] + dict = "data/fuzzer_dictionaries/net_websocket_frame_parser_fuzzer.dict" } fuzzer_test("net_http_chunked_decoder_fuzzer") { @@ -2024,7 +2024,6 @@ ":net_fuzzer_test_support", "//net", ] - dict = "http/http_chunked_decoder_fuzzer.dict" } fuzzer_test("net_http_proxy_client_socket_fuzzer") { @@ -2037,7 +2036,7 @@ "//base", "//net", ] - dict = "data/http/http.dict" + dict = "data/fuzzer_dictionaries/net_http_proxy_client_socket_fuzzer.dict" } fuzzer_test("net_quic_crypto_framer_parse_message_fuzzer") { @@ -2085,5 +2084,5 @@ "//base", "//net", ] - dict = "data/http/http.dict" + dict = "data/fuzzer_dictionaries/net_url_request_fuzzer.dict" }
diff --git a/net/base/filename_util.cc b/net/base/filename_util.cc index 153ce43d..1e1d51c0 100644 --- a/net/base/filename_util.cc +++ b/net/base/filename_util.cc
@@ -174,8 +174,10 @@ if (filename_lower == known_devices[i]) return true; // Starts with "DEVICE.". - if (filename_lower.find(std::string(known_devices[i]) + ".") == 0) + if (base::StartsWith(filename_lower, std::string(known_devices[i]) + ".", + base::CompareCase::SENSITIVE)) { return true; + } } static const char* const magic_names[] = {
diff --git a/net/base/registry_controlled_domains/effective_tld_names.dat b/net/base/registry_controlled_domains/effective_tld_names.dat index 39db97a..8ff464c 100644 --- a/net/base/registry_controlled_domains/effective_tld_names.dat +++ b/net/base/registry_controlled_domains/effective_tld_names.dat
@@ -270,18 +270,14 @@ pro.az biz.az -// ba : https://en.wikipedia.org/wiki/.ba +// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf ba -org.ba -net.ba +com.ba edu.ba gov.ba mil.ba -unsa.ba -unbi.ba -co.ba -com.ba -rs.ba +net.ba +org.ba // bb : https://en.wikipedia.org/wiki/.bb bb @@ -2552,7 +2548,6 @@ kamiamakusa.kumamoto.jp kashima.kumamoto.jp kikuchi.kumamoto.jp -kosa.kumamoto.jp kumamoto.kumamoto.jp mashiki.kumamoto.jp mifune.kumamoto.jp @@ -2637,7 +2632,6 @@ kakuda.miyagi.jp kami.miyagi.jp kawasaki.miyagi.jp -kesennuma.miyagi.jp marumori.miyagi.jp matsushima.miyagi.jp minamisanriku.miyagi.jp @@ -10636,6 +10630,10 @@ // ===BEGIN PRIVATE DOMAINS=== // (Note: these are in alphabetical order by company name) +// Agnat sp. z o.o. : https://domena.pl +// Submitted by Przemyslaw Plewa <it-admin@domena.pl> +beep.pl + // Alces Software Ltd : http://alces-software.com // Submitted by Mark J. Titorenko <mark.titorenko@alces-software.com> *.compute.estate @@ -10646,24 +10644,24 @@ cloudfront.net // Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/ -// Submitted by Luke Wells <lawells@amazon.com> +// Submitted by Philip Allchin <pallchin@amazon.com> +compute.amazonaws.com ap-northeast-1.compute.amazonaws.com ap-northeast-2.compute.amazonaws.com ap-southeast-1.compute.amazonaws.com ap-southeast-2.compute.amazonaws.com -cn-north-1.compute.amazonaws.cn -compute-1.amazonaws.com -compute.amazonaws.cn -compute.amazonaws.com eu-central-1.compute.amazonaws.com eu-west-1.compute.amazonaws.com sa-east-1.compute.amazonaws.com -us-east-1.amazonaws.com us-gov-west-1.compute.amazonaws.com us-west-1.compute.amazonaws.com us-west-2.compute.amazonaws.com +us-east-1.amazonaws.com +compute-1.amazonaws.com z-1.compute-1.amazonaws.com z-2.compute-1.amazonaws.com +compute.amazonaws.com.cn +cn-north-1.compute.amazonaws.com.cn // Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ // Submitted by Adam Stein <astein@amazon.com> @@ -10697,6 +10695,13 @@ // Submitted by Thomas Orozco <thomas@aptible.com> on-aptible.com +// Association potager.org : https://potager.org/ +// Submitted by Lunar <jardiniers@potager.org> +potager.org +poivron.org +sweetpepper.org +pimienta.org + // AVM : https://avm.de // Submitted by Andreas Weise <a.weise@avm.de> myfritz.net @@ -10705,6 +10710,14 @@ // Submitted by Adrian <adrian@betainabox.com> betainabox.com +// Boxfuse : https://boxfuse.com +// Submitted by Axel Fontaine <axel@boxfuse.com> +boxfuse.io + +// callidomus: https://www.callidomus.com/ +// Submitted by Marcus Popp <admin@callidomus.com> +mycd.eu + // CentralNic : http://www.centralnic.com/names/domains // Submitted by registry <gavin.brown@centralnic.com> ae.org @@ -10759,10 +10772,18 @@ // c.la : http://www.c.la/ c.la +// certmgr.org : https://certmgr.org +// Submitted by B. Blechschmidt <hostmaster@certmgr.org> +certmgr.org + // Citrix : https://citrix.com // Submitted by Alex Stoddard <alex.stoddard@citrix.com> xenapponazure.com +// ClearVox : http://www.clearvox.nl/ +// Submitted by Leon Rowland <leon@clearvox.nl> +virtueeldomein.nl + // cloudControl : https://www.cloudcontrol.com/ // Submitted by Tobias Wilken <tw@cloudcontrol.com> cloudcontrolled.com @@ -10792,6 +10813,14 @@ // CHROMIUM - Disabled as per https://code.google.com/p/chromium/issues/detail?id=459802 // *.platform.sh +// Craynic, s.r.o. : http://www.craynic.com/ +// Submitted by Ales Krajnik <ales.krajnik@craynic.com> +realm.cz + +// Cryptonomic : https://cryptonomic.net/ +// Submitted by Andrew Cady <public-suffix-list@cryptonomic.net> +*.cryptonomic.net + // Cupcake : https://cupcake.io/ // Submitted by Jonathan Rudenberg <jonathan@cupcake.io> cupcake.is @@ -10833,6 +10862,11 @@ // Submitted by Richard Harper <richard@duckdns.org> duckdns.org +// dy.fi : http://dy.fi/ +// Submitted by Heikki Hannikainen <hessu@hes.iki.fi> +dy.fi +tunk.org + // DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ dyndns-at-home.com dyndns-at-work.com @@ -11118,6 +11152,10 @@ // Submitted by Dominik Menke <dom@digineo.de> 2016-01-18 dynv6.net +// E4YOU spol. s.r.o. : https://e4you.cz/ +// Submitted by Vladimir Dudr <info@e4you.cz> +e4.cz + // EU.org https://eu.org/ // Submitted by Pierre Beyssac <hostmaster@eu.org> eu.org @@ -11177,6 +11215,13 @@ uk.eu.org us.eu.org +// Evennode : http://www.evennode.com/ +// Submitted by Michal Kralik <support@evennode.com> +eu-1.evennode.com +eu-2.evennode.com +us-1.evennode.com +us-2.evennode.com + // Facebook, Inc. // Submitted by Peter Ruibal <public-suffix@fb.com> apps.fbsbx.com @@ -11189,6 +11234,10 @@ a.prod.fastly.net global.prod.fastly.net +// Featherhead : https://featherhead.xyz/ +// Submitted by Simon Menke <simon@featherhead.xyz> +fhapp.xyz + // Firebase, Inc. // Submitted by Chris Raynor <chris@firebase.com> firebaseapp.com @@ -11197,6 +11246,15 @@ // Submitted by Jonathan Rudenberg <jonathan@flynn.io> flynnhub.com +// Freebox : http://www.freebox.fr +// Submitted by Romain Fliedel <rfliedel@freebox.fr> +freebox-os.com +freeboxos.com +fbx-os.fr +fbxos.fr +freebox-os.fr +freeboxos.fr + // GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains // Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk> service.gov.uk @@ -11308,6 +11366,14 @@ // Hashbang : https://hashbang.sh hashbang.sh +// Hasura : https://hasura.io +// Submitted by Shahidh K Muhammed <shahidh@hasura.io> +hasura-app.io + +// Hepforge : https://www.hepforge.org +// Submitted by David Grellscheid <admin@hepforge.org> +hepforge.org + // Heroku : https://www.heroku.com/ // Submitted by Tom Maher <tmaher@heroku.com> herokuapp.com @@ -11321,6 +11387,15 @@ biz.at info.at +// Magento Commerce +// Submitted by Damien Tournoud <dtournoud@magento.cloud> +*.magentosite.cloud + +// Meteor Development Group : https://www.meteor.com/hosting +// Submitted by Pierre Carrier <pierre@meteor.com> +meteorapp.com +eu.meteorapp.com + // Michau Enterprises Limited : http://www.co.pl/ co.pl @@ -11351,6 +11426,94 @@ nsupdate.info nerdpol.ovh +// No-IP.com : https://noip.com/ +// Submitted by Deven Reza <publicsuffixlist@noip.com> +blogsyte.com +brasilia.me +cable-modem.org +ciscofreak.com +collegefan.org +couchpotatofries.org +damnserver.com +ddns.me +ditchyourip.com +dnsfor.me +dnsiskinky.com +dvrcam.info +dynns.com +eating-organic.net +fantasyleague.cc +geekgalaxy.com +golffan.us +health-carereform.com +homesecuritymac.com +homesecuritypc.com +hopto.me +ilovecollege.info +loginto.me +mlbfan.org +mmafan.biz +myactivedirectory.com +mydissent.net +myeffect.net +mymediapc.net +mypsx.net +mysecuritycamera.com +mysecuritycamera.net +mysecuritycamera.org +net-freaks.com +nflfan.org +nhlfan.net +no-ip.ca +no-ip.co.uk +no-ip.net +noip.us +onthewifi.com +pgafan.net +point2this.com +pointto.us +privatizehealthinsurance.net +quicksytes.com +read-books.org +securitytactics.com +serveexchange.com +servehumour.com +servep2p.com +servesarcasm.com +stufftoread.com +ufcfan.org +unusualperson.com +workisboring.com +3utilities.com +bounceme.net +ddns.net +ddnsking.com +gotdns.ch +hopto.org +myftp.biz +myftp.org +myvnc.com +no-ip.biz +no-ip.info +no-ip.org +noip.me +redirectme.net +servebeer.com +serveblog.net +servecounterstrike.com +serveftp.com +servegame.com +servehalflife.com +servehttp.com +serveirc.com +serveminecraft.net +servemp3.com +servepics.com +servequake.com +sytes.net +webhop.me +zapto.org + // NYC.mn : http://www.information.nyc.mn // Submitted by Matthew Brown <mattbrown@nyc.mn> nyc.mn @@ -11375,6 +11538,10 @@ // Submitted by Charly Coste <changaco@changaco.oy.lc> oy.lc +// Pagefog : https://pagefog.com/ +// Submitted by Derek Myers <derek@pagefog.com> +pgfog.com + // Pagefront : https://www.pagefronthq.com/ // Submitted by Jason Kriss <jason@pagefronthq.com> pagefrontapp.com @@ -11429,18 +11596,37 @@ // Submitted by Asheesh Laroia <asheesh@sandstorm.io> sandcats.io +// SBE network solutions GmbH : https://www.sbe.de/ +// Submitted by Norman Meilick <nm@sbe.de> +logoip.de +logoip.com + // Service Online LLC : http://drs.ua/ // Submitted by Serhii Bulakh <support@drs.ua> biz.ua co.ua pp.ua +// Shopblocks : http://www.shopblocks.com/ +// Submitted by Alex Bowers <alex@shopblocks.com> +myshopblocks.com + // SinaAppEngine : http://sae.sina.com.cn/ // Submitted by SinaAppEngine <saesupport@sinacloud.com> sinaapp.com vipsinaapp.com 1kapp.com +// Skyhat : http://www.skyhat.io +// Submitted by Shante Adam <shante@skyhat.io> +bounty-full.com +alpha.bounty-full.com +beta.bounty-full.com + +// SpaceKit : https://www.spacekit.io/ +// Submitted by Reza Akhavan <spacekit.io@gmail.com> +spacekit.io + // Synology, Inc. : https://www.synology.com/ // Submitted by Rony Weng <ronyweng@synology.com> diskstation.me @@ -11464,11 +11650,15 @@ med.pl sopot.pl -// TownNews.com domains : http://www.townnews.com +// TownNews.com : http://www.townnews.com // Submitted by Dustin Ward <dward@townnews.com> bloxcms.com townnews-staging.com +// TuxFamily : http://tuxfamily.org +// Submitted by TuxFamily administrators <adm@staff.tuxfamily.org> +tuxfamily.org + // UDR Limited : http://www.udr.hk.com // Submitted by registry <hostmaster@udr.hk.com> hk.com
diff --git a/net/base/registry_controlled_domains/effective_tld_names.gperf b/net/base/registry_controlled_domains/effective_tld_names.gperf index e2901fc..587d03e 100644 --- a/net/base/registry_controlled_domains/effective_tld_names.gperf +++ b/net/base/registry_controlled_domains/effective_tld_names.gperf
@@ -18,6 +18,7 @@ 2.bg, 0 2000.hu, 0 3.bg, 0 +3utilities.com, 4 4.bg, 0 4u.com, 4 5.bg, 0 @@ -215,6 +216,7 @@ allfinanz, 0 allstate, 0 ally, 0 +alpha.bounty-full.com, 4 alsace, 0 alstahaug.no, 0 alstom, 0 @@ -555,6 +557,7 @@ beauxarts.museum, 0 bedzin.pl, 0 beeldengeluid.museum, 0 +beep.pl, 4 beer, 0 beiarn.no, 0 bel.tr, 0 @@ -578,6 +581,7 @@ best, 0 bestbuy, 0 bet, 0 +beta.bounty-full.com, 4 betainabox.com, 4 better-than.tv, 4 bf, 0 @@ -727,6 +731,7 @@ blogspot.tw, 4 blogspot.ug, 4 blogspot.vn, 4 +blogsyte.com, 4 bloomberg, 0 bloxcms.com, 4 blue, 0 @@ -770,8 +775,11 @@ botanicalgarden.museum, 0 botanicgarden.museum, 0 botany.museum, 0 +bounceme.net, 4 +bounty-full.com, 4 boutique, 0 box, 0 +boxfuse.io, 4 bozen.it, 0 br, 0 br.com, 4 @@ -780,6 +788,7 @@ brand.se, 0 brandywinevalley.museum, 0 brasil.museum, 0 +brasilia.me, 4 bremanger.no, 0 brescia.it, 0 bridgestone, 0 @@ -850,6 +859,7 @@ ca.us, 0 caa.aero, 0 cab, 0 +cable-modem.org, 4 cadaques.museum, 0 cafe, 0 cagliari.it, 0 @@ -985,6 +995,7 @@ ceo, 0 cern, 0 certification.aero, 0 +certmgr.org, 4 cesena-forli.it, 0 cesenaforli.it, 0 cf, 0 @@ -1076,6 +1087,7 @@ circle, 0 circus.museum, 0 cisco, 0 +ciscofreak.com, 4 citadel, 0 citi, 0 citic, 0 @@ -1118,7 +1130,7 @@ cm, 0 cmw.ru, 0 cn, 0 -cn-north-1.compute.amazonaws.cn, 4 +cn-north-1.compute.amazonaws.com.cn, 4 cn.com, 4 cn.eu.org, 4 cn.it, 0 @@ -1130,7 +1142,6 @@ co.ag, 0 co.ao, 0 co.at, 0 -co.ba, 0 co.bb, 0 co.bi, 0 co.bw, 0 @@ -1199,6 +1210,7 @@ coldwar.museum, 0 collection.museum, 0 college, 0 +collegefan.org, 4 cologne, 0 colonialwilliamsburg.museum, 0 coloradoplateau.museum, 0 @@ -1346,8 +1358,8 @@ company, 0 compare, 0 compute-1.amazonaws.com, 4 -compute.amazonaws.cn, 4 compute.amazonaws.com, 4 +compute.amazonaws.com.cn, 4 compute.estate, 6 computer, 0 computer.museum, 0 @@ -1385,6 +1397,7 @@ corvette.museum, 0 cosenza.it, 0 costume.museum, 0 +couchpotatofries.org, 4 council.aero, 0 country, 0 countryestate.museum, 0 @@ -1413,6 +1426,7 @@ crs, 0 cruise, 0 cruises, 0 +cryptonomic.net, 6 cs.it, 0 csc, 0 ct.it, 0 @@ -1455,6 +1469,7 @@ daiwa.hiroshima.jp, 0 dali.museum, 0 dallas.museum, 0 +damnserver.com, 4 dance, 0 daplie.me, 4 database.museum, 0 @@ -1469,6 +1484,9 @@ dazaifu.fukuoka.jp, 0 dc.us, 0 dclk, 0 +ddns.me, 4 +ddns.net, 4 +ddnsking.com, 4 ddr.museum, 0 dds, 0 de, 0 @@ -1518,6 +1536,7 @@ discovery.museum, 0 dish, 0 diskstation.me, 4 +ditchyourip.com, 4 divtasvuodna.no, 0 divttasvuotna.no, 0 diy, 0 @@ -1537,7 +1556,9 @@ dnsdojo.com, 4 dnsdojo.net, 4 dnsdojo.org, 4 +dnsfor.me, 4 dnshome.de, 4 +dnsiskinky.com, 4 do, 0 docs, 0 dodge, 0 @@ -1587,8 +1608,10 @@ durban, 0 durham.museum, 0 dvag, 0 +dvrcam.info, 4 dvrdns.org, 4 dwg, 0 +dy.fi, 4 dyn-o-saur.com, 4 dynalias.com, 4 dynalias.net, 4 @@ -1613,6 +1636,7 @@ dyndns.org, 4 dyndns.tv, 4 dyndns.ws, 4 +dynns.com, 4 dynv6.net, 4 dyroy.no, 0 dz, 0 @@ -1621,10 +1645,12 @@ e.se, 0 e12.ve, 0 e164.arpa, 0 +e4.cz, 4 earth, 0 eastafrica.museum, 0 eastcoast.museum, 0 eat, 0 +eating-organic.net, 4 ebetsu.hokkaido.jp, 0 ebina.kanagawa.jp, 0 ebino.miyazaki.jp, 0 @@ -1856,10 +1882,13 @@ etne.no, 0 etnedal.no, 0 eu, 0 +eu-1.evennode.com, 4 +eu-2.evennode.com, 4 eu-central-1.compute.amazonaws.com, 4 eu-west-1.compute.amazonaws.com, 4 eu.com, 4 eu.int, 0 +eu.meteorapp.com, 4 eu.org, 4 eun.eg, 0 eurovision, 0 @@ -1894,6 +1923,7 @@ familyds.org, 4 fan, 0 fans, 0 +fantasyleague.cc, 4 far.br, 0 fareast.ru, 0 farm, 0 @@ -1906,6 +1936,8 @@ fashion, 0 fast, 0 fauske.no, 0 +fbx-os.fr, 4 +fbxos.fr, 4 fc.it, 0 fe.it, 0 fed.us, 0 @@ -1921,6 +1953,7 @@ fetsund.no, 0 fg.it, 0 fh.se, 0 +fhapp.xyz, 4 fhs.no, 0 fhsk.se, 0 fhv.se, 0 @@ -2036,6 +2069,10 @@ franziskaner.museum, 0 fredrikstad.no, 0 free, 0 +freebox-os.com, 4 +freebox-os.fr, 4 +freeboxos.com, 4 +freeboxos.fr, 4 freemasonry.museum, 0 frei.no, 0 freiburg.museum, 0 @@ -2229,6 +2266,7 @@ ge.it, 0 gea, 0 geek.nz, 0 +geekgalaxy.com, 4 geelvinck.museum, 0 geisei.kochi.jp, 0 gemological.museum, 0 @@ -2335,6 +2373,7 @@ gold, 0 goldpoint, 0 golf, 0 +golffan.us, 4 gon.pk, 0 gonohe.aomori.jp, 0 goo, 0 @@ -2354,6 +2393,7 @@ gosen.niigata.jp, 0 goshiki.hyogo.jp, 0 got, 0 +gotdns.ch, 4 gotdns.com, 4 gotdns.org, 4 gotemba.shizuoka.jp, 0 @@ -2641,6 +2681,7 @@ hashima.gifu.jp, 0 hashimoto.wakayama.jp, 0 hasuda.saitama.jp, 0 +hasura-app.io, 4 hasvik.no, 0 hatogaya.saitama.jp, 0 hatoyama.saitama.jp, 0 @@ -2658,6 +2699,7 @@ hdfcbank, 0 he.cn, 0 health, 0 +health-carereform.com, 4 health.museum, 0 health.nz, 0 health.vn, 0 @@ -2673,6 +2715,7 @@ hemne.no, 0 hemnes.no, 0 hemsedal.no, 0 +hepforge.org, 4 herad.no, 0 here, 0 here-for-more.info, 4 @@ -2809,6 +2852,8 @@ homelinux.net, 4 homelinux.org, 4 homes, 0 +homesecuritymac.com, 4 +homesecuritypc.com, 4 homesense, 0 homeunix.com, 4 homeunix.net, 4 @@ -2822,6 +2867,8 @@ honjo.akita.jp, 0 honjo.saitama.jp, 0 honjyo.akita.jp, 0 +hopto.me, 4 +hopto.org, 4 hornindal.no, 0 horokanai.hokkaido.jp, 0 horology.museum, 0 @@ -2937,6 +2984,7 @@ il.us, 0 ilawa.pl, 0 illustration.museum, 0 +ilovecollege.info, 4 im, 0 im.it, 0 imabari.ehime.jp, 0 @@ -3523,7 +3571,6 @@ kerryhotels, 0 kerrylogistics, 0 kerryproperties, 0 -kesennuma.miyagi.jp, 0 ketrzyn.pl, 0 kfh, 0 kg, 0 @@ -3657,7 +3704,6 @@ kopervik.no, 0 koriyama.fukushima.jp, 0 koryo.nara.jp, 0 -kosa.kumamoto.jp, 0 kosai.shizuoka.jp, 0 kosaka.akita.jp, 0 kosei.shiga.jp, 0 @@ -3971,7 +4017,10 @@ lodi.it, 0 lodingen.no, 0 loft, 0 +loginto.me, 4 logistics.aero, 0 +logoip.com, 4 +logoip.de, 4 lol, 0 lom.it, 0 lom.no, 0 @@ -4046,6 +4095,7 @@ maebashi.gunma.jp, 0 magadan.ru, 0 magazine.aero, 0 +magentosite.cloud, 6 maibara.shiga.jp, 0 maif, 0 mail.pl, 0 @@ -4186,6 +4236,7 @@ merseine.nu, 4 mesaverde.museum, 0 messina.it, 0 +meteorapp.com, 4 metlife, 0 mex.com, 4 mg, 0 @@ -4375,9 +4426,11 @@ mk.ua, 0 ml, 0 mlb, 0 +mlbfan.org, 4 mls, 0 mm, 2 mma, 0 +mmafan.biz, 4 mn, 0 mn.it, 0 mn.us, 0 @@ -4523,15 +4576,28 @@ my, 0 my.eu.org, 4 my.id, 0 +myactivedirectory.com, 4 +mycd.eu, 4 +mydissent.net, 4 mydrobo.com, 4 myds.me, 4 +myeffect.net, 4 myfritz.net, 4 +myftp.biz, 4 +myftp.org, 4 mykolaiv.ua, 0 +mymediapc.net, 4 myoko.niigata.jp, 0 mypep.link, 4 mypets.ws, 4 myphotos.cc, 4 +mypsx.net, 4 +mysecuritycamera.com, 4 +mysecuritycamera.net, 4 +mysecuritycamera.org, 4 +myshopblocks.com, 4 mytis.ru, 0 +myvnc.com, 4 mz, 2 mzansimagic, 0 n.bg, 0 @@ -4698,6 +4764,7 @@ nesseby.no, 0 nesset.no, 0 net, 0 +net-freaks.com, 4 net.ac, 0 net.ae, 0 net.af, 0 @@ -4845,6 +4912,7 @@ nf, 0 nf.ca, 0 nfl, 0 +nflfan.org, 4 nfshost.com, 4 ng, 0 ng.eu.org, 4 @@ -4855,6 +4923,7 @@ ngrok.io, 4 nh.us, 0 nhk, 0 +nhlfan.net, 4 nhs.uk, 0 ni, 0 nic.in, 0 @@ -4919,6 +4988,12 @@ nm.us, 0 nnov.ru, 0 no, 0 +no-ip.biz, 4 +no-ip.ca, 4 +no-ip.co.uk, 4 +no-ip.info, 4 +no-ip.net, 4 +no-ip.org, 4 no.com, 4 no.eu.org, 4 no.it, 0 @@ -4929,6 +5004,8 @@ nogata.fukuoka.jp, 0 nogi.tochigi.jp, 0 noheji.aomori.jp, 0 +noip.me, 4 +noip.us, 4 nokia, 0 nom.ad, 0 nom.ag, 0 @@ -5155,6 +5232,7 @@ onojo.fukuoka.jp, 0 onomichi.hiroshima.jp, 0 ontario.museum, 0 +onthewifi.com, 4 onyourside, 0 ookuwa.nagano.jp, 0 ooo, 0 @@ -5477,6 +5555,8 @@ pfizer, 0 pg, 2 pg.it, 0 +pgafan.net, 4 +pgfog.com, 4 ph, 0 pharmacien.fr, 0 pharmaciens.km, 0 @@ -5504,6 +5584,7 @@ pila.pl, 0 pilot.aero, 0 pilots.museum, 0 +pimienta.org, 4 pin, 0 pinb.gov.pl, 0 ping, 0 @@ -5545,6 +5626,9 @@ podzone.net, 4 podzone.org, 4 pohl, 0 +point2this.com, 4 +pointto.us, 4 +poivron.org, 4 poker, 0 pokrovsk.su, 0 pol.dz, 0 @@ -5567,6 +5651,7 @@ portlligat.museum, 0 post, 0 posts-and-telecommunications.museum, 0 +potager.org, 4 potenza.it, 0 powiat.pl, 0 poznan.pl, 4 @@ -5604,6 +5689,7 @@ priv.me, 0 priv.no, 0 priv.pl, 0 +privatizehealthinsurance.net, 4 pro, 0 pro.az, 0 pro.br, 0 @@ -5674,6 +5760,7 @@ quebec, 0 quebec.museum, 0 quest, 0 +quicksytes.com, 4 qvc, 0 r.bg, 0 r.cdn77.net, 4 @@ -5707,9 +5794,11 @@ re.it, 0 re.kr, 0 read, 0 +read-books.org, 4 readmyblog.org, 4 realestate, 0 realestate.pl, 0 +realm.cz, 4 realtor, 0 realty, 0 rebun.hokkaido.jp, 0 @@ -5723,6 +5812,7 @@ recreation.aero, 0 red, 0 red.sv, 0 +redirectme.net, 4 redstone, 0 redumbrella, 0 reg.dk, 4 @@ -5824,7 +5914,6 @@ royken.no, 0 royrvik.no, 0 rs, 0 -rs.ba, 0 rsc.cdn77.org, 4 rsvp, 0 ru, 0 @@ -6056,6 +6145,7 @@ sec.ps, 0 secure, 0 security, 0 +securitytactics.com, 4 seek, 0 seihi.nagasaki.jp, 0 seika.kyoto.jp, 0 @@ -6091,9 +6181,25 @@ servebbs.com, 4 servebbs.net, 4 servebbs.org, 4 +servebeer.com, 4 +serveblog.net, 4 +servecounterstrike.com, 4 +serveexchange.com, 4 +serveftp.com, 4 serveftp.net, 4 serveftp.org, 4 +servegame.com, 4 servegame.org, 4 +servehalflife.com, 4 +servehttp.com, 4 +servehumour.com, 4 +serveirc.com, 4 +serveminecraft.net, 4 +servemp3.com, 4 +servep2p.com, 4 +servepics.com, 4 +servequake.com, 4 +servesarcasm.com, 4 service.gov.uk, 4 services, 0 services.aero, 0 @@ -6353,6 +6459,7 @@ space, 0 space-to-rent.com, 4 space.museum, 0 +spacekit.io, 4 spb.ru, 0 spb.su, 0 spiegel, 0 @@ -6430,6 +6537,7 @@ study, 0 stuff-4-sale.org, 4 stuff-4-sale.us, 4 +stufftoread.com, 4 stuttgart.museum, 0 stv.ru, 0 style, 0 @@ -6481,6 +6589,7 @@ svizzera.museum, 0 swatch, 0 sweden.museum, 0 +sweetpepper.org, 4 swidnica.pl, 0 swiebodzin.pl, 0 swiftcover, 0 @@ -6495,6 +6604,7 @@ symantec, 0 synology.me, 4 systems, 0 +sytes.net, 4 syzran.ru, 0 sz, 0 szczecin.pl, 0 @@ -6906,6 +7016,7 @@ tula.ru, 0 tula.su, 0 tunes, 0 +tunk.org, 4 tur.ar, 0 tur.br, 0 turek.pl, 0 @@ -6916,6 +7027,7 @@ tushu, 0 tuva.ru, 0 tuva.su, 0 +tuxfamily.org, 4 tv, 0 tv.bb, 0 tv.bo, 0 @@ -6960,6 +7072,7 @@ ueda.nagano.jp, 0 ueno.gunma.jp, 0 uenohara.yamanashi.jp, 0 +ufcfan.org, 4 ug, 0 ug.gov.pl, 0 ugim.gov.pl, 0 @@ -6986,7 +7099,6 @@ umi.fukuoka.jp, 0 umig.gov.pl, 0 unazuki.toyama.jp, 0 -unbi.ba, 0 undersea.museum, 0 unicom, 0 union.aero, 0 @@ -6996,7 +7108,7 @@ unjarga.no, 0 unnan.shimane.jp, 0 uno, 0 -unsa.ba, 0 +unusualperson.com, 4 unzen.nagasaki.jp, 0 uol, 0 uonuma.niigata.jp, 0 @@ -7017,6 +7129,8 @@ uruma.okinawa.jp, 0 uryu.hokkaido.jp, 0 us, 0 +us-1.evennode.com, 4 +us-2.evennode.com, 4 us-east-1.amazonaws.com, 4 us-gov-west-1.compute.amazonaws.com, 4 us-west-1.compute.amazonaws.com, 4 @@ -7162,6 +7276,7 @@ virgin, 0 virginia.museum, 0 virtual.museum, 0 +virtueeldomein.nl, 4 virtuel.museum, 0 visa, 0 vision, 0 @@ -7263,6 +7378,7 @@ weber, 0 webhop.biz, 4 webhop.info, 4 +webhop.me, 4 webhop.net, 4 webhop.org, 4 website, 0 @@ -7306,6 +7422,7 @@ woodside, 0 work, 0 workinggroup.aero, 0 +workisboring.com, 4 works, 0 works.aero, 0 workshop.museum, 0 @@ -7889,6 +8006,7 @@ zaporizhzhe.ua, 0 zaporizhzhia.ua, 0 zappos, 0 +zapto.org, 4 zara, 0 zarow.pl, 0 zentsuji.kagawa.jp, 0
diff --git a/net/cert/internal/cert_issuer_source.h b/net/cert/internal/cert_issuer_source.h index 61580a8..1ffc3b3a 100644 --- a/net/cert/internal/cert_issuer_source.h +++ b/net/cert/internal/cert_issuer_source.h
@@ -11,11 +11,10 @@ #include "base/callback.h" #include "net/base/net_export.h" #include "net/cert/internal/completion_status.h" +#include "net/cert/internal/parsed_certificate.h" namespace net { -class ParsedCertificate; - // Interface for looking up issuers of a certificate during path building. // Provides a synchronous and asynchronous method for retrieving issuers, so the // path builder can try to complete synchronously first. The caller is expected @@ -58,9 +57,8 @@ // Matches are appended to |issuers|. Any existing contents of |issuers| will // not be modified. If the implementation does not support synchronous // lookups, or if there are no matches, |issuers| is not modified. - virtual void SyncGetIssuersOf( - const ParsedCertificate* cert, - std::vector<scoped_refptr<ParsedCertificate>>* issuers) = 0; + virtual void SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) = 0; // Finds certificates whose Subject matches |cert|'s Issuer. // If an async callback will be made |*out_req| is filled with a Request
diff --git a/net/cert/internal/cert_issuer_source_aia.cc b/net/cert/internal/cert_issuer_source_aia.cc index 4dacc340..5ee96a0 100644 --- a/net/cert/internal/cert_issuer_source_aia.cc +++ b/net/cert/internal/cert_issuer_source_aia.cc
@@ -6,7 +6,6 @@ #include "base/bind.h" #include "net/cert/cert_net_fetcher.h" -#include "net/cert/internal/parsed_certificate.h" #include "url/gurl.h" namespace net { @@ -37,7 +36,7 @@ CertIssuerSource::IssuerCallback issuers_callback_; std::vector<std::unique_ptr<CertNetFetcher::Request>> cert_fetcher_requests_; size_t pending_requests_ = 0; - std::vector<scoped_refptr<ParsedCertificate>> results_; + ParsedCertificateList results_; size_t current_result_ = 0; DISALLOW_COPY_AND_ASSIGN(AiaRequest); @@ -109,9 +108,8 @@ CertIssuerSourceAia::~CertIssuerSourceAia() = default; -void CertIssuerSourceAia::SyncGetIssuersOf( - const ParsedCertificate* cert, - std::vector<scoped_refptr<ParsedCertificate>>* issuers) { +void CertIssuerSourceAia::SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) { // CertIssuerSourceAia never returns synchronous results. }
diff --git a/net/cert/internal/cert_issuer_source_aia.h b/net/cert/internal/cert_issuer_source_aia.h index e0c7fe7..afeeda5 100644 --- a/net/cert/internal/cert_issuer_source_aia.h +++ b/net/cert/internal/cert_issuer_source_aia.h
@@ -22,9 +22,8 @@ ~CertIssuerSourceAia() override; // CertIssuerSource implementation: - void SyncGetIssuersOf( - const ParsedCertificate* cert, - std::vector<scoped_refptr<ParsedCertificate>>* issuers) override; + void SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) override; void AsyncGetIssuersOf(const ParsedCertificate* cert, const IssuerCallback& issuers_callback, std::unique_ptr<Request>* out_req) override;
diff --git a/net/cert/internal/cert_issuer_source_aia_unittest.cc b/net/cert/internal/cert_issuer_source_aia_unittest.cc index 455cf66..2132080 100644 --- a/net/cert/internal/cert_issuer_source_aia_unittest.cc +++ b/net/cert/internal/cert_issuer_source_aia_unittest.cc
@@ -166,7 +166,7 @@ StrictMock<MockCertNetFetcherImpl> mock_fetcher; CertIssuerSourceAia aia_source(&mock_fetcher); - std::vector<scoped_refptr<ParsedCertificate>> issuers; + ParsedCertificateList issuers; aia_source.SyncGetIssuersOf(cert.get(), &issuers); EXPECT_EQ(0U, issuers.size()); }
diff --git a/net/cert/internal/cert_issuer_source_static.cc b/net/cert/internal/cert_issuer_source_static.cc index c7685f436..d8a42a3 100644 --- a/net/cert/internal/cert_issuer_source_static.cc +++ b/net/cert/internal/cert_issuer_source_static.cc
@@ -4,8 +4,6 @@ #include "net/cert/internal/cert_issuer_source_static.h" -#include "net/cert/internal/parsed_certificate.h" - namespace net { CertIssuerSourceStatic::CertIssuerSourceStatic() = default; @@ -16,9 +14,8 @@ cert->normalized_subject().AsStringPiece(), std::move(cert))); } -void CertIssuerSourceStatic::SyncGetIssuersOf( - const ParsedCertificate* cert, - std::vector<scoped_refptr<ParsedCertificate>>* issuers) { +void CertIssuerSourceStatic::SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) { auto range = intermediates_.equal_range(cert->normalized_issuer().AsStringPiece()); for (auto it = range.first; it != range.second; ++it)
diff --git a/net/cert/internal/cert_issuer_source_static.h b/net/cert/internal/cert_issuer_source_static.h index af67268c2..f7151e80 100644 --- a/net/cert/internal/cert_issuer_source_static.h +++ b/net/cert/internal/cert_issuer_source_static.h
@@ -23,9 +23,8 @@ void AddCert(scoped_refptr<ParsedCertificate> cert); // CertIssuerSource implementation: - void SyncGetIssuersOf( - const ParsedCertificate* cert, - std::vector<scoped_refptr<ParsedCertificate>>* issuers) override; + void SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) override; void AsyncGetIssuersOf(const ParsedCertificate* cert, const IssuerCallback& issuers_callback, std::unique_ptr<Request>* out_req) override;
diff --git a/net/cert/internal/cert_issuer_source_static_unittest.cc b/net/cert/internal/cert_issuer_source_static_unittest.cc index 148f362..d59744c 100644 --- a/net/cert/internal/cert_issuer_source_static_unittest.cc +++ b/net/cert/internal/cert_issuer_source_static_unittest.cc
@@ -78,7 +78,7 @@ CertIssuerSourceStatic source; source.AddCert(root_); - std::vector<scoped_refptr<ParsedCertificate>> issuers; + ParsedCertificateList issuers; source.SyncGetIssuersOf(c1_.get(), &issuers); ASSERT_EQ(0U, issuers.size()); } @@ -87,7 +87,7 @@ CertIssuerSourceStatic source; AddAllCerts(&source); - std::vector<scoped_refptr<ParsedCertificate>> issuers; + ParsedCertificateList issuers; source.SyncGetIssuersOf(i1_1_.get(), &issuers); ASSERT_EQ(1U, issuers.size()); EXPECT_TRUE(issuers[0] == root_); @@ -102,7 +102,7 @@ CertIssuerSourceStatic source; AddAllCerts(&source); - std::vector<scoped_refptr<ParsedCertificate>> issuers; + ParsedCertificateList issuers; source.SyncGetIssuersOf(c1_.get(), &issuers); ASSERT_EQ(2U, issuers.size()); @@ -120,7 +120,7 @@ CertIssuerSourceStatic source; AddAllCerts(&source); - std::vector<scoped_refptr<ParsedCertificate>> issuers; + ParsedCertificateList issuers; source.SyncGetIssuersOf(root_.get(), &issuers); ASSERT_EQ(1U, issuers.size());
diff --git a/net/cert/internal/parsed_certificate.cc b/net/cert/internal/parsed_certificate.cc index e8e08c4e..a3e5cc3 100644 --- a/net/cert/internal/parsed_certificate.cc +++ b/net/cert/internal/parsed_certificate.cc
@@ -162,7 +162,7 @@ size_t length, DataSource source, const ParseCertificateOptions& options, - std::vector<scoped_refptr<ParsedCertificate>>* chain) { + ParsedCertificateList* chain) { scoped_refptr<ParsedCertificate> cert( CreateFromCertificateData(data, length, source, options)); if (!cert)
diff --git a/net/cert/internal/parsed_certificate.h b/net/cert/internal/parsed_certificate.h index 8237752..a4c6c3b 100644 --- a/net/cert/internal/parsed_certificate.h +++ b/net/cert/internal/parsed_certificate.h
@@ -18,8 +18,11 @@ struct GeneralNames; class NameConstraints; +class ParsedCertificate; class SignatureAlgorithm; +using ParsedCertificateList = std::vector<scoped_refptr<ParsedCertificate>>; + // Represents an X.509 certificate, including Certificate, TBSCertificate, and // standard extensions. // Creating a ParsedCertificate does not completely parse and validate the
diff --git a/net/cert/internal/path_builder.cc b/net/cert/internal/path_builder.cc new file mode 100644 index 0000000..863d850 --- /dev/null +++ b/net/cert/internal/path_builder.cc
@@ -0,0 +1,628 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/internal/path_builder.h" + +#include <set> +#include <unordered_set> + +#include "base/callback_helpers.h" +#include "base/memory/ptr_util.h" +#include "net/base/net_errors.h" +#include "net/cert/internal/cert_issuer_source.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/internal/parse_name.h" // For CertDebugString. +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/trust_store.h" +#include "net/cert/internal/verify_certificate_chain.h" +#include "net/cert/internal/verify_name_match.h" +#include "net/der/parser.h" +#include "net/der/tag.h" + +namespace net { + +namespace { + +using CertIssuerSources = std::vector<CertIssuerSource*>; + +// TODO(mattm): decide how much debug logging to keep. +std::string CertDebugString(const ParsedCertificate* cert) { + RDNSequence subject, issuer; + std::string subject_str, issuer_str; + if (!ParseName(cert->tbs().subject_tlv, &subject) || + !ConvertToRFC2253(subject, &subject_str)) + subject_str = "???"; + if (!ParseName(cert->tbs().issuer_tlv, &issuer) || + !ConvertToRFC2253(issuer, &issuer_str)) + issuer_str = "???"; + + return subject_str + "(" + issuer_str + ")"; +} + +// CertIssuersIter iterates through the intermediates from |cert_issuer_sources| +// which may be issuers of |cert|. +class CertIssuersIter { + public: + // Constructs the CertIssuersIter. |*cert_issuer_sources| must be valid for + // the lifetime of the CertIssuersIter. + CertIssuersIter(scoped_refptr<ParsedCertificate> cert, + CertIssuerSources* cert_issuer_sources, + const TrustStore& trust_store); + + // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC + // is returned and the cert is stored in |*out_cert|. If an issuer is not + // ready, ASYNC is returned and |callback| will be called once |*out_cert| has + // been set. If |callback| is null, always completes synchronously. + // + // In either case, if all issuers have been exhausted, |*out_cert| is cleared. + CompletionStatus GetNextIssuer(scoped_refptr<ParsedCertificate>* out_cert, + const base::Closure& callback); + + // Returns the |cert| for which issuers are being retrieved. + const ParsedCertificate* cert() const { return cert_.get(); } + scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } + + private: + void GotAsyncCerts(CertIssuerSource::Request* request); + + scoped_refptr<ParsedCertificate> cert_; + CertIssuerSources* cert_issuer_sources_; + + // The list of issuers for |cert_|. This is added to incrementally (first + // synchronous results, then possibly multiple times as asynchronous results + // arrive.) The issuers may be re-sorted each time new issuers are added, but + // only the results from |cur_| onwards should be sorted, since the earlier + // results were already returned. + // Elements should not be removed from |issuers_| once added, since + // |present_issuers_| will point to data owned by the certs. + ParsedCertificateList issuers_; + // The index of the next cert in |issuers_| to return. + size_t cur_ = 0; + // Set of DER-encoded values for the certs in |issuers_|. Used to prevent + // duplicates. This is based on the full DER of the cert to allow different + // versions of the same certificate to be tried in different candidate paths. + // This points to data owned by |issuers_|. + std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; + + // Tracks whether asynchronous requests have been made yet. + bool did_async_query_ = false; + // If asynchronous requests were made, how many of them are still outstanding? + size_t pending_async_results_; + // Owns the Request objects for any asynchronous requests so that they will be + // cancelled if CertIssuersIter is destroyed. + std::vector<std::unique_ptr<CertIssuerSource::Request>> + pending_async_requests_; + + // When GetNextIssuer was called and returned asynchronously, |*out_cert_| is + // where the result will be stored, and |callback_| will be run when the + // result is ready. + scoped_refptr<ParsedCertificate>* out_cert_; + base::Closure callback_; + + DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); +}; + +CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, + CertIssuerSources* cert_issuer_sources, + const TrustStore& trust_store) + : cert_(in_cert), cert_issuer_sources_(cert_issuer_sources) { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; + trust_store.FindTrustAnchorsByNormalizedName(in_cert->normalized_issuer(), + &issuers_); + // Insert matching roots into |present_issuers_| in case they also are + // returned by a CertIssuerSource. It is assumed + // FindTrustAnchorsByNormalizedName does not itself return dupes. + for (const auto& root : issuers_) + present_issuers_.insert(root->der_cert().AsStringPiece()); + + for (auto* cert_issuer_source : *cert_issuer_sources_) { + ParsedCertificateList new_issuers; + cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); + for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { + if (present_issuers_.find(issuer->der_cert().AsStringPiece()) != + present_issuers_.end()) + continue; + present_issuers_.insert(issuer->der_cert().AsStringPiece()); + issuers_.push_back(std::move(issuer)); + } + } + // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust + // anchor subject (or is a trust anchor), that should be sorted higher too. + // See big list of possible sorting hints in RFC 4158.) + // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that + // is done) +} + +CompletionStatus CertIssuersIter::GetNextIssuer( + scoped_refptr<ParsedCertificate>* out_cert, + const base::Closure& callback) { + // Should not be called again while already waiting for an async result. + DCHECK(callback_.is_null()); + + if (cur_ < issuers_.size()) { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << "): returning item " << cur_ << " of " << issuers_.size(); + // Still have issuers that haven't been returned yet, return one of them. + // A reference to the returned issuer is retained, since |present_issuers_| + // points to data owned by it. + *out_cert = issuers_[cur_++]; + return CompletionStatus::SYNC; + } + if (did_async_query_) { + if (pending_async_results_ == 0) { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << ") Reached the end of all available issuers."; + // Reached the end of all available issuers. + *out_cert = nullptr; + return CompletionStatus::SYNC; + } + + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << ") Still waiting for async results from other " + "CertIssuerSources."; + // Still waiting for async results from other CertIssuerSources. + out_cert_ = out_cert; + callback_ = callback; + return CompletionStatus::ASYNC; + } + // Reached the end of synchronously gathered issuers. + + if (callback.is_null()) { + // Synchronous-only mode, don't try to query async sources. + *out_cert = nullptr; + return CompletionStatus::SYNC; + } + + // Now issue request(s) for async ones (AIA, etc). + did_async_query_ = true; + pending_async_results_ = 0; + for (auto* cert_issuer_source : *cert_issuer_sources_) { + std::unique_ptr<CertIssuerSource::Request> request; + cert_issuer_source->AsyncGetIssuersOf( + cert(), + base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)), + &request); + if (request) { + DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert()) + << ") pending..."; + pending_async_results_++; + pending_async_requests_.push_back(std::move(request)); + } + } + + if (pending_async_results_ == 0) { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << ") No cert sources have async results."; + // No cert sources have async results. + *out_cert = nullptr; + return CompletionStatus::SYNC; + } + + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ + << ")"; + out_cert_ = out_cert; + callback_ = callback; + return CompletionStatus::ASYNC; +} + +void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) { + DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert()) + << ")"; + while (true) { + scoped_refptr<ParsedCertificate> cert; + CompletionStatus status = request->GetNext(&cert); + if (!cert) { + if (status == CompletionStatus::SYNC) { + // Request is exhausted, no more results pending from that + // CertIssuerSource. + DCHECK_GT(pending_async_results_, 0U); + pending_async_results_--; + } + break; + } + DCHECK_EQ(status, CompletionStatus::SYNC); + if (present_issuers_.find(cert->der_cert().AsStringPiece()) != + present_issuers_.end()) + continue; + present_issuers_.insert(cert->der_cert().AsStringPiece()); + issuers_.push_back(std::move(cert)); + } + + // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may + // be more than the ones just inserted, depending on |cur_| value). + + // Notify that more results are available, if necessary. + if (!callback_.is_null()) { + if (cur_ < issuers_.size()) { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << "): async returning item " << cur_ << " of " + << issuers_.size(); + *out_cert_ = std::move(issuers_[cur_++]); + base::ResetAndReturn(&callback_).Run(); + } else if (pending_async_results_ == 0) { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << "): async returning empty result"; + *out_cert_ = nullptr; + base::ResetAndReturn(&callback_).Run(); + } else { + DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) + << "): empty result, but other async results " + "pending, waiting.."; + } + } +} + +// CertIssuerIterPath tracks which certs are present in the path and prevents +// paths from being built which repeat any certs (including different versions +// of the same cert, based on Subject+SubjectAltName+SPKI). +class CertIssuerIterPath { + public: + // Returns true if |cert| is already present in the path. + bool IsPresent(const ParsedCertificate* cert) const { + return present_certs_.find(GetKey(cert)) != present_certs_.end(); + } + + // Appends |cert_issuers_iter| to the path. The cert referred to by + // |cert_issuers_iter| must not be present in the path already. + void Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter) { + bool added = + present_certs_.insert(GetKey(cert_issuers_iter->cert())).second; + DCHECK(added); + cur_path_.push_back(std::move(cert_issuers_iter)); + } + + // Pops the last CertIssuersIter off the path. + void Pop() { + size_t num_erased = present_certs_.erase(GetKey(cur_path_.back()->cert())); + DCHECK_EQ(num_erased, 1U); + cur_path_.pop_back(); + } + + // Copies the ParsedCertificate elements of the current path to |*out_path|. + void CopyPath(ParsedCertificateList* out_path) { + out_path->clear(); + for (const auto& node : cur_path_) + out_path->push_back(node->reference_cert()); + } + + // Returns true if the path is empty. + bool Empty() const { return cur_path_.empty(); } + + // Returns the last CertIssuersIter in the path. + CertIssuersIter* back() { return cur_path_.back().get(); } + + std::string PathDebugString() { + std::string s; + for (const auto& node : cur_path_) { + if (!s.empty()) + s += " <- "; + s += CertDebugString(node->cert()); + } + return s; + } + + private: + using Key = + std::tuple<base::StringPiece, base::StringPiece, base::StringPiece>; + + static Key GetKey(const ParsedCertificate* cert) { + // TODO(mattm): ideally this would use a normalized version of + // SubjectAltName, but it's not that important just for LoopChecker. + // + // Note that subject_alt_names_extension().value will be empty if the cert + // had no SubjectAltName extension, so there is no need for a condition on + // has_subject_alt_names(). + return Key(cert->normalized_subject().AsStringPiece(), + cert->subject_alt_names_extension().value.AsStringPiece(), + cert->tbs().spki_tlv.AsStringPiece()); + } + + std::vector<std::unique_ptr<CertIssuersIter>> cur_path_; + + // This refers to data owned by |cur_path_|. + // TODO(mattm): use unordered_set. Requires making a hash function for Key. + std::set<Key> present_certs_; +}; + +} // namespace + +// CertPathIter generates possible paths from |cert| to a trust anchor in +// |trust_store|, using intermediates from the |cert_issuer_source| objects if +// necessary. +class CertPathIter { + public: + CertPathIter(scoped_refptr<ParsedCertificate> cert, + const TrustStore* trust_store); + + // Adds a CertIssuerSource to provide intermediates for use in path building. + // The |*cert_issuer_source| must remain valid for the lifetime of the + // CertPathIter. + void AddCertIssuerSource(CertIssuerSource* cert_issuer_source); + + // Gets the next candidate path. If a path is ready synchronously, SYNC is + // returned and the path is stored in |*path|. If a path is not ready, + // ASYNC is returned and |callback| will be called once |*path| has been set. + // In either case, if all paths have been exhausted, |*path| is cleared. + CompletionStatus GetNextPath(ParsedCertificateList* path, + const base::Closure& callback); + + private: + enum State { + STATE_NONE, + STATE_GET_NEXT_ISSUER, + STATE_GET_NEXT_ISSUER_COMPLETE, + STATE_RETURN_A_PATH, + STATE_BACKTRACK, + }; + + CompletionStatus DoLoop(bool allow_async); + + CompletionStatus DoGetNextIssuer(bool allow_async); + CompletionStatus DoGetNextIssuerComplete(); + CompletionStatus DoBackTrack(); + + void HandleGotNextIssuer(void); + + // Stores the next candidate issuer certificate, until it is used during the + // STATE_GET_NEXT_ISSUER_COMPLETE step. + scoped_refptr<ParsedCertificate> next_cert_; + // The current path being explored, made up of CertIssuerIters. Each node + // keeps track of the state of searching for issuers of that cert, so that + // when backtracking it can resume the search where it left off. + CertIssuerIterPath cur_path_; + // The CertIssuerSources for retrieving candidate issuers. + CertIssuerSources cert_issuer_sources_; + // The TrustStore for checking if a path ends in a trust anchor. + const TrustStore* trust_store_; + // The output variable for storing the next candidate path, which the client + // passes in to GetNextPath. Only used for a single path output. + ParsedCertificateList* out_path_; + // The callback to be called if an async lookup generated a candidate path. + base::Closure callback_; + // Current state of the state machine. + State next_state_; + + DISALLOW_COPY_AND_ASSIGN(CertPathIter); +}; + +CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert, + const TrustStore* trust_store) + : next_cert_(std::move(cert)), + trust_store_(trust_store), + next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {} + +void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) { + cert_issuer_sources_.push_back(cert_issuer_source); +} + +CompletionStatus CertPathIter::GetNextPath(ParsedCertificateList* path, + const base::Closure& callback) { + out_path_ = path; + out_path_->clear(); + CompletionStatus rv = DoLoop(!callback.is_null()); + if (rv == CompletionStatus::ASYNC) { + callback_ = callback; + } else { + // Clear the reference to the output parameter as a precaution. + out_path_ = nullptr; + } + return rv; +} + +CompletionStatus CertPathIter::DoLoop(bool allow_async) { + CompletionStatus result = CompletionStatus::SYNC; + do { + State state = next_state_; + next_state_ = STATE_NONE; + switch (state) { + case STATE_NONE: + NOTREACHED(); + break; + case STATE_GET_NEXT_ISSUER: + result = DoGetNextIssuer(allow_async); + break; + case STATE_GET_NEXT_ISSUER_COMPLETE: + result = DoGetNextIssuerComplete(); + break; + case STATE_RETURN_A_PATH: + // If the returned path did not verify, keep looking for other paths + // (the trust root is not part of cur_path_, so don't need to + // backtrack). + next_state_ = STATE_GET_NEXT_ISSUER; + result = CompletionStatus::SYNC; + break; + case STATE_BACKTRACK: + result = DoBackTrack(); + break; + } + } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE && + next_state_ != STATE_RETURN_A_PATH); + + return result; +} + +CompletionStatus CertPathIter::DoGetNextIssuer(bool allow_async) { + next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE; + CompletionStatus rv = cur_path_.back()->GetNextIssuer( + &next_cert_, allow_async ? base::Bind(&CertPathIter::HandleGotNextIssuer, + base::Unretained(this)) + : base::Closure()); + return rv; +} + +CompletionStatus CertPathIter::DoGetNextIssuerComplete() { + if (next_cert_) { + // Skip this cert if it is already in the chain. + if (cur_path_.IsPresent(next_cert_.get())) { + next_state_ = STATE_GET_NEXT_ISSUER; + return CompletionStatus::SYNC; + } + // If the cert matches a trust root, this is a (possibly) complete path. + // Signal readiness. Don't add it to cur_path_, since that would cause an + // unnecessary lookup of issuers of the trust root. + if (trust_store_->IsTrustedCertificate(next_cert_.get())) { + DVLOG(1) << "CertPathIter IsTrustedCertificate(" + << CertDebugString(next_cert_.get()) << ") = true"; + next_state_ = STATE_RETURN_A_PATH; + cur_path_.CopyPath(out_path_); + out_path_->push_back(std::move(next_cert_)); + next_cert_ = nullptr; + return CompletionStatus::SYNC; + } + + cur_path_.Append(base::WrapUnique(new CertIssuersIter( + std::move(next_cert_), &cert_issuer_sources_, *trust_store_))); + next_cert_ = nullptr; + DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString(); + // Continue descending the tree. + next_state_ = STATE_GET_NEXT_ISSUER; + } else { + // TODO(mattm): should also include such paths in CertPathBuilder::Result, + // maybe with a flag to enable it. Or use a visitor pattern so the caller + // can decide what to do with any failed paths. + // No more issuers for current chain, go back up and see if there are any + // more for the previous cert. + next_state_ = STATE_BACKTRACK; + } + return CompletionStatus::SYNC; +} + +CompletionStatus CertPathIter::DoBackTrack() { + DVLOG(1) << "CertPathIter backtracking..."; + cur_path_.Pop(); + if (cur_path_.Empty()) { + // Exhausted all paths. + next_state_ = STATE_NONE; + } else { + // Continue exploring issuers of the previous path. + next_state_ = STATE_GET_NEXT_ISSUER; + } + return CompletionStatus::SYNC; +} + +void CertPathIter::HandleGotNextIssuer(void) { + DCHECK(!callback_.is_null()); + CompletionStatus rv = DoLoop(true /* allow_async */); + if (rv == CompletionStatus::SYNC) { + // Clear the reference to the output parameter as a precaution. + out_path_ = nullptr; + base::ResetAndReturn(&callback_).Run(); + } +} + +CertPathBuilder::ResultPath::ResultPath() = default; +CertPathBuilder::ResultPath::~ResultPath() = default; +CertPathBuilder::Result::Result() = default; +CertPathBuilder::Result::~Result() = default; + +CertPathBuilder::CertPathBuilder(scoped_refptr<ParsedCertificate> cert, + const TrustStore* trust_store, + const SignaturePolicy* signature_policy, + const der::GeneralizedTime& time, + Result* result) + : cert_path_iter_(new CertPathIter(std::move(cert), trust_store)), + trust_store_(trust_store), + signature_policy_(signature_policy), + time_(time), + next_state_(STATE_NONE), + out_result_(result) {} + +CertPathBuilder::~CertPathBuilder() {} + +void CertPathBuilder::AddCertIssuerSource( + CertIssuerSource* cert_issuer_source) { + cert_path_iter_->AddCertIssuerSource(cert_issuer_source); +} + +CompletionStatus CertPathBuilder::Run(const base::Closure& callback) { + DCHECK_EQ(STATE_NONE, next_state_); + next_state_ = STATE_GET_NEXT_PATH; + CompletionStatus rv = DoLoop(!callback.is_null()); + + if (rv == CompletionStatus::ASYNC) + callback_ = callback; + + return rv; +} + +CompletionStatus CertPathBuilder::DoLoop(bool allow_async) { + CompletionStatus result = CompletionStatus::SYNC; + + do { + State state = next_state_; + next_state_ = STATE_NONE; + switch (state) { + case STATE_NONE: + NOTREACHED(); + break; + case STATE_GET_NEXT_PATH: + result = DoGetNextPath(allow_async); + break; + case STATE_GET_NEXT_PATH_COMPLETE: + result = DoGetNextPathComplete(); + break; + } + } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE); + + return result; +} + +CompletionStatus CertPathBuilder::DoGetNextPath(bool allow_async) { + next_state_ = STATE_GET_NEXT_PATH_COMPLETE; + CompletionStatus rv = cert_path_iter_->GetNextPath( + &next_path_, allow_async ? base::Bind(&CertPathBuilder::HandleGotNextPath, + base::Unretained(this)) + : base::Closure()); + return rv; +} + +void CertPathBuilder::HandleGotNextPath() { + DCHECK(!callback_.is_null()); + CompletionStatus rv = DoLoop(true /* allow_async */); + if (rv == CompletionStatus::SYNC) + base::ResetAndReturn(&callback_).Run(); +} + +CompletionStatus CertPathBuilder::DoGetNextPathComplete() { + if (next_path_.empty()) { + // No more paths to check, signal completion. + next_state_ = STATE_NONE; + return CompletionStatus::SYNC; + } + + bool verify_result = VerifyCertificateChainAssumingTrustedRoot( + next_path_, *trust_store_, signature_policy_, time_); + DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = " + << verify_result; + AddResultPath(next_path_, verify_result); + + if (verify_result) { + // Found a valid path, return immediately. + // TODO(mattm): add debug/test mode that tries all possible paths. + next_state_ = STATE_NONE; + return CompletionStatus::SYNC; + } + + // Path did not verify. Try more paths. If there are no more paths, the result + // will be returned next time DoGetNextPathComplete is called with next_path_ + // empty. + next_state_ = STATE_GET_NEXT_PATH; + return CompletionStatus::SYNC; +} + +void CertPathBuilder::AddResultPath(const ParsedCertificateList& path, + bool is_success) { + std::unique_ptr<ResultPath> result_path(new ResultPath()); + // TODO(mattm): better error reporting. + result_path->error = is_success ? OK : ERR_CERT_AUTHORITY_INVALID; + // TODO(mattm): set best_result_index based on number or severity of errors. + if (result_path->error == OK) + out_result_->best_result_index = out_result_->paths.size(); + // TODO(mattm): add flag to only return a single path or all attempted paths? + result_path->path = path; + out_result_->paths.push_back(std::move(result_path)); +} + +} // namespace net
diff --git a/net/cert/internal/path_builder.h b/net/cert/internal/path_builder.h new file mode 100644 index 0000000..f08ad127 --- /dev/null +++ b/net/cert/internal/path_builder.h
@@ -0,0 +1,172 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CERT_INTERNAL_PATH_BUILDER_H_ +#define NET_CERT_INTERNAL_PATH_BUILDER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/callback.h" +#include "net/base/completion_callback.h" +#include "net/base/net_errors.h" +#include "net/base/net_export.h" +#include "net/cert/internal/completion_status.h" +#include "net/cert/internal/parsed_certificate.h" +#include "net/der/input.h" +#include "net/der/parse_values.h" + +namespace net { + +namespace der { +struct GeneralizedTime; +} + +class CertPathIter; +class CertIssuerSource; +class TrustStore; +class SignaturePolicy; + +// Checks whether a certificate is trusted by building candidate paths to trust +// anchors and verifying those paths according to RFC 5280. Each instance of +// CertPathBuilder is used for a single verification. +// +// WARNING: This implementation is currently experimental. Consult an OWNER +// before using it. +class NET_EXPORT CertPathBuilder { + public: + // Represents a single candidate path that was built. + struct NET_EXPORT ResultPath { + ResultPath(); + ~ResultPath(); + + // Returns true if this path was successfully verified. + bool is_success() const { return error == OK; } + + // The candidate path, in forward direction. + // * path[0] is the target certificate. + // * path[i+1] is a candidate issuer of path[i]. The subject matches + // path[i]'s issuer, but nothing else is guaranteed unless is_success() is + // true. + // * path[N-1] will be a trust anchor if is_success() is true, otherwise + // it may or may not be a trust anchor. + ParsedCertificateList path; + + // A net error code result of attempting to verify this path. + // TODO(mattm): may want to have an independent result enum, which caller + // can map to a net error if they want. + int error = ERR_UNEXPECTED; + }; + + // Provides the overall result of path building. This includes the paths that + // were attempted. + struct NET_EXPORT Result { + Result(); + ~Result(); + + // Returns true if there was a valid path. + bool is_success() const { return error() == OK; } + + // Returns the net error code of the overall best result. + int error() const { + if (paths.empty()) + return ERR_CERT_AUTHORITY_INVALID; + return paths[best_result_index]->error; + } + + // List of paths that were attempted and the result for each. + std::vector<std::unique_ptr<ResultPath>> paths; + + // Index into |paths|. Before use, |paths.empty()| must be checked. + // NOTE: currently the definition of "best" is fairly limited. Successful is + // better than unsuccessful, but otherwise nothing is guaranteed. + size_t best_result_index = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(Result); + }; + + // TODO(mattm): allow caller specified hook/callback to extend path + // verification. + // + // Creates a CertPathBuilder that attempts to find a path from |cert| to a + // trust anchor in |trust_store|, which satisfies |signature_policy| and is + // valid at |time|. Details of attempted path(s) are stored in |*result|. + // + // The caller must keep |trust_store|, |signature_policy|, and |*result| valid + // for the lifetime of the CertPathBuilder. + CertPathBuilder(scoped_refptr<ParsedCertificate> cert, + const TrustStore* trust_store, + const SignaturePolicy* signature_policy, + const der::GeneralizedTime& time, + Result* result); + ~CertPathBuilder(); + + // Adds a CertIssuerSource to provide intermediates for use in path building. + // Multiple sources may be added. Must not be called after Run is called. + // The |*cert_issuer_source| must remain valid for the lifetime of the + // CertPathBuilder. + // + // (If no issuer sources are added, the target certificate will only verify if + // it is a trust anchor or is directly signed by a trust anchor.) + void AddCertIssuerSource(CertIssuerSource* cert_issuer_source); + + // Begins verification of the target certificate. + // + // If the return value is SYNC then the verification is complete and the + // |result| value can be inspected for the status, and |callback| will not be + // called. + // If the return value is ASYNC, the |callback| will be called asynchronously + // once the verification is complete. |result| should not be examined or + // modified until the |callback| is run. + // + // If |callback| is null, verification always completes synchronously, even if + // it fails to find a valid path and one could have been found asynchronously. + // + // The CertPathBuilder may be deleted while an ASYNC verification is pending, + // in which case the verification is cancelled, |callback| will not be called, + // and the output Result will be in an undefined state. + // It is safe to delete the CertPathBuilder during the |callback|. + // Run must not be called more than once on each CertPathBuilder instance. + CompletionStatus Run(const base::Closure& callback); + + private: + enum State { + STATE_NONE, + STATE_GET_NEXT_PATH, + STATE_GET_NEXT_PATH_COMPLETE, + }; + + CompletionStatus DoLoop(bool allow_async); + + CompletionStatus DoGetNextPath(bool allow_async); + void HandleGotNextPath(); + CompletionStatus DoGetNextPathComplete(); + + void AddResultPath(const ParsedCertificateList& path, bool is_success); + + base::Closure callback_; + + std::unique_ptr<CertPathIter> cert_path_iter_; + const TrustStore* trust_store_; + const SignaturePolicy* signature_policy_; + const der::GeneralizedTime time_; + + // Stores the next complete path to attempt verification on. This is filled in + // by |cert_path_iter_| during the STATE_GET_NEXT_PATH step, and thus should + // only be accessed during the STATE_GET_NEXT_PATH_COMPLETE step. + // (Will be empty if all paths have been tried, otherwise will be a candidate + // path starting with the target cert and ending with a trust anchor.) + ParsedCertificateList next_path_; + State next_state_; + + Result* out_result_; + + DISALLOW_COPY_AND_ASSIGN(CertPathBuilder); +}; + +} // namespace net + +#endif // NET_CERT_INTERNAL_PATH_BUILDER_H_
diff --git a/net/cert/internal/path_builder_pkits_unittest.cc b/net/cert/internal/path_builder_pkits_unittest.cc new file mode 100644 index 0000000..a046d1cf --- /dev/null +++ b/net/cert/internal/path_builder_pkits_unittest.cc
@@ -0,0 +1,227 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/internal/path_builder.h" + +#include "net/base/net_errors.h" +#include "net/cert/internal/cert_issuer_source_static.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/internal/parsed_certificate.h" +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/trust_store.h" +#include "net/cert/internal/verify_certificate_chain.h" +#include "net/der/input.h" + +// Disable tests that require DSA signatures (DSA signatures are intentionally +// unsupported). Custom versions of the DSA tests are defined below which expect +// verification to fail. +#define Section1ValidDSASignaturesTest4 DISABLED_Section1ValidDSASignaturesTest4 +#define Section1ValidDSAParameterInheritanceTest5 \ + DISABLED_Section1ValidDSAParameterInheritanceTest5 + +// Disable tests that require name constraints with name types that are +// intentionally unsupported. Custom versions of the tests are defined below +// which expect verification to fail. +#define Section13ValidRFC822nameConstraintsTest21 \ + DISABLED_Section13ValidRFC822nameConstraintsTest21 +#define Section13ValidRFC822nameConstraintsTest23 \ + DISABLED_Section13ValidRFC822nameConstraintsTest23 +#define Section13ValidRFC822nameConstraintsTest25 \ + DISABLED_Section13ValidRFC822nameConstraintsTest25 +#define Section13ValidDNandRFC822nameConstraintsTest27 \ + DISABLED_Section13ValidDNandRFC822nameConstraintsTest27 +#define Section13ValidURInameConstraintsTest34 \ + DISABLED_Section13ValidURInameConstraintsTest34 +#define Section13ValidURInameConstraintsTest36 \ + DISABLED_Section13ValidURInameConstraintsTest36 + +// TODO(mattm): these require CRL support: +#define Section7InvalidkeyUsageCriticalcRLSignFalseTest4 \ + DISABLED_Section7InvalidkeyUsageCriticalcRLSignFalseTest4 +#define Section7InvalidkeyUsageNotCriticalcRLSignFalseTest5 \ + DISABLED_Section7InvalidkeyUsageNotCriticalcRLSignFalseTest5 + +#include "net/cert/internal/nist_pkits_unittest.h" + +namespace net { + +namespace { + +class PathBuilderPkitsTestDelegate { + public: + static bool Verify(std::vector<std::string> cert_ders, + std::vector<std::string> crl_ders) { + if (cert_ders.empty()) { + ADD_FAILURE() << "cert_ders is empty"; + return false; + } + ParsedCertificateList certs; + for (const std::string& der : cert_ders) { + certs.push_back(ParsedCertificate::CreateFromCertificateCopy(der, {})); + if (!certs.back()) { + ADD_FAILURE() << "ParsedCertificate::CreateFromCertificateCopy failed"; + return false; + } + } + // First entry in the PKITS chain is the trust anchor. + // TODO(mattm): test with all possible trust anchors in the trust store? + TrustStore trust_store; + trust_store.AddTrustedCertificate(certs[0]); + + // TODO(mattm): test with other irrelevant certs in cert_issuer_sources? + CertIssuerSourceStatic cert_issuer_source; + for (size_t i = 1; i < cert_ders.size() - 1; ++i) + cert_issuer_source.AddCert(certs[i]); + + scoped_refptr<ParsedCertificate> target_cert(certs.back()); + + SimpleSignaturePolicy signature_policy(1024); + + // Run all tests at the time the PKITS was published. + der::GeneralizedTime time = {2011, 4, 15, 0, 0, 0}; + + CertPathBuilder::Result result; + CertPathBuilder path_builder(std::move(target_cert), &trust_store, + &signature_policy, time, &result); + path_builder.AddCertIssuerSource(&cert_issuer_source); + + CompletionStatus rv = path_builder.Run(base::Closure()); + EXPECT_EQ(CompletionStatus::SYNC, rv); + + return result.is_success(); + } +}; + +} // namespace + +class PkitsTest01SignatureVerificationCustomPathBuilderFoo + : public PkitsTest<PathBuilderPkitsTestDelegate> {}; + +// Modified version of 4.1.4 Valid DSA Signatures Test4 +TEST_F(PkitsTest01SignatureVerificationCustomPathBuilderFoo, + Section1ValidDSASignaturesTest4Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert", + "ValidDSASignaturesTest4EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL"}; + // DSA signatures are intentionally unsupported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +// Modified version of 4.1.5 Valid DSA Parameter Inheritance Test5 +TEST_F(PkitsTest01SignatureVerificationCustomPathBuilderFoo, + Section1ValidDSAParameterInheritanceTest5Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", "DSACACert", + "DSAParametersInheritedCACert", + "ValidDSAParameterInheritanceTest5EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", "DSACACRL", + "DSAParametersInheritedCACRL"}; + // DSA signatures are intentionally unsupported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +class PkitsTest13SignatureVerificationCustomPathBuilderFoo + : public PkitsTest<PathBuilderPkitsTestDelegate> {}; + +// Modified version of 4.13.21 Valid RFC822 nameConstraints Test21 +TEST_F(PkitsTest13SignatureVerificationCustomPathBuilderFoo, + Section13ValidRFC822nameConstraintsTest21Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", + "nameConstraintsRFC822CA1Cert", + "ValidRFC822nameConstraintsTest21EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", + "nameConstraintsRFC822CA1CRL"}; + // Name constraints on rfc822Names are not supported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +// Modified version of 4.13.23 Valid RFC822 nameConstraints Test23 +TEST_F(PkitsTest13SignatureVerificationCustomPathBuilderFoo, + Section13ValidRFC822nameConstraintsTest23Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", + "nameConstraintsRFC822CA2Cert", + "ValidRFC822nameConstraintsTest23EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", + "nameConstraintsRFC822CA2CRL"}; + // Name constraints on rfc822Names are not supported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +// Modified version of 4.13.25 Valid RFC822 nameConstraints Test25 +TEST_F(PkitsTest13SignatureVerificationCustomPathBuilderFoo, + Section13ValidRFC822nameConstraintsTest25Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", + "nameConstraintsRFC822CA3Cert", + "ValidRFC822nameConstraintsTest25EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", + "nameConstraintsRFC822CA3CRL"}; + // Name constraints on rfc822Names are not supported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +// Modified version of 4.13.27 Valid DN and RFC822 nameConstraints Test27 +TEST_F(PkitsTest13SignatureVerificationCustomPathBuilderFoo, + Section13ValidDNandRFC822nameConstraintsTest27Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", + "nameConstraintsDN1CACert", + "nameConstraintsDN1subCA3Cert", + "ValidDNandRFC822nameConstraintsTest27EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsDN1CACRL", + "nameConstraintsDN1subCA3CRL"}; + // Name constraints on rfc822Names are not supported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +// Modified version of 4.13.34 Valid URI nameConstraints Test34 +TEST_F(PkitsTest13SignatureVerificationCustomPathBuilderFoo, + Section13ValidURInameConstraintsTest34Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", + "nameConstraintsURI1CACert", + "ValidURInameConstraintsTest34EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI1CACRL"}; + // Name constraints on uniformResourceIdentifiers are not supported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +// Modified version of 4.13.36 Valid URI nameConstraints Test36 +TEST_F(PkitsTest13SignatureVerificationCustomPathBuilderFoo, + Section13ValidURInameConstraintsTest36Custom) { + const char* const certs[] = {"TrustAnchorRootCertificate", + "nameConstraintsURI2CACert", + "ValidURInameConstraintsTest36EE"}; + const char* const crls[] = {"TrustAnchorRootCRL", "nameConstraintsURI2CACRL"}; + // Name constraints on uniformResourceIdentifiers are not supported. + ASSERT_FALSE(this->Verify(certs, crls)); +} + +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest01SignatureVerification, + PathBuilderPkitsTestDelegate); +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest02ValidityPeriods, + PathBuilderPkitsTestDelegate); +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest03VerifyingNameChaining, + PathBuilderPkitsTestDelegate); +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest06VerifyingBasicConstraints, + PathBuilderPkitsTestDelegate); +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest07KeyUsage, + PathBuilderPkitsTestDelegate); +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest13NameConstraints, + PathBuilderPkitsTestDelegate); +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + PkitsTest16PrivateCertificateExtensions, + PathBuilderPkitsTestDelegate); + +// TODO(mattm): CRL support: PkitsTest04BasicCertificateRevocationTests, +// PkitsTest05VerifyingPathswithSelfIssuedCertificates, +// PkitsTest14DistributionPoints, PkitsTest15DeltaCRLs + +// TODO(mattm): Certificate Policies support: PkitsTest08CertificatePolicies, +// PkitsTest09RequireExplicitPolicy PkitsTest10PolicyMappings, +// PkitsTest11InhibitPolicyMapping, PkitsTest12InhibitAnyPolicy + +} // namespace net
diff --git a/net/cert/internal/path_builder_unittest.cc b/net/cert/internal/path_builder_unittest.cc new file mode 100644 index 0000000..dfdf25b --- /dev/null +++ b/net/cert/internal/path_builder_unittest.cc
@@ -0,0 +1,1108 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/internal/path_builder.h" + +#include "base/base_paths.h" +#include "base/cancelable_callback.h" +#include "base/files/file_util.h" +#include "base/location.h" +#include "base/path_service.h" +#include "base/threading/thread_task_runner_handle.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/cert/internal/cert_issuer_source_static.h" +#include "net/cert/internal/parsed_certificate.h" +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/test_helpers.h" +#include "net/cert/internal/trust_store.h" +#include "net/cert/internal/verify_certificate_chain.h" +#include "net/cert/pem_tokenizer.h" +#include "net/der/input.h" +#include "net/test/cert_test_util.h" +#include "net/test/test_certificate_data.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +using ::testing::_; +using ::testing::Invoke; +using ::testing::SaveArg; +using ::testing::StrictMock; +using ::testing::SetArgPointee; +using ::testing::Return; + +// AsyncCertIssuerSourceStatic always returns its certs asynchronously. +class AsyncCertIssuerSourceStatic : public CertIssuerSource { + public: + class StaticAsyncRequest : public Request { + public: + StaticAsyncRequest(const IssuerCallback& issuers_callback, + ParsedCertificateList&& issuers) + : cancelable_closure_(base::Bind(&StaticAsyncRequest::RunCallback, + base::Unretained(this))), + issuers_callback_(issuers_callback) { + issuers_.swap(issuers); + issuers_iter_ = issuers_.begin(); + } + ~StaticAsyncRequest() override {} + + CompletionStatus GetNext( + scoped_refptr<ParsedCertificate>* out_cert) override { + if (issuers_iter_ == issuers_.end()) + *out_cert = nullptr; + else + *out_cert = std::move(*issuers_iter_++); + return CompletionStatus::SYNC; + } + + base::Closure callback() { return cancelable_closure_.callback(); } + + private: + void RunCallback() { issuers_callback_.Run(this); } + + base::CancelableClosure cancelable_closure_; + IssuerCallback issuers_callback_; + ParsedCertificateList issuers_; + ParsedCertificateList::iterator issuers_iter_; + + DISALLOW_COPY_AND_ASSIGN(StaticAsyncRequest); + }; + + ~AsyncCertIssuerSourceStatic() override {} + + void AddCert(scoped_refptr<ParsedCertificate> cert) { + static_cert_issuer_source_.AddCert(std::move(cert)); + } + + void SyncGetIssuersOf(const ParsedCertificate* cert, + ParsedCertificateList* issuers) override {} + void AsyncGetIssuersOf(const ParsedCertificate* cert, + const IssuerCallback& issuers_callback, + std::unique_ptr<Request>* out_req) override { + num_async_gets_++; + ParsedCertificateList issuers; + static_cert_issuer_source_.SyncGetIssuersOf(cert, &issuers); + std::unique_ptr<StaticAsyncRequest> req( + new StaticAsyncRequest(issuers_callback, std::move(issuers))); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, req->callback()); + *out_req = std::move(req); + } + int num_async_gets() const { return num_async_gets_; } + + private: + CertIssuerSourceStatic static_cert_issuer_source_; + + int num_async_gets_ = 0; +}; + +// Reads a data file from the unit-test data. +std::string ReadTestFileToString(const std::string& file_name) { + // Compute the full path, relative to the src/ directory. + base::FilePath src_root; + PathService::Get(base::DIR_SOURCE_ROOT, &src_root); + base::FilePath filepath = src_root.AppendASCII(file_name); + + // Read the full contents of the file. + std::string file_data; + if (!base::ReadFileToString(filepath, &file_data)) { + ADD_FAILURE() << "Couldn't read file: " << filepath.value(); + return std::string(); + } + + return file_data; +} + +// Reads a verify_certificate_chain_unittest-style test case from |file_name|. +// Test cases are comprised of a certificate chain, trust store, a timestamp to +// validate at, and the expected result of verification (though the expected +// result is ignored here). +void ReadVerifyCertChainTestFromFile(const std::string& file_name, + std::vector<std::string>* chain, + scoped_refptr<ParsedCertificate>* root, + der::GeneralizedTime* time) { + chain->clear(); + + std::string file_data = ReadTestFileToString(file_name); + + std::vector<std::string> pem_headers; + + const char kCertificateHeader[] = "CERTIFICATE"; + const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; + const char kTimeHeader[] = "TIME"; + + pem_headers.push_back(kCertificateHeader); + pem_headers.push_back(kTrustedCertificateHeader); + pem_headers.push_back(kTimeHeader); + + bool has_time = false; + + PEMTokenizer pem_tokenizer(file_data, pem_headers); + while (pem_tokenizer.GetNext()) { + const std::string& block_type = pem_tokenizer.block_type(); + const std::string& block_data = pem_tokenizer.data(); + + if (block_type == kCertificateHeader) { + chain->push_back(block_data); + } else if (block_type == kTrustedCertificateHeader) { + *root = ParsedCertificate::CreateFromCertificateCopy(block_data, {}); + ASSERT_TRUE(*root); + } else if (block_type == kTimeHeader) { + ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; + has_time = true; + ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time)); + } + } + + ASSERT_TRUE(has_time); +} + +::testing::AssertionResult ReadTestPem(const std::string& file_name, + const std::string& block_name, + std::string* result) { + const PemBlockMapping mappings[] = { + {block_name.c_str(), result}, + }; + + return ReadTestDataFromPemFile(file_name, mappings); +} + +::testing::AssertionResult ReadTestCert( + const std::string& file_name, + scoped_refptr<ParsedCertificate>* result) { + std::string der; + ::testing::AssertionResult r = ReadTestPem( + "net/data/ssl/certificates/" + file_name, "CERTIFICATE", &der); + if (!r) + return r; + *result = ParsedCertificate::CreateFromCertificateCopy(der, {}); + if (!*result) + return ::testing::AssertionFailure() << "CreateFromCertificateCopy failed"; + return ::testing::AssertionSuccess(); +} + +// Run the path builder, and wait for async completion if necessary. The return +// value signifies whether the path builder completed synchronously or +// asynchronously, not that RunPathBuilder itself is asynchronous. +CompletionStatus RunPathBuilder(CertPathBuilder* path_builder) { + TestClosure callback; + CompletionStatus rv = path_builder->Run(callback.closure()); + + if (rv == CompletionStatus::ASYNC) { + DVLOG(1) << "waiting for async completion..."; + callback.WaitForResult(); + DVLOG(1) << "async completed."; + } + return rv; +} + +class PathBuilderMultiRootTest : public ::testing::Test { + public: + PathBuilderMultiRootTest() : signature_policy_(1024) {} + + void SetUp() override { + ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b_)); + ASSERT_TRUE(ReadTestCert("multi-root-B-by-C.pem", &b_by_c_)); + ASSERT_TRUE(ReadTestCert("multi-root-B-by-F.pem", &b_by_f_)); + ASSERT_TRUE(ReadTestCert("multi-root-C-by-D.pem", &c_by_d_)); + ASSERT_TRUE(ReadTestCert("multi-root-C-by-E.pem", &c_by_e_)); + ASSERT_TRUE(ReadTestCert("multi-root-D-by-D.pem", &d_by_d_)); + ASSERT_TRUE(ReadTestCert("multi-root-E-by-E.pem", &e_by_e_)); + ASSERT_TRUE(ReadTestCert("multi-root-F-by-E.pem", &f_by_e_)); + } + + protected: + scoped_refptr<ParsedCertificate> a_by_b_, b_by_c_, b_by_f_, c_by_d_, c_by_e_, + d_by_d_, e_by_e_, f_by_e_; + + SimpleSignaturePolicy signature_policy_; + der::GeneralizedTime time_ = {2016, 4, 11, 0, 0, 0}; +}; + +// If the target cert is a trust anchor, it should verify and should not include +// anything else in the path. +TEST_F(PathBuilderMultiRootTest, TargetIsTrustAnchor) { + TrustStore trust_store; + trust_store.AddTrustedCertificate(a_by_b_); + trust_store.AddTrustedCertificate(b_by_f_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + EXPECT_EQ(1U, result.paths[result.best_result_index]->path.size()); + EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]); +} + +// If the target cert is directly issued by a trust anchor, it should verify +// without any intermediate certs being provided. +TEST_F(PathBuilderMultiRootTest, TargetDirectlySignedByTrustAnchor) { + TrustStore trust_store; + trust_store.AddTrustedCertificate(b_by_f_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + EXPECT_EQ(2U, result.paths[result.best_result_index]->path.size()); + EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]); + EXPECT_EQ(b_by_f_, result.paths[result.best_result_index]->path[1]); +} + +// Test that async cert queries are not made if the path can be successfully +// built with synchronously available certs. +TEST_F(PathBuilderMultiRootTest, TriesSyncFirst) { + TrustStore trust_store; + trust_store.AddTrustedCertificate(e_by_e_); + + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(b_by_f_); + sync_certs.AddCert(f_by_e_); + + AsyncCertIssuerSourceStatic async_certs; + async_certs.AddCert(b_by_c_); + async_certs.AddCert(c_by_e_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&async_certs); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + EXPECT_EQ(0, async_certs.num_async_gets()); +} + +// Test that async cert queries are not made if no callback is provided. +TEST_F(PathBuilderMultiRootTest, SychronousOnlyMode) { + TrustStore trust_store; + trust_store.AddTrustedCertificate(e_by_e_); + + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(f_by_e_); + + AsyncCertIssuerSourceStatic async_certs; + async_certs.AddCert(b_by_f_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&async_certs); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, path_builder.Run(base::Closure())); + + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error()); + EXPECT_EQ(0, async_certs.num_async_gets()); +} + +// If async queries are needed, all async sources will be queried +// simultaneously. +TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) { + TrustStore trust_store; + trust_store.AddTrustedCertificate(e_by_e_); + + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(b_by_c_); + sync_certs.AddCert(b_by_f_); + + AsyncCertIssuerSourceStatic async_certs1; + async_certs1.AddCert(c_by_e_); + + AsyncCertIssuerSourceStatic async_certs2; + async_certs2.AddCert(f_by_e_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&async_certs1); + path_builder.AddCertIssuerSource(&async_certs2); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + EXPECT_EQ(1, async_certs1.num_async_gets()); + EXPECT_EQ(1, async_certs2.num_async_gets()); +} + +// Test that PathBuilder does not generate longer paths than necessary if one of +// the supplied certs is itself a trust anchor. +TEST_F(PathBuilderMultiRootTest, TestLongChain) { + // Both D(D) and C(D) are trusted roots. + TrustStore trust_store; + trust_store.AddTrustedCertificate(d_by_d_); + trust_store.AddTrustedCertificate(c_by_d_); + + // Certs B(C), and C(D) are all supplied. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(b_by_c_); + sync_certs.AddCert(c_by_d_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + // The result path should be A(B) <- B(C) <- C(D) + // not the longer but also valid A(B) <- B(C) <- C(D) <- D(D) + EXPECT_EQ(3U, result.paths[result.best_result_index]->path.size()); +} + +// Test that PathBuilder will backtrack and try a different path if the first +// one doesn't work out. +TEST_F(PathBuilderMultiRootTest, TestBacktracking) { + // Only D(D) is a trusted root. + TrustStore trust_store; + trust_store.AddTrustedCertificate(d_by_d_); + + // Certs B(F) and F(E) are supplied synchronously, thus the path + // A(B) <- B(F) <- F(E) should be built first, though it won't verify. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(b_by_f_); + sync_certs.AddCert(f_by_e_); + + // Certs B(C), and C(D) are supplied asynchronously, so the path + // A(B) <- B(C) <- C(D) <- D(D) should be tried second. + AsyncCertIssuerSourceStatic async_certs; + async_certs.AddCert(b_by_c_); + async_certs.AddCert(c_by_d_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + path_builder.AddCertIssuerSource(&async_certs); + + EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + // The result path should be A(B) <- B(C) <- C(D) <- D(D) + ASSERT_EQ(4U, result.paths[result.best_result_index]->path.size()); + EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]); + EXPECT_EQ(b_by_c_, result.paths[result.best_result_index]->path[1]); + EXPECT_EQ(c_by_d_, result.paths[result.best_result_index]->path[2]); + EXPECT_EQ(d_by_d_, result.paths[result.best_result_index]->path[3]); +} + +// Test that whichever order CertIssuerSource returns the issuers, the path +// building still succeeds. +TEST_F(PathBuilderMultiRootTest, TestCertIssuerOrdering) { + // Only D(D) is a trusted root. + TrustStore trust_store; + trust_store.AddTrustedCertificate(d_by_d_); + + for (bool reverse_order : {false, true}) { + SCOPED_TRACE(reverse_order); + std::vector<scoped_refptr<ParsedCertificate>> certs = { + b_by_c_, b_by_f_, f_by_e_, c_by_d_, c_by_e_}; + CertIssuerSourceStatic sync_certs; + if (reverse_order) { + for (auto it = certs.rbegin(); it != certs.rend(); ++it) + sync_certs.AddCert(*it); + } else { + for (const auto& cert : certs) + sync_certs.AddCert(cert); + } + + CertPathBuilder::Result result; + CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, + time_, &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + // The result path should be A(B) <- B(C) <- C(D) <- D(D) + ASSERT_EQ(4U, result.paths[result.best_result_index]->path.size()); + EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]); + EXPECT_EQ(b_by_c_, result.paths[result.best_result_index]->path[1]); + EXPECT_EQ(c_by_d_, result.paths[result.best_result_index]->path[2]); + EXPECT_EQ(d_by_d_, result.paths[result.best_result_index]->path[3]); + } +} + +class PathBuilderKeyRolloverTest : public ::testing::Test { + public: + PathBuilderKeyRolloverTest() : signature_policy_(1024) {} + + void SetUp() override { + std::vector<std::string> path; + + ReadVerifyCertChainTestFromFile( + "net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem", + &path, &oldroot_, &time_); + ASSERT_EQ(2U, path.size()); + target_ = ParsedCertificate::CreateFromCertificateCopy(path[0], {}); + oldintermediate_ = + ParsedCertificate::CreateFromCertificateCopy(path[1], {}); + ASSERT_TRUE(target_); + ASSERT_TRUE(oldintermediate_); + + ReadVerifyCertChainTestFromFile( + "net/data/verify_certificate_chain_unittest/" + "key-rollover-longrolloverchain.pem", + &path, &oldroot_, &time_); + ASSERT_EQ(4U, path.size()); + newintermediate_ = + ParsedCertificate::CreateFromCertificateCopy(path[1], {}); + newroot_ = ParsedCertificate::CreateFromCertificateCopy(path[2], {}); + newrootrollover_ = + ParsedCertificate::CreateFromCertificateCopy(path[3], {}); + ASSERT_TRUE(newintermediate_); + ASSERT_TRUE(newroot_); + ASSERT_TRUE(newrootrollover_); + } + + protected: + // oldroot-------->newrootrollover newroot + // | | | + // v v v + // oldintermediate newintermediate + // | | + // +------------+-------------+ + // | + // v + // target + scoped_refptr<ParsedCertificate> target_; + scoped_refptr<ParsedCertificate> oldintermediate_; + scoped_refptr<ParsedCertificate> newintermediate_; + scoped_refptr<ParsedCertificate> oldroot_; + scoped_refptr<ParsedCertificate> newroot_; + scoped_refptr<ParsedCertificate> newrootrollover_; + + SimpleSignaturePolicy signature_policy_; + der::GeneralizedTime time_; +}; + +// Tests that if only the old root cert is trusted, the path builder can build a +// path through the new intermediate and rollover cert to the old root. +TEST_F(PathBuilderKeyRolloverTest, TestRolloverOnlyOldRootTrusted) { + // Only oldroot is trusted. + TrustStore trust_store; + trust_store.AddTrustedCertificate(oldroot_); + + // Old intermediate cert is not provided, so the pathbuilder will need to go + // through the rollover cert. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(newintermediate_); + sync_certs.AddCert(newrootrollover_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + // Path builder will first attempt: target <- newintermediate <- oldroot + // but it will fail since newintermediate is signed by newroot. + ASSERT_EQ(2U, result.paths.size()); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(oldroot_, result.paths[0]->path[2]); + + // Path builder will next attempt: + // target <- newintermediate <- newrootrollover <- oldroot + // which will succeed. + EXPECT_EQ(1U, result.best_result_index); + EXPECT_EQ(OK, result.paths[1]->error); + ASSERT_EQ(4U, result.paths[1]->path.size()); + EXPECT_EQ(target_, result.paths[1]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[1]->path[1]); + EXPECT_EQ(newrootrollover_, result.paths[1]->path[2]); + EXPECT_EQ(oldroot_, result.paths[1]->path[3]); +} + +// Tests that if both old and new roots are trusted it can build a path through +// either. +// TODO(mattm): Once prioritization is implemented, it should test that it +// always builds the path through the new intermediate and new root. +TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) { + // Both oldroot and newroot are trusted. + TrustStore trust_store; + trust_store.AddTrustedCertificate(oldroot_); + trust_store.AddTrustedCertificate(newroot_); + + // Both old and new intermediates + rollover cert are provided. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(oldintermediate_); + sync_certs.AddCert(newintermediate_); + sync_certs.AddCert(newrootrollover_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + // Path builder willattempt one of: + // target <- oldintermediate <- oldroot + // target <- newintermediate <- newroot + // either will succeed. + ASSERT_EQ(1U, result.paths.size()); + EXPECT_EQ(OK, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + if (result.paths[0]->path[1] != newintermediate_) { + DVLOG(1) << "USED OLD"; + EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(oldroot_, result.paths[0]->path[2]); + } else { + DVLOG(1) << "USED NEW"; + EXPECT_EQ(newintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(newroot_, result.paths[0]->path[2]); + } +} + +// Tests that multiple trust root matches on a single path will be considered. +// Both roots have the same subject but different keys. Only one of them will +// verify. +TEST_F(PathBuilderKeyRolloverTest, TestMultipleRootMatchesOnlyOneWorks) { + // Both newroot and oldroot are trusted. + TrustStore trust_store; + // Note: The test assumes newroot will be tried before oldroot. + // Currently this depends on the order the roots are added. + trust_store.AddTrustedCertificate(newroot_); + trust_store.AddTrustedCertificate(oldroot_); + + // Only oldintermediate is supplied, so the path with newroot should fail, + // oldroot should succeed. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(oldintermediate_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + ASSERT_EQ(2U, result.paths.size()); + + // Path builder will first attempt: target <- oldintermediate <- newroot + // but it will fail since oldintermediate is signed by oldroot. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(newroot_, result.paths[0]->path[2]); + + // Path builder will next attempt: + // target <- old intermediate <- oldroot + // which should succeed. + EXPECT_EQ(OK, result.paths[1]->error); + ASSERT_EQ(3U, result.paths[1]->path.size()); + EXPECT_EQ(target_, result.paths[1]->path[0]); + EXPECT_EQ(oldintermediate_, result.paths[1]->path[1]); + EXPECT_EQ(oldroot_, result.paths[1]->path[2]); +} + +// Tests that the path builder doesn't build longer than necessary paths. +TEST_F(PathBuilderKeyRolloverTest, TestRolloverLongChain) { + // Only oldroot is trusted. + TrustStore trust_store; + trust_store.AddTrustedCertificate(oldroot_); + + // New intermediate and new root are provided synchronously. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(newintermediate_); + sync_certs.AddCert(newroot_); + + // Rollover cert is only provided asynchronously. This will force the + // pathbuilder to first try building a longer than necessary path. + AsyncCertIssuerSourceStatic async_certs; + async_certs.AddCert(newrootrollover_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + path_builder.AddCertIssuerSource(&async_certs); + + EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + ASSERT_EQ(3U, result.paths.size()); + + // Path builder will first attempt: target <- newintermediate <- oldroot + // but it will fail since newintermediate is signed by newroot. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(oldroot_, result.paths[0]->path[2]); + + // Path builder will next attempt: + // target <- newintermediate <- newroot <- oldroot + // but it will fail since newroot is self-signed. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[1]->error); + ASSERT_EQ(4U, result.paths[1]->path.size()); + EXPECT_EQ(target_, result.paths[1]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[1]->path[1]); + EXPECT_EQ(newroot_, result.paths[1]->path[2]); + EXPECT_EQ(oldroot_, result.paths[1]->path[3]); + + // Path builder will skip: + // target <- newintermediate <- newroot <- newrootrollover <- ... + // Since newroot and newrootrollover have the same Name+SAN+SPKI. + + // Finally path builder will use: + // target <- newintermediate <- newrootrollover <- oldroot + EXPECT_EQ(2U, result.best_result_index); + EXPECT_EQ(OK, result.paths[2]->error); + ASSERT_EQ(4U, result.paths[2]->path.size()); + EXPECT_EQ(target_, result.paths[2]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[2]->path[1]); + EXPECT_EQ(newrootrollover_, result.paths[2]->path[2]); + EXPECT_EQ(oldroot_, result.paths[2]->path[3]); +} + +// If the target cert is a trust root, that alone is a valid path. +TEST_F(PathBuilderKeyRolloverTest, TestEndEntityIsTrustRoot) { + // Trust newintermediate. + TrustStore trust_store; + trust_store.AddTrustedCertificate(newintermediate_); + + CertPathBuilder::Result result; + // Newintermediate is also the target cert. + CertPathBuilder path_builder(newintermediate_, &trust_store, + &signature_policy_, time_, &result); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + ASSERT_EQ(1U, result.paths.size()); + EXPECT_EQ(OK, result.paths[0]->error); + ASSERT_EQ(1U, result.paths[0]->path.size()); + EXPECT_EQ(newintermediate_, result.paths[0]->path[0]); +} + +// If target has same Name+SAN+SPKI as a necessary intermediate, test if a path +// can still be built. +// Since LoopChecker will prevent the intermediate from being included, this +// currently does NOT verify. This case shouldn't occur in the web PKI. +TEST_F(PathBuilderKeyRolloverTest, + TestEndEntityHasSameNameAndSpkiAsIntermediate) { + // Trust oldroot. + TrustStore trust_store; + trust_store.AddTrustedCertificate(oldroot_); + + // New root rollover is provided synchronously. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(newrootrollover_); + + CertPathBuilder::Result result; + // Newroot is the target cert. + CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_, + time_, &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + // This could actually be OK, but CertPathBuilder does not build the + // newroot <- newrootrollover <- oldroot path. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error()); +} + +// If target has same Name+SAN+SPKI as the trust root, test that a (trivial) +// path can still be built. +TEST_F(PathBuilderKeyRolloverTest, + TestEndEntityHasSameNameAndSpkiAsTrustAnchor) { + // Trust newrootrollover. + TrustStore trust_store; + trust_store.AddTrustedCertificate(newrootrollover_); + + CertPathBuilder::Result result; + // Newroot is the target cert. + CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_, + time_, &result); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + + ASSERT_FALSE(result.paths.empty()); + const CertPathBuilder::ResultPath* best_result = + result.paths[result.best_result_index].get(); + + // Newroot has same name+SPKI as newrootrollover, thus the path is valid and + // only contains newroot. + EXPECT_EQ(OK, best_result->error); + ASSERT_EQ(1U, best_result->path.size()); + EXPECT_EQ(newroot_, best_result->path[0]); +} + +// Test that PathBuilder will not try the same path twice if multiple +// CertIssuerSources provide the same certificate. +TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediates) { + // Create a separate copy of oldintermediate. + scoped_refptr<ParsedCertificate> oldintermediate_dupe( + ParsedCertificate::CreateFromCertificateCopy( + oldintermediate_->der_cert().AsStringPiece(), {})); + + // Only newroot is a trusted root. + TrustStore trust_store; + trust_store.AddTrustedCertificate(newroot_); + + // The oldintermediate is supplied synchronously by |sync_certs1| and + // another copy of oldintermediate is supplied synchronously by |sync_certs2|. + // The path target <- oldintermediate <- newroot should be built first, + // though it won't verify. It should not be attempted again even though + // oldintermediate was supplied twice. + CertIssuerSourceStatic sync_certs1; + sync_certs1.AddCert(oldintermediate_); + CertIssuerSourceStatic sync_certs2; + sync_certs2.AddCert(oldintermediate_dupe); + + // The newintermediate is supplied asynchronously, so the path + // target <- newintermediate <- newroot should be tried second. + AsyncCertIssuerSourceStatic async_certs; + async_certs.AddCert(newintermediate_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs1); + path_builder.AddCertIssuerSource(&sync_certs2); + path_builder.AddCertIssuerSource(&async_certs); + + EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(OK, result.error()); + ASSERT_EQ(2U, result.paths.size()); + + // Path builder will first attempt: target <- oldintermediate <- newroot + // but it will fail since oldintermediate is signed by oldroot. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + // Compare the DER instead of ParsedCertificate pointer, don't care which copy + // of oldintermediate was used in the path. + EXPECT_EQ(oldintermediate_->der_cert(), result.paths[0]->path[1]->der_cert()); + EXPECT_EQ(newroot_, result.paths[0]->path[2]); + + // Path builder will next attempt: target <- newintermediate <- newroot + // which will succeed. + EXPECT_EQ(1U, result.best_result_index); + EXPECT_EQ(OK, result.paths[1]->error); + ASSERT_EQ(3U, result.paths[1]->path.size()); + EXPECT_EQ(target_, result.paths[1]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[1]->path[1]); + EXPECT_EQ(newroot_, result.paths[1]->path[2]); +} + +// Test that PathBuilder will not try the same path twice if the same cert is +// presented via a CertIssuerSources and a TrustAnchor. +TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediateAndRoot) { + // Create a separate copy of newroot. + scoped_refptr<ParsedCertificate> newroot_dupe( + ParsedCertificate::CreateFromCertificateCopy( + newroot_->der_cert().AsStringPiece(), {})); + + // Only newroot is a trusted root. + TrustStore trust_store; + trust_store.AddTrustedCertificate(newroot_); + + // The oldintermediate and newroot are supplied synchronously by |sync_certs|. + CertIssuerSourceStatic sync_certs; + sync_certs.AddCert(oldintermediate_); + sync_certs.AddCert(newroot_dupe); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&sync_certs); + + EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder)); + + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error()); + ASSERT_EQ(1U, result.paths.size()); + + // Path builder attempt: target <- oldintermediate <- newroot + // but it will fail since oldintermediate is signed by oldroot. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]); + // Compare the DER instead of ParsedCertificate pointer, don't care which copy + // of newroot was used in the path. + EXPECT_EQ(newroot_->der_cert(), result.paths[0]->path[2]->der_cert()); +} + +class MockCertIssuerSourceRequest : public CertIssuerSource::Request { + public: + MOCK_METHOD1(GetNext, CompletionStatus(scoped_refptr<ParsedCertificate>*)); +}; + +class MockCertIssuerSource : public CertIssuerSource { + public: + MOCK_METHOD2(SyncGetIssuersOf, + void(const ParsedCertificate*, ParsedCertificateList*)); + MOCK_METHOD3(AsyncGetIssuersOf, + void(const ParsedCertificate*, + const IssuerCallback&, + std::unique_ptr<Request>*)); +}; + +// Helper class to pass the Request to the PathBuilder when it calls +// AsyncGetIssuersOf. (GoogleMock has a ByMove helper, but it apparently can +// only be used with Return, not SetArgPointee.) +class CertIssuerSourceRequestMover { + public: + CertIssuerSourceRequestMover(std::unique_ptr<CertIssuerSource::Request> req) + : request_(std::move(req)) {} + void MoveIt(const ParsedCertificate* cert, + const CertIssuerSource::IssuerCallback& issuers_callback, + std::unique_ptr<CertIssuerSource::Request>* out_req) { + *out_req = std::move(request_); + } + + private: + std::unique_ptr<CertIssuerSource::Request> request_; +}; + +// Test that a single CertIssuerSource returning multiple async batches of +// issuers is handled correctly. Due to the StrictMocks, it also tests that path +// builder does not request issuers of certs that it shouldn't. +TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) { + StrictMock<MockCertIssuerSource> cert_issuer_source; + + // Only newroot is a trusted root. + TrustStore trust_store; + trust_store.AddTrustedCertificate(newroot_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&cert_issuer_source); + + CertIssuerSource::IssuerCallback target_issuers_callback; + // Create the mock CertIssuerSource::Request... + std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>> + target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>()); + // Keep a raw pointer to the Request... + StrictMock<MockCertIssuerSourceRequest>* target_issuers_req = + target_issuers_req_owner.get(); + // Setup helper class to pass ownership of the Request to the PathBuilder when + // it calls AsyncGetIssuersOf. + CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner)); + { + ::testing::InSequence s; + EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _)); + EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _)) + .WillOnce( + DoAll(SaveArg<1>(&target_issuers_callback), + Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt))); + } + + TestClosure callback; + CompletionStatus rv = path_builder.Run(callback.closure()); + ASSERT_EQ(CompletionStatus::ASYNC, rv); + + ASSERT_FALSE(target_issuers_callback.is_null()); + + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // First async batch: return oldintermediate_. + EXPECT_CALL(*target_issuers_req, GetNext(_)) + .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_), + Return(CompletionStatus::SYNC))) + .WillOnce( + DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC))); + { + ::testing::InSequence s; + // oldintermediate_ does not create a valid path, so both sync and async + // lookups are expected. + EXPECT_CALL(cert_issuer_source, + SyncGetIssuersOf(oldintermediate_.get(), _)); + EXPECT_CALL(cert_issuer_source, + AsyncGetIssuersOf(oldintermediate_.get(), _, _)); + } + target_issuers_callback.Run(target_issuers_req); + ::testing::Mock::VerifyAndClearExpectations(target_issuers_req); + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // Second async batch: return newintermediate_. + EXPECT_CALL(*target_issuers_req, GetNext(_)) + .WillOnce(DoAll(SetArgPointee<0>(newintermediate_), + Return(CompletionStatus::SYNC))) + .WillOnce( + DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC))); + // newroot_ is in the trust store, so this path will be completed + // synchronously. AsyncGetIssuersOf will not be called on newintermediate_. + EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _)); + target_issuers_callback.Run(target_issuers_req); + // Note that VerifyAndClearExpectations(target_issuers_req) is not called + // here. PathBuilder could have destroyed it already, so just let the + // expectations get checked by the destructor. + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // Ensure pathbuilder finished and filled result. + callback.WaitForResult(); + + EXPECT_EQ(OK, result.error()); + ASSERT_EQ(2U, result.paths.size()); + + // Path builder first attempts: target <- oldintermediate <- newroot + // but it will fail since oldintermediate is signed by oldroot. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(newroot_, result.paths[0]->path[2]); + + // After the second batch of async results, path builder will attempt: + // target <- newintermediate <- newroot which will succeed. + EXPECT_EQ(OK, result.paths[1]->error); + ASSERT_EQ(3U, result.paths[1]->path.size()); + EXPECT_EQ(target_, result.paths[1]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[1]->path[1]); + EXPECT_EQ(newroot_, result.paths[1]->path[2]); +} + +// Test that PathBuilder will not try the same path twice if CertIssuerSources +// asynchronously provide the same certificate multiple times. +TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) { + StrictMock<MockCertIssuerSource> cert_issuer_source; + + // Only newroot is a trusted root. + TrustStore trust_store; + trust_store.AddTrustedCertificate(newroot_); + + CertPathBuilder::Result result; + CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_, + &result); + path_builder.AddCertIssuerSource(&cert_issuer_source); + + CertIssuerSource::IssuerCallback target_issuers_callback; + // Create the mock CertIssuerSource::Request... + std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>> + target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>()); + // Keep a raw pointer to the Request... + StrictMock<MockCertIssuerSourceRequest>* target_issuers_req = + target_issuers_req_owner.get(); + // Setup helper class to pass ownership of the Request to the PathBuilder when + // it calls AsyncGetIssuersOf. + CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner)); + { + ::testing::InSequence s; + EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _)); + EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _)) + .WillOnce( + DoAll(SaveArg<1>(&target_issuers_callback), + Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt))); + } + + TestClosure callback; + CompletionStatus rv = path_builder.Run(callback.closure()); + ASSERT_EQ(CompletionStatus::ASYNC, rv); + + ASSERT_FALSE(target_issuers_callback.is_null()); + + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // First async batch: return oldintermediate_. + EXPECT_CALL(*target_issuers_req, GetNext(_)) + .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_), + Return(CompletionStatus::SYNC))) + .WillOnce( + DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC))); + { + ::testing::InSequence s; + // oldintermediate_ does not create a valid path, so both sync and async + // lookups are expected. + EXPECT_CALL(cert_issuer_source, + SyncGetIssuersOf(oldintermediate_.get(), _)); + EXPECT_CALL(cert_issuer_source, + AsyncGetIssuersOf(oldintermediate_.get(), _, _)); + } + target_issuers_callback.Run(target_issuers_req); + ::testing::Mock::VerifyAndClearExpectations(target_issuers_req); + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // Second async batch: return a different copy of oldintermediate_ again. + scoped_refptr<ParsedCertificate> oldintermediate_dupe( + ParsedCertificate::CreateFromCertificateCopy( + oldintermediate_->der_cert().AsStringPiece(), {})); + EXPECT_CALL(*target_issuers_req, GetNext(_)) + .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_dupe), + Return(CompletionStatus::SYNC))) + .WillOnce( + DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC))); + target_issuers_callback.Run(target_issuers_req); + // oldintermediate was already processed above, it should not generate any + // more requests. + ::testing::Mock::VerifyAndClearExpectations(target_issuers_req); + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // Third async batch: return newintermediate_. + EXPECT_CALL(*target_issuers_req, GetNext(_)) + .WillOnce(DoAll(SetArgPointee<0>(newintermediate_), + Return(CompletionStatus::SYNC))) + .WillOnce( + DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC))); + // newroot_ is in the trust store, so this path will be completed + // synchronously. AsyncGetIssuersOf will not be called on newintermediate_. + EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _)); + target_issuers_callback.Run(target_issuers_req); + // Note that VerifyAndClearExpectations(target_issuers_req) is not called + // here. PathBuilder could have destroyed it already, so just let the + // expectations get checked by the destructor. + ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source); + + // Ensure pathbuilder finished and filled result. + callback.WaitForResult(); + + EXPECT_EQ(OK, result.error()); + ASSERT_EQ(2U, result.paths.size()); + + // Path builder first attempts: target <- oldintermediate <- newroot + // but it will fail since oldintermediate is signed by oldroot. + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error); + ASSERT_EQ(3U, result.paths[0]->path.size()); + EXPECT_EQ(target_, result.paths[0]->path[0]); + EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]); + EXPECT_EQ(newroot_, result.paths[0]->path[2]); + + // The second async result does not generate any path. + + // After the third batch of async results, path builder will attempt: + // target <- newintermediate <- newroot which will succeed. + EXPECT_EQ(OK, result.paths[1]->error); + ASSERT_EQ(3U, result.paths[1]->path.size()); + EXPECT_EQ(target_, result.paths[1]->path[0]); + EXPECT_EQ(newintermediate_, result.paths[1]->path[1]); + EXPECT_EQ(newroot_, result.paths[1]->path[2]); +} + +} // namespace + +} // namespace net
diff --git a/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc b/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc new file mode 100644 index 0000000..e08ea30 --- /dev/null +++ b/net/cert/internal/path_builder_verify_certificate_chain_unittest.cc
@@ -0,0 +1,56 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/internal/path_builder.h" + +#include "net/cert/internal/cert_issuer_source_static.h" +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/trust_store.h" +#include "net/cert/internal/verify_certificate_chain_typed_unittest.h" + +namespace net { + +namespace { + +class PathBuilderDelegate { + public: + static void Verify(const ParsedCertificateList& chain, + const ParsedCertificateList& roots, + const der::GeneralizedTime& time, + bool expected_result) { + SimpleSignaturePolicy signature_policy(1024); + ASSERT_FALSE(chain.empty()); + + TrustStore trust_store; + for (const auto& root : roots) + trust_store.AddTrustedCertificate(root); + + CertIssuerSourceStatic intermediate_cert_issuer_source; + for (size_t i = 1; i < chain.size(); ++i) + intermediate_cert_issuer_source.AddCert(chain[i]); + + CertPathBuilder::Result result; + // First cert in the |chain| is the target. + CertPathBuilder path_builder(chain.front(), &trust_store, &signature_policy, + time, &result); + path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); + + CompletionStatus rv = path_builder.Run(base::Closure()); + EXPECT_EQ(CompletionStatus::SYNC, rv); + + EXPECT_EQ(expected_result, result.is_success()); + } +}; + +} // namespace + +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + VerifyCertificateChainSingleRootTest, + PathBuilderDelegate); + +INSTANTIATE_TYPED_TEST_CASE_P(PathBuilder, + VerifyCertificateChainNonSingleRootTest, + PathBuilderDelegate); + +} // namespace net
diff --git a/net/cert/internal/trust_store.cc b/net/cert/internal/trust_store.cc index 892698ba5..d46933b 100644 --- a/net/cert/internal/trust_store.cc +++ b/net/cert/internal/trust_store.cc
@@ -4,8 +4,6 @@ #include "net/cert/internal/trust_store.h" -#include "net/cert/internal/parsed_certificate.h" - namespace net { TrustStore::TrustStore() {} @@ -24,7 +22,7 @@ void TrustStore::FindTrustAnchorsByNormalizedName( const der::Input& normalized_name, - std::vector<scoped_refptr<ParsedCertificate>>* matches) const { + ParsedCertificateList* matches) const { auto range = anchors_.equal_range(normalized_name.AsStringPiece()); for (auto it = range.first; it != range.second; ++it) matches->push_back(it->second); @@ -33,9 +31,13 @@ bool TrustStore::IsTrustedCertificate(const ParsedCertificate* cert) const { auto range = anchors_.equal_range(cert->normalized_subject().AsStringPiece()); for (auto it = range.first; it != range.second; ++it) { - // First compare the ParsedCertificate pointers as an optimization, fall - // back to comparing full DER encoding. - if (it->second == cert || it->second->der_cert() == cert->der_cert()) + // First compare the ParsedCertificate pointers as an optimization. + if (it->second == cert || + // Trust check is based on Name+SPKI match. This could match the same + // certificate stored in a different ParsedCertificate object, or a + // different cert that has the same Name+SPKI. + (it->second->normalized_subject() == cert->normalized_subject() && + it->second->tbs().spki_tlv == cert->tbs().spki_tlv)) return true; } return false;
diff --git a/net/cert/internal/trust_store.h b/net/cert/internal/trust_store.h index 611af1c..0afbf9a 100644 --- a/net/cert/internal/trust_store.h +++ b/net/cert/internal/trust_store.h
@@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/strings/string_piece.h" #include "net/base/net_export.h" +#include "net/cert/internal/parsed_certificate.h" namespace net { @@ -18,8 +19,6 @@ class Input; } -class ParsedCertificate; - // A very simple implementation of a TrustStore, which contains a set of // trusted certificates. // TODO(mattm): convert this into an interface, provide implementations that @@ -36,9 +35,8 @@ void AddTrustedCertificate(scoped_refptr<ParsedCertificate> anchor); // Returns the trust anchors that match |name| in |*matches|, if any. - void FindTrustAnchorsByNormalizedName( - const der::Input& normalized_name, - std::vector<scoped_refptr<ParsedCertificate>>* matches) const; + void FindTrustAnchorsByNormalizedName(const der::Input& normalized_name, + ParsedCertificateList* matches) const; // Returns true if |cert| matches a certificate in the TrustStore. bool IsTrustedCertificate(const ParsedCertificate* cert) const
diff --git a/net/cert/internal/verify_certificate_chain.cc b/net/cert/internal/verify_certificate_chain.cc index 73bd6f13..baef57a 100644 --- a/net/cert/internal/verify_certificate_chain.cc +++ b/net/cert/internal/verify_certificate_chain.cc
@@ -9,7 +9,6 @@ #include "base/logging.h" #include "net/cert/internal/name_constraints.h" #include "net/cert/internal/parse_certificate.h" -#include "net/cert/internal/parsed_certificate.h" #include "net/cert/internal/signature_algorithm.h" #include "net/cert/internal/signature_policy.h" #include "net/cert/internal/trust_store.h" @@ -336,9 +335,6 @@ } // namespace -// TODO(eroman): Move this into existing anonymous namespace. -namespace { - // This implementation is structured to mimic the description of certificate // path verification given by RFC 5280 section 6.1. // @@ -346,7 +342,7 @@ // the chain. This root certificate is assumed to be trusted, and neither its // signature nor issuer name are verified. (It needn't be self-signed). bool VerifyCertificateChainAssumingTrustedRoot( - const std::vector<scoped_refptr<ParsedCertificate>>& certs, + const ParsedCertificateList& certs, // The trust store is only used for assertions. const TrustStore& trust_store, const SignaturePolicy* signature_policy, @@ -450,56 +446,4 @@ return true; } -// TODO(eroman): This function is a temporary hack in the absence of full -// path building. It may insert 1 certificate at the root of the -// chain to ensure that the path's root certificate is a trust anchor. -// -// Beyond this no other verification is done on the chain. The caller is -// responsible for verifying the subsequent chain's correctness. -WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor( - const TrustStore& trust_store, - std::vector<scoped_refptr<ParsedCertificate>>* certs) { - if (certs->empty()) - return false; - - // Check if the current root certificate is trusted. If it is then no - // extra work is needed. - if (trust_store.IsTrustedCertificate(certs->back().get())) - return true; - - std::vector<scoped_refptr<ParsedCertificate>> trust_anchors; - trust_store.FindTrustAnchorsByNormalizedName( - certs->back()->normalized_issuer(), &trust_anchors); - if (trust_anchors.empty()) - return false; - // TODO(mattm): this only tries the first match, even if there are multiple. - certs->push_back(std::move(trust_anchors[0])); - return true; -} - -} // namespace - -bool VerifyCertificateChain( - const std::vector<scoped_refptr<ParsedCertificate>>& cert_chain, - const TrustStore& trust_store, - const SignaturePolicy* signature_policy, - const der::GeneralizedTime& time, - std::vector<scoped_refptr<ParsedCertificate>>* trusted_chain_out) { - if (cert_chain.empty()) - return false; - - std::vector<scoped_refptr<ParsedCertificate>> full_chain = cert_chain; - - // Modify the certificate chain so that its root is a trusted certificate. - if (!BuildSimplePathToTrustAnchor(trust_store, &full_chain)) - return false; - - // Verify the chain. - bool success = VerifyCertificateChainAssumingTrustedRoot( - full_chain, trust_store, signature_policy, time); - if (success && trusted_chain_out != nullptr) - *trusted_chain_out = std::move(full_chain); - return success; -} - } // namespace net
diff --git a/net/cert/internal/verify_certificate_chain.h b/net/cert/internal/verify_certificate_chain.h index 291c843..5dc6275 100644 --- a/net/cert/internal/verify_certificate_chain.h +++ b/net/cert/internal/verify_certificate_chain.h
@@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "net/base/net_export.h" +#include "net/cert/internal/parsed_certificate.h" #include "net/der/input.h" namespace net { @@ -18,12 +19,12 @@ struct GeneralizedTime; } -class ParsedCertificate; class SignaturePolicy; class TrustStore; -// VerifyCertificateChain() verifies a certificate path (chain) based on the -// rules in RFC 5280. +// VerifyCertificateChainAssumingTrustedRoot() verifies a certificate path +// (chain) based on the rules in RFC 5280. The caller is responsible for +// building the path and ensuring the chain ends in a trusted root certificate. // // WARNING: This implementation is in progress, and is currently incomplete. // Consult an OWNER before using it. @@ -38,11 +39,11 @@ // // * cert_chain[0] is the target certificate to verify. // * cert_chain[i+1] holds the certificate that issued cert_chain[i]. -// * cert_chain[N-1] must be the trust anchor, or have been directly -// issued by a trust anchor. +// * cert_chain[N-1] must be the trust anchor. // // trust_store: -// Contains the set of trusted public keys (and their names). +// Contains the set of trusted public keys (and their names). This is only +// used to DCHECK that the final cert is a trust anchor. // // signature_policy: // The policy to use when verifying signatures (what hash algorithms are @@ -51,28 +52,17 @@ // time: // The UTC time to use for expiration checks. // -// trusted_chain_out: -// The vector to populate with the verified trusted certificate chain. -// * trusted_chain_out[0] is the target certificate verified. -// * trusted_chain_out[i+1] holds the certificate that issued -// trusted_chain_out[i]. -// * trusted_chain_out[N-1] is the trust anchor. -// If a nullptr is passed, this parameter is ignored. -// If the target certificate can not be verified, this parameter is -// ignored. -// // --------- // Outputs // --------- // // Returns true if the target certificate can be verified. -NET_EXPORT bool VerifyCertificateChain( - const std::vector<scoped_refptr<ParsedCertificate>>& cert_chain, +NET_EXPORT bool VerifyCertificateChainAssumingTrustedRoot( + const ParsedCertificateList& certs, + // The trust store is only used for assertions. const TrustStore& trust_store, const SignaturePolicy* signature_policy, - const der::GeneralizedTime& time, - std::vector<scoped_refptr<ParsedCertificate>>* trusted_chain_out) - WARN_UNUSED_RESULT; + const der::GeneralizedTime& time) WARN_UNUSED_RESULT; } // namespace net
diff --git a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc index 4c543f4..33a1156 100644 --- a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc +++ b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
@@ -52,35 +52,30 @@ ADD_FAILURE() << "cert_ders is empty"; return false; } - // First entry in the PKITS chain is the trust anchor. - TrustStore trust_store; - scoped_refptr<ParsedCertificate> anchor( - ParsedCertificate::CreateFromCertificateCopy(cert_ders[0], {})); - EXPECT_TRUE(anchor); - if (anchor) - trust_store.AddTrustedCertificate(std::move(anchor)); // PKITS lists chains from trust anchor to target, VerifyCertificateChain // takes them starting with the target and not including the trust anchor. std::vector<scoped_refptr<net::ParsedCertificate>> input_chain; - for (size_t i = cert_ders.size() - 1; i > 0; --i) { + for (auto i = cert_ders.rbegin(); i != cert_ders.rend(); ++i) { if (!net::ParsedCertificate::CreateAndAddToVector( - reinterpret_cast<const uint8_t*>(cert_ders[i].data()), - cert_ders[i].size(), + reinterpret_cast<const uint8_t*>(i->data()), i->size(), net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, {}, &input_chain)) { - ADD_FAILURE() << "cert " << i << " failed to parse"; + ADD_FAILURE() << "cert failed to parse"; return false; } } + TrustStore trust_store; + trust_store.AddTrustedCertificate(input_chain.back()); + SimpleSignaturePolicy signature_policy(1024); // Run all tests at the time the PKITS was published. der::GeneralizedTime time = {2011, 4, 15, 0, 0, 0}; - return VerifyCertificateChain(input_chain, trust_store, &signature_policy, - time, nullptr); + return VerifyCertificateChainAssumingTrustedRoot(input_chain, trust_store, + &signature_policy, time); } };
diff --git a/net/cert/internal/verify_certificate_chain_typed_unittest.h b/net/cert/internal/verify_certificate_chain_typed_unittest.h new file mode 100644 index 0000000..1ddd464 --- /dev/null +++ b/net/cert/internal/verify_certificate_chain_typed_unittest.h
@@ -0,0 +1,305 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CERT_INTERNAL_VERIFY_CERTIFICATE_CHAIN_TYPED_UNITTEST_H_ +#define NET_CERT_INTERNAL_VERIFY_CERTIFICATE_CHAIN_TYPED_UNITTEST_H_ + +#include "base/base_paths.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "net/cert/internal/parsed_certificate.h" +#include "net/cert/internal/test_helpers.h" +#include "net/cert/pem_tokenizer.h" +#include "net/der/input.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +template <typename TestDelegate> +class VerifyCertificateChainTest : public ::testing::Test { + public: + void RunTest(const char* file_name) { + ParsedCertificateList chain; + ParsedCertificateList roots; + der::GeneralizedTime time; + bool expected_result; + + ReadTestFromFile(file_name, &chain, &roots, &time, &expected_result); + + TestDelegate::Verify(chain, roots, time, expected_result); + } + + private: + // Reads a data file from the unit-test data. + std::string ReadTestFileToString(const std::string& file_name) { + // Compute the full path, relative to the src/ directory. + base::FilePath src_root; + PathService::Get(base::DIR_SOURCE_ROOT, &src_root); + base::FilePath filepath = src_root.AppendASCII( + std::string("net/data/verify_certificate_chain_unittest/") + file_name); + + // Read the full contents of the file. + std::string file_data; + if (!base::ReadFileToString(filepath, &file_data)) { + ADD_FAILURE() << "Couldn't read file: " << filepath.value(); + return std::string(); + } + + return file_data; + } + + // Reads a test case from |file_name|. Test cases are comprised of a + // certificate chain, trust store, a timestamp to validate at, and the + // expected result of verification. + void ReadTestFromFile(const std::string& file_name, + ParsedCertificateList* chain, + ParsedCertificateList* roots, + der::GeneralizedTime* time, + bool* verify_result) { + chain->clear(); + roots->clear(); + + std::string file_data = ReadTestFileToString(file_name); + + std::vector<std::string> pem_headers; + + const char kCertificateHeader[] = "CERTIFICATE"; + const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; + const char kTimeHeader[] = "TIME"; + const char kResultHeader[] = "VERIFY_RESULT"; + + pem_headers.push_back(kCertificateHeader); + pem_headers.push_back(kTrustedCertificateHeader); + pem_headers.push_back(kTimeHeader); + pem_headers.push_back(kResultHeader); + + bool has_time = false; + bool has_result = false; + + PEMTokenizer pem_tokenizer(file_data, pem_headers); + while (pem_tokenizer.GetNext()) { + const std::string& block_type = pem_tokenizer.block_type(); + const std::string& block_data = pem_tokenizer.data(); + + if (block_type == kCertificateHeader) { + ASSERT_TRUE(net::ParsedCertificate::CreateAndAddToVector( + reinterpret_cast<const uint8_t*>(block_data.data()), + block_data.size(), + net::ParsedCertificate::DataSource::INTERNAL_COPY, {}, chain)); + } else if (block_type == kTrustedCertificateHeader) { + ASSERT_TRUE(net::ParsedCertificate::CreateAndAddToVector( + reinterpret_cast<const uint8_t*>(block_data.data()), + block_data.size(), + net::ParsedCertificate::DataSource::INTERNAL_COPY, {}, roots)); + } else if (block_type == kTimeHeader) { + ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; + has_time = true; + ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time)); + } else if (block_type == kResultHeader) { + ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader; + ASSERT_TRUE(block_data == "SUCCESS" || block_data == "FAIL") + << "Unrecognized result: " << block_data; + has_result = true; + *verify_result = block_data == "SUCCESS"; + } + } + + ASSERT_TRUE(has_time); + ASSERT_TRUE(has_result); + } +}; + +// Tests that have only one root. These can be tested without requiring any +// path-building ability. +template <typename TestDelegate> +class VerifyCertificateChainSingleRootTest + : public VerifyCertificateChainTest<TestDelegate> {}; + +TYPED_TEST_CASE_P(VerifyCertificateChainSingleRootTest); + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetAndIntermediary) { + this->RunTest("target-and-intermediary.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IntermediaryLacksBasicConstraints) { + this->RunTest("intermediary-lacks-basic-constraints.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IntermediaryBasicConstraintsCaFalse) { + this->RunTest("intermediary-basic-constraints-ca-false.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IntermediaryBasicConstraintsNotCritical) { + this->RunTest("intermediary-basic-constraints-not-critical.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IntermediaryLacksSigningKeyUsage) { + this->RunTest("intermediary-lacks-signing-key-usage.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IntermediaryUnknownCriticalExtension) { + this->RunTest("intermediary-unknown-critical-extension.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IntermediaryUnknownNonCriticalExtension) { + this->RunTest("intermediary-unknown-non-critical-extension.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + ViolatesBasicConstraintsPathlen0) { + this->RunTest("violates-basic-constraints-pathlen-0.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + BasicConstraintsPathlen0SelfIssued) { + this->RunTest("basic-constraints-pathlen-0-self-issued.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetSignedWithMd5) { + this->RunTest("target-signed-with-md5.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, IntermediarySignedWithMd5) { + this->RunTest("intermediary-signed-with-md5.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetWrongSignature) { + this->RunTest("target-wrong-signature.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetSignedBy512bitRsa) { + this->RunTest("target-signed-by-512bit-rsa.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetSignedUsingEcdsa) { + this->RunTest("target-signed-using-ecdsa.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, ExpiredIntermediary) { + this->RunTest("expired-intermediary.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, ExpiredTarget) { + this->RunTest("expired-target.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, ExpiredTargetNotBefore) { + this->RunTest("expired-target-notBefore.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, ExpiredRoot) { + this->RunTest("expired-root.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetNotEndEntity) { + this->RunTest("target-not-end-entity.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + TargetHasKeyCertSignButNotCa) { + this->RunTest("target-has-keycertsign-but-not-ca.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, TargetHasPathlenButNotCa) { + this->RunTest("target-has-pathlen-but-not-ca.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + TargetUnknownCriticalExtension) { + this->RunTest("target-unknown-critical-extension.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IssuerAndSubjectNotByteForByteEqual) { + this->RunTest("issuer-and-subject-not-byte-for-byte-equal.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + IssuerAndSubjectNotByteForByteEqualAnchor) { + this->RunTest("issuer-and-subject-not-byte-for-byte-equal-anchor.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, ViolatesPathlen1Root) { + this->RunTest("violates-pathlen-1-root.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, NonSelfSignedRoot) { + this->RunTest("non-self-signed-root.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, KeyRolloverOldChain) { + this->RunTest("key-rollover-oldchain.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, KeyRolloverRolloverChain) { + this->RunTest("key-rollover-rolloverchain.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, + KeyRolloverLongRolloverChain) { + this->RunTest("key-rollover-longrolloverchain.pem"); +} + +TYPED_TEST_P(VerifyCertificateChainSingleRootTest, KeyRolloverNewChain) { + this->RunTest("key-rollover-newchain.pem"); +} + +// TODO(eroman): Add test that invalidate validity dates where the day or month +// ordinal not in range, like "March 39, 2016" are rejected. + +REGISTER_TYPED_TEST_CASE_P(VerifyCertificateChainSingleRootTest, + TargetAndIntermediary, + IntermediaryLacksBasicConstraints, + IntermediaryBasicConstraintsCaFalse, + IntermediaryBasicConstraintsNotCritical, + IntermediaryLacksSigningKeyUsage, + IntermediaryUnknownCriticalExtension, + IntermediaryUnknownNonCriticalExtension, + ViolatesBasicConstraintsPathlen0, + BasicConstraintsPathlen0SelfIssued, + TargetSignedWithMd5, + IntermediarySignedWithMd5, + TargetWrongSignature, + TargetSignedBy512bitRsa, + TargetSignedUsingEcdsa, + ExpiredIntermediary, + ExpiredTarget, + ExpiredTargetNotBefore, + ExpiredRoot, + TargetNotEndEntity, + TargetHasKeyCertSignButNotCa, + TargetHasPathlenButNotCa, + TargetUnknownCriticalExtension, + IssuerAndSubjectNotByteForByteEqual, + IssuerAndSubjectNotByteForByteEqualAnchor, + ViolatesPathlen1Root, + NonSelfSignedRoot, + KeyRolloverOldChain, + KeyRolloverRolloverChain, + KeyRolloverLongRolloverChain, + KeyRolloverNewChain); + +// Tests that have zero roots or more than one root. +template <typename TestDelegate> +class VerifyCertificateChainNonSingleRootTest + : public VerifyCertificateChainTest<TestDelegate> {}; + +TYPED_TEST_CASE_P(VerifyCertificateChainNonSingleRootTest); + +TYPED_TEST_P(VerifyCertificateChainNonSingleRootTest, UnknownRoot) { + this->RunTest("unknown-root.pem"); +} + +REGISTER_TYPED_TEST_CASE_P(VerifyCertificateChainNonSingleRootTest, + UnknownRoot); + +} // namespace net + +#endif // NET_CERT_INTERNAL_VERIFY_CERTIFICATE_CHAIN_TYPED_UNITTEST_H_
diff --git a/net/cert/internal/verify_certificate_chain_unittest.cc b/net/cert/internal/verify_certificate_chain_unittest.cc index 9103f12f..b857296 100644 --- a/net/cert/internal/verify_certificate_chain_unittest.cc +++ b/net/cert/internal/verify_certificate_chain_unittest.cc
@@ -4,254 +4,41 @@ #include "net/cert/internal/verify_certificate_chain.h" -#include "base/base_paths.h" -#include "base/files/file_util.h" -#include "base/path_service.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "net/cert/internal/parsed_certificate.h" #include "net/cert/internal/signature_policy.h" -#include "net/cert/internal/test_helpers.h" #include "net/cert/internal/trust_store.h" -#include "net/cert/pem_tokenizer.h" -#include "net/der/input.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "net/cert/internal/verify_certificate_chain_typed_unittest.h" namespace net { namespace { -// Reads a data file from the unit-test data. -std::string ReadTestFileToString(const std::string& file_name) { - // Compute the full path, relative to the src/ directory. - base::FilePath src_root; - PathService::Get(base::DIR_SOURCE_ROOT, &src_root); - base::FilePath filepath = src_root.AppendASCII( - std::string("net/data/verify_certificate_chain_unittest/") + file_name); +class VerifyCertificateChainAssumingTrustedRootDelegate { + public: + static void Verify(const ParsedCertificateList& chain, + const ParsedCertificateList& roots, + const der::GeneralizedTime& time, + bool expected_result) { + TrustStore trust_store; + ASSERT_EQ(1U, roots.size()); + trust_store.AddTrustedCertificate(roots[0]); - // Read the full contents of the file. - std::string file_data; - if (!base::ReadFileToString(filepath, &file_data)) { - ADD_FAILURE() << "Couldn't read file: " << filepath.value(); - return std::string(); + ParsedCertificateList full_chain(chain); + full_chain.push_back(roots[0]); + + SimpleSignaturePolicy signature_policy(1024); + + bool result = VerifyCertificateChainAssumingTrustedRoot( + full_chain, trust_store, &signature_policy, time); + + ASSERT_EQ(expected_result, result); } - - return file_data; -} - -// Reads a test case from |file_name|. Test cases are comprised of a -// certificate chain, trust store, a timestamp to validate at, and the -// expected result of verification. -void ReadTestFromFile(const std::string& file_name, - std::vector<std::string>* chain, - TrustStore* trust_store, - der::GeneralizedTime* time, - bool* verify_result) { - chain->clear(); - trust_store->Clear(); - - std::string file_data = ReadTestFileToString(file_name); - - std::vector<std::string> pem_headers; - - const char kCertificateHeader[] = "CERTIFICATE"; - const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; - const char kTimeHeader[] = "TIME"; - const char kResultHeader[] = "VERIFY_RESULT"; - - pem_headers.push_back(kCertificateHeader); - pem_headers.push_back(kTrustedCertificateHeader); - pem_headers.push_back(kTimeHeader); - pem_headers.push_back(kResultHeader); - - bool has_time = false; - bool has_result = false; - - PEMTokenizer pem_tokenizer(file_data, pem_headers); - while (pem_tokenizer.GetNext()) { - const std::string& block_type = pem_tokenizer.block_type(); - const std::string& block_data = pem_tokenizer.data(); - - if (block_type == kCertificateHeader) { - chain->push_back(block_data); - } else if (block_type == kTrustedCertificateHeader) { - scoped_refptr<ParsedCertificate> cert( - ParsedCertificate::CreateFromCertificateCopy(block_data, {})); - ASSERT_TRUE(cert); - trust_store->AddTrustedCertificate(std::move(cert)); - } else if (block_type == kTimeHeader) { - ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; - has_time = true; - ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time)); - } else if (block_type == kResultHeader) { - ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader; - ASSERT_TRUE(block_data == "SUCCESS" || block_data == "FAIL") - << "Unrecognized result: " << block_data; - has_result = true; - *verify_result = block_data == "SUCCESS"; - } - } - - ASSERT_TRUE(has_time); - ASSERT_TRUE(has_result); -} - -void RunTest(const char* file_name) { - std::vector<std::string> chain; - TrustStore trust_store; - der::GeneralizedTime time; - bool expected_result; - - ReadTestFromFile(file_name, &chain, &trust_store, &time, &expected_result); - - std::vector<scoped_refptr<net::ParsedCertificate>> input_chain; - for (const auto& cert_der : chain) { - ASSERT_TRUE(net::ParsedCertificate::CreateAndAddToVector( - reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size(), - net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, {}, - &input_chain)); - } - - SimpleSignaturePolicy signature_policy(1024); - - std::vector<scoped_refptr<ParsedCertificate>> trusted_chain; - bool result = VerifyCertificateChain(input_chain, trust_store, - &signature_policy, time, &trusted_chain); - if (result) { - ASSERT_EQ(trusted_chain.size(), input_chain.size() + 1); - ASSERT_TRUE(std::equal(input_chain.begin(), input_chain.end(), - trusted_chain.begin())); - ASSERT_TRUE(trust_store.IsTrustedCertificate(trusted_chain.back().get())); - } else { - ASSERT_EQ(trusted_chain.size(), 0u); - } - - ASSERT_EQ(expected_result, result); -} - -TEST(VerifyCertificateChainTest, TargetAndIntermediary) { - RunTest("target-and-intermediary.pem"); -} - -TEST(VerifyCertificateChainTest, UnknownRoot) { - RunTest("unknown-root.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediaryLacksBasicConstraints) { - RunTest("intermediary-lacks-basic-constraints.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsCaFalse) { - RunTest("intermediary-basic-constraints-ca-false.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsNotCritical) { - RunTest("intermediary-basic-constraints-not-critical.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediaryLacksSigningKeyUsage) { - RunTest("intermediary-lacks-signing-key-usage.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediaryUnknownCriticalExtension) { - RunTest("intermediary-unknown-critical-extension.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediaryUnknownNonCriticalExtension) { - RunTest("intermediary-unknown-non-critical-extension.pem"); -} - -TEST(VerifyCertificateChainTest, ViolatesBasicConstraintsPathlen0) { - RunTest("violates-basic-constraints-pathlen-0.pem"); -} - -TEST(VerifyCertificateChainTest, BasicConstraintsPathlen0SelfIssued) { - RunTest("basic-constraints-pathlen-0-self-issued.pem"); -} - -TEST(VerifyCertificateChainTest, TargetSignedWithMd5) { - RunTest("target-signed-with-md5.pem"); -} - -TEST(VerifyCertificateChainTest, IntermediarySignedWithMd5) { - RunTest("intermediary-signed-with-md5.pem"); -} - -TEST(VerifyCertificateChainTest, TargetWrongSignature) { - RunTest("target-wrong-signature.pem"); -} - -TEST(VerifyCertificateChainTest, TargetSignedBy512bitRsa) { - RunTest("target-signed-by-512bit-rsa.pem"); -} - -TEST(VerifyCertificateChainTest, TargetSignedUsingEcdsa) { - RunTest("target-signed-using-ecdsa.pem"); -} - -TEST(VerifyCertificateChainTest, ExpiredIntermediary) { - RunTest("expired-intermediary.pem"); -} - -TEST(VerifyCertificateChainTest, ExpiredTarget) { - RunTest("expired-target.pem"); -} - -TEST(VerifyCertificateChainTest, ExpiredTargetNotBefore) { - RunTest("expired-target-notBefore.pem"); -} - -TEST(VerifyCertificateChainTest, ExpiredRoot) { - RunTest("expired-root.pem"); -} - -TEST(VerifyCertificateChainTest, TargetNotEndEntity) { - RunTest("target-not-end-entity.pem"); -} - -TEST(VerifyCertificateChainTest, TargetHasKeyCertSignButNotCa) { - RunTest("target-has-keycertsign-but-not-ca.pem"); -} - -TEST(VerifyCertificateChainTest, TargetHasPathlenButNotCa) { - RunTest("target-has-pathlen-but-not-ca.pem"); -} - -TEST(VerifyCertificateChainTest, TargetUnknownCriticalExtension) { - RunTest("target-unknown-critical-extension.pem"); -} - -TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqual) { - RunTest("issuer-and-subject-not-byte-for-byte-equal.pem"); -} - -TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqualAnchor) { - RunTest("issuer-and-subject-not-byte-for-byte-equal-anchor.pem"); -} - -TEST(VerifyCertificateChainTest, ViolatesPathlen1Root) { - RunTest("violates-pathlen-1-root.pem"); -} - -TEST(VerifyCertificateChainTest, NonSelfSignedRoot) { - RunTest("non-self-signed-root.pem"); -} - -// Tests that verifying a chain with no certificates fails. -TEST(VerifyCertificateChainTest, EmptyChainIsInvalid) { - TrustStore trust_store; - der::GeneralizedTime time; - std::vector<scoped_refptr<ParsedCertificate>> chain; - SimpleSignaturePolicy signature_policy(2048); - - ASSERT_FALSE(VerifyCertificateChain(chain, trust_store, &signature_policy, - time, nullptr)); -} - -// TODO(eroman): Add test that invalidate validity dates where the day or month -// ordinal not in range, like "March 39, 2016" are rejected. +}; } // namespace +INSTANTIATE_TYPED_TEST_CASE_P( + VerifyCertificateChainAssumingTrustedRoot, + VerifyCertificateChainSingleRootTest, + VerifyCertificateChainAssumingTrustedRootDelegate); + } // namespace net
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc index 407c9ff2..2469f28 100644 --- a/net/cookies/canonical_cookie.cc +++ b/net/cookies/canonical_cookie.cc
@@ -480,9 +480,9 @@ const std::string& name) { const char kSecurePrefix[] = "__Secure-"; const char kHostPrefix[] = "__Host-"; - if (name.find(kSecurePrefix) == 0) + if (base::StartsWith(name, kSecurePrefix, base::CompareCase::SENSITIVE)) return CanonicalCookie::COOKIE_PREFIX_SECURE; - if (name.find(kHostPrefix) == 0) + if (base::StartsWith(name, kHostPrefix, base::CompareCase::SENSITIVE)) return CanonicalCookie::COOKIE_PREFIX_HOST; return CanonicalCookie::COOKIE_PREFIX_NONE; }
diff --git a/net/data/fuzzer_dictionaries/net_dns_hosts_parse_fuzzer.dict b/net/data/fuzzer_dictionaries/net_dns_hosts_parse_fuzzer.dict new file mode 100644 index 0000000..dd72cefb --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_dns_hosts_parse_fuzzer.dict
@@ -0,0 +1,843 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting DNS responses. + +# Some 16-bit big-endian values. Useful in a number of fields. Includes +# A, AAAA, and CNAME IDs, low values for record counts, and multiples of +# lengths of A and AAAA data fields. +"\x00\x00" +"\x00\x01" +"\x00\x02" +"\x00\x03" +"\x00\x04" +"\x00\x05" +"\x00\x08" +"\x00\x0C" +"\x00\x10" +"\x00\x1C" +"\x00\x20" +"\x00\x30" + +# Some encoded domain names. +"\x03foo\x00" +"\x03foo\x03com\x00" +"\x01a\x03foo\x03com\x00" +"\x03bar\x00" + +# Message headers (Without message ID field). +"\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Truncated message, requiring TCP fallback. +"\x83\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Varying number of answers +"\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x02\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x10\x00\x00\x00\x00" + +# A, AAAA, and CNAME request suffixes - appear after domain name. +"\x00\x01\x00\x01" +"\x00\x1c\x00\x01" +"\x00\x05\x00\x01" + +# A, AAAA, and CNAME requests for foo and foo.com. +"\x03foo\x00\x00\x01\x00\x01" +"\x03foo\x00\x00\x1c\x00\x01" +"\x03foo\x00\x00\x05\x00\x01" +"\x03foo\x03com\x00\x00\x01\x00\x01" +"\x03foo\x03com\x00\x00\x1c\x00\x01" +"\x03foo\x03com\x00\x00\x05\x00\x01" + +# All of the answers below are missing the name field, which should appear +# first. + +# A answer suffixes, two different IP and TTLs. +"\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x01\x02\x03\x04" +"\x00\x01\x00\x01\x00\x00\x00\xFF\x00\x04\x02\x03\x04\x05" + +# AAAA answer suffixes, two different IPs and TTLs. +"\x00\x1C\x00\x01\x00\x00\x00\x00\x00\x08\x01\x02\x03\x04\x05\x06\x07\x08" +"\x00\x1C\x00\x01\x00\x00\x00\xFF\x00\x08\x02\x03\x04\x05\x06\x07\x08\x09" + +# CDATA answer suffixes, first two truncated as well. +"\x00\x05\x00\x01\x00\x00\x00\xFF" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03foo\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03bar\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x09\x03foo\x03com\x00" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_dns_hosts_parse_fuzzer binary, RFC 1034 and RFC 1035. +"all" +"QNAME=ISI.EDU.," +"pointing" +"C.ISI.EDU," +"C.ISI.EDU." +"C.ISI.EDU)" +"52.0.0.10.IN-ADDR.ARPA." +"[RFC-799]" +"XX.LCS.MIT.EDU," +"XX.LCS.MIT.EDU." +"CPU" +"C.ISI.EDU:" +"A.B.C.D" +"ARPA" +"*.X.COM" +"IN-ADDR.ARPA" +"0" +"\"*.X\"," +"resources" +"supported" +"string" +"returning" +"AXFR" +"YALE.ARPA." +"B.C.D," +"list" +"large" +"CNAME," +"ASCII" +"M." +"YALE.EDU." +"direct" +"IN," +"[RFC-1035]." +"\"A\"" +"\"IN-ADDR.ARPA\"." +"HINFO" +"RFC-1031," +"QCLASS=IN," +"Z." +"QCLASS=IN." +"ARPANET" +"QNAME=65.0.6.26.IN-ADDR.ARPA.,QCLASS=IN,QTYPE=PTR" +"section" +"51.0.0.10.IN-ADDR.ARPA." +"|(VAXA.ISI.EDU,VENERA.ISI.EDU," +"DEC-2060" +"version" +"[RFC-1031]." +"TTL" +"[RFC-742]" +"QTYPE=NS" +"FTP" +"hash" +"QTYPE=CNAME," +"RFC-793," +"address" +"SNAME," +"[" +"\"NAME/FINGER\"," +"SRI-NIC.ARPA." +"SRI-NIC.ARPA," +"MB" +"SRI-NIC.ARPA:" +"QTYPE=CNAME" +"NOT" +"MX" +"[RFC-821]" +"useful" +"select" +"SRI-NIC.ARPA" +"use" +"SNAME" +"from" +"to" +"positive" +"(QCLASS)" +"[RFC-1032]." +"(DNS)," +"TELNET," +"call" +"B.X," +"memory" +"type" +"[RFC-973]" +"RFC-822." +"QNAME=SIR-NIC.ARPA," +"MILNET" +"TOPS20" +"[IEN-116," +"PTR)." +"HOSTS.TXT," +"COMSAT," +"EXPIRE." +"must" +"EVEN" +"|(C.ISI.EDU,SRI-NIC.ARPA" +"QNAME=USC-ISIC.ARPA.," +"this" +"CNAME." +"work" +"EDU," +"EDU." +"EDU" +"following" +"root" +"[RFC-1010]" +"F." +"J.," +"type." +"high" +"[RFC-953]" +"US" +"allowed" +"serial" +"IEN-116," +"[RFC-1032]" +"[RFC-1033]." +"write" +"NOSC" +"VENERA.ISI.EDU.|" +"Z.X" +"A" +"QTYPE," +"[RFC-810]" +"QTYPE." +"may" +"after" +"RFC-1032," +"such" +"data" +"\"A" +"a" +"UDP" +"short" +"(CNAME)" +"[RFC-1002]" +"UDEL.EDU." +"SRI," +"RFC-953." +"RFC-953," +"TELNET)." +"(HOSTS.TXT)" +"ISI.EDU" +"MIL" +"[RFC-952]" +"RFC-830," +"pointer" +"its" +"STYPE" +"before" +"HAS" +"RR" +"HOSTMASTER.SRI-NIC.ARPA." +"65.0.6.26.IN-ADDR.ARPA," +"65.0.6.26.IN-ADDR.ARPA." +"RD" +"NAMES" +"YALE" +"QNAME=BRL.MIL," +"RA," +"ACM," +"QCLASS" +"ARPA." +"not" +"(QTYPE)," +"OPCODE=SQUERY,RESPONSE" +"name" +"RFC," +"mode" +"RFC-799," +"ICS.UCI" +"RESOLVERS" +"A.X.COM" +"SOME" +"CNAME" +"UDEL" +"(QNAME)," +"E." +"space" +"L." +"MINIMUM" +"RDATA" +"supports" +"REFRESH," +"HOSTMASTER@SRI-NIC.ARPA." +"This" +"SLIST:" +"free" +"RFC" +"base" +"RFC-952" +"received." +"SLIST." +"SLIST," +"DATA." +"thread" +"YALE-BULLDOG.ARPA." +"could" +"QCLASS," +"times" +"length" +"HOSTMASTER@SRI-NIC.ARPA" +"MIT.EDU" +"already" +"CONFIGURED" +"number" +"one" +"RFC-" +"Start" +"ISI" +"RFC." +"RFC-1001," +"open" +"CSNET" +"size" +"\"" +"X." +"A.ISI.EDU" +"TTL)" +"\"HOSTNAME" +"unknown" +"top" +"SERVERS" +"too" +"RFC-953]." +"QTYPE" +"BBN" +"that" +"completed" +"XX" +"*.A.X.COM" +"QTYPE=MX," +"MX." +"RD." +"K." +"target" +"16" +"Z.X)," +"LCS.MIT.EDU" +"[RFC-1031]" +"and" +"[RFC-805]" +"[RFC-811]" +"(RCODE)" +"have" +"need" +"RESPONSE," +"null" +"any" +"contents" +"|(SRI-NIC.ARPA," +"SOMEONE" +"RESOURCE" +"73.0.0.26.IN-ADDR.ARPA." +"DARPA" +"ACC.ARPA." +"RFC-812," +"-" +"mechanism" +"internal" +"take" +"which" +"MIL." +"MIL," +"=" +"UCI" +"RFC-742," +"multiple" +"TCP/IP" +"USC-ISIC.ARPA." +"QNAME=USC-ISIC.ARPA," +"The" +"]" +"class" +"D." +"RFC-1010," +"D," +"RFC-805," +"AA," +"VAXA.ISI.EDU." +"QNAME=ISI.EDU," +"MG)." +"\"DOD" +"QNAME=SRI-NIC.ARPA," +"text" +"labels" +"VENERA" +"RFC-1033," +"INCORRECTLY" +"[RFC-" +"Z" +"[RFC-952," +"RECORDS" +"implementation" +"true" +"cache" +"[RFC-768]" +"XX.LCS.MIT.EDU" +"only" +"PVM@ISI.EDU." +"RETRY," +"get" +"PVM@ISI.EDU" +"ACHILLES" +"LOUIE.UDEL.EDU." +"IN-ADDR" +"resource" +"A.ISI" +"THIS" +"NIC" +"(via" +"Zones" +"RFC-920," +"J." +"RFC-920." +"common" +"set" +"configured" +"QNAME=SRI-NIC.ARPA.," +"this," +"are" +"RFC-883]." +"A.ISI.EDU." +"A.ISI.EDU)" +"INTRODUCTION" +"TCP" +"MIT" +"PC" +"unable" +"probably" +"C.D," +"103.0.3.26.IN-ADDR.ARPA." +"available" +"C" +"parent" +"RFC-830]." +"REFRESH" +"UNIX" +"CH)." +"key" +"52.0.0.10.IN-ADDR.ARPA" +"P." +"AND" +"RFC-1002," +"OPCODE=SQUERY" +"ROME.UCI" +"LCS" +"PDP-11/70" +"ISI.EDU," +"ISI.EDU." +"MAILB" +"[RFC-974]" +"CONCEPTS" +"[RFC-920]" +"SOA," +"RCODE=NE" +"DNS." +"DNS," +"poll" +"UMN-REI-UC.ARPA." +"SNAME." +"[RFC-883]" +"RFC-974," +"RFC-1002" +"create" +"S.," +"." +"[RFC-830]" +"expected" +"empty" +"RA" +"CH" +"(RD)" +"VENERA.ISI.EDU." +"SRI" +"A.B.X," +"NAME" +"value" +"while" +"error" +"loop" +"\"NICNAME/WHOIS\"," +"is" +"CACHE" +"FACILITIES" +"in" +"|(XX.LCS.MIT.EDU," +"SOA" +"binary" +"[RFC-819]" +")" +"SRI-NIC" +"V." +"\"A\"." +"QNAME." +"QNAME," +"units" +"(NE)." +"used" +"IP" +"\"." +"IN" +"ID" +"IF" +"task" +"SCENARIO" +"RFC-883," +"HOSTS.TXT" +"Names" +"RFC-811," +"the" +"If" +"being" +"EXPIRE" +"RFC-882," +"|ACHILLES.MIT.EDU)" +"XX.COM." +"(RDATA)" +"source" +"CSNET." +"build" +"ACHILLES.MIT.EDU." +"format" +"read" +"(AA)" +"ISIC.ARPA," +"SERIAL" +"VAXA.ISI" +"found," +"SLIST" +"sorting" +"OPCODE=SQUERY," +"OF" +"AUTHORITY" +"OS" +"AA" +"DOMAIN" +"because" +"SRI-NIC.ARPA.|" +"some" +"back" +"growth" +"USC-ISIC.ARPA," +"RFC-821," +"happens" +"for" +"W." +"RFC-883" +"X.COM" +"avoid" +"does" +"allocate" +"COM" +"assuming" +"BRL" +"PTR" +"[RFC-793]" +"be" +"QCLASS=*" +"MIT.EDU." +"by" +"C." +"on" +"SCLASS" +"of" +"FTP)" +"FTP," +"UK" +"or" +"ACC" +"SBELT." +"SBELT," +"No" +"(SBELT)" +"A.X.COM." +"A.X.COM," +"REFERENCES" +"USC-ISIC.ARPA" +"[RFC-1001]" +"RESPONSE" +"transfer" +"support" +"*" +"NE" +"long" +"QTYPE=*" +"start" +"C.ISI.EDU" +"TTL," +"RD," +"\"4.3.2.1.IN-ADDR.ARPA\"." +"NS" +"was" +"RR." +"RR," +"QTYPE=A" +"MEMO" +"but" +"QNAME" +"[RFC-1001," +"DNS" +"line" +"trying" +"with" +"TCP/UDP" +"count" +"SBELT" +"(NIC)" +"up" +"classes:" +"RFC-768," +"[IEN-116]" +"VAXA" +"NETBIOS" +"called" +"delete" +"CIC" +"USC-" +"RETRY" +"RFC-810," +"RECORDS," +"an" +"To" +"as" +"at" +"file" +"[RFC-812]" +"physical" +"X.COM," +"no" +"[RFC-882," +"when" +"A," +"virtual" +"RFC-952," +"RFC-952." +"valid" +"test" +"you" +"IP/TCP" +"STATUS" +"requested" +"[RFC-974" +"SPACE" +"QNAME=SIR-NIC.ARPA.," +"RFC-819," +"variable" +"[RFC-882]" +"BIBLIOGRAPHY" +"[RFC-1033]" +"US." +"\"MILNET" +"As" +"RFC-973," +"RFC-882" +"QTYPE=MX" +"4.0.10.18.IN-ADDR.ARPA." +"FOO.F.ISI.ARPA," +"Assuming" +"[RFC-1034]," +"[RFC-1034]." +"UNIX\"" +"IMPLEMENTATION" +"EGP." +"ANCOUNT" +"@" +"P" +"TXT-DATA" +"RMAILBX" +"|QTYPE=A," +"QDCOUNT" +"[RFC-1010]." +"EMAILBX" +"IN-" +"OPCODE=IQUERY," +"MX)" +"ID=997" +"\"VENERA.ISI.EDU\";" +"OPCODE" +"MILNET-GW.ISI.EDU." +"52.0.2.10.IN-ADDR.ARPA." +"objects" +"MD" +"MG" +"MF" +"MR" +"QNAME=10.IN-ADDR.ARPA." +"S." +"GGP" +"few" +"QTYPE=PTR," +"MD," +"F" +"[RFC-974]." +"MGMNAME" +"GW.LCS.MIT.EDU." +"GW.LCS.MIT.EDU," +"V" +"\\DDD" +"ALL" +"10.IN-ADDR.ARPA." +"closing" +"EXCHANGE." +"MADNAME." +"$ORIGIN" +"HIS" +"26.IN-ADDR.ARPA." +"(MD)" +"QTYPES" +"PROTOCOL" +"26.IN-ADDR.ARPA" +"NSCOUNT" +"(MR)" +"PREFERENCE" +"<BIT" +"$INCLUDE." +"MR)" +"VAXA.ISI.EDU" +"77.0.0.10.IN-ADDR.ARPA." +"\"IBM-PC" +"$INCLUDE" +"SERVER" +"18.IN-ADDR.ARPA." +"ADDRESS" +"Check" +"static" +"GW.ISI.EDU." +"(QNAME)." +"GW.ISI.EDU," +"F.ISI.ARPA," +"F.ISI.ARPA." +"time." +"PTRDNAME" +"HOSTMASTER@SRI-" +"(STATUS)" +"(MINFO)" +"(MG)" +"QCLASS." +"(HS)" +"X," +"MNAME" +"QNAME=VENERA.ISI.EDU" +"MASTER" +"(IN)" +"KNOWS." +"RNAME" +"|QR|" +"VAXA.ISI.EDU," +"R" +"1)" +"ARCOUNT" +"RCODE" +"NEWNAME" +"CLASS" +"begin" +"(MF)." +"Common" +"<RDATA>" +"QR" +"average" +"QNAME=6.0.0.10.IN-ADDR.ARPA," +"WKS" +"SYSTEM," +"MADNAME" +"ARPANET," +"MINFO" +"DEFINITIONS" +"failed" +"[RFC-1034]" +"(QCLASS)," +"SPECIFICATION" +"X" +"THE" +"MILNET." +"MILNET-" +"bytes" +"(MX)" +"NSDNAME" +"10.IN-ADDR.ARPA" +"|AA|TC|RD|RA|" +"QTYPE=A," +"corruption" +"FOO.F.ISI.ARPA" +"(QUERY)" +"MF," +"FOO" +"CURLEY" +"X.Y," +"AXFR," +"S" +"MAILA" +"exceeds" +"ISI.EDU:" +"103.0.0.26.IN-ADDR.ARPA." +"MOE" +"[RFC-822]." +"CHAOS" +"NAMEDROPPERS@SRI-NIC.ARPA" +"SOA." +"RESOLVER" +"A.X," +"EXCHANGE" +"SMTP" +"QCLASS=*," +"CS" +"$ORIGIN," +"B.X" +"(MB," +"TYPE" +"Size" +"parse" +"ADDR.ARPA" +"(SMTP)." +"key." +"MAP>" +"OWN" +"VENERA.ISI.EDU" +"DDD." +"MB." +"NS," +"I" +"OPCODE=RESPONSE," +"ARPA," +"WITHIN" +"tables" +"unsigned" +"LARRY" +"D" +"\\X" +"WHICH" +"(IQUERY)" +"QCLASS=IN" +"discarded" +"6.0.0.10.IN-ADDR.ARPA." +"MAIL" +"QTYPE=MAILB" +"HS" +"SUPPORT" +"STOOGES" +"X.Y" +"/" +"(SLIST)." +"O" +"OS," +"OFFSET" +"FILES" +"RR)," +"$INCLUDE," +"guard" +"[<TTL>]" +"CRLF" +"Error" +"ERRORS-TO:" +"22.0.2.10.IN-ADDR.ARPA." +"default" +"MESSAGES" +"signed" +"<SUBSYS>ISI-MAILBOXES.TXT" +"MULTICS.MIT.EDU." +"NULL" +"application" +"TXT" +"TC" +"PROTOCOL=TCP" +"UDP." +"UDP," +"F.ISI.ARPA" +"(EXPERIMENTAL)" +"RDLENGTH" +"NIC.ARPA" +
diff --git a/net/data/fuzzer_dictionaries/net_dns_record_fuzzer.dict b/net/data/fuzzer_dictionaries/net_dns_record_fuzzer.dict new file mode 100644 index 0000000..eb26765b --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_dns_record_fuzzer.dict
@@ -0,0 +1,843 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting DNS responses. + +# Some 16-bit big-endian values. Useful in a number of fields. Includes +# A, AAAA, and CNAME IDs, low values for record counts, and multiples of +# lengths of A and AAAA data fields. +"\x00\x00" +"\x00\x01" +"\x00\x02" +"\x00\x03" +"\x00\x04" +"\x00\x05" +"\x00\x08" +"\x00\x0C" +"\x00\x10" +"\x00\x1C" +"\x00\x20" +"\x00\x30" + +# Some encoded domain names. +"\x03foo\x00" +"\x03foo\x03com\x00" +"\x01a\x03foo\x03com\x00" +"\x03bar\x00" + +# Message headers (Without message ID field). +"\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Truncated message, requiring TCP fallback. +"\x83\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Varying number of answers +"\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x02\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x10\x00\x00\x00\x00" + +# A, AAAA, and CNAME request suffixes - appear after domain name. +"\x00\x01\x00\x01" +"\x00\x1c\x00\x01" +"\x00\x05\x00\x01" + +# A, AAAA, and CNAME requests for foo and foo.com. +"\x03foo\x00\x00\x01\x00\x01" +"\x03foo\x00\x00\x1c\x00\x01" +"\x03foo\x00\x00\x05\x00\x01" +"\x03foo\x03com\x00\x00\x01\x00\x01" +"\x03foo\x03com\x00\x00\x1c\x00\x01" +"\x03foo\x03com\x00\x00\x05\x00\x01" + +# All of the answers below are missing the name field, which should appear +# first. + +# A answer suffixes, two different IP and TTLs. +"\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x01\x02\x03\x04" +"\x00\x01\x00\x01\x00\x00\x00\xFF\x00\x04\x02\x03\x04\x05" + +# AAAA answer suffixes, two different IPs and TTLs. +"\x00\x1C\x00\x01\x00\x00\x00\x00\x00\x08\x01\x02\x03\x04\x05\x06\x07\x08" +"\x00\x1C\x00\x01\x00\x00\x00\xFF\x00\x08\x02\x03\x04\x05\x06\x07\x08\x09" + +# CDATA answer suffixes, first two truncated as well. +"\x00\x05\x00\x01\x00\x00\x00\xFF" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03foo\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03bar\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x09\x03foo\x03com\x00" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_dns_record_fuzzer binary, RFC 1034 and RFC 1035. +"all" +"QNAME=ISI.EDU.," +"pointing" +"C.ISI.EDU," +"C.ISI.EDU." +"C.ISI.EDU)" +"52.0.0.10.IN-ADDR.ARPA." +"[RFC-799]" +"XX.LCS.MIT.EDU," +"XX.LCS.MIT.EDU." +"CPU" +"C.ISI.EDU:" +"A.B.C.D" +"ARPA" +"*.X.COM" +"IN-ADDR.ARPA" +"0" +"\"*.X\"," +"resources" +"supported" +"string" +"returning" +"AXFR" +"YALE.ARPA." +"B.C.D," +"list" +"large" +"CNAME," +"ASCII" +"M." +"YALE.EDU." +"direct" +"IN," +"[RFC-1035]." +"\"A\"" +"\"IN-ADDR.ARPA\"." +"HINFO" +"RFC-1031," +"QCLASS=IN," +"Z." +"QCLASS=IN." +"ARPANET" +"QNAME=65.0.6.26.IN-ADDR.ARPA.,QCLASS=IN,QTYPE=PTR" +"section" +"51.0.0.10.IN-ADDR.ARPA." +"|(VAXA.ISI.EDU,VENERA.ISI.EDU," +"DEC-2060" +"version" +"[RFC-1031]." +"TTL" +"[RFC-742]" +"QTYPE=NS" +"FTP" +"hash" +"QTYPE=CNAME," +"RFC-793," +"address" +"SNAME," +"[" +"\"NAME/FINGER\"," +"SRI-NIC.ARPA." +"SRI-NIC.ARPA," +"MB" +"SRI-NIC.ARPA:" +"QTYPE=CNAME" +"NOT" +"MX" +"[RFC-821]" +"useful" +"select" +"SRI-NIC.ARPA" +"use" +"SNAME" +"from" +"to" +"positive" +"(QCLASS)" +"[RFC-1032]." +"(DNS)," +"TELNET," +"call" +"B.X," +"memory" +"type" +"[RFC-973]" +"RFC-822." +"QNAME=SIR-NIC.ARPA," +"MILNET" +"TOPS20" +"[IEN-116," +"PTR)." +"HOSTS.TXT," +"COMSAT," +"EXPIRE." +"must" +"EVEN" +"|(C.ISI.EDU,SRI-NIC.ARPA" +"QNAME=USC-ISIC.ARPA.," +"this" +"CNAME." +"work" +"EDU," +"EDU." +"EDU" +"following" +"root" +"[RFC-1010]" +"F." +"J.," +"type." +"high" +"[RFC-953]" +"US" +"allowed" +"serial" +"IEN-116," +"[RFC-1032]" +"[RFC-1033]." +"write" +"NOSC" +"VENERA.ISI.EDU.|" +"Z.X" +"A" +"QTYPE," +"[RFC-810]" +"QTYPE." +"may" +"after" +"RFC-1032," +"such" +"data" +"\"A" +"a" +"UDP" +"short" +"(CNAME)" +"[RFC-1002]" +"UDEL.EDU." +"SRI," +"RFC-953." +"RFC-953," +"TELNET)." +"(HOSTS.TXT)" +"ISI.EDU" +"MIL" +"[RFC-952]" +"RFC-830," +"pointer" +"its" +"STYPE" +"before" +"HAS" +"RR" +"HOSTMASTER.SRI-NIC.ARPA." +"65.0.6.26.IN-ADDR.ARPA," +"65.0.6.26.IN-ADDR.ARPA." +"RD" +"NAMES" +"YALE" +"QNAME=BRL.MIL," +"RA," +"ACM," +"QCLASS" +"ARPA." +"not" +"(QTYPE)," +"OPCODE=SQUERY,RESPONSE" +"name" +"RFC," +"mode" +"RFC-799," +"ICS.UCI" +"RESOLVERS" +"A.X.COM" +"SOME" +"CNAME" +"UDEL" +"(QNAME)," +"E." +"space" +"L." +"MINIMUM" +"RDATA" +"supports" +"REFRESH," +"HOSTMASTER@SRI-NIC.ARPA." +"This" +"SLIST:" +"free" +"RFC" +"base" +"RFC-952" +"received." +"SLIST." +"SLIST," +"DATA." +"thread" +"YALE-BULLDOG.ARPA." +"could" +"QCLASS," +"times" +"length" +"HOSTMASTER@SRI-NIC.ARPA" +"MIT.EDU" +"already" +"CONFIGURED" +"number" +"one" +"RFC-" +"Start" +"ISI" +"RFC." +"RFC-1001," +"open" +"CSNET" +"size" +"\"" +"X." +"A.ISI.EDU" +"TTL)" +"\"HOSTNAME" +"unknown" +"top" +"SERVERS" +"too" +"RFC-953]." +"QTYPE" +"BBN" +"that" +"completed" +"XX" +"*.A.X.COM" +"QTYPE=MX," +"MX." +"RD." +"K." +"target" +"16" +"Z.X)," +"LCS.MIT.EDU" +"[RFC-1031]" +"and" +"[RFC-805]" +"[RFC-811]" +"(RCODE)" +"have" +"need" +"RESPONSE," +"null" +"any" +"contents" +"|(SRI-NIC.ARPA," +"SOMEONE" +"RESOURCE" +"73.0.0.26.IN-ADDR.ARPA." +"DARPA" +"ACC.ARPA." +"RFC-812," +"-" +"mechanism" +"internal" +"take" +"which" +"MIL." +"MIL," +"=" +"UCI" +"RFC-742," +"multiple" +"TCP/IP" +"USC-ISIC.ARPA." +"QNAME=USC-ISIC.ARPA," +"The" +"]" +"class" +"D." +"RFC-1010," +"D," +"RFC-805," +"AA," +"VAXA.ISI.EDU." +"QNAME=ISI.EDU," +"MG)." +"\"DOD" +"QNAME=SRI-NIC.ARPA," +"text" +"labels" +"VENERA" +"RFC-1033," +"INCORRECTLY" +"[RFC-" +"Z" +"[RFC-952," +"RECORDS" +"implementation" +"true" +"cache" +"[RFC-768]" +"XX.LCS.MIT.EDU" +"only" +"PVM@ISI.EDU." +"RETRY," +"get" +"PVM@ISI.EDU" +"ACHILLES" +"LOUIE.UDEL.EDU." +"IN-ADDR" +"resource" +"A.ISI" +"THIS" +"NIC" +"(via" +"Zones" +"RFC-920," +"J." +"RFC-920." +"common" +"set" +"configured" +"QNAME=SRI-NIC.ARPA.," +"this," +"are" +"RFC-883]." +"A.ISI.EDU." +"A.ISI.EDU)" +"INTRODUCTION" +"TCP" +"MIT" +"PC" +"unable" +"probably" +"C.D," +"103.0.3.26.IN-ADDR.ARPA." +"available" +"C" +"parent" +"RFC-830]." +"REFRESH" +"UNIX" +"CH)." +"key" +"52.0.0.10.IN-ADDR.ARPA" +"P." +"AND" +"RFC-1002," +"OPCODE=SQUERY" +"ROME.UCI" +"LCS" +"PDP-11/70" +"ISI.EDU," +"ISI.EDU." +"MAILB" +"[RFC-974]" +"CONCEPTS" +"[RFC-920]" +"SOA," +"RCODE=NE" +"DNS." +"DNS," +"poll" +"UMN-REI-UC.ARPA." +"SNAME." +"[RFC-883]" +"RFC-974," +"RFC-1002" +"create" +"S.," +"." +"[RFC-830]" +"expected" +"empty" +"RA" +"CH" +"(RD)" +"VENERA.ISI.EDU." +"SRI" +"A.B.X," +"NAME" +"value" +"while" +"error" +"loop" +"\"NICNAME/WHOIS\"," +"is" +"CACHE" +"FACILITIES" +"in" +"|(XX.LCS.MIT.EDU," +"SOA" +"binary" +"[RFC-819]" +")" +"SRI-NIC" +"V." +"\"A\"." +"QNAME." +"QNAME," +"units" +"(NE)." +"used" +"IP" +"\"." +"IN" +"ID" +"IF" +"task" +"SCENARIO" +"RFC-883," +"HOSTS.TXT" +"Names" +"RFC-811," +"the" +"If" +"being" +"EXPIRE" +"RFC-882," +"|ACHILLES.MIT.EDU)" +"XX.COM." +"(RDATA)" +"source" +"CSNET." +"build" +"ACHILLES.MIT.EDU." +"format" +"read" +"(AA)" +"ISIC.ARPA," +"SERIAL" +"VAXA.ISI" +"found," +"SLIST" +"sorting" +"OPCODE=SQUERY," +"OF" +"AUTHORITY" +"OS" +"AA" +"DOMAIN" +"because" +"SRI-NIC.ARPA.|" +"some" +"back" +"growth" +"USC-ISIC.ARPA," +"RFC-821," +"happens" +"for" +"W." +"RFC-883" +"X.COM" +"avoid" +"does" +"allocate" +"COM" +"assuming" +"BRL" +"PTR" +"[RFC-793]" +"be" +"QCLASS=*" +"MIT.EDU." +"by" +"C." +"on" +"SCLASS" +"of" +"FTP)" +"FTP," +"UK" +"or" +"ACC" +"SBELT." +"SBELT," +"No" +"(SBELT)" +"A.X.COM." +"A.X.COM," +"REFERENCES" +"USC-ISIC.ARPA" +"[RFC-1001]" +"RESPONSE" +"transfer" +"support" +"*" +"NE" +"long" +"QTYPE=*" +"start" +"C.ISI.EDU" +"TTL," +"RD," +"\"4.3.2.1.IN-ADDR.ARPA\"." +"NS" +"was" +"RR." +"RR," +"QTYPE=A" +"MEMO" +"but" +"QNAME" +"[RFC-1001," +"DNS" +"line" +"trying" +"with" +"TCP/UDP" +"count" +"SBELT" +"(NIC)" +"up" +"classes:" +"RFC-768," +"[IEN-116]" +"VAXA" +"NETBIOS" +"called" +"delete" +"CIC" +"USC-" +"RETRY" +"RFC-810," +"RECORDS," +"an" +"To" +"as" +"at" +"file" +"[RFC-812]" +"physical" +"X.COM," +"no" +"[RFC-882," +"when" +"A," +"virtual" +"RFC-952," +"RFC-952." +"valid" +"test" +"you" +"IP/TCP" +"STATUS" +"requested" +"[RFC-974" +"SPACE" +"QNAME=SIR-NIC.ARPA.," +"RFC-819," +"variable" +"[RFC-882]" +"BIBLIOGRAPHY" +"[RFC-1033]" +"US." +"\"MILNET" +"As" +"RFC-973," +"RFC-882" +"QTYPE=MX" +"4.0.10.18.IN-ADDR.ARPA." +"FOO.F.ISI.ARPA," +"Assuming" +"[RFC-1034]," +"[RFC-1034]." +"UNIX\"" +"IMPLEMENTATION" +"EGP." +"ANCOUNT" +"@" +"P" +"TXT-DATA" +"RMAILBX" +"|QTYPE=A," +"QDCOUNT" +"[RFC-1010]." +"EMAILBX" +"IN-" +"OPCODE=IQUERY," +"MX)" +"ID=997" +"\"VENERA.ISI.EDU\";" +"OPCODE" +"MILNET-GW.ISI.EDU." +"52.0.2.10.IN-ADDR.ARPA." +"objects" +"MD" +"MG" +"MF" +"MR" +"QNAME=10.IN-ADDR.ARPA." +"S." +"GGP" +"few" +"QTYPE=PTR," +"MD," +"F" +"[RFC-974]." +"MGMNAME" +"GW.LCS.MIT.EDU." +"GW.LCS.MIT.EDU," +"V" +"\\DDD" +"ALL" +"10.IN-ADDR.ARPA." +"closing" +"EXCHANGE." +"MADNAME." +"$ORIGIN" +"HIS" +"26.IN-ADDR.ARPA." +"(MD)" +"QTYPES" +"PROTOCOL" +"26.IN-ADDR.ARPA" +"NSCOUNT" +"(MR)" +"PREFERENCE" +"<BIT" +"$INCLUDE." +"MR)" +"VAXA.ISI.EDU" +"77.0.0.10.IN-ADDR.ARPA." +"\"IBM-PC" +"$INCLUDE" +"SERVER" +"18.IN-ADDR.ARPA." +"ADDRESS" +"Check" +"static" +"GW.ISI.EDU." +"(QNAME)." +"GW.ISI.EDU," +"F.ISI.ARPA," +"F.ISI.ARPA." +"time." +"PTRDNAME" +"HOSTMASTER@SRI-" +"(STATUS)" +"(MINFO)" +"(MG)" +"QCLASS." +"(HS)" +"X," +"MNAME" +"QNAME=VENERA.ISI.EDU" +"MASTER" +"(IN)" +"KNOWS." +"RNAME" +"|QR|" +"VAXA.ISI.EDU," +"R" +"1)" +"ARCOUNT" +"RCODE" +"NEWNAME" +"CLASS" +"begin" +"(MF)." +"Common" +"<RDATA>" +"QR" +"average" +"QNAME=6.0.0.10.IN-ADDR.ARPA," +"WKS" +"SYSTEM," +"MADNAME" +"ARPANET," +"MINFO" +"DEFINITIONS" +"failed" +"[RFC-1034]" +"(QCLASS)," +"SPECIFICATION" +"X" +"THE" +"MILNET." +"MILNET-" +"bytes" +"(MX)" +"NSDNAME" +"10.IN-ADDR.ARPA" +"|AA|TC|RD|RA|" +"QTYPE=A," +"corruption" +"FOO.F.ISI.ARPA" +"(QUERY)" +"MF," +"FOO" +"CURLEY" +"X.Y," +"AXFR," +"S" +"MAILA" +"exceeds" +"ISI.EDU:" +"103.0.0.26.IN-ADDR.ARPA." +"MOE" +"[RFC-822]." +"CHAOS" +"NAMEDROPPERS@SRI-NIC.ARPA" +"SOA." +"RESOLVER" +"A.X," +"EXCHANGE" +"SMTP" +"QCLASS=*," +"CS" +"$ORIGIN," +"B.X" +"(MB," +"TYPE" +"Size" +"parse" +"ADDR.ARPA" +"(SMTP)." +"key." +"MAP>" +"OWN" +"VENERA.ISI.EDU" +"DDD." +"MB." +"NS," +"I" +"OPCODE=RESPONSE," +"ARPA," +"WITHIN" +"tables" +"unsigned" +"LARRY" +"D" +"\\X" +"WHICH" +"(IQUERY)" +"QCLASS=IN" +"discarded" +"6.0.0.10.IN-ADDR.ARPA." +"MAIL" +"QTYPE=MAILB" +"HS" +"SUPPORT" +"STOOGES" +"X.Y" +"/" +"(SLIST)." +"O" +"OS," +"OFFSET" +"FILES" +"RR)," +"$INCLUDE," +"guard" +"[<TTL>]" +"CRLF" +"Error" +"ERRORS-TO:" +"22.0.2.10.IN-ADDR.ARPA." +"default" +"MESSAGES" +"signed" +"<SUBSYS>ISI-MAILBOXES.TXT" +"MULTICS.MIT.EDU." +"NULL" +"application" +"TXT" +"TC" +"PROTOCOL=TCP" +"UDP." +"UDP," +"F.ISI.ARPA" +"(EXPERIMENTAL)" +"RDLENGTH" +"NIC.ARPA" +
diff --git a/net/data/fuzzer_dictionaries/net_get_domain_and_registry_fuzzer.dict b/net/data/fuzzer_dictionaries/net_get_domain_and_registry_fuzzer.dict new file mode 100644 index 0000000..b5c58a5 --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_get_domain_and_registry_fuzzer.dict
@@ -0,0 +1,848 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting DNS responses. + +# Some 16-bit big-endian values. Useful in a number of fields. Includes +# A, AAAA, and CNAME IDs, low values for record counts, and multiples of +# lengths of A and AAAA data fields. +"\x00\x00" +"\x00\x01" +"\x00\x02" +"\x00\x03" +"\x00\x04" +"\x00\x05" +"\x00\x08" +"\x00\x0C" +"\x00\x10" +"\x00\x1C" +"\x00\x20" +"\x00\x30" + +# Some encoded domain names. +"\x03foo\x00" +"\x03foo\x03com\x00" +"\x01a\x03foo\x03com\x00" +"\x03bar\x00" + +# Message headers (Without message ID field). +"\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Truncated message, requiring TCP fallback. +"\x83\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Varying number of answers +"\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x02\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x10\x00\x00\x00\x00" + +# A, AAAA, and CNAME request suffixes - appear after domain name. +"\x00\x01\x00\x01" +"\x00\x1c\x00\x01" +"\x00\x05\x00\x01" + +# A, AAAA, and CNAME requests for foo and foo.com. +"\x03foo\x00\x00\x01\x00\x01" +"\x03foo\x00\x00\x1c\x00\x01" +"\x03foo\x00\x00\x05\x00\x01" +"\x03foo\x03com\x00\x00\x01\x00\x01" +"\x03foo\x03com\x00\x00\x1c\x00\x01" +"\x03foo\x03com\x00\x00\x05\x00\x01" + +# All of the answers below are missing the name field, which should appear +# first. + +# A answer suffixes, two different IP and TTLs. +"\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x01\x02\x03\x04" +"\x00\x01\x00\x01\x00\x00\x00\xFF\x00\x04\x02\x03\x04\x05" + +# AAAA answer suffixes, two different IPs and TTLs. +"\x00\x1C\x00\x01\x00\x00\x00\x00\x00\x08\x01\x02\x03\x04\x05\x06\x07\x08" +"\x00\x1C\x00\x01\x00\x00\x00\xFF\x00\x08\x02\x03\x04\x05\x06\x07\x08\x09" + +# CDATA answer suffixes, first two truncated as well. +"\x00\x05\x00\x01\x00\x00\x00\xFF" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03foo\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03bar\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x09\x03foo\x03com\x00" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_get_domain_and_registry_fuzzer binary, RFC 1034 and RFC 1035. +"all" +"QNAME=ISI.EDU.," +"pointing" +"C.ISI.EDU," +"C.ISI.EDU." +"C.ISI.EDU)" +"52.0.0.10.IN-ADDR.ARPA." +"[RFC-799]" +"XX.LCS.MIT.EDU," +"XX.LCS.MIT.EDU." +"CPU" +"C.ISI.EDU:" +"A.B.C.D" +"ARPA" +"*.X.COM" +"IN-ADDR.ARPA" +"to" +"\"*.X\"," +"resources" +"supported" +"string" +"returning" +"AXFR" +"YALE.ARPA." +"B.C.D," +"list" +"large" +"CNAME," +"ASCII" +"M." +"YALE.EDU." +"direct" +"IN," +"[RFC-1035]." +"\"A\"" +"\"IN-ADDR.ARPA\"." +"HINFO" +"RFC-1031," +"QCLASS=IN," +"Z." +"QCLASS=IN." +"ARPANET" +"QNAME=65.0.6.26.IN-ADDR.ARPA.,QCLASS=IN,QTYPE=PTR" +"section" +"51.0.0.10.IN-ADDR.ARPA." +"|(VAXA.ISI.EDU,VENERA.ISI.EDU," +"DEC-2060" +"version" +"[RFC-1031]." +"TTL" +"[RFC-742]" +"QTYPE=NS" +"FTP" +"hash" +"QTYPE=CNAME," +"RFC-793," +"address" +"SNAME," +"[" +"\"NAME/FINGER\"," +"SRI-NIC.ARPA." +"SRI-NIC.ARPA," +"MB" +"SRI-NIC.ARPA:" +"QTYPE=CNAME" +"NOT" +"MX" +"[RFC-821]" +"useful" +"select" +"SRI-NIC.ARPA" +"use" +"SNAME" +"from" +"0" +"positive" +"(QCLASS)" +"[RFC-1032]." +"(DNS)," +"TELNET," +"call" +"B.X," +"memory" +"type" +"[RFC-973]" +"RFC-822." +"QNAME=SIR-NIC.ARPA," +"MILNET" +"TOPS20" +"[IEN-116," +"PTR)." +"HOSTS.TXT," +"COMSAT," +"EXPIRE." +"must" +"EVEN" +"|(C.ISI.EDU,SRI-NIC.ARPA" +"QNAME=USC-ISIC.ARPA.," +"this" +"CNAME." +"work" +"EDU," +"EDU." +"EDU" +"following" +"root" +"[RFC-1010]" +"F." +"J.," +"type." +"high" +"[RFC-953]" +"US" +"allowed" +"serial" +"IEN-116," +"[RFC-1032]" +"end" +"[RFC-1033]." +"write" +"NOSC" +"VENERA.ISI.EDU.|" +"Z.X" +"A" +"QTYPE," +"[RFC-810]" +"QTYPE." +"may" +"after" +"RFC-1032," +"such" +"data" +"\"A" +"a" +"UDP" +"short" +"(CNAME)" +"[RFC-1002]" +"UDEL.EDU." +"SRI," +"RFC-953." +"RFC-953," +"TELNET)." +"(HOSTS.TXT)" +"ISI.EDU" +"MIL" +"[RFC-952]" +"RFC-830," +"pointer" +"its" +"STYPE" +"before" +"HAS" +"RR" +"HOSTMASTER.SRI-NIC.ARPA." +"65.0.6.26.IN-ADDR.ARPA," +"65.0.6.26.IN-ADDR.ARPA." +"RD" +"NAMES" +"YALE" +"QNAME=BRL.MIL," +"RA," +"ACM," +"QCLASS" +"ARPA." +"not" +"(QTYPE)," +"OPCODE=SQUERY,RESPONSE" +"name" +"RFC," +"mode" +"RFC-799," +"ICS.UCI" +"RESOLVERS" +"A.X.COM" +"SOME" +"CNAME" +"UDEL" +"(QNAME)," +"E." +"space" +"L." +"MINIMUM" +"RDATA" +"supports" +"REFRESH," +"HOSTMASTER@SRI-NIC.ARPA." +"This" +"SLIST:" +"free" +"RFC" +"base" +"RFC-952" +"received." +"SLIST." +"SLIST," +"DATA." +"thread" +"YALE-BULLDOG.ARPA." +"could" +"QCLASS," +"times" +"length" +"HOSTMASTER@SRI-NIC.ARPA" +"MIT.EDU" +"already" +"CONFIGURED" +"number" +"one" +"RFC-" +"Start" +"ISI" +"RFC." +"RFC-1001," +"open" +"CSNET" +"size" +"\"" +"X." +"A.ISI.EDU" +"TTL)" +"\"HOSTNAME" +"unknown" +"top" +"SERVERS" +"2" +"too" +"RFC-953]." +"QTYPE" +"BBN" +"that" +"completed" +"XX" +"*.A.X.COM" +"QTYPE=MX," +"MX." +"RD." +"K." +"target" +"16" +"Z.X)," +"LCS.MIT.EDU" +"[RFC-1031]" +"and" +"[RFC-805]" +"[RFC-811]" +"(RCODE)" +"have" +"need" +"RESPONSE," +"null" +"any" +"contents" +"|(SRI-NIC.ARPA," +"SOMEONE" +"RESOURCE" +"73.0.0.26.IN-ADDR.ARPA." +"DARPA" +"ACC.ARPA." +"RFC-812," +"-" +"mechanism" +"internal" +"take" +"which" +"MIL." +"MIL," +"=" +"UCI" +"RFC-742," +"multiple" +"TCP/IP" +"USC-ISIC.ARPA." +"QNAME=USC-ISIC.ARPA," +"The" +"]" +"class" +"D." +"RFC-1010," +"D," +"RFC-805," +"AA," +"VAXA.ISI.EDU." +"QNAME=ISI.EDU," +"MG)." +"\"DOD" +"QNAME=SRI-NIC.ARPA," +"text" +"labels" +"VENERA" +"RFC-1033," +"INCORRECTLY" +"[RFC-" +"Z" +"[RFC-952," +"RECORDS" +"implementation" +"with" +"cache" +"[RFC-768]" +"XX.LCS.MIT.EDU" +"only" +"PVM@ISI.EDU." +"RETRY," +"get" +"PVM@ISI.EDU" +"ACHILLES" +"LOUIE.UDEL.EDU." +"IN-ADDR" +"resource" +"A.ISI" +"THIS" +"NIC" +"(via" +"Zones" +"RFC-920," +"J." +"RFC-920." +"common" +"set" +"configured" +"QNAME=SRI-NIC.ARPA.," +"this," +"are" +"RFC-883]." +"A.ISI.EDU." +"A.ISI.EDU)" +"INTRODUCTION" +"TCP" +"MIT" +"PC" +"3" +"unable" +"probably" +"C.D," +"103.0.3.26.IN-ADDR.ARPA." +"available" +"C" +"parent" +"RFC-830]." +"REFRESH" +"UNIX" +"CH)." +"key" +"52.0.0.10.IN-ADDR.ARPA" +"P." +"AND" +"RFC-1002," +"OPCODE=SQUERY" +"ROME.UCI" +"LCS" +"PDP-11/70" +"ISI.EDU," +"ISI.EDU." +"MAILB" +"[RFC-974]" +"CONCEPTS" +"[RFC-920]" +"SOA," +"RCODE=NE" +"DNS." +"DNS," +"poll" +"UMN-REI-UC.ARPA." +"SNAME." +"[RFC-883]" +"RFC-974," +"RFC-1002" +"create" +"S.," +"." +"[RFC-830]" +"expected" +"empty" +"RA" +"CH" +"(RD)" +"VENERA.ISI.EDU." +"SRI" +"A.B.X," +"NAME" +"value" +"while" +"error" +"loop" +"\"NICNAME/WHOIS\"," +"is" +"CACHE" +"FACILITIES" +"in" +"|(XX.LCS.MIT.EDU," +"SOA" +"binary" +"[RFC-819]" +")" +"SRI-NIC" +"V." +"\"A\"." +"QNAME." +"QNAME," +"units" +"(NE)." +"used" +"IP" +"\"." +"IN" +"ID" +"IF" +"task" +"SCENARIO" +"RFC-883," +"HOSTS.TXT" +"Names" +"RFC-811," +"the" +"If" +"being" +"EXPIRE" +"RFC-882," +"|ACHILLES.MIT.EDU)" +"XX.COM." +"(RDATA)" +"source" +"CSNET." +"build" +"ACHILLES.MIT.EDU." +"format" +"read" +"(AA)" +"ISIC.ARPA," +"SERIAL" +"VAXA.ISI" +"found," +"SLIST" +"sorting" +"OPCODE=SQUERY," +"OF" +"AUTHORITY" +"OS" +"AA" +"DOMAIN" +"because" +"SRI-NIC.ARPA.|" +"some" +"back" +"growth" +"USC-ISIC.ARPA," +"RFC-821," +"happens" +"for" +"W." +"RFC-883" +"X.COM" +"avoid" +"does" +"allocate" +"COM" +"assuming" +"BRL" +"PTR" +"[RFC-793]" +"be" +"QCLASS=*" +"MIT.EDU." +"by" +"C." +"on" +"SCLASS" +"of" +"FTP)" +"FTP," +"UK" +"or" +"ACC" +"SBELT." +"SBELT," +"No" +"(SBELT)" +"A.X.COM." +"A.X.COM," +"REFERENCES" +"USC-ISIC.ARPA" +"[RFC-1001]" +"RESPONSE" +"transfer" +"support" +"*" +"NE" +"long" +"QTYPE=*" +"start" +"C.ISI.EDU" +"TTL," +"RD," +"\"4.3.2.1.IN-ADDR.ARPA\"." +"NS" +"was" +"RR." +"RR," +"QTYPE=A" +"MEMO" +"but" +"QNAME" +"[RFC-1001," +"DNS" +"line" +"trying" +"true" +"TCP/UDP" +"count" +"SBELT" +"(NIC)" +"up" +"classes:" +"RFC-768," +"[IEN-116]" +"VAXA" +"NETBIOS" +"called" +"delete" +"CIC" +"USC-" +"RETRY" +"RFC-810," +"RECORDS," +"an" +"To" +"as" +"at" +"file" +"[RFC-812]" +"physical" +"X.COM," +"no" +"[RFC-882," +"when" +"A," +"virtual" +"RFC-952," +"RFC-952." +"valid" +"5" +"test" +"you" +"IP/TCP" +"STATUS" +"requested" +"[RFC-974" +"SPACE" +"QNAME=SIR-NIC.ARPA.," +"RFC-819," +"variable" +"[RFC-882]" +"BIBLIOGRAPHY" +"[RFC-1033]" +"US." +"\"MILNET" +"As" +"RFC-973," +"RFC-882" +"QTYPE=MX" +"4.0.10.18.IN-ADDR.ARPA." +"FOO.F.ISI.ARPA," +"Assuming" +"[RFC-1034]," +"[RFC-1034]." +"UNIX\"" +"IMPLEMENTATION" +"EGP." +"ANCOUNT" +"@" +"P" +"TXT-DATA" +"RMAILBX" +"|QTYPE=A," +"QDCOUNT" +"[RFC-1010]." +"EMAILBX" +"IN-" +"OPCODE=IQUERY," +"MX)" +"ID=997" +"\"VENERA.ISI.EDU\";" +"OPCODE" +"MILNET-GW.ISI.EDU." +"52.0.2.10.IN-ADDR.ARPA." +"objects" +"MD" +"MG" +"MF" +"MR" +"QNAME=10.IN-ADDR.ARPA." +"OFFSET" +"S." +"GGP" +"few" +"QTYPE=PTR," +"MD," +"F" +"[RFC-974]." +"MGMNAME" +"GW.LCS.MIT.EDU." +"GW.LCS.MIT.EDU," +"V" +"\\DDD" +"ALL" +"10.IN-ADDR.ARPA." +"closing" +"EXCHANGE." +"MADNAME." +"$ORIGIN" +"HIS" +"26.IN-ADDR.ARPA." +"(MD)" +"QTYPES" +"PROTOCOL" +"26.IN-ADDR.ARPA" +"NSCOUNT" +"(MR)" +"PREFERENCE" +"<BIT" +"$INCLUDE." +"MR)" +"VAXA.ISI.EDU" +"77.0.0.10.IN-ADDR.ARPA." +"\"IBM-PC" +"$INCLUDE" +"SERVER" +"18.IN-ADDR.ARPA." +"ADDRESS" +"Check" +"static" +"GW.ISI.EDU." +"(QNAME)." +"GW.ISI.EDU," +"F.ISI.ARPA," +"F.ISI.ARPA." +"time." +"PTRDNAME" +"HOSTMASTER@SRI-" +"(STATUS)" +"(MINFO)" +"(MG)" +"QCLASS." +"(HS)" +"X," +"MNAME" +"QNAME=VENERA.ISI.EDU" +"MASTER" +"(IN)" +"KNOWS." +"RNAME" +"|QR|" +"VAXA.ISI.EDU," +"R" +"1)" +"ARCOUNT" +"RCODE" +"NEWNAME" +"CLASS" +"begin" +"(MF)." +"Common" +"<RDATA>" +"QR" +"average" +"QNAME=6.0.0.10.IN-ADDR.ARPA," +"WKS" +"SYSTEM," +"MADNAME" +"ARPANET," +"MINFO" +"DEFINITIONS" +"failed" +"[RFC-1034]" +"(QCLASS)," +"SPECIFICATION" +"X" +"THE" +"MILNET." +"MILNET-" +"bytes" +"(MX)" +"NSDNAME" +"10.IN-ADDR.ARPA" +"|AA|TC|RD|RA|" +"QTYPE=A," +"corruption" +"FOO.F.ISI.ARPA" +"(QUERY)" +"MF," +"FOO" +"CURLEY" +"X.Y," +"AXFR," +"S" +"MAILA" +"exceeds" +"ISI.EDU:" +"103.0.0.26.IN-ADDR.ARPA." +"MOE" +"[RFC-822]." +"CHAOS" +"NAMEDROPPERS@SRI-NIC.ARPA" +"SOA." +"RESOLVER" +"A.X," +"EXCHANGE" +"SMTP" +"QCLASS=*," +"CS" +"$ORIGIN," +"B.X" +"(MB," +"TYPE" +"Size" +"parse" +"ADDR.ARPA" +"(SMTP)." +"key." +"MAP>" +"OWN" +"VENERA.ISI.EDU" +"DDD." +"MB." +"NS," +"I" +"OPCODE=RESPONSE," +"ARPA," +"WITHIN" +"tables" +"unsigned" +"LARRY" +"D" +"\\X" +"WHICH" +"(IQUERY)" +"QCLASS=IN" +"discarded" +"6.0.0.10.IN-ADDR.ARPA." +"MAIL" +"QTYPE=MAILB" +"HS" +"SUPPORT" +"STOOGES" +"X.Y" +"/" +"(SLIST)." +"O" +"OS," +"offset" +"FILES" +"RR)," +"$INCLUDE," +"guard" +"[<TTL>]" +"CRLF" +"Error" +"ERRORS-TO:" +"22.0.2.10.IN-ADDR.ARPA." +"default" +"MESSAGES" +"signed" +"<SUBSYS>ISI-MAILBOXES.TXT" +"MULTICS.MIT.EDU." +"NULL" +"application" +"TXT" +"TC" +"PROTOCOL=TCP" +"UDP." +"UDP," +"F.ISI.ARPA" +"(EXPERIMENTAL)" +"RDLENGTH" +"NIC.ARPA" +
diff --git a/net/data/fuzzer_dictionaries/net_host_resolver_impl_fuzzer.dict b/net/data/fuzzer_dictionaries/net_host_resolver_impl_fuzzer.dict new file mode 100644 index 0000000..3e7f1d89 --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_host_resolver_impl_fuzzer.dict
@@ -0,0 +1,1397 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting DNS responses. + +# Some 16-bit big-endian values. Useful in a number of fields. Includes +# A, AAAA, and CNAME IDs, low values for record counts, and multiples of +# lengths of A and AAAA data fields. +"\x00\x00" +"\x00\x01" +"\x00\x02" +"\x00\x03" +"\x00\x04" +"\x00\x05" +"\x00\x08" +"\x00\x0C" +"\x00\x10" +"\x00\x1C" +"\x00\x20" +"\x00\x30" + +# Some encoded domain names. +"\x03foo\x00" +"\x03foo\x03com\x00" +"\x01a\x03foo\x03com\x00" +"\x03bar\x00" + +# Message headers (Without message ID field). +"\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Truncated message, requiring TCP fallback. +"\x83\x80\x00\x01\x00\x01\x00\x00\x00\x00" +# Varying number of answers +"\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x02\x00\x00\x00\x00" +"\x81\x80\x00\x01\x00\x10\x00\x00\x00\x00" + +# A, AAAA, and CNAME request suffixes - appear after domain name. +"\x00\x01\x00\x01" +"\x00\x1c\x00\x01" +"\x00\x05\x00\x01" + +# A, AAAA, and CNAME requests for foo and foo.com. +"\x03foo\x00\x00\x01\x00\x01" +"\x03foo\x00\x00\x1c\x00\x01" +"\x03foo\x00\x00\x05\x00\x01" +"\x03foo\x03com\x00\x00\x01\x00\x01" +"\x03foo\x03com\x00\x00\x1c\x00\x01" +"\x03foo\x03com\x00\x00\x05\x00\x01" + +# All of the answers below are missing the name field, which should appear +# first. + +# A answer suffixes, two different IP and TTLs. +"\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x01\x02\x03\x04" +"\x00\x01\x00\x01\x00\x00\x00\xFF\x00\x04\x02\x03\x04\x05" + +# AAAA answer suffixes, two different IPs and TTLs. +"\x00\x1C\x00\x01\x00\x00\x00\x00\x00\x08\x01\x02\x03\x04\x05\x06\x07\x08" +"\x00\x1C\x00\x01\x00\x00\x00\xFF\x00\x08\x02\x03\x04\x05\x06\x07\x08\x09" + +# CDATA answer suffixes, first two truncated as well. +"\x00\x05\x00\x01\x00\x00\x00\xFF" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03foo\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x05\x03bar\x00" +"\x00\x05\x00\x01\x00\x00\x00\xFF\x00\x09\x03foo\x03com\x00" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_host_resolver_impl_fuzzer binary, RFC 1034 and RFC 1035. +"EXPIRE" +"all" +"code" +"QNAME=ISI.EDU.," +"chain" +"C.ISI.EDU," +"C.ISI.EDU." +"results" +"existing" +"INTRODUCTION" +"52.0.0.10.IN-ADDR.ARPA." +"QCLASS" +"[RFC-799]" +"follow" +"XX.LCS.MIT.EDU." +"(which" +"C.ISI.EDU:" +"content" +"A.B.X," +"pointing" +"zone" +"A.B.C.D" +"CPU" +"(RCODE)" +"send" +"IN-ADDR.ARPA" +"0" +"Host" +"program" +"under" +"\"*.X\"," +"exit." +"resources" +"TOPS20" +"labels" +"string" +"advantage" +"returning" +"very" +"none" +"C.ISI.EDU)" +"AXFR" +"YALE.ARPA." +"difference" +"Experimental" +"entire" +"did" +"supports" +"list" +"large" +"CNAME," +"-1" +"delegate" +"small" +"ASCII" +"C." +"M." +"YALE.EDU." +"direct" +"past" +"likely" +"\"A\"" +"\"IN-ADDR.ARPA\"." +"XX.LCS.MIT.EDU," +"HINFO" +"RFC-1031," +"IN," +"particular," +"Z." +"errors" +"appear" +"ARPANET" +"QNAME=65.0.6.26.IN-ADDR.ARPA.,QCLASS=IN,QTYPE=PTR" +"QCLASS=*" +"section" +"51.0.0.10.IN-ADDR.ARPA." +"children" +"current" +"DEC-2060" +"waiting" +"version" +"above" +"TTL" +"[RFC-742]" +"shared" +"method" +"QTYPE=NS" +"FTP" +"*.A.X.COM" +"hash" +"EDU." +"exchange" +"QTYPE=CNAME," +"never" +"[RFC-" +"here" +"\"HOSTNAME" +"RFC-793," +"address" +"SNAME," +"path" +"Distribution" +"\"NAME/FINGER\"," +"change" +"search" +"SRI-NIC.ARPA." +"[RFC-952," +"SRI-NIC.ARPA," +"MB" +"receive" +"changed" +"SRI-NIC.ARPA:" +"prior" +"amount" +"QTYPE=CNAME" +"RFC-822." +"here." +"published" +"NOT" +"Serial" +"J.," +"error," +"MX" +"error." +"composed" +"named" +"via" +"useful" +"addresses" +"case." +"ARPA" +"When" +"private" +"*.X.COM" +"total" +"gateway" +"select" +"Status" +"SRI-NIC.ARPA" +"use" +"SNAME" +"from" +"would" +"to" +"positive" +"contains" +"(QCLASS)" +"two" +"[RFC-1032]." +"(DNS)," +"TELNET," +"call" +"B.X," +"memory" +"type" +"until" +"used." +"more" +"sort" +"QNAME=SIR-NIC.ARPA," +"MILNET" +"name." +"Domain" +"[IEN-116," +"PTR)." +"HOSTS.TXT," +"COMSAT," +"EXPIRE." +"known" +"cases" +"must" +"EVEN" +"account" +"include" +"QCLASS=IN." +"QNAME=USC-ISIC.ARPA.," +"this" +"CNAME." +"work" +"EDU," +"can" +"evolved" +"EDU" +"following" +"original" +"root" +"example" +"F." +"history" +"type." +"stream" +"Organizations" +"process" +"pieces" +"high" +"minimum" +"[RFC-953]" +"numbers" +"want" +"allowed" +"serial" +"keep" +"IEN-116," +"returned" +"class." +"information" +"class," +"end" +"goal" +"[RFC-1033]." +"divided" +"holds" +"write" +"located" +"NOSC" +"VENERA.ISI.EDU.|" +"plus" +"Z.X" +"A" +"map" +"[RFC-810]" +"QTYPE." +"may" +"after" +"Request" +"containing" +"RFC-1032," +"date" +"such" +"[RFC-1035]." +"data" +"response" +"types" +"\"A" +"a" +"FTP," +"All" +"short" +"attempt" +"IF" +"After" +"UDEL.EDU." +"SRI," +")" +"RFC-953," +"so" +"TELNET)." +"MIT.EDU" +"order" +"(HOSTS.TXT)" +"ACHILLES" +"ISI.EDU" +"MIL" +"over" +"move" +"vary" +"Z.X)," +"RFC-830," +"through" +"V." +"during" +"still" +"pointer" +"its" +"STYPE" +"before" +"25" +"style" +"HAS" +"group" +"RR" +"HOSTMASTER.SRI-NIC.ARPA." +"65.0.6.26.IN-ADDR.ARPA," +"fix" +"65.0.6.26.IN-ADDR.ARPA." +"28" +"actually" +"RD" +"NAMES" +"YALE" +"policy" +"mail" +"QNAME=BRL.MIL," +"it." +"them" +"good" +"return" +"greater" +"combination" +"B.C.D," +"matches" +"RA," +"ACM," +"9" +"ARPA." +"they" +"half" +"not" +"However," +"parsing" +"[RFC-973]" +"instructions" +"OPCODE=SQUERY,RESPONSE" +"term" +"name" +"RFC," +"always" +"Authority" +"THIS" +"RFC." +"mode" +"timeout" +"RFC-799," +"found" +"|" +"mean" +"RESOLVERS" +"status" +"domain" +"From" +"Network" +"QTYPE," +"series" +"SOME" +"idea" +"related" +"CNAME" +"UDEL" +"happen" +"beyond" +"RFC-882" +"special" +"out" +"try" +"E." +"space" +"open" +"since" +"stub" +"L." +"MINIMUM" +"RFC-768," +"RDATA" +"get" +"cause" +"REFRESH," +"HOSTMASTER@SRI-NIC.ARPA." +"SERVERS" +"This" +"SLIST:" +"free" +"RFC" +"reason" +"base" +"put" +"byte" +"RFC-952" +"received." +"generate" +"SLIST," +"RFC-883," +"definition" +"DATA." +"thread" +"YALE-BULLDOG.ARPA." +"could" +"transition" +"QCLASS," +"times" +"MIT" +"length" +"place" +"ICS.UCI" +"HOSTMASTER@SRI-NIC.ARPA" +"first" +"origin" +"already" +"RD." +"CONFIGURED" +"number" +"one" +"RFC-" +"Start" +"ISI" +"RFC-953." +"construct" +"another" +"owner" +"message" +"QTYPE=*" +"Local" +"CSNET" +"size" +"doesn't" +"given" +"\"" +"X." +"A.ISI.EDU" +"service" +"set," +"introduction" +"unknown" +"top" +"system" +"least" +"parallel" +"their" +"intermediate" +"master" +"listed" +"passed" +"QTYPE" +"ignored." +"scheme" +"Data" +"store" +"gives" +"BBN" +"that" +"completed" +"UDP" +"XX" +"part" +"too" +"RFC-953]." +"(CNAME)" +"translation" +"copy" +"than" +"population" +"wide" +"Set" +"K." +"target" +"DNS," +"16" +"was" +"require" +"second" +"matter" +"See" +"classes" +"were" +"[RFC-1031]" +"result" +"and" +"Information" +"[RFC-805]" +"QNAME" +"[RFC-811]" +"[RFC-1032]" +"say" +"have" +"need" +"Mail" +"1" +"null" +"RETRY" +"any" +"contents" +"|(SRI-NIC.ARPA," +"SOMEONE" +"RESOURCE" +"73.0.0.26.IN-ADDR.ARPA." +"min" +"DARPA" +"database." +"responsible" +"able" +"RFC-812," +"mechanism" +"client" +"also" +"(AA)" +"contact" +"take" +"which" +"MIL." +"MIL," +"=" +"UCI" +"added" +"multiple" +"Name" +"USC-ISIC.ARPA." +"QCLASS=IN," +"track" +"object" +"most" +"detect" +"connected" +"services" +"The" +"]" +"model" +"domain." +"D." +"RFC-1010," +"D," +"[RFC-1010]" +"RFC-805," +"AA," +"sometimes" +"Some" +"VAXA.ISI.EDU." +"QNAME=ISI.EDU," +"MG)." +"error" +"If" +"fact" +"QNAME=SRI-NIC.ARPA," +"particularly" +"text" +"supported" +"terminate" +"VENERA" +"attempts" +"relation" +"RFC-1033," +"Under" +"|(VAXA.ISI.EDU,VENERA.ISI.EDU," +"USC-ISIC.ARPA," +"find" +"cache." +"Z" +"based" +"advanced" +"RECORDS" +"implementation" +"(" +"cache" +"[RFC-768]" +"outside" +"should" +"XX.LCS.MIT.EDU" +"only" +"PVM@ISI.EDU." +"RETRY," +"local" +"do" +"[RFC-1031]." +"means" +"there" +"While" +"cannot" +"new" +"2" +"LOUIE.UDEL.EDU." +"IN-ADDR" +"processes" +"resource" +"A.ISI" +"cached" +"NIC" +"generally" +"(via" +"ROME.UCI" +"Zones" +"RFC-920," +"J." +"RFC-920." +"common" +"mapped" +"including" +"where" +"valid" +"set" +"For" +"configured" +"we" +"QNAME=SRI-NIC.ARPA.," +"up" +"relative" +"depends" +"individual" +"are" +"RFC-883]." +"close" +"A.ISI.EDU." +"said" +"A.ISI.EDU)" +"purpose" +"TCP" +"label" +"PC" +"3" +"unable" +"between" +"probably" +"boundary" +"C.D," +"numerous" +"across" +"available" +"C" +"terms" +"ability" +"parent" +"RFC-830]." +"LCS.MIT.EDU" +"negotiated" +"REFRESH" +"UNIX" +"CH)." +"key" +"March" +"configuration" +"come" +"classes." +"AND" +"both" +"RFC-1002," +"OPCODE=SQUERY" +"last" +"LCS" +"deals" +"PDP-11/70" +"equal" +"against" +"ISI.EDU." +"MAILB" +"[RFC-974]" +"opcode" +"RFC-742," +"C.ISI.EDU" +"expression" +"can't" +"load" +"among" +"[RFC-920]" +"point" +"simple" +"had" +"period" +"header" +"[IEN-116]" +"DNS." +"52.0.0.10.IN-ADDR.ARPA" +"table" +"poll" +"UMN-REI-UC.ARPA." +"[" +"[RFC-883]" +"RFC-974," +"RFC-1002" +"addition" +"P." +"create" +"S.," +"political" +"copies" +"been" +"." +"Early" +"Introduction" +"describes" +"expected" +"empty" +"RA" +"SLIST." +"CH" +"(RD)" +"VENERA.ISI.EDU." +"with" +"SRI" +"PVM@ISI.EDU" +"[RFC-821]" +"Using" +"an" +"case" +"exception" +"has" +"NAME" +"these" +"appearance" +"value" +"will" +"while" +"replaced" +"many" +"loop" +"SOA," +"RFC-1001," +"\"NICNAME/WHOIS\"," +"is" +"CACHE" +"it" +"encountered" +"FACILITIES" +"in" +"|(XX.LCS.MIT.EDU," +"RESPONSE," +"if" +"SOA" +"binary" +"different" +"perhaps" +"[RFC-819]" +"perform" +"make" +"hostname" +"same" +"orders" +"QNAME." +"QNAME," +"parts" +"widely" +"of:" +"several" +"Types" +"(NE)." +"development" +"fairly" +"used" +"Institute" +"IP" +"\"." +"CONCEPTS" +"effect" +"user" +"IN" +"infinite" +"frequently" +"ID" +"recent" +"task" +"SCENARIO" +"database" +"makes" +"depending" +"well" +"It" +"HOSTS.TXT" +"without" +"thought" +"edge" +"Names" +"RFC-811," +"In" +"organization" +"the" +"ACC.ARPA." +"left" +"United" +"protocol" +"less" +"being" +"-" +"rest" +"A," +"Access" +"CSNET." +"stored" +"RFC-882," +"Internet" +"followed" +"(QTYPE)," +"previous" +"RFC-952," +"|ACHILLES.MIT.EDU)" +"majority" +"XX.COM." +"|(C.ISI.EDU,SRI-NIC.ARPA" +"character" +"capabilities" +"(RDATA)" +"source" +"add" +"internal" +"TTL)" +"4" +"Although" +"RCODE=NE" +"5" +"save" +"administrative" +"remaining" +"match" +"build" +"around" +"ACHILLES.MIT.EDU." +"format" +"read" +"Of" +"possible" +"required." +"alias" +"ISIC.ARPA," +"integer" +"bit" +"VAXA.ISI" +"found," +"desire" +"SLIST" +"sorting" +"OPCODE=SQUERY," +"OF" +"AUTHORITY" +"server" +"specific" +"popular" +"output" +"OS" +"Before" +"STATUS" +"DOMAIN" +"because" +"old" +"often" +"deal" +"sequence" +"RFC-821," +"SRI-NIC.ARPA.|" +"Since" +"some" +"System" +"growth" +"equivalent" +"examples" +"loaded" +"INCORRECTLY" +"unless" +"reasons" +"TCP/IP" +"happens" +"ignore" +"for" +"W." +"RFC-883" +"X.COM" +"avoid" +"QTYPE=MX" +"does" +"allocate" +"COM" +"assuming" +"BRL" +"PTR" +"[RFC-793]" +"refer" +"be" +"example," +"MIT.EDU." +"broken" +"host" +"become" +"by" +"SRI-NIC" +"on" +"about" +"actual" +"socket" +"SCLASS" +"RFC-810," +"of" +"FTP)" +"US" +"compatible" +"extensions" +"\"A\"." +"UK" +"referred" +"or" +"ACC" +"SBELT." +"SBELT," +"No" +"(SBELT)" +"into" +"within" +"A.X.COM." +"Two" +"A.X.COM," +"negative" +"included" +"REFERENCES" +"determine" +"USC-ISIC.ARPA" +"file." +"[RFC-1001]" +"[RFC-830]" +"RESPONSE" +"fast" +"additional" +"[RFC-812]" +"transfer" +"support" +"*" +"question" +"NE" +"long" +"class" +"start" +"SERIAL" +"TTL," +"User" +"A.X.COM" +"forward" +"RD," +"\"4.3.2.1.IN-ADDR.ARPA\"." +"NS" +"sections" +"function" +"RR." +"RR," +"QTYPE=A" +"complete" +"form" +"MEMO" +"but" +"back" +"failure" +"link" +"DNS" +"SNAME." +"encoded" +"line" +"trying" +"true" +"TCP/UDP" +"[RFC-1033]" +"count" +"SBELT" +"made" +"[RFC-952]" +"algorithm" +"used," +"(NIC)" +"official" +"this," +"classes:" +"experimental" +"ISI.EDU," +"limit" +"critical" +"VAXA" +"distribution" +"NETBIOS" +"similar" +"called" +"[RFC-1001," +"delete" +"CIC" +"USC-" +"units" +"ad" +"RECORDS," +"defined" +"request" +"specified" +"influence" +"general" +"To" +"as" +"exist" +"at" +"file" +"MX." +"check" +"physical" +"X.COM," +"functions" +"QNAME=USC-ISIC.ARPA," +"no" +"[RFC-882," +"when" +"QTYPE=MX," +"virtual" +"details." +"field" +"RFC-952." +"other" +"role" +"test" +"you" +"(QNAME)," +"IP/TCP" +"formats" +"AA" +"requested" +"[RFC-974" +"SPACE" +"QNAME=SIR-NIC.ARPA.," +"RFC-819," +"important" +"variable" +"[RFC-882]" +"[RFC-1002]" +"structure" +"\"DOD" +"BIBLIOGRAPHY" +"lead" +"using" +"US." +"\"MILNET" +"103.0.3.26.IN-ADDR.ARPA." +"together" +"An" +"As" +"RFC-973," +"time" +"failures" +"starting" +"having" +"V" +"FOO.F.ISI.ARPA," +"Assuming" +"[RFC-1034]." +"calculate" +"IMPLEMENTATION" +"Not" +"ANCOUNT" +"Secondary" +"@" +"ALL" +"P" +"TXT-DATA" +"namespaces" +"entries" +"RMAILBX" +"prevent" +"QDCOUNT" +"[RFC-1010]." +"EMAILBX" +"IN-" +"OPCODE=IQUERY," +"MX)" +"implemented" +"port" +"Available" +"ID=997" +"[RFC-1034]," +"\"VENERA.ISI.EDU\";" +"OPCODE" +"MILNET-GW.ISI.EDU." +";" +"body" +"52.0.2.10.IN-ADDR.ARPA." +"reported" +"objects" +"strong" +"UNIX\"" +"MD" +"MF" +"QNAME=10.IN-ADDR.ARPA." +"serialize" +"<SUBSYS>ISI-MAILBOXES.TXT" +"X," +"Too" +"77.0.0.10.IN-ADDR.ARPA." +"spawned" +"exception." +"permitted" +"RDLENGTH" +"few" +"duplicate" +"QTYPE=PTR," +"CURLEY" +"MD," +"F" +"[RFC-974]." +"MGMNAME" +"validity" +"GW.LCS.MIT.EDU," +"Time" +"(back" +"\\DDD" +"10.IN-ADDR.ARPA." +"closing" +"requested," +"reserved" +"EXCHANGE." +"HIS" +"reject" +"ensure" +"(MD)" +"QTYPES" +"PROTOCOL" +"description" +"26.IN-ADDR.ARPA" +"NSCOUNT" +"(MR)" +"derived" +"Foreign" +"OWN" +"26.IN-ADDR.ARPA." +"TC" +"map." +"cases." +"PREFERENCE" +"don't" +"VENERA.ISI.EDU" +"held" +"X" +"below:" +"$INCLUDE." +"forms" +"MR)" +"VAXA.ISI.EDU" +"main" +"pending" +"timestamp" +"Ignoring" +"MADNAME." +"\\" +"$ORIGIN" +"\"IBM-PC" +"document" +"$INCLUDE" +"SERVER" +"ADDRESS" +"identifier" +"Check" +"reduce" +"static" +"expect" +"MASTER" +"GW.ISI.EDU." +"(QNAME)." +"is:" +"GW.ISI.EDU," +"F.ISI.ARPA," +"F.ISI.ARPA." +"time." +"PTRDNAME" +"HOSTMASTER@SRI-" +"(STATUS)" +"possibility" +"|QTYPE=A," +"(MINFO)" +"initialize" +"beginning" +"compression" +"(MG)" +"created" +"QCLASS." +"encoding" +"(HS)" +"MNAME" +"ports" +"QNAME=VENERA.ISI.EDU" +"(IN)" +"Response" +"KNOWS." +"|QR|" +"VAXA.ISI.EDU," +"Reserved" +"14" +"1)" +"SOA." +"ARCOUNT" +"Other" +"RCODE" +"NEWNAME" +"22.0.2.10.IN-ADDR.ARPA." +"With" +"CLASS" +"begin" +"(MF)." +"Common" +"<RDATA>" +"Responses" +"EGP." +"average" +"R" +"QNAME=6.0.0.10.IN-ADDR.ARPA," +"WKS" +"SYSTEM," +"ARPANET," +"MINFO" +"participate" +"DEFINITIONS" +"failed" +"[RFC-1034]" +"mixture" +"SPECIFICATION" +"THE" +"MILNET." +"MILNET-" +"<BIT" +"bytes" +"(MX)" +"10.IN-ADDR.ARPA" +"4.0.10.18.IN-ADDR.ARPA." +"FOO.F.ISI.ARPA" +"(QUERY)" +"maximum" +"existence" +"|AA|TC|RD|RA|" +"MADNAME" +"subject" +"QTYPE=A," +"FILES" +"reading" +"0." +"corruption" +"0," +"Sending" +"MF," +"connection." +"Server" +"entries." +"suggested" +"reverse" +"AXFR," +"according" +"connection" +"MAILA" +"(QCLASS)," +"exceeds" +"ISI.EDU:" +"103.0.0.26.IN-ADDR.ARPA." +"[RFC-822]." +"NAMEDROPPERS@SRI-NIC.ARPA" +"RESOLVER" +"respect" +"throughout" +"S" +"FOO" +"define" +"enable" +"EXCHANGE" +"SMTP" +"MG" +"QCLASS=*," +"CS" +"$ORIGIN," +"(MB," +"TYPE" +"Any" +"Size" +"rename" +"almost" +"parse" +"ADDR.ARPA" +"(SMTP)." +"key." +"MAP>" +"expired" +"member" +"Address" +"DDD." +"MB." +"NS," +"I" +"MR" +"read," +"OPCODE=RESPONSE," +"person" +"entry" +"WITHIN" +"LARRY" +"front" +"tables" +"loading" +"unsigned" +"aspects" +"D" +"CHAOS" +"WHICH" +"(IQUERY)" +"QCLASS=IN" +"6.0.0.10.IN-ADDR.ARPA." +"S." +"QTYPE=MAILB" +"HS" +"SUPPORT" +"A.X," +"STOOGES" +"discarded" +"done." +"literals" +"X.Y" +"However" +"/" +"(SLIST)." +"X.Y," +"integer." +"ARPA," +"who" +"18.IN-ADDR.ARPA." +"B.X" +"expansion" +"OS," +"offset" +"F.ISI.ARPA" +"GGP" +"O" +"Communications" +"RR)," +"location" +"MOE" +"range" +"value." +"Message" +"block" +"$INCLUDE," +"guard" +"[<TTL>]" +"QR" +"CRLF" +"Error" +"ERRORS-TO:" +"he" +"default" +"MESSAGES" +"signed" +"storing" +"MULTICS.MIT.EDU." +"New" +"NULL" +"application" +"OFFSET" +"holding" +"TXT" +"NSDNAME" +"PROTOCOL=TCP" +"UDP." +"UDP," +"RNAME" +"GW.LCS.MIT.EDU." +"(EXPERIMENTAL)" +"\\X" +"MAIL" +"NIC.ARPA" +
diff --git a/net/data/fuzzer_dictionaries/net_http_proxy_client_socket_fuzzer.dict b/net/data/fuzzer_dictionaries/net_http_proxy_client_socket_fuzzer.dict new file mode 100644 index 0000000..4028d26e --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_http_proxy_client_socket_fuzzer.dict
@@ -0,0 +1,1088 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting HTTP/1.x responses. + +# Entries that are generally useful in headers +":" +"\x0A" +"\x0D" +"0" +"50" +"500" +# Horizontal whitespace. Matters mostly in status line. +" " +"\x09" +# Header continuation +"\x0D\x0A\x09" +# Used in a lot of individual headers +";" +"=" +"," +"\"" +"-" + +# Status line components +"HTTP" +"/1.1" +"/1.0" +# More interesting status codes. Leading space so can be inserted into +# other status lines. +" 100" +" 200" +" 206" +" 301" +" 302" +" 303" +" 304" +" 307" +" 308" +" 401" +" 403" +" 404" +" 500" +" 501" +" 403" + +# Full status lines (Some with relevant following headers) +"HTTP/1.1 200 OK\x0A\x0A" +"HTTP/1.1 100 Continue\x0A\x0A" +"HTTP/1.1 401 Unauthorized\x0AWWW-Authenticate: Basic realm=\"Middle-Earth\"\x0A\xA0" +"HTTP/1.1 407 Proxy Authentication Required\x0AProxy-Authenticate: Digest realm=\"Middle-Earth\", nonce=\"aaaaaaaaaa\"\x0A\x0A" +"HTTP/1.0 301 Moved Permanently\x0ALocation: /a\x0A\x0A" +"HTTP/1.1 302 Found\x0ALocation: http://lost/\x0A\x0A" + +# Proxy authentication headers. Note that fuzzers don't support NTLM or +# negotiate. +"WWW-Authenticate:" +"Proxy-Authenticate:" +"Basic" +"Digest" +"realm" +"nonce" + +"Connection:" +"Proxy-Connection:" +"Keep-Alive" +"Close" +"Upgrade" +"\x0AConnection: Keep-Alive" +"\x0AConnection: Close" +"\x0AProxy-Connection: Keep-Alive" +"\x0AProxy-Connection: Close" + +"Content-Length:" +"Transfer-Encoding:" +"chunked" +"\x0AContent-Length: 0" +"\x0AContent-Length: 500" +"\x0ATransfer-Encoding: chunked\x0A\x0A5\x0A12345\x0A0\x0A\x0A" + +"Location:" +"\x0ALocation: http://foo/" +"\x0ALocation: http://bar/" +"\x0ALocation: https://foo/" +"\x0ALocation: https://bar/" + +"Accept-Ranges:" +"bytes" +"\x0AAccept-Ranges: bytes" + +"Content-Range:" + +"Age:" +"\x0AAge: 0" +"\x0AAge: 3153600000" + +"Cache-Control:" +"max-age" +"no-cache" +"no-store" +"must-revalidate" +"\x0ACache-Control: max-age=3153600000" +"\x0ACache-Control: max-age=0" +"\x0ACache-Control: no-cache" +"\x0ACache-Control: no-store" +"\x0ACache-Control: must-revalidate" + +"Content-Disposition:" +"attachment" +"filename" + +"Content-Encoding:" +"gzip" +"deflate" +"sdch" +"br" +"\x0AContent-Encoding: gzip" +"\x0AContent-Encoding: deflate" +"\x0AContent-Encoding: sdch" +"\x0AContent-Encoding: br" + +"Date:" +"Fri, 01 Apr, 2050 14:14:14 GMT" +"Mon, 28 Mar, 2016 04:04:04 GMT" +"\x0ADate: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0ADate: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Last-Modified:" +"\x0ALast-Modified: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0ALast-Modified: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Expires:" +"\x0AExpires: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0AExpires: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Set-Cookie:" +"Expires" +"Max-Age" +"Domain" +"Path" +"Secure" +"HttpOnly" +"Priority" +"Low" +"Medium" +"High" +"SameSite" +"Strict" +"Lax" +"\x0ASet-Cookie: foo=bar" +"\x0ASet-Cookie: foo2=bar2;HttpOnly;Priority=Low;SameSite=Strict;Path=/" +"\x0ASet-Cookie: foo=chicken;SameSite=Lax" + +"Strict-Transport-Security:" +"includeSubDomains" + +"Vary:" +"\x0AVary: Cookie" +"\x0AVary: Age" + +"ETag:" +"\x0AETag: jumboshrimp" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_http_proxy_client_socket_fuzzer binary and RFC 2616. +"all" +"code" +"maximum" +"Transfer-Encoding" +"D.," +"results" +"follow" +"(LZW)." +"provided." +"(which" +"ISDN" +"\"TE\"" +"LF>" +"FORCE" +"calculate" +"\"IETF" +"UNIX," +"ARPA" +"\"OPTIONAL\"" +"environment" +"Host" +"program" +"USENET" +"TEXT" +"Not" +"Nov" +"include" +"resources" +"CONNECT" +"digit" +"supported" +"string" +"returning" +"ALL" +"HTTP/1.1;" +"SP," +"SP." +"entries" +"HTTP/1.1," +"HTTP/1.1." +"difference" +"(URI):" +"--" +"[CRLF]" +"EXPRESS" +"list" +"HTTP/1.0\"," +"(RFC" +"large" +"ONLY" +"Tag" +"(LWS" +"enclosing" +"\"SHOULD\"," +"(URL)\"," +"\"A\"..\"Z\">" +"unexpected" +"GET)" +"\"HEAD\"" +"direct" +"Failed" +"second" +"Version" +"\"A\"" +"allowed." +"pass" +"GET," +"tag." +"implemented" +"\"HTTP/1.0\"" +"INFRINGE" +"errors" +"ISO-8859-4," +"appear" +"opaque" +"section" +"CPU" +"current" +"waiting" +"version" +"above" +"TTL" +"shared" +"CRLF)" +"public" +"FTP" +"NNTP." +"WWW-" +"never" +"equals" +"\"HTTP/1.1" +"reported" +"objects" +"address" +"active" +"path" +"[" +"\"POST\"" +"HTTP." +"change" +"MA" +"\"AS" +"broken" +"BACK)" +"NOT" +"NNTP" +"named" +"useful" +"secure" +"family" +"case." +"detected." +"\"HTTP\"" +"private" +"CERN/3.0" +"CTE" +"(CTE)" +"Too" +"CTL" +"PUT," +"user-agent" +"PUT)" +"byte" +"select" +"use" +"TASK" +"from" +"exception." +"working" +"to" +"value." +"WARRANTIES" +"two" +"URI;" +"User-Agent" +"few" +"--THIS_STRING_SEPARATES" +"POST," +"call" +"6" +"MUST," +"scope" +"type" +"authorization" +"more" +"ISO-8859-9," +"(GMT)," +"(TE)" +"name." +"initial" +"Required" +"RFC-850" +"warn" +"bytes," +"Found" +"cases" +"MHTML" +"name:" +"must" +"parse" +"lowercase" +"MHTML," +"RIGHTS" +"this" +"NTP" +"work" +"--THIS_STRING_SEPARATES--" +"Syntax" +"paragraph" +"can" +"tracing" +"following" +"\"I" +"closing" +"modifier" +"root" +"example" +"requested," +"J.," +"control" +"type." +"reserved" +"links" +"process" +"attribute" +"allowed" +"high" +"currency" +"numbers" +"want" +"type:" +"native" +"LF" +"class," +"end" +"Missing" +"HTTP-" +"HTTP," +"charset" +"1" +"line." +"2*N" +"H." +"1XX" +"WARRANTIES," +"HTTP:" +"A" +"badly" +"HEAD" +"may" +"insecure" +"after" +"variant" +"different" +"wrong" +"[SP" +"ANSI," +"date" +"such" +"data" +"parallel" +"repeat" +"a" +"FTP," +"All" +"short" +"\"GET\"" +"Y." +"UA" +"(2**N)," +"element" +"so" +"cases." +"File" +"(LWS)" +"\"DEFLATE" +"order" +"\"SHOULD" +"don't" +"MIC" +"move" +"vary" +"satisfied" +"CD-ROM," +"ended" +"HTTP-WG." +"LINK," +"pointer" +"its" +"digest" +"before" +"HTML" +"(OK)" +"using:" +"MAY," +"fix" +"ISO-3166" +"actually" +"407" +"(GNU" +"\"HTTP/1.1\"," +"P.," +"401" +"MERCHANTABILITY" +"DNS." +"into" +"\"HTTP" +"it." +"it," +"return" +"combination" +"URL" +"URI" +"number" +"Bad" +"not" +"However," +"SSL" +"name" +"always" +"decimal" +"expectation." +"did" +"ISO-639" +"]URI," +"found" +"trailer" +"mean" +"breakdown" +"domain" +"From" +"UTC" +"(via" +"(URI)" +"UNLINK" +"used" +"expect" +"exceeded" +"(MIC)" +"event" +"out" +"is:" +"by" +"E." +"space" +"\"MUST/MAY/SHOULD\"" +"REQUIRED" +"ALPHA" +"HTTP/2.4" +"4DIGIT" +"increase" +"L." +"time." +"PATCH," +"supports" +"2DIGIT" +"K.," +"(A," +"This" +"free" +"\"B\"" +"RFC" +"base" +"proxy" +"IMPLIED," +"POST" +"received." +"generate" +"text/plain" +"ISO-8859-7," +"\"HTTP/1.1\"" +"Partial" +"could" +"transition" +"DISCLAIMS" +"times" +"filter" +"HTML\"," +"length" +"HEAD." +"HEAD," +"S.," +"first" +"origin" +"\"E\"" +"already" +"UPALPHA" +"3DIGIT" +"*" +"Cache" +"Please" +"token." +"one" +"CHAR" +"ISI" +"another" +"FITNESS" +"message" +"CSS1," +"open" +"size" +"doesn't" +"\"" +"script" +"unknown" +"top" +"header)" +"system" +"construct" +"image/gif" +"2" +"ignored." +"listed" +"Date" +"LOALPHA" +"scheme" +"final" +"store" +"too" +"M." +"Success" +"that" +"completed" +"OPTIONAL;" +"task" +"tokens" +"R" +"pragma" +"(IANA" +"WAIS" +"F.," +"than" +"(A" +"K." +"target" +"16" +"require" +"Only" +"WWW-Authenticate" +"HTTP/2.13," +"headers" +"See" +"GMT." +"HTTP/2.0," +"were" +"1)" +"IS\"" +"stale" +"1*8ALPHA" +"are" +"and" +"IRC/6.9," +"false" +"URL)." +"turned" +"ANSI" +"B" +"(IANA)" +"(LWS)." +"have" +"MIME," +"need" +"HTTP/1.1.)" +"null" +"any" +"contents" +"conversion" +"data)" +"(LZ77)" +"(MIME" +"mechanism" +"internal" +"(C)" +"take" +"which" +"With" +"UCI" +"HTTP/0.9," +"content-" +"200" +"begin" +"headers)" +"unless" +"TCP/IP" +"Content-Disposition" +"206" +"buffer" +"object" +"\"MUST\"," +"regular" +"letter" +"entry" +"The" +"]" +"the" +"D." +"(STD" +"incompatible" +"L.," +"(URL)" +"left" +"+" +"\"MIME" +"Note:" +"particularly" +"WA" +"text" +"labels" +"\"C\"" +"Authentication" +"Unrecognized" +"CRLF." +"PARTICULAR" +"CRLF," +"SP" +"find" +"MUST" +"true," +"cache." +"upgrade" +"cache)" +"implementation" +"(" +"[RFC" +"cache" +"3" +"should" +"failed" +"only" +"unable" +"LDAP)" +"USA" +"US-ASCII" +"(UA)" +"get" +"E.," +"HEREIN" +"\"HTTP\"." +"cannot" +"new" +"THE" +"BNF" +"DIGIT," +"closure" +"PUT" +"0)" +"resource" +"A.," +"W." +"Content-Type:" +"ISO-8859." +"calling" +"J." +"INCLUDING" +"common" +"INTERNET" +"release" +"ISI/RR-98-463," +"\"CONNECT\"" +"where" +"set" +"IANA" +"For" +"\"F\"" +"configured" +"C" +"this," +"multipart" +"close" +"end." +"detect" +"GET" +"WWW\"," +"1*DIGIT" +"BUT" +"MIT" +"outside" +"Proxy-Authorization" +"closed" +"between" +"probably" +"boundary" +"reading" +"\"SHALL" +"\"RECOMMENDED\"," +"available" +"we" +"FOR" +"missing" +"importance" +"screen" +"connection." +"ISO-8859-1" +"UNIX" +"STD" +"key" +"(MIME)" +"P." +"\"HTTP/1.1\"." +"HTTP/1.0)," +"AND" +"received" +"WWW" +"TRACE" +"\"MAY\"," +"many" +"*TEXT" +"Unsupported" +"Rules" +"connection" +"Unicode" +"*OCTET" +"exceeds" +"(URN)" +"safely" +"finds" +"can't" +"WARRANTY" +"ISO-8859-8," +"Content-Length" +"consume" +"stream" +"simple" +"header" +"DNS)" +"colon" +"adding" +"spans" +"1*HEX" +"table" +"allocated" +"BCP" +"application/pdf" +"LWS:" +"\"REQUIRED\"," +"Wed," +"C." +"C," +"Proxy-Authenticate" +"encryption" +"create" +"(MHTML)\"," +"been" +"." +"HTTP/12.3." +"\"OPTIONS\"" +"\"PUT\"" +"context." +"LWS," +"basic" +"expected" +"prototype" +"GMT," +"empty" +">" +"URL." +"PNG,\"" +"\"D\"" +"CA" +"HEX" +"N" +"0*3DIGIT" +"\"W/\"" +"CR" +"\"DELETE\"" +"unnecessarily" +"case" +"exception" +"save" +"(HTTP)" +"value" +"Assigned" +"while" +"\"GZIP" +"\"SHALL\"," +"error" +"\"GMT\"" +"\"TRACE\"" +"resident" +"is" +"thus" +"it" +"encountered" +"Content" +"MIME" +"in" +"SIGCOMM" +"You" +"if" +"result" +"binary" +"containing" +"\"A" +")" +"CREATE" +"expired" +"1DIGIT" +"same" +"OPTIONS" +"read" +"BNF," +"unrecognized" +"units" +"UST" +"status" +"\"%" +"extended" +"http" +"context" +"I" +"IP" +"(O)." +"allocation" +"running" +"*LWS" +"user" +"SMTP" +"stack" +"tracking" +"IETF" +"CR." +"failing" +"ANY" +"patterns" +"M.," +"Names" +"In" +"position" +"model" +"audio" +"If" +"US-ASCII." +"MAY" +"THAT" +"being" +"(OK)." +"actions" +"invalid" +"HTTP/1.0)" +"CRC." +"previous" +"tables" +"TO" +"<US-ASCII" +"character" +"source" +"ISO-8859-2," +"valid" +"location" +"HTTP/1.0" +"HTTP/1.1" +"size," +"has" +"match" +"build" +"URI." +"tests" +"format" +"transfer-encoding" +"H.," +"T" +"using" +"LIMITED" +"OK" +"success" +"text/html" +"ISO-8859-5," +"B," +"signal" +"MIME:" +"(HTCPCP/1.0)\"," +"server" +"discarded" +"true" +"OF" +"output" +"page" +"S." +"right" +"old" +"sequence" +"uppercase" +"B.," +"some" +"back" +"HT" +"Last-Modified" +"growth" +"equivalent" +"specified" +"multiple" +"H.F.," +"HTTP/1.0." +"(BNF)" +"happens" +"ignore" +"PUT." +"INDEX." +"trace" +"for" +"avoid" +"CR," +"does" +"Authorization" +"assuming" +"be" +"run" +"GET." +"deleted" +"302" +"X3.4-1986" +"<URL:" +"O" +"ISO-8859-1." +"last-modified" +"host" +"HTTP/1.0," +"LWS>" +"INFORMATION" +"X3.4-1986," +"properties" +"ALPHA," +"Location" +"on" +"DIGIT" +"ENGINEERING" +"actual" +"extension" +"of" +"R.," +"\"UTF-8," +"*<TEXT," +"OR" +"range" +"3ALPHA" +"URI," +"positive" +"Message" +"DELETE" +"content-type" +"or" +"UC" +"No" +"ISO-" +"image" +"ACM" +"HEX\"" +"URL," +"because" +"ISO-8859-6," +"T.," +"operator" +"T/TCP" +"mark" +"file." +"area" +"GET\"" +"transfer" +"support" +"there" +"long" +"class" +"start" +"HT." +"forward" +"was" +"function" +"HT," +"N." +"HTTP/1.1\"," +"memory" +"OCTET" +"but" +"failure" +"TE:" +"IMPLIED" +"CRLF" +"DNS" +"Error" +"\"ZLIB" +"line" +"trying" +"with" +"GMT" +"count" +"algorithm" +"default" +"B." +"ISO-8859-1," +"up" +"ISO-8859-1)" +"SHOULD" +"PURPOSE." +"limit" +"used." +"WILL" +"DEL" +"define" +"called" +"delete" +"DELETE," +"storing" +"USE" +"image/jpeg" +"defined" +"LWS" +"combining" +"unsafe" +"an" +"To" +"as" +"warning" +"exist" +"at" +"file" +"NOT\"" +"NOT," +"W3C/MIT" +"ISO-8859-1:1987." +"SHTTP/1.3," +"no" +"when" +"A," +"virtual" +"A." +"details." +"application" +"other" +"OPTIONAL" +"Proxy" +"LF," +"test" +"MD5" +"you" +"TE" +"ISO-8859-3," +"requested" +"elements" +"C)" +"symbol" +"T." +"code)" +"variable" +"SOCIETY" +"\"MUST" +"TCP" +"ISO-10646\"," +"NOT\"," +"R." +"lead" +"audio/basic" +"IANA." +"\"WAIS" +"persistent" +"Its" +"As" +"time" +"failures" +"\"ISO-8859-1\"" +"once" +
diff --git a/net/data/fuzzer_dictionaries/net_http_stream_parser_fuzzer.dict b/net/data/fuzzer_dictionaries/net_http_stream_parser_fuzzer.dict new file mode 100644 index 0000000..cba14dc --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_http_stream_parser_fuzzer.dict
@@ -0,0 +1,1039 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting HTTP/1.x responses. + +# Entries that are generally useful in headers +":" +"\x0A" +"\x0D" +"0" +"50" +"500" +# Horizontal whitespace. Matters mostly in status line. +" " +"\x09" +# Header continuation +"\x0D\x0A\x09" +# Used in a lot of individual headers +";" +"=" +"," +"\"" +"-" + +# Status line components +"HTTP" +"/1.1" +"/1.0" +# More interesting status codes. Leading space so can be inserted into +# other status lines. +" 100" +" 200" +" 206" +" 301" +" 302" +" 303" +" 304" +" 307" +" 308" +" 401" +" 403" +" 404" +" 500" +" 501" +" 403" + +# Full status lines (Some with relevant following headers) +"HTTP/1.1 200 OK\x0A\x0A" +"HTTP/1.1 100 Continue\x0A\x0A" +"HTTP/1.1 401 Unauthorized\x0AWWW-Authenticate: Basic realm=\"Middle-Earth\"\x0A\xA0" +"HTTP/1.1 407 Proxy Authentication Required\x0AProxy-Authenticate: Digest realm=\"Middle-Earth\", nonce=\"aaaaaaaaaa\"\x0A\x0A" +"HTTP/1.0 301 Moved Permanently\x0ALocation: /a\x0A\x0A" +"HTTP/1.1 302 Found\x0ALocation: http://lost/\x0A\x0A" + +# Proxy authentication headers. Note that fuzzers don't support NTLM or +# negotiate. +"WWW-Authenticate:" +"Proxy-Authenticate:" +"Basic" +"Digest" +"realm" +"nonce" + +"Connection:" +"Proxy-Connection:" +"Keep-Alive" +"Close" +"Upgrade" +"\x0AConnection: Keep-Alive" +"\x0AConnection: Close" +"\x0AProxy-Connection: Keep-Alive" +"\x0AProxy-Connection: Close" + +"Content-Length:" +"Transfer-Encoding:" +"chunked" +"\x0AContent-Length: 0" +"\x0AContent-Length: 500" +"\x0ATransfer-Encoding: chunked\x0A\x0A5\x0A12345\x0A0\x0A\x0A" + +"Location:" +"\x0ALocation: http://foo/" +"\x0ALocation: http://bar/" +"\x0ALocation: https://foo/" +"\x0ALocation: https://bar/" + +"Accept-Ranges:" +"bytes" +"\x0AAccept-Ranges: bytes" + +"Content-Range:" + +"Age:" +"\x0AAge: 0" +"\x0AAge: 3153600000" + +"Cache-Control:" +"max-age" +"no-cache" +"no-store" +"must-revalidate" +"\x0ACache-Control: max-age=3153600000" +"\x0ACache-Control: max-age=0" +"\x0ACache-Control: no-cache" +"\x0ACache-Control: no-store" +"\x0ACache-Control: must-revalidate" + +"Content-Disposition:" +"attachment" +"filename" + +"Content-Encoding:" +"gzip" +"deflate" +"sdch" +"br" +"\x0AContent-Encoding: gzip" +"\x0AContent-Encoding: deflate" +"\x0AContent-Encoding: sdch" +"\x0AContent-Encoding: br" + +"Date:" +"Fri, 01 Apr, 2050 14:14:14 GMT" +"Mon, 28 Mar, 2016 04:04:04 GMT" +"\x0ADate: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0ADate: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Last-Modified:" +"\x0ALast-Modified: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0ALast-Modified: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Expires:" +"\x0AExpires: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0AExpires: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Set-Cookie:" +"Expires" +"Max-Age" +"Domain" +"Path" +"Secure" +"HttpOnly" +"Priority" +"Low" +"Medium" +"High" +"SameSite" +"Strict" +"Lax" +"\x0ASet-Cookie: foo=bar" +"\x0ASet-Cookie: foo2=bar2;HttpOnly;Priority=Low;SameSite=Strict;Path=/" +"\x0ASet-Cookie: foo=chicken;SameSite=Lax" + +"Strict-Transport-Security:" +"includeSubDomains" + +"Vary:" +"\x0AVary: Cookie" +"\x0AVary: Age" + +"ETag:" +"\x0AETag: jumboshrimp" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_http_stream_parser_fuzzer binary and RFC 2616. +"all" +"code" +"maximum" +"Transfer-Encoding" +"D.," +"results" +"follow" +"(LZW)." +"provided." +"(which" +"ISDN" +"\"TE\"" +"LF>" +"FORCE" +"calculate" +"\"IETF" +"UNIX," +"ARPA" +"\"OPTIONAL\"" +"environment" +"ENGINEERING" +"program" +"USENET" +"TEXT" +"Not" +"Nov" +"include" +"resources" +"(STD" +"labels" +"string" +"returning" +"HTTP/1.1;" +"SP," +"SP." +"entries" +"HTTP/1.1," +"HTTP/1.1." +"difference" +"(URI):" +"did" +"[CRLF]" +"EXPRESS" +"list" +"HTTP/1.0\"," +"(RFC" +"large" +"ONLY" +"Tag" +"(LWS" +"(URL)\"," +"\"A\"..\"Z\">" +"unexpected" +"GET)" +"direct" +"Failed" +"second" +"Version" +"\"A\"" +"allowed." +"GET," +"tag." +"implemented" +"\"HTTP/1.0\"" +"errors" +"ISO-8859-4," +"appear" +"incompatible" +"section" +"CPU" +"current" +"waiting" +"version" +"above" +"TTL" +"new" +"CRLF)" +"public" +"FTP" +"NNTP." +"WWW-" +"never" +"equals" +"\"HTTP/1.1" +"reported" +"objects" +"address" +"active" +"\"HEAD\"" +"[" +"\"POST\"" +"HTTP." +"change" +"MA" +"\"AS" +"last-modified" +"BACK)" +"NOT" +"NNTP" +"named" +"useful" +"secure" +"case." +"detected." +"\"HTTP\"" +"private" +"CERN/3.0" +"CTE" +"(CTE)" +"Too" +"CTL" +"PUT," +"user-agent" +"PUT)" +"POST" +"select" +"use" +"TASK" +"from" +"exception." +"working" +"to" +"positive" +"two" +"URI;" +"properties" +"few" +"--THIS_STRING_SEPARATES" +"POST," +"call" +"memory" +"MUST," +"scope" +"type" +"authorization" +"more" +"ISO-8859-9," +"(GMT)," +"(TE)" +"name." +"LF," +"RFC-850" +"warn" +"bytes," +"Found" +"cases" +"MHTML" +"name:" +"must" +"Content" +"ALL" +"MHTML," +"RIGHTS" +"this" +"NTP" +"work" +"--THIS_STRING_SEPARATES--" +"Syntax" +"can" +"of" +"following" +"\"I" +"closing" +"root" +"example" +"requested," +"J.," +"type." +"reserved" +"stream" +"process" +"attribute" +"allowed" +"high" +"currency" +"numbers" +"want" +"type:" +"native" +"LF" +"class," +"end" +"Missing" +"HTTP-" +"HTTP," +"links" +"1" +"line." +"2*N" +"H." +"1XX" +"WARRANTIES," +"HTTP:" +"A" +"badly" +"HEAD" +"may" +"insecure" +"after" +"containing" +"tracking" +"wrong" +"[SP" +"ANSI," +"date" +"such" +"data" +"parallel" +"repeat" +"a" +"FTP," +"All" +"short" +"Y." +"UA" +"(2**N)," +"element" +"so" +"cases." +"File" +"(LWS)" +"\"DEFLATE" +"order" +"charset" +"\"SHOULD" +"don't" +"MIC" +"move" +"vary" +"satisfied" +"CD-ROM," +"HTTP-WG." +"LINK," +"pointer" +"its" +"digest" +"before" +"HTML" +"(OK)" +"Rules" +"MAY," +"fix" +"ISO-3166" +"actually" +"407" +"(GNU" +"\"HTTP/1.1\"," +"P.," +"401" +"MERCHANTABILITY" +"DNS." +"into" +"\"HTTP" +"it." +"it," +"return" +"URL" +"URI" +"number" +"Bad" +"not" +"However," +"SSL" +"name" +"always" +"expectation." +"--" +"ISO-639" +"]URI," +"found" +"trailer" +"mean" +"breakdown" +"From" +"UTC" +"(via" +"(URI)" +"UNLINK" +"expect" +"exceeded" +"(MIC)" +"event" +"out" +"is:" +"E." +"space" +"\"MUST/MAY/SHOULD\"" +"REQUIRED" +"ALPHA" +"HTTP/2.4" +"4DIGIT" +"increase" +"L." +"time." +"PATCH," +"supports" +"2DIGIT" +"K.," +"(A," +"This" +"free" +"\"B\"" +"RFC" +"base" +"IMPLIED," +"byte" +"received." +"generate" +"text/plain" +"ISO-8859-7," +"\"HTTP/1.1\"" +"Partial" +"could" +"transition" +"DISCLAIMS" +"times" +"filter" +"HTML\"," +"length" +"HEAD." +"HEAD," +"S.," +"first" +"origin" +"\"E\"" +"already" +"UPALPHA" +"3DIGIT" +"Cache" +"Please" +"token." +"one" +"CHAR" +"ISI" +"another" +"FITNESS" +"message" +"CSS1," +"open" +"size" +"doesn't" +"\"" +"script" +"unknown" +"top" +"header)" +"system" +"construct" +"image/gif" +"2" +"ignored." +"listed" +"Date" +"LOALPHA" +"scheme" +"store" +"too" +"M." +"Success" +"that" +"completed" +"OPTIONAL;" +"R" +"pragma" +"(IANA" +"WAIS" +"F.," +"than" +"K." +"target" +"Content-Type:" +"require" +"Only" +"HTTP/2.13," +"headers" +"See" +"GMT." +"HTTP/2.0," +"were" +"1)" +"IS\"" +"1*8ALPHA" +"are" +"and" +"IRC/6.9," +"false" +"turned" +"ANSI" +"B" +"(IANA)" +"tables" +"have" +"MIME," +"need" +"HTTP/1.1.)" +"null" +"any" +"contents" +"data)" +"(LZ77)" +"(MIME" +"mechanism" +"internal" +"(C)" +"take" +"which" +"With" +"UCI" +"HTTP/0.9," +"content-" +"200" +"begin" +"multiple" +"TCP/IP" +"Content-Disposition" +"206" +"buffer" +"object" +"\"MUST\"," +"regular" +"entry" +"The" +"]" +"model" +"D." +"US-ASCII" +"L.," +"(URL)" +"If" +"+" +"\"MIME" +"Note:" +"particularly" +"WA" +"text" +"supported" +"\"C\"" +"Unrecognized" +"CRLF." +"CRLF," +"SP" +"find" +"MUST" +"true," +"cache." +"upgrade" +"cache)" +"implementation" +"(" +"[RFC" +"cache" +"outside" +"should" +"failed" +"only" +"URL)." +"LDAP)" +"USA" +"WARRANTIES" +"(UA)" +"get" +"there" +"HEREIN" +"\"HTTP\"." +"cannot" +"shared" +"THE" +"BNF" +"DIGIT," +"closure" +"PUT" +"reading" +"resource" +"A.," +"W." +"16" +"ISO-8859." +"calling" +"J." +"INCLUDING" +"common" +"INTERNET" +"release" +"ISI/RR-98-463," +"\"CONNECT\"" +"where" +"set" +"IANA" +"For" +"\"F\"" +"configured" +"C" +"this," +"multipart" +"close" +"E.," +"end." +"detect" +"GET" +"WWW\"," +"1*DIGIT" +"BUT" +"MIT" +"3" +"unable" +"between" +"probably" +"boundary" +"0)" +"\"SHALL" +"\"RECOMMENDED\"," +"available" +"we" +"FOR" +"missing" +"importance" +"screen" +"connection." +"PARTICULAR" +"UNIX" +"STD" +"ISO-8859-1" +"key" +"(MIME)" +"P." +"\"HTTP/1.1\"." +"HTTP/1.0)," +"AND" +"received" +"WWW" +"TRACE" +"\"MAY\"," +"many" +"*TEXT" +"Unsupported" +"using:" +"connection" +"Unicode" +"*OCTET" +"exceeds" +"(URN)" +"safely" +"ANY" +"can't" +"WARRANTY" +"ISO-8859-8," +"Content-Length" +"consume" +"simple" +"header" +"DNS)" +"colon" +"\"GET\"" +"spans" +"1*HEX" +"table" +"allocated" +"BCP" +"application/pdf" +"LWS:" +"save" +"\"REQUIRED\"," +"Wed," +"C." +"C," +"encryption" +"create" +"(MHTML)\"," +"been" +"." +"HTTP/12.3." +"\"PUT\"" +"context." +"LWS," +"basic" +"expected" +"prototype" +"GMT," +"empty" +"define" +"PNG,\"" +"\"D\"" +"with" +"CA" +"HEX" +"N" +"0*3DIGIT" +"\"W/\"" +"CR" +"\"DELETE\"" +"unnecessarily" +"case" +"exception" +"(A" +"(HTTP)" +"value" +"INFRINGE" +"while" +"\"GZIP" +"\"SHALL\"," +"error" +"\"GMT\"" +"(LWS)." +"resident" +"is" +"thus" +"it" +"encountered" +"parse" +"MIME" +"in" +"SIGCOMM" +"You" +"if" +"result" +"binary" +"different" +"\"A" +")" +"CREATE" +"expired" +"1DIGIT" +"same" +"OPTIONS" +"transfer-encoding" +"BNF," +"unrecognized" +"units" +"UST" +"status" +"\"%" +"used" +"http" +"context" +"I" +"IP" +"(O)." +"allocation" +"running" +"*LWS" +"user" +"SMTP" +"\"SHOULD\"," +"stack" +"task" +"CR." +"failing" +"IETF" +"M.," +"Names" +"In" +"position" +"the" +"audio" +"left" +"US-ASCII." +"MAY" +"THAT" +"being" +"(OK)." +"actions" +"invalid" +"HTTP/1.0)" +"CRC." +"previous" +"adding" +"TO" +"<US-ASCII" +"source" +"ISO-8859-2," +"\"OPTIONS\"" +"location" +"HTTP/1.0" +"HTTP/1.1" +"size," +"has" +"match" +"build" +"URI." +"tests" +"format" +"read" +"H.," +"T" +"using" +"LIMITED" +"OK" +"text/html" +"success" +"ISO-8859-5," +"B," +"signal" +"MIME:" +"(HTCPCP/1.0)\"," +"server" +"ignore" +"OF" +"output" +"page" +"S." +"because" +"old" +"sequence" +"HT." +"B.," +"some" +"back" +"HT" +"Last-Modified" +"growth" +"DEL" +"specified" +"unless" +"H.F.," +"HTTP/1.0." +"(BNF)" +"happens" +"discarded" +"PUT." +"INDEX." +"trace" +"for" +"avoid" +"CR," +"does" +"CONNECT" +"assuming" +"be" +"run" +"GET." +"deleted" +"equivalent" +"X3.4-1986" +"<URL:" +"O" +"ISO-8859-1." +"broken" +"host" +"HTTP/1.0," +"LWS>" +"INFORMATION" +"X3.4-1986," +"by" +"ALPHA," +"Location" +"on" +"DIGIT" +"actual" +"extension" +"tracing" +"R.," +"\"UTF-8," +"*<TEXT," +"OR" +"range" +"3ALPHA" +"URI," +"value." +"Message" +"DELETE" +"content-type" +"or" +"UC" +"No" +"ISO-" +"image" +"ACM" +"HEX\"" +"URL," +"ISO-8859-6," +"T.," +"operator" +"T/TCP" +"file." +"GET\"" +"transfer" +"support" +"*" +"long" +"class" +"start" +"forward" +"was" +"function" +"HT," +"N." +"HTTP/1.1\"," +"OCTET" +"but" +"failure" +"TE:" +"IMPLIED" +"CRLF" +"DNS" +"Error" +"\"ZLIB" +"line" +"trying" +"true" +"GMT" +"count" +"default" +"B." +"ISO-8859-1," +"up" +"ISO-8859-1)" +"SHOULD" +"PURPOSE." +"used." +"WILL" +">" +"called" +"delete" +"DELETE," +"storing" +"USE" +"image/jpeg" +"defined" +"LWS" +"URL." +"unsafe" +"an" +"To" +"as" +"warning" +"exist" +"at" +"file" +"NOT\"" +"NOT," +"W3C/MIT" +"ISO-8859-1:1987." +"SHTTP/1.3," +"no" +"when" +"A," +"virtual" +"A." +"details." +"application" +"valid" +"OPTIONAL" +"\"TRACE\"" +"test" +"MD5" +"you" +"TE" +"ISO-8859-3," +"requested" +"elements" +"C)" +"symbol" +"T." +"code)" +"variable" +"SOCIETY" +"\"MUST" +"TCP" +"ISO-10646\"," +"NOT\"," +"R." +"audio/basic" +"IANA." +"\"WAIS" +"persistent" +"Its" +"As" +"time" +"failures" +"\"ISO-8859-1\"" +"once" +
diff --git a/net/data/fuzzer_dictionaries/net_mime_sniffer_fuzzer.dict b/net/data/fuzzer_dictionaries/net_mime_sniffer_fuzzer.dict new file mode 100644 index 0000000..ec42dd9 --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_mime_sniffer_fuzzer.dict
@@ -0,0 +1,299 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file has been generated with testing/libfuzzer/dictionary_generator.py +# using net_mime_sniffer_fuzzer binary and RFC 2045. +"all" +"BASE64" +"US-ASCII." +"LESS" +"being" +"text" +"supported" +"\"C\"" +"TAB)" +"X.400" +"invalid" +"EQUAL" +"CRLF." +"CRLF," +"A." +"data" +"its" +"to" +"before" +"TO" +"implementation" +"true" +"US-ASCII," +"0" +"only" +"internal" +"TAB" +"(US-ASCII)" +"FORMATTING" +"(A" +"TILDE," +"US-ASCII" +"(STD" +"\"F\")" +"V" +"string" +"get" +"EXPRESSLY" +"H" +"L" +"P" +"T" +"CONTENT-TYPE" +"CONTENT-TRANSFER-" +"not" +"X" +"D" +"BNF" +"ENCODING:" +"name" +"ON" +"d" +"success" +"MAY" +"\"=0D=0A\"." +"bytes" +"(RFC" +"default" +"ONLY" +"RFC." +"THE" +"section" +"\"0123456789ABCDEF\"." +"ASCII" +"*(CRLF" +"A" +"set" +"NO)" +"[RFC-821])" +"\"=0D=0A\"" +"\"=0C\"," +"M." +"some" +"direct" +"sign" +"TEXT," +"\"A\"" +"are" +"allowed." +"\"X-\")" +"MIME." +"\"X-\"," +"event" +"THAN," +"MUST" +"for" +"space" +"+" +"1*DIGIT" +"/" +"THAN" +"may" +"3" +"version" +"HISTORICAL" +"MIME," +"probably" +"CRLF)" +"REQUIRES" +"corruption" +"IMPLEMENTORS:" +"available" +"be" +"C" +"G" +"7BIT\"" +"This" +"NO" +"K" +"NJ" +"O" +"(EXCLAMATION" +"RFC" +"1)" +"[ATK]," +"base" +"STD" +"ISO-8859-1" +"W" +"application/octet-stream" +"\"=3D\"." +"[" +"CA" +"by" +"AND" +"on" +"c" +"NOTE:" +"g" +"of" +"could" +"POINT" +"S" +"times" +"s" +"MANDATORY" +"NOT" +"UA" +"or" +"CR," +"STRONGLY" +"TAB," +"already" +"useful" +"*(SPACE" +"No" +"(MIME)" +"number" +"one" +"CHAR" +"RFC," +"\"=0D\"" +"because" +"[RFC-821])," +"S." +"EBCDIC." +"[RFC-821]." +"(SMTP)" +"IMPORTANT:" +"\"=0A=0D\"" +"use" +"from" +"USA" +"&" +"IETF" +"transfer" +"top" +"(US-ASCII" +"IANA" +"long" +"\"=0D\"," +"few" +"2" +"E" +"expected" +"type" +">" +"\"D\"" +"B" +"N." +"received" +"[RFC-1741]," +"completed" +"J" +"LF)" +"SMTP.)" +"but" +"back" +"warn" +"R" +"SIGN)" +"CRLF" +"EBCDIC" +"BETWEEN" +"CR" +"line" +"Z" +"with" +"unnecessarily" +"must" +"count" +"(HT)" +"GREATER" +"16" +"this" +"was" +"work" +"value" +"ISO-8859-1," +"while" +"following" +"IANA.>" +"called" +"(US-" +"and" +"(PEM)" +"type." +"UNIX" +"RELATIONSHIP" +"ENCODING" +"\"E\"" +"attribute" +"is" +"allowed" +"thus" +"lost." +"Virtual" +"an" +"high" +"as" +"MIME" +"at" +"have" +"in" +"need" +"any" +"contents" +"native" +"LF" +"binary" +"F" +"\"X-\"" +"7BIT" +"TX" +"no" +")" +"FORBIDDEN" +"2(DIGIT" +"format" +"when" +"length" +"mechanism" +"j" +"RESTRICTIONS:" +"application" +"that" +"valid" +"which" +"=" +"LWSP" +"profile" +"ISO" +"begin" +"used" +"multiple" +"SPACE" +"I" +"SMTP" +"after" +"M" +"\"B\"" +"Q" +"U" +"[X400]" +"Y" +"such" +"The" +"N" +"]" +"\"=0A\"," +"a" +"short" +"WARNING" +"ALWAYS" +"SPACE," +"NOTE" +"As" +"does" +"<A" +"the" +"avoid" +"If" +
diff --git a/net/data/fuzzer_dictionaries/net_parse_data_url_fuzzer.dict b/net/data/fuzzer_dictionaries/net_parse_data_url_fuzzer.dict new file mode 100644 index 0000000..1668f4c --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_parse_data_url_fuzzer.dict
@@ -0,0 +1,449 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file has been generated with testing/libfuzzer/dictionary_generator.py +# using net_parse_data_url_fuzzer binary and RFC 3986. +"all" +"DNS" +"text" +"labels" +"DQUOTE" +"\"%D3%81%87%A4%95%81@%C2%85%81%83%88\"." +"[RFC2234]" +"F.," +"FORCE" +"SOCIETY" +"\"%\"" +"with" +"cache" +"WINS," +"D.1." +"0" +"only" +"HTML" +"SPONSORED" +"[RFC1630]." +"D.," +"[RFC1123]" +"US-ASCII" +"(STD" +"[RFC1808]," +"string" +"get" +"==" +"H" +"HEREIN" +"[BCP35]" +"SP)" +"SCTP)" +"(NUL)" +"THE" +"(URI):" +"REPRESENTS" +"[RFC2732]." +"resource" +"A.," +"EXPRESS" +"list" +"(%2E)," +"WILL" +"HE/SHE" +"J." +"INCLUDING" +"common" +"segment." +"[RFC2732]" +"(URL)\"," +"set" +"HTTP" +"IANA" +"INFORMATION" +"(%41-%5A" +"[RFC2518]" +"M." +"direct" +"sign" +"Only" +"Version" +"are" +"allowed." +"\"X\"" +"HTTP," +"(SP)." +"2DIGIT" +"section" +"BUT" +"\"UTF-8," +"3" +"version" +"[RFC1034]" +"probably" +"[UCS]," +"metadata" +"Y.," +"C" +"WWW\"" +"parent" +"0X" +"W3C/IETF" +"S" +"key" +"address" +"INPUT" +"[" +"P." +"WWW:" +"AND" +"received" +"WWW" +"[BCP35]." +"MA" +"\"AS" +"[RFC2718]." +"(IDNA)\"," +"implementation" +"TCP" +"NOT" +"(URN)" +"ANY" +"[RFC1808]" +"WARRANTY" +"useful" +"[RFC1737]." +"[STD63]," +"\"HTTP\"" +"(MIME)" +"TELNET" +"[RFC1630]" +"S." +"D.2." +"B.," +"[RFC2234]." +"[RFC2234]," +"BCP" +"select" +"[STD63];" +"use" +"LATIN" +"from" +"C." +"to" +"WARRANTIES" +"(MHTML)\"," +"ENGINEERING" +"URI;" +"." +"few" +"(DNS)." +"expected" +"USENET" +"type" +"empty" +"XML" +"URL?\"," +"W3C/MIT" +"F" +"CA" +"STD:" +"SMTP" +"[RFC2141]," +"N" +"A)," +"flag" +"NOTE:" +"CR" +"MHTML" +"BY" +"must" +"ANY)," +"ALL" +"[STD63]" +"RIGHTS" +"this" +"SP" +"[BCP19]" +"value" +"INFRINGE" +"while" +"KATAKANA" +"resources" +"error" +"following" +"example" +"loop" +"J.," +"2E:" +"type." +"L." +"have" +"%61-%7A)," +"is" +"allowed" +"thus" +"URI," +"parse" +"STEP" +"MIME" +"UTF-8" +"in" +"[RFC0952]." +"native" +"FOR" +"binary" +"ISO/IEC" +"\"A" +"(%5F)," +")" +"algorithm." +"returning" +"\"A\"," +"[RFC2141]" +"BUFFER" +"ABNF" +"[RFC2557]." +"I." +"WARRANTIES," +"URN" +"EBCDIC" +"A" +"LF" +"used" +"http" +"I" +"IP" +"IS" +"after" +"L" +"Q" +"'A'" +"running" +"HEXDIG" +"such" +"EBCDIC," +"data" +"TASK" +"a" +"task" +"P" +"[ASCII]." +"M.," +"Names" +"flag." +"the" +"If" +"[RFC3490]" +"US-ASCII." +"2C:" +"THAT" +"being" +"when" +"E.," +"(%2D)," +"\"URL:\"" +"mechanism" +"WITH" +"its" +"before" +"tables" +"[UCS]" +"TO" +"BNF" +"platform" +"internal" +"P.," +"ORGANIZATION" +"\"HTTP" +"URI." +"it," +"D" +"format" +"URL" +"S.," +"(0" +"URI\"" +"URI" +"K." +"URI:" +"T" +"D.W." +"not" +"R." +"LIMITED" +"\"%3A\")" +"name" +"OF" +"B." +"[RFC1736]" +"(R)," +"IPR" +"[RFC1738];" +"OUTPUT" +"LALR" +"OR" +"STD" +"[RFC3513]" +"because" +"bytes" +"DNS," +"some" +"back" +"(URI)" +"*DIGIT" +"[RFC2046]" +"[RFC3305]" +"\"%7E\"" +"W3C" +"E." +"for" +"space" +"ABNF\"," +"avoid" +"[RFC1535]." +"/" +"increase" +"may" +"time." +"does" +"'F'" +"[RFC2396]" +"be" +"K.," +"DISCLAIM" +"G" +"(UTF-16)," +"This" +"M" +"INTERNET" +"RFC" +"X3.4," +"base" +"(T):" +"IMPLIED," +"by" +"\"URL\"" +"on" +"DIGIT" +"(ABNF)" +"WEBDAV\"," +"of" +"could" +"R.," +"(ABNF:" +"failed" +"or" +"1*4HEXDIG" +"already" +"No" +"CAPITAL" +"number" +"one" +"ISO" +"FITNESS" +"message" +"open" +"ANSI" +"[BCP19]," +"\"%C3%80\"," +"IETF" +"unknown" +"support" +"\"URN" +"[RFC1123]." +"long" +"[RFC0952]" +"[ASCII]" +":" +"was" +"[RFC3513]." +"[RFC2718]" +"B" +"N." +"that" +"IDNA" +"OCTET" +"but" +"R" +"POSIX" +"LETTER" +"CONTRIBUTOR," +"[RFC1738]" +"line" +"(C)" +"true" +"\"URI\"" +"PARTICULAR" +"target" +"16" +"default" +"double" +"\"URN\"" +"[RFC2557]" +"enabled" +"up" +"TCP," +"PURPOSE." +"MERCHANTABILITY" +"1)" +"IS\"" +"\"IANA" +"called" +"multipart" +"and" +"USE" +"false" +"(IF" +"USA" +"URL," +"an" +"To" +"as" +"(%7E)" +"at" +"file" +"need" +"any" +"\"%E3%82%A2\"." +"physical" +"1*HEXDIG" +"no" +"[RFC1737]" +"-" +"invalid" +"A." +"application" +"valid" +"take" +"which" +"test" +"[RFC2732]," +"you" +"=" +"GRAVE" +"<URI>" +"begin" +"[RFC2396]," +"multiple" +"2B:" +"period," +"UDP," +"[RFC1535]" +"T." +"(UCS)\"," +"U" +"A-F." +"T.," +"The" +"]" +"source" +"D." +"persistent" +"traditional" +"L.," +"As" +"IMPLIED" +"(URL)" +"ALPHA" +"[RFC3305]." +"H.," +"\"MIME"
diff --git a/net/data/fuzzer_dictionaries/net_url_request_fuzzer.dict b/net/data/fuzzer_dictionaries/net_url_request_fuzzer.dict new file mode 100644 index 0000000..742ae16 --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_url_request_fuzzer.dict
@@ -0,0 +1,1718 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Fuzzer dictionary targetting HTTP/1.x responses. + +# Entries that are generally useful in headers +":" +"\x0A" +"\x0D" +"0" +"50" +"500" +# Horizontal whitespace. Matters mostly in status line. +" " +"\x09" +# Header continuation +"\x0D\x0A\x09" +# Used in a lot of individual headers +";" +"=" +"," +"\"" +"-" + +# Status line components +"HTTP" +"/1.1" +"/1.0" +# More interesting status codes. Leading space so can be inserted into +# other status lines. +" 100" +" 200" +" 206" +" 301" +" 302" +" 303" +" 304" +" 307" +" 308" +" 401" +" 403" +" 404" +" 500" +" 501" +" 403" + +# Full status lines (Some with relevant following headers) +"HTTP/1.1 200 OK\x0A\x0A" +"HTTP/1.1 100 Continue\x0A\x0A" +"HTTP/1.1 401 Unauthorized\x0AWWW-Authenticate: Basic realm=\"Middle-Earth\"\x0A\xA0" +"HTTP/1.1 407 Proxy Authentication Required\x0AProxy-Authenticate: Digest realm=\"Middle-Earth\", nonce=\"aaaaaaaaaa\"\x0A\x0A" +"HTTP/1.0 301 Moved Permanently\x0ALocation: /a\x0A\x0A" +"HTTP/1.1 302 Found\x0ALocation: http://lost/\x0A\x0A" + +# Proxy authentication headers. Note that fuzzers don't support NTLM or +# negotiate. +"WWW-Authenticate:" +"Proxy-Authenticate:" +"Basic" +"Digest" +"realm" +"nonce" + +"Connection:" +"Proxy-Connection:" +"Keep-Alive" +"Close" +"Upgrade" +"\x0AConnection: Keep-Alive" +"\x0AConnection: Close" +"\x0AProxy-Connection: Keep-Alive" +"\x0AProxy-Connection: Close" + +"Content-Length:" +"Transfer-Encoding:" +"chunked" +"\x0AContent-Length: 0" +"\x0AContent-Length: 500" +"\x0ATransfer-Encoding: chunked\x0A\x0A5\x0A12345\x0A0\x0A\x0A" + +"Location:" +"\x0ALocation: http://foo/" +"\x0ALocation: http://bar/" +"\x0ALocation: https://foo/" +"\x0ALocation: https://bar/" + +"Accept-Ranges:" +"bytes" +"\x0AAccept-Ranges: bytes" + +"Content-Range:" + +"Age:" +"\x0AAge: 0" +"\x0AAge: 3153600000" + +"Cache-Control:" +"max-age" +"no-cache" +"no-store" +"must-revalidate" +"\x0ACache-Control: max-age=3153600000" +"\x0ACache-Control: max-age=0" +"\x0ACache-Control: no-cache" +"\x0ACache-Control: no-store" +"\x0ACache-Control: must-revalidate" + +"Content-Disposition:" +"attachment" +"filename" + +"Content-Encoding:" +"gzip" +"deflate" +"sdch" +"br" +"\x0AContent-Encoding: gzip" +"\x0AContent-Encoding: deflate" +"\x0AContent-Encoding: sdch" +"\x0AContent-Encoding: br" + +"Date:" +"Fri, 01 Apr, 2050 14:14:14 GMT" +"Mon, 28 Mar, 2016 04:04:04 GMT" +"\x0ADate: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0ADate: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Last-Modified:" +"\x0ALast-Modified: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0ALast-Modified: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Expires:" +"\x0AExpires: Fri, 01 Apr, 2050 14:14:14 GMT" +"\x0AExpires: Mon, 28 Mar, 2016 04:04:04 GMT" + +"Set-Cookie:" +"Expires" +"Max-Age" +"Domain" +"Path" +"Secure" +"HttpOnly" +"Priority" +"Low" +"Medium" +"High" +"SameSite" +"Strict" +"Lax" +"\x0ASet-Cookie: foo=bar" +"\x0ASet-Cookie: foo2=bar2;HttpOnly;Priority=Low;SameSite=Strict;Path=/" +"\x0ASet-Cookie: foo=chicken;SameSite=Lax" + +"Strict-Transport-Security:" +"includeSubDomains" + +"Vary:" +"\x0AVary: Cookie" +"\x0AVary: Age" + +"ETag:" +"\x0AETag: jumboshrimp" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using net_url_request_fuzzer binary and RFC 3986. +"all" +"consider" +"Transfer-Encoding" +"D.," +"prefix" +"concept" +"CR" +"follow" +"RFC-850" +"(which" +"ISDN" +"\"TE\"" +"increase" +"number" +"calculate" +"\"IETF" +"fixed-length" +"\"OPTIONAL\"" +"to" +"Host" +"program" +"Western" +"under" +"Changing" +"(STD" +"digit" +"returned" +"returning" +"very" +"SP," +"SP." +"Validation" +"(URI):" +"Incomplete" +"Origin" +"--" +"cause" +"EXPRESS" +"list" +"large" +"expired." +"small" +"(URL)\"," +"range." +"past" +"second" +"Version" +"allowed." +"tag." +"implemented" +"canonical" +"even" +"established" +"errors" +"incompatible" +"section" +"contributed" +"while" +"decoding" +"version" +"above" +"TTL" +"new" +"increasing" +"method" +"WWW-" +"never" +"equals" +"here" +"ranges" +"reported" +"compressed" +"active" +"path" +"strong" +"Index" +"changed" +"DISCLAIMS" +"prior" +"amount" +"published" +"NOT" +"error," +"options" +"via" +"followed" +"secure" +"family" +"\"HTTP\"" +"Unspecified" +"replace" +"CERN/3.0" +"CTE" +"(CTE)" +"TO" +"Too" +"CTL" +"PUT," +"total" +"PUT)" +"Security" +"select" +"languages" +"TASK" +"exception." +"would" +"contains" +"negative" +"User-Agent" +"call" +"MUST," +"type" +"until" +"authorization" +"more" +"ISO-8859-9," +"initiated" +"composite" +"LF," +"line" +"it" +"warn" +"American" +"varying" +"known" +"Found" +"MHTML" +"must" +"parse" +"none" +"1999" +"work" +"paragraph" +"sent" +"evolved" +"root" +"example" +"requested," +"history" +"type." +"(HTCPCP/1.0)\"," +"accept" +"currency" +"minimum" +"Compromise" +"numbers" +"want" +"type:" +"times" +"simple" +"LF" +"information" +"needs" +"end" +"goal" +"verify" +"far" +"Pragma" +"reject" +"A" +"badly" +"HEAD" +"description" +"number." +"insecure" +"after" +"variant" +"confirmed" +"reflect" +"wrong" +"law" +"response" +"types" +"a" +"All" +"short" +"attempt" +"third" +"menu." +")" +"algorithms" +"cases." +"File" +"\"DEFLATE" +"order" +"\"SHOULD" +"help" +"don't" +"over" +"vary" +"satisfied" +"CD-ROM," +"held" +"HTTP-WG." +"through" +"of," +"existence" +"its" +"digest" +"before" +"difference" +"20" +"termed" +"MAY," +"fix" +"ISO-3166" +"actually" +"407" +"(GNU" +"absence" +"\"HTTP/1.1\"," +"Sun," +"MERCHANTABILITY" +"408" +"it." +"them" +"good" +"return" +"HTTP/2.4" +"combination" +"URL" +"URI" +"Due" +"Bad" +"they" +"Control" +"always" +"decimal" +"refresh" +"expectation." +"MAY" +"token" +"]URI," +"[CRLF]" +"found" +"Content-Type" +"ports" +"trailer" +"referred" +"status" +"weight" +"series" +"reduce" +"(URI)" +"expect" +"max-age=0" +"combining" +"operation" +"beyond" +"Type" +"event" +"is:" +"by" +"E." +"network" +"Server:" +"open" +"\"MUST/MAY/SHOULD\"" +"since" +"request/response" +"content" +"message." +"PATCH," +"7" +"2DIGIT" +"available." +"K.," +"linear" +"Extension" +"University" +"enclosing" +"free" +"reason" +"base" +"proxy" +"POST" +"beginning" +"generate" +"text/plain" +"definition" +"perform" +"Partial" +"created" +"UPALPHA" +"script" +"\"GMT\"" +"filter" +"SSL" +"expecting" +"If-Modified-Since" +"HEAD." +"HEAD," +"assign" +"user" +"major" +"already" +"Copyright" +"encoding" +"Cache" +"Please" +"token." +"TCP" +"content-range" +"least" +"another" +"FITNESS" +"invalid." +"\"" +"service" +"image/gif" +"top" +"header)" +"construct" +"2" +"ignored." +"listed" +"passed" +"Delta" +"LOALPHA" +"scheme" +"store" +"too" +"M." +"immediate" +"direct" +"tokens" +"part" +"WAIS" +"F.," +"to:" +"distance" +"Code" +"target" +"Content-Type:" +"zero," +"likely" +"WWW-Authenticate" +"matter" +"idle" +"determined" +"stale" +"ISO-8859-8," +"payload" +"ANSI" +"B" +"seen" +"HTTP/1.1.)" +"null" +"OPTIONS" +"contents" +"paths" +"data." +"data)" +"zero" +"depending" +"Acceptable" +"responsible" +"(MIME" +"also" +"internal" +"(C)" +"build" +"finding" +"With" +"UCI" +"Names" +"content-" +"added" +"headers." +"Content-Disposition" +"object" +"\"MUST\"," +"most" +"regular" +"ensure" +"letter" +"2*N" +"services" +"The" +"Responses" +"payload." +"clear" +"sometimes" +"flow" +"Client" +"ISO-8859-3," +"Its" +"incomplete" +"\"MIME" +"Note:" +"particularly" +"labels" +"\"C\"" +"session" +"Unrecognized" +"find" +"]" +"implementation" +"[RFC" +"ranges." +"BNF," +"user-agent" +"failed" +"URL)." +"LDAP)" +"8" +"US-ASCII" +"do" +"hit" +"stop" +"\"HTTP\"." +"While" +"Set" +"rest" +"report" +"during" +"body," +"PUT" +"(via" +"public" +"twice" +"bad" +"common" +"release" +"require" +"set" +"mandatory" +"reference" +"\"F\"" +"MIME:" +"depends" +"individual" +"result" +"J." +"close" +"subject" +"said" +"headers" +"WWW\"," +"See" +"BUT" +"unable" +"various" +"probably" +"0)" +"0." +"0," +"discovery" +"available" +"we" +"reasons." +"terms" +"missing" +"Server" +"(MIME)" +"OPTIONAL;" +"AND" +"both" +"protect" +"Unexpected" +"last" +"reverse" +"\"MAY\"," +"*TEXT" +"against" +"connection" +"became" +"context" +"exceeds" +"however," +"mean" +"reached." +"finds" +"experimental" +"load" +"Redirect" +"Content-Length" +"alternate" +"consume" +"point" +"reasons" +"had" +"header" +"DNS)" +"DNS." +"B.," +"(O)." +"1.0" +"throughout" +"BCP" +"[" +"application/pdf" +"\"REQUIRED\"," +"C." +"basis" +"\"POST\"" +"create" +"acceptance" +"(MHTML)\"," +"Reason" +"been" +"." +"much" +"\"PUT\"" +"basic" +"expected" +"text/html;" +"empty" +"HTTP/1.0" +"concerning" +"Flow" +"N" +"size," +"\"W/\"" +"reason." +"MA" +"\"DELETE\"" +"unnecessarily" +"exception" +"handling" +"Group," +"particular," +"technical" +"near" +"\"GZIP" +"error" +"(IANA)" +"\"TRACE\"" +"Accept-Language" +"played" +"is" +"herein" +"encountered" +"E-mail" +"MIME" +"in" +"accepted." +"if" +"containing" +"\"A" +"lengths" +"make" +"format" +"\"I" +"unrecognized" +"widely" +"9" +"several" +"higher" +"\"%" +"used" +"temporary" +"alert" +"action" +"purpose" +"characters" +"stack" +"recent" +"lower" +"task" +"database" +"NNTP" +"failing" +"person" +"client" +"length." +"entry" +"the" +"left" +"protocol" +"US-ASCII." +"THAT" +"bandwidth" +"inactive" +"(TE)" +"Internet" +"HTTP/1.0)" +"HTTP/1.0." +"previous" +"tables" +"unique" +"case." +"character" +"Trailers" +"source" +"ISO-8859-2," +"subjects" +"WILL" +"location" +"0*3DIGIT" +"input" +"save" +"remaining" +"URI." +"URI," +"fact," +"transfer-encoding" +"possible" +"required." +"Assigned" +"Length" +"URI;" +"integer" +"bit" +"Sat," +"desire" +"OK" +"success" +"ISO-8859-5," +"OF" +"signal" +"INFRINGE" +"H.F.," +"specific" +"X3.4-1986" +"security" +"OR" +"S." +"right" +"old" +"often" +"deal" +"people" +"successfully" +"some" +"back" +"HT" +"Last-Modified" +"headers)" +"DEL" +"examples" +"unless" +"(BNF)" +"TCP/IP" +"ignore" +"PUT." +"INDEX." +"headers," +"for" +"track" +"CONNECT" +"be" +"replaced" +"run" +"deleted" +"example," +"<URL:" +"O" +"last-modified" +"become" +"relating" +"permitted" +"ALPHA," +"First" +"ENGINEERING" +"anything" +"tracing" +"\"UTF-8," +"*<TEXT," +"range" +"3ALPHA" +"extensions" +"positive" +"block" +"IRC/6.9," +"W3C/MIT" +"into" +"within" +"ACM" +"two" +"down" +"file." +"compression" +"IETF" +"expired" +"support" +"initial" +"question" +"long" +"User" +"HT." +"forward" +"version." +"sections" +"disallowed" +"lowest" +"HT," +"an" +"form" +"attempted" +"registered" +"differences" +"URL." +"failure" +"server." +"link" +"CRLF" +"DNS" +"encoded" +"Non-Authoritative" +"true" +"GMT" +"reset" +"consist" +"versions" +"used," +"maximum" +"us" +"used." +"If-None-Match" +"HTML\"," +"similar" +"called" +"delete" +"DELETE," +"storing" +"associated" +"Introduction" +"request" +"specified" +"influence" +"To" +"single" +"warning" +"exist" +"New" +"NOT," +"check" +"ISO-8859-1:1987." +"encrypt" +"Only" +"no" +"May" +"when" +"A," +"invalid" +"A." +"MHTML," +"name." +"setting" +"role" +"Proxy" +"test" +"TE" +"pseudonym" +"negotiation." +"exceeded" +"update" +"T." +"variable" +"NOT\"," +"R." +"longer" +"algorithm" +"IANA." +"age" +"packets" +"together" +"An" +"As" +"time" +"failures" +"requires" +"avoid" +"code." +"once" +"code" +"partial" +"chain" +"TEXT" +"results" +"existing" +"go" +"(LZW)." +"provided." +"CPU" +"CREATE" +"Notice" +"LF>" +"\"HEAD\"" +"zone" +"UNIX," +"ARPA" +"send" +"Standard" +"environment" +"USENET" +"Not" +"Nov" +"include" +"resources" +"string" +"advantage" +"outside" +"Explicit" +"ALL" +"HTTP/1.1;" +"entries" +"HTTP/1.1," +"HTTP/1.1." +"entire" +"Protocol" +"level" +"did" +"button" +"HTTP/1.0\"," +"(RFC" +"try" +"ONLY" +"Tag" +"(LWS" +"\"SHOULD\"," +"prevent" +"\"A\"..\"Z\">" +"unexpected" +"INFORMATION" +"Failed" +"\"A\"" +"Satisfiable" +"port" +"append" +"\"HTTP/1.0\"" +"formats" +"ISO-8859-4," +"appear" +"rate" +"opaque" +"current" +"waiting" +"HTML" +"shared" +"CRLF)" +"302" +"body" +"FTP" +"NNTP." +"\"SHALL" +"following" +"objects" +"address" +"1*HEX" +"Distribution" +"entry." +"HTTP." +"change" +"cache)" +"incoming" +"\"AS" +"receive" +"larger" +"host" +"descended" +"here." +"+" +"{" +"makes" +"composed" +"named" +"useful" +"addresses" +"extra" +"detected." +"When" +"private" +"session." +"gateway" +"Status" +"use" +"from" +"stream" +"working" +"value." +"next" +"few" +"--THIS_STRING_SEPARATES" +"POST," +"memory" +"scope" +"means" +"HEX\"" +"(GMT)," +"bytes:" +"Default" +"Require" +"Required" +"DIGIT" +"validity" +"bytes," +"Connection" +"Time" +"cases" +"name:" +"behalf" +"MD5" +"lowercase" +"RIGHTS" +"this" +"NTP" +"--THIS_STRING_SEPARATES--" +"Syntax" +"values" +"can" +"believed" +"making" +"closing" +"modifier" +"J.," +"control" +"reserved" +"links" +"process" +"attribute" +"high" +"tag" +"allowed" +"Policy" +"input," +"native" +"class," +"Missing" +"HTTP-" +"HTTP," +"charset" +"delay" +"located" +"R.," +"instead" +"1XX" +"WARRANTIES," +"parameter" +"FORCE" +"STD" +"may" +"Request" +"British" +"HEREIN" +"Roman" +"client's" +"[SP" +"ANSI," +"date" +"such" +"data" +"HTTP/1.1\"," +"Y." +"UA" +"revalidate" +"element" +"so" +"allow" +"(LWS)" +"holds" +"move" +"years" +"including" +"LINK," +"still" +"pointer" +"non-zero" +"1" +"negotiated" +"Multiple" +"line." +"using:" +"forms" +"Referer" +"P.," +"PNG,\"" +"cache-control" +"policy" +"mail" +"\"HTTP" +"SIGCOMM" +"greater" +"matches" +"lesser" +"not" +"parsing" +"matched" +"term" +"name" +"establishment" +"A.," +"ISO-639" +"entirely" +"identifier" +"elements" +"|" +"successful" +"domain" +"From" +"Network" +"related" +"UNLINK" +"trying" +"(LZ77)" +"year" +"(MIC)" +"Parameter" +"special" +"out" +"ultimately" +"space" +"REQUIRED" +"416" +"WARRANTY" +"4DIGIT" +"time," +"L." +"time." +"supports" +"(A," +"state" +"This" +"derived" +"INTERNET" +"possibility" +"\"B\"" +"RFC" +"IMPLIED," +"byte" +"received." +"log" +"ISO-8859-7," +"\"HTTP/1.1\"" +"language" +"could" +"transition" +"programming" +"tries" +"keep" +"length" +"place" +"S.," +"first" +"origin" +"there" +"sent." +"3DIGIT" +"K." +"one" +"CHAR" +"list," +"ISI" +"version:" +"message" +"CSS1," +"quality" +"size" +"doesn't" +"given" +"For" +"enabled." +"unknown" +"system" +"unspecified" +"parallel" +"priority" +"their" +"attack" +"intermediate" +"HTTP:" +"Date" +"x-gzip" +"Data" +"Response" +"HTTP/2.0," +"gives" +"Success" +"that" +"completed" +"exactly" +"R" +"pragma" +"(IANA" +"copy" +"than" +"History" +"wide" +"12" +"14" +"16" +"was" +"Universal" +"protected" +"servers." +"were" +"1)" +"IS\"" +"SHTTP/1.3," +"1*8ALPHA" +"Location" +"and" +"Information" +"false" +"1.1" +"1.2" +"(2**N)," +"turned" +"Tue," +"Other" +"SP" +"(LWS)." +"have" +"MIME," +"need" +"Mail" +"any" +"Requested" +"conversion" +"HTTP/2.13," +"database." +"After" +"able" +"mechanism" +"OPTIONAL" +"take" +"which" +"HTTP/0.9," +"201" +"200" +"begin" +"multiple" +"Name" +"trace" +"206" +"buffer" +"who" +"connected" +"plus" +"HTTP/12.3." +"\"OPTIONS\"" +"segment" +"class" +"D." +"considered" +"GET" +"Some" +"TE:" +"L.," +"(URL)" +"}" +"fact" +"Web" +"WA" +"violation" +"text" +"supported" +"synchronous" +"Authentication" +"inconsistent" +"CRLF." +"CRLF," +"label" +"Public" +"MUST" +"true," +"cache." +"upgrade" +"based" +"Posting" +"(" +"cache" +"3" +"should" +"only" +"Proxy-Authorization" +"Byte" +"Strong" +"local" +"MIC" +"WARRANTIES" +"(UA)" +"<US-ASCII" +"handle" +"get" +"E.," +"Accept-Ranges" +"expectation" +"(See" +"cannot" +"128" +"THE" +"conjunction" +"BNF" +"DIGIT," +"closure" +"resource" +"ended" +"cached" +"W." +"ISO-8859." +"calling" +"INCLUDING" +"contain" +"ISI/RR-98-463," +"\"CONNECT\"" +"where" +"ignored" +"IANA" +"exists" +"configured" +"C" +"packet" +"up" +"relative" +"multipart" +"end." +"detect" +"has" +"stream." +"1*DIGIT" +"Oct" +"written" +"LIMITED" +"closed" +"between" +"boundary" +"reading" +"across" +"\"RECOMMENDED\"," +"Body" +"ability" +"FOR" +"opening" +"importance" +"screen" +"connection." +"ISO-8859-1" +"UNIX" +"key" +"group" +"configuration" +"P." +"valid" +"\"HTTP/1.1\"." +"HTTP/1.0)," +"WWW" +"revoked" +"TRACE" +"many" +"taking" +"(OK)" +"equal" +"Rules" +"(0)" +"Unicode" +"*OCTET" +"(URN)" +"safely" +"can't" +"among" +"(OK)." +"Log" +"period" +"colon" +"adding" +"spans" +"article" +"table" +"allocated" +"LWS:" +"Identifier" +"Wed," +"USA" +"Proxy-Authenticate" +"encryption" +"Jun" +"copies" +"But" +"mark" +"defined" +"combined" +"LWS," +"LWS" +"prototype" +">" +"enable" +"401" +"content-disposition" +"received" +"unsafe" +"SMTP" +"ANY" +"World" +"chain." +"case" +"disconnected" +"(HTTP)" +"these" +"Number" +"value" +"will" +"Fri," +"\"SHALL\"," +"Any" +"Additional" +"resident" +"NOT\"" +"thus" +"it," +"according" +"Content" +"Content-Range" +"properties" +"Unsupported" +"malformed" +"PARTICULAR" +"You" +"binary" +"different" +"perhaps" +"generic" +"pay" +"set." +"00:00:00" +"1DIGIT" +"same" +"parts" +"largest" +"units" +"document" +"Types" +"residing" +"breakdown" +"UTC" +"extended" +"http" +"I" +"IP" +"effect" +"allocation" +"running" +"*LWS" +"infinite" +"frequently" +"tracking" +"undefined" +"CR." +"well" +"It" +"If-Range" +"patterns" +"without" +"M.," +"CR," +"In" +"position" +"model" +"audio" +"If" +"negotiation" +"Also," +"Service" +"less" +"being" +"generally" +"obtain" +"actions" +"Access" +"stored" +"CRC." +"However," +"application" +"capabilities" +"appeared" +"add" +"Thu," +"4" +"Although" +"HTTP/1.1" +"usage" +"(A" +"match" +"details" +"tests" +"aspects" +"read" +"Many" +"H.," +"early" +"action," +"T" +"address." +"using" +"password" +"loss" +"like" +"text/html" +"Content-Encoding" +"B," +"B." +"\"HTTP/1.1" +"server" +"discarded" +"either" +"BACK)" +"output" +"Operation" +"page" +"\"GET\"" +"exceed" +"because" +"sequence" +"uppercase" +"Since" +"growth" +"Authority" +"respect" +"International" +"recognition" +"happens" +"provided" +"trust" +"lead" +"MIT" +"highest" +"expectation," +"does" +"Authorization" +"assuming" +"refer" +"GET)" +"GET," +"GET." +"equivalent" +"Official" +"C)" +"ISO-8859-1." +"broken" +"Range" +"HTTP/1.0," +"LWS>" +"X3.4-1986," +"Microsoft" +"on" +"about" +"actual" +"extension" +"of" +"C," +"accepted" +"FTP," +"compatible" +"addition" +"unidirectional" +"Message" +"DELETE" +"content-type" +"or" +"UC" +"final" +"No" +"ISO-" +"image" +"Two" +"Internal" +"times," +"ISO-8859-6," +"determine" +"T.," +"operator" +"T/TCP" +"additional" +"area" +"GET\"" +"transfer" +"*" +"decode" +"start" +"describes" +"low" +"strict" +"context." +"function" +"complete" +"N." +"enough" +"OCTET" +"but" +"IMPLIED" +"Error" +"Dec" +"with" +"Trailer" +"count" +"clients." +"made" +"compute" +"default" +"GMT," +"ISO-8859-1," +"Moved" +"this," +"ISO-8859-1)" +"SHOULD" +"PURPOSE." +"limit" +"GMT." +"site" +"problem" +"define" +"USE" +"image/jpeg" +"\"E\"" +"URL," +"describe" +"general" +"as" +"UST" +"at" +"file" +"lifetime" +"are" +"Accept-Encoding" +"incorrect" +"variety" +"\"D\"" +"virtual" +"details." +"field" +"other" +"5" +"Purpose" +"you" +"CA" +"requested" +"repeat" +"HEX" +"symbol" +"Cache-Control" +"Remove" +"March" +"important" +"H." +"code)" +"included" +"SOCIETY" +"\"MUST" +"ISO-10646\"," +"\"ZLIB" +"audio/basic" +"\"ISO-8859-1\"" +"\"WAIS" +"persistent" +"having" +"directory" +"ALPHA" +"validation" +"original" +
diff --git a/net/data/fuzzer_dictionaries/net_websocket_frame_parser_fuzzer.dict b/net/data/fuzzer_dictionaries/net_websocket_frame_parser_fuzzer.dict new file mode 100644 index 0000000..afba1606 --- /dev/null +++ b/net/data/fuzzer_dictionaries/net_websocket_frame_parser_fuzzer.dict
@@ -0,0 +1,460 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file has been generated with testing/libfuzzer/dictionary_generator.py +# using net_websocket_frame_parser_fuzzer binary and RFC 6455. +"WG" +"all" +"LETTER" +"(\"MUST\"," +"Unknown" +"supported" +"|K|" +"[WSAPI]," +"[TALKING]." +"\"UTF-8," +"[RFC6265]" +"[FIPS.180-3]," +"F.," +"T." +"U+007A" +"\"IETF" +"implementation" +"(" +"cache" +"\"OPTIONAL\"" +"environment" +"0" +"only" +"version" +"G.," +"text" +"G." +"[RFC3987])." +"string" +"get" +"==" +"failed." +"[RFC3986]." +"(2MSL)," +"|F|R|R|R|" +"DIGIT)" +"FIN" +"(URI):" +"SHA-1" +"resource" +"MAY" +"EXAMPLE:" +"list" +"SYN" +"large" +"A.5" +"J." +"common" +"RSV3:" +"\"RECOMMENDED\"," +"ASCII" +"(IP" +"Y.," +"set" +"HTTP" +"IANA" +"frame" +"M." +"direct" +"this," +"Version" +"are" +"[RFC4086]" +"GET," +"UTF-8-" +"_ASCII_" +"TLS," +"TLS." +"Z)" +"GET" +"section" +"[RFC3986]:" +"TCP" +"ABNF." +"unable" +"probably" +"MUST" +"[RFC3986]," +"metadata" +"available" +"R.," +"C" +"hash" +"\"SHALL" +"U+007E" +"\"HTTP/1.1" +"\"MAY\"," +"CONNECTING" +"_ASCII" +"key" +"address" +"OPTIONAL;" +"[" +"P." +"received" +"NOTE:" +"RSV1," +"WHATWG" +"\"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"" +"(IETF)" +"IMPLEMENTATION" +"|I|S|S|S|" +"CLOSED" +"NOT" +"[RFC3629]." +"J.," +"UTF-8." +"\"REQUIRED\"," +"useful" +"SHUT_WR" +"(IETF)." +"H." +"HTTP)." +"S." +"ASCII)" +"allocated" +"poll" +"BCP" +"select" +"[RFC4270])." +"use" +"LATIN" +"from" +"C." +"certificate" +"to" +"\"SOCKS" +"create" +"S.," +"|N|V|V|V|" +"[RFC2616]" +"(IRI)" +"call" +"memory" +"expected" +"type" +"empty" +"with" +"[RFC2616]." +"OPEN" +"[RFC4648]" +"BNF" +"NOT\"," +"[RFC2119]" +"flag" +"[RFC4270]" +"TCP." +"[RFC2616]," +"\"258EAFA5-E914-47DA-" +"CLOSING" +"unnecessarily" +"must" +"high" +"[RFC3864]." +"ANSI" +"this" +"work" +"value" +"while" +"\"SHALL\"," +"error" +"following" +"closing" +"(NZDIGIT" +"UTF-8" +"type." +"(UUID)" +"is" +"in" +"thus" +"Invalid" +"parse" +"key." +"allowed" +"Z)." +"TLS.)" +"failed" +"|A|" +"binary" +"\"A" +"[RFC5226]" +")" +"algorithm." +"returning" +"ISSN:" +"U+0041" +"write" +"[RFC5234]" +"I." +"units" +"[RFC4122]" +"[WSAPI]" +"URN" +"A" +"used" +"XOR" +"HTML" +"[RFC1928]" +"may" +"IP" +"after" +"(TLS)" +"H.," +"IRI" +"running" +"*LWS" +"HTTPS" +"CAPITAL" +"SMTP" +"such" +"data" +"a" +"length:" +"[ANSI.X3-4.1986]" +"tracking" +"[RFC6265]." +"i" +"2BX" +"or" +"[RFC5226]." +"[RFC5226]," +"M.," +"Names" +"HTTP," +"RST" +"the" +"MOD" +"If" +"\"SHOULD" +"being" +"-" +"SHA-1," +"E.," +"(IDN)" +"ABNF)." +"D.," +"mechanism" +"[RFC4122])" +"(GUID," +"RSV3" +"its" +"_A" +"before" +"U+0061" +"[RFC2119]." +"unsigned" +"writing" +"source" +"SOCKS5" +"P.," +"HTTP/1.1" +"\"HTTP" +"URI." +"..." +"format" +"read" +"|S|" +"URI" +"Bad" +"URI:" +"[RFC3629]" +"not" +"R." +"\"IESG" +"missing," +"name" +"success" +"C5AB0DC85B11\"." +"signal" +"WD-" +"A.," +"API" +"SQL" +"page" +"STD" +"API)," +"because" +"bytes" +"some" +"back" +"HYBI" +"\"258EAFA5-" +"RST," +"[RFC6066]" +"[RFC3864]" +"I.," +"RSV2," +"[RFC5234]," +"for" +"space" +"ABNF\"," +"avoid" +"/" +"L." +"time." +"does" +"TIME_WAIT" +"CONNECT" +"GUID." +"assuming" +"supports" +"[RFC3986]" +"be" +"run" +"This" +"ABNF," +"PUB" +"free" +"E914-47DA-95CA-C5AB0DC85B11\"" +"RFC" +"X3.4," +"base" +"[RFC4648])," +"[RFC4648])." +"[RFC6066]." +"received." +"by" +"[RFC2818]." +"on" +"DIGIT" +"FIN:" +"ABNF" +"TLS\"," +"of" +"could" +"&" +"[TALKING]" +"wrong" +"times" +"[RFC6202]" +"length" +"UI" +"UK" +"transfer" +"HTTP/1.1\"." +"[ANSI.X3-4.1986]." +"HTTP/1.1\"," +"support" +"[RFC5246]." +"API\"," +"already" +"HTTP/HTTPS" +">=" +"E914-47DA-95CA-C5AB0DC85B11\"," +"[RFC4648])" +"number" +"one" +"IDN" +"Start" +"NZDIGIT" +"RFC." +"ISO" +"SMALL" +"open" +"U+0021" +"size" +"IETF" +"unknown" +"top" +"*" +"MASK" +"long" +"class" +"start" +"too" +":" +"was" +"configured" +"[RFC2817]." +"TLS" +"that" +"completed" +"[FIPS.180-3]" +"but" +"95CA-C5AB0DC85B11\"" +"BSD" +"FIPS" +"[RFC6454]" +"DNS" +"Error" +"line" +"trying" +"true" +"\"URI\"" +"target" +"16" +"default" +"B." +"up" +"SHOULD" +"(IESG)." +"API." +"called" +"and" +"UPGRADE" +"false" +"[RFC6202]." +"[RFC2817]" +"URI)" +"lost." +"[RFC2818]" +"an" +"To" +"as" +"at" +"have" +"need" +"null" +"U+005A" +"any" +"contents" +"[RFC5246]" +"\"SHOULD\"," +"no" +"when" +"invalid" +"A." +"application" +"valid" +"take" +"which" +"test" +"you" +"=" +"[RFC5321]" +"requested" +"begin" +"multiple" +"[RFC5234]." +"(FIN/ACK)," +"HTTP\"," +"[RFC3987]" +"L-S.," +"\"MUST" +"W3C" +"\"MUST\"," +"E." +"Common" +"T.," +"The" +"]" +"pages" +"D." +"\"GET" +"[RFC6265])," +"TW12" +"IANA." +"finished" +"L.," +"As" +"ALPHA" +"+" +"D.3." +
diff --git a/net/data/http/http.dict b/net/data/http/http.dict deleted file mode 100644 index 2e750cb8..0000000 --- a/net/data/http/http.dict +++ /dev/null
@@ -1,163 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Fuzzer dictionary targetting HTTP/1.x responses. - -# Entries that are generally useful in headers -":" -"\x0A" -"\x0D" -"0" -"50" -"500" -# Horizontal whitespace. Matters mostly in status line. -" " -"\x09" -# Header continuation -"\x0D\x0A\x09" -# Used in a lot of individual headers -";" -"=" -"," -"\"" -"-" - -# Status line components -"HTTP" -"/1.1" -"/1.0" -# More interesting status codes. Leading space so can be inserted into -# other status lines. -" 100" -" 200" -" 206" -" 301" -" 302" -" 303" -" 304" -" 307" -" 308" -" 401" -" 403" -" 404" -" 500" -" 501" -" 403" - -# Full status lines (Some with relevant following headers) -"HTTP/1.1 200 OK\x0A\x0A" -"HTTP/1.1 100 Continue\x0A\x0A" -"HTTP/1.1 401 Unauthorized\x0AWWW-Authenticate: Basic realm=\"Middle-Earth\"\x0A\xA0" -"HTTP/1.1 407 Proxy Authentication Required\x0AProxy-Authenticate: Digest realm=\"Middle-Earth\", nonce=\"aaaaaaaaaa\"\x0A\x0A" -"HTTP/1.0 301 Moved Permanently\x0ALocation: /a\x0A\x0A" -"HTTP/1.1 302 Found\x0ALocation: http://lost/\x0A\x0A" - -# Proxy authentication headers. Note that fuzzers don't support NTLM or -# negotiate. -"WWW-Authenticate:" -"Proxy-Authenticate:" -"Basic" -"Digest" -"realm" -"nonce" - -"Connection:" -"Proxy-Connection:" -"Keep-Alive" -"Close" -"Upgrade" -"\x0AConnection: Keep-Alive" -"\x0AConnection: Close" -"\x0AProxy-Connection: Keep-Alive" -"\x0AProxy-Connection: Close" - -"Content-Length:" -"Transfer-Encoding:" -"chunked" -"\x0AContent-Length: 0" -"\x0AContent-Length: 500" -"\x0ATransfer-Encoding: chunked\x0A\x0A5\x0A12345\x0A0\x0A\x0A" - -"Location:" -"\x0ALocation: http://foo/" -"\x0ALocation: http://bar/" -"\x0ALocation: https://foo/" -"\x0ALocation: https://bar/" - -"Accept-Ranges:" -"bytes" -"\x0AAccept-Ranges: bytes" - -"Content-Range:" - -"Age:" -"\x0AAge: 0" -"\x0AAge: 3153600000" - -"Cache-Control:" -"max-age" -"no-cache" -"no-store" -"must-revalidate" -"\x0ACache-Control: max-age=3153600000" -"\x0ACache-Control: max-age=0" -"\x0ACache-Control: no-cache" -"\x0ACache-Control: no-store" -"\x0ACache-Control: must-revalidate" - -"Content-Disposition:" -"attachment" -"filename" - -"Content-Encoding:" -"gzip" -"deflate" -"sdch" -"br" -"\x0AContent-Encoding: gzip" -"\x0AContent-Encoding: deflate" -"\x0AContent-Encoding: sdch" -"\x0AContent-Encoding: br" - -"Date:" -"Fri, 01 Apr, 2050 14:14:14 GMT" -"Mon, 28 Mar, 2016 04:04:04 GMT" -"\x0ADate: Fri, 01 Apr, 2050 14:14:14 GMT" -"\x0ADate: Mon, 28 Mar, 2016 04:04:04 GMT" - -"Last-Modified:" -"\x0ALast-Modified: Fri, 01 Apr, 2050 14:14:14 GMT" -"\x0ALast-Modified: Mon, 28 Mar, 2016 04:04:04 GMT" - -"Expires:" -"\x0AExpires: Fri, 01 Apr, 2050 14:14:14 GMT" -"\x0AExpires: Mon, 28 Mar, 2016 04:04:04 GMT" - -"Set-Cookie:" -"Expires" -"Max-Age" -"Domain" -"Path" -"Secure" -"HttpOnly" -"Priority" -"Low" -"Medium" -"High" -"SameSite" -"Strict" -"Lax" -"\x0ASet-Cookie: foo=bar" -"\x0ASet-Cookie: foo2=bar2;HttpOnly;Priority=Low;SameSite=Strict;Path=/" -"\x0ASet-Cookie: foo=chicken;SameSite=Lax" - -"Strict-Transport-Security:" -"includeSubDomains" - -"Vary:" -"\x0AVary: Cookie" -"\x0AVary: Age" - -"ETag:" -"\x0AETag: jumboshrimp"
diff --git a/net/data/ssl/symantec/roots/8da084fcf99ce07722f89b3205939806fa5cb811e1c813f6a108c7d336b3408e.pem b/net/data/ssl/symantec/roots/8da084fcf99ce07722f89b3205939806fa5cb811e1c813f6a108c7d336b3408e.pem deleted file mode 100644 index 410007a..0000000 --- a/net/data/ssl/symantec/roots/8da084fcf99ce07722f89b3205939806fa5cb811e1c813f6a108c7d336b3408e.pem +++ /dev/null
@@ -1,90 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: - 4a:47:00:01:00:02:e5:a0:5d:d6:3f:00:51:bf - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Class 3 CA, CN=TC TrustCenter Class 3 CA II - Validity - Not Before: Jan 12 14:41:57 2006 GMT - Not After : Dec 31 22:59:59 2025 GMT - Subject: C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Class 3 CA, CN=TC TrustCenter Class 3 CA II - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:b4:e0:bb:51:bb:39:5c:8b:04:c5:4c:79:1c:23: - 86:31:10:63:43:55:27:3f:c6:45:c7:a4:3d:ec:09: - 0d:1a:1e:20:c2:56:1e:de:1b:37:07:30:22:2f:6f: - f1:06:f1:ab:ad:d6:c8:ab:61:a3:2f:43:c4:b0:b2: - 2d:fc:c3:96:69:7b:7e:8a:e4:cc:c0:39:12:90:42: - 60:c9:cc:35:68:ee:da:5f:90:56:5f:cd:1c:4d:5b: - 58:49:eb:0e:01:4f:64:fa:2c:3c:89:58:d8:2f:2e: - e2:b0:68:e9:22:3b:75:89:d6:44:1a:65:f2:1b:97: - 26:1d:28:6d:ac:e8:bd:59:1d:2b:24:f6:d6:84:03: - 66:88:24:00:78:60:f1:f8:ab:fe:02:b2:6b:fb:22: - fb:35:e6:16:d1:ad:f6:2e:12:e4:fa:35:6a:e5:19: - b9:5d:db:3b:1e:1a:fb:d3:ff:15:14:08:d8:09:6a: - ba:45:9d:14:79:60:7d:af:40:8a:07:73:b3:93:96: - d3:74:34:8d:3a:37:29:de:5c:ec:f5:ee:2e:31:c2: - 20:dc:be:f1:4f:7f:23:52:d9:5b:e2:64:d9:9c:aa: - 07:08:b5:45:bd:d1:d0:31:c1:ab:54:9f:a9:d2:c3: - 62:60:03:f1:bb:39:4a:92:4a:3d:0a:b9:9d:c5:a0: - fe:37 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: critical - CA:TRUE - X509v3 Key Usage: critical - Certificate Sign, CRL Sign - X509v3 Subject Key Identifier: - D4:A2:FC:9F:B3:C3:D8:03:D3:57:5C:07:A4:D0:24:A7:C0:F2:00:D4 - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.trustcenter.de/crl/v2/tc_class_3_ca_II.crl - URI:ldap://www.trustcenter.de/CN=TC%20TrustCenter%20Class%203%20CA%20II,O=TC%20TrustCenter%20GmbH,OU=rootcerts,DC=trustcenter,DC=de?certificateRevocationList?base? - - Signature Algorithm: sha1WithRSAEncryption - 36:60:e4:70:f7:06:20:43:d9:23:1a:42:f2:f8:a3:b2:b9:4d: - 8a:b4:f3:c2:9a:55:31:7c:c4:3b:67:9a:b4:df:4d:0e:8a:93: - 4a:17:8b:1b:8d:ca:89:e1:cf:3a:1e:ac:1d:f1:9c:32:b4:8e: - 59:76:a2:41:85:25:37:a0:13:d0:f5:7c:4e:d5:ea:96:e2:6e: - 72:c1:bb:2a:fe:6c:6e:f8:91:98:46:fc:c9:1b:57:5b:ea:c8: - 1a:3b:3f:b0:51:98:3c:07:da:2c:59:01:da:8b:44:e8:e1:74: - fd:a7:68:dd:54:ba:83:46:ec:c8:46:b5:f8:af:97:c0:3b:09: - 1c:8f:ce:72:96:3d:33:56:70:bc:96:cb:d8:d5:7d:20:9a:83: - 9f:1a:dc:39:f1:c5:72:a3:11:03:fd:3b:42:52:29:db:e8:01: - f7:9b:5e:8c:d6:8d:86:4e:19:fa:bc:1c:be:c5:21:a5:87:9e: - 78:2e:36:db:09:71:a3:72:34:f8:6c:e3:06:09:f2:5e:56:a5: - d3:dd:98:fa:d4:e6:06:f4:f0:b6:20:63:4b:ea:29:bd:aa:82: - 66:1e:fb:81:aa:a7:37:ad:13:18:e6:92:c3:81:c1:33:bb:88: - 1e:a1:e7:e2:b4:bd:31:6c:0e:51:3d:6f:fb:96:56:80:e2:36: - 17:d1:dc:e4 ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW -Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q -Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 -1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq -ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 -Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX -XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN -irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 -TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 -g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB -95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj -S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== ------END CERTIFICATE-----
diff --git a/net/data/ssl/symantec/roots/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pem b/net/data/ssl/symantec/roots/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pem new file mode 100644 index 0000000..c0d77069 --- /dev/null +++ b/net/data/ssl/symantec/roots/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pem
@@ -0,0 +1,82 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0f:6b:55:2f:9e:bf:90:7b:0f:66:29:a9:bd:f4:d8:ce + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Symantec Corporation, CN=Symantec Enterprise Mobile Root for Microsoft + Validity + Not Before: Mar 15 00:00:00 2012 GMT + Not After : Mar 14 23:59:59 2032 GMT + Subject: C=US, O=Symantec Corporation, CN=Symantec Enterprise Mobile Root for Microsoft + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b5:3d:b0:72:ee:91:e9:a5:69:9c:11:4d:7a:f9: + b3:fa:3d:f2:94:9b:23:b7:a6:03:ec:62:18:fc:85: + 12:22:fe:c1:71:7d:54:93:b9:91:7d:62:f6:ca:a8: + 38:15:65:f8:77:3d:e5:82:20:3a:d4:b5:d1:6e:8d: + 06:49:bd:df:82:0e:24:85:e7:ef:78:2d:18:f2:e0: + 0b:68:46:3e:24:10:c8:57:ee:0e:6d:71:a6:d3:b1: + 56:1c:d7:29:d5:b2:ea:54:05:0a:a8:3c:a1:b8:25: + 52:07:05:a0:df:e7:dc:ee:5c:3b:41:b5:ab:5c:33: + 32:d2:ce:eb:e9:96:f8:40:f4:0a:ba:33:1d:f8:56: + 03:09:82:f5:67:07:c4:c0:34:c1:5d:fc:45:bb:ea: + 3c:9a:d5:74:71:6d:d5:86:d3:c2:fc:85:bc:54:eb: + a3:d5:f2:4f:d5:45:af:57:bc:f0:22:c0:8f:a2:45: + c8:75:34:77:de:a1:6d:37:72:b3:73:8d:0c:6b:53: + ba:59:e1:a8:3e:80:57:d2:5f:59:ee:68:75:cf:81: + 9c:a3:ca:45:8c:37:db:05:72:34:1c:32:02:f8:d5: + f9:2c:0d:da:58:9e:c4:17:b4:9b:c9:90:c4:88:59: + 3f:71:91:90:44:18:be:22:8b:79:92:2e:42:b0:8b: + 97:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Alternative Name: + DirName:/CN=MPKI-2048-1-111 + X509v3 Subject Key Identifier: + 4D:EC:DF:26:06:DC:24:10:C0:B6:99:F4:D7:39:C7:6F:19:F8:26:28 + Signature Algorithm: sha256WithRSAEncryption + a9:57:59:d0:01:54:14:46:af:c7:79:54:0c:6a:2a:5b:d8:3a: + 1d:81:e4:88:a3:31:b4:f1:f3:35:f1:46:73:5c:43:c9:fe:bc: + a2:6a:19:c0:bd:2f:5f:cb:38:a3:6d:6e:e8:14:5e:f2:78:7e: + 45:7a:e1:bb:f4:2e:9b:45:eb:e0:1d:50:1c:34:5b:7f:98:8a: + 86:0f:87:da:e4:64:26:77:fc:09:df:23:41:4f:0e:9f:fa:0e: + fa:44:85:f0:29:97:a4:94:e2:f4:40:2d:91:1c:76:f4:a8:60: + de:71:a6:b0:05:e2:4f:69:d9:19:0b:89:3a:e0:fa:ab:2b:fa: + f1:b3:32:ed:fc:7c:70:65:5e:d0:7b:11:7b:9d:e8:5b:1a:4a: + 76:a4:7b:51:39:ac:7d:a9:0c:74:38:e8:bb:55:df:c4:ce:c0: + a7:21:5a:b8:1b:9f:01:c5:a7:10:fe:7d:f9:6a:08:99:01:d1: + f6:35:50:38:e4:f6:43:e4:18:d8:80:4c:ec:c7:04:e2:61:8c: + 7d:49:ed:cf:b4:a5:f1:f2:90:92:09:08:35:73:a0:23:32:ca: + e9:9c:9e:1c:be:0b:07:2c:77:5e:17:4c:da:9c:82:e1:80:1b: + a5:f3:da:f7:88:bf:bf:39:27:f8:24:fe:b1:4b:c8:97:ed:e4: + 12:14:25:88 +-----BEGIN CERTIFICATE----- +MIIDvTCCAqWgAwIBAgIQD2tVL56/kHsPZimpvfTYzjANBgkqhkiG9w0BAQsFADBk +MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xNjA0 +BgNVBAMTLVN5bWFudGVjIEVudGVycHJpc2UgTW9iaWxlIFJvb3QgZm9yIE1pY3Jv +c29mdDAeFw0xMjAzMTUwMDAwMDBaFw0zMjAzMTQyMzU5NTlaMGQxCzAJBgNVBAYT +AlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjE2MDQGA1UEAxMtU3lt +YW50ZWMgRW50ZXJwcmlzZSBNb2JpbGUgUm9vdCBmb3IgTWljcm9zb2Z0MIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtT2wcu6R6aVpnBFNevmz+j3ylJsj +t6YD7GIY/IUSIv7BcX1Uk7mRfWL2yqg4FWX4dz3lgiA61LXRbo0GSb3fgg4khefv +eC0Y8uALaEY+JBDIV+4ObXGm07FWHNcp1bLqVAUKqDyhuCVSBwWg3+fc7lw7QbWr +XDMy0s7r6Zb4QPQKujMd+FYDCYL1ZwfEwDTBXfxFu+o8mtV0cW3VhtPC/IW8VOuj +1fJP1UWvV7zwIsCPokXIdTR33qFtN3Kzc40Ma1O6WeGoPoBX0l9Z7mh1z4Gco8pF +jDfbBXI0HDIC+NX5LA3aWJ7EF7SbyZDEiFk/cZGQRBi+Iot5ki5CsIuXWwIDAQAB +o2swaTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAnBgNVHREEIDAe +pBwwGjEYMBYGA1UEAxMPTVBLSS0yMDQ4LTEtMTExMB0GA1UdDgQWBBRN7N8mBtwk +EMC2mfTXOcdvGfgmKDANBgkqhkiG9w0BAQsFAAOCAQEAqVdZ0AFUFEavx3lUDGoq +W9g6HYHkiKMxtPHzNfFGc1xDyf68omoZwL0vX8s4o21u6BRe8nh+RXrhu/Qum0Xr +4B1QHDRbf5iKhg+H2uRkJnf8Cd8jQU8On/oO+kSF8CmXpJTi9EAtkRx29Khg3nGm +sAXiT2nZGQuJOuD6qyv68bMy7fx8cGVe0HsRe53oWxpKdqR7UTmsfakMdDjou1Xf +xM7ApyFauBufAcWnEP59+WoImQHR9jVQOOT2Q+QY2IBM7McE4mGMfUntz7Sl8fKQ +kgkINXOgIzLK6ZyeHL4LByx3XhdM2pyC4YAbpfPa94i/vzkn+CT+sUvIl+3kEhQl +iA== +-----END CERTIFICATE-----
diff --git a/net/data/verify_certificate_chain_unittest/generate-key-rollover.py b/net/data/verify_certificate_chain_unittest/generate-key-rollover.py new file mode 100755 index 0000000..e06b4522 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/generate-key-rollover.py
@@ -0,0 +1,92 @@ +#!/usr/bin/python +# Copyright (c) 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""A certificate tree with two self-signed root certificates(oldroot, newroot), +and a third root certificate (newrootrollover) which has the same key as newroot +but is signed by oldroot, all with the same subject and issuer. +There are two intermediates with the same key, subject and issuer +(oldintermediate signed by oldroot, and newintermediate signed by newroot). +The target certificate is signed by the intermediate key. + + +In graphical form: + + oldroot-------->newrootrollover newroot + | | | + v v v +oldintermediate newintermediate + | | + +------------+-------------+ + | + v + target + + +Several chains are output: + key-rollover-oldchain.pem: + target<-oldintermediate<-oldroot + key-rollover-rolloverchain.pem: + target<-newintermediate<-newrootrollover<-oldroot + key-rollover-longrolloverchain.pem: + target<-newintermediate<-newroot<-newrootrollover<-oldroot + key-rollover-newchain.pem: + target<-newintermediate<-newroot + +All of these chains should verify successfully. +""" + +import common + +# The new certs should have a newer notbefore date than "old" certs. This should +# affect path builder sorting, but otherwise won't matter. +JANUARY_2_2015_UTC = '150102120000Z' + +# Self-signed root certificates. Same name, different keys. +oldroot = common.create_self_signed_root_certificate('Root') +oldroot.set_validity_range(common.JANUARY_1_2015_UTC, common.JANUARY_1_2016_UTC) +newroot = common.create_self_signed_root_certificate('Root') +newroot.set_validity_range(JANUARY_2_2015_UTC, common.JANUARY_1_2016_UTC) +# Root with the new key signed by the old key. +newrootrollover = common.create_intermediary_certificate('Root', oldroot) +newrootrollover.set_key_path(newroot.get_key_path()) +newrootrollover.set_validity_range(JANUARY_2_2015_UTC, + common.JANUARY_1_2016_UTC) + +# Intermediate signed by oldroot. +oldintermediate = common.create_intermediary_certificate('Intermediate', + oldroot) +oldintermediate.set_validity_range(common.JANUARY_1_2015_UTC, + common.JANUARY_1_2016_UTC) +# Intermediate signed by newroot. Same key as oldintermediate. +newintermediate = common.create_intermediary_certificate('Intermediate', + newroot) +newintermediate.set_key_path(oldintermediate.get_key_path()) +newintermediate.set_validity_range(JANUARY_2_2015_UTC, + common.JANUARY_1_2016_UTC) + +# Target certificate. +target = common.create_end_entity_certificate('Target', oldintermediate) + +oldchain = [target, oldintermediate] +rolloverchain = [target, newintermediate, newrootrollover] +longrolloverchain = [target, newintermediate, newroot, newrootrollover] +oldtrusted = [oldroot] + +newchain = [target, newintermediate] +newtrusted = [newroot] + +time = common.DEFAULT_TIME +verify_result = True + +common.write_test_file(__doc__, oldchain, oldtrusted, time, verify_result, + out_pem="key-rollover-oldchain.pem") +common.write_test_file(__doc__, rolloverchain, oldtrusted, time, verify_result, + out_pem="key-rollover-rolloverchain.pem") +common.write_test_file(__doc__, longrolloverchain, oldtrusted, time, + verify_result, + out_pem="key-rollover-longrolloverchain.pem") +common.write_test_file(__doc__, newchain, newtrusted, time, verify_result, + out_pem="key-rollover-newchain.pem") +
diff --git a/net/data/verify_certificate_chain_unittest/key-rollover-longrolloverchain.pem b/net/data/verify_certificate_chain_unittest/key-rollover-longrolloverchain.pem new file mode 100644 index 0000000..fcd63fa --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/key-rollover-longrolloverchain.pem
@@ -0,0 +1,489 @@ +[Created by: ./generate-key-rollover.py] + +A certificate tree with two self-signed root certificates(oldroot, newroot), +and a third root certificate (newrootrollover) which has the same key as newroot +but is signed by oldroot, all with the same subject and issuer. +There are two intermediates with the same key, subject and issuer +(oldintermediate signed by oldroot, and newintermediate signed by newroot). +The target certificate is signed by the intermediate key. + + +In graphical form: + + oldroot-------->newrootrollover newroot + | | | + v v v +oldintermediate newintermediate + | | + +------------+-------------+ + | + v + target + + +Several chains are output: + key-rollover-oldchain.pem: + target<-oldintermediate<-oldroot + key-rollover-rolloverchain.pem: + target<-newintermediate<-newrootrollover<-oldroot + key-rollover-longrolloverchain.pem: + target<-newintermediate<-newroot<-newrootrollover<-oldroot + key-rollover-newchain.pem: + target<-newintermediate<-newroot + +All of these chains should verify successfully. + + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Intermediate + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Target + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:12:1c:48:e4:73:1f:5c:d2:54:a9:7b:58:1c: + 37:73:c2:49:26:3e:ed:b5:6b:55:17:c9:4c:52:34: + ce:d9:76:86:32:74:74:ae:11:b2:99:1b:51:a0:33: + 48:34:2f:b9:d3:2b:06:c2:5c:29:53:35:ce:7c:a6: + 67:b2:6a:d4:33:c3:13:62:30:a1:53:5f:45:78:5b: + bb:47:ad:07:a4:98:9a:e9:e3:b1:3b:e6:33:c2:c1: + 5c:95:d7:c8:b9:a6:72:27:7a:79:da:c4:c8:5a:1a: + 3e:5e:5e:a6:62:64:c6:72:86:b1:78:98:5b:63:27: + 70:15:04:6b:b1:0f:11:9c:4d:3b:5c:e7:8d:c0:be: + d5:84:46:6c:bd:11:1e:21:c1:82:9c:d0:aa:2d:2f: + f8:2a:e9:3b:e4:35:15:6d:c7:4a:dd:a8:65:69:b8: + 16:a1:8a:04:a2:44:68:40:b6:99:ae:61:df:9f:6c: + 40:ef:79:c9:a3:6d:e4:2d:07:01:68:f1:21:4e:0e: + 28:a7:fd:2f:ad:ee:7d:65:cf:36:fd:4f:1b:ba:10: + 8e:86:fd:ec:37:67:0c:20:71:66:48:64:f3:82:af: + f5:e1:73:c9:09:36:03:3f:c2:47:7a:f2:33:b9:f9: + 9f:53:9b:24:5e:c3:cc:05:d9:a9:ed:d7:b2:2a:c5: + b7:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C9:45:0B:2A:F2:D8:8D:2A:D7:CE:AF:56:BF:82:B0:84:0C:C8:2E:F4 + X509v3 Authority Key Identifier: + keyid:B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Intermediate.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Intermediate.crl + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: sha256WithRSAEncryption + 63:66:9e:6c:34:8c:5d:74:ae:90:25:55:ae:86:49:b9:3d:fd: + 27:bc:4f:69:7b:70:cb:25:0e:a3:8c:7a:7d:9c:4f:0b:7c:f2: + 85:a5:ea:82:d2:37:c2:74:a2:ae:a8:bf:62:f4:5f:d4:c6:41: + 45:0c:cc:27:53:aa:8f:66:58:e9:b0:de:ae:98:14:bd:92:df: + 9b:0f:f2:c5:3b:d2:bc:1c:3e:80:b4:09:0f:c1:9f:d6:3a:29: + 52:71:b6:1a:92:95:5a:18:dc:b4:30:dc:61:61:93:54:d1:55: + 83:92:5d:c0:c7:dc:ab:d7:08:dd:8a:44:cf:92:f9:4d:86:25: + aa:ac:52:f6:0e:17:99:0b:31:d2:75:5e:33:f9:f5:b6:77:42: + 07:62:a9:53:cc:f3:79:84:57:d9:14:3f:ab:4c:8b:ae:c7:9f: + cf:7a:1f:bf:7e:1d:44:bd:76:b4:cd:8d:c8:1d:75:f7:3b:b5: + bc:35:8b:3f:29:b1:cb:67:a4:17:af:a4:ca:9f:2b:e7:15:66: + e4:c8:c1:7c:08:78:9e:5d:4b:c3:c6:58:66:96:42:e8:e6:40: + fd:dc:24:ce:3b:58:11:38:40:0e:fc:a9:c0:2c:0f:e5:cc:bb: + 02:32:31:b9:bc:6f:2d:1d:f6:2b:7c:d3:f8:24:f6:60:38:8a: + 1f:dd:e1:50 +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxJbnRl +cm1lZGlhdGUwHhcNMTUwMTAxMTIwMDAwWhcNMTYwMTAxMTIwMDAwWjARMQ8wDQYD +VQQDDAZUYXJnZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+EhxI +5HMfXNJUqXtYHDdzwkkmPu21a1UXyUxSNM7ZdoYydHSuEbKZG1GgM0g0L7nTKwbC +XClTNc58pmeyatQzwxNiMKFTX0V4W7tHrQekmJrp47E75jPCwVyV18i5pnInenna +xMhaGj5eXqZiZMZyhrF4mFtjJ3AVBGuxDxGcTTtc543AvtWERmy9ER4hwYKc0Kot +L/gq6TvkNRVtx0rdqGVpuBahigSiRGhAtpmuYd+fbEDvecmjbeQtBwFo8SFODiin +/S+t7n1lzzb9Txu6EI6G/ew3ZwwgcWZIZPOCr/Xhc8kJNgM/wkd68jO5+Z9TmyRe +w8wF2ant17Iqxbc5AgMBAAGjgekwgeYwHQYDVR0OBBYEFMlFCyry2I0q186vVr+C +sIQMyC70MB8GA1UdIwQYMBaAFLE5eRM10ANr6cRjK8zWYcOC7BTBMD8GCCsGAQUF +BwEBBDMwMTAvBggrBgEFBQcwAoYjaHR0cDovL3VybC1mb3ItYWlhL0ludGVybWVk +aWF0ZS5jZXIwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL3VybC1mb3ItY3JsL0lu +dGVybWVkaWF0ZS5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF +BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAY2aebDSMXXSukCVVroZJ +uT39J7xPaXtwyyUOo4x6fZxPC3zyhaXqgtI3wnSirqi/YvRf1MZBRQzMJ1Oqj2ZY +6bDerpgUvZLfmw/yxTvSvBw+gLQJD8Gf1jopUnG2GpKVWhjctDDcYWGTVNFVg5Jd +wMfcq9cI3YpEz5L5TYYlqqxS9g4XmQsx0nVeM/n1tndCB2KpU8zzeYRX2RQ/q0yL +rsefz3ofv34dRL12tM2NyB119zu1vDWLPymxy2ekF6+kyp8r5xVm5MjBfAh4nl1L +w8ZYZpZC6OZA/dwkzjtYEThADvypwCwP5cy7AjIxubxvLR32K3zT+CT2YDiKH93h +UA== +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Intermediate + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:d0:2e:3b:06:d6:ea:65:bd:dd:b2:d3:e8:88: + ea:08:73:01:42:ac:ca:38:28:17:32:93:5e:16:a8: + c1:79:44:9a:db:24:08:ba:81:52:63:9c:b4:ed:57: + d4:b2:ac:54:64:3b:70:39:7e:37:da:11:e1:8c:ba: + 09:bc:1a:9b:e7:fe:6d:75:f8:71:31:f0:ca:52:89: + 2a:9e:d5:53:db:b8:c0:76:cf:bf:58:58:e1:bb:81: + de:62:bb:06:58:1f:9b:64:03:75:7d:ee:76:6f:39: + 47:cb:8e:34:32:07:83:89:b0:83:2a:78:d0:ac:e2: + 86:0a:a8:ab:3b:97:81:de:9d:36:b4:03:b7:d5:06: + 05:53:d7:80:03:44:86:53:72:db:7a:5f:c5:20:dd: + c7:44:58:3b:40:7f:0e:39:bc:be:0d:ca:6a:f6:82: + a2:97:a2:17:79:51:6f:42:5d:0d:6a:b7:a0:de:5f: + 6a:00:be:e7:5a:b7:91:e9:fc:77:fd:75:88:8d:52: + 76:3d:0e:91:4b:c7:db:96:a4:5f:39:59:55:62:65: + 3b:15:7a:bc:7b:09:9f:3e:75:d9:9e:c5:00:b3:19: + d4:26:7e:eb:db:62:07:c2:f5:b6:4e:87:2d:eb:56: + 8b:5a:68:6c:85:2f:b4:3e:1d:dd:5d:31:49:98:8b: + 06:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + X509v3 Authority Key Identifier: + keyid:15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + a8:ad:48:d8:6e:1d:24:09:d2:b3:29:3c:48:60:27:7f:37:64: + d5:f1:3b:b3:5c:43:de:7c:b4:5f:ee:3a:f2:1a:25:24:0a:8a: + 25:6d:19:5b:dc:0c:4e:48:61:2f:60:d3:6b:f3:9c:03:2c:d3: + fa:c8:9b:99:e7:2e:c5:43:c0:5f:14:cd:8b:92:62:4f:e5:3a: + cd:b5:0a:d8:b2:01:c7:44:b4:3a:86:66:bf:fa:11:a5:f8:24: + 3f:d1:1a:e8:eb:1e:ad:f0:70:31:6f:bc:21:cf:db:ce:63:4e: + 84:e9:52:9e:bb:1b:c4:72:ae:e0:6c:88:9e:99:dc:79:d9:fd: + 83:26:8e:f6:19:70:d9:5e:fc:f4:0c:d1:17:6f:af:10:f6:64: + 16:08:d8:72:ba:3a:2d:66:28:5a:41:0d:f3:47:87:a7:9c:78: + c6:cd:5e:25:71:0b:f2:93:b8:26:17:b2:19:17:cc:03:ed:c0: + 6e:06:e2:4b:4a:57:5f:23:02:2a:69:06:7a:c4:b7:3e:2f:e8: + f0:03:ae:b8:2d:df:63:22:20:73:23:75:d9:3c:d7:22:e4:b4: + 65:65:ed:b9:e6:02:1d:b5:51:11:9c:db:92:e4:fe:8c:1d:bb: + c5:95:87:5b:38:ee:ff:e4:01:d1:5d:84:b9:73:d3:da:23:ca: + 5e:05:d3:7d +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowFzEVMBMGA1UEAwwMSW50 +ZXJtZWRpYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNAuOwbW +6mW93bLT6IjqCHMBQqzKOCgXMpNeFqjBeUSa2yQIuoFSY5y07VfUsqxUZDtwOX43 +2hHhjLoJvBqb5/5tdfhxMfDKUokqntVT27jAds+/WFjhu4HeYrsGWB+bZAN1fe52 +bzlHy440MgeDibCDKnjQrOKGCqirO5eB3p02tAO31QYFU9eAA0SGU3Lbel/FIN3H +RFg7QH8OOby+Dcpq9oKil6IXeVFvQl0Nareg3l9qAL7nWreR6fx3/XWIjVJ2PQ6R +S8fblqRfOVlVYmU7FXq8ewmfPnXZnsUAsxnUJn7r22IHwvW2Toct61aLWmhshS+0 +Ph3dXTFJmIsGVQIDAQABo4HLMIHIMB0GA1UdDgQWBBSxOXkTNdADa+nEYyvM1mHD +guwUwTAfBgNVHSMEGDAWgBQVnqat9Z+KocEImb9mb8/Kcs0MNDA3BggrBgEFBQcB +AQQrMCkwJwYIKwYBBQUHMAKGG2h0dHA6Ly91cmwtZm9yLWFpYS9Sb290LmNlcjAs +BgNVHR8EJTAjMCGgH6AdhhtodHRwOi8vdXJsLWZvci1jcmwvUm9vdC5jcmwwDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AKitSNhuHSQJ0rMpPEhgJ383ZNXxO7NcQ958tF/uOvIaJSQKiiVtGVvcDE5IYS9g +02vznAMs0/rIm5nnLsVDwF8UzYuSYk/lOs21CtiyAcdEtDqGZr/6EaX4JD/RGujr +Hq3wcDFvvCHP285jToTpUp67G8RyruBsiJ6Z3HnZ/YMmjvYZcNle/PQM0RdvrxD2 +ZBYI2HK6Oi1mKFpBDfNHh6eceMbNXiVxC/KTuCYXshkXzAPtwG4G4ktKV18jAipp +BnrEtz4v6PADrrgt32MiIHMjddk81yLktGVl7bnmAh21URGc25Lk/owdu8WVh1s4 +7v/kAdFdhLlz09ojyl4F030= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ae:ea:3b:3f:b6:e9:3d:ea:eb:3d:dd:e8:4d:45: + 83:63:78:ea:07:90:3a:3c:4f:92:54:2b:2d:02:1b: + eb:9e:81:72:68:2e:73:f8:4a:a1:de:0c:d6:f0:c2: + 61:26:90:0b:48:59:ab:23:25:8f:e4:4a:6b:c9:2d: + ba:a7:35:c4:22:df:76:99:d8:7b:f7:6d:ca:9b:da: + d2:ed:7e:c8:93:b2:a7:f6:f0:05:6a:5d:c6:e1:79: + d0:25:59:a9:50:1e:65:eb:1c:c9:cd:4e:6a:3a:2a: + a4:1a:fa:81:a3:e7:ae:d7:de:43:d9:e8:0b:5c:b0: + 6b:46:39:c5:9c:4a:6d:59:bf:da:70:2e:80:ac:c8: + 80:e3:83:d1:71:7b:a7:0b:92:bf:a8:81:ad:5c:b2: + d5:e9:b9:5f:b5:4f:93:43:67:72:36:b3:f7:17:b9: + 1b:da:2a:13:83:70:36:ae:59:03:3d:f0:71:de:a2: + 7a:41:ad:b5:e9:a2:51:e4:18:ec:88:ad:48:f1:df: + 17:04:43:54:2a:af:3c:c0:f5:84:39:43:d1:a7:d2: + 52:0f:3c:dd:ef:13:58:8c:1d:d4:dd:2e:6d:1a:e7: + 73:9b:8b:f3:41:7b:9a:53:4e:0d:92:d3:5d:3f:fc: + c3:61:dc:5f:a0:93:3c:08:cc:b4:9b:ce:9d:78:e3: + 77:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + X509v3 Authority Key Identifier: + keyid:15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 58:4b:60:7e:0b:c2:3d:20:f3:49:34:91:55:d3:5f:5b:ce:81: + 31:da:71:9f:72:d7:f4:cc:be:cf:58:b8:97:aa:99:87:3d:34: + 12:ac:40:1c:8e:02:46:83:ee:04:e1:7e:5e:57:ca:a4:ae:e1: + d0:b4:12:e9:65:33:f5:4e:c4:f6:49:00:7f:83:6d:75:67:84: + b2:db:52:5a:a2:3e:5d:2d:5c:f3:45:fe:6a:d3:c4:0a:76:52: + c6:9b:b0:89:01:b9:b6:be:30:60:d9:b4:2e:1d:1e:bf:ef:d8: + 12:90:9f:cb:67:29:20:61:9f:1a:67:64:88:4c:43:ec:10:7d: + 87:11:00:44:6a:ce:37:af:73:f4:fa:d2:22:2f:24:3a:6f:79: + 09:6c:8d:de:b5:71:0e:6e:b7:64:a9:be:73:a8:c1:c8:50:74: + d2:c4:2b:ef:4f:25:20:8f:41:f0:1f:6e:52:77:eb:a0:1a:94: + 87:7c:35:11:37:5c:33:f5:83:47:e0:f2:0e:97:af:23:61:23: + 25:0b:92:6c:3b:30:a1:aa:c6:dc:4a:05:6e:43:76:58:82:66: + cd:f6:d6:ef:9b:80:36:d6:95:b7:d1:ec:5c:53:f7:78:84:ef: + 48:6a:2c:f7:93:97:f2:7a:ce:ec:f3:eb:63:e1:5a:e0:69:02: + 5d:34:36:93 +-----BEGIN CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7qOz+26T3q6z3d6E1F +g2N46geQOjxPklQrLQIb656Bcmguc/hKod4M1vDCYSaQC0hZqyMlj+RKa8ktuqc1 +xCLfdpnYe/dtypva0u1+yJOyp/bwBWpdxuF50CVZqVAeZescyc1OajoqpBr6gaPn +rtfeQ9noC1ywa0Y5xZxKbVm/2nAugKzIgOOD0XF7pwuSv6iBrVyy1em5X7VPk0Nn +cjaz9xe5G9oqE4NwNq5ZAz3wcd6iekGttemiUeQY7IitSPHfFwRDVCqvPMD1hDlD +0afSUg883e8TWIwd1N0ubRrnc5uL80F7mlNODZLTXT/8w2HcX6CTPAjMtJvOnXjj +d8kCAwEAAaOByzCByDAdBgNVHQ4EFgQUFZ6mrfWfiqHBCJm/Zm/PynLNDDQwHwYD +VR0jBBgwFoAUFZ6mrfWfiqHBCJm/Zm/PynLNDDQwNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBYS2B+C8I9 +IPNJNJFV019bzoEx2nGfctf0zL7PWLiXqpmHPTQSrEAcjgJGg+4E4X5eV8qkruHQ +tBLpZTP1TsT2SQB/g211Z4Sy21Jaoj5dLVzzRf5q08QKdlLGm7CJAbm2vjBg2bQu +HR6/79gSkJ/LZykgYZ8aZ2SITEPsEH2HEQBEas43r3P0+tIiLyQ6b3kJbI3etXEO +brdkqb5zqMHIUHTSxCvvTyUgj0HwH25Sd+ugGpSHfDURN1wz9YNH4PIOl68jYSMl +C5JsOzChqsbcSgVuQ3ZYgmbN9tbvm4A21pW30excU/d4hO9Iaiz3k5fyes7s8+tj +4VrgaQJdNDaT +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ae:ea:3b:3f:b6:e9:3d:ea:eb:3d:dd:e8:4d:45: + 83:63:78:ea:07:90:3a:3c:4f:92:54:2b:2d:02:1b: + eb:9e:81:72:68:2e:73:f8:4a:a1:de:0c:d6:f0:c2: + 61:26:90:0b:48:59:ab:23:25:8f:e4:4a:6b:c9:2d: + ba:a7:35:c4:22:df:76:99:d8:7b:f7:6d:ca:9b:da: + d2:ed:7e:c8:93:b2:a7:f6:f0:05:6a:5d:c6:e1:79: + d0:25:59:a9:50:1e:65:eb:1c:c9:cd:4e:6a:3a:2a: + a4:1a:fa:81:a3:e7:ae:d7:de:43:d9:e8:0b:5c:b0: + 6b:46:39:c5:9c:4a:6d:59:bf:da:70:2e:80:ac:c8: + 80:e3:83:d1:71:7b:a7:0b:92:bf:a8:81:ad:5c:b2: + d5:e9:b9:5f:b5:4f:93:43:67:72:36:b3:f7:17:b9: + 1b:da:2a:13:83:70:36:ae:59:03:3d:f0:71:de:a2: + 7a:41:ad:b5:e9:a2:51:e4:18:ec:88:ad:48:f1:df: + 17:04:43:54:2a:af:3c:c0:f5:84:39:43:d1:a7:d2: + 52:0f:3c:dd:ef:13:58:8c:1d:d4:dd:2e:6d:1a:e7: + 73:9b:8b:f3:41:7b:9a:53:4e:0d:92:d3:5d:3f:fc: + c3:61:dc:5f:a0:93:3c:08:cc:b4:9b:ce:9d:78:e3: + 77:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + X509v3 Authority Key Identifier: + keyid:02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 51:9b:dd:56:f2:b1:2b:e5:36:c8:2f:1d:a9:53:1f:89:e1:24: + 33:bd:ac:56:c1:c3:1a:38:a6:7e:fc:61:9a:ae:7c:1f:13:3e: + 37:e4:e6:a9:11:9e:2b:6e:ce:dd:12:0c:c1:b2:b7:eb:48:0e: + c7:a5:65:f0:86:49:8a:dc:cf:1b:6d:33:af:af:96:51:49:01: + e4:82:d6:e6:5a:d0:41:c7:05:9f:16:eb:06:bd:bc:ab:fe:a0: + d7:ac:de:62:d1:71:7e:69:82:31:03:e3:60:28:e6:18:3b:e5: + 93:2b:58:ee:d5:0b:7b:b6:af:f2:4f:22:eb:4d:b7:a6:74:68: + b7:82:68:7f:a9:b6:ee:a0:20:d7:c6:16:0e:9c:1c:39:ea:24: + 5e:60:12:fc:39:60:0d:54:3e:aa:b3:43:e1:0f:ef:d7:8f:3e: + 09:a9:55:95:e9:3d:0c:4f:ad:cb:c2:f3:2c:10:43:67:54:f9: + 66:54:81:ff:62:61:94:05:b0:42:af:f0:c5:ac:00:91:28:5c: + aa:a3:61:44:ba:c2:a6:ab:f8:1d:7e:02:69:33:48:fe:ac:93: + 7f:4c:99:91:d9:18:37:f9:70:3f:56:2a:ee:4a:e0:4d:f3:60: + 12:5d:30:d8:37:bf:ca:40:85:29:0c:a7:8f:ab:ad:03:6d:7b: + ba:62:7f:58 +-----BEGIN CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7qOz+26T3q6z3d6E1F +g2N46geQOjxPklQrLQIb656Bcmguc/hKod4M1vDCYSaQC0hZqyMlj+RKa8ktuqc1 +xCLfdpnYe/dtypva0u1+yJOyp/bwBWpdxuF50CVZqVAeZescyc1OajoqpBr6gaPn +rtfeQ9noC1ywa0Y5xZxKbVm/2nAugKzIgOOD0XF7pwuSv6iBrVyy1em5X7VPk0Nn +cjaz9xe5G9oqE4NwNq5ZAz3wcd6iekGttemiUeQY7IitSPHfFwRDVCqvPMD1hDlD +0afSUg883e8TWIwd1N0ubRrnc5uL80F7mlNODZLTXT/8w2HcX6CTPAjMtJvOnXjj +d8kCAwEAAaOByzCByDAdBgNVHQ4EFgQUFZ6mrfWfiqHBCJm/Zm/PynLNDDQwHwYD +VR0jBBgwFoAUAs72rBo5HoXoctGKxh3oeo+dFWswNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBRm91W8rEr +5TbILx2pUx+J4SQzvaxWwcMaOKZ+/GGarnwfEz435OapEZ4rbs7dEgzBsrfrSA7H +pWXwhkmK3M8bbTOvr5ZRSQHkgtbmWtBBxwWfFusGvbyr/qDXrN5i0XF+aYIxA+Ng +KOYYO+WTK1ju1Qt7tq/yTyLrTbemdGi3gmh/qbbuoCDXxhYOnBw56iReYBL8OWAN +VD6qs0PhD+/Xjz4JqVWV6T0MT63LwvMsEENnVPlmVIH/YmGUBbBCr/DFrACRKFyq +o2FEusKmq/gdfgJpM0j+rJN/TJmR2Rg3+XA/ViruSuBN82ASXTDYN7/KQIUpDKeP +q60DbXu6Yn9Y +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a6:44:ec:a7:15:00:1f:89:ac:91:f8:ec:7b:03: + 46:0b:53:15:ed:23:40:35:94:f3:96:80:27:d3:4a: + 84:92:68:c9:0c:e0:14:32:c7:31:67:49:29:58:77: + ea:ce:8a:72:5b:93:b1:a0:a8:e5:84:c6:52:9d:5a: + c0:41:bf:98:5f:18:5d:aa:d1:65:79:fb:e9:b0:84: + 92:9d:2c:58:bc:f1:c4:29:59:ed:bc:ac:85:ce:d7: + 0e:aa:08:e8:2d:90:25:cb:91:9d:7d:91:74:42:a0: + ae:77:d2:11:7b:57:49:04:24:c0:94:f4:20:54:60: + d9:1b:76:76:0b:2c:23:3c:67:90:8c:06:ed:4e:df: + ac:24:22:26:f7:26:8f:5a:d2:5b:79:8a:6f:6e:53: + 27:60:10:cb:c7:b4:9f:60:2d:8f:32:69:4b:01:d1: + f0:6d:69:1a:22:14:06:66:63:97:e8:fc:79:41:8d: + 15:44:44:d1:43:2a:37:5e:77:e4:06:e6:a9:85:13: + e9:24:63:9d:09:d0:f5:13:d5:ba:59:2e:1c:d2:70: + 06:b1:80:f7:57:d7:30:f7:14:f3:18:06:7f:84:38: + b6:81:46:9f:a2:36:87:0e:5f:1a:45:38:b7:20:16: + b7:c6:e1:91:3b:0e:0c:ab:b7:4e:3d:a4:6d:66:d8: + 85:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + X509v3 Authority Key Identifier: + keyid:02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 0e:00:56:5c:72:31:88:bd:95:13:f7:64:96:1c:63:c2:1c:11: + 60:04:d2:c3:5f:7c:a2:d7:d1:33:6d:51:6b:77:61:78:a8:70: + 2e:50:97:5d:c1:e8:9b:dd:c6:61:a7:d3:e1:2c:83:07:85:5c: + c9:d7:1e:22:c2:5f:76:83:19:d7:de:4a:5e:82:0f:43:80:45: + 02:d7:d0:3d:ca:c3:c0:fc:04:c8:f6:89:32:d7:47:c6:bf:1f: + c6:bd:71:e1:07:00:90:12:ec:61:63:1b:6c:e9:58:2c:fc:4c: + a9:8f:58:e1:b1:6e:a5:ca:4d:be:7e:32:16:74:5f:fd:35:e4: + 37:aa:1a:c5:33:21:20:8a:3e:1c:af:da:f3:c7:a2:22:d3:93: + 6c:5e:ac:0a:65:d5:db:e4:8b:11:5e:ca:eb:8f:da:c4:5d:2f: + 7a:98:e8:3c:d1:89:15:05:02:86:ef:eb:17:18:81:28:ca:d6: + 58:87:bd:d4:e2:50:41:92:d9:7f:b1:f7:53:8f:f3:cc:f3:1e: + 1d:e4:5a:c2:60:1b:17:42:78:53:e9:2d:5d:bb:f9:21:50:ff: + 87:53:be:5f:e6:d4:8f:25:7f:d7:83:d7:f8:4d:c1:7c:7a:40: + 0b:11:f1:d9:c6:eb:97:45:00:d6:6b:84:1c:4f:fc:8e:1f:5b: + b5:3d:60:0c +-----BEGIN TRUSTED_CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKZE7KcVAB+JrJH47HsD +RgtTFe0jQDWU85aAJ9NKhJJoyQzgFDLHMWdJKVh36s6KcluTsaCo5YTGUp1awEG/ +mF8YXarRZXn76bCEkp0sWLzxxClZ7byshc7XDqoI6C2QJcuRnX2RdEKgrnfSEXtX +SQQkwJT0IFRg2Rt2dgssIzxnkIwG7U7frCQiJvcmj1rSW3mKb25TJ2AQy8e0n2At +jzJpSwHR8G1pGiIUBmZjl+j8eUGNFURE0UMqN1535AbmqYUT6SRjnQnQ9RPVulku +HNJwBrGA91fXMPcU8xgGf4Q4toFGn6I2hw5fGkU4tyAWt8bhkTsODKu3Tj2kbWbY +hfsCAwEAAaOByzCByDAdBgNVHQ4EFgQUAs72rBo5HoXoctGKxh3oeo+dFWswHwYD +VR0jBBgwFoAUAs72rBo5HoXoctGKxh3oeo+dFWswNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAOAFZccjGI +vZUT92SWHGPCHBFgBNLDX3yi19EzbVFrd2F4qHAuUJddweib3cZhp9PhLIMHhVzJ +1x4iwl92gxnX3kpegg9DgEUC19A9ysPA/ATI9oky10fGvx/GvXHhBwCQEuxhYxts +6Vgs/Eypj1jhsW6lyk2+fjIWdF/9NeQ3qhrFMyEgij4cr9rzx6Ii05NsXqwKZdXb +5IsRXsrrj9rEXS96mOg80YkVBQKG7+sXGIEoytZYh73U4lBBktl/sfdTj/PM8x4d +5FrCYBsXQnhT6S1du/khUP+HU75f5tSPJX/Xg9f4TcF8ekALEfHZxuuXRQDWa4Qc +T/yOH1u1PWAM +-----END TRUSTED_CERTIFICATE----- + +-----BEGIN TIME----- +MTUwMzAyMTIwMDAwWg== +-----END TIME----- + +-----BEGIN VERIFY_RESULT----- +U1VDQ0VTUw== +-----END VERIFY_RESULT-----
diff --git a/net/data/verify_certificate_chain_unittest/key-rollover-newchain.pem b/net/data/verify_certificate_chain_unittest/key-rollover-newchain.pem new file mode 100644 index 0000000..97d56749 --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/key-rollover-newchain.pem
@@ -0,0 +1,311 @@ +[Created by: ./generate-key-rollover.py] + +A certificate tree with two self-signed root certificates(oldroot, newroot), +and a third root certificate (newrootrollover) which has the same key as newroot +but is signed by oldroot, all with the same subject and issuer. +There are two intermediates with the same key, subject and issuer +(oldintermediate signed by oldroot, and newintermediate signed by newroot). +The target certificate is signed by the intermediate key. + + +In graphical form: + + oldroot-------->newrootrollover newroot + | | | + v v v +oldintermediate newintermediate + | | + +------------+-------------+ + | + v + target + + +Several chains are output: + key-rollover-oldchain.pem: + target<-oldintermediate<-oldroot + key-rollover-rolloverchain.pem: + target<-newintermediate<-newrootrollover<-oldroot + key-rollover-longrolloverchain.pem: + target<-newintermediate<-newroot<-newrootrollover<-oldroot + key-rollover-newchain.pem: + target<-newintermediate<-newroot + +All of these chains should verify successfully. + + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Intermediate + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Target + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:12:1c:48:e4:73:1f:5c:d2:54:a9:7b:58:1c: + 37:73:c2:49:26:3e:ed:b5:6b:55:17:c9:4c:52:34: + ce:d9:76:86:32:74:74:ae:11:b2:99:1b:51:a0:33: + 48:34:2f:b9:d3:2b:06:c2:5c:29:53:35:ce:7c:a6: + 67:b2:6a:d4:33:c3:13:62:30:a1:53:5f:45:78:5b: + bb:47:ad:07:a4:98:9a:e9:e3:b1:3b:e6:33:c2:c1: + 5c:95:d7:c8:b9:a6:72:27:7a:79:da:c4:c8:5a:1a: + 3e:5e:5e:a6:62:64:c6:72:86:b1:78:98:5b:63:27: + 70:15:04:6b:b1:0f:11:9c:4d:3b:5c:e7:8d:c0:be: + d5:84:46:6c:bd:11:1e:21:c1:82:9c:d0:aa:2d:2f: + f8:2a:e9:3b:e4:35:15:6d:c7:4a:dd:a8:65:69:b8: + 16:a1:8a:04:a2:44:68:40:b6:99:ae:61:df:9f:6c: + 40:ef:79:c9:a3:6d:e4:2d:07:01:68:f1:21:4e:0e: + 28:a7:fd:2f:ad:ee:7d:65:cf:36:fd:4f:1b:ba:10: + 8e:86:fd:ec:37:67:0c:20:71:66:48:64:f3:82:af: + f5:e1:73:c9:09:36:03:3f:c2:47:7a:f2:33:b9:f9: + 9f:53:9b:24:5e:c3:cc:05:d9:a9:ed:d7:b2:2a:c5: + b7:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C9:45:0B:2A:F2:D8:8D:2A:D7:CE:AF:56:BF:82:B0:84:0C:C8:2E:F4 + X509v3 Authority Key Identifier: + keyid:B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Intermediate.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Intermediate.crl + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: sha256WithRSAEncryption + 63:66:9e:6c:34:8c:5d:74:ae:90:25:55:ae:86:49:b9:3d:fd: + 27:bc:4f:69:7b:70:cb:25:0e:a3:8c:7a:7d:9c:4f:0b:7c:f2: + 85:a5:ea:82:d2:37:c2:74:a2:ae:a8:bf:62:f4:5f:d4:c6:41: + 45:0c:cc:27:53:aa:8f:66:58:e9:b0:de:ae:98:14:bd:92:df: + 9b:0f:f2:c5:3b:d2:bc:1c:3e:80:b4:09:0f:c1:9f:d6:3a:29: + 52:71:b6:1a:92:95:5a:18:dc:b4:30:dc:61:61:93:54:d1:55: + 83:92:5d:c0:c7:dc:ab:d7:08:dd:8a:44:cf:92:f9:4d:86:25: + aa:ac:52:f6:0e:17:99:0b:31:d2:75:5e:33:f9:f5:b6:77:42: + 07:62:a9:53:cc:f3:79:84:57:d9:14:3f:ab:4c:8b:ae:c7:9f: + cf:7a:1f:bf:7e:1d:44:bd:76:b4:cd:8d:c8:1d:75:f7:3b:b5: + bc:35:8b:3f:29:b1:cb:67:a4:17:af:a4:ca:9f:2b:e7:15:66: + e4:c8:c1:7c:08:78:9e:5d:4b:c3:c6:58:66:96:42:e8:e6:40: + fd:dc:24:ce:3b:58:11:38:40:0e:fc:a9:c0:2c:0f:e5:cc:bb: + 02:32:31:b9:bc:6f:2d:1d:f6:2b:7c:d3:f8:24:f6:60:38:8a: + 1f:dd:e1:50 +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxJbnRl +cm1lZGlhdGUwHhcNMTUwMTAxMTIwMDAwWhcNMTYwMTAxMTIwMDAwWjARMQ8wDQYD +VQQDDAZUYXJnZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+EhxI +5HMfXNJUqXtYHDdzwkkmPu21a1UXyUxSNM7ZdoYydHSuEbKZG1GgM0g0L7nTKwbC +XClTNc58pmeyatQzwxNiMKFTX0V4W7tHrQekmJrp47E75jPCwVyV18i5pnInenna +xMhaGj5eXqZiZMZyhrF4mFtjJ3AVBGuxDxGcTTtc543AvtWERmy9ER4hwYKc0Kot +L/gq6TvkNRVtx0rdqGVpuBahigSiRGhAtpmuYd+fbEDvecmjbeQtBwFo8SFODiin +/S+t7n1lzzb9Txu6EI6G/ew3ZwwgcWZIZPOCr/Xhc8kJNgM/wkd68jO5+Z9TmyRe +w8wF2ant17Iqxbc5AgMBAAGjgekwgeYwHQYDVR0OBBYEFMlFCyry2I0q186vVr+C +sIQMyC70MB8GA1UdIwQYMBaAFLE5eRM10ANr6cRjK8zWYcOC7BTBMD8GCCsGAQUF +BwEBBDMwMTAvBggrBgEFBQcwAoYjaHR0cDovL3VybC1mb3ItYWlhL0ludGVybWVk +aWF0ZS5jZXIwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL3VybC1mb3ItY3JsL0lu +dGVybWVkaWF0ZS5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF +BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAY2aebDSMXXSukCVVroZJ +uT39J7xPaXtwyyUOo4x6fZxPC3zyhaXqgtI3wnSirqi/YvRf1MZBRQzMJ1Oqj2ZY +6bDerpgUvZLfmw/yxTvSvBw+gLQJD8Gf1jopUnG2GpKVWhjctDDcYWGTVNFVg5Jd +wMfcq9cI3YpEz5L5TYYlqqxS9g4XmQsx0nVeM/n1tndCB2KpU8zzeYRX2RQ/q0yL +rsefz3ofv34dRL12tM2NyB119zu1vDWLPymxy2ekF6+kyp8r5xVm5MjBfAh4nl1L +w8ZYZpZC6OZA/dwkzjtYEThADvypwCwP5cy7AjIxubxvLR32K3zT+CT2YDiKH93h +UA== +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Intermediate + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:d0:2e:3b:06:d6:ea:65:bd:dd:b2:d3:e8:88: + ea:08:73:01:42:ac:ca:38:28:17:32:93:5e:16:a8: + c1:79:44:9a:db:24:08:ba:81:52:63:9c:b4:ed:57: + d4:b2:ac:54:64:3b:70:39:7e:37:da:11:e1:8c:ba: + 09:bc:1a:9b:e7:fe:6d:75:f8:71:31:f0:ca:52:89: + 2a:9e:d5:53:db:b8:c0:76:cf:bf:58:58:e1:bb:81: + de:62:bb:06:58:1f:9b:64:03:75:7d:ee:76:6f:39: + 47:cb:8e:34:32:07:83:89:b0:83:2a:78:d0:ac:e2: + 86:0a:a8:ab:3b:97:81:de:9d:36:b4:03:b7:d5:06: + 05:53:d7:80:03:44:86:53:72:db:7a:5f:c5:20:dd: + c7:44:58:3b:40:7f:0e:39:bc:be:0d:ca:6a:f6:82: + a2:97:a2:17:79:51:6f:42:5d:0d:6a:b7:a0:de:5f: + 6a:00:be:e7:5a:b7:91:e9:fc:77:fd:75:88:8d:52: + 76:3d:0e:91:4b:c7:db:96:a4:5f:39:59:55:62:65: + 3b:15:7a:bc:7b:09:9f:3e:75:d9:9e:c5:00:b3:19: + d4:26:7e:eb:db:62:07:c2:f5:b6:4e:87:2d:eb:56: + 8b:5a:68:6c:85:2f:b4:3e:1d:dd:5d:31:49:98:8b: + 06:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + X509v3 Authority Key Identifier: + keyid:15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + a8:ad:48:d8:6e:1d:24:09:d2:b3:29:3c:48:60:27:7f:37:64: + d5:f1:3b:b3:5c:43:de:7c:b4:5f:ee:3a:f2:1a:25:24:0a:8a: + 25:6d:19:5b:dc:0c:4e:48:61:2f:60:d3:6b:f3:9c:03:2c:d3: + fa:c8:9b:99:e7:2e:c5:43:c0:5f:14:cd:8b:92:62:4f:e5:3a: + cd:b5:0a:d8:b2:01:c7:44:b4:3a:86:66:bf:fa:11:a5:f8:24: + 3f:d1:1a:e8:eb:1e:ad:f0:70:31:6f:bc:21:cf:db:ce:63:4e: + 84:e9:52:9e:bb:1b:c4:72:ae:e0:6c:88:9e:99:dc:79:d9:fd: + 83:26:8e:f6:19:70:d9:5e:fc:f4:0c:d1:17:6f:af:10:f6:64: + 16:08:d8:72:ba:3a:2d:66:28:5a:41:0d:f3:47:87:a7:9c:78: + c6:cd:5e:25:71:0b:f2:93:b8:26:17:b2:19:17:cc:03:ed:c0: + 6e:06:e2:4b:4a:57:5f:23:02:2a:69:06:7a:c4:b7:3e:2f:e8: + f0:03:ae:b8:2d:df:63:22:20:73:23:75:d9:3c:d7:22:e4:b4: + 65:65:ed:b9:e6:02:1d:b5:51:11:9c:db:92:e4:fe:8c:1d:bb: + c5:95:87:5b:38:ee:ff:e4:01:d1:5d:84:b9:73:d3:da:23:ca: + 5e:05:d3:7d +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowFzEVMBMGA1UEAwwMSW50 +ZXJtZWRpYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNAuOwbW +6mW93bLT6IjqCHMBQqzKOCgXMpNeFqjBeUSa2yQIuoFSY5y07VfUsqxUZDtwOX43 +2hHhjLoJvBqb5/5tdfhxMfDKUokqntVT27jAds+/WFjhu4HeYrsGWB+bZAN1fe52 +bzlHy440MgeDibCDKnjQrOKGCqirO5eB3p02tAO31QYFU9eAA0SGU3Lbel/FIN3H +RFg7QH8OOby+Dcpq9oKil6IXeVFvQl0Nareg3l9qAL7nWreR6fx3/XWIjVJ2PQ6R +S8fblqRfOVlVYmU7FXq8ewmfPnXZnsUAsxnUJn7r22IHwvW2Toct61aLWmhshS+0 +Ph3dXTFJmIsGVQIDAQABo4HLMIHIMB0GA1UdDgQWBBSxOXkTNdADa+nEYyvM1mHD +guwUwTAfBgNVHSMEGDAWgBQVnqat9Z+KocEImb9mb8/Kcs0MNDA3BggrBgEFBQcB +AQQrMCkwJwYIKwYBBQUHMAKGG2h0dHA6Ly91cmwtZm9yLWFpYS9Sb290LmNlcjAs +BgNVHR8EJTAjMCGgH6AdhhtodHRwOi8vdXJsLWZvci1jcmwvUm9vdC5jcmwwDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AKitSNhuHSQJ0rMpPEhgJ383ZNXxO7NcQ958tF/uOvIaJSQKiiVtGVvcDE5IYS9g +02vznAMs0/rIm5nnLsVDwF8UzYuSYk/lOs21CtiyAcdEtDqGZr/6EaX4JD/RGujr +Hq3wcDFvvCHP285jToTpUp67G8RyruBsiJ6Z3HnZ/YMmjvYZcNle/PQM0RdvrxD2 +ZBYI2HK6Oi1mKFpBDfNHh6eceMbNXiVxC/KTuCYXshkXzAPtwG4G4ktKV18jAipp +BnrEtz4v6PADrrgt32MiIHMjddk81yLktGVl7bnmAh21URGc25Lk/owdu8WVh1s4 +7v/kAdFdhLlz09ojyl4F030= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ae:ea:3b:3f:b6:e9:3d:ea:eb:3d:dd:e8:4d:45: + 83:63:78:ea:07:90:3a:3c:4f:92:54:2b:2d:02:1b: + eb:9e:81:72:68:2e:73:f8:4a:a1:de:0c:d6:f0:c2: + 61:26:90:0b:48:59:ab:23:25:8f:e4:4a:6b:c9:2d: + ba:a7:35:c4:22:df:76:99:d8:7b:f7:6d:ca:9b:da: + d2:ed:7e:c8:93:b2:a7:f6:f0:05:6a:5d:c6:e1:79: + d0:25:59:a9:50:1e:65:eb:1c:c9:cd:4e:6a:3a:2a: + a4:1a:fa:81:a3:e7:ae:d7:de:43:d9:e8:0b:5c:b0: + 6b:46:39:c5:9c:4a:6d:59:bf:da:70:2e:80:ac:c8: + 80:e3:83:d1:71:7b:a7:0b:92:bf:a8:81:ad:5c:b2: + d5:e9:b9:5f:b5:4f:93:43:67:72:36:b3:f7:17:b9: + 1b:da:2a:13:83:70:36:ae:59:03:3d:f0:71:de:a2: + 7a:41:ad:b5:e9:a2:51:e4:18:ec:88:ad:48:f1:df: + 17:04:43:54:2a:af:3c:c0:f5:84:39:43:d1:a7:d2: + 52:0f:3c:dd:ef:13:58:8c:1d:d4:dd:2e:6d:1a:e7: + 73:9b:8b:f3:41:7b:9a:53:4e:0d:92:d3:5d:3f:fc: + c3:61:dc:5f:a0:93:3c:08:cc:b4:9b:ce:9d:78:e3: + 77:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + X509v3 Authority Key Identifier: + keyid:15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 58:4b:60:7e:0b:c2:3d:20:f3:49:34:91:55:d3:5f:5b:ce:81: + 31:da:71:9f:72:d7:f4:cc:be:cf:58:b8:97:aa:99:87:3d:34: + 12:ac:40:1c:8e:02:46:83:ee:04:e1:7e:5e:57:ca:a4:ae:e1: + d0:b4:12:e9:65:33:f5:4e:c4:f6:49:00:7f:83:6d:75:67:84: + b2:db:52:5a:a2:3e:5d:2d:5c:f3:45:fe:6a:d3:c4:0a:76:52: + c6:9b:b0:89:01:b9:b6:be:30:60:d9:b4:2e:1d:1e:bf:ef:d8: + 12:90:9f:cb:67:29:20:61:9f:1a:67:64:88:4c:43:ec:10:7d: + 87:11:00:44:6a:ce:37:af:73:f4:fa:d2:22:2f:24:3a:6f:79: + 09:6c:8d:de:b5:71:0e:6e:b7:64:a9:be:73:a8:c1:c8:50:74: + d2:c4:2b:ef:4f:25:20:8f:41:f0:1f:6e:52:77:eb:a0:1a:94: + 87:7c:35:11:37:5c:33:f5:83:47:e0:f2:0e:97:af:23:61:23: + 25:0b:92:6c:3b:30:a1:aa:c6:dc:4a:05:6e:43:76:58:82:66: + cd:f6:d6:ef:9b:80:36:d6:95:b7:d1:ec:5c:53:f7:78:84:ef: + 48:6a:2c:f7:93:97:f2:7a:ce:ec:f3:eb:63:e1:5a:e0:69:02: + 5d:34:36:93 +-----BEGIN TRUSTED_CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7qOz+26T3q6z3d6E1F +g2N46geQOjxPklQrLQIb656Bcmguc/hKod4M1vDCYSaQC0hZqyMlj+RKa8ktuqc1 +xCLfdpnYe/dtypva0u1+yJOyp/bwBWpdxuF50CVZqVAeZescyc1OajoqpBr6gaPn +rtfeQ9noC1ywa0Y5xZxKbVm/2nAugKzIgOOD0XF7pwuSv6iBrVyy1em5X7VPk0Nn +cjaz9xe5G9oqE4NwNq5ZAz3wcd6iekGttemiUeQY7IitSPHfFwRDVCqvPMD1hDlD +0afSUg883e8TWIwd1N0ubRrnc5uL80F7mlNODZLTXT/8w2HcX6CTPAjMtJvOnXjj +d8kCAwEAAaOByzCByDAdBgNVHQ4EFgQUFZ6mrfWfiqHBCJm/Zm/PynLNDDQwHwYD +VR0jBBgwFoAUFZ6mrfWfiqHBCJm/Zm/PynLNDDQwNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBYS2B+C8I9 +IPNJNJFV019bzoEx2nGfctf0zL7PWLiXqpmHPTQSrEAcjgJGg+4E4X5eV8qkruHQ +tBLpZTP1TsT2SQB/g211Z4Sy21Jaoj5dLVzzRf5q08QKdlLGm7CJAbm2vjBg2bQu +HR6/79gSkJ/LZykgYZ8aZ2SITEPsEH2HEQBEas43r3P0+tIiLyQ6b3kJbI3etXEO +brdkqb5zqMHIUHTSxCvvTyUgj0HwH25Sd+ugGpSHfDURN1wz9YNH4PIOl68jYSMl +C5JsOzChqsbcSgVuQ3ZYgmbN9tbvm4A21pW30excU/d4hO9Iaiz3k5fyes7s8+tj +4VrgaQJdNDaT +-----END TRUSTED_CERTIFICATE----- + +-----BEGIN TIME----- +MTUwMzAyMTIwMDAwWg== +-----END TIME----- + +-----BEGIN VERIFY_RESULT----- +U1VDQ0VTUw== +-----END VERIFY_RESULT-----
diff --git a/net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem b/net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem new file mode 100644 index 0000000..6669c2a --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem
@@ -0,0 +1,311 @@ +[Created by: ./generate-key-rollover.py] + +A certificate tree with two self-signed root certificates(oldroot, newroot), +and a third root certificate (newrootrollover) which has the same key as newroot +but is signed by oldroot, all with the same subject and issuer. +There are two intermediates with the same key, subject and issuer +(oldintermediate signed by oldroot, and newintermediate signed by newroot). +The target certificate is signed by the intermediate key. + + +In graphical form: + + oldroot-------->newrootrollover newroot + | | | + v v v +oldintermediate newintermediate + | | + +------------+-------------+ + | + v + target + + +Several chains are output: + key-rollover-oldchain.pem: + target<-oldintermediate<-oldroot + key-rollover-rolloverchain.pem: + target<-newintermediate<-newrootrollover<-oldroot + key-rollover-longrolloverchain.pem: + target<-newintermediate<-newroot<-newrootrollover<-oldroot + key-rollover-newchain.pem: + target<-newintermediate<-newroot + +All of these chains should verify successfully. + + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Intermediate + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Target + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:12:1c:48:e4:73:1f:5c:d2:54:a9:7b:58:1c: + 37:73:c2:49:26:3e:ed:b5:6b:55:17:c9:4c:52:34: + ce:d9:76:86:32:74:74:ae:11:b2:99:1b:51:a0:33: + 48:34:2f:b9:d3:2b:06:c2:5c:29:53:35:ce:7c:a6: + 67:b2:6a:d4:33:c3:13:62:30:a1:53:5f:45:78:5b: + bb:47:ad:07:a4:98:9a:e9:e3:b1:3b:e6:33:c2:c1: + 5c:95:d7:c8:b9:a6:72:27:7a:79:da:c4:c8:5a:1a: + 3e:5e:5e:a6:62:64:c6:72:86:b1:78:98:5b:63:27: + 70:15:04:6b:b1:0f:11:9c:4d:3b:5c:e7:8d:c0:be: + d5:84:46:6c:bd:11:1e:21:c1:82:9c:d0:aa:2d:2f: + f8:2a:e9:3b:e4:35:15:6d:c7:4a:dd:a8:65:69:b8: + 16:a1:8a:04:a2:44:68:40:b6:99:ae:61:df:9f:6c: + 40:ef:79:c9:a3:6d:e4:2d:07:01:68:f1:21:4e:0e: + 28:a7:fd:2f:ad:ee:7d:65:cf:36:fd:4f:1b:ba:10: + 8e:86:fd:ec:37:67:0c:20:71:66:48:64:f3:82:af: + f5:e1:73:c9:09:36:03:3f:c2:47:7a:f2:33:b9:f9: + 9f:53:9b:24:5e:c3:cc:05:d9:a9:ed:d7:b2:2a:c5: + b7:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C9:45:0B:2A:F2:D8:8D:2A:D7:CE:AF:56:BF:82:B0:84:0C:C8:2E:F4 + X509v3 Authority Key Identifier: + keyid:B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Intermediate.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Intermediate.crl + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: sha256WithRSAEncryption + 63:66:9e:6c:34:8c:5d:74:ae:90:25:55:ae:86:49:b9:3d:fd: + 27:bc:4f:69:7b:70:cb:25:0e:a3:8c:7a:7d:9c:4f:0b:7c:f2: + 85:a5:ea:82:d2:37:c2:74:a2:ae:a8:bf:62:f4:5f:d4:c6:41: + 45:0c:cc:27:53:aa:8f:66:58:e9:b0:de:ae:98:14:bd:92:df: + 9b:0f:f2:c5:3b:d2:bc:1c:3e:80:b4:09:0f:c1:9f:d6:3a:29: + 52:71:b6:1a:92:95:5a:18:dc:b4:30:dc:61:61:93:54:d1:55: + 83:92:5d:c0:c7:dc:ab:d7:08:dd:8a:44:cf:92:f9:4d:86:25: + aa:ac:52:f6:0e:17:99:0b:31:d2:75:5e:33:f9:f5:b6:77:42: + 07:62:a9:53:cc:f3:79:84:57:d9:14:3f:ab:4c:8b:ae:c7:9f: + cf:7a:1f:bf:7e:1d:44:bd:76:b4:cd:8d:c8:1d:75:f7:3b:b5: + bc:35:8b:3f:29:b1:cb:67:a4:17:af:a4:ca:9f:2b:e7:15:66: + e4:c8:c1:7c:08:78:9e:5d:4b:c3:c6:58:66:96:42:e8:e6:40: + fd:dc:24:ce:3b:58:11:38:40:0e:fc:a9:c0:2c:0f:e5:cc:bb: + 02:32:31:b9:bc:6f:2d:1d:f6:2b:7c:d3:f8:24:f6:60:38:8a: + 1f:dd:e1:50 +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxJbnRl +cm1lZGlhdGUwHhcNMTUwMTAxMTIwMDAwWhcNMTYwMTAxMTIwMDAwWjARMQ8wDQYD +VQQDDAZUYXJnZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+EhxI +5HMfXNJUqXtYHDdzwkkmPu21a1UXyUxSNM7ZdoYydHSuEbKZG1GgM0g0L7nTKwbC +XClTNc58pmeyatQzwxNiMKFTX0V4W7tHrQekmJrp47E75jPCwVyV18i5pnInenna +xMhaGj5eXqZiZMZyhrF4mFtjJ3AVBGuxDxGcTTtc543AvtWERmy9ER4hwYKc0Kot +L/gq6TvkNRVtx0rdqGVpuBahigSiRGhAtpmuYd+fbEDvecmjbeQtBwFo8SFODiin +/S+t7n1lzzb9Txu6EI6G/ew3ZwwgcWZIZPOCr/Xhc8kJNgM/wkd68jO5+Z9TmyRe +w8wF2ant17Iqxbc5AgMBAAGjgekwgeYwHQYDVR0OBBYEFMlFCyry2I0q186vVr+C +sIQMyC70MB8GA1UdIwQYMBaAFLE5eRM10ANr6cRjK8zWYcOC7BTBMD8GCCsGAQUF +BwEBBDMwMTAvBggrBgEFBQcwAoYjaHR0cDovL3VybC1mb3ItYWlhL0ludGVybWVk +aWF0ZS5jZXIwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL3VybC1mb3ItY3JsL0lu +dGVybWVkaWF0ZS5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF +BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAY2aebDSMXXSukCVVroZJ +uT39J7xPaXtwyyUOo4x6fZxPC3zyhaXqgtI3wnSirqi/YvRf1MZBRQzMJ1Oqj2ZY +6bDerpgUvZLfmw/yxTvSvBw+gLQJD8Gf1jopUnG2GpKVWhjctDDcYWGTVNFVg5Jd +wMfcq9cI3YpEz5L5TYYlqqxS9g4XmQsx0nVeM/n1tndCB2KpU8zzeYRX2RQ/q0yL +rsefz3ofv34dRL12tM2NyB119zu1vDWLPymxy2ekF6+kyp8r5xVm5MjBfAh4nl1L +w8ZYZpZC6OZA/dwkzjtYEThADvypwCwP5cy7AjIxubxvLR32K3zT+CT2YDiKH93h +UA== +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Intermediate + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:d0:2e:3b:06:d6:ea:65:bd:dd:b2:d3:e8:88: + ea:08:73:01:42:ac:ca:38:28:17:32:93:5e:16:a8: + c1:79:44:9a:db:24:08:ba:81:52:63:9c:b4:ed:57: + d4:b2:ac:54:64:3b:70:39:7e:37:da:11:e1:8c:ba: + 09:bc:1a:9b:e7:fe:6d:75:f8:71:31:f0:ca:52:89: + 2a:9e:d5:53:db:b8:c0:76:cf:bf:58:58:e1:bb:81: + de:62:bb:06:58:1f:9b:64:03:75:7d:ee:76:6f:39: + 47:cb:8e:34:32:07:83:89:b0:83:2a:78:d0:ac:e2: + 86:0a:a8:ab:3b:97:81:de:9d:36:b4:03:b7:d5:06: + 05:53:d7:80:03:44:86:53:72:db:7a:5f:c5:20:dd: + c7:44:58:3b:40:7f:0e:39:bc:be:0d:ca:6a:f6:82: + a2:97:a2:17:79:51:6f:42:5d:0d:6a:b7:a0:de:5f: + 6a:00:be:e7:5a:b7:91:e9:fc:77:fd:75:88:8d:52: + 76:3d:0e:91:4b:c7:db:96:a4:5f:39:59:55:62:65: + 3b:15:7a:bc:7b:09:9f:3e:75:d9:9e:c5:00:b3:19: + d4:26:7e:eb:db:62:07:c2:f5:b6:4e:87:2d:eb:56: + 8b:5a:68:6c:85:2f:b4:3e:1d:dd:5d:31:49:98:8b: + 06:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + X509v3 Authority Key Identifier: + keyid:02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 56:90:dd:ae:50:4b:18:56:7f:e9:1c:e4:29:7c:60:7e:87:27: + b5:cd:2b:00:67:2b:f7:a2:32:db:38:92:18:46:00:22:c4:2d: + 1f:ff:32:5f:62:69:30:db:c8:aa:63:68:6a:0f:db:2d:13:15: + 8f:74:22:54:67:fb:95:19:35:49:66:1e:a1:65:67:3c:71:02: + 85:34:f7:3b:20:51:03:e9:a1:b9:7d:9b:3b:21:d4:7a:28:6e: + bd:01:50:a6:7e:2b:a0:bc:ad:d5:55:63:3d:04:f3:f0:aa:c3: + 4e:b3:aa:b8:68:89:a0:8c:b7:9e:38:37:81:2c:01:57:93:7c: + 3f:aa:54:2e:35:66:a4:c0:81:ca:06:5c:c6:ab:72:f4:38:08: + cd:60:40:53:42:48:71:0a:e7:f5:82:3c:bb:51:89:a4:8b:1e: + c9:44:4c:7f:10:7d:d3:f4:60:04:07:36:b2:44:82:b2:0a:3c: + e9:82:55:4a:37:cf:47:b6:d3:ea:e5:fc:b8:49:4c:6b:77:a6: + 42:29:1c:1f:97:78:18:f7:88:da:52:42:87:19:e4:13:0d:91: + 73:cc:98:6a:22:70:e2:5c:54:d0:96:b7:94:37:3c:0f:f6:9a: + e3:02:fb:95:63:5a:87:d4:0d:16:16:bd:95:fa:88:c3:a8:e4: + d0:91:dd:be +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowFzEVMBMGA1UEAwwMSW50 +ZXJtZWRpYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNAuOwbW +6mW93bLT6IjqCHMBQqzKOCgXMpNeFqjBeUSa2yQIuoFSY5y07VfUsqxUZDtwOX43 +2hHhjLoJvBqb5/5tdfhxMfDKUokqntVT27jAds+/WFjhu4HeYrsGWB+bZAN1fe52 +bzlHy440MgeDibCDKnjQrOKGCqirO5eB3p02tAO31QYFU9eAA0SGU3Lbel/FIN3H +RFg7QH8OOby+Dcpq9oKil6IXeVFvQl0Nareg3l9qAL7nWreR6fx3/XWIjVJ2PQ6R +S8fblqRfOVlVYmU7FXq8ewmfPnXZnsUAsxnUJn7r22IHwvW2Toct61aLWmhshS+0 +Ph3dXTFJmIsGVQIDAQABo4HLMIHIMB0GA1UdDgQWBBSxOXkTNdADa+nEYyvM1mHD +guwUwTAfBgNVHSMEGDAWgBQCzvasGjkehehy0YrGHeh6j50VazA3BggrBgEFBQcB +AQQrMCkwJwYIKwYBBQUHMAKGG2h0dHA6Ly91cmwtZm9yLWFpYS9Sb290LmNlcjAs +BgNVHR8EJTAjMCGgH6AdhhtodHRwOi8vdXJsLWZvci1jcmwvUm9vdC5jcmwwDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AFaQ3a5QSxhWf+kc5Cl8YH6HJ7XNKwBnK/eiMts4khhGACLELR//Ml9iaTDbyKpj +aGoP2y0TFY90IlRn+5UZNUlmHqFlZzxxAoU09zsgUQPpobl9mzsh1Hoobr0BUKZ+ +K6C8rdVVYz0E8/Cqw06zqrhoiaCMt544N4EsAVeTfD+qVC41ZqTAgcoGXMarcvQ4 +CM1gQFNCSHEK5/WCPLtRiaSLHslETH8QfdP0YAQHNrJEgrIKPOmCVUo3z0e20+rl +/LhJTGt3pkIpHB+XeBj3iNpSQocZ5BMNkXPMmGoicOJcVNCWt5Q3PA/2muMC+5Vj +WofUDRYWvZX6iMOo5NCR3b4= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a6:44:ec:a7:15:00:1f:89:ac:91:f8:ec:7b:03: + 46:0b:53:15:ed:23:40:35:94:f3:96:80:27:d3:4a: + 84:92:68:c9:0c:e0:14:32:c7:31:67:49:29:58:77: + ea:ce:8a:72:5b:93:b1:a0:a8:e5:84:c6:52:9d:5a: + c0:41:bf:98:5f:18:5d:aa:d1:65:79:fb:e9:b0:84: + 92:9d:2c:58:bc:f1:c4:29:59:ed:bc:ac:85:ce:d7: + 0e:aa:08:e8:2d:90:25:cb:91:9d:7d:91:74:42:a0: + ae:77:d2:11:7b:57:49:04:24:c0:94:f4:20:54:60: + d9:1b:76:76:0b:2c:23:3c:67:90:8c:06:ed:4e:df: + ac:24:22:26:f7:26:8f:5a:d2:5b:79:8a:6f:6e:53: + 27:60:10:cb:c7:b4:9f:60:2d:8f:32:69:4b:01:d1: + f0:6d:69:1a:22:14:06:66:63:97:e8:fc:79:41:8d: + 15:44:44:d1:43:2a:37:5e:77:e4:06:e6:a9:85:13: + e9:24:63:9d:09:d0:f5:13:d5:ba:59:2e:1c:d2:70: + 06:b1:80:f7:57:d7:30:f7:14:f3:18:06:7f:84:38: + b6:81:46:9f:a2:36:87:0e:5f:1a:45:38:b7:20:16: + b7:c6:e1:91:3b:0e:0c:ab:b7:4e:3d:a4:6d:66:d8: + 85:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + X509v3 Authority Key Identifier: + keyid:02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 0e:00:56:5c:72:31:88:bd:95:13:f7:64:96:1c:63:c2:1c:11: + 60:04:d2:c3:5f:7c:a2:d7:d1:33:6d:51:6b:77:61:78:a8:70: + 2e:50:97:5d:c1:e8:9b:dd:c6:61:a7:d3:e1:2c:83:07:85:5c: + c9:d7:1e:22:c2:5f:76:83:19:d7:de:4a:5e:82:0f:43:80:45: + 02:d7:d0:3d:ca:c3:c0:fc:04:c8:f6:89:32:d7:47:c6:bf:1f: + c6:bd:71:e1:07:00:90:12:ec:61:63:1b:6c:e9:58:2c:fc:4c: + a9:8f:58:e1:b1:6e:a5:ca:4d:be:7e:32:16:74:5f:fd:35:e4: + 37:aa:1a:c5:33:21:20:8a:3e:1c:af:da:f3:c7:a2:22:d3:93: + 6c:5e:ac:0a:65:d5:db:e4:8b:11:5e:ca:eb:8f:da:c4:5d:2f: + 7a:98:e8:3c:d1:89:15:05:02:86:ef:eb:17:18:81:28:ca:d6: + 58:87:bd:d4:e2:50:41:92:d9:7f:b1:f7:53:8f:f3:cc:f3:1e: + 1d:e4:5a:c2:60:1b:17:42:78:53:e9:2d:5d:bb:f9:21:50:ff: + 87:53:be:5f:e6:d4:8f:25:7f:d7:83:d7:f8:4d:c1:7c:7a:40: + 0b:11:f1:d9:c6:eb:97:45:00:d6:6b:84:1c:4f:fc:8e:1f:5b: + b5:3d:60:0c +-----BEGIN TRUSTED_CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKZE7KcVAB+JrJH47HsD +RgtTFe0jQDWU85aAJ9NKhJJoyQzgFDLHMWdJKVh36s6KcluTsaCo5YTGUp1awEG/ +mF8YXarRZXn76bCEkp0sWLzxxClZ7byshc7XDqoI6C2QJcuRnX2RdEKgrnfSEXtX +SQQkwJT0IFRg2Rt2dgssIzxnkIwG7U7frCQiJvcmj1rSW3mKb25TJ2AQy8e0n2At +jzJpSwHR8G1pGiIUBmZjl+j8eUGNFURE0UMqN1535AbmqYUT6SRjnQnQ9RPVulku +HNJwBrGA91fXMPcU8xgGf4Q4toFGn6I2hw5fGkU4tyAWt8bhkTsODKu3Tj2kbWbY +hfsCAwEAAaOByzCByDAdBgNVHQ4EFgQUAs72rBo5HoXoctGKxh3oeo+dFWswHwYD +VR0jBBgwFoAUAs72rBo5HoXoctGKxh3oeo+dFWswNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAOAFZccjGI +vZUT92SWHGPCHBFgBNLDX3yi19EzbVFrd2F4qHAuUJddweib3cZhp9PhLIMHhVzJ +1x4iwl92gxnX3kpegg9DgEUC19A9ysPA/ATI9oky10fGvx/GvXHhBwCQEuxhYxts +6Vgs/Eypj1jhsW6lyk2+fjIWdF/9NeQ3qhrFMyEgij4cr9rzx6Ii05NsXqwKZdXb +5IsRXsrrj9rEXS96mOg80YkVBQKG7+sXGIEoytZYh73U4lBBktl/sfdTj/PM8x4d +5FrCYBsXQnhT6S1du/khUP+HU75f5tSPJX/Xg9f4TcF8ekALEfHZxuuXRQDWa4Qc +T/yOH1u1PWAM +-----END TRUSTED_CERTIFICATE----- + +-----BEGIN TIME----- +MTUwMzAyMTIwMDAwWg== +-----END TIME----- + +-----BEGIN VERIFY_RESULT----- +U1VDQ0VTUw== +-----END VERIFY_RESULT-----
diff --git a/net/data/verify_certificate_chain_unittest/key-rollover-rolloverchain.pem b/net/data/verify_certificate_chain_unittest/key-rollover-rolloverchain.pem new file mode 100644 index 0000000..94105ff --- /dev/null +++ b/net/data/verify_certificate_chain_unittest/key-rollover-rolloverchain.pem
@@ -0,0 +1,400 @@ +[Created by: ./generate-key-rollover.py] + +A certificate tree with two self-signed root certificates(oldroot, newroot), +and a third root certificate (newrootrollover) which has the same key as newroot +but is signed by oldroot, all with the same subject and issuer. +There are two intermediates with the same key, subject and issuer +(oldintermediate signed by oldroot, and newintermediate signed by newroot). +The target certificate is signed by the intermediate key. + + +In graphical form: + + oldroot-------->newrootrollover newroot + | | | + v v v +oldintermediate newintermediate + | | + +------------+-------------+ + | + v + target + + +Several chains are output: + key-rollover-oldchain.pem: + target<-oldintermediate<-oldroot + key-rollover-rolloverchain.pem: + target<-newintermediate<-newrootrollover<-oldroot + key-rollover-longrolloverchain.pem: + target<-newintermediate<-newroot<-newrootrollover<-oldroot + key-rollover-newchain.pem: + target<-newintermediate<-newroot + +All of these chains should verify successfully. + + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Intermediate + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Target + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:be:12:1c:48:e4:73:1f:5c:d2:54:a9:7b:58:1c: + 37:73:c2:49:26:3e:ed:b5:6b:55:17:c9:4c:52:34: + ce:d9:76:86:32:74:74:ae:11:b2:99:1b:51:a0:33: + 48:34:2f:b9:d3:2b:06:c2:5c:29:53:35:ce:7c:a6: + 67:b2:6a:d4:33:c3:13:62:30:a1:53:5f:45:78:5b: + bb:47:ad:07:a4:98:9a:e9:e3:b1:3b:e6:33:c2:c1: + 5c:95:d7:c8:b9:a6:72:27:7a:79:da:c4:c8:5a:1a: + 3e:5e:5e:a6:62:64:c6:72:86:b1:78:98:5b:63:27: + 70:15:04:6b:b1:0f:11:9c:4d:3b:5c:e7:8d:c0:be: + d5:84:46:6c:bd:11:1e:21:c1:82:9c:d0:aa:2d:2f: + f8:2a:e9:3b:e4:35:15:6d:c7:4a:dd:a8:65:69:b8: + 16:a1:8a:04:a2:44:68:40:b6:99:ae:61:df:9f:6c: + 40:ef:79:c9:a3:6d:e4:2d:07:01:68:f1:21:4e:0e: + 28:a7:fd:2f:ad:ee:7d:65:cf:36:fd:4f:1b:ba:10: + 8e:86:fd:ec:37:67:0c:20:71:66:48:64:f3:82:af: + f5:e1:73:c9:09:36:03:3f:c2:47:7a:f2:33:b9:f9: + 9f:53:9b:24:5e:c3:cc:05:d9:a9:ed:d7:b2:2a:c5: + b7:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C9:45:0B:2A:F2:D8:8D:2A:D7:CE:AF:56:BF:82:B0:84:0C:C8:2E:F4 + X509v3 Authority Key Identifier: + keyid:B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Intermediate.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Intermediate.crl + + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + Signature Algorithm: sha256WithRSAEncryption + 63:66:9e:6c:34:8c:5d:74:ae:90:25:55:ae:86:49:b9:3d:fd: + 27:bc:4f:69:7b:70:cb:25:0e:a3:8c:7a:7d:9c:4f:0b:7c:f2: + 85:a5:ea:82:d2:37:c2:74:a2:ae:a8:bf:62:f4:5f:d4:c6:41: + 45:0c:cc:27:53:aa:8f:66:58:e9:b0:de:ae:98:14:bd:92:df: + 9b:0f:f2:c5:3b:d2:bc:1c:3e:80:b4:09:0f:c1:9f:d6:3a:29: + 52:71:b6:1a:92:95:5a:18:dc:b4:30:dc:61:61:93:54:d1:55: + 83:92:5d:c0:c7:dc:ab:d7:08:dd:8a:44:cf:92:f9:4d:86:25: + aa:ac:52:f6:0e:17:99:0b:31:d2:75:5e:33:f9:f5:b6:77:42: + 07:62:a9:53:cc:f3:79:84:57:d9:14:3f:ab:4c:8b:ae:c7:9f: + cf:7a:1f:bf:7e:1d:44:bd:76:b4:cd:8d:c8:1d:75:f7:3b:b5: + bc:35:8b:3f:29:b1:cb:67:a4:17:af:a4:ca:9f:2b:e7:15:66: + e4:c8:c1:7c:08:78:9e:5d:4b:c3:c6:58:66:96:42:e8:e6:40: + fd:dc:24:ce:3b:58:11:38:40:0e:fc:a9:c0:2c:0f:e5:cc:bb: + 02:32:31:b9:bc:6f:2d:1d:f6:2b:7c:d3:f8:24:f6:60:38:8a: + 1f:dd:e1:50 +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxJbnRl +cm1lZGlhdGUwHhcNMTUwMTAxMTIwMDAwWhcNMTYwMTAxMTIwMDAwWjARMQ8wDQYD +VQQDDAZUYXJnZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+EhxI +5HMfXNJUqXtYHDdzwkkmPu21a1UXyUxSNM7ZdoYydHSuEbKZG1GgM0g0L7nTKwbC +XClTNc58pmeyatQzwxNiMKFTX0V4W7tHrQekmJrp47E75jPCwVyV18i5pnInenna +xMhaGj5eXqZiZMZyhrF4mFtjJ3AVBGuxDxGcTTtc543AvtWERmy9ER4hwYKc0Kot +L/gq6TvkNRVtx0rdqGVpuBahigSiRGhAtpmuYd+fbEDvecmjbeQtBwFo8SFODiin +/S+t7n1lzzb9Txu6EI6G/ew3ZwwgcWZIZPOCr/Xhc8kJNgM/wkd68jO5+Z9TmyRe +w8wF2ant17Iqxbc5AgMBAAGjgekwgeYwHQYDVR0OBBYEFMlFCyry2I0q186vVr+C +sIQMyC70MB8GA1UdIwQYMBaAFLE5eRM10ANr6cRjK8zWYcOC7BTBMD8GCCsGAQUF +BwEBBDMwMTAvBggrBgEFBQcwAoYjaHR0cDovL3VybC1mb3ItYWlhL0ludGVybWVk +aWF0ZS5jZXIwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL3VybC1mb3ItY3JsL0lu +dGVybWVkaWF0ZS5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF +BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAY2aebDSMXXSukCVVroZJ +uT39J7xPaXtwyyUOo4x6fZxPC3zyhaXqgtI3wnSirqi/YvRf1MZBRQzMJ1Oqj2ZY +6bDerpgUvZLfmw/yxTvSvBw+gLQJD8Gf1jopUnG2GpKVWhjctDDcYWGTVNFVg5Jd +wMfcq9cI3YpEz5L5TYYlqqxS9g4XmQsx0nVeM/n1tndCB2KpU8zzeYRX2RQ/q0yL +rsefz3ofv34dRL12tM2NyB119zu1vDWLPymxy2ekF6+kyp8r5xVm5MjBfAh4nl1L +w8ZYZpZC6OZA/dwkzjtYEThADvypwCwP5cy7AjIxubxvLR32K3zT+CT2YDiKH93h +UA== +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Intermediate + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:d0:2e:3b:06:d6:ea:65:bd:dd:b2:d3:e8:88: + ea:08:73:01:42:ac:ca:38:28:17:32:93:5e:16:a8: + c1:79:44:9a:db:24:08:ba:81:52:63:9c:b4:ed:57: + d4:b2:ac:54:64:3b:70:39:7e:37:da:11:e1:8c:ba: + 09:bc:1a:9b:e7:fe:6d:75:f8:71:31:f0:ca:52:89: + 2a:9e:d5:53:db:b8:c0:76:cf:bf:58:58:e1:bb:81: + de:62:bb:06:58:1f:9b:64:03:75:7d:ee:76:6f:39: + 47:cb:8e:34:32:07:83:89:b0:83:2a:78:d0:ac:e2: + 86:0a:a8:ab:3b:97:81:de:9d:36:b4:03:b7:d5:06: + 05:53:d7:80:03:44:86:53:72:db:7a:5f:c5:20:dd: + c7:44:58:3b:40:7f:0e:39:bc:be:0d:ca:6a:f6:82: + a2:97:a2:17:79:51:6f:42:5d:0d:6a:b7:a0:de:5f: + 6a:00:be:e7:5a:b7:91:e9:fc:77:fd:75:88:8d:52: + 76:3d:0e:91:4b:c7:db:96:a4:5f:39:59:55:62:65: + 3b:15:7a:bc:7b:09:9f:3e:75:d9:9e:c5:00:b3:19: + d4:26:7e:eb:db:62:07:c2:f5:b6:4e:87:2d:eb:56: + 8b:5a:68:6c:85:2f:b4:3e:1d:dd:5d:31:49:98:8b: + 06:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B1:39:79:13:35:D0:03:6B:E9:C4:63:2B:CC:D6:61:C3:82:EC:14:C1 + X509v3 Authority Key Identifier: + keyid:15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + a8:ad:48:d8:6e:1d:24:09:d2:b3:29:3c:48:60:27:7f:37:64: + d5:f1:3b:b3:5c:43:de:7c:b4:5f:ee:3a:f2:1a:25:24:0a:8a: + 25:6d:19:5b:dc:0c:4e:48:61:2f:60:d3:6b:f3:9c:03:2c:d3: + fa:c8:9b:99:e7:2e:c5:43:c0:5f:14:cd:8b:92:62:4f:e5:3a: + cd:b5:0a:d8:b2:01:c7:44:b4:3a:86:66:bf:fa:11:a5:f8:24: + 3f:d1:1a:e8:eb:1e:ad:f0:70:31:6f:bc:21:cf:db:ce:63:4e: + 84:e9:52:9e:bb:1b:c4:72:ae:e0:6c:88:9e:99:dc:79:d9:fd: + 83:26:8e:f6:19:70:d9:5e:fc:f4:0c:d1:17:6f:af:10:f6:64: + 16:08:d8:72:ba:3a:2d:66:28:5a:41:0d:f3:47:87:a7:9c:78: + c6:cd:5e:25:71:0b:f2:93:b8:26:17:b2:19:17:cc:03:ed:c0: + 6e:06:e2:4b:4a:57:5f:23:02:2a:69:06:7a:c4:b7:3e:2f:e8: + f0:03:ae:b8:2d:df:63:22:20:73:23:75:d9:3c:d7:22:e4:b4: + 65:65:ed:b9:e6:02:1d:b5:51:11:9c:db:92:e4:fe:8c:1d:bb: + c5:95:87:5b:38:ee:ff:e4:01:d1:5d:84:b9:73:d3:da:23:ca: + 5e:05:d3:7d +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowFzEVMBMGA1UEAwwMSW50 +ZXJtZWRpYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNAuOwbW +6mW93bLT6IjqCHMBQqzKOCgXMpNeFqjBeUSa2yQIuoFSY5y07VfUsqxUZDtwOX43 +2hHhjLoJvBqb5/5tdfhxMfDKUokqntVT27jAds+/WFjhu4HeYrsGWB+bZAN1fe52 +bzlHy440MgeDibCDKnjQrOKGCqirO5eB3p02tAO31QYFU9eAA0SGU3Lbel/FIN3H +RFg7QH8OOby+Dcpq9oKil6IXeVFvQl0Nareg3l9qAL7nWreR6fx3/XWIjVJ2PQ6R +S8fblqRfOVlVYmU7FXq8ewmfPnXZnsUAsxnUJn7r22IHwvW2Toct61aLWmhshS+0 +Ph3dXTFJmIsGVQIDAQABo4HLMIHIMB0GA1UdDgQWBBSxOXkTNdADa+nEYyvM1mHD +guwUwTAfBgNVHSMEGDAWgBQVnqat9Z+KocEImb9mb8/Kcs0MNDA3BggrBgEFBQcB +AQQrMCkwJwYIKwYBBQUHMAKGG2h0dHA6Ly91cmwtZm9yLWFpYS9Sb290LmNlcjAs +BgNVHR8EJTAjMCGgH6AdhhtodHRwOi8vdXJsLWZvci1jcmwvUm9vdC5jcmwwDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AKitSNhuHSQJ0rMpPEhgJ383ZNXxO7NcQ958tF/uOvIaJSQKiiVtGVvcDE5IYS9g +02vznAMs0/rIm5nnLsVDwF8UzYuSYk/lOs21CtiyAcdEtDqGZr/6EaX4JD/RGujr +Hq3wcDFvvCHP285jToTpUp67G8RyruBsiJ6Z3HnZ/YMmjvYZcNle/PQM0RdvrxD2 +ZBYI2HK6Oi1mKFpBDfNHh6eceMbNXiVxC/KTuCYXshkXzAPtwG4G4ktKV18jAipp +BnrEtz4v6PADrrgt32MiIHMjddk81yLktGVl7bnmAh21URGc25Lk/owdu8WVh1s4 +7v/kAdFdhLlz09ojyl4F030= +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 2 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:ae:ea:3b:3f:b6:e9:3d:ea:eb:3d:dd:e8:4d:45: + 83:63:78:ea:07:90:3a:3c:4f:92:54:2b:2d:02:1b: + eb:9e:81:72:68:2e:73:f8:4a:a1:de:0c:d6:f0:c2: + 61:26:90:0b:48:59:ab:23:25:8f:e4:4a:6b:c9:2d: + ba:a7:35:c4:22:df:76:99:d8:7b:f7:6d:ca:9b:da: + d2:ed:7e:c8:93:b2:a7:f6:f0:05:6a:5d:c6:e1:79: + d0:25:59:a9:50:1e:65:eb:1c:c9:cd:4e:6a:3a:2a: + a4:1a:fa:81:a3:e7:ae:d7:de:43:d9:e8:0b:5c:b0: + 6b:46:39:c5:9c:4a:6d:59:bf:da:70:2e:80:ac:c8: + 80:e3:83:d1:71:7b:a7:0b:92:bf:a8:81:ad:5c:b2: + d5:e9:b9:5f:b5:4f:93:43:67:72:36:b3:f7:17:b9: + 1b:da:2a:13:83:70:36:ae:59:03:3d:f0:71:de:a2: + 7a:41:ad:b5:e9:a2:51:e4:18:ec:88:ad:48:f1:df: + 17:04:43:54:2a:af:3c:c0:f5:84:39:43:d1:a7:d2: + 52:0f:3c:dd:ef:13:58:8c:1d:d4:dd:2e:6d:1a:e7: + 73:9b:8b:f3:41:7b:9a:53:4e:0d:92:d3:5d:3f:fc: + c3:61:dc:5f:a0:93:3c:08:cc:b4:9b:ce:9d:78:e3: + 77:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 15:9E:A6:AD:F5:9F:8A:A1:C1:08:99:BF:66:6F:CF:CA:72:CD:0C:34 + X509v3 Authority Key Identifier: + keyid:02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 51:9b:dd:56:f2:b1:2b:e5:36:c8:2f:1d:a9:53:1f:89:e1:24: + 33:bd:ac:56:c1:c3:1a:38:a6:7e:fc:61:9a:ae:7c:1f:13:3e: + 37:e4:e6:a9:11:9e:2b:6e:ce:dd:12:0c:c1:b2:b7:eb:48:0e: + c7:a5:65:f0:86:49:8a:dc:cf:1b:6d:33:af:af:96:51:49:01: + e4:82:d6:e6:5a:d0:41:c7:05:9f:16:eb:06:bd:bc:ab:fe:a0: + d7:ac:de:62:d1:71:7e:69:82:31:03:e3:60:28:e6:18:3b:e5: + 93:2b:58:ee:d5:0b:7b:b6:af:f2:4f:22:eb:4d:b7:a6:74:68: + b7:82:68:7f:a9:b6:ee:a0:20:d7:c6:16:0e:9c:1c:39:ea:24: + 5e:60:12:fc:39:60:0d:54:3e:aa:b3:43:e1:0f:ef:d7:8f:3e: + 09:a9:55:95:e9:3d:0c:4f:ad:cb:c2:f3:2c:10:43:67:54:f9: + 66:54:81:ff:62:61:94:05:b0:42:af:f0:c5:ac:00:91:28:5c: + aa:a3:61:44:ba:c2:a6:ab:f8:1d:7e:02:69:33:48:fe:ac:93: + 7f:4c:99:91:d9:18:37:f9:70:3f:56:2a:ee:4a:e0:4d:f3:60: + 12:5d:30:d8:37:bf:ca:40:85:29:0c:a7:8f:ab:ad:03:6d:7b: + ba:62:7f:58 +-----BEGIN CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMjEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7qOz+26T3q6z3d6E1F +g2N46geQOjxPklQrLQIb656Bcmguc/hKod4M1vDCYSaQC0hZqyMlj+RKa8ktuqc1 +xCLfdpnYe/dtypva0u1+yJOyp/bwBWpdxuF50CVZqVAeZescyc1OajoqpBr6gaPn +rtfeQ9noC1ywa0Y5xZxKbVm/2nAugKzIgOOD0XF7pwuSv6iBrVyy1em5X7VPk0Nn +cjaz9xe5G9oqE4NwNq5ZAz3wcd6iekGttemiUeQY7IitSPHfFwRDVCqvPMD1hDlD +0afSUg883e8TWIwd1N0ubRrnc5uL80F7mlNODZLTXT/8w2HcX6CTPAjMtJvOnXjj +d8kCAwEAAaOByzCByDAdBgNVHQ4EFgQUFZ6mrfWfiqHBCJm/Zm/PynLNDDQwHwYD +VR0jBBgwFoAUAs72rBo5HoXoctGKxh3oeo+dFWswNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBRm91W8rEr +5TbILx2pUx+J4SQzvaxWwcMaOKZ+/GGarnwfEz435OapEZ4rbs7dEgzBsrfrSA7H +pWXwhkmK3M8bbTOvr5ZRSQHkgtbmWtBBxwWfFusGvbyr/qDXrN5i0XF+aYIxA+Ng +KOYYO+WTK1ju1Qt7tq/yTyLrTbemdGi3gmh/qbbuoCDXxhYOnBw56iReYBL8OWAN +VD6qs0PhD+/Xjz4JqVWV6T0MT63LwvMsEENnVPlmVIH/YmGUBbBCr/DFrACRKFyq +o2FEusKmq/gdfgJpM0j+rJN/TJmR2Rg3+XA/ViruSuBN82ASXTDYN7/KQIUpDKeP +q60DbXu6Yn9Y +-----END CERTIFICATE----- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root + Validity + Not Before: Jan 1 12:00:00 2015 GMT + Not After : Jan 1 12:00:00 2016 GMT + Subject: CN=Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:a6:44:ec:a7:15:00:1f:89:ac:91:f8:ec:7b:03: + 46:0b:53:15:ed:23:40:35:94:f3:96:80:27:d3:4a: + 84:92:68:c9:0c:e0:14:32:c7:31:67:49:29:58:77: + ea:ce:8a:72:5b:93:b1:a0:a8:e5:84:c6:52:9d:5a: + c0:41:bf:98:5f:18:5d:aa:d1:65:79:fb:e9:b0:84: + 92:9d:2c:58:bc:f1:c4:29:59:ed:bc:ac:85:ce:d7: + 0e:aa:08:e8:2d:90:25:cb:91:9d:7d:91:74:42:a0: + ae:77:d2:11:7b:57:49:04:24:c0:94:f4:20:54:60: + d9:1b:76:76:0b:2c:23:3c:67:90:8c:06:ed:4e:df: + ac:24:22:26:f7:26:8f:5a:d2:5b:79:8a:6f:6e:53: + 27:60:10:cb:c7:b4:9f:60:2d:8f:32:69:4b:01:d1: + f0:6d:69:1a:22:14:06:66:63:97:e8:fc:79:41:8d: + 15:44:44:d1:43:2a:37:5e:77:e4:06:e6:a9:85:13: + e9:24:63:9d:09:d0:f5:13:d5:ba:59:2e:1c:d2:70: + 06:b1:80:f7:57:d7:30:f7:14:f3:18:06:7f:84:38: + b6:81:46:9f:a2:36:87:0e:5f:1a:45:38:b7:20:16: + b7:c6:e1:91:3b:0e:0c:ab:b7:4e:3d:a4:6d:66:d8: + 85:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + X509v3 Authority Key Identifier: + keyid:02:CE:F6:AC:1A:39:1E:85:E8:72:D1:8A:C6:1D:E8:7A:8F:9D:15:6B + + Authority Information Access: + CA Issuers - URI:http://url-for-aia/Root.cer + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://url-for-crl/Root.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + 0e:00:56:5c:72:31:88:bd:95:13:f7:64:96:1c:63:c2:1c:11: + 60:04:d2:c3:5f:7c:a2:d7:d1:33:6d:51:6b:77:61:78:a8:70: + 2e:50:97:5d:c1:e8:9b:dd:c6:61:a7:d3:e1:2c:83:07:85:5c: + c9:d7:1e:22:c2:5f:76:83:19:d7:de:4a:5e:82:0f:43:80:45: + 02:d7:d0:3d:ca:c3:c0:fc:04:c8:f6:89:32:d7:47:c6:bf:1f: + c6:bd:71:e1:07:00:90:12:ec:61:63:1b:6c:e9:58:2c:fc:4c: + a9:8f:58:e1:b1:6e:a5:ca:4d:be:7e:32:16:74:5f:fd:35:e4: + 37:aa:1a:c5:33:21:20:8a:3e:1c:af:da:f3:c7:a2:22:d3:93: + 6c:5e:ac:0a:65:d5:db:e4:8b:11:5e:ca:eb:8f:da:c4:5d:2f: + 7a:98:e8:3c:d1:89:15:05:02:86:ef:eb:17:18:81:28:ca:d6: + 58:87:bd:d4:e2:50:41:92:d9:7f:b1:f7:53:8f:f3:cc:f3:1e: + 1d:e4:5a:c2:60:1b:17:42:78:53:e9:2d:5d:bb:f9:21:50:ff: + 87:53:be:5f:e6:d4:8f:25:7f:d7:83:d7:f8:4d:c1:7c:7a:40: + 0b:11:f1:d9:c6:eb:97:45:00:d6:6b:84:1c:4f:fc:8e:1f:5b: + b5:3d:60:0c +-----BEGIN TRUSTED_CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 +MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKZE7KcVAB+JrJH47HsD +RgtTFe0jQDWU85aAJ9NKhJJoyQzgFDLHMWdJKVh36s6KcluTsaCo5YTGUp1awEG/ +mF8YXarRZXn76bCEkp0sWLzxxClZ7byshc7XDqoI6C2QJcuRnX2RdEKgrnfSEXtX +SQQkwJT0IFRg2Rt2dgssIzxnkIwG7U7frCQiJvcmj1rSW3mKb25TJ2AQy8e0n2At +jzJpSwHR8G1pGiIUBmZjl+j8eUGNFURE0UMqN1535AbmqYUT6SRjnQnQ9RPVulku +HNJwBrGA91fXMPcU8xgGf4Q4toFGn6I2hw5fGkU4tyAWt8bhkTsODKu3Tj2kbWbY +hfsCAwEAAaOByzCByDAdBgNVHQ4EFgQUAs72rBo5HoXoctGKxh3oeo+dFWswHwYD +VR0jBBgwFoAUAs72rBo5HoXoctGKxh3oeo+dFWswNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw +IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAOAFZccjGI +vZUT92SWHGPCHBFgBNLDX3yi19EzbVFrd2F4qHAuUJddweib3cZhp9PhLIMHhVzJ +1x4iwl92gxnX3kpegg9DgEUC19A9ysPA/ATI9oky10fGvx/GvXHhBwCQEuxhYxts +6Vgs/Eypj1jhsW6lyk2+fjIWdF/9NeQ3qhrFMyEgij4cr9rzx6Ii05NsXqwKZdXb +5IsRXsrrj9rEXS96mOg80YkVBQKG7+sXGIEoytZYh73U4lBBktl/sfdTj/PM8x4d +5FrCYBsXQnhT6S1du/khUP+HU75f5tSPJX/Xg9f4TcF8ekALEfHZxuuXRQDWa4Qc +T/yOH1u1PWAM +-----END TRUSTED_CERTIFICATE----- + +-----BEGIN TIME----- +MTUwMzAyMTIwMDAwWg== +-----END TIME----- + +-----BEGIN VERIFY_RESULT----- +U1VDQ0VTUw== +-----END VERIFY_RESULT-----
diff --git a/net/dns/record_rdata.h b/net/dns/record_rdata.h index d2ca587..0aa29d57 100644 --- a/net/dns/record_rdata.h +++ b/net/dns/record_rdata.h
@@ -12,6 +12,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/logging.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "net/base/ip_address.h" @@ -198,7 +199,11 @@ uint16_t Type() const override; // Length of the bitmap in bits. - unsigned bitmap_length() const { return bitmap_.size() * 8; } + // This will be between 8 and 256, per RFC 3845, Section 2.1.2. + uint16_t bitmap_length() const { + DCHECK_LE(bitmap_.size(), 32u); + return static_cast<uint16_t>(bitmap_.size() * 8); + } // Returns bit i-th bit in the bitmap, where bits withing a byte are organized // most to least significant. If it is set, a record with rrtype i exists for
diff --git a/net/dns/record_rdata_unittest.cc b/net/dns/record_rdata_unittest.cc index c41e39a..f73853ed 100644 --- a/net/dns/record_rdata_unittest.cc +++ b/net/dns/record_rdata_unittest.cc
@@ -17,9 +17,6 @@ } TEST(RecordRdataTest, ParseSrvRecord) { - std::unique_ptr<SrvRecordRdata> record1_obj; - std::unique_ptr<SrvRecordRdata> record2_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -40,7 +37,8 @@ base::StringPiece record2_strpiece = MakeStringPiece( record + first_record_len, sizeof(record) - first_record_len); - record1_obj = SrvRecordRdata::Create(record1_strpiece, parser); + std::unique_ptr<SrvRecordRdata> record1_obj = + SrvRecordRdata::Create(record1_strpiece, parser); ASSERT_TRUE(record1_obj != NULL); ASSERT_EQ(1, record1_obj->priority()); ASSERT_EQ(2, record1_obj->weight()); @@ -48,7 +46,8 @@ ASSERT_EQ("www.google.com", record1_obj->target()); - record2_obj = SrvRecordRdata::Create(record2_strpiece, parser); + std::unique_ptr<SrvRecordRdata> record2_obj = + SrvRecordRdata::Create(record2_strpiece, parser); ASSERT_TRUE(record2_obj != NULL); ASSERT_EQ(257, record2_obj->priority()); ASSERT_EQ(258, record2_obj->weight()); @@ -61,8 +60,6 @@ } TEST(RecordRdataTest, ParseARecord) { - std::unique_ptr<ARecordRdata> record_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -73,7 +70,8 @@ DnsRecordParser parser(record, sizeof(record), 0); base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); - record_obj = ARecordRdata::Create(record_strpiece, parser); + std::unique_ptr<ARecordRdata> record_obj = + ARecordRdata::Create(record_strpiece, parser); ASSERT_TRUE(record_obj != NULL); ASSERT_EQ("127.0.0.1", record_obj->address().ToString()); @@ -82,8 +80,6 @@ } TEST(RecordRdataTest, ParseAAAARecord) { - std::unique_ptr<AAAARecordRdata> record_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -95,7 +91,8 @@ DnsRecordParser parser(record, sizeof(record), 0); base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); - record_obj = AAAARecordRdata::Create(record_strpiece, parser); + std::unique_ptr<AAAARecordRdata> record_obj = + AAAARecordRdata::Create(record_strpiece, parser); ASSERT_TRUE(record_obj != NULL); ASSERT_EQ("1234:5678::9", record_obj->address().ToString()); @@ -104,8 +101,6 @@ } TEST(RecordRdataTest, ParseCnameRecord) { - std::unique_ptr<CnameRecordRdata> record_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -115,7 +110,8 @@ DnsRecordParser parser(record, sizeof(record), 0); base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); - record_obj = CnameRecordRdata::Create(record_strpiece, parser); + std::unique_ptr<CnameRecordRdata> record_obj = + CnameRecordRdata::Create(record_strpiece, parser); ASSERT_TRUE(record_obj != NULL); ASSERT_EQ("www.google.com", record_obj->cname()); @@ -124,8 +120,6 @@ } TEST(RecordRdataTest, ParsePtrRecord) { - std::unique_ptr<PtrRecordRdata> record_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -135,7 +129,8 @@ DnsRecordParser parser(record, sizeof(record), 0); base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); - record_obj = PtrRecordRdata::Create(record_strpiece, parser); + std::unique_ptr<PtrRecordRdata> record_obj = + PtrRecordRdata::Create(record_strpiece, parser); ASSERT_TRUE(record_obj != NULL); ASSERT_EQ("www.google.com", record_obj->ptrdomain()); @@ -144,8 +139,6 @@ } TEST(RecordRdataTest, ParseTxtRecord) { - std::unique_ptr<TxtRecordRdata> record_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -155,7 +148,8 @@ DnsRecordParser parser(record, sizeof(record), 0); base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); - record_obj = TxtRecordRdata::Create(record_strpiece, parser); + std::unique_ptr<TxtRecordRdata> record_obj = + TxtRecordRdata::Create(record_strpiece, parser); ASSERT_TRUE(record_obj != NULL); std::vector<std::string> expected; @@ -169,8 +163,6 @@ } TEST(RecordRdataTest, ParseNsecRecord) { - std::unique_ptr<NsecRecordRdata> record_obj; - // These are just the rdata portions of the DNS records, rather than complete // records, but it works well enough for this test. @@ -181,7 +173,8 @@ DnsRecordParser parser(record, sizeof(record), 0); base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); - record_obj = NsecRecordRdata::Create(record_strpiece, parser); + std::unique_ptr<NsecRecordRdata> record_obj = + NsecRecordRdata::Create(record_strpiece, parser); ASSERT_TRUE(record_obj != NULL); ASSERT_EQ(16u, record_obj->bitmap_length()); @@ -196,5 +189,39 @@ ASSERT_TRUE(record_obj->IsEqual(record_obj.get())); } +TEST(RecordRdataTest, CreateNsecRecordWithEmptyBitmapReturnsNull) { + // These are just the rdata portions of the DNS records, rather than complete + // records, but it works well enough for this test. + // This record has a bitmap that is 0 bytes long. + const uint8_t record[] = {0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o', 'g', + 'l', 'e', 0x03, 'c', 'o', 'm', 0x00, 0x00, 0x00}; + + DnsRecordParser parser(record, sizeof(record), 0); + base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); + + std::unique_ptr<NsecRecordRdata> record_obj = + NsecRecordRdata::Create(record_strpiece, parser); + ASSERT_FALSE(record_obj); +} + +TEST(RecordRdataTest, CreateNsecRecordWithOversizedBitmapReturnsNull) { + // These are just the rdata portions of the DNS records, rather than complete + // records, but it works well enough for this test. + // This record has a bitmap that is 33 bytes long. The maximum size allowed by + // RFC 3845, Section 2.1.2, is 32 bytes. + const uint8_t record[] = { + 0x03, 'w', 'w', 'w', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', + 0x03, 'c', 'o', 'm', 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + DnsRecordParser parser(record, sizeof(record), 0); + base::StringPiece record_strpiece = MakeStringPiece(record, sizeof(record)); + + std::unique_ptr<NsecRecordRdata> record_obj = + NsecRecordRdata::Create(record_strpiece, parser); + ASSERT_FALSE(record_obj); +} } // namespace net
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 4105646..081d829 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -98,7 +98,6 @@ time_func(&base::TimeTicks::Now), enable_http2_alternative_service_with_different_host(false), enable_quic_alternative_service_with_different_host(true), - enable_npn(false), enable_priority_dependencies(true), enable_quic(false), disable_quic_on_timeout_with_open_streams(false), @@ -377,11 +376,7 @@ } void HttpNetworkSession::GetNpnProtos(NextProtoVector* npn_protos) const { - if (HttpStreamFactory::spdy_enabled() && params_.enable_npn) { - *npn_protos = next_protos_; - } else { - npn_protos->clear(); - } + npn_protos->clear(); } void HttpNetworkSession::GetSSLConfig(const HttpRequestInfo& request,
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index fd3b0961..a6844a4 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -101,9 +101,6 @@ // of the origin. bool enable_quic_alternative_service_with_different_host; - // Enables NPN support. Note that ALPN is always enabled. - bool enable_npn; - // Enable setting of HTTP/2 dependencies based on priority. bool enable_priority_dependencies;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 76bb795e..60173ab 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -15865,37 +15865,6 @@ trans->GetTotalReceivedBytes()); } -TEST_P(HttpNetworkTransactionTest, EnableNPN) { - session_deps_.enable_npn = true; - - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - HttpRequestInfo request; - TestCompletionCallback callback; - EXPECT_EQ(ERR_IO_PENDING, - trans.Start(&request, callback.callback(), BoundNetLog())); - - EXPECT_THAT(trans.server_ssl_config_.alpn_protos, - testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11)); - EXPECT_THAT(trans.server_ssl_config_.npn_protos, - testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11)); -} - -TEST_P(HttpNetworkTransactionTest, DisableNPN) { - session_deps_.enable_npn = false; - - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - HttpRequestInfo request; - TestCompletionCallback callback; - EXPECT_EQ(ERR_IO_PENDING, - trans.Start(&request, callback.callback(), BoundNetLog())); - - EXPECT_THAT(trans.server_ssl_config_.alpn_protos, - testing::ElementsAre(kProtoHTTP2, kProtoSPDY31, kProtoHTTP11)); - EXPECT_TRUE(trans.server_ssl_config_.npn_protos.empty()); -} - #if !defined(OS_IOS) TEST_P(HttpNetworkTransactionTest, TokenBindingSpdy) { const std::string https_url = "https://www.example.com";
diff --git a/net/http/http_server_properties.cc b/net/http/http_server_properties.cc index cea3032..98cf6c8 100644 --- a/net/http/http_server_properties.cc +++ b/net/http/http_server_properties.cc
@@ -14,21 +14,6 @@ const char kAlternativeServiceHeader[] = "Alt-Svc"; -namespace { - -// The order of these strings much match the order of the enum definition -// for AlternateProtocol. -const char* const kAlternateProtocolStrings[] = { - "npn-spdy/3.1", - "npn-h2", - "quic"}; - -static_assert(arraysize(kAlternateProtocolStrings) == - NUM_VALID_ALTERNATE_PROTOCOLS, - "kAlternateProtocolStrings has incorrect size"); - -} // namespace - void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage) { UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage, ALTERNATE_PROTOCOL_USAGE_MAX); @@ -47,12 +32,12 @@ const char* AlternateProtocolToString(AlternateProtocol protocol) { switch (protocol) { - case NPN_SPDY_3_1: - case NPN_HTTP_2: case QUIC: - DCHECK(IsAlternateProtocolValid(protocol)); - return kAlternateProtocolStrings[ - protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION]; + return "quic"; + case NPN_HTTP_2: + return "h2"; + case NPN_SPDY_3_1: + return "npn-spdy/3.1"; case UNINITIALIZED_ALTERNATE_PROTOCOL: return "Uninitialized"; } @@ -61,12 +46,17 @@ } AlternateProtocol AlternateProtocolFromString(const std::string& str) { - for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION; - i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) { - AlternateProtocol protocol = static_cast<AlternateProtocol>(i); - if (str == AlternateProtocolToString(protocol)) - return protocol; - } + if (str == "quic") + return QUIC; + if (str == "h2") + return NPN_HTTP_2; + // "npn-h2" is accepted here so that persisted settings with the old string + // can be loaded from disk. TODO(bnc): Remove around 2016 December. + if (str == "npn-h2") + return NPN_HTTP_2; + if (str == "npn-spdy/3.1") + return NPN_SPDY_3_1; + return UNINITIALIZED_ALTERNATE_PROTOCOL; }
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc index 9b2048a..51f50949 100644 --- a/net/http/http_server_properties_manager_unittest.cc +++ b/net/http/http_server_properties_manager_unittest.cc
@@ -246,7 +246,7 @@ std::unique_ptr<base::DictionaryValue> alternative_service_dict0( new base::DictionaryValue); alternative_service_dict0->SetInteger("port", 443); - alternative_service_dict0->SetString("protocol_str", "npn-h2"); + alternative_service_dict0->SetString("protocol_str", "h2"); std::unique_ptr<base::DictionaryValue> alternative_service_dict1( new base::DictionaryValue); alternative_service_dict1->SetInteger("port", 1234); @@ -1121,9 +1121,9 @@ "\"servers\":[" "{\"http://www.google.com\":{" "\"alternative_service\":[{\"expiration\":\"13756212000000000\"," - "\"port\":443,\"protocol_str\":\"npn-h2\"}," + "\"port\":443,\"protocol_str\":\"h2\"}," "{\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\"," - "\"port\":1234,\"protocol_str\":\"npn-h2\"}]}}," + "\"port\":1234,\"protocol_str\":\"h2\"}]}}," "{\"http://mail.google.com\":{\"alternative_service\":[{" "\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\"," "\"port\":444,\"protocol_str\":\"npn-spdy/3.1\"}]," @@ -1142,7 +1142,7 @@ TEST_P(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) { std::unique_ptr<base::Value> server_value = base::JSONReader::Read( - "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"}," + "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"h2\"}," "{\"port\":123,\"protocol_str\":\"quic\"," "\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\"," "\"port\":1234,\"protocol_str\":\"npn-h2\","
diff --git a/net/http/transport_security_state_ct_policies.inc b/net/http/transport_security_state_ct_policies.inc index b813ce0..af76103 100644 --- a/net/http/transport_security_state_ct_policies.inc +++ b/net/http/transport_security_state_ct_policies.inc
@@ -104,6 +104,9 @@ {{0x56, 0x7b, 0x82, 0x11, 0xfd, 0x20, 0xd3, 0xd2, 0x83, 0xee, 0x0c, 0xd7, 0xce, 0x06, 0x72, 0xcb, 0x9d, 0x99, 0xbc, 0x5b, 0x48, 0x7a, 0x58, 0xc9, 0xd5, 0x4e, 0xc6, 0x7f, 0x77, 0xd4, 0xa8, 0xf5}}, + {{0x5c, 0x4f, 0x28, 0x53, 0x88, 0xf3, 0x83, 0x36, 0x26, 0x9a, 0x55, + 0xc7, 0xc1, 0x2c, 0x0b, 0x3c, 0xa7, 0x3f, 0xef, 0x2a, 0x5a, 0x4d, + 0xf8, 0x2b, 0x89, 0x14, 0x1e, 0x84, 0x1a, 0x6c, 0x4d, 0xe4}}, {{0x67, 0xdc, 0x4f, 0x32, 0xfa, 0x10, 0xe7, 0xd0, 0x1a, 0x79, 0xa0, 0x73, 0xaa, 0x0c, 0x9e, 0x02, 0x12, 0xec, 0x2f, 0xfc, 0x3d, 0x77, 0x9e, 0x0a, 0xa7, 0xf9, 0xc0, 0xf0, 0xe1, 0xc2, 0xc8, 0x93}}, @@ -131,9 +134,6 @@ {{0x87, 0xaf, 0x34, 0xd6, 0x6f, 0xb3, 0xf2, 0xfd, 0xf3, 0x6e, 0x09, 0x11, 0x1e, 0x9a, 0xba, 0x2f, 0x6f, 0x44, 0xb2, 0x07, 0xf3, 0x86, 0x3f, 0x3d, 0x0b, 0x54, 0xb2, 0x50, 0x23, 0x90, 0x9a, 0xa5}}, - {{0x93, 0x92, 0xae, 0x21, 0x49, 0x92, 0x4a, 0xde, 0x37, 0xe6, 0x45, - 0xdb, 0xa1, 0xff, 0x4b, 0xdd, 0xdc, 0xda, 0x2b, 0x29, 0x1b, 0x60, - 0x97, 0x66, 0x9d, 0x2a, 0xfa, 0x5c, 0x7a, 0x37, 0x26, 0x19}}, {{0x95, 0x73, 0x54, 0x73, 0xbd, 0x67, 0xa3, 0xb9, 0x5a, 0x8d, 0x5f, 0x90, 0xc5, 0xa2, 0x1a, 0xce, 0x1e, 0x0d, 0x79, 0x47, 0x32, 0x06, 0x74, 0xd4, 0xab, 0x84, 0x79, 0x72, 0xb9, 0x15, 0x44, 0xd2}},
diff --git a/net/net.gyp b/net/net.gyp index 328c0a6..d033f73 100644 --- a/net/net.gyp +++ b/net/net.gyp
@@ -346,8 +346,6 @@ 'dns/mdns_cache_unittest.cc', 'dns/mdns_client_unittest.cc', 'dns/mdns_query_unittest.cc', - 'dns/record_parsed_unittest.cc', - 'dns/record_rdata_unittest.cc', ], }], [ 'OS == "win"', {
diff --git a/net/net.gypi b/net/net.gypi index 7dabdaa..8a4a799c 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -105,6 +105,8 @@ 'cert/internal/parse_ocsp.h', 'cert/internal/parsed_certificate.cc', 'cert/internal/parsed_certificate.h', + 'cert/internal/path_builder.cc', + 'cert/internal/path_builder.h', 'cert/internal/signature_algorithm.cc', 'cert/internal/signature_algorithm.h', 'cert/internal/signature_policy.cc', @@ -1405,11 +1407,15 @@ 'cert/internal/parse_certificate_unittest.cc', 'cert/internal/parse_name_unittest.cc', 'cert/internal/parse_ocsp_unittest.cc', + 'cert/internal/path_builder_pkits_unittest.cc', + 'cert/internal/path_builder_unittest.cc', + 'cert/internal/path_builder_verify_certificate_chain_unittest.cc', 'cert/internal/signature_algorithm_unittest.cc', 'cert/internal/test_helpers.cc', 'cert/internal/test_helpers.h', - 'cert/internal/verify_certificate_chain_unittest.cc', 'cert/internal/verify_certificate_chain_pkits_unittest.cc', + 'cert/internal/verify_certificate_chain_typed_unittest.h', + 'cert/internal/verify_certificate_chain_unittest.cc', 'cert/internal/verify_name_match_unittest.cc', 'cert/internal/verify_signed_data_unittest.cc', 'cert/jwk_serializer_unittest.cc', @@ -2465,6 +2471,10 @@ 'data/verify_certificate_chain_unittest/intermediary-unknown-non-critical-extension.pem', 'data/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal-anchor.pem', 'data/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal.pem', + 'data/verify_certificate_chain_unittest/key-rollover-longrolloverchain.pem', + 'data/verify_certificate_chain_unittest/key-rollover-newchain.pem', + 'data/verify_certificate_chain_unittest/key-rollover-oldchain.pem', + 'data/verify_certificate_chain_unittest/key-rollover-rolloverchain.pem', 'data/verify_certificate_chain_unittest/non-self-signed-root.pem', 'data/verify_certificate_chain_unittest/target-and-intermediary.pem', 'data/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca.pem',
diff --git a/net/net_common.gypi b/net/net_common.gypi index 9f91244..e5b41531 100644 --- a/net/net_common.gypi +++ b/net/net_common.gypi
@@ -223,10 +223,6 @@ 'dns/mdns_client.h', 'dns/mdns_client_impl.cc', 'dns/mdns_client_impl.h', - 'dns/record_parsed.cc', - 'dns/record_parsed.h', - 'dns/record_rdata.cc', - 'dns/record_rdata.h', ] }], [ 'OS == "win"', {
diff --git a/net/quic/congestion_control/cubic.cc b/net/quic/congestion_control/cubic.cc index 9a924b5..ca90d71 100644 --- a/net/quic/congestion_control/cubic.cc +++ b/net/quic/congestion_control/cubic.cc
@@ -117,7 +117,7 @@ // Cubic is "independent" of RTT, the update is limited by the time elapsed. if (last_congestion_window_ == current_congestion_window && - (current_time.Subtract(last_update_time_) <= MaxCubicTimeInterval())) { + (current_time - last_update_time_ <= MaxCubicTimeInterval())) { return max(last_target_congestion_window_, estimated_tcp_congestion_window_); } @@ -145,9 +145,9 @@ // through the app-limited period. if (FLAGS_shift_quic_cubic_epoch_when_app_limited && app_limited_start_time_ != QuicTime::Zero()) { - QuicTime::Delta shift = current_time.Subtract(app_limited_start_time_); + QuicTime::Delta shift = current_time - app_limited_start_time_; DVLOG(1) << "Shifting epoch for quiescence by " << shift.ToMicroseconds(); - epoch_ = epoch_.Add(shift); + epoch_ = epoch_ + shift; app_limited_start_time_ = QuicTime::Zero(); } } @@ -156,7 +156,7 @@ // the round trip time in account. This is done to allow us to use shift as a // divide operator. int64_t elapsed_time = - (current_time.Add(delay_min).Subtract(epoch_).ToMicroseconds() << 10) / + ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / kNumMicrosPerSecond; int64_t offset = time_to_origin_point_ - elapsed_time;
diff --git a/net/quic/congestion_control/cubic_bytes.cc b/net/quic/congestion_control/cubic_bytes.cc index e09cc76..cae49226 100644 --- a/net/quic/congestion_control/cubic_bytes.cc +++ b/net/quic/congestion_control/cubic_bytes.cc
@@ -112,7 +112,7 @@ // Cubic is "independent" of RTT, the update is limited by the time elapsed. if (last_congestion_window_ == current_congestion_window && - (current_time.Subtract(last_update_time_) <= MaxCubicTimeInterval())) { + (current_time - last_update_time_ <= MaxCubicTimeInterval())) { return max(last_target_congestion_window_, estimated_tcp_congestion_window_); } @@ -140,7 +140,7 @@ // the round trip time in account. This is done to allow us to use shift as a // divide operator. int64_t elapsed_time = - (current_time.Add(delay_min).Subtract(epoch_).ToMicroseconds() << 10) / + ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / kNumMicrosPerSecond; int64_t offset = time_to_origin_point_ - elapsed_time;
diff --git a/net/quic/congestion_control/general_loss_algorithm.cc b/net/quic/congestion_control/general_loss_algorithm.cc index e99a1f57..05491b1b 100644 --- a/net/quic/congestion_control/general_loss_algorithm.cc +++ b/net/quic/congestion_control/general_loss_algorithm.cc
@@ -67,7 +67,7 @@ QuicTime::Delta::Max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt()); QuicTime::Delta loss_delay = QuicTime::Delta::Max(QuicTime::Delta::FromMilliseconds(kMinLossDelayMs), - max_rtt.Add(max_rtt >> reordering_shift_)); + max_rtt + (max_rtt >> reordering_shift_)); QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked(); for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin(); it != unacked_packets.end() && packet_number <= largest_observed; @@ -91,7 +91,7 @@ if ((!it->retransmittable_frames.empty() && unacked_packets.largest_sent_packet() == largest_observed) || (loss_type_ == kTime || loss_type_ == kAdaptiveTime)) { - QuicTime when_lost = it->sent_time.Add(loss_delay); + QuicTime when_lost = it->sent_time + loss_delay; if (time < when_lost) { loss_detection_timeout_ = when_lost; break; @@ -101,7 +101,7 @@ } // NACK-based loss detection allows for a max reordering window of 1 RTT. - if (it->sent_time.Add(rtt_stats.smoothed_rtt()) < + if (it->sent_time + rtt_stats.smoothed_rtt() < unacked_packets.GetTransmissionInfo(largest_observed).sent_time) { packets_lost->push_back(std::make_pair(packet_number, it->bytes_sent)); continue; @@ -128,8 +128,9 @@ // Calculate the extra time needed so this wouldn't have been declared lost. // Extra time needed is based on how long it's been since the spurious // retransmission was sent, because the SRTT and latest RTT may have changed. - QuicTime::Delta extra_time_needed = time.Subtract( - unacked_packets.GetTransmissionInfo(spurious_retransmission).sent_time); + QuicTime::Delta extra_time_needed = + time - + unacked_packets.GetTransmissionInfo(spurious_retransmission).sent_time; // Increase the reordering fraction until enough time would be allowed. QuicTime::Delta max_rtt = QuicTime::Delta::Max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
diff --git a/net/quic/congestion_control/general_loss_algorithm_test.cc b/net/quic/congestion_control/general_loss_algorithm_test.cc index b0e1519..e547557a 100644 --- a/net/quic/congestion_control/general_loss_algorithm_test.cc +++ b/net/quic/congestion_control/general_loss_algorithm_test.cc
@@ -125,10 +125,10 @@ // Early retransmit when the final packet gets acked and the first is nacked. unacked_packets_.RemoveFromInFlight(2); VerifyLosses(2, nullptr, 0); - EXPECT_EQ(clock_.Now().Add(rtt_stats_.smoothed_rtt().Multiply(1.25)), + EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); - clock_.AdvanceTime(rtt_stats_.latest_rtt().Multiply(1.25)); + clock_.AdvanceTime(1.25 * rtt_stats_.latest_rtt()); QuicPacketNumber lost[] = {1}; VerifyLosses(2, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -140,7 +140,7 @@ SendDataPacket(i); // Advance the time 1/4 RTT between 3 and 4. if (i == 3) { - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25)); + clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); } } @@ -152,15 +152,15 @@ VerifyLosses(kNumSentPackets, lost, arraysize(lost)); // The time has already advanced 1/4 an RTT, so ensure the timeout is set // 1.25 RTTs after the earliest pending packet(3), not the last(4). - EXPECT_EQ(clock_.Now().Add(rtt_stats_.smoothed_rtt()), + EXPECT_EQ(clock_.Now() + rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); QuicPacketNumber lost2[] = {1, 2, 3}; VerifyLosses(kNumSentPackets, lost2, arraysize(lost2)); - EXPECT_EQ(clock_.Now().Add(rtt_stats_.smoothed_rtt().Multiply(0.25)), + EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25)); + clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); QuicPacketNumber lost3[] = {1, 2, 3, 4}; VerifyLosses(kNumSentPackets, lost3, arraysize(lost3)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -185,8 +185,8 @@ TEST_F(GeneralLossAlgorithmTest, AlwaysLosePacketSent1RTTEarlier) { // Transmit 1 packet and then wait an rtt plus 1ms. SendDataPacket(1); - clock_.AdvanceTime( - rtt_stats_.smoothed_rtt().Add(QuicTime::Delta::FromMilliseconds(1))); + clock_.AdvanceTime(rtt_stats_.smoothed_rtt() + + QuicTime::Delta::FromMilliseconds(1)); // Transmit 2 packets. SendDataPacket(2); @@ -212,8 +212,8 @@ for (size_t i = 1; i < 500; ++i) { VerifyLosses(2, nullptr, 0); } - EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(1.25), - loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); + EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); } TEST_F(GeneralLossAlgorithmTest, NoLossUntilTimeout) { @@ -222,7 +222,7 @@ // Transmit 10 packets at 1/10th an RTT interval. for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.1)); + clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt()); } // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -230,10 +230,10 @@ unacked_packets_.RemoveFromInFlight(2); VerifyLosses(2, nullptr, 0); // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(0.25), - loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); + EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); VerifyLosses(2, nullptr, 0); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25)); + clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); QuicPacketNumber lost[] = {1}; VerifyLosses(2, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -245,7 +245,7 @@ // Transmit 10 packets at 1/10th an RTT interval. for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.1)); + clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt()); } // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -254,7 +254,7 @@ VerifyLosses(1, nullptr, 0); // The timer should still not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25)); + clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); VerifyLosses(1, nullptr, 0); clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); VerifyLosses(1, nullptr, 0); @@ -276,9 +276,9 @@ unacked_packets_.RemoveFromInFlight(10); VerifyLosses(10, nullptr, 0); // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(0.25), - loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25)); + EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); QuicPacketNumber lost[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; VerifyLosses(10, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -300,9 +300,9 @@ unacked_packets_.RemoveFromInFlight(10); VerifyLosses(10, nullptr, 0); // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(0.25), - loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.25)); + EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); // Now ack packets 1 to 9 and ensure the timer is no longer set and no packets // are lost. for (QuicPacketNumber i = 1; i <= 9; ++i) { @@ -319,9 +319,9 @@ // Transmit 2 packets at 1/10th an RTT interval. for (size_t i = 1; i <= kNumSentPackets; ++i) { SendDataPacket(i); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(0.1)); + clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt()); } - EXPECT_EQ(QuicTime::Zero().Add(rtt_stats_.smoothed_rtt()), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + rtt_stats_.smoothed_rtt(), clock_.Now()); // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -329,10 +329,10 @@ unacked_packets_.RemoveFromInFlight(2); VerifyLosses(2, nullptr, 0); // Expect the timer to be set to 1/16 RTT's in the future. - EXPECT_EQ(rtt_stats_.smoothed_rtt().Multiply(1.0f / 16), - loss_algorithm_.GetLossTimeout().Subtract(clock_.Now())); + EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16), + loss_algorithm_.GetLossTimeout() - clock_.Now()); VerifyLosses(2, nullptr, 0); - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(1.0f / 16)); + clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16)); QuicPacketNumber lost[] = {1}; VerifyLosses(2, lost, arraysize(lost)); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -342,7 +342,7 @@ // Advance the time 1/4 RTT and indicate the loss was spurious. // The new threshold should be 1/2 RTT. - clock_.AdvanceTime(rtt_stats_.smoothed_rtt().Multiply(1.0f / 4)); + clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4)); loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(), rtt_stats_, 11); EXPECT_EQ(1, loss_algorithm_.reordering_shift());
diff --git a/net/quic/congestion_control/hybrid_slow_start.cc b/net/quic/congestion_control/hybrid_slow_start.cc index 5f334c7..6774396 100644 --- a/net/quic/congestion_control/hybrid_slow_start.cc +++ b/net/quic/congestion_control/hybrid_slow_start.cc
@@ -94,7 +94,7 @@ QuicTime::Delta::FromMicroseconds(max(min_rtt_increase_threshold_us, kHybridStartDelayMinThresholdUs)); - if (current_min_rtt_ > min_rtt.Add(min_rtt_increase_threshold)) { + if (current_min_rtt_ > min_rtt + min_rtt_increase_threshold) { hystart_found_ = DELAY; } }
diff --git a/net/quic/congestion_control/hybrid_slow_start_test.cc b/net/quic/congestion_control/hybrid_slow_start_test.cc index 0e8c934..18601af 100644 --- a/net/quic/congestion_control/hybrid_slow_start_test.cc +++ b/net/quic/congestion_control/hybrid_slow_start_test.cc
@@ -59,17 +59,17 @@ // term RTT provided. for (int n = 0; n < kHybridStartMinSamples; ++n) { EXPECT_FALSE(slow_start_->ShouldExitSlowStart( - rtt_.Add(QuicTime::Delta::FromMilliseconds(n)), rtt_, 100)); + rtt_ + QuicTime::Delta::FromMilliseconds(n), rtt_, 100)); } slow_start_->StartReceiveRound(end_packet_number++); for (int n = 1; n < kHybridStartMinSamples; ++n) { EXPECT_FALSE(slow_start_->ShouldExitSlowStart( - rtt_.Add(QuicTime::Delta::FromMilliseconds(n + 10)), rtt_, 100)); + rtt_ + QuicTime::Delta::FromMilliseconds(n + 10), rtt_, 100)); } // Expect to trigger since all packets in this burst was above the long term // RTT provided. EXPECT_TRUE(slow_start_->ShouldExitSlowStart( - rtt_.Add(QuicTime::Delta::FromMilliseconds(10)), rtt_, 100)); + rtt_ + QuicTime::Delta::FromMilliseconds(10), rtt_, 100)); } } // namespace test
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc index e18183f..7f366c9 100644 --- a/net/quic/congestion_control/pacing_sender.cc +++ b/net/quic/congestion_control/pacing_sender.cc
@@ -40,10 +40,6 @@ sender_->SetNumEmulatedConnections(num_connections); } -void PacingSender::SetMaxCongestionWindow(QuicByteCount max_congestion_window) { - sender_->SetMaxCongestionWindow(max_congestion_window); -} - void PacingSender::SetMaxPacingRate(QuicBandwidth max_pacing_rate) { max_pacing_rate_ = max_pacing_rate; } @@ -95,12 +91,12 @@ // If the last send was delayed, and the alarm took a long time to get // invoked, allow the connection to make up for lost time. if (was_last_send_delayed_) { - ideal_next_packet_send_time_ = ideal_next_packet_send_time_.Add(delay); + ideal_next_packet_send_time_ = ideal_next_packet_send_time_ + delay; // The send was application limited if it takes longer than the // pacing delay between sent packets. const bool application_limited = last_delayed_packet_sent_time_.IsInitialized() && - sent_time > last_delayed_packet_sent_time_.Add(delay); + sent_time > last_delayed_packet_sent_time_ + delay; const bool making_up_for_lost_time = ideal_next_packet_send_time_ <= sent_time; // As long as we're making up time and not application limited, @@ -113,8 +109,8 @@ last_delayed_packet_sent_time_ = QuicTime::Zero(); } } else { - ideal_next_packet_send_time_ = QuicTime::Max( - ideal_next_packet_send_time_.Add(delay), sent_time.Add(delay)); + ideal_next_packet_send_time_ = + QuicTime::Max(ideal_next_packet_send_time_ + delay, sent_time + delay); } return in_flight; } @@ -144,11 +140,11 @@ } // If the next send time is within the alarm granularity, send immediately. - if (ideal_next_packet_send_time_ > now.Add(alarm_granularity_)) { + if (ideal_next_packet_send_time_ > now + alarm_granularity_) { DVLOG(1) << "Delaying packet: " - << ideal_next_packet_send_time_.Subtract(now).ToMicroseconds(); + << (ideal_next_packet_send_time_ - now).ToMicroseconds(); was_last_send_delayed_ = true; - return ideal_next_packet_send_time_.Subtract(now); + return ideal_next_packet_send_time_ - now; } DVLOG(1) << "Sending packet now";
diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h index 207901ed..e587aca 100644 --- a/net/quic/congestion_control/pacing_sender.h +++ b/net/quic/congestion_control/pacing_sender.h
@@ -45,7 +45,6 @@ const CachedNetworkParameters& cached_network_params, bool max_bandwidth_resumption) override; void SetNumEmulatedConnections(int num_connections) override; - void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override; void OnCongestionEvent(bool rtt_updated, QuicByteCount bytes_in_flight, const CongestionVector& acked_packets,
diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc index fbcbaa19..c531a59a 100644 --- a/net/quic/congestion_control/pacing_sender_test.cc +++ b/net/quic/congestion_control/pacing_sender_test.cc
@@ -354,9 +354,6 @@ EXPECT_CALL(*mock_sender_, SetNumEmulatedConnections(2)); pacing_sender_->SetNumEmulatedConnections(2); - EXPECT_CALL(*mock_sender_, SetMaxCongestionWindow(kBytes)); - pacing_sender_->SetMaxCongestionWindow(kBytes); - SendAlgorithmInterface::CongestionVector packets; EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kBytes, packets, packets)); pacing_sender_->OnCongestionEvent(true, kBytes, packets, packets);
diff --git a/net/quic/congestion_control/rtt_stats.cc b/net/quic/congestion_control/rtt_stats.cc index 4809f1a..86eb3ab 100644 --- a/net/quic/congestion_control/rtt_stats.cc +++ b/net/quic/congestion_control/rtt_stats.cc
@@ -37,7 +37,8 @@ num_samples_for_forced_min_(0), windowed_min_rtt_( QuicTime::Delta::FromMilliseconds(kMinRttWindowLengthMs), - QuicTime::Delta::Zero()) {} + QuicTime::Delta::Zero(), + QuicTime::Zero()) {} void RttStats::SampleNewWindowedMinRtt(uint32_t num_samples) { num_samples_for_forced_min_ = num_samples; @@ -46,10 +47,9 @@ } void RttStats::ExpireSmoothedMetrics() { - mean_deviation_ = - max(mean_deviation_, - QuicTime::Delta::FromMicroseconds( - std::abs(smoothed_rtt_.Subtract(latest_rtt_).ToMicroseconds()))); + mean_deviation_ = max(mean_deviation_, + QuicTime::Delta::FromMicroseconds(std::abs( + (smoothed_rtt_ - latest_rtt_).ToMicroseconds()))); smoothed_rtt_ = max(smoothed_rtt_, latest_rtt_); } @@ -80,7 +80,7 @@ previous_srtt_ = smoothed_rtt_; if (rtt_sample > ack_delay) { - rtt_sample = rtt_sample.Subtract(ack_delay); + rtt_sample = rtt_sample - ack_delay; } latest_rtt_ = rtt_sample; // First time call. @@ -91,9 +91,8 @@ } else { mean_deviation_ = QuicTime::Delta::FromMicroseconds(static_cast<int64_t>( kOneMinusBeta * mean_deviation_.ToMicroseconds() + - kBeta * std::abs(smoothed_rtt_.Subtract(rtt_sample).ToMicroseconds()))); - smoothed_rtt_ = - smoothed_rtt_.Multiply(kOneMinusAlpha).Add(rtt_sample.Multiply(kAlpha)); + kBeta * std::abs((smoothed_rtt_ - rtt_sample).ToMicroseconds()))); + smoothed_rtt_ = kOneMinusAlpha * smoothed_rtt_ + kAlpha * rtt_sample; DVLOG(1) << " smoothed_rtt(us):" << smoothed_rtt_.ToMicroseconds() << " mean_deviation(us):" << mean_deviation_.ToMicroseconds(); }
diff --git a/net/quic/congestion_control/rtt_stats.h b/net/quic/congestion_control/rtt_stats.h index ac15149..009f07ec 100644 --- a/net/quic/congestion_control/rtt_stats.h +++ b/net/quic/congestion_control/rtt_stats.h
@@ -99,7 +99,11 @@ uint32_t num_samples_for_forced_min_; // Windowed min_rtt. - WindowedFilter<QuicTime::Delta, MinFilter<QuicTime::Delta>> windowed_min_rtt_; + WindowedFilter<QuicTime::Delta, + MinFilter<QuicTime::Delta>, + QuicTime, + QuicTime::Delta> + windowed_min_rtt_; DISALLOW_COPY_AND_ASSIGN(RttStats); };
diff --git a/net/quic/congestion_control/rtt_stats_test.cc b/net/quic/congestion_control/rtt_stats_test.cc index 9a25946..1402883 100644 --- a/net/quic/congestion_control/rtt_stats_test.cc +++ b/net/quic/congestion_control/rtt_stats_test.cc
@@ -78,29 +78,29 @@ rtt_stats_.WindowedMinRtt()); rtt_stats_.UpdateRtt( QuicTime::Delta::FromMilliseconds(10), QuicTime::Delta::Zero(), - QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(10))); + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(10)); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.WindowedMinRtt()); rtt_stats_.UpdateRtt( QuicTime::Delta::FromMilliseconds(50), QuicTime::Delta::Zero(), - QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(20))); + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(20)); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.WindowedMinRtt()); rtt_stats_.UpdateRtt( QuicTime::Delta::FromMilliseconds(50), QuicTime::Delta::Zero(), - QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(30))); + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(30)); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.WindowedMinRtt()); rtt_stats_.UpdateRtt( QuicTime::Delta::FromMilliseconds(50), QuicTime::Delta::Zero(), - QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(40))); + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(40)); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.WindowedMinRtt()); // Verify that ack_delay does not go into recording of min_rtt_. rtt_stats_.UpdateRtt( QuicTime::Delta::FromMilliseconds(7), QuicTime::Delta::FromMilliseconds(2), - QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(50))); + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(50)); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(7), rtt_stats_.min_rtt()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(7), rtt_stats_.WindowedMinRtt()); } @@ -132,21 +132,21 @@ EXPECT_EQ(initial_rtt, rtt_stats_.WindowedMinRtt()); EXPECT_EQ(initial_rtt, rtt_stats_.smoothed_rtt()); - EXPECT_EQ(initial_rtt.Multiply(0.5), rtt_stats_.mean_deviation()); + EXPECT_EQ(0.5 * initial_rtt, rtt_stats_.mean_deviation()); // Update once with a 20ms RTT. - QuicTime::Delta doubled_rtt = initial_rtt.Multiply(2); + QuicTime::Delta doubled_rtt = 2 * initial_rtt; rtt_stats_.UpdateRtt(doubled_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); - EXPECT_EQ(initial_rtt.Multiply(1.125), rtt_stats_.smoothed_rtt()); + EXPECT_EQ(1.125 * initial_rtt, rtt_stats_.smoothed_rtt()); // Expire the smoothed metrics, increasing smoothed rtt and mean deviation. rtt_stats_.ExpireSmoothedMetrics(); EXPECT_EQ(doubled_rtt, rtt_stats_.smoothed_rtt()); - EXPECT_EQ(initial_rtt.Multiply(0.875), rtt_stats_.mean_deviation()); + EXPECT_EQ(0.875 * initial_rtt, rtt_stats_.mean_deviation()); // Now go back down to 5ms and expire the smoothed metrics, and ensure the // mean deviation increases to 15ms. - QuicTime::Delta half_rtt = initial_rtt.Multiply(0.5); + QuicTime::Delta half_rtt = 0.5 * initial_rtt; rtt_stats_.UpdateRtt(half_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); EXPECT_GT(doubled_rtt, rtt_stats_.smoothed_rtt()); EXPECT_LT(initial_rtt, rtt_stats_.mean_deviation());
diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc index 821beb7..205e15c 100644 --- a/net/quic/congestion_control/send_algorithm_interface.cc +++ b/net/quic/congestion_control/send_algorithm_interface.cc
@@ -20,12 +20,7 @@ CongestionControlType congestion_control_type, QuicConnectionStats* stats, QuicPacketCount initial_congestion_window) { - QuicPacketCount max_congestion_window = - (kDefaultSocketReceiveBuffer * kConservativeReceiveBufferFraction) / - kDefaultTCPMSS; - if (FLAGS_quic_ignore_srbf) { - max_congestion_window = kDefaultMaxCongestionWindowPackets; - } + QuicPacketCount max_congestion_window = kDefaultMaxCongestionWindowPackets; switch (congestion_control_type) { case kCubic: return new TcpCubicSenderPackets(
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h index f711e76f..e6c0728 100644 --- a/net/quic/congestion_control/send_algorithm_interface.h +++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -47,9 +47,6 @@ // particularly for congestion avoidance. Can be set any time. virtual void SetNumEmulatedConnections(int num_connections) = 0; - // Sets the maximum congestion window in bytes. - virtual void SetMaxCongestionWindow(QuicByteCount max_congestion_window) = 0; - // Indicates an update to the congestion state, caused either by an incoming // ack or loss event timeout. |rtt_updated| indicates whether a new // latest_rtt sample has been taken, |byte_in_flight| the bytes in flight
diff --git a/net/quic/congestion_control/send_algorithm_simulator.cc b/net/quic/congestion_control/send_algorithm_simulator.cc index 46f7db36..bb1316f 100644 --- a/net/quic/congestion_control/send_algorithm_simulator.cc +++ b/net/quic/congestion_control/send_algorithm_simulator.cc
@@ -98,9 +98,9 @@ void SendAlgorithmSimulator::TransferBytes(QuicByteCount max_bytes, QuicTime::Delta max_time) { - const QuicTime end_time = - max_time.IsInfinite() ? QuicTime::Zero().Add(QuicTime::Delta::Infinite()) - : clock_->Now().Add(max_time); + const QuicTime end_time = max_time.IsInfinite() + ? QuicTime::Zero() + QuicTime::Delta::Infinite() + : clock_->Now() + max_time; QuicByteCount bytes_sent = 0; while (!pending_transfers_.empty() && clock_->Now() < end_time && bytes_sent < max_bytes) { @@ -145,7 +145,7 @@ continue; } // If the flow hasn't started, use the start time. - QuicTime::Delta transfer_send_time = it->start_time.Subtract(clock_->Now()); + QuicTime::Delta transfer_send_time = it->start_time - clock_->Now(); if (clock_->Now() >= it->start_time) { transfer_send_time = it->sender->send_algorithm->TimeUntilSend( clock_->Now(), it->bytes_in_flight); @@ -225,16 +225,16 @@ } DCHECK_LT(*next_acked, it->packet_number); // Consider a delayed ack for the current next_acked. - if (ack_delay < it->ack_time.Subtract(clock_->Now())) { + if (ack_delay < it->ack_time - clock_->Now()) { break; } *next_acked = it->packet_number; - ack_delay = it->ack_time.Subtract(clock_->Now()); + ack_delay = it->ack_time - clock_->Now(); if (HasRecentLostPackets(transfer, *next_acked) || (*next_acked - last_acked) >= 2) { break; } - ack_delay = ack_delay.Add(delayed_ack_timer_); + ack_delay = ack_delay + delayed_ack_timer_; } DVLOG(1) << "FindNextAck found next_acked_:" << transfer->sender->next_acked @@ -308,7 +308,7 @@ << largest_observed.send_time.ToDebuggingValue() << " to ack_time:" << largest_observed.ack_time.ToDebuggingValue(); QuicTime::Delta measured_rtt = - largest_observed.ack_time.Subtract(largest_observed.send_time); + largest_observed.ack_time - largest_observed.send_time; DCHECK_GE(measured_rtt.ToMicroseconds(), rtt_.ToMicroseconds()); sender->rtt_stats->UpdateRtt(measured_rtt, QuicTime::Delta::Zero(), clock_->Now()); @@ -324,8 +324,7 @@ transfer->bytes_lost += lost_packets.size() * kPacketSize; if (transfer->bytes_acked >= transfer->num_bytes) { // Remove completed transfers and record transfer bandwidth. - QuicTime::Delta transfer_time = - clock_->Now().Subtract(transfer->start_time); + QuicTime::Delta transfer_time = clock_->Now() - transfer->start_time; sender->last_transfer_loss_rate = static_cast<float>(transfer->bytes_lost) / (transfer->bytes_lost + transfer->bytes_acked); @@ -373,14 +372,14 @@ // If the number of bytes in flight are less than the bdp, there's // no buffering delay. Bytes lost from the buffer are not counted. QuicByteCount bdp = bandwidth_.ToBytesPerPeriod(rtt_); - QuicTime ack_time = clock_->Now().Add(rtt_).Add(sender->additional_rtt); + QuicTime ack_time = clock_->Now() + rtt_ + sender->additional_rtt; if (kPacketSize > bdp) { - ack_time = ack_time.Add(bandwidth_.TransferTime(kPacketSize - bdp)); + ack_time = ack_time + bandwidth_.TransferTime(kPacketSize - bdp); } QuicTime queue_ack_time = sent_packets_.empty() ? QuicTime::Zero() - : sent_packets_.back().ack_time.Add( - bandwidth_.TransferTime(kPacketSize)); + : sent_packets_.back().ack_time + + bandwidth_.TransferTime(kPacketSize); ack_time = QuicTime::Max(ack_time, queue_ack_time); sent_packets_.push_back(SentPacket(sender->last_sent, clock_->Now(), ack_time, packet_lost, transfer));
diff --git a/net/quic/congestion_control/tcp_cubic_sender_base.cc b/net/quic/congestion_control/tcp_cubic_sender_base.cc index 9ab49e92..539eadc 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_base.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_base.cc
@@ -243,8 +243,7 @@ if (rtt_stats_->smoothed_rtt().IsZero()) { return QuicTime::Delta::Zero(); } - return rtt_stats_->smoothed_rtt().Add( - rtt_stats_->mean_deviation().Multiply(4)); + return rtt_stats_->smoothed_rtt() + 4 * rtt_stats_->mean_deviation(); } bool TcpCubicSenderBase::InSlowStart() const {
diff --git a/net/quic/congestion_control/tcp_cubic_sender_bytes.cc b/net/quic/congestion_control/tcp_cubic_sender_bytes.cc index 012bf04..88f02e2 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_bytes.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_bytes.cc
@@ -80,12 +80,6 @@ cubic_.SetNumConnections(num_connections_); } -void TcpCubicSenderBytes::SetMaxCongestionWindow( - QuicByteCount max_congestion_window) { - DCHECK(!FLAGS_quic_ignore_srbf); - max_congestion_window_ = max_congestion_window; -} - void TcpCubicSenderBytes::ExitSlowstart() { slowstart_threshold_ = congestion_window_; } @@ -123,8 +117,7 @@ // TODO(jri): Separate out all of slow start into a separate class. if (slow_start_large_reduction_ && InSlowStart()) { DCHECK_LT(kDefaultTCPMSS, congestion_window_); - if (FLAGS_quic_sslr_limit_reduction && - congestion_window_ >= 2 * initial_tcp_congestion_window_) { + if (congestion_window_ >= 2 * initial_tcp_congestion_window_) { min_slow_start_exit_window_ = congestion_window_ / 2; } congestion_window_ = congestion_window_ - kDefaultTCPMSS;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_bytes.h b/net/quic/congestion_control/tcp_cubic_sender_bytes.h index e7a0765..375b572 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_bytes.h +++ b/net/quic/congestion_control/tcp_cubic_sender_bytes.h
@@ -40,7 +40,6 @@ // Start implementation of SendAlgorithmInterface. void SetNumEmulatedConnections(int num_connections) override; - void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override; void OnConnectionMigration() override; QuicByteCount GetCongestionWindow() const override; QuicByteCount GetSlowStartThreshold() const override;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc index 9c33e1d..6415172f 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -232,7 +232,6 @@ } TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLossWithLargeReduction) { - FLAGS_quic_sslr_limit_reduction = true; QuicConfig config; QuicTagVector options; options.push_back(kSSLR); @@ -327,7 +326,6 @@ } TEST_F(TcpCubicSenderBytesTest, SlowStartPacketLossWithMaxHalfReduction) { - FLAGS_quic_sslr_limit_reduction = true; QuicConfig config; QuicTagVector options; options.push_back(kSSLR); @@ -876,7 +874,6 @@ } TEST_F(TcpCubicSenderBytesTest, DefaultMaxCwnd) { - ValueRestore<bool> old_flag(&FLAGS_quic_ignore_srbf, true); RttStats rtt_stats; QuicConnectionStats stats; std::unique_ptr<SendAlgorithmInterface> sender(SendAlgorithmInterface::Create(
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets.cc b/net/quic/congestion_control/tcp_cubic_sender_packets.cc index 33960df..65dae271 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_packets.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_packets.cc
@@ -78,12 +78,6 @@ cubic_.SetNumConnections(num_connections_); } -void TcpCubicSenderPackets::SetMaxCongestionWindow( - QuicByteCount max_congestion_window) { - DCHECK(!FLAGS_quic_ignore_srbf); - max_tcp_congestion_window_ = max_congestion_window / kDefaultTCPMSS; -} - void TcpCubicSenderPackets::ExitSlowstart() { slowstart_threshold_ = congestion_window_; } @@ -125,8 +119,7 @@ // TODO(jri): Separate out all of slow start into a separate class. if (slow_start_large_reduction_ && InSlowStart()) { DCHECK_LT(1u, congestion_window_); - if (FLAGS_quic_sslr_limit_reduction && - congestion_window_ >= 2 * initial_tcp_congestion_window_) { + if (congestion_window_ >= 2 * initial_tcp_congestion_window_) { min_slow_start_exit_window_ = congestion_window_ / 2; } congestion_window_ = congestion_window_ - 1;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets.h b/net/quic/congestion_control/tcp_cubic_sender_packets.h index 610e75e1..2fe630f 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_packets.h +++ b/net/quic/congestion_control/tcp_cubic_sender_packets.h
@@ -42,7 +42,6 @@ // Start implementation of SendAlgorithmInterface. void SetNumEmulatedConnections(int num_connections) override; - void SetMaxCongestionWindow(QuicByteCount max_congestion_window) override; void OnConnectionMigration() override; QuicByteCount GetCongestionWindow() const override; QuicByteCount GetSlowStartThreshold() const override;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc index 91094a6..57cda3f 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -243,7 +243,6 @@ } TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossWithLargeReduction) { - FLAGS_quic_sslr_limit_reduction = true; QuicConfig config; QuicTagVector options; options.push_back(kSSLR); @@ -338,7 +337,6 @@ } TEST_F(TcpCubicSenderPacketsTest, SlowStartPacketLossWithMaxHalfReduction) { - FLAGS_quic_sslr_limit_reduction = true; QuicConfig config; QuicTagVector options; options.push_back(kSSLR); @@ -1028,7 +1026,6 @@ } TEST_F(TcpCubicSenderPacketsTest, DefaultMaxCwnd) { - ValueRestore<bool> old_flag(&FLAGS_quic_ignore_srbf, true); RttStats rtt_stats; QuicConnectionStats stats; std::unique_ptr<SendAlgorithmInterface> sender(SendAlgorithmInterface::Create(
diff --git a/net/quic/congestion_control/windowed_filter.h b/net/quic/congestion_control/windowed_filter.h index 9c2ce1a..50a6b1c 100644 --- a/net/quic/congestion_control/windowed_filter.h +++ b/net/quic/congestion_control/windowed_filter.h
@@ -51,29 +51,39 @@ }; // Use the following to construct a windowed filter object of type T. -// For a min filter: WindowedFilter<T, MinFilter<T>> ObjectName; -// For a max filter: WindowedFilter<T, MaxFilter<T>> ObjectName; -template <class T, class Compare> +// For example, a min filter using QuicTime as the time type: +// WindowedFilter<T, MinFilter<T>, QuicTime, QuicTime::Delta> ObjectName; +// A max filter using 64-bit integers as the time type: +// WindowedFilter<T, MaxFilter<T>, uint64_t, int64_t> ObjectName; +// Specifically, this template takes four arguments: +// 1. T -- type of the measurement that is being filtered. +// 2. Compare -- MinFilter<T> or MaxFilter<T>, depending on the type of filter +// desired. +// 3. TimeT -- the type used to represent timestamps. +// 4. TimeDeltaT -- the type used to represent continuous time intervals between +// two timestamps. Has to be the type of (a - b) if both |a| and |b| are +// of type TimeT. +template <class T, class Compare, typename TimeT, typename TimeDeltaT> class WindowedFilter { public: // |window_length| is the period after which a best estimate expires. // |zero_value| is used as the uninitialized value for objects of T. // Importantly, |zero_value| should be an invalid value for a true sample. - WindowedFilter(QuicTime::Delta window_length, T zero_value) + WindowedFilter(TimeDeltaT window_length, T zero_value, TimeT zero_time) : window_length_(window_length), zero_value_(zero_value), - estimates_{Sample(zero_value_, QuicTime::Zero()), - Sample(zero_value_, QuicTime::Zero()), - Sample(zero_value_, QuicTime::Zero())} {} + estimates_{Sample(zero_value_, zero_time), + Sample(zero_value_, zero_time), + Sample(zero_value_, zero_time)} {} // Updates best estimates with |sample|, and expires and updates best // estimates as necessary. - void Update(T new_sample, QuicTime new_time) { + void Update(T new_sample, TimeT new_time) { // Reset all estimates if they have not yet been initialized, if new sample // is a new best, or if the newest recorded estimate is too old. if (estimates_[0].sample == zero_value_ || Compare()(new_sample, estimates_[0].sample) || - new_time.Subtract(estimates_[2].time) > window_length_) { + new_time - estimates_[2].time > window_length_) { Reset(new_sample, new_time); return; } @@ -86,7 +96,7 @@ } // Expire and update estimates as necessary. - if (new_time.Subtract(estimates_[0].time) > window_length_) { + if (new_time - estimates_[0].time > window_length_) { // The best estimate hasn't been updated for an entire window, so promote // second and third best estimates. estimates_[0] = estimates_[1]; @@ -96,14 +106,14 @@ // outside the window as well, since it may also have been recorded a // long time ago. Don't need to iterate once more since we cover that // case at the beginning of the method. - if (new_time.Subtract(estimates_[0].time) > window_length_) { + if (new_time - estimates_[0].time > window_length_) { estimates_[0] = estimates_[1]; estimates_[1] = estimates_[2]; } return; } if (estimates_[1].sample == estimates_[0].sample && - new_time.Subtract(estimates_[1].time) > window_length_ >> 2) { + new_time - estimates_[1].time > window_length_ >> 2) { // A quarter of the window has passed without a better sample, so the // second-best estimate is taken from the second quarter of the window. estimates_[2] = estimates_[1] = Sample(new_sample, new_time); @@ -111,7 +121,7 @@ } if (estimates_[2].sample == estimates_[1].sample && - new_time.Subtract(estimates_[2].time) > window_length_ >> 1) { + new_time - estimates_[2].time > window_length_ >> 1) { // We've passed a half of the window without a better estimate, so take // a third-best estimate from the second half of the window. estimates_[2] = Sample(new_sample, new_time); @@ -119,7 +129,7 @@ } // Resets all estimates to new sample. - void Reset(T new_sample, QuicTime new_time) { + void Reset(T new_sample, TimeT new_time) { estimates_[0] = estimates_[1] = estimates_[2] = Sample(new_sample, new_time); } @@ -131,14 +141,14 @@ private: struct Sample { T sample; - QuicTime time; - Sample(T init_sample, QuicTime init_time) + TimeT time; + Sample(T init_sample, TimeT init_time) : sample(init_sample), time(init_time) {} }; - QuicTime::Delta window_length_; // Time length of window. - T zero_value_; // Uninitialized value of T. - Sample estimates_[3]; // Best estimate is element 0. + TimeDeltaT window_length_; // Time length of window. + T zero_value_; // Uninitialized value of T. + Sample estimates_[3]; // Best estimate is element 0. }; } // namespace net
diff --git a/net/quic/congestion_control/windowed_filter_test.cc b/net/quic/congestion_control/windowed_filter_test.cc index 25870b86..fd540d0c 100644 --- a/net/quic/congestion_control/windowed_filter_test.cc +++ b/net/quic/congestion_control/windowed_filter_test.cc
@@ -19,9 +19,11 @@ // Set the window to 99ms, so 25ms is more than a quarter rtt. WindowedFilterTest() : windowed_min_rtt_(QuicTime::Delta::FromMilliseconds(99), - QuicTime::Delta::Zero()), + QuicTime::Delta::Zero(), + QuicTime::Zero()), windowed_max_bw_(QuicTime::Delta::FromMilliseconds(99), - QuicBandwidth::Zero()) {} + QuicBandwidth::Zero(), + QuicTime::Zero()) {} // Sets up windowed_min_rtt_ to have the following values: // Best = 20ms, recorded at 25ms @@ -37,8 +39,8 @@ << " " << windowed_min_rtt_.GetBest().ToMilliseconds() << " " << windowed_min_rtt_.GetSecondBest().ToMilliseconds() << " " << windowed_min_rtt_.GetThirdBest().ToMilliseconds(); - now = now.Add(QuicTime::Delta::FromMilliseconds(25)); - rtt_sample = rtt_sample.Add(QuicTime::Delta::FromMilliseconds(10)); + now = now + QuicTime::Delta::FromMilliseconds(25); + rtt_sample = rtt_sample + QuicTime::Delta::FromMilliseconds(10); } EXPECT_EQ(QuicTime::Delta::FromMilliseconds(20), windowed_min_rtt_.GetBest()); @@ -62,7 +64,7 @@ << " " << windowed_max_bw_.GetBest().ToBitsPerSecond() << " " << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " " << windowed_max_bw_.GetThirdBest().ToBitsPerSecond(); - now = now.Add(QuicTime::Delta::FromMilliseconds(25)); + now = now + QuicTime::Delta::FromMilliseconds(25); bw_sample = bw_sample.Subtract(QuicBandwidth::FromBitsPerSecond(100)); } EXPECT_EQ(QuicBandwidth::FromBitsPerSecond(900), @@ -74,10 +76,31 @@ } protected: - WindowedFilter<QuicTime::Delta, MinFilter<QuicTime::Delta>> windowed_min_rtt_; - WindowedFilter<QuicBandwidth, MaxFilter<QuicBandwidth>> windowed_max_bw_; + WindowedFilter<QuicTime::Delta, + MinFilter<QuicTime::Delta>, + QuicTime, + QuicTime::Delta> + windowed_min_rtt_; + WindowedFilter<QuicBandwidth, + MaxFilter<QuicBandwidth>, + QuicTime, + QuicTime::Delta> + windowed_max_bw_; }; +namespace { +// Test helper function: updates the filter with a lot of small values in order +// to ensure that it is not susceptible to noise. +void UpdateWithIrrelevantSamples( + WindowedFilter<uint64_t, MaxFilter<uint64_t>, uint64_t, uint64_t>* filter, + uint64_t max_value, + uint64_t time) { + for (uint64_t i = 0; i < 1000; i++) { + filter->Update(i % max_value, time); + } +} +} // namespace + TEST_F(WindowedFilterTest, UninitializedEstimates) { EXPECT_EQ(QuicTime::Delta::Zero(), windowed_min_rtt_.GetBest()); EXPECT_EQ(QuicTime::Delta::Zero(), windowed_min_rtt_.GetSecondBest()); @@ -96,8 +119,8 @@ // Gradually increase the rtt samples and ensure the windowed min rtt starts // rising. for (int i = 0; i < 6; ++i) { - now = now.Add(QuicTime::Delta::FromMilliseconds(25)); - rtt_sample = rtt_sample.Add(QuicTime::Delta::FromMilliseconds(10)); + now = now + QuicTime::Delta::FromMilliseconds(25); + rtt_sample = rtt_sample + QuicTime::Delta::FromMilliseconds(10); windowed_min_rtt_.Update(rtt_sample, now); VLOG(1) << "i: " << i << " sample: " << rtt_sample.ToMilliseconds() << " mins: " @@ -126,7 +149,7 @@ // Gradually decrease the bw samples and ensure the windowed max bw starts // decreasing. for (int i = 0; i < 6; ++i) { - now = now.Add(QuicTime::Delta::FromMilliseconds(25)); + now = now + QuicTime::Delta::FromMilliseconds(25); bw_sample = bw_sample.Subtract(QuicBandwidth::FromBitsPerSecond(100)); windowed_max_bw_.Update(bw_sample, now); VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond() @@ -150,14 +173,15 @@ TEST_F(WindowedFilterTest, SampleChangesThirdBestMin) { InitializeMinFilter(); // RTT sample lower than the third-choice min-rtt sets that, but nothing else. - QuicTime::Delta rtt_sample = windowed_min_rtt_.GetThirdBest().Subtract( - QuicTime::Delta::FromMilliseconds(5)); + QuicTime::Delta rtt_sample = + windowed_min_rtt_.GetThirdBest() - QuicTime::Delta::FromMilliseconds(5); // This assert is necessary to avoid triggering -Wstrict-overflow // See crbug/616957 ASSERT_GT(windowed_min_rtt_.GetThirdBest(), QuicTime::Delta::FromMilliseconds(5)); // Latest sample was recorded at 100ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(101)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); + windowed_min_rtt_.Update(rtt_sample, now); windowed_min_rtt_.Update(rtt_sample, now); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest()); EXPECT_EQ(QuicTime::Delta::FromMilliseconds(40), @@ -171,7 +195,7 @@ QuicBandwidth bw_sample = windowed_max_bw_.GetThirdBest().Add(QuicBandwidth::FromBitsPerSecond(50)); // Latest sample was recorded at 100ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(101)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_max_bw_.Update(bw_sample, now); EXPECT_EQ(bw_sample, windowed_max_bw_.GetThirdBest()); EXPECT_EQ(QuicBandwidth::FromBitsPerSecond(700), @@ -183,14 +207,14 @@ InitializeMinFilter(); // RTT sample lower than the second-choice min sets that and also // the third-choice min. - QuicTime::Delta rtt_sample = windowed_min_rtt_.GetSecondBest().Subtract( - QuicTime::Delta::FromMilliseconds(5)); + QuicTime::Delta rtt_sample = + windowed_min_rtt_.GetSecondBest() - QuicTime::Delta::FromMilliseconds(5); // This assert is necessary to avoid triggering -Wstrict-overflow // See crbug/616957 ASSERT_GT(windowed_min_rtt_.GetSecondBest(), QuicTime::Delta::FromMilliseconds(5)); // Latest sample was recorded at 100ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(101)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_min_rtt_.Update(rtt_sample, now); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest()); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetSecondBest()); @@ -204,7 +228,7 @@ QuicBandwidth bw_sample = windowed_max_bw_.GetSecondBest().Add( QuicBandwidth::FromBitsPerSecond(50)); // Latest sample was recorded at 100ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(101)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_max_bw_.Update(bw_sample, now); EXPECT_EQ(bw_sample, windowed_max_bw_.GetThirdBest()); EXPECT_EQ(bw_sample, windowed_max_bw_.GetSecondBest()); @@ -215,13 +239,13 @@ InitializeMinFilter(); // RTT sample lower than the first-choice min-rtt sets that and also // the second and third-choice mins. - QuicTime::Delta rtt_sample = windowed_min_rtt_.GetBest().Subtract( - QuicTime::Delta::FromMilliseconds(5)); + QuicTime::Delta rtt_sample = + windowed_min_rtt_.GetBest() - QuicTime::Delta::FromMilliseconds(5); // This assert is necessary to avoid triggering -Wstrict-overflow // See crbug/616957 ASSERT_GT(windowed_min_rtt_.GetBest(), QuicTime::Delta::FromMilliseconds(5)); // Latest sample was recorded at 100ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(101)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_min_rtt_.Update(rtt_sample, now); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest()); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetSecondBest()); @@ -235,7 +259,7 @@ QuicBandwidth bw_sample = windowed_max_bw_.GetBest().Add(QuicBandwidth::FromBitsPerSecond(50)); // Latest sample was recorded at 100ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(101)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_max_bw_.Update(bw_sample, now); EXPECT_EQ(bw_sample, windowed_max_bw_.GetThirdBest()); EXPECT_EQ(bw_sample, windowed_max_bw_.GetSecondBest()); @@ -247,9 +271,9 @@ QuicTime::Delta old_third_best = windowed_min_rtt_.GetThirdBest(); QuicTime::Delta old_second_best = windowed_min_rtt_.GetSecondBest(); QuicTime::Delta rtt_sample = - old_third_best.Add(QuicTime::Delta::FromMilliseconds(5)); + old_third_best + QuicTime::Delta::FromMilliseconds(5); // Best min sample was recorded at 25ms, so expiry time is 124ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(125)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(125); windowed_min_rtt_.Update(rtt_sample, now); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest()); EXPECT_EQ(old_third_best, windowed_min_rtt_.GetSecondBest()); @@ -263,7 +287,7 @@ QuicBandwidth bw_sample = old_third_best.Subtract(QuicBandwidth::FromBitsPerSecond(50)); // Best max sample was recorded at 25ms, so expiry time is 124ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(125)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(125); windowed_max_bw_.Update(bw_sample, now); EXPECT_EQ(bw_sample, windowed_max_bw_.GetThirdBest()); EXPECT_EQ(old_third_best, windowed_max_bw_.GetSecondBest()); @@ -274,9 +298,9 @@ InitializeMinFilter(); QuicTime::Delta old_third_best = windowed_min_rtt_.GetThirdBest(); QuicTime::Delta rtt_sample = - old_third_best.Add(QuicTime::Delta::FromMilliseconds(5)); + old_third_best + QuicTime::Delta::FromMilliseconds(5); // Second best min sample was recorded at 75ms, so expiry time is 174ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(175)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(175); windowed_min_rtt_.Update(rtt_sample, now); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest()); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetSecondBest()); @@ -289,7 +313,7 @@ QuicBandwidth bw_sample = old_third_best.Subtract(QuicBandwidth::FromBitsPerSecond(50)); // Second best max sample was recorded at 75ms, so expiry time is 174ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(175)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(175); windowed_max_bw_.Update(bw_sample, now); EXPECT_EQ(bw_sample, windowed_max_bw_.GetThirdBest()); EXPECT_EQ(bw_sample, windowed_max_bw_.GetSecondBest()); @@ -298,15 +322,15 @@ TEST_F(WindowedFilterTest, ExpireAllMins) { InitializeMinFilter(); - QuicTime::Delta rtt_sample = windowed_min_rtt_.GetThirdBest().Add( - QuicTime::Delta::FromMilliseconds(5)); + QuicTime::Delta rtt_sample = + windowed_min_rtt_.GetThirdBest() + QuicTime::Delta::FromMilliseconds(5); // This assert is necessary to avoid triggering -Wstrict-overflow // See crbug/616957 ASSERT_LT(windowed_min_rtt_.GetThirdBest(), - QuicTime::Delta::Infinite().Subtract( - QuicTime::Delta::FromMilliseconds(5))); + QuicTime::Delta::Infinite() - QuicTime::Delta::FromMilliseconds(5)); + // Third best min sample was recorded at 100ms, so expiry time is 199ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(200)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(200); windowed_min_rtt_.Update(rtt_sample, now); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetThirdBest()); EXPECT_EQ(rtt_sample, windowed_min_rtt_.GetSecondBest()); @@ -318,13 +342,51 @@ QuicBandwidth bw_sample = windowed_max_bw_.GetThirdBest().Subtract( QuicBandwidth::FromBitsPerSecond(50)); // Third best max sample was recorded at 100ms, so expiry time is 199ms. - QuicTime now = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(200)); + QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(200); windowed_max_bw_.Update(bw_sample, now); EXPECT_EQ(bw_sample, windowed_max_bw_.GetThirdBest()); EXPECT_EQ(bw_sample, windowed_max_bw_.GetSecondBest()); EXPECT_EQ(bw_sample, windowed_max_bw_.GetBest()); } +// Test the windowed filter where the time used is an exact counter instead of a +// timestamp. This is useful if, for example, the time is measured in round +// trips. +TEST_F(WindowedFilterTest, ExpireCounterBasedMax) { + // Create a window which starts at t = 0 and expires after two cycles. + WindowedFilter<uint64_t, MaxFilter<uint64_t>, uint64_t, uint64_t> max_filter( + 2, 0, 0); + + // Insert 50000 at t = 1. + const uint64_t kBest = 50000; + max_filter.Update(50000, 1); + EXPECT_EQ(kBest, max_filter.GetBest()); + UpdateWithIrrelevantSamples(&max_filter, 20, 1); + EXPECT_EQ(kBest, max_filter.GetBest()); + + // Insert 40000 at t = 2. Nothing is expected to expire. + max_filter.Update(40000, 2); + EXPECT_EQ(kBest, max_filter.GetBest()); + UpdateWithIrrelevantSamples(&max_filter, 20, 2); + EXPECT_EQ(kBest, max_filter.GetBest()); + + // Insert 30000 at t = 3. Nothing is expected to expire yet. + max_filter.Update(30000, 3); + EXPECT_EQ(kBest, max_filter.GetBest()); + UpdateWithIrrelevantSamples(&max_filter, 20, 3); + EXPECT_EQ(kBest, max_filter.GetBest()); + VLOG(0) << max_filter.GetSecondBest(); + VLOG(0) << max_filter.GetThirdBest(); + + // Insert 20000 at t = 4. 50000 at t = 1 expires, so 40000 becomes the new + // maximum. + const uint64_t kNewBest = 40000; + max_filter.Update(20000, 4); + EXPECT_EQ(kNewBest, max_filter.GetBest()); + UpdateWithIrrelevantSamples(&max_filter, 20, 4); + EXPECT_EQ(kNewBest, max_filter.GetBest()); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h index 4c47af0..0b8ddcc 100644 --- a/net/quic/crypto/crypto_protocol.h +++ b/net/quic/crypto/crypto_protocol.h
@@ -126,6 +126,8 @@ const QuicTag kMTUH = TAG('M', 'T', 'U', 'H'); // High-target MTU discovery. const QuicTag kMTUL = TAG('M', 'T', 'U', 'L'); // Low-target MTU discovery. +const QuicTag kFHOL = TAG('F', 'H', 'O', 'L'); // Force head of line blocking. + // Proof types (i.e. certificate types) // NOTE: although it would be silly to do so, specifying both kX509 and kX59R // is allowed and is equivalent to specifying only kX509.
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc index 2e73826..91a4458b 100644 --- a/net/quic/crypto/crypto_server_test.cc +++ b/net/quic/crypto/crypto_server_test.cc
@@ -149,6 +149,7 @@ // clang-format off CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "PUBS", pub_hex_.c_str(), @@ -399,6 +400,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "SNI", kBadSNIs[i], "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), @@ -448,6 +450,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "PUBS", pub_hex_.c_str(), @@ -477,6 +480,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "PUBS", pub_hex_.c_str(), @@ -508,6 +512,7 @@ // clang-format off ShouldFailMentioning("too small", CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "VER\0", client_version_string_.c_str(), nullptr)); // clang-format on @@ -531,6 +536,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "STK", kBadSourceAddressTokens[i], "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); @@ -556,6 +562,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "NONC", kBadNonces[i], "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), @@ -570,6 +577,7 @@ // clang-format off CryptoHandshakeMessage msg1 = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -597,6 +605,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); @@ -610,6 +619,7 @@ // clang-format off CryptoHandshakeMessage msg1 = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -641,6 +651,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "VER\0", bad_version.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); @@ -656,6 +667,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", (string(1, 'X') + scid_hex_).c_str(), @@ -678,6 +690,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -701,6 +714,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -724,6 +738,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -758,6 +773,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -836,14 +852,15 @@ CryptoTestUtils::ProofVerifyContextForTesting()); std::unique_ptr<ProofVerifyDetails> details; string error_details; - DummyProofVerifierCallback callback; + std::unique_ptr<ProofVerifierCallback> callback( + new DummyProofVerifierCallback()); string chlo_hash; CryptoUtils::HashHandshakeMessage(msg, &chlo_hash); EXPECT_EQ(QUIC_SUCCESS, proof_verifier->VerifyProof( "test.example.com", 443, scfg_str.as_string(), client_version_, chlo_hash, certs, "", proof.as_string(), verify_context.get(), - &error_details, &details, &callback)); + &error_details, &details, std::move(callback))); } TEST_P(CryptoServerTest, RejectInvalidXlct) { @@ -854,6 +871,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -883,6 +901,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -909,6 +928,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -1021,6 +1041,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); @@ -1046,6 +1067,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -1070,6 +1092,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(), @@ -1115,6 +1138,7 @@ // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "SCID", scid_hex_.c_str(),
diff --git a/net/quic/crypto/proof_source.h b/net/quic/crypto/proof_source.h index 74b9df3c..a03c798f 100644 --- a/net/quic/crypto/proof_source.h +++ b/net/quic/crypto/proof_source.h
@@ -5,6 +5,7 @@ #ifndef NET_QUIC_CRYPTO_PROOF_SOURCE_H_ #define NET_QUIC_CRYPTO_PROOF_SOURCE_H_ +#include <memory> #include <string> #include <vector> @@ -35,9 +36,36 @@ DISALLOW_COPY_AND_ASSIGN(Chain); }; + // Callback base class for receiving the results of an async call to GetProof. + class Callback { + public: + Callback() {} + virtual ~Callback() {} + + // Invoked upon completion of GetProof. + // + // |ok| indicates whether the operation completed successfully. If false, + // the values of the remaining three arguments are undefined. + // + // |chain| is a reference-counted pointer to an object representing the + // certificate chain. + // + // |signature| contains the signature of the server config. + // + // |leaf_cert_sct| holds the signed timestamp (RFC6962) of the leaf cert. + virtual void Run(bool ok, + const scoped_refptr<Chain>& chain, + const std::string& signature, + const std::string& leaf_cert_sct) = 0; + + private: + Callback(const Callback&) = delete; + Callback& operator=(const Callback&) = delete; + }; + virtual ~ProofSource() {} - // GetProof finds a certificate chain for |hostname|, sets |out_certs| to + // GetProof finds a certificate chain for |hostname|, sets |out_chain| to // point to it (in leaf-first order), calculates a signature of // |server_config| using that chain and puts the result in |out_signature|. // @@ -52,13 +80,13 @@ // |out_chain| is reference counted to avoid the (assumed) expense of copying // out the certificates. // - // The number of certificate chains is expected to be small and fixed thus - // the ProofSource retains ownership of the contents of |out_certs|. The + // The number of certificate chains is expected to be small and fixed, thus + // the ProofSource retains ownership of the contents of |out_chain|. The // expectation is that they will be cached forever. // // For version before QUIC_VERSION_30, the signature values should be cached // because |server_config| will be somewhat static. However, since they aren't - // bounded, the ProofSource may wish to evicit entries from that cache, thus + // bounded, the ProofSource may wish to evict entries from that cache, thus // the caller takes ownership of |*out_signature|. // // For QUIC_VERSION_30 and later, the signature depends on |chlo_hash| @@ -70,6 +98,7 @@ // // |out_leaf_cert_sct| points to the signed timestamp (RFC6962) of the leaf // cert. + // // This function may be called concurrently. virtual bool GetProof(const IPAddress& server_ip, const std::string& hostname, @@ -80,6 +109,18 @@ scoped_refptr<Chain>* out_chain, std::string* out_signature, std::string* out_leaf_cert_sct) = 0; + + // Async version of GetProof with identical semantics, except that the results + // are delivered to |callback|. Callers should expect that |callback| might + // be invoked synchronously. The ProofSource takes ownership of |callback| in + // any case. + virtual void GetProof(const IPAddress& server_ip, + const std::string& hostname, + const std::string& server_config, + QuicVersion quic_version, + base::StringPiece chlo_hash, + bool ecdsa_ok, + std::unique_ptr<Callback> callback) = 0; }; } // namespace net
diff --git a/net/quic/crypto/proof_source_chromium.cc b/net/quic/crypto/proof_source_chromium.cc index 3a62346..a5c21c58 100644 --- a/net/quic/crypto/proof_source_chromium.cc +++ b/net/quic/crypto/proof_source_chromium.cc
@@ -151,4 +151,22 @@ return true; } +void ProofSourceChromium::GetProof(const IPAddress& server_ip, + const std::string& hostname, + const std::string& server_config, + QuicVersion quic_version, + base::StringPiece chlo_hash, + bool ecdsa_ok, + std::unique_ptr<Callback> callback) { + // As a transitional implementation, just call the synchronous version of + // GetProof, then invoke the callback with the results and destroy it. + scoped_refptr<ProofSource::Chain> chain; + string signature; + string leaf_cert_sct; + const bool ok = + GetProof(server_ip, hostname, server_config, quic_version, chlo_hash, + ecdsa_ok, &chain, &signature, &leaf_cert_sct); + callback->Run(ok, chain, signature, leaf_cert_sct); +} + } // namespace net
diff --git a/net/quic/crypto/proof_source_chromium.h b/net/quic/crypto/proof_source_chromium.h index f84746e..904bd0d 100644 --- a/net/quic/crypto/proof_source_chromium.h +++ b/net/quic/crypto/proof_source_chromium.h
@@ -43,6 +43,14 @@ std::string* out_signature, std::string* out_leaf_cert_sct) override; + void GetProof(const IPAddress& server_ip, + const std::string& hostname, + const std::string& server_config, + QuicVersion quic_version, + base::StringPiece chlo_hash, + bool ecdsa_ok, + std::unique_ptr<Callback> callback) override; + private: std::unique_ptr<crypto::RSAPrivateKey> private_key_; scoped_refptr<ProofSource::Chain> chain_;
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc index 697674c..1b95f65 100644 --- a/net/quic/crypto/proof_test.cc +++ b/net/quic/crypto/proof_test.cc
@@ -67,21 +67,19 @@ string error_details; std::unique_ptr<ProofVerifyContext> verify_context( CryptoTestUtils::ProofVerifyContextForTesting()); - TestProofVerifierCallback* callback = - new TestProofVerifierCallback(&comp_callback, &ok, &error_details); + std::unique_ptr<TestProofVerifierCallback> callback( + new TestProofVerifierCallback(&comp_callback, &ok, &error_details)); QuicAsyncStatus status = verifier->VerifyProof( hostname, port, server_config, quic_version, chlo_hash, certs, "", proof, - verify_context.get(), &error_details, &details, callback); + verify_context.get(), &error_details, &details, std::move(callback)); switch (status) { case QUIC_FAILURE: - delete callback; ASSERT_FALSE(expected_ok); ASSERT_NE("", error_details); return; case QUIC_SUCCESS: - delete callback; ASSERT_TRUE(expected_ok); ASSERT_EQ("", error_details); return; @@ -105,6 +103,38 @@ return der_bytes; } +class TestCallback : public ProofSource::Callback { + public: + explicit TestCallback(bool* called, + bool* ok, + scoped_refptr<ProofSource::Chain>* chain, + string* signature, + string* leaf_cert_sct) + : called_(called), + ok_(ok), + chain_(chain), + signature_(signature), + leaf_cert_sct_(leaf_cert_sct) {} + + void Run(bool ok, + const scoped_refptr<ProofSource::Chain>& chain, + const string& signature, + const string& leaf_cert_sct) override { + *ok_ = ok; + *chain_ = chain; + *signature_ = signature; + *leaf_cert_sct_ = leaf_cert_sct; + *called_ = true; + } + + private: + bool* called_; + bool* ok_; + scoped_refptr<ProofSource::Chain>* chain_; + string* signature_; + string* leaf_cert_sct_; +}; + class ProofTest : public ::testing::TestWithParam<QuicVersion> {}; } // namespace @@ -171,6 +201,43 @@ first_chlo_hash, wrong_certs, corrupt_signature, false); } +TEST_P(ProofTest, VerifySourceAsync) { + std::unique_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting()); + + const string server_config = "server config bytes"; + const string hostname = "test.example.com"; + const string first_chlo_hash = "first chlo hash bytes"; + const string second_chlo_hash = "first chlo hash bytes"; + const QuicVersion quic_version = GetParam(); + IPAddress server_ip; + + // Call synchronous version + scoped_refptr<ProofSource::Chain> expected_chain; + string expected_signature; + string expected_leaf_cert_sct; + ASSERT_TRUE(source->GetProof(server_ip, hostname, server_config, quic_version, + first_chlo_hash, false /* no ECDSA */, + &expected_chain, &expected_signature, + &expected_leaf_cert_sct)); + + // Call asynchronous version and compare results + bool called = false; + bool ok; + scoped_refptr<ProofSource::Chain> chain; + string signature; + string leaf_cert_sct; + std::unique_ptr<ProofSource::Callback> cb( + new TestCallback(&called, &ok, &chain, &signature, &leaf_cert_sct)); + source->GetProof(server_ip, hostname, server_config, quic_version, + first_chlo_hash, false /* no ECDSA */, std::move(cb)); + // TODO(gredner): whan GetProof really invokes the callback asynchronously, + // figure out what to do here. + ASSERT_TRUE(called); + ASSERT_TRUE(ok); + EXPECT_THAT(chain->certs, ::testing::ContainerEq(expected_chain->certs)); + EXPECT_EQ(leaf_cert_sct, expected_leaf_cert_sct); +} + TEST_P(ProofTest, UseAfterFree) { ProofSource* source = CryptoTestUtils::ProofSourceForTesting();
diff --git a/net/quic/crypto/proof_verifier.h b/net/quic/crypto/proof_verifier.h index fc520aa..d05e1dd 100644 --- a/net/quic/crypto/proof_verifier.h +++ b/net/quic/crypto/proof_verifier.h
@@ -70,7 +70,6 @@ // // This function may also return QUIC_PENDING, in which case the ProofVerifier // will call back, on the original thread, via |callback| when complete. - // In this case, the ProofVerifier will take ownership of |callback|. // // The signature uses SHA-256 as the hash function and PSS padding in the // case of RSA. @@ -86,7 +85,7 @@ const ProofVerifyContext* context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, - ProofVerifierCallback* callback) = 0; + std::unique_ptr<ProofVerifierCallback> callback) = 0; }; } // namespace net
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index 096374a..621eb1f 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -76,7 +76,7 @@ const std::string& signature, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* verify_details, - ProofVerifierCallback* callback); + std::unique_ptr<ProofVerifierCallback> callback); private: enum State { @@ -180,7 +180,7 @@ const string& signature, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* verify_details, - ProofVerifierCallback* callback) { + std::unique_ptr<ProofVerifierCallback> callback) { DCHECK(error_details); DCHECK(verify_details); DCHECK(callback); @@ -246,7 +246,7 @@ *verify_details = std::move(verify_details_); return QUIC_SUCCESS; case ERR_IO_PENDING: - callback_.reset(callback); + callback_ = std::move(callback); return QUIC_PENDING; default: *error_details = error_details_; @@ -491,7 +491,7 @@ const ProofVerifyContext* verify_context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* verify_details, - ProofVerifierCallback* callback) { + std::unique_ptr<ProofVerifierCallback> callback) { if (!verify_context) { *error_details = "Missing context"; return QUIC_FAILURE; @@ -504,7 +504,7 @@ chromium_context->cert_verify_flags, chromium_context->net_log)); QuicAsyncStatus status = job->VerifyProof( hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, - signature, error_details, verify_details, callback); + signature, error_details, verify_details, std::move(callback)); if (status == QUIC_PENDING) { active_jobs_.insert(job.release()); }
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h index fe84992e..b15751c 100644 --- a/net/quic/crypto/proof_verifier_chromium.h +++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -84,7 +84,7 @@ const ProofVerifyContext* verify_context, std::string* error_details, std::unique_ptr<ProofVerifyDetails>* verify_details, - ProofVerifierCallback* callback) override; + std::unique_ptr<ProofVerifierCallback> callback) override; private: class Job;
diff --git a/net/quic/crypto/proof_verifier_chromium_test.cc b/net/quic/crypto/proof_verifier_chromium_test.cc index ba881c6..fff1bf6d 100644 --- a/net/quic/crypto/proof_verifier_chromium_test.cc +++ b/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -233,7 +233,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); } @@ -252,7 +252,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, ct::GetSCTListForTesting(), "", verify_context_.get(), &error_details_, - &details_, callback.get()); + &details_, std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); CheckSCT(/*sct_expected_ok=*/true); } @@ -272,7 +272,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, ct::GetSCTListWithInvalidSCT(), "", verify_context_.get(), - &error_details_, &details_, callback.get()); + &error_details_, &details_, std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); CheckSCT(/*sct_expected_ok=*/false); } @@ -290,7 +290,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", kTestConfig, verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); } @@ -320,7 +320,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_SUCCESS, status); ASSERT_TRUE(details_.get()); @@ -356,7 +356,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_SUCCESS, status); ASSERT_TRUE(details_.get()); @@ -391,7 +391,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_SUCCESS, status); ASSERT_TRUE(details_.get()); @@ -436,7 +436,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); ASSERT_TRUE(details_.get()); @@ -477,7 +477,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_SUCCESS, status); ASSERT_TRUE(details_.get()); @@ -523,7 +523,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); ASSERT_TRUE(details_.get()); @@ -575,7 +575,7 @@ QuicAsyncStatus status = proof_verifier.VerifyProof( kTestHostname, kTestPort, kTestConfig, QUIC_VERSION_25, "", certs_, "", GetTestSignature(), verify_context_.get(), &error_details_, &details_, - callback.get()); + std::move(callback)); ASSERT_EQ(QUIC_FAILURE, status); ASSERT_TRUE(details_.get());
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc index 53c60c2..b31a737 100644 --- a/net/quic/crypto/quic_crypto_client_config.cc +++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -413,6 +413,7 @@ const QuicVersion preferred_version, const CachedState* cached, QuicRandom* rand, + bool demand_x509_proof, QuicCryptoNegotiatedParameters* out_params, CryptoHandshakeMessage* out) const { out->set_tag(kCHLO); @@ -429,10 +430,6 @@ out->SetStringPiece(kUAID, user_agent_id_); } - char proof_nonce[32]; - rand->RandBytes(proof_nonce, arraysize(proof_nonce)); - out->SetStringPiece(kNONP, StringPiece(proof_nonce, arraysize(proof_nonce))); - // Even though this is an inchoate CHLO, send the SCID so that // the STK can be validated by the server. const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); @@ -447,6 +444,14 @@ out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); } + if (!demand_x509_proof) { + return; + } + + char proof_nonce[32]; + rand->RandBytes(proof_nonce, arraysize(proof_nonce)); + out->SetStringPiece(kNONP, StringPiece(proof_nonce, arraysize(proof_nonce))); + if (disable_ecdsa_) { out->SetVector(kPDMD, QuicTagVector{kX59R}); } else { @@ -493,7 +498,7 @@ DCHECK(error_details != nullptr); FillInchoateClientHello(server_id, preferred_version, cached, rand, - out_params, out); + /* demand_x509_proof= */ true, out_params, out); const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); if (!scfg) {
diff --git a/net/quic/crypto/quic_crypto_client_config.h b/net/quic/crypto/quic_crypto_client_config.h index b306392..6a7a5c99 100644 --- a/net/quic/crypto/quic_crypto_client_config.h +++ b/net/quic/crypto/quic_crypto_client_config.h
@@ -210,11 +210,14 @@ // to store the cached certs that were sent as hints to the server in // |out_params->cached_certs|. |preferred_version| is the version of the // QUIC protocol that this client chose to use initially. This allows the - // server to detect downgrade attacks. + // server to detect downgrade attacks. If |demand_x509_proof| is true, + // then |out| will include an X509 proof demand, and the associated + // certificate related fields. void FillInchoateClientHello(const QuicServerId& server_id, const QuicVersion preferred_version, const CachedState* cached, QuicRandom* rand, + bool demand_x509_proof, QuicCryptoNegotiatedParameters* out_params, CryptoHandshakeMessage* out) const;
diff --git a/net/quic/crypto/quic_crypto_client_config_test.cc b/net/quic/crypto/quic_crypto_client_config_test.cc index d15f6b0c..8fb6e058 100644 --- a/net/quic/crypto/quic_crypto_client_config_test.cc +++ b/net/quic/crypto/quic_crypto_client_config_test.cc
@@ -158,7 +158,7 @@ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, - ¶ms, &msg); + /* demand_x509_proof= */ true, ¶ms, &msg); QuicTag cver; EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kVER, &cver)); @@ -184,7 +184,7 @@ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, - ¶ms, &msg); + /* demand_x509_proof= */ true, ¶ms, &msg); QuicTag pdmd; EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd)); @@ -210,7 +210,7 @@ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, - ¶ms, &msg); + /* demand_x509_proof= */ true, ¶ms, &msg); StringPiece scid; EXPECT_TRUE(msg.GetStringPiece(kSCID, &scid)); @@ -226,7 +226,7 @@ QuicServerId server_id("www.google.com", 443, PRIVACY_MODE_DISABLED); MockRandom rand; config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, - ¶ms, &msg); + /* demand_x509_proof= */ true, ¶ms, &msg); QuicTag pdmd; EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index df3a3ced..4f0e1144 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -604,6 +604,10 @@ bool x509_supported = false; bool x509_ecdsa_supported = false; ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); + if (!x509_supported && FLAGS_quic_require_x509) { + *error_details = "Missing or invalid PDMD"; + return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; + } DCHECK(proof_source_.get()); string chlo_hash; CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); @@ -1163,21 +1167,27 @@ const QuicCryptoNegotiatedParameters& params, const CachedNetworkParameters* cached_network_params, CryptoHandshakeMessage* out) const { - base::AutoLock locked(configs_lock_); + string serialized; + string source_address_token; + const CommonCertSets* common_cert_sets; + { + base::AutoLock locked(configs_lock_); + serialized = primary_config_->serialized; + common_cert_sets = primary_config_->common_cert_sets; + source_address_token = NewSourceAddressToken( + *primary_config_, previous_source_address_tokens, client_ip, rand, + clock->WallNow(), cached_network_params); + } + out->set_tag(kSCUP); - out->SetStringPiece(kSCFG, primary_config_->serialized); - out->SetStringPiece( - kSourceAddressTokenTag, - NewSourceAddressToken(*primary_config_.get(), - previous_source_address_tokens, client_ip, rand, - clock->WallNow(), cached_network_params)); + out->SetStringPiece(kSCFG, serialized); + out->SetStringPiece(kSourceAddressTokenTag, source_address_token); scoped_refptr<ProofSource::Chain> chain; string signature; string cert_sct; if (FLAGS_quic_use_hash_in_scup) { - if (!proof_source_->GetProof(server_ip, params.sni, - primary_config_->serialized, version, + if (!proof_source_->GetProof(server_ip, params.sni, serialized, version, chlo_hash, params.x509_ecdsa_supported, &chain, &signature, &cert_sct)) { DVLOG(1) << "Server: failed to get proof."; @@ -1185,9 +1195,8 @@ } } else { if (!proof_source_->GetProof( - server_ip, params.sni, primary_config_->serialized, version, - params.client_nonce, params.x509_ecdsa_supported, &chain, - &signature, &cert_sct)) { + server_ip, params.sni, serialized, version, params.client_nonce, + params.x509_ecdsa_supported, &chain, &signature, &cert_sct)) { DVLOG(1) << "Server: failed to get proof."; return false; } @@ -1195,7 +1204,7 @@ const string compressed = CompressChain( compressed_certs_cache, chain, params.client_common_set_hashes, - params.client_cached_cert_hashes, primary_config_->common_cert_sets); + params.client_cached_cert_hashes, common_cert_sets); out->SetStringPiece(kCertificateTag, compressed); out->SetStringPiece(kPROF, signature); @@ -1249,7 +1258,8 @@ bool x509_supported = false; ParseProofDemand(client_hello, &x509_supported, ¶ms->x509_ecdsa_supported); - if (!x509_supported) { + if (!x509_supported && FLAGS_quic_require_x509) { + QUIC_BUG << "x509 certificates not supported in proof demand"; return; }
diff --git a/net/quic/quic_alarm.cc b/net/quic/quic_alarm.cc index 30edcaa..3067a29 100644 --- a/net/quic/quic_alarm.cc +++ b/net/quic/quic_alarm.cc
@@ -35,7 +35,7 @@ Cancel(); return; } - if (std::abs(new_deadline.Subtract(deadline_).ToMicroseconds()) < + if (std::abs((new_deadline - deadline_).ToMicroseconds()) < granularity.ToMicroseconds()) { return; }
diff --git a/net/quic/quic_alarm_test.cc b/net/quic/quic_alarm_test.cc index 0509090..fb6ef5c 100644 --- a/net/quic/quic_alarm_test.cc +++ b/net/quic/quic_alarm_test.cc
@@ -80,8 +80,8 @@ QuicAlarmTest() : delegate_(new MockDelegate()), alarm_(delegate_), - deadline_(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7))), - deadline2_(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(14))), + deadline_(QuicTime::Zero() + QuicTime::Delta::FromSeconds(7)), + deadline2_(QuicTime::Zero() + QuicTime::Delta::FromSeconds(14)), new_deadline_(QuicTime::Zero()) {} void ResetAlarm() { alarm_.Set(new_deadline_); } @@ -98,7 +98,7 @@ } TEST_F(QuicAlarmTest, Set) { - QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); + QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7); alarm_.Set(deadline); EXPECT_TRUE(alarm_.IsSet()); EXPECT_TRUE(alarm_.scheduled()); @@ -106,7 +106,7 @@ } TEST_F(QuicAlarmTest, Cancel) { - QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); + QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7); alarm_.Set(deadline); alarm_.Cancel(); EXPECT_FALSE(alarm_.IsSet()); @@ -115,9 +115,9 @@ } TEST_F(QuicAlarmTest, Update) { - QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); + QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7); alarm_.Set(deadline); - QuicTime new_deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(8)); + QuicTime new_deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(8); alarm_.Update(new_deadline, QuicTime::Delta::Zero()); EXPECT_TRUE(alarm_.IsSet()); EXPECT_TRUE(alarm_.scheduled()); @@ -125,7 +125,7 @@ } TEST_F(QuicAlarmTest, UpdateWithZero) { - QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); + QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7); alarm_.Set(deadline); alarm_.Update(QuicTime::Zero(), QuicTime::Delta::Zero()); EXPECT_FALSE(alarm_.IsSet()); @@ -134,7 +134,7 @@ } TEST_F(QuicAlarmTest, Fire) { - QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); + QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7); alarm_.Set(deadline); alarm_.FireAlarm(); EXPECT_FALSE(alarm_.IsSet()); @@ -157,7 +157,7 @@ DestructiveDelegate* delegate(new DestructiveDelegate); DestructiveAlarm* alarm = new DestructiveAlarm(delegate); delegate->set_alarm(alarm); - QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7)); + QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7); alarm->Set(deadline); // This should not crash, even though it will destroy alarm. alarm->FireAlarm();
diff --git a/net/quic/quic_buffered_packet_store.cc b/net/quic/quic_buffered_packet_store.cc index 5d6b88056..c5771de 100644 --- a/net/quic/quic_buffered_packet_store.cc +++ b/net/quic/quic_buffered_packet_store.cc
@@ -109,7 +109,7 @@ queue.buffered_packets.push_back(std::move(new_entry)); if (!expiration_alarm_->IsSet()) { - expiration_alarm_->Set(clock_->ApproximateNow().Add(connection_life_span_)); + expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_); } return SUCCESS; } @@ -131,8 +131,7 @@ } void QuicBufferedPacketStore::OnExpirationTimeout() { - QuicTime expiration_time = - clock_->ApproximateNow().Subtract(connection_life_span_); + QuicTime expiration_time = clock_->ApproximateNow() - connection_life_span_; while (!undecryptable_packets_.empty()) { auto& entry = undecryptable_packets_.front(); if (entry.second.creation_time > expiration_time) { @@ -142,7 +141,7 @@ undecryptable_packets_.erase(undecryptable_packets_.begin()); } if (!undecryptable_packets_.empty()) { - expiration_alarm_->Set(clock_->ApproximateNow().Add(connection_life_span_)); + expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_); } }
diff --git a/net/quic/quic_buffered_packet_store_test.cc b/net/quic/quic_buffered_packet_store_test.cc index 84f22f0f..ba0b25f 100644 --- a/net/quic/quic_buffered_packet_store_test.cc +++ b/net/quic/quic_buffered_packet_store_test.cc
@@ -59,8 +59,7 @@ server_address_(Loopback6(), 65535), client_address_(Loopback6(), 65535), packet_content_("some encrypted content"), - packet_time_( - QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(42))), + packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)), data_packet_(packet_content_.data(), packet_content_.size(), packet_time_) {} @@ -190,9 +189,9 @@ store_.EnqueuePacket(connection_id2, data_packet_, server_address_, another_client_address); // Advance clock to the time when connection 1 expires. - clock_.AdvanceTime(QuicBufferedPacketStorePeer::expiration_alarm(&store_) - ->deadline() - .Subtract(clock_.ApproximateNow())); + clock_.AdvanceTime( + QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() - + clock_.ApproximateNow()); ASSERT_GE(clock_.ApproximateNow(), QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline()); // Fire alarm to remove long-staying connection 1 packets. @@ -217,9 +216,9 @@ client_address_); store_.EnqueuePacket(connection_id3, data_packet_, server_address_, client_address_); - clock_.AdvanceTime(QuicBufferedPacketStorePeer::expiration_alarm(&store_) - ->deadline() - .Subtract(clock_.ApproximateNow())); + clock_.AdvanceTime( + QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() - + clock_.ApproximateNow()); alarm_factory_.FireAlarm( QuicBufferedPacketStorePeer::expiration_alarm(&store_)); // |last_expired_packet_queue_| should be updated.
diff --git a/net/quic/quic_chromium_alarm_factory.cc b/net/quic/quic_chromium_alarm_factory.cc index 8973b97..05b8e6e1 100644 --- a/net/quic/quic_chromium_alarm_factory.cc +++ b/net/quic/quic_chromium_alarm_factory.cc
@@ -41,7 +41,7 @@ weak_factory_.InvalidateWeakPtrs(); } - int64_t delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds(); + int64_t delay_us = (deadline() - (clock_->Now())).ToMicroseconds(); if (delay_us < 0) { delay_us = 0; }
diff --git a/net/quic/quic_chromium_alarm_factory_test.cc b/net/quic/quic_chromium_alarm_factory_test.cc index d47c98e..62c56790 100644 --- a/net/quic/quic_chromium_alarm_factory_test.cc +++ b/net/quic/quic_chromium_alarm_factory_test.cc
@@ -41,7 +41,7 @@ std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate)); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); // Verify that the alarm task has been posted. ASSERT_EQ(1u, runner_->GetPostedTasks().size()); @@ -49,7 +49,7 @@ runner_->GetPostedTasks()[0].delay); runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + delta, clock_.Now()); EXPECT_TRUE(delegate->fired()); } @@ -58,7 +58,7 @@ std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate)); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); alarm->Cancel(); // The alarm task should still be posted. @@ -67,7 +67,7 @@ runner_->GetPostedTasks()[0].delay); runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + delta, clock_.Now()); EXPECT_FALSE(delegate->fired()); } @@ -76,10 +76,10 @@ std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate)); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); alarm->Cancel(); QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Set(clock_.Now().Add(new_delta)); + alarm->Set(clock_.Now() + new_delta); // The alarm task should still be posted. ASSERT_EQ(1u, runner_->GetPostedTasks().size()); @@ -87,14 +87,14 @@ runner_->GetPostedTasks()[0].delay); runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + delta, clock_.Now()); EXPECT_FALSE(delegate->fired()); // The alarm task should be posted again. ASSERT_EQ(1u, runner_->GetPostedTasks().size()); runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + new_delta, clock_.Now()); EXPECT_TRUE(delegate->fired()); } @@ -103,17 +103,17 @@ std::unique_ptr<QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate)); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); alarm->Cancel(); QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(new_delta)); + alarm->Set(clock_.Now() + new_delta); // Both alarm tasks will be posted. ASSERT_EQ(2u, runner_->GetPostedTasks().size()); // The earlier task will execute and will fire the alarm-> runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + new_delta, clock_.Now()); EXPECT_TRUE(delegate->fired()); delegate->Clear(); @@ -123,7 +123,7 @@ // When the latter task is executed, the weak ptr will be invalid and // the alarm will not fire. runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + delta, clock_.Now()); EXPECT_FALSE(delegate->fired()); } @@ -133,10 +133,9 @@ QuicTime start = clock_.Now(); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Update(clock_.Now().Add(new_delta), - QuicTime::Delta::FromMicroseconds(1)); + alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1)); // The alarm task should still be posted. ASSERT_EQ(1u, runner_->GetPostedTasks().size()); @@ -144,25 +143,23 @@ runner_->GetPostedTasks()[0].delay); runner_->RunNextTask(); - EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); + EXPECT_EQ(QuicTime::Zero() + delta, clock_.Now()); EXPECT_FALSE(delegate->fired()); // Move the alarm forward 1us and ensure it doesn't move forward. - alarm->Update(clock_.Now().Add(new_delta), - QuicTime::Delta::FromMicroseconds(2)); + alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(2)); ASSERT_EQ(1u, runner_->GetPostedTasks().size()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds( - new_delta.Subtract(delta).ToMicroseconds()), - runner_->GetPostedTasks()[0].delay); + EXPECT_EQ( + base::TimeDelta::FromMicroseconds((new_delta - delta).ToMicroseconds()), + runner_->GetPostedTasks()[0].delay); runner_->RunNextTask(); - EXPECT_EQ(start.Add(new_delta), clock_.Now()); + EXPECT_EQ(start + new_delta, clock_.Now()); EXPECT_TRUE(delegate->fired()); // Set the alarm via an update call. new_delta = QuicTime::Delta::FromMicroseconds(5); - alarm->Update(clock_.Now().Add(new_delta), - QuicTime::Delta::FromMicroseconds(1)); + alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1)); EXPECT_TRUE(alarm->IsSet()); // Update it with an uninitialized time and ensure it's cancelled.
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index a10373a..f18ff5bc 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1057,7 +1057,7 @@ dict->SetString("version", QuicVersionToString(connection()->version())); dict->SetInteger("open_streams", GetNumOpenOutgoingStreams()); std::unique_ptr<base::ListValue> stream_list(new base::ListValue()); - for (StreamMap::const_iterator it = dynamic_streams().begin(); + for (DynamicStreamMap::const_iterator it = dynamic_streams().begin(); it != dynamic_streams().end(); ++it) { stream_list->AppendString(base::UintToString(it->second->id())); }
diff --git a/net/quic/quic_chromium_packet_reader.cc b/net/quic/quic_chromium_packet_reader.cc index dbd67a5..af9e7a5 100644 --- a/net/quic/quic_chromium_packet_reader.cc +++ b/net/quic/quic_chromium_packet_reader.cc
@@ -39,7 +39,7 @@ return; if (num_packets_read_ == 0) - yield_after_ = clock_->Now().Add(yield_after_duration_); + yield_after_ = clock_->Now() + yield_after_duration_; DCHECK(socket_); read_pending_ = true;
diff --git a/net/quic/quic_client_promised_info.cc b/net/quic/quic_client_promised_info.cc index 4de7adf..120db553 100644 --- a/net/quic/quic_client_promised_info.cc +++ b/net/quic/quic_client_promised_info.cc
@@ -32,8 +32,8 @@ cleanup_alarm_.reset(session_->connection()->alarm_factory()->CreateAlarm( new QuicClientPromisedInfo::CleanupAlarm(this))); cleanup_alarm_->Set( - session_->connection()->helper()->GetClock()->ApproximateNow().Add( - QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs))); + session_->connection()->helper()->GetClock()->ApproximateNow() + + QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs)); } void QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
diff --git a/net/quic/quic_client_session_base.cc b/net/quic/quic_client_session_base.cc index dff71e4..1d83ee39 100644 --- a/net/quic/quic_client_session_base.cc +++ b/net/quic/quic_client_session_base.cc
@@ -174,7 +174,7 @@ if (IsClosedStream(id)) { return nullptr; } - StreamMap::iterator it = dynamic_streams().find(id); + DynamicStreamMap::iterator it = dynamic_streams().find(id); if (it != dynamic_streams().end()) { return static_cast<QuicSpdyStream*>(it->second); }
diff --git a/net/quic/quic_clock.cc b/net/quic/quic_clock.cc index 6196bbb..673fe69d 100644 --- a/net/quic/quic_clock.cc +++ b/net/quic/quic_clock.cc
@@ -38,11 +38,11 @@ // result // // result = Now() - (WallNow() - walltime) - return Now().Subtract(QuicTime::Delta::FromMicroseconds( - WallNow() - .Subtract( - QuicTime::Delta::FromMicroseconds(walltime.ToUNIXMicroseconds())) - .ToUNIXMicroseconds())); + return Now() - QuicTime::Delta::FromMicroseconds( + WallNow() + .Subtract(QuicTime::Delta::FromMicroseconds( + walltime.ToUNIXMicroseconds())) + .ToUNIXMicroseconds()); } } // namespace net
diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc index 25e567c..516c32d 100644 --- a/net/quic/quic_config.cc +++ b/net/quic/quic_config.cc
@@ -417,7 +417,8 @@ socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL), multipath_enabled_(kMPTH, PRESENCE_OPTIONAL), connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL), - alternate_server_address_(kASAD, PRESENCE_OPTIONAL) { + alternate_server_address_(kASAD, PRESENCE_OPTIONAL), + force_hol_blocking_(kFHOL, PRESENCE_OPTIONAL) { SetDefaults(); } @@ -643,6 +644,18 @@ return alternate_server_address_.GetReceivedValue(); } +void QuicConfig::SetForceHolBlocking() { + force_hol_blocking_.SetSendValue(1); +} + +bool QuicConfig::ForceHolBlocking(Perspective perspective) const { + if (perspective == Perspective::IS_SERVER) { + return force_hol_blocking_.HasReceivedValue(); + } else { + return force_hol_blocking_.HasSendValue(); + } +} + bool QuicConfig::negotiated() const { // TODO(ianswett): Add the negotiated parameters once and iterate over all // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h index ddafce4..5baeb33 100644 --- a/net/quic/quic_config.h +++ b/net/quic/quic_config.h
@@ -386,6 +386,10 @@ const IPEndPoint& ReceivedAlternateServerAddress() const; + void SetForceHolBlocking(); + + bool ForceHolBlocking(Perspective perspective) const; + bool negotiated() const; // ToHandshakeMessage serialises the settings in this object as a series of @@ -445,6 +449,9 @@ // An alternate server address the client could connect to. QuicFixedIPEndPoint alternate_server_address_; + + // Force HOL blocking for measurement purposes. + QuicFixedUint32 force_hol_blocking_; }; } // namespace net
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index c529062..957cc399 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc
@@ -829,9 +829,9 @@ const char* QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) { if (incoming_ack.largest_observed > packet_generator_.packet_number()) { - LOG(WARNING) << ENDPOINT << "Peer's observed unsent packet:" - << incoming_ack.largest_observed << " vs " - << packet_generator_.packet_number(); + DLOG(WARNING) << ENDPOINT << "Peer's observed unsent packet:" + << incoming_ack.largest_observed << " vs " + << packet_generator_.packet_number(); // We got an error for data we have not sent. Error out. return "Largest observed too high."; } @@ -874,9 +874,9 @@ if (!sent_entropy_manager_.IsValidEntropy(incoming_ack.largest_observed, incoming_ack.packets, incoming_ack.entropy_hash)) { - LOG(WARNING) << ENDPOINT << "Peer sent invalid entropy." - << " largest_observed:" << incoming_ack.largest_observed - << " last_received:" << last_header_.packet_number; + DLOG(WARNING) << ENDPOINT << "Peer sent invalid entropy." + << " largest_observed:" << incoming_ack.largest_observed + << " last_received:" << last_header_.packet_number; return "Invalid entropy."; } } else { @@ -1065,10 +1065,9 @@ } else if (!ack_alarm_->IsSet()) { // Wait the minimum of a quarter min_rtt and the delayed ack time. QuicTime::Delta ack_delay = QuicTime::Delta::Min( - DelayedAckTime(), - sent_packet_manager_->GetRttStats()->min_rtt().Multiply( - ack_decimation_delay_)); - ack_alarm_->Set(clock_->ApproximateNow().Add(ack_delay)); + DelayedAckTime(), sent_packet_manager_->GetRttStats()->min_rtt() * + ack_decimation_delay_); + ack_alarm_->Set(clock_->ApproximateNow() + ack_delay); } } else { // Ack with a timer or every 2 packets by default. @@ -1076,7 +1075,7 @@ kDefaultRetransmittablePacketsBeforeAck) { ack_queued_ = true; } else if (!ack_alarm_->IsSet()) { - ack_alarm_->Set(clock_->ApproximateNow().Add(DelayedAckTime())); + ack_alarm_->Set(clock_->ApproximateNow() + DelayedAckTime()); } } @@ -1084,8 +1083,9 @@ if (received_packet_manager_.HasNewMissingPackets()) { if (ack_mode_ == ACK_DECIMATION_WITH_REORDERING) { // Wait the minimum of an eighth min_rtt and the existing ack time. - QuicTime ack_time = clock_->ApproximateNow().Add( - sent_packet_manager_->GetRttStats()->min_rtt().Multiply(0.125)); + QuicTime ack_time = + clock_->ApproximateNow() + + 0.125 * sent_packet_manager_->GetRttStats()->min_rtt(); if (!ack_alarm_->IsSet() || ack_alarm_->deadline() > ack_time) { ack_alarm_->Cancel(); ack_alarm_->Set(ack_time); @@ -1578,7 +1578,7 @@ DCHECK_NE(kInvalidPathId, path_id); // If the scheduler requires a delay, then we can not send this packet now. if (!delay.IsZero()) { - send_alarm_->Update(now.Add(delay), QuicTime::Delta::FromMilliseconds(1)); + send_alarm_->Update(now + delay, QuicTime::Delta::FromMilliseconds(1)); DVLOG(1) << ENDPOINT << "Delaying sending " << delay.ToMilliseconds() << "ms"; return false; @@ -2141,9 +2141,9 @@ // Adjust the idle timeout on client and server to prevent clients from // sending requests to servers which have already closed the connection. if (perspective_ == Perspective::IS_SERVER) { - idle_timeout = idle_timeout.Add(QuicTime::Delta::FromSeconds(3)); + idle_timeout = idle_timeout + QuicTime::Delta::FromSeconds(3); } else if (idle_timeout > QuicTime::Delta::FromSeconds(1)) { - idle_timeout = idle_timeout.Subtract(QuicTime::Delta::FromSeconds(1)); + idle_timeout = idle_timeout - QuicTime::Delta::FromSeconds(1); } handshake_timeout_ = handshake_timeout; idle_network_timeout_ = idle_timeout; @@ -2159,7 +2159,7 @@ // |delta| can be < 0 as |now| is approximate time but |time_of_last_packet| // is accurate time. However, this should not change the behavior of // timeout handling. - QuicTime::Delta idle_duration = now.Subtract(time_of_last_packet); + QuicTime::Delta idle_duration = now - time_of_last_packet; DVLOG(1) << ENDPOINT << "last packet " << time_of_last_packet.ToDebuggingValue() << " now:" << now.ToDebuggingValue() @@ -2175,8 +2175,7 @@ } if (!handshake_timeout_.IsInfinite()) { - QuicTime::Delta connected_duration = - now.Subtract(stats_.connection_creation_time); + QuicTime::Delta connected_duration = now - stats_.connection_creation_time; DVLOG(1) << ENDPOINT << "connection time: " << connected_duration.ToMicroseconds() << " handshake timeout: " << handshake_timeout_.ToMicroseconds(); @@ -2196,10 +2195,10 @@ QuicTime time_of_last_packet = max(time_of_last_received_packet_, time_of_last_sent_new_packet_); - QuicTime deadline = time_of_last_packet.Add(idle_network_timeout_); + QuicTime deadline = time_of_last_packet + idle_network_timeout_; if (!handshake_timeout_.IsInfinite()) { deadline = - min(deadline, stats_.connection_creation_time.Add(handshake_timeout_)); + min(deadline, stats_.connection_creation_time + handshake_timeout_); } timeout_alarm_->Cancel(); @@ -2217,7 +2216,7 @@ return; } QuicTime::Delta ping_timeout = QuicTime::Delta::FromSeconds(kPingTimeoutSecs); - ping_alarm_->Update(clock_->ApproximateNow().Add(ping_timeout), + ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout, QuicTime::Delta::FromSeconds(1)); } @@ -2266,7 +2265,7 @@ // Move generator into batch mode. If caller wants us to include an ack, // check the delayed-ack timer to see if there's ack info to be sent. if (!already_in_batch_mode_) { - DVLOG(1) << "Entering Batch Mode."; + DVLOG(2) << "Entering Batch Mode."; connection_->packet_generator_.StartBatchOperations(); } if (ShouldSendAck(ack_mode)) { @@ -2299,7 +2298,7 @@ } // If we changed the generator's batch state, restore original batch state. if (!already_in_batch_mode_) { - DVLOG(1) << "Leaving Batch Mode."; + DVLOG(2) << "Leaving Batch Mode."; connection_->packet_generator_.FinishBatchOperations(); } DCHECK_EQ(already_in_batch_mode_,
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index fd4c088..232b0e3 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc
@@ -463,7 +463,7 @@ UMA_HISTOGRAM_CUSTOM_TIMES( "Net.QuicTimeBetweenTwoPacketSent", base::TimeDelta::FromMilliseconds( - sent_time.Subtract(last_packet_sent_time_).ToMilliseconds()), + (sent_time - last_packet_sent_time_).ToMilliseconds()), base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10), 100); }
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index 80ba471..c604b4d 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc
@@ -2475,7 +2475,7 @@ EXPECT_EQ(1u, writer_->header().packet_number); // Simulate the retransmission alarm firing and sending a tlp, // so send algorithm's OnRetransmissionTimeout is not called. - clock_.AdvanceTime(retransmission_time.Subtract(clock_.Now())); + clock_.AdvanceTime(retransmission_time - clock_.Now()); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _)); connection_.GetRetransmissionAlarm()->Fire(); EXPECT_EQ(2u, writer_->header().packet_number); @@ -2487,7 +2487,7 @@ connection_.DisableTailLossProbe(); QuicTime default_retransmission_time = - clock_.ApproximateNow().Add(DefaultRetransmissionTime()); + clock_.ApproximateNow() + DefaultRetransmissionTime(); SendStreamDataToPeer(3, "foo", 0, !kFin, nullptr); EXPECT_EQ(1u, stop_waiting()->least_unacked); @@ -2507,7 +2507,7 @@ connection_.DisableTailLossProbe(); QuicTime default_retransmission_time = - clock_.ApproximateNow().Add(DefaultRetransmissionTime()); + clock_.ApproximateNow() + DefaultRetransmissionTime(); use_tagging_decrypter(); // A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at @@ -2783,7 +2783,7 @@ connection_.SendStreamDataWithString(3, "bar", 0, !kFin, nullptr); QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm(); EXPECT_TRUE(retransmission_alarm->IsSet()); - EXPECT_EQ(clock_.Now().Add(DefaultRetransmissionTime()), + EXPECT_EQ(clock_.Now() + DefaultRetransmissionTime(), retransmission_alarm->deadline()); // Advance the time right before the RTO, then receive an ack for the first @@ -2796,7 +2796,7 @@ EXPECT_GT(retransmission_alarm->deadline(), clock_.Now()); // Move forward past the original RTO and ensure the RTO is still pending. - clock_.AdvanceTime(DefaultRetransmissionTime().Multiply(2)); + clock_.AdvanceTime(2 * DefaultRetransmissionTime()); // Ensure the second packet gets retransmitted when it finally fires. EXPECT_TRUE(retransmission_alarm->IsSet()); @@ -2838,8 +2838,9 @@ QuicConfig config; connection_.SetFromConfig(config); // Subtract a second from the idle timeout on the client side. - QuicTime default_timeout = clock_.ApproximateNow().Add( - QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1)); + QuicTime default_timeout = + clock_.ApproximateNow() + + QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline()); EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _, @@ -2866,8 +2867,8 @@ EXPECT_TRUE(connection_.connected()); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber()); - QuicTime handshake_timeout = clock_.ApproximateNow().Add(timeout).Subtract( - QuicTime::Delta::FromSeconds(1)); + QuicTime handshake_timeout = + clock_.ApproximateNow() + timeout - QuicTime::Delta::FromSeconds(1); EXPECT_EQ(handshake_timeout, connection_.GetTimeoutAlarm()->deadline()); EXPECT_TRUE(connection_.connected()); @@ -2884,7 +2885,7 @@ EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_TRUE(connection_.connected()); - clock_.AdvanceTime(timeout.Subtract(QuicTime::Delta::FromSeconds(2))); + clock_.AdvanceTime(timeout - QuicTime::Delta::FromSeconds(2)); EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_HANDSHAKE_TIMEOUT, _, ConnectionCloseSource::FROM_SELF)); @@ -2912,7 +2913,7 @@ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet()); SendStreamDataToPeer(kHeadersStreamId, "GET /", 0, kFin, nullptr); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); - EXPECT_EQ(clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(15)), + EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15), connection_.GetPingAlarm()->deadline()); // Now recevie and ACK of the previous packet, which will move the @@ -2925,9 +2926,8 @@ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); // The ping timer is set slightly less than 15 seconds in the future, because // of the 1s ping timer alarm granularity. - EXPECT_EQ(clock_.ApproximateNow() - .Add(QuicTime::Delta::FromSeconds(15)) - .Subtract(QuicTime::Delta::FromMilliseconds(5)), + EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15) - + QuicTime::Delta::FromMilliseconds(5), connection_.GetPingAlarm()->deadline()); writer_->Reset(); @@ -3186,7 +3186,7 @@ const QuicTime::Delta initial_idle_timeout = QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout); + QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; // When we send a packet, the timeout will change to 5ms + // kInitialIdleTimeoutSecs. @@ -3202,12 +3202,12 @@ // The original alarm will fire. We should not time out because we had a // network event at t=5ms. The alarm will reregister. - clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms).Subtract(five_ms)); + clock_.AdvanceTime(initial_idle_timeout - five_ms - five_ms); EXPECT_EQ(default_timeout, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_TRUE(connection_.connected()); - EXPECT_EQ(default_timeout.Add(five_ms).Add(five_ms), + EXPECT_EQ(default_timeout + five_ms + five_ms, connection_.GetTimeoutAlarm()->deadline()); // This time, we should time out. @@ -3215,7 +3215,7 @@ ConnectionCloseSource::FROM_SELF)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); clock_.AdvanceTime(five_ms); - EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow()); + EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_FALSE(connection_.connected()); @@ -3250,7 +3250,7 @@ const QuicTime::Delta default_idle_timeout = QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs - 1); const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow().Add(default_idle_timeout); + QuicTime default_timeout = clock_.ApproximateNow() + default_idle_timeout; // When we send a packet, the timeout will change to 5ms + // kInitialIdleTimeoutSecs. @@ -3266,19 +3266,19 @@ // The original alarm will fire. We should not time out because we had a // network event at t=5ms. The alarm will reregister. - clock_.AdvanceTime(default_idle_timeout.Subtract(five_ms).Subtract(five_ms)); + clock_.AdvanceTime(default_idle_timeout - five_ms - five_ms); EXPECT_EQ(default_timeout, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_TRUE(connection_.connected()); - EXPECT_EQ(default_timeout.Add(five_ms).Add(five_ms), + EXPECT_EQ(default_timeout + five_ms + five_ms, connection_.GetTimeoutAlarm()->deadline()); // This time, we should time out. EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_NETWORK_IDLE_TIMEOUT, _, ConnectionCloseSource::FROM_SELF)); clock_.AdvanceTime(five_ms); - EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow()); + EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_FALSE(connection_.connected()); @@ -3295,7 +3295,7 @@ const QuicTime::Delta initial_idle_timeout = QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout); + QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, nullptr); @@ -3313,12 +3313,12 @@ // The original alarm will fire. We should not time out because we had a // network event at t=5ms. The alarm will reregister. - clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms)); + clock_.AdvanceTime(initial_idle_timeout - five_ms); EXPECT_EQ(default_timeout, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_TRUE(connection_.connected()); EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_EQ(default_timeout.Add(five_ms), + EXPECT_EQ(default_timeout + five_ms, connection_.GetTimeoutAlarm()->deadline()); // This time, we should time out. @@ -3326,7 +3326,7 @@ ConnectionCloseSource::FROM_SELF)); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); clock_.AdvanceTime(five_ms); - EXPECT_EQ(default_timeout.Add(five_ms), clock_.ApproximateNow()); + EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet()); EXPECT_FALSE(connection_.connected()); @@ -3344,9 +3344,9 @@ QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); connection_.SetNetworkTimeouts( QuicTime::Delta::Infinite(), - initial_idle_timeout.Add(QuicTime::Delta::FromSeconds(1))); + initial_idle_timeout + QuicTime::Delta::FromSeconds(1)); const QuicTime::Delta five_ms = QuicTime::Delta::FromMilliseconds(5); - QuicTime default_timeout = clock_.ApproximateNow().Add(initial_idle_timeout); + QuicTime default_timeout = clock_.ApproximateNow() + initial_idle_timeout; EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); connection_.SendStreamDataWithString(kClientDataStreamId1, "foo", 0, !kFin, @@ -3367,12 +3367,12 @@ // The original alarm will fire. We should not time out because we had a // network event at t=5ms. The alarm will reregister. - clock_.AdvanceTime(initial_idle_timeout.Subtract(five_ms)); + clock_.AdvanceTime(initial_idle_timeout - five_ms); EXPECT_EQ(default_timeout, clock_.ApproximateNow()); connection_.GetTimeoutAlarm()->Fire(); EXPECT_TRUE(connection_.connected()); EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); - EXPECT_EQ(default_timeout.Add(five_ms), + EXPECT_EQ(default_timeout + five_ms, connection_.GetTimeoutAlarm()->deadline()); // Now, send packets while advancing the time and verify that the connection @@ -3528,7 +3528,7 @@ } TEST_P(QuicConnectionTest, SendDelayedAck) { - QuicTime ack_time = clock_.ApproximateNow().Add(DefaultDelayedAckTime()); + QuicTime ack_time = clock_.ApproximateNow() + DefaultDelayedAckTime(); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3564,8 +3564,8 @@ QuicTime::Delta::Zero(), QuicTime::Zero()); // The ack time should be based on min_rtt/4, since it's less than the // default delayed ack time. - QuicTime ack_time = clock_.ApproximateNow().Add( - QuicTime::Delta::FromMilliseconds(kMinRttMs / 4)); + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3617,8 +3617,8 @@ QuicTime::Delta::Zero(), QuicTime::Zero()); // The ack time should be based on min_rtt/8, since it's less than the // default delayed ack time. - QuicTime ack_time = clock_.ApproximateNow().Add( - QuicTime::Delta::FromMilliseconds(kMinRttMs / 8)); + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 8); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3670,8 +3670,8 @@ QuicTime::Delta::Zero(), QuicTime::Zero()); // The ack time should be based on min_rtt/4, since it's less than the // default delayed ack time. - QuicTime ack_time = clock_.ApproximateNow().Add( - QuicTime::Delta::FromMilliseconds(kMinRttMs / 4)); + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3702,7 +3702,7 @@ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 9, !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); - ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5)); + ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5); EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); @@ -3731,8 +3731,8 @@ QuicTime::Delta::Zero(), QuicTime::Zero()); // The ack time should be based on min_rtt/4, since it's less than the // default delayed ack time. - QuicTime ack_time = clock_.ApproximateNow().Add( - QuicTime::Delta::FromMilliseconds(kMinRttMs / 4)); + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3763,7 +3763,7 @@ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 19, !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); - ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5)); + ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5); EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); @@ -3805,8 +3805,8 @@ QuicTime::Delta::Zero(), QuicTime::Zero()); // The ack time should be based on min_rtt/8, since it's less than the // default delayed ack time. - QuicTime ack_time = clock_.ApproximateNow().Add( - QuicTime::Delta::FromMilliseconds(kMinRttMs / 8)); + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 8); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3837,7 +3837,7 @@ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 9, !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); - ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5)); + ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5); EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); @@ -3868,8 +3868,8 @@ QuicTime::Delta::Zero(), QuicTime::Zero()); // The ack time should be based on min_rtt/8, since it's less than the // default delayed ack time. - QuicTime ack_time = clock_.ApproximateNow().Add( - QuicTime::Delta::FromMilliseconds(kMinRttMs / 8)); + QuicTime ack_time = clock_.ApproximateNow() + + QuicTime::Delta::FromMilliseconds(kMinRttMs / 8); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); const uint8_t tag = 0x07; @@ -3900,7 +3900,7 @@ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); ProcessDataPacketAtLevel(kDefaultPathId, kFirstDecimatedPacket + 19, !kEntropyFlag, !kHasStopWaiting, ENCRYPTION_INITIAL); - ack_time = clock_.ApproximateNow().Add(QuicTime::Delta::FromMilliseconds(5)); + ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5); EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); @@ -3936,7 +3936,7 @@ ProcessPacket(kDefaultPathId, 1); // Check that ack is sent and that delayed ack alarm is set. EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); - QuicTime ack_time = clock_.ApproximateNow().Add(DefaultDelayedAckTime()); + QuicTime ack_time = clock_.ApproximateNow() + DefaultDelayedAckTime(); EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline()); // Completing the handshake as the server does nothing. @@ -4661,7 +4661,7 @@ scoped_refptr<MockAckListener> listener(new StrictMock<MockAckListener>); QuicTime default_retransmission_time = - clock_.ApproximateNow().Add(DefaultRetransmissionTime()); + clock_.ApproximateNow() + DefaultRetransmissionTime(); connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener.get()); EXPECT_EQ(1u, stop_waiting()->least_unacked); @@ -4817,7 +4817,7 @@ .WillRepeatedly(Return(QuicTime::Delta::FromMilliseconds(1))); connection_.OnCanWrite(); EXPECT_TRUE(connection_.GetSendAlarm()->IsSet()); - EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(1)), + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(1), connection_.GetSendAlarm()->deadline()); // Process an ack and the send alarm will be set to the new 2ms delay. @@ -4830,7 +4830,7 @@ EXPECT_EQ(1u, writer_->frame_count()); EXPECT_EQ(1u, writer_->stream_frames().size()); EXPECT_TRUE(connection_.GetSendAlarm()->IsSet()); - EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(2)), + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(2), connection_.GetSendAlarm()->deadline()); writer_->Reset(); }
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc index 68d0f0d7..7ac7fc50 100644 --- a/net/quic/quic_crypto_client_stream.cc +++ b/net/quic/quic_crypto_client_stream.cc
@@ -321,7 +321,7 @@ crypto_config_->FillInchoateClientHello( server_id_, session()->connection()->supported_versions().front(), cached, session()->connection()->random_generator(), - &crypto_negotiated_params_, &out); + /* demand_x509_proof= */ true, &crypto_negotiated_params_, &out); // Pad the inchoate client hello to fill up a packet. const QuicByteCount kFramingOverhead = 50; // A rough estimate. const QuicByteCount max_packet_size = @@ -390,20 +390,10 @@ crypto_negotiated_params_.initial_crypters.encrypter.release()); session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - if (FLAGS_quic_reply_to_rej) { - // TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and - // ENCRYPTION_FIRST_ESTABLSIHED. - encryption_established_ = true; - session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED); - } else { - if (!encryption_established_) { - encryption_established_ = true; - session()->OnCryptoHandshakeEvent( - QuicSession::ENCRYPTION_FIRST_ESTABLISHED); - } else { - session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED); - } - } + // TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and + // ENCRYPTION_FIRST_ESTABLSIHED + encryption_established_ = true; + session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED); } void QuicCryptoClientStream::DoReceiveREJ( @@ -486,7 +476,8 @@ server_id_.host(), server_id_.port(), cached->server_config(), session()->connection()->version(), chlo_hash_, cached->certs(), cached->cert_sct(), cached->signature(), verify_context_.get(), - &verify_error_details_, &verify_details_, proof_verify_callback); + &verify_error_details_, &verify_details_, + std::unique_ptr<ProofVerifierCallback>(proof_verify_callback)); switch (status) { case QUIC_PENDING: @@ -494,10 +485,8 @@ DVLOG(1) << "Doing VerifyProof"; break; case QUIC_FAILURE: - delete proof_verify_callback; break; case QUIC_SUCCESS: - delete proof_verify_callback; verify_ok_ = true; break; }
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc index 3358002f..cd92ea6 100644 --- a/net/quic/quic_flags.cc +++ b/net/quic/quic_flags.cc
@@ -66,21 +66,10 @@ // If true, headers stream will support receiving PUSH_PROMISE frames. bool FLAGS_quic_supports_push_promise = true; -// If true, make sure new incoming streams correctly cede to higher -// priority (or batch) streams when doing QUIC writes. -bool FLAGS_quic_cede_correctly = true; - -// Resend 0RTT requests in response to an REJ that re-establishes encryption. -bool FLAGS_quic_reply_to_rej = true; - // If true, QUIC connections can do bandwidth resumption with an initial window // of < 10 packets. bool FLAGS_quic_no_lower_bw_resumption_limit = true; -// Limit the ruction of slow start large reduction to 1/2 the current CWND once -// the initial flight has been acked. -bool FLAGS_quic_sslr_limit_reduction = true; - // If true, flow controller may grow the receive window size if necessary. bool FLAGS_quic_auto_tune_receive_window = true; @@ -103,10 +92,6 @@ // flags. bool FLAGS_quic_use_old_public_reset_packets = true; -// Ignore the peer's recieve buffer size and instead set max CWND based on the -// amount of data the sender is willing to have in flight. -bool FLAGS_quic_ignore_srbf = true; - // Allow the NPRR connection option which reduces QUIC\'s pacing rate during // recovery instead of PRR. bool FLAGS_quic_allow_noprr = true; @@ -164,3 +149,9 @@ // If true, enables QUIC_VERSION_35. bool FLAGS_quic_enable_version_35 = false; + +// If true, enables QUIC_VERSION_36. +bool FLAGS_quic_enable_version_36 = false; + +// If true, requires support for X509 certificates in QUIC CHLO PDMDs. +bool FLAGS_quic_require_x509 = false;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h index 8677ca7..0a54c7b 100644 --- a/net/quic/quic_flags.h +++ b/net/quic/quic_flags.h
@@ -25,17 +25,13 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_fix; NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise; NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_cede_correctly; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_reply_to_rej; NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_lower_bw_resumption_limit; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_sslr_limit_reduction; NET_EXPORT_PRIVATE extern bool FLAGS_quic_auto_tune_receive_window; NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_autotune_by_default; NET_EXPORT_PRIVATE extern bool FLAGS_quic_loss_recovery_use_largest_acked; NET_EXPORT_PRIVATE extern bool FLAGS_quic_only_one_sending_alarm; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_hash_in_scup; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_old_public_reset_packets; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_ignore_srbf; NET_EXPORT_PRIVATE extern bool FLAGS_quic_allow_noprr; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_optimized_write_path; NET_EXPORT_PRIVATE extern bool FLAGS_quic_dispatcher_creates_id; @@ -52,5 +48,7 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_mtu_discovery_ack_listener; NET_EXPORT_PRIVATE extern bool FLAGS_quic_simple_packet_number_length; NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_version_35; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_version_36; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_x509; #endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_flow_controller.cc b/net/quic/quic_flow_controller.cc index 30c5386..f3c8eef 100644 --- a/net/quic/quic_flow_controller.cc +++ b/net/quic/quic_flow_controller.cc
@@ -135,8 +135,8 @@ } // Now we can compare timing of window updates with RTT. - QuicTime::Delta since_last = now.Subtract(prev); - QuicTime::Delta two_rtt = rtt.Multiply(2); + QuicTime::Delta since_last = now - prev; + QuicTime::Delta two_rtt = 2 * rtt; if (since_last >= two_rtt) { // If interval between window updates is sufficiently large, there
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index 889e0705..007a947 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc
@@ -1595,7 +1595,7 @@ ack_frame->received_packet_times.reserve(num_received_packets); ack_frame->received_packet_times.push_back( - std::make_pair(seq_num, creation_time_.Add(last_timestamp_))); + std::make_pair(seq_num, creation_time_ + last_timestamp_)); for (uint8_t i = 1; i < num_received_packets; ++i) { if (!reader->ReadBytes(&delta_from_largest_observed, @@ -1614,10 +1614,10 @@ return false; } - last_timestamp_ = last_timestamp_.Add( - QuicTime::Delta::FromMicroseconds(incremental_time_delta_us)); + last_timestamp_ = last_timestamp_ + QuicTime::Delta::FromMicroseconds( + incremental_time_delta_us); ack_frame->received_packet_times.push_back( - std::make_pair(seq_num, creation_time_.Add(last_timestamp_))); + std::make_pair(seq_num, creation_time_ + last_timestamp_)); } } return true; @@ -2447,9 +2447,9 @@ // Use the lowest 4 bytes of the time delta from the creation_time_. const uint64_t time_epoch_delta_us = UINT64_C(1) << 32; - uint32_t time_delta_us = static_cast<uint32_t>( - it->second.Subtract(creation_time_).ToMicroseconds() & - (time_epoch_delta_us - 1)); + uint32_t time_delta_us = + static_cast<uint32_t>((it->second - creation_time_).ToMicroseconds() & + (time_epoch_delta_us - 1)); if (!writer->WriteBytes(&time_delta_us, sizeof(time_delta_us))) { return false; } @@ -2469,8 +2469,7 @@ return false; } - uint64_t frame_time_delta_us = - it->second.Subtract(prev_time).ToMicroseconds(); + uint64_t frame_time_delta_us = (it->second - prev_time).ToMicroseconds(); prev_time = it->second; if (!writer->WriteUFloat16(frame_time_delta_us)) { return false;
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 4f2ba4f..88a0b8e 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc
@@ -351,7 +351,7 @@ QuicFramerTest() : encrypter_(new test::TestEncrypter()), decrypter_(new test::TestDecrypter()), - start_(QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(0x10))), + start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)), framer_(QuicSupportedVersions(), start_, Perspective::IS_SERVER) { version_ = GetParam(); framer_.set_version(version_);
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc index 72c3ac9..fc56faf2 100644 --- a/net/quic/quic_headers_stream.cc +++ b/net/quic/quic_headers_stream.cc
@@ -35,14 +35,14 @@ int64_t OnNewEntry(const HpackEntry& entry) override { DVLOG(1) << entry.GetDebugString(); - return clock_->ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds(); + return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds(); } void OnUseEntry(const HpackEntry& entry) override { const QuicTime::Delta elapsed( - clock_->ApproximateNow() - .Subtract(QuicTime::Delta::FromMicroseconds(entry.time_added())) - .Subtract(QuicTime::Zero())); + clock_->ApproximateNow() - + QuicTime::Delta::FromMicroseconds(entry.time_added()) - + QuicTime::Zero()); DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds() << " ms"; headers_stream_hpack_visitor_->OnUseEntry(elapsed); @@ -56,6 +56,46 @@ DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor); }; +// When forced HOL blocking is enabled, extra bytes in the form of +// HTTP/2 DATA frame headers are inserted on the way down to the +// session layer. |ForceAckListener| filters the |OnPacketAcked()| +// notifications generated by the session layer to not count the extra +// bytes. Otherwise, code that is using ack listener on streams might +// consider it an error if more bytes are acked than were written to +// the stream, it is the case with some internal stats gathering code. +class ForceHolAckListener : public QuicAckListenerInterface { + public: + // |extra_bytes| should be initialized to the size of the HTTP/2 + // DATA frame header inserted when forced HOL blocking is enabled. + ForceHolAckListener(QuicAckListenerInterface* stream_ack_listener, + int extra_bytes) + : stream_ack_listener_(stream_ack_listener), extra_bytes_(extra_bytes) { + DCHECK_GE(extra_bytes, 0); + } + + void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override { + if (extra_bytes_ > 0) { + // Don't count the added HTTP/2 DATA frame header bytes + int delta = std::min(extra_bytes_, acked_bytes); + extra_bytes_ -= delta; + acked_bytes -= delta; + } + stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time); + } + + void OnPacketRetransmitted(int retransmitted_bytes) override { + stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes); + } + + private: + ~ForceHolAckListener() override {} + + scoped_refptr<QuicAckListenerInterface> stream_ack_listener_; + int extra_bytes_; + + DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener); +}; + } // namespace QuicHeadersStream::HpackDebugVisitor::HpackDebugVisitor() {} @@ -97,6 +137,9 @@ void OnStreamFrameData(SpdyStreamId stream_id, const char* data, size_t len) override { + if (stream_->OnStreamFrameData(stream_id, data, len)) { + return; + } CloseConnection("SPDY DATA frame received."); } @@ -133,6 +176,9 @@ void OnDataFrameHeader(SpdyStreamId stream_id, size_t length, bool fin) override { + if (stream_->OnDataFrameHeader(stream_id, length, fin)) { + return; + } CloseConnection("SPDY DATA frame received."); } @@ -330,6 +376,63 @@ return frame.size(); } +QuicConsumedData QuicHeadersStream::WritevStreamData( + QuicStreamId id, + QuicIOVector iov, + QuicStreamOffset offset, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate) { + const size_t max_len = SpdyConstants::GetFrameMaximumSize(HTTP2) - + SpdyConstants::GetDataFrameMinimumSize(HTTP2); + + QuicConsumedData result(0, false); + size_t total_length = iov.total_length; + + // Encapsulate the data into HTTP/2 DATA frames. The outer loop + // handles each element of the source iov, the inner loop handles + // the possibility of fragmenting eacho of those into multiple DATA + // frames, as the DATA frames have a max size of 16KB. + for (int i = 0; i < iov.iov_count; i++) { + size_t offset = 0; + const struct iovec* src_iov = &iov.iov[i]; + do { + size_t len = + std::min(std::min(src_iov->iov_len - offset, max_len), total_length); + char* data = static_cast<char*>(src_iov->iov_base) + offset; + SpdyDataIR spdy_data(id, StringPiece(data, len)); + offset += len; + // fin handling, set it only it only very last generated HTTP/2 + // DATA frame. + bool last_iov = i == iov.iov_count - 1; + bool last_fragment_within_iov = offset >= src_iov->iov_len; + bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; + spdy_data.set_fin(frame_fin); + if (frame_fin) { + result.fin_consumed = true; + } + SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); + DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " + << len << " fin " << spdy_data.fin() << " remaining " + << src_iov->iov_len - offset; + + scoped_refptr<ForceHolAckListener> ack_listener; + if (ack_notifier_delegate != nullptr) { + ack_listener = + new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); + } + + WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, + ack_listener.get()); + result.bytes_consumed += len; + total_length -= len; + if (total_length <= 0) { + return result; + } + } while (offset < src_iov->iov_len); + } + return result; +} + void QuicHeadersStream::OnDataAvailable() { char buffer[1024]; struct iovec iov; @@ -405,7 +508,7 @@ // headers from lower numbered streams actually came off the // wire after headers for the current stream, hence there was // HOL blocking. - QuicTime::Delta delta(prev_max_timestamp_.Subtract(cur_max_timestamp_)); + QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_; DVLOG(1) << "stream " << stream_id << ": Net.QuicSession.HeadersHOLBlockedTime " << delta.ToMilliseconds(); @@ -452,7 +555,7 @@ // headers from lower numbered streams actually came off the // wire after headers for the current stream, hence there was // HOL blocking. - QuicTime::Delta delta = prev_max_timestamp_.Subtract(cur_max_timestamp_); + QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_; DVLOG(1) << "stream " << stream_id_ << ": Net.QuicSession.HeadersHOLBlockedTime " << delta.ToMilliseconds(); @@ -506,4 +609,39 @@ spdy_framer_.UpdateHeaderEncoderTableSize(value); } +bool QuicHeadersStream::OnDataFrameHeader(QuicStreamId stream_id, + size_t length, + bool fin) { + if (!spdy_session_->force_hol_blocking()) { + return false; + } + if (!IsConnected()) { + return true; + } + DVLOG(1) << "DATA frame header for stream " << stream_id << " length " + << length << " fin " << fin; + fin_ = fin; + frame_len_ = length; + if (fin && length == 0) { + OnStreamFrameData(stream_id, "", 0); + } + return true; +} + +bool QuicHeadersStream::OnStreamFrameData(QuicStreamId stream_id, + const char* data, + size_t len) { + if (!spdy_session_->force_hol_blocking()) { + return false; + } + if (!IsConnected()) { + return true; + } + frame_len_ -= len; + // Ignore fin_ while there is more data coming, if frame_len_ > 0. + spdy_session_->OnStreamFrameData(stream_id, data, len, + frame_len_ > 0 ? false : fin_); + return true; +} + } // namespace net
diff --git a/net/quic/quic_headers_stream.h b/net/quic/quic_headers_stream.h index 3f17403..e80040e0 100644 --- a/net/quic/quic_headers_stream.h +++ b/net/quic/quic_headers_stream.h
@@ -65,6 +65,15 @@ SpdyHeaderBlock headers, QuicAckListenerInterface* ack_listener); + // For forcing HOL blocking. This encapsulates data from other + // streams into HTTP/2 data frames on the headers stream. + QuicConsumedData WritevStreamData( + QuicStreamId id, + QuicIOVector iov, + QuicStreamOffset offset, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate); + // ReliableQuicStream implementation void OnDataAvailable() override; @@ -123,6 +132,12 @@ // Called when the size of the compressed frame payload is available. void OnCompressedFrameSize(size_t frame_len); + // For force HOL blocking, where stream frames from all streams are + // plumbed through headers stream as HTTP/2 data frames. Return false + // if force_hol_blocking_ is false; + bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin); + bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len); + // Returns true if the session is still connected. bool IsConnected();
diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index 1dbc07e..728e897 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc
@@ -7,6 +7,7 @@ #include <string> #include "base/strings/string_number_conversions.h" +#include "net/quic/quic_bug_tracker.h" #include "net/quic/quic_utils.h" #include "net/quic/spdy_utils.h" #include "net/quic/test_tools/quic_connection_peer.h" @@ -26,6 +27,9 @@ using std::string; using std::vector; using testing::ElementsAre; +using testing::_; +using testing::AtLeast; +using testing::HasSubstr; using testing::InSequence; using testing::Invoke; using testing::Return; @@ -114,6 +118,26 @@ MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); }; +class ForceHolAckListener : public QuicAckListenerInterface { + public: + ForceHolAckListener() : total_acked_bytes_(0) {} + + void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override { + total_acked_bytes_ += acked_bytes; + } + + void OnPacketRetransmitted(int retransmitted_bytes) override {} + + size_t total_acked_bytes() { return total_acked_bytes_; } + + private: + ~ForceHolAckListener() override {} + + size_t total_acked_bytes_; + + DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener); +}; + // Run all tests with each version, perspective (client or server), // and relevant flag options (false or true) struct TestParams { @@ -171,10 +195,27 @@ QuicConsumedData SaveIov(const QuicIOVector& data) { const iovec* iov = data.iov; int count = data.iov_count; + int consumed = 0; for (int i = 0; i < count; ++i) { saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); + consumed += iov[i].iov_len; } - return QuicConsumedData(saved_data_.length(), false); + return QuicConsumedData(consumed, false); + } + + QuicConsumedData SaveIovAndNotifyAckListener( + const QuicIOVector& data, + QuicAckListenerInterface* ack_listener) { + QuicConsumedData result = SaveIov(data); + if (ack_listener) { + ack_listener->OnPacketAcked(result.bytes_consumed, + QuicTime::Delta::Zero()); + } + return result; + } + + void SavePayload(const char* data, size_t len) { + saved_payloads_.append(data, len); } bool SaveHeaderData(const char* data, int len) { @@ -293,6 +334,7 @@ string body_; string saved_data_; string saved_header_data_; + string saved_payloads_; std::unique_ptr<SpdyFramer> framer_; StrictMock<MockVisitor> visitor_; std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_encoder_visitor_; @@ -455,9 +497,6 @@ } TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { - if (!FLAGS_quic_measure_headers_hol_blocking_time) { - return; - } QuicStreamId stream_id; bool fin = true; QuicStreamFrame stream_frames[10]; @@ -550,8 +589,9 @@ } TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { - SpdyDataIR data(2, ""); + SpdyDataIR data(2, "ping"); SpdySerializedFrame frame(framer_->SerializeFrame(data)); + EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, "SPDY DATA frame received.", _)) .WillOnce(InvokeWithoutArgs( @@ -561,6 +601,33 @@ headers_stream_->OnStreamFrame(stream_frame_); } +TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameForceHolBlocking) { + if (version() <= QUIC_VERSION_35) { + return; + } + QuicSpdySessionPeer::SetForceHolBlocking(&session_, true); + SpdyDataIR data(2, "ping"); + SpdySerializedFrame frame(framer_->SerializeFrame(data)); + EXPECT_CALL(session_, OnStreamFrameData(2, _, 4, false)); + stream_frame_.data_buffer = frame.data(); + stream_frame_.data_length = frame.size(); + headers_stream_->OnStreamFrame(stream_frame_); +} + +TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameEmptyWithFin) { + if (version() <= QUIC_VERSION_35) { + return; + } + QuicSpdySessionPeer::SetForceHolBlocking(&session_, true); + SpdyDataIR data(2, ""); + data.set_fin(true); + SpdySerializedFrame frame(framer_->SerializeFrame(data)); + EXPECT_CALL(session_, OnStreamFrameData(2, _, 0, true)); + stream_frame_.data_buffer = frame.data(); + stream_frame_.data_length = frame.size(); + headers_stream_->OnStreamFrame(stream_frame_); +} + TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR); SpdySerializedFrame frame(framer_->SerializeFrame(data)); @@ -781,6 +848,61 @@ } } +TEST_P(QuicHeadersStreamTest, WritevStreamData) { + QuicStreamId id = kClientDataStreamId1; + QuicStreamOffset offset = 0; + struct iovec iov; + string data; + + // This test will issue a write that will require fragmenting into + // multiple HTTP/2 DATA frames. + const int kMinDataFrames = 4; + const size_t data_len = + SpdyConstants::GetFrameMaximumSize(HTTP2) * kMinDataFrames + 1024; + // Set headers stream send window large enough for data written below. + headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4); + test::GenerateBody(&data, data_len); + + for (bool fin : {true, false}) { + for (bool use_ack_listener : {true, false}) { + scoped_refptr<ForceHolAckListener> ack_listener; + if (use_ack_listener) { + ack_listener = new ForceHolAckListener(); + } + EXPECT_CALL(session_, + WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + .WillRepeatedly(WithArgs<2, 5>(Invoke( + this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); + + QuicConsumedData consumed_data = headers_stream_->WritevStreamData( + id, MakeIOVector(data, &iov), offset, fin, ack_listener.get()); + + EXPECT_EQ(consumed_data.bytes_consumed, data_len); + EXPECT_EQ(consumed_data.fin_consumed, fin); + // Now process the written data with the SPDY framer, and verify + // that the original data is unchanged. + EXPECT_CALL(visitor_, OnDataFrameHeader(id, _, _)) + .Times(AtLeast(kMinDataFrames)); + EXPECT_CALL(visitor_, OnStreamFrameData(id, _, _)) + .WillRepeatedly(WithArgs<1, 2>( + Invoke(this, &QuicHeadersStreamTest::SavePayload))); + if (fin) { + EXPECT_CALL(visitor_, OnStreamEnd(id)); + } + framer_->ProcessInput(saved_data_.data(), saved_data_.length()); + EXPECT_EQ(saved_payloads_, data); + + if (use_ack_listener) { + // Notice, acked bytes doesn't include extra bytes used by + // HTTP/2 DATA frame headers. + EXPECT_EQ(ack_listener->total_acked_bytes(), data_len); + } + saved_data_.clear(); + saved_payloads_.clear(); + } + } +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index 41ef5c7b..9829ab46 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc
@@ -192,6 +192,10 @@ if (FLAGS_quic_enable_version_35) { filtered_versions.push_back(version); } + } else if (version == QUIC_VERSION_36) { + if (FLAGS_quic_enable_version_35 && FLAGS_quic_enable_version_36) { + filtered_versions.push_back(version); + } } else { filtered_versions.push_back(version); } @@ -224,6 +228,8 @@ return MakeQuicTag('Q', '0', '3', '4'); case QUIC_VERSION_35: return MakeQuicTag('Q', '0', '3', '5'); + case QUIC_VERSION_36: + return MakeQuicTag('Q', '0', '3', '6'); default: // This shold be an ERROR because we should never attempt to convert an // invalid QuicVersion to be written to the wire. @@ -261,6 +267,7 @@ RETURN_STRING_LITERAL(QUIC_VERSION_33); RETURN_STRING_LITERAL(QUIC_VERSION_34); RETURN_STRING_LITERAL(QUIC_VERSION_35); + RETURN_STRING_LITERAL(QUIC_VERSION_36); default: return "QUIC_VERSION_UNSUPPORTED"; }
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index d5b6c53..c3089f7 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h
@@ -372,6 +372,7 @@ QUIC_VERSION_34 = 34, // Deprecates entropy, removes private flag from packet // header, uses new ack and stop waiting wire format. QUIC_VERSION_35 = 35, // Allows endpoints to independently set stream limit. + QUIC_VERSION_36 = 36, // Add support to force HOL blocking. }; // This vector contains QUIC versions which we currently support. @@ -382,9 +383,9 @@ // IMPORTANT: if you are adding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions static const QuicVersion kSupportedQuicVersions[] = { - QUIC_VERSION_35, QUIC_VERSION_34, QUIC_VERSION_33, QUIC_VERSION_32, - QUIC_VERSION_31, QUIC_VERSION_30, QUIC_VERSION_29, QUIC_VERSION_28, - QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25}; + QUIC_VERSION_36, QUIC_VERSION_35, QUIC_VERSION_34, QUIC_VERSION_33, + QUIC_VERSION_32, QUIC_VERSION_31, QUIC_VERSION_30, QUIC_VERSION_29, + QUIC_VERSION_28, QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25}; typedef std::vector<QuicVersion> QuicVersionVector;
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc index 64ac095..126f610 100644 --- a/net/quic/quic_protocol_test.cc +++ b/net/quic/quic_protocol_test.cc
@@ -189,7 +189,7 @@ frame.packets.Add(4); frame.packets.Add(5); frame.received_packet_times = { - {6, QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(7))}}; + {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}}; std::ostringstream stream; stream << frame; EXPECT_EQ(
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc index 73226a1..4ce6945 100644 --- a/net/quic/quic_received_packet_manager.cc +++ b/net/quic/quic_received_packet_manager.cc
@@ -175,7 +175,7 @@ max(stats_->max_sequence_reordering, ack_frame_.largest_observed - packet_number); int64_t reordering_time_us = - receipt_time.Subtract(time_largest_observed_).ToMicroseconds(); + (receipt_time - time_largest_observed_).ToMicroseconds(); stats_->max_time_reordering_us = max(stats_->max_time_reordering_us, reordering_time_us); } @@ -231,10 +231,9 @@ ack_frame_.ack_delay_time = QuicTime::Delta::Infinite(); } else { // Ensure the delta is zero if approximate now is "in the past". - ack_frame_.ack_delay_time = - approximate_now < time_largest_observed_ - ? QuicTime::Delta::Zero() - : approximate_now.Subtract(time_largest_observed_); + ack_frame_.ack_delay_time = approximate_now < time_largest_observed_ + ? QuicTime::Delta::Zero() + : approximate_now - time_largest_observed_; } // Clear all packet times if any are too far from largest observed.
diff --git a/net/quic/quic_received_packet_manager_test.cc b/net/quic/quic_received_packet_manager_test.cc index a3bca2f5..ee654b75 100644 --- a/net/quic/quic_received_packet_manager_test.cc +++ b/net/quic/quic_received_packet_manager_test.cc
@@ -342,7 +342,7 @@ TEST_P(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) { QuicPacketHeader header; header.packet_number = 2u; - QuicTime two_ms = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2)); + QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); EXPECT_FALSE(received_manager_.ack_frame_updated()); received_manager_.RecordPacketReceived(0u, header, two_ms); EXPECT_TRUE(received_manager_.ack_frame_updated()); @@ -354,7 +354,7 @@ EXPECT_EQ(QuicTime::Delta::Zero(), ack.ack_frame->ack_delay_time); EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size()); - QuicTime four_ms = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(4)); + QuicTime four_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(4); ack = received_manager_.GetUpdatedAckFrame(four_ms); EXPECT_FALSE(received_manager_.ack_frame_updated()); // When UpdateReceivedPacketInfo after not having received a new packet, @@ -383,8 +383,8 @@ RecordPacketReceipt(1, 0); EXPECT_TRUE(received_manager_.ack_frame_updated()); RecordPacketReceipt(6, 0); - RecordPacketReceipt( - 2, 0, QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1))); + RecordPacketReceipt(2, 0, + QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1)); EXPECT_EQ(4u, stats_.max_sequence_reordering); EXPECT_EQ(1000, stats_.max_time_reordering_us);
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index 33e79fe..7ec63fc 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc
@@ -163,14 +163,6 @@ config.HasClientSentConnectionOption(kUNDO, perspective_)) { undo_pending_retransmits_ = true; } - if (!FLAGS_quic_ignore_srbf && config.HasReceivedSocketReceiveBuffer()) { - receive_buffer_bytes_ = - max(kMinSocketReceiveBuffer, - static_cast<QuicByteCount>(config.ReceivedSocketReceiveBuffer())); - QuicByteCount max_cwnd_bytes = static_cast<QuicByteCount>( - receive_buffer_bytes_ * kConservativeReceiveBufferFraction); - send_algorithm_->SetMaxCongestionWindow(max_cwnd_bytes); - } send_algorithm_->SetFromConfig(config, perspective_); if (network_change_visitor_ != nullptr) { @@ -772,8 +764,7 @@ return false; } - QuicTime::Delta send_delta = - ack_receive_time.Subtract(transmission_info.sent_time); + QuicTime::Delta send_delta = ack_receive_time - transmission_info.sent_time; const int kMaxSendDeltaSeconds = 30; if (FLAGS_quic_socket_walltimestamps && send_delta.ToSeconds() > kMaxSendDeltaSeconds) { @@ -815,7 +806,7 @@ } switch (GetRetransmissionMode()) { case HANDSHAKE_MODE: - return clock_->ApproximateNow().Add(GetCryptoRetransmissionDelay()); + return clock_->ApproximateNow() + GetCryptoRetransmissionDelay(); case LOSS_MODE: return loss_algorithm_->GetLossTimeout(); case TLP_MODE: { @@ -823,17 +814,17 @@ // set the timer based on the earliest retransmittable packet. // Base the updated timer on the send time of the last packet. const QuicTime sent_time = unacked_packets_.GetLastPacketSentTime(); - const QuicTime tlp_time = sent_time.Add(GetTailLossProbeDelay()); + const QuicTime tlp_time = sent_time + GetTailLossProbeDelay(); // Ensure the TLP timer never gets set to a time in the past. return QuicTime::Max(clock_->ApproximateNow(), tlp_time); } case RTO_MODE: { // The RTO is based on the first outstanding packet. const QuicTime sent_time = unacked_packets_.GetLastPacketSentTime(); - QuicTime rto_time = sent_time.Add(GetRetransmissionDelay()); + QuicTime rto_time = sent_time + GetRetransmissionDelay(); // Wait for TLP packets to be acked before an RTO fires. QuicTime tlp_time = - unacked_packets_.GetLastPacketSentTime().Add(GetTailLossProbeDelay()); + unacked_packets_.GetLastPacketSentTime() + GetTailLossProbeDelay(); return QuicTime::Max(tlp_time, rto_time); } } @@ -866,10 +857,9 @@ static_cast<int64_t>(0.5 * srtt.ToMilliseconds()))); } if (!unacked_packets_.HasMultipleInFlightPackets()) { - return QuicTime::Delta::Max( - srtt.Multiply(2), - srtt.Multiply(1.5).Add( - QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs / 2))); + return QuicTime::Delta::Max(2 * srtt, + 1.5 * srtt + QuicTime::Delta::FromMilliseconds( + kMinRetransmissionTimeMs / 2)); } return QuicTime::Delta::FromMilliseconds( max(kMinTailLossProbeTimeoutMs, @@ -888,8 +878,9 @@ } // Calculate exponential back off. - retransmission_delay = retransmission_delay.Multiply( - 1 << min<size_t>(consecutive_rto_count_, kMaxRetransmissions)); + retransmission_delay = + retransmission_delay * + (1 << min<size_t>(consecutive_rto_count_, kMaxRetransmissions)); if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) { return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs);
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index 45cd30b..b21d39e9 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -766,7 +766,7 @@ } QuicTime rto_packet_time = clock_.Now(); // Advance the time. - clock_.AdvanceTime(manager_.GetRetransmissionTime().Subtract(clock_.Now())); + clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now()); // The first tail loss probe retransmits 1 packet. manager_.OnRetransmissionTimeout(); @@ -784,7 +784,7 @@ QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA, &path_id)); EXPECT_FALSE(manager_.HasPendingRetransmissions()); - clock_.AdvanceTime(manager_.GetRetransmissionTime().Subtract(clock_.Now())); + clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now()); // The second tail loss probe retransmits 1 packet. manager_.OnRetransmissionTimeout(); @@ -805,7 +805,7 @@ rto_packet_time = clock_.Now(); EXPECT_CALL(*send_algorithm_, RetransmissionDelay()) .WillOnce(Return(QuicTime::Delta::FromSeconds(1))); - EXPECT_EQ(rto_packet_time.Add(QuicTime::Delta::FromSeconds(1)), + EXPECT_EQ(rto_packet_time + QuicTime::Delta::FromSeconds(1), manager_.GetRetransmissionTime()); // Advance the time enough to ensure all packets are RTO'd. @@ -1195,7 +1195,7 @@ // Check the min. RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); rtt_stats->set_initial_rtt_us(1 * kNumMicrosPerMilli); - EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(10)), + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(10), manager_.GetRetransmissionTime()); // Test with a standard smoothed RTT. @@ -1203,16 +1203,16 @@ QuicTime::Delta srtt = QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us()); - QuicTime expected_time = clock_.Now().Add(srtt.Multiply(1.5)); + QuicTime expected_time = clock_.Now() + 1.5 * srtt; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); // Retransmit the packet by invoking the retransmission timeout. - clock_.AdvanceTime(srtt.Multiply(1.5)); + clock_.AdvanceTime(1.5 * srtt); manager_.OnRetransmissionTimeout(); RetransmitNextPacket(2); // The retransmission time should now be twice as far in the future. - expected_time = clock_.Now().Add(srtt.Multiply(2).Multiply(1.5)); + expected_time = clock_.Now() + srtt * 2 * 1.5; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } @@ -1224,15 +1224,15 @@ // Check the min. RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats()); rtt_stats->set_initial_rtt_us(1 * kNumMicrosPerMilli); - EXPECT_EQ(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(10)), + EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromMilliseconds(10), manager_.GetRetransmissionTime()); // Test with a standard smoothed RTT. rtt_stats->set_initial_rtt_us(100 * kNumMicrosPerMilli); QuicTime::Delta srtt = QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us()); - QuicTime::Delta expected_tlp_delay = srtt.Multiply(2); - QuicTime expected_time = clock_.Now().Add(expected_tlp_delay); + QuicTime::Delta expected_tlp_delay = 2 * srtt; + QuicTime expected_time = clock_.Now() + expected_tlp_delay; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); // Retransmit the packet by invoking the retransmission timeout. @@ -1253,7 +1253,7 @@ manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA, &path_id)); EXPECT_FALSE(manager_.HasPendingRetransmissions()); - expected_time = clock_.Now().Add(expected_tlp_delay); + expected_time = clock_.Now() + expected_tlp_delay; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } @@ -1269,7 +1269,7 @@ QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(500); EXPECT_CALL(*send_algorithm_, RetransmissionDelay()) .WillRepeatedly(Return(expected_rto_delay)); - QuicTime expected_time = clock_.Now().Add(expected_rto_delay); + QuicTime expected_time = clock_.Now() + expected_rto_delay; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); // Retransmit the packet by invoking the retransmission timeout. @@ -1286,7 +1286,7 @@ EXPECT_FALSE(manager_.HasPendingRetransmissions()); // The delay should double the second time. - expected_time = clock_.Now().Add(expected_rto_delay).Add(expected_rto_delay); + expected_time = clock_.Now() + expected_rto_delay + expected_rto_delay; // Once we always base the timer on the right edge, leaving the older packets // in flight doesn't change the timeout. EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); @@ -1305,7 +1305,7 @@ // and the TLP time. In production, there would always be two TLP's first. // Since retransmission was spurious, smoothed_rtt_ is expired, and replaced // by the latest RTT sample of 500ms. - expected_time = clock_.Now().Add(QuicTime::Delta::FromMilliseconds(1000)); + expected_time = clock_.Now() + QuicTime::Delta::FromMilliseconds(1000); // Once we always base the timer on the right edge, leaving the older packets // in flight doesn't change the timeout. EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); @@ -1323,7 +1323,7 @@ for (int i = 0; i < 5; ++i) { EXPECT_EQ(delay, QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - delay = delay.Add(delay); + delay = delay + delay; manager_.OnRetransmissionTimeout(); RetransmitNextPacket(i + 2); } @@ -1348,7 +1348,7 @@ for (int i = 0; i < 5; ++i) { EXPECT_EQ(delay, QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)); - delay = delay.Add(delay); + delay = delay + delay; manager_.OnRetransmissionTimeout(); RetransmitNextPacket(i + 2); } @@ -1371,7 +1371,7 @@ NackPackets(1, 2, &ack_frame); manager_.OnIncomingAck(ack_frame, clock_.Now()); - QuicTime timeout(clock_.Now().Add(QuicTime::Delta::FromMilliseconds(10))); + QuicTime timeout(clock_.Now() + QuicTime::Delta::FromMilliseconds(10)); EXPECT_CALL(*loss_algorithm, GetLossTimeout()) .WillRepeatedly(Return(timeout)); EXPECT_EQ(timeout, manager_.GetRetransmissionTime()); @@ -1622,79 +1622,6 @@ EXPECT_TRUE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_)); } -TEST_P(QuicSentPacketManagerTest, - NegotiateConservativeReceiveWindowFromOptions) { - ValueRestore<bool> old_flag(&FLAGS_quic_ignore_srbf, false); - EXPECT_EQ(kDefaultSocketReceiveBuffer, - QuicSentPacketManagerPeer::GetReceiveWindow(&manager_)); - - // Try to set a size below the minimum and ensure it gets set to the min. - QuicConfig client_config; - QuicConfigPeer::SetReceivedSocketReceiveBuffer(&client_config, 1024); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - EXPECT_CALL(*send_algorithm_, - SetMaxCongestionWindow(kMinSocketReceiveBuffer * 0.6)); - EXPECT_CALL(*send_algorithm_, PacingRate(_)) - .WillRepeatedly(Return(QuicBandwidth::Zero())); - EXPECT_CALL(*send_algorithm_, GetCongestionWindow()) - .WillOnce(Return(10 * kDefaultTCPMSS)); - EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); - manager_.SetFromConfig(client_config); - - EXPECT_EQ(kMinSocketReceiveBuffer, - QuicSentPacketManagerPeer::GetReceiveWindow(&manager_)); - - // Ensure the smaller send window only allows 16 packets to be sent. - QuicPathId path_id = kInvalidPathId; - for (QuicPacketNumber i = 1; i <= 16; ++i) { - EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)) - .WillOnce(Return(QuicTime::Delta::Zero())); - EXPECT_EQ(QuicTime::Delta::Zero(), - manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA, - &path_id)); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), i, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)) - .WillOnce(Return(true)); - SerializedPacket packet(CreatePacket(i, true)); - manager_.OnPacketSent(&packet, kInvalidPathId, 0, clock_.Now(), - NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); - } - EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)) - .WillOnce(Return(QuicTime::Delta::Infinite())); - EXPECT_EQ( - QuicTime::Delta::Infinite(), - manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA, &path_id)); -} - -TEST_P(QuicSentPacketManagerTest, ReceiveWindowLimited) { - ValueRestore<bool> old_flag(&FLAGS_quic_ignore_srbf, false); - EXPECT_EQ(kDefaultSocketReceiveBuffer, - QuicSentPacketManagerPeer::GetReceiveWindow(&manager_)); - - // Ensure the smaller send window only allows 256 * 0.95 packets to be sent. - QuicPathId path_id = kInvalidPathId; - for (QuicPacketNumber i = 1; i <= 244; ++i) { - EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)) - .WillOnce(Return(QuicTime::Delta::Zero())); - EXPECT_EQ(QuicTime::Delta::Zero(), - manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA, - &path_id)); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), i, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)) - .WillOnce(Return(true)); - SerializedPacket packet(CreatePacket(i, true)); - manager_.OnPacketSent(&packet, kInvalidPathId, 0, clock_.Now(), - NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); - } - EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _)) - .WillOnce(Return(QuicTime::Delta::Infinite())); - EXPECT_EQ( - QuicTime::Delta::Infinite(), - manager_.TimeUntilSend(clock_.Now(), HAS_RETRANSMITTABLE_DATA, &path_id)); -} - TEST_P(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) { uint32_t initial_rtt_us = 325000; EXPECT_NE(initial_rtt_us,
diff --git a/net/quic/quic_server_session_base.cc b/net/quic/quic_server_session_base.cc index 63a4602..44bee9903 100644 --- a/net/quic/quic_server_session_base.cc +++ b/net/quic/quic_server_session_base.cc
@@ -116,7 +116,7 @@ connection()->sent_packet_manager(); int64_t srtt_ms = sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds(); - int64_t now_ms = now.Subtract(last_scup_time_).ToMilliseconds(); + int64_t now_ms = (now - last_scup_time_).ToMilliseconds(); int64_t packets_since_last_scup = connection()->packet_number_of_last_sent_packet() - last_scup_packet_number_;
diff --git a/net/quic/quic_server_session_base_test.cc b/net/quic/quic_server_session_base_test.cc index 96479f1..980fdb1 100644 --- a/net/quic/quic_server_session_base_test.cc +++ b/net/quic/quic_server_session_base_test.cc
@@ -459,8 +459,8 @@ // but not enough packets have been sent. int64_t srtt_ms = sent_packet_manager->GetRttStats()->smoothed_rtt().ToMilliseconds(); - now = now.Add(QuicTime::Delta::FromMilliseconds( - kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms)); + now = now + QuicTime::Delta::FromMilliseconds( + kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms); session_->OnCongestionWindowChange(now); // The connection no longer has pending data to be written.
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index b232a1e..788cc68b 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc
@@ -121,7 +121,7 @@ } while (!dynamic_stream_map_.empty()) { - StreamMap::iterator it = dynamic_stream_map_.begin(); + DynamicStreamMap::iterator it = dynamic_stream_map_.begin(); QuicStreamId id = it->first; it->second->OnConnectionClosed(error, source); // The stream should call CloseStream as part of OnConnectionClosed. @@ -308,7 +308,7 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) { DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; - StreamMap::iterator it = dynamic_stream_map_.find(stream_id); + DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id); if (it == dynamic_stream_map_.end()) { // When CloseStreamInner has been called recursively (via // ReliableQuicStream::OnClose), the stream will already have been deleted @@ -615,7 +615,7 @@ ReliableQuicStream* QuicSession::GetOrCreateStream( const QuicStreamId stream_id) { - StreamMap::iterator it = static_stream_map_.find(stream_id); + StaticStreamMap::iterator it = static_stream_map_.find(stream_id); if (it != static_stream_map_.end()) { return it->second; } @@ -679,7 +679,7 @@ DCHECK(!ContainsKey(static_stream_map_, stream_id)) << "Attempt to call GetOrCreateDynamicStream for a static stream"; - StreamMap::iterator it = dynamic_stream_map_.find(stream_id); + DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id); if (it != dynamic_stream_map_.end()) { return it->second; }
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h index 46c22d3..16f96c7 100644 --- a/net/quic/quic_session.h +++ b/net/quic/quic_session.h
@@ -17,6 +17,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/containers/small_map.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "net/base/ip_endpoint.h" @@ -227,7 +228,11 @@ bool ShouldYield(QuicStreamId stream_id); protected: - typedef std::unordered_map<QuicStreamId, ReliableQuicStream*> StreamMap; + using StaticStreamMap = + base::SmallMap<std::unordered_map<QuicStreamId, ReliableQuicStream*>, 2>; + + using DynamicStreamMap = + base::SmallMap<std::unordered_map<QuicStreamId, ReliableQuicStream*>, 10>; // Creates a new stream to handle a peer-initiated stream. // Caller does not own the returned stream. @@ -273,11 +278,13 @@ // Return true if given stream is peer initiated. bool IsIncomingStream(QuicStreamId id) const; - StreamMap& static_streams() { return static_stream_map_; } - const StreamMap& static_streams() const { return static_stream_map_; } + StaticStreamMap& static_streams() { return static_stream_map_; } + const StaticStreamMap& static_streams() const { return static_stream_map_; } - StreamMap& dynamic_streams() { return dynamic_stream_map_; } - const StreamMap& dynamic_streams() const { return dynamic_stream_map_; } + DynamicStreamMap& dynamic_streams() { return dynamic_stream_map_; } + const DynamicStreamMap& dynamic_streams() const { + return dynamic_stream_map_; + } std::vector<ReliableQuicStream*>* closed_streams() { return &closed_streams_; @@ -367,10 +374,10 @@ // Static streams, such as crypto and header streams. Owned by child classes // that create these streams. - StreamMap static_stream_map_; + StaticStreamMap static_stream_map_; // Map from StreamId to pointers to streams. Owns the streams. - StreamMap dynamic_stream_map_; + DynamicStreamMap dynamic_stream_map_; // The ID to use for the next outgoing stream. QuicStreamId next_outgoing_stream_id_;
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc index fbc4c8f..7b5925a8 100644 --- a/net/quic/quic_session_test.cc +++ b/net/quic/quic_session_test.cc
@@ -32,10 +32,13 @@ #include "testing/gmock_mutant.h" #include "testing/gtest/include/gtest/gtest.h" +using net::SpdyHeaderBlock; +using net::SpdyPriority; using std::set; using std::string; using std::vector; using testing::CreateFunctor; +using testing::AtLeast; using testing::InSequence; using testing::Invoke; using testing::Return; @@ -721,7 +724,7 @@ EXPECT_FALSE(stream2->flow_controller()->IsBlocked()); EXPECT_FALSE(session_.IsConnectionFlowControlBlocked()); EXPECT_FALSE(session_.IsStreamFlowControlBlocked()); - EXPECT_CALL(*connection_, SendBlocked(stream2->id())); + EXPECT_CALL(*connection_, SendBlocked(_)).Times(AtLeast(1)); EXPECT_CALL(*connection_, SendBlocked(0)); stream2->WriteOrBufferBody(body, false, nullptr); EXPECT_TRUE(stream2->flow_controller()->IsBlocked()); @@ -1118,6 +1121,16 @@ kDefaultMaxStreamsPerConnection); } +TEST_P(QuicSessionTestServer, EnableFHOLThroughConfigOption) { + QuicConfigPeer::SetReceivedForceHolBlocking(session_.config()); + session_.OnConfigNegotiated(); + if (version() <= QUIC_VERSION_35) { + EXPECT_FALSE(session_.force_hol_blocking()); + } else { + EXPECT_TRUE(session_.force_hol_blocking()); + } +} + class QuicSessionTestClient : public QuicSessionTestBase { protected: QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {} @@ -1195,6 +1208,16 @@ 0UL); } +TEST_P(QuicSessionTestClient, EnableFHOLThroughConfigOption) { + session_.config()->SetForceHolBlocking(); + session_.OnConfigNegotiated(); + if (version() <= QUIC_VERSION_35) { + EXPECT_FALSE(session_.force_hol_blocking()); + } else { + EXPECT_TRUE(session_.force_hol_blocking()); + } +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/quic_spdy_session.cc b/net/quic/quic_spdy_session.cc index ef0a422..fe1923a 100644 --- a/net/quic/quic_spdy_session.cc +++ b/net/quic/quic_spdy_session.cc
@@ -16,7 +16,7 @@ QuicSpdySession::QuicSpdySession(QuicConnection* connection, const QuicConfig& config) - : QuicSession(connection, config) {} + : QuicSession(connection, config), force_hol_blocking_(false) {} QuicSpdySession::~QuicSpdySession() { // Set the streams' session pointers in closed and dynamic stream lists @@ -153,6 +153,32 @@ config()->HasClientSentConnectionOption(kDHDT, perspective())) { headers_stream_->DisableHpackDynamicTable(); } + const QuicVersion version = connection()->version(); + if (version > QUIC_VERSION_35 && config()->ForceHolBlocking(perspective())) { + force_hol_blocking_ = true; + // Autotuning makes sure that the headers stream flow control does + // not get in the way, and normal stream and connection level flow + // control are active anyway. This is really only for the client + // side (and mainly there just in tests and toys), where + // autotuning and/or large buffers are not enabled by default. + headers_stream_->flow_controller()->set_auto_tune_receive_window(true); + } +} + +void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id, + const char* data, + size_t len, + bool fin) { + QuicSpdyStream* stream = GetSpdyDataStream(stream_id); + if (stream == nullptr) { + return; + } + const QuicStreamOffset offset = + stream->flow_controller()->highest_received_byte_offset(); + const QuicStreamFrame frame(stream_id, fin, offset, StringPiece(data, len)); + DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id + << " offset " << offset << " len " << len << " fin " << fin; + OnStreamFrame(frame); } } // namespace net
diff --git a/net/quic/quic_spdy_session.h b/net/quic/quic_spdy_session.h index f08ad4c..28a2437 100644 --- a/net/quic/quic_spdy_session.h +++ b/net/quic/quic_spdy_session.h
@@ -100,6 +100,14 @@ void OnConfigNegotiated() override; + // Called by |headers_stream_| when |force_hol_blocking_| is true. + virtual void OnStreamFrameData(QuicStreamId stream_id, + const char* data, + size_t len, + bool fin); + + bool force_hol_blocking() const { return force_hol_blocking_; } + protected: // Override CreateIncomingDynamicStream() and CreateOutgoingDynamicStream() // with QuicSpdyStream return type to make sure that all data streams are @@ -121,6 +129,11 @@ std::unique_ptr<QuicHeadersStream> headers_stream_; + // If set, redirect all data through the headers stream in order to + // simulate forced HOL blocking between streams as happens in + // HTTP/2 over TCP. + bool force_hol_blocking_; + DISALLOW_COPY_AND_ASSIGN(QuicSpdySession); };
diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc index 7b1b3ee..3cbceb64 100644 --- a/net/quic/quic_spdy_stream.cc +++ b/net/quic/quic_spdy_stream.cc
@@ -402,4 +402,18 @@ spdy_session_ = nullptr; } +QuicConsumedData QuicSpdyStream::WritevDataInner( + QuicIOVector iov, + QuicStreamOffset offset, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate) { + if (spdy_session_->headers_stream() != nullptr && + spdy_session_->force_hol_blocking()) { + return spdy_session_->headers_stream()->WritevStreamData( + id(), iov, offset, fin, ack_notifier_delegate); + } + return ReliableQuicStream::WritevDataInner(iov, offset, fin, + ack_notifier_delegate); +} + } // namespace net
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h index 86d69a8e..01f7a29 100644 --- a/net/quic/quic_spdy_stream.h +++ b/net/quic/quic_spdy_stream.h
@@ -210,6 +210,14 @@ // Returns true if headers have been fully read and consumed. bool FinishedReadingHeaders() const; + // Redirects to the headers stream if force HOL blocking enabled, + // otherwise just pass through. + QuicConsumedData WritevDataInner( + QuicIOVector iov, + QuicStreamOffset offset, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate) override; + private: friend class test::QuicSpdyStreamPeer; friend class test::ReliableQuicStreamPeer;
diff --git a/net/quic/quic_spdy_stream_test.cc b/net/quic/quic_spdy_stream_test.cc index a869ded..94be546b 100644 --- a/net/quic/quic_spdy_stream_test.cc +++ b/net/quic/quic_spdy_stream_test.cc
@@ -444,7 +444,7 @@ GenerateBody(&body, kWindow + kOverflow); EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)); - EXPECT_CALL(*session_, WritevData(stream_, kClientDataStreamId1, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kWindow, true))); stream_->WriteOrBufferData(body, false, nullptr); @@ -690,7 +690,7 @@ bool fin = true; EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); - EXPECT_CALL(*session_, WritevData(stream_, kClientDataStreamId1, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, fin))); stream_->WriteOrBufferData(body, fin, nullptr); @@ -966,14 +966,18 @@ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kBodySize - 1, false))); stream_->WriteOrBufferData(string(kBodySize, 'x'), false, nullptr); - EXPECT_EQ(1u, stream_->queued_data_bytes()); + if (!session_->force_hol_blocking()) { + EXPECT_EQ(1u, stream_->queued_data_bytes()); + } // Writing trailers will send a FIN, but not close the write side of the // stream as there are queued bytes. EXPECT_CALL(*session_, WriteHeadersMock(_, _, true, _, _)); stream_->WriteTrailers(SpdyHeaderBlock(), nullptr); EXPECT_TRUE(stream_->fin_sent()); - EXPECT_FALSE(stream_->write_side_closed()); + if (!session_->force_hol_blocking()) { + EXPECT_FALSE(stream_->write_side_closed()); + } } TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc index da26cc52f..f6f0182 100644 --- a/net/quic/quic_stream_sequencer.cc +++ b/net/quic/quic_stream_sequencer.cc
@@ -19,6 +19,7 @@ #include "net/quic/quic_utils.h" #include "net/quic/reliable_quic_stream.h" +using base::IntToString; using base::StringPiece; using std::min; using std::numeric_limits; @@ -158,7 +159,7 @@ if (!result) { QUIC_BUG << "Invalid argument to MarkConsumed." << " expect to consume: " << num_bytes_consumed - << ", but not enough bytes available."; + << ", but not enough bytes available. " << DebugString(); stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); return; } @@ -202,4 +203,16 @@ return buffered_frames_.BytesConsumed(); } +const string QuicStreamSequencer::DebugString() const { + // clang-format off + return "QuicStreamSequencer:" + "\n bytes buffered: " + IntToString(NumBytesBuffered()) + + "\n bytes consumed: " + IntToString( NumBytesConsumed()) + + "\n has bytes to read: " + (HasBytesToRead() ? "true" : "false") + + "\n frames received: " + IntToString(num_frames_received()) + + "\n close offset bytes: " + IntToString( close_offset_) + + "\n is closed: " + (IsClosed() ? "true" : "false"); + // clang-format on +} + } // namespace net
diff --git a/net/quic/quic_stream_sequencer.h b/net/quic/quic_stream_sequencer.h index 3f37a7ec..d0e5d93a 100644 --- a/net/quic/quic_stream_sequencer.h +++ b/net/quic/quic_stream_sequencer.h
@@ -95,6 +95,9 @@ bool ignore_read_data() const { return ignore_read_data_; } + // Returns std::string describing internal state. + const std::string DebugString() const; + private: friend class test::QuicStreamSequencerPeer;
diff --git a/net/quic/quic_sustained_bandwidth_recorder.cc b/net/quic/quic_sustained_bandwidth_recorder.cc index 41aa51e70..b4b4a61 100644 --- a/net/quic/quic_sustained_bandwidth_recorder.cc +++ b/net/quic/quic_sustained_bandwidth_recorder.cc
@@ -41,7 +41,7 @@ // If we have been recording for at least 3 * srtt, then record the latest // bandwidth estimate as a valid sustained bandwidth estimate. - if (estimate_time.Subtract(start_time_) >= srtt.Multiply(3)) { + if (estimate_time - start_time_ >= 3 * srtt) { has_estimate_ = true; bandwidth_estimate_recorded_during_slow_start_ = in_slow_start; bandwidth_estimate_ = bandwidth;
diff --git a/net/quic/quic_sustained_bandwidth_recorder_test.cc b/net/quic/quic_sustained_bandwidth_recorder_test.cc index 91cff412..c369907 100644 --- a/net/quic/quic_sustained_bandwidth_recorder_test.cc +++ b/net/quic/quic_sustained_bandwidth_recorder_test.cc
@@ -33,14 +33,14 @@ // Send a second reading, again this should not result in a valid estimate, // as not enough time has passed. - estimate_time = estimate_time.Add(srtt); + estimate_time = estimate_time + srtt; recorder.RecordEstimate(in_recovery, in_slow_start, bandwidth, estimate_time, wall_time, srtt); EXPECT_FALSE(recorder.HasEstimate()); // Now 3 * kSRTT has elapsed since first recording, expect a valid estimate. - estimate_time = estimate_time.Add(srtt); - estimate_time = estimate_time.Add(srtt); + estimate_time = estimate_time + srtt; + estimate_time = estimate_time + srtt; recorder.RecordEstimate(in_recovery, in_slow_start, bandwidth, estimate_time, wall_time, srtt); EXPECT_TRUE(recorder.HasEstimate()); @@ -60,7 +60,7 @@ wall_time, srtt); EXPECT_EQ(recorder.BandwidthEstimate(), bandwidth); - estimate_time = estimate_time.Add(srtt.Multiply(3)); + estimate_time = estimate_time + 3 * srtt; const int64_t kSeconds = 556677; QuicWallTime second_bandwidth_wall_time = QuicWallTime::FromUNIXSeconds(kSeconds); @@ -80,7 +80,7 @@ estimate_time, wall_time, srtt); EXPECT_EQ(recorder.BandwidthEstimate(), third_bandwidth); - estimate_time = estimate_time.Add(srtt.Multiply(3)); + estimate_time = estimate_time + 3 * srtt; recorder.RecordEstimate(in_recovery, in_slow_start, third_bandwidth, estimate_time, wall_time, srtt); EXPECT_EQ(recorder.BandwidthEstimate(), third_bandwidth); @@ -111,14 +111,14 @@ wall_time, srtt); // Now 3 * kSRTT has elapsed since first recording, expect a valid estimate. - estimate_time = estimate_time.Add(srtt.Multiply(3)); + estimate_time = estimate_time + 3 * srtt; recorder.RecordEstimate(in_recovery, in_slow_start, bandwidth, estimate_time, wall_time, srtt); EXPECT_TRUE(recorder.HasEstimate()); EXPECT_TRUE(recorder.EstimateRecordedDuringSlowStart()); // Now send another estimate, this time not in slow start. - estimate_time = estimate_time.Add(srtt.Multiply(3)); + estimate_time = estimate_time + 3 * srtt; in_slow_start = false; recorder.RecordEstimate(in_recovery, in_slow_start, bandwidth, estimate_time, wall_time, srtt);
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h index 63b2a34..3c5a670 100644 --- a/net/quic/quic_time.h +++ b/net/quic/quic_time.h
@@ -70,22 +70,6 @@ // Converts the time offset to a rounded number of microseconds. inline int64_t ToMicroseconds() const { return time_offset_; } - inline Delta Add(Delta delta) const WARN_UNUSED_RESULT { - return Delta(time_offset_ + delta.time_offset_); - } - - inline Delta Subtract(Delta delta) const WARN_UNUSED_RESULT { - return Delta(time_offset_ - delta.time_offset_); - } - - inline Delta Multiply(int i) const WARN_UNUSED_RESULT { - return Delta(time_offset_ * i); - } - - inline Delta Multiply(double d) const WARN_UNUSED_RESULT { - return Delta(time_offset_ * d); - } - // Returns the larger delta of time1 and time2. static inline Delta Max(Delta delta1, Delta delta2) { return delta1 < delta2 ? delta2 : delta1; @@ -109,8 +93,19 @@ friend inline QuicTime::Delta operator<<(QuicTime::Delta lhs, size_t rhs); friend inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs); - // Highest number of microseconds that DateTimeOffset can hold. - static const int64_t kQuicInfiniteTimeUs = INT64_C(0x7fffffffffffffff) / 10; + friend inline QuicTime::Delta operator+(QuicTime::Delta lhs, + QuicTime::Delta rhs); + friend inline QuicTime::Delta operator-(QuicTime::Delta lhs, + QuicTime::Delta rhs); + friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs); + friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs); + + friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs); + friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs); + friend inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs); + + static const int64_t kQuicInfiniteTimeUs = + std::numeric_limits<int64_t>::max(); explicit QUICTIME_CONSTEXPR Delta(int64_t time_offset) : time_offset_(time_offset) {} @@ -144,23 +139,12 @@ inline bool IsInitialized() const { return 0 != time_; } - inline QuicTime Add(Delta delta) const WARN_UNUSED_RESULT { - return QuicTime(time_ + delta.time_offset_); - } - - inline QuicTime Subtract(Delta delta) const WARN_UNUSED_RESULT { - return QuicTime(time_ - delta.time_offset_); - } - - inline Delta Subtract(QuicTime other) const WARN_UNUSED_RESULT { - return Delta(time_ - other.time_); - } - private: friend inline bool operator==(QuicTime lhs, QuicTime rhs); friend inline bool operator<(QuicTime lhs, QuicTime rhs); - friend class QuicClock; - friend class QuicClockTest; + friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs); + friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs); + friend inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs); explicit QUICTIME_CONSTEXPR QuicTime(int64_t time) : time_(time) {} @@ -169,7 +153,7 @@ // A QuicWallTime represents an absolute time that is globally consistent. In // practice, clock-skew means that comparing values from different machines -// requires some flexibility in interpretation. +// requires some flexibility. class NET_EXPORT_PRIVATE QuicWallTime { public: // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds @@ -263,6 +247,37 @@ return !(lhs < rhs); } +// Non-member arithmetic operators for QuicTime::Delta. +inline QuicTime::Delta operator+(QuicTime::Delta lhs, QuicTime::Delta rhs) { + return QuicTime::Delta(lhs.time_offset_ + rhs.time_offset_); +} +inline QuicTime::Delta operator-(QuicTime::Delta lhs, QuicTime::Delta rhs) { + return QuicTime::Delta(lhs.time_offset_ - rhs.time_offset_); +} +inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs) { + return QuicTime::Delta(lhs.time_offset_ * rhs); +} +inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) { + return QuicTime::Delta(lhs.time_offset_ * rhs); +} +inline QuicTime::Delta operator*(int lhs, QuicTime::Delta rhs) { + return rhs * lhs; +} +inline QuicTime::Delta operator*(double lhs, QuicTime::Delta rhs) { + return rhs * lhs; +} + +// Non-member arithmetic operators for QuicTime and QuicTime::Delta. +inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs) { + return QuicTime(lhs.time_ + rhs.time_offset_); +} +inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs) { + return QuicTime(lhs.time_ - rhs.time_offset_); +} +inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs) { + return QuicTime::Delta(lhs.time_ - rhs.time_); +} + } // namespace net #endif // NET_QUIC_QUIC_TIME_H_
diff --git a/net/quic/quic_time_test.cc b/net/quic/quic_time_test.cc index 602de36..9bdba53 100644 --- a/net/quic/quic_time_test.cc +++ b/net/quic/quic_time_test.cc
@@ -39,22 +39,26 @@ TEST(QuicTimeDeltaTest, Add) { EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2000), - QuicTime::Delta::Zero().Add(QuicTime::Delta::FromMilliseconds(2))); + QuicTime::Delta::Zero() + QuicTime::Delta::FromMilliseconds(2)); } TEST(QuicTimeDeltaTest, Subtract) { EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1000), - QuicTime::Delta::FromMilliseconds(2).Subtract( - QuicTime::Delta::FromMilliseconds(1))); + QuicTime::Delta::FromMilliseconds(2) - + QuicTime::Delta::FromMilliseconds(1)); } TEST(QuicTimeDeltaTest, Multiply) { int i = 2; EXPECT_EQ(QuicTime::Delta::FromMicroseconds(4000), - QuicTime::Delta::FromMilliseconds(2).Multiply(i)); + QuicTime::Delta::FromMilliseconds(2) * i); + EXPECT_EQ(QuicTime::Delta::FromMicroseconds(4000), + i * QuicTime::Delta::FromMilliseconds(2)); double d = 2; EXPECT_EQ(QuicTime::Delta::FromMicroseconds(4000), - QuicTime::Delta::FromMilliseconds(2).Multiply(d)); + QuicTime::Delta::FromMilliseconds(2) * d); + EXPECT_EQ(QuicTime::Delta::FromMicroseconds(4000), + d * QuicTime::Delta::FromMilliseconds(2)); } TEST(QuicTimeDeltaTest, Max) { @@ -77,16 +81,15 @@ TEST_F(QuicTimeTest, Initialized) { EXPECT_FALSE(QuicTime::Zero().IsInitialized()); - EXPECT_TRUE(QuicTime::Zero() - .Add(QuicTime::Delta::FromMicroseconds(1)) + EXPECT_TRUE((QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(1)) .IsInitialized()); } TEST_F(QuicTimeTest, Add) { - QuicTime time_1 = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1)); - QuicTime time_2 = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2)); + QuicTime time_1 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1); + QuicTime time_2 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); - QuicTime::Delta diff = time_2.Subtract(time_1); + QuicTime::Delta diff = time_2 - time_1; EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1), diff); EXPECT_EQ(1000, diff.ToMicroseconds()); @@ -94,21 +97,21 @@ } TEST_F(QuicTimeTest, Subtract) { - QuicTime time_1 = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1)); - QuicTime time_2 = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2)); + QuicTime time_1 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1); + QuicTime time_2 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1), time_2.Subtract(time_1)); + EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1), time_2 - time_1); } TEST_F(QuicTimeTest, SubtractDelta) { - QuicTime time = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2)); - EXPECT_EQ(QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1)), - time.Subtract(QuicTime::Delta::FromMilliseconds(1))); + QuicTime time = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); + EXPECT_EQ(QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1), + time - QuicTime::Delta::FromMilliseconds(1)); } TEST_F(QuicTimeTest, Max) { - QuicTime time_1 = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1)); - QuicTime time_2 = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2)); + QuicTime time_1 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1); + QuicTime time_2 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); EXPECT_EQ(time_2, QuicTime::Max(time_1, time_2)); } @@ -117,7 +120,7 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); QuicTime now = clock_.ApproximateNow(); - QuicTime time = QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(1000)); + QuicTime time = QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(1000); EXPECT_EQ(now, time); @@ -126,13 +129,13 @@ EXPECT_NE(now, time); - time = time.Add(QuicTime::Delta::FromMilliseconds(1)); + time = time + QuicTime::Delta::FromMilliseconds(1); EXPECT_EQ(now, time); } TEST_F(QuicTimeTest, LE) { const QuicTime zero = QuicTime::Zero(); - const QuicTime one = zero.Add(QuicTime::Delta::FromSeconds(1)); + const QuicTime one = zero + QuicTime::Delta::FromSeconds(1); EXPECT_TRUE(zero <= zero); EXPECT_TRUE(zero <= one); EXPECT_TRUE(one <= one);
diff --git a/net/quic/quic_unacked_packet_map_test.cc b/net/quic/quic_unacked_packet_map_test.cc index 26a0043..5d85da9 100644 --- a/net/quic/quic_unacked_packet_map_test.cc +++ b/net/quic/quic_unacked_packet_map_test.cc
@@ -24,7 +24,7 @@ protected: QuicUnackedPacketMapTest() : unacked_packets_(), - now_(QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(1000))) {} + now_(QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1000)) {} ~QuicUnackedPacketMapTest() override { STLDeleteElements(&packets_); }
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc index 1af16db..0fddb62 100644 --- a/net/quic/quic_utils.cc +++ b/net/quic/quic_utils.cc
@@ -569,16 +569,39 @@ return out; } -string QuicUtils::BinaryToAscii(StringPiece binary) { +string QuicUtils::HexDump(StringPiece binary_input) { string out = ""; - for (const unsigned char c : binary) { - // Leading space. - out += " "; - if (isprint(c)) { - out += c; - } else { - out += '.'; + const int kBytesPerRow = 16; + const int size = binary_input.size(); + for (int i = 0; i < size;) { + // Print one row of hex. + for (int j = i; j < i + kBytesPerRow; ++j) { + if (j < size) { + out += HexEncode(string(1, binary_input[j])); + } else { + out += " "; + } + out += " "; } + out += " |"; + + // Print one row of ascii. + for (int j = i; j < i + kBytesPerRow; ++j) { + if (j < size) { + char c = binary_input[j]; + bool is_printable = (c >= 32 && c < 127); + if (!is_printable) { + // Non-printable characters are replaced with '.'. + c = '.'; + } + out += string(1, c); + } else { + out += " "; + } + } + + out += "|\n"; + i += kBytesPerRow; } return out; }
diff --git a/net/quic/quic_utils.h b/net/quic/quic_utils.h index 69e8372..726cef4 100644 --- a/net/quic/quic_utils.h +++ b/net/quic/quic_utils.h
@@ -143,9 +143,12 @@ static std::string HexDecode(const char* data, size_t length); static std::string HexDecode(base::StringPiece data); - // Converts binary data into an ASCII string. Each character in the resulting - // string is preceeded by a space, and replaced with a '.' if not printable. - static std::string BinaryToAscii(base::StringPiece binary); + // Returns a std::string containing hex and ASCII representations of |binary|, + // side-by-side in the style of hexdump. Non-printable characters will be + // printed as '.' in the ASCII output. + // For example: + // "48 65 6c 6c 6f 2c 20 51 55 49 43 21 01 02 03 04 |Hello, QUIC!....|" + static std::string HexDump(base::StringPiece binary_data); private: DISALLOW_COPY_AND_ASSIGN(QuicUtils);
diff --git a/net/quic/quic_utils_test.cc b/net/quic/quic_utils_test.cc index 7412a24..e8e864b 100644 --- a/net/quic/quic_utils_test.cc +++ b/net/quic/quic_utils_test.cc
@@ -185,6 +185,27 @@ reinterpret_cast<const char*>(data.data()), data.size())); } +TEST(QuicUtilsTest, HexDump) { + // Verify output of the HexDump method is as expected. + char packet[] = { + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21, + 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c, + 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74, + 0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00, + }; + EXPECT_EQ( + QuicUtils::HexDump(packet), + "48 65 6C 6C 6F 2C 20 51 55 49 43 21 20 54 68 69 |Hello, QUIC! Thi|\n" + "73 20 73 74 72 69 6E 67 20 73 68 6F 75 6C 64 20 |s string should |\n" + "62 65 20 6C 6F 6E 67 20 65 6E 6F 75 67 68 20 74 |be long enough t|\n" + "6F 20 73 70 61 6E 20 6D 75 6C 74 69 70 6C 65 20 |o span multiple |\n" + "6C 69 6E 65 73 20 6F 66 20 6F 75 74 70 75 74 2E |lines of output.|\n" + "01 02 03 |... |\n"); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc index c7d3b6ac..749749b1 100644 --- a/net/quic/reliable_quic_stream.cc +++ b/net/quic/reliable_quic_stream.cc
@@ -290,7 +290,7 @@ min(send_window, connection_flow_controller_->SendWindowSize()); } - if (FLAGS_quic_cede_correctly && session_->ShouldYield(id())) { + if (session_->ShouldYield(id())) { session_->MarkConnectionLevelWriteBlocked(id()); return QuicConsumedData(0, false); } @@ -309,9 +309,9 @@ write_length = static_cast<size_t>(send_window); } - QuicConsumedData consumed_data = session()->WritevData( - this, id(), QuicIOVector(iov, iov_count, write_length), - stream_bytes_written_, fin, ack_listener); + QuicConsumedData consumed_data = + WritevDataInner(QuicIOVector(iov, iov_count, write_length), + stream_bytes_written_, fin, ack_listener); stream_bytes_written_ += consumed_data.bytes_consumed; AddBytesSent(consumed_data.bytes_consumed); @@ -341,6 +341,15 @@ return consumed_data; } +QuicConsumedData ReliableQuicStream::WritevDataInner( + QuicIOVector iov, + QuicStreamOffset offset, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate) { + return session()->WritevData(this, id(), iov, offset, fin, + ack_notifier_delegate); +} + void ReliableQuicStream::CloseReadSide() { if (read_side_closed_) { return;
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h index da320363..67bc4b8b 100644 --- a/net/quic/reliable_quic_stream.h +++ b/net/quic/reliable_quic_stream.h
@@ -191,6 +191,14 @@ bool fin, QuicAckListenerInterface* ack_listener); + // Allows override of the session level writev, for the force HOL + // blocking experiment. + virtual QuicConsumedData WritevDataInner( + QuicIOVector iov, + QuicStreamOffset offset, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate); + // Close the write side of the socket. Further writes will fail. // Can be called by the subclass or internally. // Does not send a FIN. May cause the stream to be closed.
diff --git a/net/quic/test_tools/mock_clock.cc b/net/quic/test_tools/mock_clock.cc index 63e088a0..524f4341 100644 --- a/net/quic/test_tools/mock_clock.cc +++ b/net/quic/test_tools/mock_clock.cc
@@ -11,7 +11,7 @@ MockClock::~MockClock() {} void MockClock::AdvanceTime(QuicTime::Delta delta) { - now_ = now_.Add(delta); + now_ = now_ + delta; } QuicTime MockClock::Now() const { @@ -23,14 +23,13 @@ } QuicWallTime MockClock::WallNow() const { - return QuicWallTime::FromUNIXSeconds( - now_.Subtract(QuicTime::Zero()).ToSeconds()); + return QuicWallTime::FromUNIXSeconds((now_ - QuicTime::Zero()).ToSeconds()); } base::TimeTicks MockClock::NowInTicks() const { base::TimeTicks ticks; return ticks + base::TimeDelta::FromMicroseconds( - now_.Subtract(QuicTime::Zero()).ToMicroseconds()); + (now_ - QuicTime::Zero()).ToMicroseconds()); } } // namespace net
diff --git a/net/quic/test_tools/quic_config_peer.cc b/net/quic/test_tools/quic_config_peer.cc index 0d60ba8..f272e9ad 100644 --- a/net/quic/test_tools/quic_config_peer.cc +++ b/net/quic/test_tools/quic_config_peer.cc
@@ -59,10 +59,15 @@ } // static + void QuicConfigPeer::SetConnectionOptionsToSend(QuicConfig* config, const QuicTagVector& options) { config->SetConnectionOptionsToSend(options); } +void QuicConfigPeer::SetReceivedForceHolBlocking(QuicConfig* config) { + config->force_hol_blocking_.SetReceivedValue(1); +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/quic_config_peer.h b/net/quic/test_tools/quic_config_peer.h index bbcf98d..4c9f3cb 100644 --- a/net/quic/test_tools/quic_config_peer.h +++ b/net/quic/test_tools/quic_config_peer.h
@@ -41,6 +41,8 @@ static void SetConnectionOptionsToSend(QuicConfig* config, const QuicTagVector& options); + static void SetReceivedForceHolBlocking(QuicConfig* config); + private: DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer); };
diff --git a/net/quic/test_tools/quic_session_peer.cc b/net/quic/test_tools/quic_session_peer.cc index 14c1475..953aaec 100644 --- a/net/quic/test_tools/quic_session_peer.cc +++ b/net/quic/test_tools/quic_session_peer.cc
@@ -61,7 +61,8 @@ } // static -QuicSession::StreamMap& QuicSessionPeer::static_streams(QuicSession* session) { +QuicSession::StaticStreamMap& QuicSessionPeer::static_streams( + QuicSession* session) { return session->static_streams(); }
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h index 19dd88d6..edc77be 100644 --- a/net/quic/test_tools/quic_session_peer.h +++ b/net/quic/test_tools/quic_session_peer.h
@@ -38,7 +38,7 @@ QuicStreamId stream_id); static std::map<QuicStreamId, QuicStreamOffset>& GetLocallyClosedStreamsHighestOffset(QuicSession* session); - static QuicSession::StreamMap& static_streams(QuicSession* session); + static QuicSession::StaticStreamMap& static_streams(QuicSession* session); static std::unordered_set<QuicStreamId>* GetDrainingStreams( QuicSession* session); static void ActivateStream(QuicSession* session, ReliableQuicStream* stream);
diff --git a/net/quic/test_tools/quic_spdy_session_peer.cc b/net/quic/test_tools/quic_spdy_session_peer.cc index e13e477..de80802 100644 --- a/net/quic/test_tools/quic_spdy_session_peer.cc +++ b/net/quic/test_tools/quic_spdy_session_peer.cc
@@ -22,5 +22,11 @@ session->static_streams()[headers_stream->id()] = headers_stream; } +// static +void QuicSpdySessionPeer::SetForceHolBlocking(QuicSpdySession* session, + bool value) { + session->force_hol_blocking_ = value; +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/quic_spdy_session_peer.h b/net/quic/test_tools/quic_spdy_session_peer.h index d6597c75..7f87287 100644 --- a/net/quic/test_tools/quic_spdy_session_peer.h +++ b/net/quic/test_tools/quic_spdy_session_peer.h
@@ -21,6 +21,7 @@ static QuicHeadersStream* GetHeadersStream(QuicSpdySession* session); static void SetHeadersStream(QuicSpdySession* session, QuicHeadersStream* headers_stream); + static void SetForceHolBlocking(QuicSpdySession* session, bool value); private: DISALLOW_COPY_AND_ASSIGN(QuicSpdySessionPeer);
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index dd0d83d..b770728d 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h
@@ -625,6 +625,9 @@ SpdyPriority priority, QuicAckListenerInterface* ack_notifier_delegate)); MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta)); + MOCK_METHOD4( + OnStreamFrameData, + void(QuicStreamId stream_id, const char* data, size_t len, bool fin)); using QuicSession::ActivateStream;
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index d1edfbb..97a3997 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -1208,10 +1208,10 @@ if (IsRenegotiationAllowed()) SSL_set_renegotiate_mode(ssl_, ssl_renegotiate_freely); - uint8_t server_key_exchange_hash = SSL_get_server_key_exchange_hash(ssl_); - if (server_key_exchange_hash != TLSEXT_hash_none) { - UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLServerKeyExchangeHash", - server_key_exchange_hash); + uint16_t signature_algorithm = SSL_get_peer_signature_algorithm(ssl_); + if (signature_algorithm != 0) { + UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLSignatureAlgorithm", + signature_algorithm); } // Verify the certificate.
diff --git a/net/spdy/hpack/hpack_decoder.cc b/net/spdy/hpack/hpack_decoder.cc index 1352dc35..d2d90a4 100644 --- a/net/spdy/hpack/hpack_decoder.cc +++ b/net/spdy/hpack/hpack_decoder.cc
@@ -103,7 +103,7 @@ return true; } -const SpdyHeaderBlock& HpackDecoder::decoded_block() { +const SpdyHeaderBlock& HpackDecoder::decoded_block() const { return decoded_block_; }
diff --git a/net/spdy/hpack/hpack_decoder.h b/net/spdy/hpack/hpack_decoder.h index 6af2721..f4134a4 100644 --- a/net/spdy/hpack/hpack_decoder.h +++ b/net/spdy/hpack/hpack_decoder.h
@@ -68,7 +68,7 @@ // call to HandleControlFrameHeadersData(). // TODO(birenroy): Remove this method when all users of HpackDecoder specify // a SpdyHeadersHandlerInterface. - const SpdyHeaderBlock& decoded_block() override; + const SpdyHeaderBlock& decoded_block() const override; void SetHeaderTableDebugVisitor( std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor)
diff --git a/net/spdy/hpack/hpack_decoder_interface.h b/net/spdy/hpack/hpack_decoder_interface.h index 1a7cdd7..76e6b2b 100644 --- a/net/spdy/hpack/hpack_decoder_interface.h +++ b/net/spdy/hpack/hpack_decoder_interface.h
@@ -51,7 +51,7 @@ // call to HandleControlFrameHeadersData(). // TODO(birenroy): Remove this method when all users of HpackDecoder specify // a SpdyHeadersHandlerInterface. - virtual const SpdyHeaderBlock& decoded_block() = 0; + virtual const SpdyHeaderBlock& decoded_block() const = 0; virtual void SetHeaderTableDebugVisitor( std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) = 0;
diff --git a/net/spdy/hpack/hpack_decoder_test.cc b/net/spdy/hpack/hpack_decoder_test.cc index 8657a35..8c711d7 100644 --- a/net/spdy/hpack/hpack_decoder_test.cc +++ b/net/spdy/hpack/hpack_decoder_test.cc
@@ -35,9 +35,6 @@ return decoder_->DecodeNextName(in, out); } HpackHeaderTable* header_table() { return &decoder_->header_table_; } - const SpdyHeaderBlock& decoded_block() const { - return decoder_->decoded_block_; - } bool DecodeNextStringLiteral(HpackInputStream* in, bool is_header_key, @@ -88,7 +85,7 @@ if (handler_exists_) { return handler_.decoded_block(); } else { - return decoder_peer_.decoded_block(); + return decoder_.decoded_block(); } }
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 5cb0edc..0a9066d 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -356,7 +356,6 @@ enable_ip_pooling(true), enable_ping(false), enable_user_alternate_protocol_ports(false), - enable_npn(false), enable_priority_dependencies(true), enable_spdy31(true), enable_quic(false), @@ -416,7 +415,6 @@ params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping; params.enable_user_alternate_protocol_ports = session_deps->enable_user_alternate_protocol_ports; - params.enable_npn = session_deps->enable_npn; params.enable_priority_dependencies = session_deps->enable_priority_dependencies; params.enable_spdy31 = session_deps->enable_spdy31;
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index acfeaee3..252ecd8 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -203,7 +203,6 @@ bool enable_ip_pooling; bool enable_ping; bool enable_user_alternate_protocol_ports; - bool enable_npn; bool enable_priority_dependencies; bool enable_spdy31; bool enable_quic;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 7f4451c..381ebabd 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -29,6 +29,7 @@ #include "net/quic/quic_session.h" #include "net/quic/quic_utils.h" #include "net/quic/test_tools/crypto_test_utils.h" +#include "net/quic/test_tools/quic_config_peer.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_flow_controller_peer.h" #include "net/quic/test_tools/quic_sent_packet_manager_peer.h" @@ -99,7 +100,8 @@ bool server_uses_stateless_rejects_if_peer_supported, QuicTag congestion_control_tag, bool auto_tune_flow_control_window, - bool disable_hpack_dynamic_table) + bool disable_hpack_dynamic_table, + bool force_hol_blocking) : client_supported_versions(client_supported_versions), server_supported_versions(server_supported_versions), negotiated_version(negotiated_version), @@ -108,7 +110,8 @@ server_uses_stateless_rejects_if_peer_supported), congestion_control_tag(congestion_control_tag), auto_tune_flow_control_window(auto_tune_flow_control_window), - disable_hpack_dynamic_table(disable_hpack_dynamic_table) {} + disable_hpack_dynamic_table(disable_hpack_dynamic_table), + force_hol_blocking(force_hol_blocking) {} friend ostream& operator<<(ostream& os, const TestParams& p) { os << "{ server_supported_versions: " @@ -123,8 +126,8 @@ os << " congestion_control_tag: " << QuicUtils::TagToString(p.congestion_control_tag); os << " auto_tune_flow_control_window: " << p.auto_tune_flow_control_window; - os << " disable_hpack_dynamic_table: " << p.disable_hpack_dynamic_table - << " }"; + os << " disable_hpack_dynamic_table: " << p.disable_hpack_dynamic_table; + os << " force_hol_blocking: " << p.force_hol_blocking << " }"; return os; } @@ -136,6 +139,7 @@ QuicTag congestion_control_tag; bool auto_tune_flow_control_window; bool disable_hpack_dynamic_table; + bool force_hol_blocking; }; // Constructs various test permutations. @@ -181,72 +185,80 @@ for (bool client_supports_stateless_rejects : {true, false}) { for (const QuicTag congestion_control_tag : {kRENO, kQBIC}) { for (bool auto_tune_flow_control_window : {true, false}) { - for (bool disable_hpack_dynamic_table : {true, false}) { - int enabled_options = 0; - if (congestion_control_tag != kQBIC) { - ++enabled_options; - } - if (auto_tune_flow_control_window) { - ++enabled_options; - } - if (disable_hpack_dynamic_table) { - ++enabled_options; - } - if (client_supports_stateless_rejects) { - ++enabled_options; - } - if (server_uses_stateless_rejects_if_peer_supported) { - ++enabled_options; - } - CHECK_GE(kMaxEnabledOptions, enabled_options); - if (enabled_options > max_enabled_options) { - max_enabled_options = enabled_options; - } - - // Run tests with no options, a single option, or all the options - // enabled to avoid a combinatorial explosion. - if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) { - continue; - } - - for (const QuicVersionVector& client_versions : version_buckets) { - if (client_versions.front() < QUIC_VERSION_30 && - FLAGS_quic_disable_pre_30) { - continue; + for (bool disable_hpack_dynamic_table : {false}) { + for (bool force_hol_blocking : {true, false}) { + int enabled_options = 0; + if (force_hol_blocking) { + ++enabled_options; } - CHECK(!client_versions.empty()); - // Add an entry for server and client supporting all versions. - params.push_back(TestParams( - client_versions, all_supported_versions, - client_versions.front(), client_supports_stateless_rejects, - server_uses_stateless_rejects_if_peer_supported, - congestion_control_tag, auto_tune_flow_control_window, - disable_hpack_dynamic_table)); + if (congestion_control_tag != kQBIC) { + ++enabled_options; + } + if (auto_tune_flow_control_window) { + ++enabled_options; + } + if (disable_hpack_dynamic_table) { + ++enabled_options; + } + if (client_supports_stateless_rejects) { + ++enabled_options; + } + if (server_uses_stateless_rejects_if_peer_supported) { + ++enabled_options; + } + CHECK_GE(kMaxEnabledOptions, enabled_options); + if (enabled_options > max_enabled_options) { + max_enabled_options = enabled_options; + } - // Run version negotiation tests tests with no options, or all - // the options enabled to avoid a combinatorial explosion. - if (enabled_options > 0 && enabled_options < kMaxEnabledOptions) { + // Run tests with no options, a single option, or all the options + // enabled to avoid a combinatorial explosion. + if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) { continue; } - // Test client supporting all versions and server supporting 1 - // version. Simulate an old server and exercise version downgrade - // in the client. Protocol negotiation should occur. Skip the i = - // 0 case because it is essentially the same as the default case. - for (size_t i = 1; i < client_versions.size(); ++i) { - if (client_versions[i] < QUIC_VERSION_30 && + for (const QuicVersionVector& client_versions : version_buckets) { + if (client_versions.front() < QUIC_VERSION_30 && FLAGS_quic_disable_pre_30) { continue; } - QuicVersionVector server_supported_versions; - server_supported_versions.push_back(client_versions[i]); + CHECK(!client_versions.empty()); + // Add an entry for server and client supporting all versions. params.push_back(TestParams( - client_versions, server_supported_versions, - server_supported_versions.front(), - client_supports_stateless_rejects, + client_versions, all_supported_versions, + client_versions.front(), client_supports_stateless_rejects, server_uses_stateless_rejects_if_peer_supported, congestion_control_tag, auto_tune_flow_control_window, - disable_hpack_dynamic_table)); + disable_hpack_dynamic_table, force_hol_blocking)); + + // Run version negotiation tests tests with no options, or all + // the options enabled to avoid a combinatorial explosion. + if (enabled_options > 0 && + enabled_options < kMaxEnabledOptions) { + continue; + } + + // Test client supporting all versions and server + // supporting 1 version. Simulate an old server and + // exercise version downgrade in the client. Protocol + // negotiation should occur. Skip the i = 0 case + // because it is essentially the same as the default + // case. + for (size_t i = 1; i < client_versions.size(); ++i) { + if (client_versions[i] < QUIC_VERSION_30 && + FLAGS_quic_disable_pre_30) { + continue; + } + QuicVersionVector server_supported_versions; + server_supported_versions.push_back(client_versions[i]); + params.push_back(TestParams( + client_versions, server_supported_versions, + server_supported_versions.front(), + client_supports_stateless_rejects, + server_uses_stateless_rejects_if_peer_supported, + congestion_control_tag, auto_tune_flow_control_window, + disable_hpack_dynamic_table, force_hol_blocking)); + } } } } @@ -402,6 +414,10 @@ if (GetParam().disable_hpack_dynamic_table) { copt.push_back(kDHDT); } + if (GetParam().force_hol_blocking) { + client_config_.SetForceHolBlocking(); + QuicConfigPeer::SetReceivedForceHolBlocking(&server_config_); + } client_config_.SetConnectionOptionsToSend(copt); // Start the server first, because CreateQuicClient() attempts @@ -509,7 +525,7 @@ void VerifyCleanConnection(bool had_packet_loss) { QuicConnectionStats client_stats = client_->client()->session()->connection()->GetStats(); - if (FLAGS_quic_reply_to_rej && !had_packet_loss) { + if (!had_packet_loss) { EXPECT_EQ(0u, client_stats.packets_lost); } EXPECT_EQ(0u, client_stats.packets_discarded); @@ -534,7 +550,7 @@ ASSERT_EQ(1u, dispatcher->session_map().size()); QuicSession* session = dispatcher->session_map().begin()->second; QuicConnectionStats server_stats = session->connection()->GetStats(); - if (FLAGS_quic_reply_to_rej && !had_packet_loss) { + if (!had_packet_loss) { EXPECT_EQ(0u, server_stats.packets_lost); } EXPECT_EQ(0u, server_stats.packets_discarded); @@ -579,6 +595,7 @@ size_t chlo_multiplier_; QuicTestServer::StreamFactory* stream_factory_; bool support_server_push_; + bool force_hol_blocking_; }; // Run all end to end tests with all supported versions.
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h index 99e529c..0beccc1 100644 --- a/net/tools/quic/quic_client.h +++ b/net/tools/quic/quic_client.h
@@ -171,7 +171,11 @@ const IPEndPoint& server_address() const { return server_address_; } - // Takes ownership of the listener. + void set_server_address(const IPEndPoint& server_address) { + server_address_ = server_address; + } + + // Takes ownership of the std::listener. void set_response_listener(ResponseListener* listener) { response_listener_.reset(listener); } @@ -246,7 +250,7 @@ bool fin); // Address of the server. - const IPEndPoint server_address_; + IPEndPoint server_address_; // If initialized, the address to bind to. IPAddress bind_to_address_;
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc index 26820af6..1d6d6ec 100644 --- a/net/tools/quic/quic_client_bin.cc +++ b/net/tools/quic/quic_client_bin.cc
@@ -324,9 +324,8 @@ cout << "headers:" << header_block.DebugString(); if (!FLAGS_body_hex.empty()) { // Print the user provided hex, rather than binary body. - cout << "body hex: " << FLAGS_body_hex << endl; - cout << "body ascii: " << net::QuicUtils::BinaryToAscii( - net::QuicUtils::HexDecode(FLAGS_body_hex)) + cout << "body:\n" + << net::QuicUtils::HexDump(net::QuicUtils::HexDecode(FLAGS_body_hex)) << endl; } else { cout << "body: " << body << endl; @@ -337,10 +336,7 @@ string response_body = client.latest_response_body(); if (!FLAGS_body_hex.empty()) { // Assume response is binary data. - cout << "body hex: " << net::QuicUtils::HexEncode(response_body) - << endl; - cout << "body ascii: " << net::QuicUtils::BinaryToAscii(response_body) - << endl; + cout << "body:\n" << net::QuicUtils::HexDump(response_body) << endl; } else { cout << "body: " << response_body << endl; }
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index 70f2af1..b4826907 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc
@@ -200,6 +200,7 @@ alarm_factory_(std::move(alarm_factory)), delete_sessions_alarm_( alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))), + buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()), supported_versions_(supported_versions), disable_quic_pre_30_(FLAGS_quic_disable_pre_30), allowed_supported_versions_(supported_versions), @@ -260,6 +261,7 @@ QuicConnectionId connection_id = header.connection_id; SessionMap::iterator it = session_map_.find(connection_id); if (it != session_map_.end()) { + DCHECK(!buffered_packets_.HasBufferedPackets(connection_id)); it->second->ProcessUdpPacket(current_server_address_, current_client_address_, *current_packet_); return false; @@ -334,6 +336,16 @@ session_map_.insert(std::make_pair(connection_id, session)); session->ProcessUdpPacket(current_server_address_, current_client_address_, *current_packet_); + std::list<QuicBufferedPacketStore::BufferedPacket> packets = + buffered_packets_.DeliverPackets(connection_id); + for (const auto& packet : packets) { + SessionMap::iterator it = session_map_.find(connection_id); + if (it == session_map_.end()) { + break; + } + it->second->ProcessUdpPacket(packet.server_address, + packet.client_address, *packet.packet); + } break; } case kFateTimeWait: @@ -594,6 +606,10 @@ DCHECK(false); } +void QuicDispatcher::OnExpiredPackets( + QuicConnectionId connection_id, + QuicBufferedPacketStore::BufferedPacketList early_arrived_packets) {} + QuicServerSessionBase* QuicDispatcher::CreateQuicSession( QuicConnectionId connection_id, const IPEndPoint& client_address) { @@ -673,9 +689,10 @@ &rejector); if (!ChloExtractor::Extract(*current_packet_, supported_versions_, &validator)) { - // TODO(rch): Since there was no CHLO in this packet, buffer it until one - // arrives. - DLOG(ERROR) << "Dropping undecryptable packet."; + DVLOG(1) << "Buffering undecryptable packet."; + buffered_packets_.EnqueuePacket(connection_id, *current_packet_, + current_server_address_, + current_client_address_); return kFateDrop; }
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h index db97253..3d4093d 100644 --- a/net/tools/quic/quic_dispatcher.h +++ b/net/tools/quic/quic_dispatcher.h
@@ -18,6 +18,7 @@ #include "net/quic/crypto/quic_compressed_certs_cache.h" #include "net/quic/crypto/quic_random.h" #include "net/quic/quic_blocked_writer_interface.h" +#include "net/quic/quic_buffered_packet_store.h" #include "net/quic/quic_connection.h" #include "net/quic/quic_protocol.h" #include "net/quic/quic_server_session_base.h" @@ -37,7 +38,8 @@ class QuicDispatcher : public QuicServerSessionBase::Visitor, public ProcessPacketInterface, public QuicBlockedWriterInterface, - public QuicFramerVisitorInterface { + public QuicFramerVisitorInterface, + public QuicBufferedPacketStore::VisitorInterface { public: // Ideally we'd have a linked_hash_set: the boolean is unused. typedef linked_hash_map<QuicBlockedWriterInterface*, @@ -139,6 +141,11 @@ bool OnPathCloseFrame(const QuicPathCloseFrame& frame) override; void OnPacketComplete() override; + // QuicBufferedPacketStore::VisitorInterface + void OnExpiredPackets(QuicConnectionId connection_id, + QuicBufferedPacketStore::BufferedPacketList + early_arrived_packets) override; + protected: virtual QuicServerSessionBase* CreateQuicSession( QuicConnectionId connection_id, @@ -275,6 +282,10 @@ // The writer to write to the socket with. std::unique_ptr<QuicPacketWriter> writer_; + // Undecryptable packets which are buffered until a connection can be + // created to handle them. + QuicBufferedPacketStore buffered_packets_; + // This vector contains QUIC versions which we currently support. // This should be ordered such that the highest supported version is the first // element, with subsequent elements in descending order (versions can be
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc index a063a2d..2b88e05 100644 --- a/net/tools/quic/quic_dispatcher_test.cc +++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -176,11 +176,11 @@ crypto_config_(QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(), CryptoTestUtils::ProofSourceForTesting()), - dispatcher_(config_, &crypto_config_, &eps_), + dispatcher_(new TestDispatcher(config_, &crypto_config_, &eps_)), time_wait_list_manager_(nullptr), session1_(nullptr), session2_(nullptr) { - dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1)); + dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1)); } ~QuicDispatcherTest() override {} @@ -252,8 +252,8 @@ ConstructReceivedPacket(*packet, helper_.GetClock()->Now())); data_ = string(packet->data(), packet->length()); - dispatcher_.ProcessPacket(server_address_, client_address, - *received_packet); + dispatcher_->ProcessPacket(server_address_, client_address, + *received_packet); } void ValidatePacket(const QuicEncryptedPacket& packet) { @@ -262,11 +262,11 @@ } void CreateTimeWaitListManager() { - time_wait_list_manager_ = - new MockTimeWaitListManager(QuicDispatcherPeer::GetWriter(&dispatcher_), - &dispatcher_, &helper_, &alarm_factory_); + time_wait_list_manager_ = new MockTimeWaitListManager( + QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(), + &helper_, &alarm_factory_); // dispatcher_ takes the ownership of time_wait_list_manager_. - QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_, + QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(), time_wait_list_manager_); } @@ -284,7 +284,7 @@ QuicConfig config_; QuicCryptoServerConfig crypto_config_; IPEndPoint server_address_; - TestDispatcher dispatcher_; + std::unique_ptr<TestDispatcher> dispatcher_; MockTimeWaitListManager* time_wait_list_manager_; TestQuicSpdyServerSession* session1_; TestQuicSpdyServerSession* session2_; @@ -295,20 +295,20 @@ IPEndPoint client_address(net::test::Loopback4(), 1); server_address_ = IPEndPoint(net::test::Any4(), 5); - EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, 1, client_address, &mock_helper_, + dispatcher_.get(), config_, 1, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(&dispatcher_), &session1_))); + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); ProcessPacket(client_address, 1, true, false, SerializeCHLO()); - EXPECT_EQ(client_address, dispatcher_.current_client_address()); - EXPECT_EQ(server_address_, dispatcher_.current_server_address()); + EXPECT_EQ(client_address, dispatcher_->current_client_address()); + EXPECT_EQ(server_address_, dispatcher_->current_server_address()); - EXPECT_CALL(dispatcher_, CreateQuicSession(2, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(2, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, 2, client_address, &mock_helper_, + dispatcher_.get(), config_, 2, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(&dispatcher_), &session2_))); + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); ProcessPacket(client_address, 2, true, false, SerializeCHLO()); EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), @@ -323,7 +323,7 @@ IPEndPoint client_address(net::test::Loopback4(), 1); server_address_ = IPEndPoint(net::test::Any4(), 5); - EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)).Times(0); + EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)).Times(0); QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1); ProcessPacket(client_address, 1, true, version, SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1); @@ -332,18 +332,18 @@ TEST_F(QuicDispatcherTest, Shutdown) { IPEndPoint client_address(net::test::Loopback4(), 1); - EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, 1, client_address, &mock_helper_, + dispatcher_.get(), config_, 1, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(&dispatcher_), &session1_))); + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); ProcessPacket(client_address, 1, true, false, SerializeCHLO()); EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); - dispatcher_.Shutdown(); + dispatcher_->Shutdown(); } TEST_F(QuicDispatcherTest, TimeWaitListManager) { @@ -352,11 +352,11 @@ // Create a new session. IPEndPoint client_address(net::test::Loopback4(), 1); QuicConnectionId connection_id = 1; - EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, connection_id, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(&dispatcher_), &session1_))); + dispatcher_.get(), config_, connection_id, client_address, + &mock_helper_, &mock_alarm_factory_, &crypto_config_, + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); ProcessPacket(client_address, connection_id, true, false, SerializeCHLO()); // Close the connection by sending public reset packet. @@ -381,7 +381,7 @@ .WillOnce( Invoke(reinterpret_cast<MockQuicConnection*>(session1_->connection()), &MockQuicConnection::ReallyProcessUdpPacket)); - dispatcher_.ProcessPacket(IPEndPoint(), client_address, *received); + dispatcher_->ProcessPacket(IPEndPoint(), client_address, *received); EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); // Dispatcher forwards subsequent packets for this connection_id to the time @@ -401,7 +401,7 @@ QuicConnectionId connection_id = 1; // Dispatcher forwards all packets for this connection_id to the time wait // list manager. - EXPECT_CALL(dispatcher_, CreateQuicSession(_, _)).Times(0); + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id, _, _)) .Times(1); @@ -417,7 +417,7 @@ server_address_ = IPEndPoint(net::test::Any4(), 5); // dispatcher_ should drop this packet. - EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)).Times(0); + EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)).Times(0); EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _)) .Times(0); @@ -429,19 +429,19 @@ QuicConnectionId connection_id = 1; server_address_ = IPEndPoint(net::test::Any4(), 5); - EXPECT_CALL(dispatcher_, CreateQuicSession(1, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, 1, client_address, &mock_helper_, + dispatcher_.get(), config_, 1, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(&dispatcher_), &session1_))); + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); // A packet whose packet number is the largest that is allowed to start a // connection. ProcessPacket(client_address, connection_id, true, false, SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId, QuicDispatcher::kMaxReasonableInitialPacketNumber); - EXPECT_EQ(client_address, dispatcher_.current_client_address()); - EXPECT_EQ(server_address_, dispatcher_.current_server_address()); + EXPECT_EQ(client_address, dispatcher_->current_client_address()); + EXPECT_EQ(server_address_, dispatcher_->current_server_address()); } TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) { @@ -451,7 +451,7 @@ QuicConnectionId connection_id = 1; // Dispatcher forwards this packet for this connection_id to the time wait // list manager. - EXPECT_CALL(dispatcher_, CreateQuicSession(_, _)).Times(0); + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id, _, _)) .Times(1); @@ -558,12 +558,13 @@ QuicServerSessionBase* CreateSessionBasedOnTestParams( QuicConnectionId connection_id, const IPEndPoint& client_address) { - CreateSession(&dispatcher_, config_, connection_id, client_address, + CreateSession(dispatcher_.get(), config_, connection_id, client_address, &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(&dispatcher_), &session1_); + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_); crypto_stream1_ = new MockQuicCryptoServerStream( - crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), session1_); + crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), + session1_); session1_->SetCryptoStream(crypto_stream1_); crypto_stream1_->set_handshake_confirmed_for_testing( GetParam().crypto_handshake_successful); @@ -587,7 +588,7 @@ IPEndPoint client_address(net::test::Loopback4(), 1); QuicConnectionId connection_id = 1; - EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) .WillOnce(testing::Return( CreateSessionBasedOnTestParams(connection_id, client_address))); @@ -628,10 +629,10 @@ IPEndPoint client_address(net::test::Loopback4(), 1); QuicConnectionId connection_id = 1; if (GetParam().enable_stateless_rejects_via_flag) { - EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) .Times(0); } else { - EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) .WillOnce(testing::Return( CreateSessionBasedOnTestParams(connection_id, client_address))); } @@ -660,6 +661,51 @@ } } +TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) { + FLAGS_quic_use_cheap_stateless_rejects = true; + CreateTimeWaitListManager(); + + const IPEndPoint client_address(net::test::Loopback4(), 1); + const QuicConnectionId connection_id = 1; + + if (!GetParam().enable_stateless_rejects_via_flag) { + // If stateless rejects are not being used, then a connection will be + // created immediately. + EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) + .WillOnce(testing::Return( + CreateSessionBasedOnTestParams(connection_id, client_address))); + } + ProcessPacket(client_address, connection_id, true, false, + "NOT DATA FOR A CHLO"); + + // Process the first packet for the connection. + // clang-format off + CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( + "CHLO", + "AEAD", "AESG", + "KEXS", "C255", + "NONC", "1234567890123456789012", + "VER\0", "Q025", + "$padding", static_cast<int>(kClientHelloMinimumSize), + nullptr); + // clang-format on + + if (GetParam().enable_stateless_rejects_via_flag) { + // If stateless rejects are enabled then a connection will be created now + // and the buffered packet will be processed + EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) + .WillOnce(testing::Return( + CreateSessionBasedOnTestParams(connection_id, client_address))); + } + EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), + ProcessUdpPacket(_, client_address, _)) + .RetiresOnSaturation(); + ProcessPacket(client_address, connection_id, true, false, + client_hello.GetSerialized().AsStringPiece().as_string()); + EXPECT_FALSE( + time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); +} + // Verify the stopgap test: Packets with truncated connection IDs should be // dropped. class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {}; @@ -672,7 +718,7 @@ IPEndPoint client_address(net::test::Loopback4(), 1); QuicConnectionId connection_id = 1; // Dispatcher drops this packet. - EXPECT_CALL(dispatcher_, CreateQuicSession(_, _)).Times(0); + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id, _, _)) .Times(0); @@ -708,38 +754,38 @@ public: void SetUp() override { writer_ = new BlockingWriter; - QuicDispatcherPeer::UseWriter(&dispatcher_, writer_); + QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_); IPEndPoint client_address(net::test::Loopback4(), 1); - EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, 1, client_address, &helper_, &alarm_factory_, - &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), - &session1_))); + dispatcher_.get(), config_, 1, client_address, &helper_, + &alarm_factory_, &crypto_config_, + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); ProcessPacket(client_address, 1, true, false, SerializeCHLO()); - EXPECT_CALL(dispatcher_, CreateQuicSession(_, client_address)) + EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) .WillOnce(testing::Return(CreateSession( - &dispatcher_, config_, 2, client_address, &helper_, &alarm_factory_, - &crypto_config_, QuicDispatcherPeer::GetCache(&dispatcher_), - &session2_))); + dispatcher_.get(), config_, 2, client_address, &helper_, + &alarm_factory_, &crypto_config_, + QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); ProcessPacket(client_address, 2, true, false, SerializeCHLO()); - blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_); + blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get()); } void TearDown() override { EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); - dispatcher_.Shutdown(); + dispatcher_->Shutdown(); } void SetBlocked() { writer_->write_blocked_ = true; } void BlockConnection2() { writer_->write_blocked_ = true; - dispatcher_.OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection2()); } protected: @@ -751,95 +797,95 @@ TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) { // No OnCanWrite calls because no connections are blocked. - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // Register connection 1 for events, and make sure it's notified. SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); EXPECT_CALL(*connection1(), OnCanWrite()); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // It should get only one notification. EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); - dispatcher_.OnCanWrite(); - EXPECT_FALSE(dispatcher_.HasPendingWrites()); + dispatcher_->OnCanWrite(); + EXPECT_FALSE(dispatcher_->HasPendingWrites()); } TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) { // Make sure we handle events in order. InSequence s; SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection2()); EXPECT_CALL(*connection1(), OnCanWrite()); EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // Check the other ordering. SetBlocked(); - dispatcher_.OnWriteBlocked(connection2()); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection1()); EXPECT_CALL(*connection2(), OnCanWrite()); EXPECT_CALL(*connection1(), OnCanWrite()); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); } TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) { // Add and remove one connction. SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); blocked_list_->erase(connection1()); EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // Add and remove one connction and make sure it doesn't affect others. SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection2()); blocked_list_->erase(connection1()); EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // Add it, remove it, and add it back and make sure things are OK. SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); blocked_list_->erase(connection1()); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); EXPECT_CALL(*connection1(), OnCanWrite()).Times(1); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); } TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) { // Make sure a double add does not necessitate a double remove. SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); blocked_list_->erase(connection1()); EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // Make sure a double add does not result in two OnCanWrite calls. SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection1()); EXPECT_CALL(*connection1(), OnCanWrite()).Times(1); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); } TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) { // Finally make sure if we write block on a write call, we stop calling. InSequence s; SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection2()); EXPECT_CALL(*connection1(), OnCanWrite()) .WillOnce(Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked)); EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); // And we'll resume where we left off when we get another call. EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_.OnCanWrite(); + dispatcher_->OnCanWrite(); } TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) { @@ -847,37 +893,37 @@ // but should not be immediately called due to limits. InSequence s; SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection2()); EXPECT_CALL(*connection1(), OnCanWrite()); EXPECT_CALL(*connection2(), OnCanWrite()) .WillOnce( Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2)); - dispatcher_.OnCanWrite(); - EXPECT_TRUE(dispatcher_.HasPendingWrites()); + dispatcher_->OnCanWrite(); + EXPECT_TRUE(dispatcher_->HasPendingWrites()); // Now call OnCanWrite again, and connection1 should get its second chance EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_.OnCanWrite(); - EXPECT_FALSE(dispatcher_.HasPendingWrites()); + dispatcher_->OnCanWrite(); + EXPECT_FALSE(dispatcher_->HasPendingWrites()); } TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) { // Finally make sure if we write block on a write call, we stop calling. InSequence s; SetBlocked(); - dispatcher_.OnWriteBlocked(connection1()); - dispatcher_.OnWriteBlocked(connection2()); + dispatcher_->OnWriteBlocked(connection1()); + dispatcher_->OnWriteBlocked(connection2()); EXPECT_CALL(*connection1(), OnCanWrite()) .WillOnce(Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked)); EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); - dispatcher_.OnCanWrite(); - EXPECT_TRUE(dispatcher_.HasPendingWrites()); + dispatcher_->OnCanWrite(); + EXPECT_TRUE(dispatcher_->HasPendingWrites()); // And we'll resume where we left off when we get another call. EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_.OnCanWrite(); - EXPECT_FALSE(dispatcher_.HasPendingWrites()); + dispatcher_->OnCanWrite(); + EXPECT_FALSE(dispatcher_->HasPendingWrites()); } } // namespace
diff --git a/net/tools/quic/quic_epoll_alarm_factory.cc b/net/tools/quic/quic_epoll_alarm_factory.cc index 21a166a7..56377b2 100644 --- a/net/tools/quic/quic_epoll_alarm_factory.cc +++ b/net/tools/quic/quic_epoll_alarm_factory.cc
@@ -23,8 +23,7 @@ void SetImpl() override { DCHECK(deadline().IsInitialized()); epoll_server_->RegisterAlarm( - deadline().Subtract(QuicTime::Zero()).ToMicroseconds(), - &epoll_alarm_impl_); + (deadline() - QuicTime::Zero()).ToMicroseconds(), &epoll_alarm_impl_); } void CancelImpl() override {
diff --git a/net/tools/quic/quic_epoll_alarm_factory_test.cc b/net/tools/quic/quic_epoll_alarm_factory_test.cc index 5dfe701..3118be8 100644 --- a/net/tools/quic/quic_epoll_alarm_factory_test.cc +++ b/net/tools/quic/quic_epoll_alarm_factory_test.cc
@@ -48,11 +48,11 @@ QuicTime start = clock_.Now(); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(start.Add(delta)); + alarm->Set(start + delta); epoll_server_.AdvanceByAndWaitForEventsAndExecuteCallbacks( delta.ToMicroseconds()); - EXPECT_EQ(start.Add(delta), clock_.Now()); + EXPECT_EQ(start + delta, clock_.Now()); } TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndCancel) { @@ -64,11 +64,11 @@ QuicTime start = clock_.Now(); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(start.Add(delta)); + alarm->Set(start + delta); alarm->Cancel(); epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds()); - EXPECT_EQ(start.Add(delta), clock_.Now()); + EXPECT_EQ(start + delta, clock_.Now()); EXPECT_FALSE(unowned_delegate->fired()); } @@ -81,18 +81,18 @@ QuicTime start = clock_.Now(); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); alarm->Cancel(); QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Set(clock_.Now().Add(new_delta)); + alarm->Set(clock_.Now() + new_delta); epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds()); - EXPECT_EQ(start.Add(delta), clock_.Now()); + EXPECT_EQ(start + delta, clock_.Now()); EXPECT_FALSE(unowned_delegate->fired()); epoll_server_.AdvanceByExactlyAndCallCallbacks( - new_delta.Subtract(delta).ToMicroseconds()); - EXPECT_EQ(start.Add(new_delta), clock_.Now()); + (new_delta - delta).ToMicroseconds()); + EXPECT_EQ(start + new_delta, clock_.Now()); EXPECT_TRUE(unowned_delegate->fired()); } @@ -105,28 +105,25 @@ QuicTime start = clock_.Now(); QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now().Add(delta)); + alarm->Set(clock_.Now() + delta); QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Update(clock_.Now().Add(new_delta), - QuicTime::Delta::FromMicroseconds(1)); + alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1)); epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds()); - EXPECT_EQ(start.Add(delta), clock_.Now()); + EXPECT_EQ(start + delta, clock_.Now()); EXPECT_FALSE(unowned_delegate->fired()); // Move the alarm forward 1us and ensure it doesn't move forward. - alarm->Update(clock_.Now().Add(new_delta), - QuicTime::Delta::FromMicroseconds(2)); + alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(2)); epoll_server_.AdvanceByExactlyAndCallCallbacks( - new_delta.Subtract(delta).ToMicroseconds()); - EXPECT_EQ(start.Add(new_delta), clock_.Now()); + (new_delta - delta).ToMicroseconds()); + EXPECT_EQ(start + new_delta, clock_.Now()); EXPECT_TRUE(unowned_delegate->fired()); // Set the alarm via an update call. new_delta = QuicTime::Delta::FromMicroseconds(5); - alarm->Update(clock_.Now().Add(new_delta), - QuicTime::Delta::FromMicroseconds(1)); + alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1)); EXPECT_TRUE(alarm->IsSet()); // Update it with an uninitialized time and ensure it's cancelled.
diff --git a/net/tools/quic/quic_epoll_clock.cc b/net/tools/quic/quic_epoll_clock.cc index cb77176..357bc50 100644 --- a/net/tools/quic/quic_epoll_clock.cc +++ b/net/tools/quic/quic_epoll_clock.cc
@@ -14,13 +14,13 @@ QuicEpollClock::~QuicEpollClock() {} QuicTime QuicEpollClock::ApproximateNow() const { - return QuicTime::Zero().Add( - QuicTime::Delta::FromMicroseconds(epoll_server_->ApproximateNowInUsec())); + return QuicTime::Zero() + QuicTime::Delta::FromMicroseconds( + epoll_server_->ApproximateNowInUsec()); } QuicTime QuicEpollClock::Now() const { - return QuicTime::Zero().Add( - QuicTime::Delta::FromMicroseconds(epoll_server_->NowInUsec())); + return QuicTime::Zero() + + QuicTime::Delta::FromMicroseconds(epoll_server_->NowInUsec()); } QuicWallTime QuicEpollClock::WallNow() const { @@ -30,8 +30,8 @@ QuicTime QuicEpollClock::ConvertWallTimeToQuicTime( const QuicWallTime& walltime) const { - return QuicTime::Zero().Add( - QuicTime::Delta::FromMicroseconds(walltime.ToUNIXMicroseconds())); -}; + return QuicTime::Zero() + + QuicTime::Delta::FromMicroseconds(walltime.ToUNIXMicroseconds()); +} } // namespace net
diff --git a/net/tools/quic/quic_epoll_clock_test.cc b/net/tools/quic/quic_epoll_clock_test.cc index 039e8bf..03d26b821 100644 --- a/net/tools/quic/quic_epoll_clock_test.cc +++ b/net/tools/quic/quic_epoll_clock_test.cc
@@ -16,13 +16,13 @@ epoll_server.set_now_in_usec(1000000); EXPECT_EQ(1000000, - clock.ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds()); + (clock.ApproximateNow() - QuicTime::Zero()).ToMicroseconds()); EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds()); EXPECT_EQ(1000000u, clock.WallNow().ToUNIXMicroseconds()); epoll_server.AdvanceBy(5); EXPECT_EQ(1000005, - clock.ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds()); + (clock.ApproximateNow() - QuicTime::Zero()).ToMicroseconds()); EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds()); EXPECT_EQ(1000005u, clock.WallNow().ToUNIXMicroseconds()); @@ -36,10 +36,10 @@ QuicEpollClock clock(&epoll_server); epoll_server.set_now_in_usec(1000000); - EXPECT_EQ(1000000, clock.Now().Subtract(QuicTime::Zero()).ToMicroseconds()); + EXPECT_EQ(1000000, (clock.Now() - QuicTime::Zero()).ToMicroseconds()); epoll_server.AdvanceBy(5); - EXPECT_EQ(1000005, clock.Now().Subtract(QuicTime::Zero()).ToMicroseconds()); + EXPECT_EQ(1000005, (clock.Now() - QuicTime::Zero()).ToMicroseconds()); } } // namespace test
diff --git a/net/tools/quic/quic_epoll_connection_helper_test.cc b/net/tools/quic/quic_epoll_connection_helper_test.cc index 078eef7..85b82aaa 100644 --- a/net/tools/quic/quic_epoll_connection_helper_test.cc +++ b/net/tools/quic/quic_epoll_connection_helper_test.cc
@@ -30,7 +30,7 @@ QuicTime::Delta delta = QuicTime::Delta::FromMilliseconds(5); epoll_server_.AdvanceBy(delta.ToMicroseconds()); - EXPECT_EQ(start.Add(delta), clock->Now()); + EXPECT_EQ(start + delta, clock->Now()); } TEST_F(QuicEpollConnectionHelperTest, GetRandomGenerator) {
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc index 7cbb6dbd..75dca39 100644 --- a/net/tools/quic/quic_simple_client_bin.cc +++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -326,9 +326,8 @@ cout << "headers:" << header_block.DebugString(); if (!FLAGS_body_hex.empty()) { // Print the user provided hex, rather than binary body. - cout << "body hex: " << FLAGS_body_hex << endl; - cout << "body ascii: " << net::QuicUtils::BinaryToAscii( - net::QuicUtils::HexDecode(FLAGS_body_hex)) + cout << "body:\n" + << net::QuicUtils::HexDump(net::QuicUtils::HexDecode(FLAGS_body_hex)) << endl; } else { cout << "body: " << body << endl; @@ -339,10 +338,7 @@ string response_body = client.latest_response_body(); if (!FLAGS_body_hex.empty()) { // Assume response is binary data. - cout << "body hex: " << net::QuicUtils::HexEncode(response_body) - << endl; - cout << "body ascii: " << net::QuicUtils::BinaryToAscii(response_body) - << endl; + cout << "body:\n" << net::QuicUtils::HexDump(response_body) << endl; } else { cout << "body: " << response_body << endl; }
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc index 8e93f9b..646783d6 100644 --- a/net/tools/quic/quic_simple_server_session_test.cc +++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -54,6 +54,7 @@ using testing::_; using testing::InSequence; using testing::Return; +using testing::AtLeast; namespace net { namespace test { @@ -205,8 +206,6 @@ visitor_ = QuicConnectionPeer::GetVisitor(connection_); headers_stream_ = new MockQuicHeadersStream(session_.get()); QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_); - // TODO(jri): Remove this line once tests pass. - FLAGS_quic_cede_correctly = false; session_->OnConfigNegotiated(); } @@ -493,11 +492,25 @@ WriteHeadersMock(stream_id, _, false, kDefaultPriority, nullptr)); // Since flow control window is smaller than response body, not the // whole body will be sent. - EXPECT_CALL(*connection_, - SendStreamData(stream_id, _, 0, false, nullptr)) - .WillOnce( - Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); - EXPECT_CALL(*connection_, SendBlocked(stream_id)); + if (!session_->force_hol_blocking()) { + EXPECT_CALL(*connection_, + SendStreamData(stream_id, _, 0, false, nullptr)) + .WillOnce(Return( + QuicConsumedData(kStreamFlowControlWindowSize, false))); + EXPECT_CALL(*connection_, SendBlocked(stream_id)); + } else { + // The forced HOL blocking encapsulates the stream data into + // HTTP/2 DATA frames within the headers stream. HTTP/2 + // DATA frames are limited to a max size of 16KB, so the + // 64KB body will be fragemented into four DATA frames. + EXPECT_CALL(*connection_, SendStreamData(_, _, _, false, nullptr)) + .Times(body_size / 16384) + .WillOnce(Return(QuicConsumedData(9 + 16394, false))) + .WillOnce(Return(QuicConsumedData(9 + 16394, false))) + .WillOnce(Return(QuicConsumedData(9 + 16394, false))) + .WillOnce(Return(QuicConsumedData(9 + 16394, false))); + EXPECT_CALL(*connection_, SendBlocked(_)); + } } } session_->PromisePushResources(request_url, push_resources, @@ -513,6 +526,10 @@ // Tests that given more than kMaxOpenStreamForTest resources, all their // PUSH_PROMISE's will be sent out and only |kMaxOpenStreamForTest| streams // will be opened and send push response. + + if (session_->force_hol_blocking()) { + return; + } size_t num_resources = kMaxStreamsForTest + 5; PromisePushResources(num_resources); EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); @@ -520,6 +537,10 @@ TEST_P(QuicSimpleServerSessionServerPushTest, HandlePromisedPushRequestsAfterStreamDraining) { + if (session_->force_hol_blocking()) { + return; + } + // Tests that after promised stream queued up, when an opened stream is marked // draining, a queued promised stream will become open and send push response. size_t num_resources = kMaxStreamsForTest + 1; @@ -543,6 +564,9 @@ TEST_P(QuicSimpleServerSessionServerPushTest, ResetPromisedStreamToCancelServerPush) { + if (session_->force_hol_blocking()) { + return; + } // Tests that after all resources are promised, a RST frame from client can // prevent a promised resource to be send out. @@ -579,6 +603,9 @@ TEST_P(QuicSimpleServerSessionServerPushTest, CloseStreamToHandleMorePromisedStream) { + if (session_->force_hol_blocking()) { + return; + } // Tests that closing a open outgoing stream can trigger a promised resource // in the queue to be send out. size_t num_resources = kMaxStreamsForTest + 1;
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc index 61ec378..7fcc964 100644 --- a/net/tools/quic/quic_socket_utils.cc +++ b/net/tools/quic/quic_socket_utils.cc
@@ -56,7 +56,7 @@ *walltimestamp = QuicWallTime::FromUNIXMicroseconds(usec); } else { *timestamp = - QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(usec)); + QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(usec); } } }
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc index 6686238..ffe3dd4d 100644 --- a/net/tools/quic/quic_time_wait_list_manager.cc +++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -267,9 +267,8 @@ QuicTime oldest_connection_id = connection_id_map_.begin()->second.time_added; QuicTime now = clock_->ApproximateNow(); - if (now.Subtract(oldest_connection_id) < time_wait_period_) { - next_alarm_interval = - oldest_connection_id.Add(time_wait_period_).Subtract(now); + if (now - oldest_connection_id < time_wait_period_) { + next_alarm_interval = oldest_connection_id + time_wait_period_ - now; } else { LOG(ERROR) << "ConnectionId lingered for longer than time_wait_period_"; } @@ -278,8 +277,8 @@ next_alarm_interval = time_wait_period_; } - connection_id_clean_up_alarm_->Set( - clock_->ApproximateNow().Add(next_alarm_interval)); + connection_id_clean_up_alarm_->Set(clock_->ApproximateNow() + + next_alarm_interval); } bool QuicTimeWaitListManager::MaybeExpireOldestConnection( @@ -300,7 +299,7 @@ void QuicTimeWaitListManager::CleanUpOldConnectionIds() { QuicTime now = clock_->ApproximateNow(); - QuicTime expiration = now.Subtract(time_wait_period_); + QuicTime expiration = now - time_wait_period_; while (MaybeExpireOldestConnection(expiration)) { }
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc index a1d06b4..70a7576 100644 --- a/net/tools/quic/quic_time_wait_list_manager_test.cc +++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -353,11 +353,11 @@ QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); // Now set the current time as time_wait_period + offset usecs. - epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); + epoll_server_.set_now_in_usec((time_wait_period + offset).ToMicroseconds()); // After all the old connection_ids are cleaned up, check the next alarm // interval. int64_t next_alarm_time = epoll_server_.ApproximateNowInUsec() + - time_wait_period.Subtract(offset).ToMicroseconds(); + (time_wait_period - offset).ToMicroseconds(); EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); time_wait_list_manager_.CleanUpOldConnectionIds(); @@ -479,7 +479,7 @@ QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); // Now set the current time as time_wait_period + offset usecs. - epoll_server_.set_now_in_usec(time_wait_period.Add(offset).ToMicroseconds()); + epoll_server_.set_now_in_usec((time_wait_period + offset).ToMicroseconds()); // After the connection_ids are cleaned up, check the next alarm interval. int64_t next_alarm_time = epoll_server_.ApproximateNowInUsec() + time_wait_period.ToMicroseconds();
diff --git a/net/tools/quic/stateless_rejector_test.cc b/net/tools/quic/stateless_rejector_test.cc index 97f7839..bac095b 100644 --- a/net/tools/quic/stateless_rejector_test.cc +++ b/net/tools/quic/stateless_rejector_test.cc
@@ -135,6 +135,7 @@ // clang-format off const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "COPT", "SREJ", nullptr); // clang-format on @@ -154,6 +155,7 @@ // clang-format off const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "PUBS", pubs_hex_.c_str(), @@ -172,6 +174,7 @@ // clang-format off const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "COPT", "SREJ", @@ -210,6 +213,7 @@ // clang-format off const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( "CHLO", + "PDMD", "X509", "AEAD", "AESG", "KEXS", "C255", "COPT", "SREJ",
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/net/tools/quic/test_tools/packet_dropping_test_writer.cc index 4d85d5a..8b2141c 100644 --- a/net/tools/quic/test_tools/packet_dropping_test_writer.cc +++ b/net/tools/quic/test_tools/packet_dropping_test_writer.cc
@@ -118,14 +118,14 @@ } // Queue it to be sent. - QuicTime send_time = clock_->ApproximateNow().Add(fake_packet_delay_); + QuicTime send_time = clock_->ApproximateNow() + fake_packet_delay_; if (!fake_bandwidth_.IsZero()) { // Calculate a time the bandwidth limit would impose. QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds( (buf_len * kNumMicrosPerSecond) / fake_bandwidth_.ToBytesPerSecond()); send_time = delayed_packets_.empty() - ? send_time.Add(bandwidth_delay) - : delayed_packets_.back().send_time.Add(bandwidth_delay); + ? send_time + bandwidth_delay + : delayed_packets_.back().send_time + bandwidth_delay; } std::unique_ptr<PerPacketOptions> delayed_options; if (options != nullptr) {
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 914c4f8a..ad5748d 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -45,18 +45,19 @@ class RecordingProofVerifier : public ProofVerifier { public: // ProofVerifier interface. - QuicAsyncStatus VerifyProof(const string& hostname, - const uint16_t port, - const string& server_config, - QuicVersion quic_version, - StringPiece chlo_hash, - const vector<string>& certs, - const string& cert_sct, - const string& signature, - const ProofVerifyContext* context, - string* error_details, - std::unique_ptr<ProofVerifyDetails>* details, - ProofVerifierCallback* callback) override { + QuicAsyncStatus VerifyProof( + const string& hostname, + const uint16_t port, + const string& server_config, + QuicVersion quic_version, + StringPiece chlo_hash, + const vector<string>& certs, + const string& cert_sct, + const string& signature, + const ProofVerifyContext* context, + string* error_details, + std::unique_ptr<ProofVerifyDetails>* details, + std::unique_ptr<ProofVerifierCallback> callback) override { common_name_.clear(); if (certs.empty()) { return QUIC_FAILURE; @@ -495,7 +496,7 @@ QuicConnectionPeer::GetHelper(client()->session()->connection()) ->GetClock(); QuicTime end_waiting_time = - clock->Now().Add(QuicTime::Delta::FromMicroseconds(timeout_us)); + clock->Now() + QuicTime::Delta::FromMicroseconds(timeout_us); while (HaveActiveStream() && (timeout_us < 0 || clock->Now() < end_waiting_time)) { client_->WaitForEvents(); @@ -515,7 +516,7 @@ QuicConnectionPeer::GetHelper(client()->session()->connection()) ->GetClock(); QuicTime end_waiting_time = - clock->Now().Add(QuicTime::Delta::FromMicroseconds(timeout_us)); + clock->Now() + QuicTime::Delta::FromMicroseconds(timeout_us); while (stream_ != nullptr && !client_->session()->IsClosedStream(stream_->id()) && stream_->stream_bytes_read() == 0 &&
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h index b76d1cfc..47e20621 100644 --- a/net/tools/quic/test_tools/quic_test_client.h +++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -202,6 +202,10 @@ size_t num_responses() const { return num_responses_; } + void set_server_address(const IPEndPoint& server_address) { + client_->set_server_address(server_address); + } + // Explicitly set the SNI value for this client, overriding the default // behavior which extracts the SNI value from the request URL. void OverrideSni(const std::string& sni) {
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 0fdeac11..dd30591 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -722,8 +722,12 @@ // Advertise "br" encoding only if transferred data is opaque to proxy. bool advertise_brotli = false; - if (request()->context()->enable_brotli()) - advertise_brotli = request()->url().SchemeIsCryptographic(); + if (request()->context()->enable_brotli()) { + if (request()->url().SchemeIsCryptographic() || + IsLocalhost(request()->url().HostNoBrackets())) { + advertise_brotli = true; + } + } // Supply Accept-Encoding headers first so that it is more likely that they // will be in the first transmitted packet. This can sometimes make it
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index f2bbeb22..7b0afbb 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h
@@ -1086,9 +1086,11 @@ // after this message is sent. IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_TakeFrontBuffer, ppapi::HostResource /* graphics_3d */) -IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBGraphics3D_SwapBuffers, +IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBGraphics3D_SwapBuffers, ppapi::HostResource /* graphics_3d */, - gpu::SyncToken /* sync_token */) + gpu::SyncToken /* sync_token */, + int32_t /* width*/, + int32_t /* height*/) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_EnsureWorkVisible, ppapi::HostResource /* context */)
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc index 0c21e37..ca29adc 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.cc +++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -117,7 +117,9 @@ return command_buffer_.get(); } -int32_t Graphics3D::DoSwapBuffers(const gpu::SyncToken& sync_token) { +int32_t Graphics3D::DoSwapBuffers(const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) { // A valid sync token would indicate a swap buffer already happened somehow. DCHECK(!sync_token.HasData()); @@ -135,7 +137,8 @@ gl->GenSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData()); IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( - API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token); + API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token, width, + height); msg->set_unblock(true); PluginDispatcher::GetForResource(this)->Send(msg); @@ -347,13 +350,15 @@ } void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context, - const gpu::SyncToken& sync_token) { + const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) { EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter( context, callback_factory_, &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context); if (enter.succeeded()) - enter.SetResult( - enter.object()->SwapBuffersWithSyncToken(enter.callback(), sync_token)); + enter.SetResult(enter.object()->SwapBuffersWithSyncToken( + enter.callback(), sync_token, width, height)); } void PPB_Graphics3D_Proxy::OnMsgTakeFrontBuffer(const HostResource& context) {
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h index 2a28fce..9536ee20 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/ppapi/proxy/ppb_graphics_3d_proxy.h
@@ -61,7 +61,9 @@ // PPB_Graphics3D_Shared overrides. gpu::CommandBuffer* GetCommandBuffer() override; gpu::GpuControl* GetGpuControl() override; - int32_t DoSwapBuffers(const gpu::SyncToken& sync_token) override; + int32_t DoSwapBuffers(const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) override; std::unique_ptr<PpapiCommandBufferProxy> command_buffer_; @@ -110,7 +112,9 @@ ppapi::proxy::SerializedHandle* transfer_buffer); void OnMsgDestroyTransferBuffer(const HostResource& context, int32_t id); void OnMsgSwapBuffers(const HostResource& context, - const gpu::SyncToken& sync_token); + const gpu::SyncToken& sync_token, + int32_t width, + int32_t height); void OnMsgTakeFrontBuffer(const HostResource& context); void OnMsgEnsureWorkVisible(const HostResource& context); // Renderer->plugin message handlers.
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.cc b/ppapi/shared_impl/ppb_graphics_3d_shared.cc index af53bfb..0c40b4cb 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.cc +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.cc
@@ -51,18 +51,22 @@ return PP_ERROR_BADARGUMENT; gles2_impl()->ResizeCHROMIUM(width, height, 1.f, true); + width_ = width; + height_ = height; // TODO(alokp): Check if resize succeeded and return appropriate error code. return PP_OK; } int32_t PPB_Graphics3D_Shared::SwapBuffers( scoped_refptr<TrackedCallback> callback) { - return SwapBuffersWithSyncToken(callback, gpu::SyncToken()); + return SwapBuffersWithSyncToken(callback, gpu::SyncToken(), width_, height_); } int32_t PPB_Graphics3D_Shared::SwapBuffersWithSyncToken( scoped_refptr<TrackedCallback> callback, - const gpu::SyncToken& sync_token) { + const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) { if (HasPendingSwap()) { Log(PP_LOGLEVEL_ERROR, "PPB_Graphics3D.SwapBuffers: Plugin attempted swap " @@ -72,7 +76,7 @@ } swap_callback_ = callback; - return DoSwapBuffers(sync_token); + return DoSwapBuffers(sync_token, width, height); } int32_t PPB_Graphics3D_Shared::GetAttribMaxValue(int32_t attribute,
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.h b/ppapi/shared_impl/ppb_graphics_3d_shared.h index 7e11f6c..4c8a1ab6 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.h +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.h
@@ -43,7 +43,9 @@ int32_t ResizeBuffers(int32_t width, int32_t height) override; int32_t SwapBuffers(scoped_refptr<TrackedCallback> callback) override; int32_t SwapBuffersWithSyncToken(scoped_refptr<TrackedCallback> callback, - const gpu::SyncToken& sync_token) override; + const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) override; int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) override; void* MapTexSubImage2DCHROMIUM(GLenum target, @@ -70,7 +72,9 @@ virtual gpu::CommandBuffer* GetCommandBuffer() = 0; virtual gpu::GpuControl* GetGpuControl() = 0; - virtual int32_t DoSwapBuffers(const gpu::SyncToken& sync_token) = 0; + virtual int32_t DoSwapBuffers(const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) = 0; bool HasPendingSwap() const; bool CreateGLES2Impl(int32_t command_buffer_size, @@ -83,6 +87,10 @@ std::unique_ptr<gpu::TransferBuffer> transfer_buffer_; std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_; + // A local cache of the size of the viewport. + int32_t width_ = -1; + int32_t height_ = -1; + // Callback that needs to be executed when swap-buffers is completed. scoped_refptr<TrackedCallback> swap_callback_;
diff --git a/ppapi/shared_impl/test_utils.cc b/ppapi/shared_impl/test_utils.cc index 2ab8c5a..18bc9e3 100644 --- a/ppapi/shared_impl/test_utils.cc +++ b/ppapi/shared_impl/test_utils.cc
@@ -213,8 +213,11 @@ } std::string StripTestPrefixes(const std::string& test_name) { - if (test_name.find("DISABLED_") == 0) - return test_name.substr(strlen("DISABLED_")); + const char kDisabledPrefix[] = "DISABLED_"; + if (base::StartsWith(test_name, kDisabledPrefix, + base::CompareCase::SENSITIVE)) { + return test_name.substr(sizeof(kDisabledPrefix) - 1); + } return test_name; }
diff --git a/ppapi/shared_impl/time_conversion.cc b/ppapi/shared_impl/time_conversion.cc index 651274a..76946b2d 100644 --- a/ppapi/shared_impl/time_conversion.cc +++ b/ppapi/shared_impl/time_conversion.cc
@@ -32,9 +32,12 @@ time.LocalExplode(&exploded); time.UTCExplode(&utc_exploded); if (exploded.HasValidValues() && utc_exploded.HasValidValues()) { - base::Time adj_time = base::Time::FromUTCExploded(exploded); - base::Time cur = base::Time::FromUTCExploded(utc_exploded); - return (adj_time - cur).InSecondsF(); + base::Time adj_time; + if (base::Time::FromUTCExploded(exploded, &adj_time)) { + base::Time cur; + if (base::Time::FromUTCExploded(utc_exploded, &cur)) + return (adj_time - cur).InSecondsF(); + } } return 0.0; }
diff --git a/ppapi/thunk/ppb_graphics_3d_api.h b/ppapi/thunk/ppb_graphics_3d_api.h index 845b35f5f..9c2e312 100644 --- a/ppapi/thunk/ppb_graphics_3d_api.h +++ b/ppapi/thunk/ppb_graphics_3d_api.h
@@ -35,7 +35,9 @@ virtual int32_t SwapBuffers(scoped_refptr<TrackedCallback> callback) = 0; virtual int32_t SwapBuffersWithSyncToken( scoped_refptr<TrackedCallback> callback, - const gpu::SyncToken& sync_token) = 0; + const gpu::SyncToken& sync_token, + int32_t width, + int32_t height) = 0; virtual int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) = 0; // Graphics3DTrusted API.
diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc index c31c25e..8e4da5f 100644 --- a/sandbox/win/src/win_utils.cc +++ b/sandbox/win/src/win_utils.cc
@@ -132,7 +132,8 @@ bool ResolveRegistryName(base::string16 name, base::string16* resolved_name) { for (size_t i = 0; i < arraysize(kKnownKey); ++i) { - if (name.find(kKnownKey[i].name) == 0) { + if (base::StartsWith(name, kKnownKey[i].name, + base::CompareCase::SENSITIVE)) { HKEY key; DWORD disposition; if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, NULL, 0,
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc index 79acc07..501db2d 100644 --- a/services/catalog/catalog.cc +++ b/services/catalog/catalog.cc
@@ -18,7 +18,7 @@ #include "services/catalog/instance.h" #include "services/catalog/reader.h" #include "services/shell/public/cpp/connection.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" namespace catalog { namespace { @@ -92,7 +92,7 @@ Catalog::Catalog(std::unique_ptr<Store> store) : store_(std::move(store)), weak_factory_(this) { shell::mojom::ServiceRequest request = GetProxy(&service_); - shell_connection_.reset(new shell::ShellConnection(this, std::move(request))); + shell_connection_.reset(new shell::ServiceContext(this, std::move(request))); } void Catalog::ScanSystemPackageDir() {
diff --git a/services/catalog/catalog.h b/services/catalog/catalog.h index 417ac8e9..3dd946e 100644 --- a/services/catalog/catalog.h +++ b/services/catalog/catalog.h
@@ -29,7 +29,7 @@ } namespace shell { -class ShellConnection; +class ServiceContext; } namespace catalog { @@ -85,7 +85,7 @@ std::unique_ptr<Store> store_; shell::mojom::ServicePtr service_; - std::unique_ptr<shell::ShellConnection> shell_connection_; + std::unique_ptr<shell::ServiceContext> shell_connection_; std::map<std::string, std::unique_ptr<Instance>> instances_;
diff --git a/services/navigation/BUILD.gn b/services/navigation/BUILD.gn index 7031c41..4d84fa5 100644 --- a/services/navigation/BUILD.gn +++ b/services/navigation/BUILD.gn
@@ -82,7 +82,7 @@ "//base/test:test_support", "//services/navigation/public/interfaces", "//services/shell/public/cpp", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp/test:run_all_shelltests", "//testing/gtest", ]
diff --git a/services/navigation/navigation.h b/services/navigation/navigation.h index 60efa73..3a731dd6 100644 --- a/services/navigation/navigation.h +++ b/services/navigation/navigation.h
@@ -9,7 +9,7 @@ #include "services/navigation/public/interfaces/view.mojom.h" #include "services/shell/public/cpp/interface_factory.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection_ref.h" +#include "services/shell/public/cpp/service_context_ref.h" namespace content { class BrowserContext; @@ -44,8 +44,8 @@ shell::Connector* connector_ = nullptr; std::string client_user_id_; - shell::ShellConnectionRefFactory ref_factory_; - std::set<std::unique_ptr<shell::ShellConnectionRef>> refs_; + shell::ServiceContextRefFactory ref_factory_; + std::set<std::unique_ptr<shell::ServiceContextRef>> refs_; mojo::BindingSet<mojom::ViewFactory> bindings_;
diff --git a/services/navigation/navigation_unittest.cc b/services/navigation/navigation_unittest.cc index 11e5dee..a15faa3 100644 --- a/services/navigation/navigation_unittest.cc +++ b/services/navigation/navigation_unittest.cc
@@ -8,21 +8,21 @@ #include "base/run_loop.h" #include "services/navigation/public/interfaces/view.mojom.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" namespace navigation { -class NavigationTest : public shell::test::ShellTest, +class NavigationTest : public shell::test::ServiceTest, public mojom::ViewClient { public: NavigationTest() - : shell::test::ShellTest("exe:navigation_unittests"), + : shell::test::ServiceTest("exe:navigation_unittests"), binding_(this) {} ~NavigationTest() override {} protected: void SetUp() override { - shell::test::ShellTest::SetUp(); + shell::test::ServiceTest::SetUp(); window_manager_connection_ = connector()->Connect("mojo:test_wm"); }
diff --git a/services/navigation/view_impl.cc b/services/navigation/view_impl.cc index 8d8af6a..6bb54cf85 100644 --- a/services/navigation/view_impl.cc +++ b/services/navigation/view_impl.cc
@@ -60,7 +60,7 @@ const std::string& client_user_id, mojom::ViewClientPtr client, mojom::ViewRequest request, - std::unique_ptr<shell::ShellConnectionRef> ref) + std::unique_ptr<shell::ServiceContextRef> ref) : connector_(connector), binding_(this, std::move(request)), client_(std::move(client)),
diff --git a/services/navigation/view_impl.h b/services/navigation/view_impl.h index 2a3fc31..427afa1 100644 --- a/services/navigation/view_impl.h +++ b/services/navigation/view_impl.h
@@ -14,7 +14,7 @@ #include "services/navigation/public/interfaces/view.mojom.h" #include "services/shell/public/cpp/interface_factory.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection_ref.h" +#include "services/shell/public/cpp/service_context_ref.h" #include "services/ui/public/cpp/window_tree_client_delegate.h" #include "ui/gfx/geometry/size.h" #include "ui/views/widget/widget_delegate.h" @@ -36,7 +36,7 @@ const std::string& client_user_id, mojom::ViewClientPtr client, mojom::ViewRequest request, - std::unique_ptr<shell::ShellConnectionRef> ref); + std::unique_ptr<shell::ServiceContextRef> ref); ~ViewImpl() override; private: @@ -90,7 +90,7 @@ shell::Connector* connector_; mojo::StrongBinding<mojom::View> binding_; mojom::ViewClientPtr client_; - std::unique_ptr<shell::ShellConnectionRef> ref_; + std::unique_ptr<shell::ServiceContextRef> ref_; views::WebView* web_view_;
diff --git a/services/shell/background/background_shell.cc b/services/shell/background/background_shell.cc index 1cac7371f..6f743c08 100644 --- a/services/shell/background/background_shell.cc +++ b/services/shell/background/background_shell.cc
@@ -17,7 +17,7 @@ #include "services/catalog/store.h" #include "services/shell/connect_params.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/service_manager.h" #include "services/shell/standalone/context.h"
diff --git a/services/shell/background/tests/background_shell_unittest.cc b/services/shell/background/tests/background_shell_unittest.cc index 9d9c401..b73c41b 100644 --- a/services/shell/background/tests/background_shell_unittest.cc +++ b/services/shell/background/tests/background_shell_unittest.cc
@@ -12,7 +12,7 @@ #include "services/shell/background/tests/test_catalog_store.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "testing/gtest/include/gtest/gtest.h" namespace shell { @@ -62,10 +62,10 @@ init_params->catalog_store = std::move(store_ptr); background_shell.Init(std::move(init_params)); ServiceImpl service; - ShellConnection shell_connection( + ServiceContext service_context( &service, background_shell.CreateServiceRequest(kTestName)); mojom::TestServicePtr test_service; - shell_connection.connector()->ConnectToInterface( + service_context.connector()->ConnectToInterface( "mojo:background_shell_test_app", &test_service); base::RunLoop run_loop; bool got_result = false;
diff --git a/services/shell/public/cpp/BUILD.gn b/services/shell/public/cpp/BUILD.gn index b116e16..0d8a088 100644 --- a/services/shell/public/cpp/BUILD.gn +++ b/services/shell/public/cpp/BUILD.gn
@@ -37,12 +37,12 @@ "lib/interface_registry.cc", "lib/names.cc", "lib/service.cc", - "lib/shell_connection.cc", - "lib/shell_connection_ref.cc", + "lib/service_context.cc", + "lib/service_context_ref.cc", "names.h", "service.h", - "shell_connection.h", - "shell_connection_ref.h", + "service_context.h", + "service_context_ref.h", ] public_deps = [ @@ -68,11 +68,11 @@ ] } - source_set("shell_test_support") { + source_set("service_test_support") { testonly = true sources = [ - "lib/shell_test.cc", - "shell_test.h", + "lib/service_test.cc", + "service_test.h", ] public_deps = [
diff --git a/services/shell/public/cpp/application_runner.h b/services/shell/public/cpp/application_runner.h index bc26b53e..11b2810 100644 --- a/services/shell/public/cpp/application_runner.h +++ b/services/shell/public/cpp/application_runner.h
@@ -13,7 +13,7 @@ namespace shell { class Service; -class ShellConnection; +class ServiceContext; // A utility for running a chromium based mojo Application. The typical use // case is to use when writing your MojoMain: @@ -37,7 +37,7 @@ void set_message_loop_type(base::MessageLoop::Type type); // Once the various parameters have been set above, use Run to initialize an - // ShellConnection wired to the provided delegate, and run a MessageLoop until + // ServiceContext wired to the provided delegate, and run a MessageLoop until // the application exits. // // Iff |init_base| is true, the runner will perform some initialization of @@ -48,18 +48,18 @@ // Calls Run above with |init_base| set to |true|. MojoResult Run(MojoHandle shell_handle); - // Allows the caller to shut down the connection with the shell. After the - // shell notices the pipe has closed, it will no longer track an instance of - // this application, though this application may continue to run and service - // requests from others. - void DestroyShellConnection(); + // Allows the caller to shut down the connection with the Service Manager. + // After the Service Manager notices the pipe has closed, it will no longer + // track an instance of this service, though this service may continue to run + // and handle requests from others. + void DestroyServiceContext(); // Allows the caller to explicitly quit the application. Must be called from // the thread which created the ApplicationRunner. void Quit(); private: - std::unique_ptr<ShellConnection> connection_; + std::unique_ptr<ServiceContext> context_; std::unique_ptr<Service> client_; // MessageLoop type. TYPE_CUSTOM is default (MessagePumpMojo will be used as
diff --git a/services/shell/public/cpp/connection.h b/services/shell/public/cpp/connection.h index b72bf89..eb49c2c8 100644 --- a/services/shell/public/cpp/connection.h +++ b/services/shell/public/cpp/connection.h
@@ -38,7 +38,7 @@ // // A Connection returned via Shell::ConnectToApplication() is owned by the // caller. -// An Connection received via AcceptConnection is owned by the ShellConnection. +// An Connection received via OnConnect is owned by the ServiceContext. // To close a connection, call CloseConnection which will destroy this object. class Connection { public:
diff --git a/services/shell/public/cpp/connector.h b/services/shell/public/cpp/connector.h index 9db076d..2f26e4c 100644 --- a/services/shell/public/cpp/connector.h +++ b/services/shell/public/cpp/connector.h
@@ -19,8 +19,8 @@ // connections between applications are established. Once Connect() is called, // this class is bound to the thread the call was made on and it cannot be // passed to another thread without calling Clone(). -// An instance of this class is created internally by ShellConnection for use -// on the thread ShellConnection is instantiated on, and this interface is +// An instance of this class is created internally by ServiceContext for use +// on the thread ServiceContext is instantiated on, and this interface is // wrapped by the Shell interface. // To use this interface on other threads, call Shell::CloneConnector() and // pass the result to another thread. To pass to subsequent threads, call
diff --git a/services/shell/public/cpp/lib/application_runner.cc b/services/shell/public/cpp/lib/application_runner.cc index 51cd8c03..78a8896 100644 --- a/services/shell/public/cpp/lib/application_runner.cc +++ b/services/shell/public/cpp/lib/application_runner.cc
@@ -11,7 +11,7 @@ #include "base/process/launch.h" #include "base/run_loop.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" namespace shell { @@ -51,12 +51,12 @@ std::unique_ptr<base::MessageLoop> loop; loop.reset(new base::MessageLoop(message_loop_type_)); - connection_.reset(new ShellConnection( + context_.reset(new ServiceContext( client_.get(), mojo::MakeRequest<mojom::Service>(mojo::MakeScopedHandle( mojo::MessagePipeHandle(service_request_handle))))); base::RunLoop run_loop; - connection_->SetConnectionLostClosure(run_loop.QuitClosure()); + context_->SetConnectionLostClosure(run_loop.QuitClosure()); run_loop.Run(); // It's very common for the client to cache the app and terminate on errors. // If we don't delete the client before the app we run the risk of the @@ -66,7 +66,7 @@ // client. loop.reset(); client_.reset(); - connection_.reset(); + context_.reset(); } return MOJO_RESULT_OK; } @@ -80,8 +80,8 @@ return Run(service_request_handle, init_base); } -void ApplicationRunner::DestroyShellConnection() { - connection_.reset(); +void ApplicationRunner::DestroyServiceContext() { + context_.reset(); } void ApplicationRunner::Quit() {
diff --git a/services/shell/public/cpp/lib/shell_connection.cc b/services/shell/public/cpp/lib/service_context.cc similarity index 82% rename from services/shell/public/cpp/lib/shell_connection.cc rename to services/shell/public/cpp/lib/service_context.cc index 173f6a3e..e5458dd 100644 --- a/services/shell/public/cpp/lib/shell_connection.cc +++ b/services/shell/public/cpp/lib/service_context.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 "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "base/bind.h" #include "base/logging.h" @@ -18,10 +18,10 @@ namespace shell { //////////////////////////////////////////////////////////////////////////////// -// ShellConnection, public: +// ServiceContext, public: -ShellConnection::ShellConnection(shell::Service* client, - mojom::ServiceRequest request) +ServiceContext::ServiceContext(shell::Service* client, + mojom::ServiceRequest request) : client_(client), binding_(this) { mojom::ConnectorPtr connector; pending_connector_request_ = GetProxy(&connector); @@ -31,19 +31,19 @@ binding_.Bind(std::move(request)); } -ShellConnection::~ShellConnection() {} +ServiceContext::~ServiceContext() {} -void ShellConnection::set_initialize_handler(const base::Closure& callback) { +void ServiceContext::set_initialize_handler(const base::Closure& callback) { initialize_handler_ = callback; } -void ShellConnection::SetAppTestConnectorForTesting( +void ServiceContext::SetAppTestConnectorForTesting( mojom::ConnectorPtr connector) { pending_connector_request_ = nullptr; connector_.reset(new ConnectorImpl(std::move(connector))); } -void ShellConnection::SetConnectionLostClosure(const base::Closure& closure) { +void ServiceContext::SetConnectionLostClosure(const base::Closure& closure) { connection_lost_closure_ = closure; if (should_run_connection_lost_closure_ && !connection_lost_closure_.is_null()) @@ -51,11 +51,11 @@ } //////////////////////////////////////////////////////////////////////////////// -// ShellConnection, mojom::Service implementation: +// ServiceContext, mojom::Service implementation: -void ShellConnection::OnStart(mojom::IdentityPtr identity, - uint32_t id, - const OnStartCallback& callback) { +void ServiceContext::OnStart(mojom::IdentityPtr identity, + uint32_t id, + const OnStartCallback& callback) { identity_ = identity.To<Identity>(); if (!initialize_handler_.is_null()) initialize_handler_.Run(); @@ -64,12 +64,12 @@ DCHECK(binding_.is_bound()); binding_.set_connection_error_handler( - base::Bind(&ShellConnection::OnConnectionError, base::Unretained(this))); + base::Bind(&ServiceContext::OnConnectionError, base::Unretained(this))); client_->OnStart(connector_.get(), identity_, id); } -void ShellConnection::OnConnect( +void ServiceContext::OnConnect( mojom::IdentityPtr source, uint32_t source_id, mojom::InterfaceProviderRequest local_interfaces, @@ -112,9 +112,9 @@ } //////////////////////////////////////////////////////////////////////////////// -// ShellConnection, private: +// ServiceContext, private: -void ShellConnection::OnConnectionError() { +void ServiceContext::OnConnectionError() { // Note that the Service doesn't technically have to quit now, it may live // on to service existing connections. All existing Connectors however are // invalid.
diff --git a/services/shell/public/cpp/lib/shell_connection_ref.cc b/services/shell/public/cpp/lib/service_context_ref.cc similarity index 63% rename from services/shell/public/cpp/lib/shell_connection_ref.cc rename to services/shell/public/cpp/lib/service_context_ref.cc index 388c028f..92c7028 100644 --- a/services/shell/public/cpp/lib/shell_connection_ref.cc +++ b/services/shell/public/cpp/lib/service_context_ref.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 "services/shell/public/cpp/shell_connection_ref.h" +#include "services/shell/public/cpp/service_context_ref.h" #include "base/bind.h" #include "base/memory/ptr_util.h" @@ -12,10 +12,10 @@ namespace shell { -class ShellConnectionRefImpl : public ShellConnectionRef { +class ServiceContextRefImpl : public ServiceContextRef { public: - ShellConnectionRefImpl( - base::WeakPtr<ShellConnectionRefFactory> factory, + ServiceContextRefImpl( + base::WeakPtr<ServiceContextRefFactory> factory, scoped_refptr<base::SingleThreadTaskRunner> service_task_runner) : factory_(factory), service_task_runner_(service_task_runner) { @@ -24,7 +24,7 @@ thread_checker_.DetachFromThread(); } - ~ShellConnectionRefImpl() override { + ~ServiceContextRefImpl() override { DCHECK(thread_checker_.CalledOnValidThread()); if (service_task_runner_->BelongsToCurrentThread() && factory_) { @@ -32,13 +32,13 @@ } else { service_task_runner_->PostTask( FROM_HERE, - base::Bind(&ShellConnectionRefFactory::Release, factory_)); + base::Bind(&ServiceContextRefFactory::Release, factory_)); } } private: - // ShellConnectionRef: - std::unique_ptr<ShellConnectionRef> Clone() override { + // ServiceContextRef: + std::unique_ptr<ServiceContextRef> Clone() override { DCHECK(thread_checker_.CalledOnValidThread()); if (service_task_runner_->BelongsToCurrentThread() && factory_) { @@ -46,40 +46,40 @@ } else { service_task_runner_->PostTask( FROM_HERE, - base::Bind(&ShellConnectionRefFactory::AddRef, factory_)); + base::Bind(&ServiceContextRefFactory::AddRef, factory_)); } return base::WrapUnique( - new ShellConnectionRefImpl(factory_, service_task_runner_)); + new ServiceContextRefImpl(factory_, service_task_runner_)); } - base::WeakPtr<ShellConnectionRefFactory> factory_; + base::WeakPtr<ServiceContextRefFactory> factory_; scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_; base::ThreadChecker thread_checker_; - DISALLOW_COPY_AND_ASSIGN(ShellConnectionRefImpl); + DISALLOW_COPY_AND_ASSIGN(ServiceContextRefImpl); }; -ShellConnectionRefFactory::ShellConnectionRefFactory( +ServiceContextRefFactory::ServiceContextRefFactory( const base::Closure& quit_closure) : quit_closure_(quit_closure), weak_factory_(this) { DCHECK(!quit_closure_.is_null()); } -ShellConnectionRefFactory::~ShellConnectionRefFactory() {} +ServiceContextRefFactory::~ServiceContextRefFactory() {} -std::unique_ptr<ShellConnectionRef> ShellConnectionRefFactory::CreateRef() { +std::unique_ptr<ServiceContextRef> ServiceContextRefFactory::CreateRef() { AddRef(); return base::WrapUnique( - new ShellConnectionRefImpl(weak_factory_.GetWeakPtr(), + new ServiceContextRefImpl(weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); } -void ShellConnectionRefFactory::AddRef() { +void ServiceContextRefFactory::AddRef() { ++ref_count_; } -void ShellConnectionRefFactory::Release() { +void ServiceContextRefFactory::Release() { if (!--ref_count_) quit_closure_.Run(); }
diff --git a/services/shell/public/cpp/lib/shell_test.cc b/services/shell/public/cpp/lib/service_test.cc similarity index 65% rename from services/shell/public/cpp/lib/shell_test.cc rename to services/shell/public/cpp/lib/service_test.cc index 6f4f1a7c..30176a1 100644 --- a/services/shell/public/cpp/lib/shell_test.cc +++ b/services/shell/public/cpp/lib/service_test.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 "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" @@ -13,32 +13,33 @@ namespace shell { namespace test { -ShellTestClient::ShellTestClient(ShellTest* test) : test_(test) {} -ShellTestClient::~ShellTestClient() {} +ServiceTestClient::ServiceTestClient(ServiceTest* test) : test_(test) {} +ServiceTestClient::~ServiceTestClient() {} -void ShellTestClient::OnStart(Connector* connector, const Identity& identity, +void ServiceTestClient::OnStart(Connector* connector, const Identity& identity, uint32_t id) { test_->OnStartCalled(connector, identity.name(), identity.user_id(), id); } -ShellTest::ShellTest() {} -ShellTest::ShellTest(const std::string& test_name) : test_name_(test_name) {} -ShellTest::~ShellTest() {} +ServiceTest::ServiceTest() {} +ServiceTest::ServiceTest(const std::string& test_name) + : test_name_(test_name) {} +ServiceTest::~ServiceTest() {} -void ShellTest::InitTestName(const std::string& test_name) { +void ServiceTest::InitTestName(const std::string& test_name) { DCHECK(test_name_.empty()); test_name_ = test_name; } -std::unique_ptr<Service> ShellTest::CreateService() { - return base::WrapUnique(new ShellTestClient(this)); +std::unique_ptr<Service> ServiceTest::CreateService() { + return base::WrapUnique(new ServiceTestClient(this)); } -std::unique_ptr<base::MessageLoop> ShellTest::CreateMessageLoop() { +std::unique_ptr<base::MessageLoop> ServiceTest::CreateMessageLoop() { return base::WrapUnique(new base::MessageLoop); } -void ShellTest::OnStartCalled(Connector* connector, +void ServiceTest::OnStartCalled(Connector* connector, const std::string& name, const std::string& user_id, uint32_t id) { @@ -49,7 +50,7 @@ initialize_called_.Run(); } -void ShellTest::SetUp() { +void ServiceTest::SetUp() { service_ = CreateService(); message_loop_ = CreateMessageLoop(); background_shell_.reset(new shell::BackgroundShell); @@ -62,16 +63,16 @@ base::MessageLoop::current()); initialize_called_ = run_loop.QuitClosure(); - shell_connection_.reset(new ShellConnection( + service_context_.reset(new ServiceContext( service_.get(), background_shell_->CreateServiceRequest(test_name_))); - connector_ = shell_connection_->connector(); + connector_ = service_context_->connector(); run_loop.Run(); } -void ShellTest::TearDown() { - shell_connection_.reset(); +void ServiceTest::TearDown() { + service_context_.reset(); background_shell_.reset(); message_loop_.reset(); service_.reset();
diff --git a/services/shell/public/cpp/service.h b/services/shell/public/cpp/service.h index 4e015e4..d79c2ca 100644 --- a/services/shell/public/cpp/service.h +++ b/services/shell/public/cpp/service.h
@@ -43,7 +43,7 @@ // Called when the Service Manager has stopped tracking this instance. The // service should use this as a signal to exit, and in fact its process may // be reaped shortly afterward. - // Return true from this method to tell the ShellConnection to run its + // Return true from this method to tell the ServiceContext to run its // connection lost closure if it has one, false to prevent it from being run. // The default implementation returns true. // When used in conjunction with ApplicationRunner, returning true here quits
diff --git a/services/shell/public/cpp/shell_connection.h b/services/shell/public/cpp/service_context.h similarity index 70% rename from services/shell/public/cpp/shell_connection.h rename to services/shell/public/cpp/service_context.h index 8348a21..2cad395 100644 --- a/services/shell/public/cpp/shell_connection.h +++ b/services/shell/public/cpp/service_context.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_SHELL_PUBLIC_CPP_SHELL_CONNECTION_H_ -#define SERVICES_SHELL_PUBLIC_CPP_SHELL_CONNECTION_H_ +#ifndef SERVICES_SHELL_PUBLIC_CPP_SERVICE_CONTEXT_H_ +#define SERVICES_SHELL_PUBLIC_CPP_SERVICE_CONTEXT_H_ #include <memory> #include <utility> @@ -22,35 +22,35 @@ class Connector; -// Encapsulates a connection to the Mojo Shell in two parts: -// - a bound InterfacePtr to mojom::Shell, the primary mechanism -// by which the instantiating application interacts with other services -// brokered by the Mojo Shell. -// - a bound InterfaceRequest of mojom::Service, an interface -// used by the Mojo Shell to inform this application of lifecycle events and +// Encapsulates a connection to the Service Manager in two parts: +// - a bound InterfacePtr to mojom::Connector, the primary mechanism +// by which the instantiating service connects to other services, +// brokered by the Service Manager. +// - a bound InterfaceRequest of mojom::Service, an interface used by the +// Service Manager to inform this service of lifecycle events and // inbound connections brokered by it. // // This class should be used in two scenarios: // - During early startup to bind the mojom::ServiceRequest obtained from -// the Mojo Shell, typically in response to either MojoMain() or main(). +// the Service Manager, typically in response to either MojoMain() or main(). // - In an implementation of mojom::ServiceFactory to bind the -// mojom::ServiceRequest passed via StartApplication. In this scenario -// there can be many instances of this class per process. +// mojom::ServiceRequest passed via CreateService. In this scenario there can +// be many instances of this class per process. // -// Instances of this class are constructed with an implementation of the Shell -// Client Lib's Service interface. See documentation in service.h +// Instances of this class are constructed with an implementation of the Service +// Manager Client Lib's Service interface. See documentation in service.h // for details. // -class ShellConnection : public mojom::Service { +class ServiceContext : public mojom::Service { public: - // Creates a new ShellConnection bound to |request|. This connection may be + // Creates a new ServiceContext bound to |request|. This connection may be // used immediately to make outgoing connections via connector(). Does not // take ownership of |client|, which must remain valid for the lifetime of - // ShellConnection. - ShellConnection(shell::Service* client, - mojom::ServiceRequest request); + // ServiceContext. + ServiceContext(shell::Service* client, + mojom::ServiceRequest request); - ~ShellConnection() override; + ~ServiceContext() override; Connector* connector() { return connector_.get(); } const Identity& identity() { return identity_; } @@ -87,7 +87,8 @@ // convenient for the client. ScopedVector<Connection> incoming_connections_; - // A pending Connector request which will eventually be passed to the shell. + // A pending Connector request which will eventually be passed to the Service + // Manager. mojom::ConnectorRequest pending_connector_request_; shell::Service* client_; @@ -98,9 +99,9 @@ base::Closure connection_lost_closure_; - DISALLOW_COPY_AND_ASSIGN(ShellConnection); + DISALLOW_COPY_AND_ASSIGN(ServiceContext); }; } // namespace shell -#endif // SERVICES_SHELL_PUBLIC_CPP_SHELL_CONNECTION_H_ +#endif // SERVICES_SHELL_PUBLIC_CPP_SERVICE_CONTEXT_H_
diff --git a/services/shell/public/cpp/service_context_ref.h b/services/shell/public/cpp/service_context_ref.h new file mode 100644 index 0000000..0b81e8d --- /dev/null +++ b/services/shell/public/cpp/service_context_ref.h
@@ -0,0 +1,59 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_SHELL_PUBLIC_CPP_SERVICE_CONTEXT_REF_H_ +#define SERVICES_SHELL_PUBLIC_CPP_SERVICE_CONTEXT_REF_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" + +namespace shell { + +class ServiceContextRefImpl; + +// An interface implementation can keep this object as a member variable to +// hold a reference to the ServiceContext, keeping it alive as long as the +// bound implementation exists. +// +// This class is safe to use on any thread and instances may be passed to other +// threads. However, each instance should only be used on one thread at a time, +// otherwise there'll be races between the AddRef resulting from cloning and +// destruction. +class ServiceContextRef { + public: + virtual ~ServiceContextRef() {} + + virtual std::unique_ptr<ServiceContextRef> Clone() = 0; +}; + +class ServiceContextRefFactory { + public: + // |quit_closure| is called whenever the last ref is destroyed. + explicit ServiceContextRefFactory(const base::Closure& quit_closure); + ~ServiceContextRefFactory(); + + std::unique_ptr<ServiceContextRef> CreateRef(); + + bool HasNoRefs() const { return !ref_count_; } + + private: + friend ServiceContextRefImpl; + + // Called from ServiceContextRefImpl. + void AddRef(); + void Release(); + + const base::Closure quit_closure_; + int ref_count_ = 0; + base::WeakPtrFactory<ServiceContextRefFactory> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ServiceContextRefFactory); +}; + +} // namespace shell + +#endif // SERVICES_SHELL_PUBLIC_CPP_SERVICE_CONTEXT_REF_H_
diff --git a/services/shell/public/cpp/shell_test.h b/services/shell/public/cpp/service_test.h similarity index 73% rename from services/shell/public/cpp/shell_test.h rename to services/shell/public/cpp/service_test.h index 452018e..ca3868ef 100644 --- a/services/shell/public/cpp/shell_test.h +++ b/services/shell/public/cpp/service_test.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SERVICES_SHELL_PUBLIC_CPP_SHELL_TEST_H_ -#define SERVICES_SHELL_PUBLIC_CPP_SHELL_TEST_H_ +#ifndef SERVICES_SHELL_PUBLIC_CPP_SERVICE_TEST_H_ +#define SERVICES_SHELL_PUBLIC_CPP_SERVICE_TEST_H_ #include <memory> #include "base/macros.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -23,16 +23,16 @@ namespace test { -class ShellTest; +class ServiceTest; -// A default implementation of Service for use in ShellTests. Tests wishing +// A default implementation of Service for use in ServiceTests. Tests wishing // to customize this should subclass this class instead of Service, -// otherwise they will have to call ShellTest::OnStartCalled() to forward +// otherwise they will have to call ServiceTest::OnStartCalled() to forward // metadata from OnStart() to the test. -class ShellTestClient : public Service { +class ServiceTestClient : public Service { public: - explicit ShellTestClient(ShellTest* test); - ~ShellTestClient() override; + explicit ServiceTestClient(ServiceTest* test); + ~ServiceTestClient() override; protected: void OnStart(Connector* connector, @@ -40,20 +40,20 @@ uint32_t id) override; private: - ShellTest* test_; + ServiceTest* test_; - DISALLOW_COPY_AND_ASSIGN(ShellTestClient); + DISALLOW_COPY_AND_ASSIGN(ServiceTestClient); }; -class ShellTest : public testing::Test { +class ServiceTest : public testing::Test { public: - ShellTest(); + ServiceTest(); // Initialize passing the name to use as the identity for the test itself. // Once set via this constructor, it cannot be changed later by calling // InitTestName(). The test executable must provide a manifest in the // appropriate location that specifies this name also. - explicit ShellTest(const std::string& test_name); - ~ShellTest() override; + explicit ServiceTest(const std::string& test_name); + ~ServiceTest() override; protected: // See constructor. Can only be called once. @@ -61,7 +61,7 @@ Connector* connector() { return connector_; } - // Instance information received from the Shell during OnStart(). + // Instance information received from the Service Manager during OnStart(). const std::string& test_name() const { return initialize_name_; } const std::string& test_userid() const { return initialize_userid_; } uint32_t test_instance_id() const { return initialize_instance_id_; } @@ -85,13 +85,13 @@ void TearDown() override; private: - friend ShellTestClient; + friend ServiceTestClient; std::unique_ptr<Service> service_; std::unique_ptr<base::MessageLoop> message_loop_; std::unique_ptr<BackgroundShell> background_shell_; - std::unique_ptr<ShellConnection> shell_connection_; + std::unique_ptr<ServiceContext> service_context_; // See constructor. std::string test_name_; @@ -103,10 +103,10 @@ base::Closure initialize_called_; - DISALLOW_COPY_AND_ASSIGN(ShellTest); + DISALLOW_COPY_AND_ASSIGN(ServiceTest); }; } // namespace test } // namespace shell -#endif // SERVICES_SHELL_PUBLIC_CPP_SHELL_TEST_H_ +#endif // SERVICES_SHELL_PUBLIC_CPP_SERVICE_TEST_H_
diff --git a/services/shell/public/cpp/shell_connection_ref.h b/services/shell/public/cpp/shell_connection_ref.h deleted file mode 100644 index b22e12e..0000000 --- a/services/shell/public/cpp/shell_connection_ref.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_SHELL_PUBLIC_CPP_SHELL_CONNECTION_REF_H_ -#define SERVICES_SHELL_PUBLIC_CPP_SHELL_CONNECTION_REF_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" - -namespace shell { - -class ShellConnectionRefImpl; - -// An interface implementation can keep this object as a member variable to -// hold a reference to the ShellConnection, keeping it alive as long as the -// bound implementation exists. -// -// This class is safe to use on any thread and instances may be passed to other -// threads. However, each instance should only be used on one thread at a time, -// otherwise there'll be races between the AddRef resulting from cloning and -// destruction. -class ShellConnectionRef { - public: - virtual ~ShellConnectionRef() {} - - virtual std::unique_ptr<ShellConnectionRef> Clone() = 0; -}; - -class ShellConnectionRefFactory { - public: - // |quit_closure| is called whenever the last ref is destroyed. - explicit ShellConnectionRefFactory(const base::Closure& quit_closure); - ~ShellConnectionRefFactory(); - - std::unique_ptr<ShellConnectionRef> CreateRef(); - - bool HasNoRefs() const { return !ref_count_; } - - private: - friend ShellConnectionRefImpl; - - // Called from ShellConnectionRefImpl. - void AddRef(); - void Release(); - - const base::Closure quit_closure_; - int ref_count_ = 0; - base::WeakPtrFactory<ShellConnectionRefFactory> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ShellConnectionRefFactory); -}; - -} // namespace shell - -#endif // SERVICES_SHELL_PUBLIC_CPP_SHELL_CONNECTION_REF_H_
diff --git a/services/shell/runner/child/test_native_main.cc b/services/shell/runner/child/test_native_main.cc index ded151ab..763b7eb 100644 --- a/services/shell/runner/child/test_native_main.cc +++ b/services/shell/runner/child/test_native_main.cc
@@ -16,7 +16,7 @@ #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/process_delegate.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/runner/common/client_util.h" #include "services/shell/runner/init.h" @@ -58,7 +58,7 @@ mojo::edk::SetParentPipeHandleFromCommandLine(); base::MessageLoop loop; - shell::ShellConnection impl(service, + shell::ServiceContext impl(service, shell::GetServiceRequestFromCommandLine()); base::RunLoop().Run();
diff --git a/services/shell/service_manager.cc b/services/shell/service_manager.cc index 90815627..70aca84c 100644 --- a/services/shell/service_manager.cc +++ b/services/shell/service_manager.cc
@@ -23,7 +23,7 @@ #include "services/shell/connect_util.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/names.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/public/interfaces/connector.mojom.h" #include "services/shell/public/interfaces/service.mojom.h" #include "services/shell/public/interfaces/service_manager.mojom.h" @@ -497,7 +497,7 @@ Identity(), CreateServiceManagerIdentity(), GetPermissiveCapabilities()); instance->StartWithService(std::move(service)); singletons_.insert(kServiceManagerName); - shell_connection_.reset(new ShellConnection(this, std::move(request))); + service_context_.reset(new ServiceContext(this, std::move(request))); if (catalog) InitCatalog(std::move(catalog));
diff --git a/services/shell/service_manager.h b/services/shell/service_manager.h index 6a448cf..5357d74 100644 --- a/services/shell/service_manager.h +++ b/services/shell/service_manager.h
@@ -27,7 +27,7 @@ #include "services/shell/public/interfaces/service_manager.mojom.h" namespace shell { -class ShellConnection; +class ServiceContext; // Creates an identity for the Service Manager, used when the Service Manager // connects to services. @@ -154,7 +154,7 @@ mojo::InterfacePtrSet<mojom::ServiceManagerListener> listeners_; base::Callback<void(const Identity&)> instance_quit_callback_; std::unique_ptr<NativeRunnerFactory> native_runner_factory_; - std::unique_ptr<ShellConnection> shell_connection_; + std::unique_ptr<ServiceContext> service_context_; base::WeakPtrFactory<ServiceManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceManager);
diff --git a/services/shell/shell_public.gyp b/services/shell/shell_public.gyp index 3cbfa9e..c10db5b 100644 --- a/services/shell/shell_public.gyp +++ b/services/shell/shell_public.gyp
@@ -59,13 +59,13 @@ 'public/cpp/lib/names.cc', 'public/cpp/lib/interface_provider.cc', 'public/cpp/lib/service.cc', - 'public/cpp/lib/shell_connection.cc', - 'public/cpp/lib/shell_connection_ref.cc', + 'public/cpp/lib/service_context.cc', + 'public/cpp/lib/service_context_ref.cc', 'public/cpp/names.h', 'public/cpp/interface_provider.h', 'public/cpp/service.h', - 'public/cpp/shell_connection.h', - 'public/cpp/shell_connection_ref.h', + 'public/cpp/service_context.h', + 'public/cpp/service_context_ref.h', ], 'dependencies': [ 'shell_interfaces',
diff --git a/services/shell/tests/connect/BUILD.gn b/services/shell/tests/connect/BUILD.gn index 00bf944..91fb22cf 100644 --- a/services/shell/tests/connect/BUILD.gn +++ b/services/shell/tests/connect/BUILD.gn
@@ -16,7 +16,7 @@ ":interfaces", "//base", "//base/test:test_support", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/interfaces", ]
diff --git a/services/shell/tests/connect/connect_unittest.cc b/services/shell/tests/connect/connect_unittest.cc index 0b43d40..bfd372d 100644 --- a/services/shell/tests/connect/connect_unittest.cc +++ b/services/shell/tests/connect/connect_unittest.cc
@@ -15,7 +15,7 @@ #include "base/test/test_suite.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/shell/public/cpp/names.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/shell/public/interfaces/service_manager.mojom.h" #include "services/shell/tests/connect/connect_test.mojom.h" @@ -68,11 +68,11 @@ } // namespace -class ConnectTest : public test::ShellTest, +class ConnectTest : public test::ServiceTest, public InterfaceFactory<test::mojom::ExposedInterface>, public test::mojom::ExposedInterface { public: - ConnectTest() : ShellTest("mojo:connect_unittests") {} + ConnectTest() : ServiceTest("mojo:connect_unittests") {} ~ConnectTest() override {} protected: @@ -108,9 +108,9 @@ } private: - // test::ShellTest: + // test::ServiceTest: void SetUp() override { - test::ShellTest::SetUp(); + test::ServiceTest::SetUp(); // We need to connect to the package first to force the shell to read the // package app's manifest and register aliases for the applications it // provides.
diff --git a/services/shell/tests/lifecycle/BUILD.gn b/services/shell/tests/lifecycle/BUILD.gn index 3e002e7..498cdbd 100644 --- a/services/shell/tests/lifecycle/BUILD.gn +++ b/services/shell/tests/lifecycle/BUILD.gn
@@ -16,7 +16,7 @@ ":interfaces", "//base", "//base/test:test_support", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/interfaces", "//services/shell/runner/common",
diff --git a/services/shell/tests/lifecycle/app_client.cc b/services/shell/tests/lifecycle/app_client.cc index 4cba823..68ca273 100644 --- a/services/shell/tests/lifecycle/app_client.cc +++ b/services/shell/tests/lifecycle/app_client.cc
@@ -4,14 +4,14 @@ #include "services/shell/tests/lifecycle/app_client.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" namespace shell { namespace test { AppClient::AppClient() {} AppClient::AppClient(shell::mojom::ServiceRequest request) - : connection_(new ShellConnection(this, std::move(request))) {} + : context_(new ServiceContext(this, std::move(request))) {} AppClient::~AppClient() {} bool AppClient::OnConnect(Connection* connection) { @@ -41,7 +41,7 @@ void AppClient::CloseShellConnection() { DCHECK(runner_); - runner_->DestroyShellConnection(); + runner_->DestroyServiceContext(); // Quit the app once the caller goes away. bindings_.set_connection_error_handler( base::Bind(&AppClient::BindingLost, base::Unretained(this)));
diff --git a/services/shell/tests/lifecycle/app_client.h b/services/shell/tests/lifecycle/app_client.h index b83a5a27..0dd6c1d 100644 --- a/services/shell/tests/lifecycle/app_client.h +++ b/services/shell/tests/lifecycle/app_client.h
@@ -20,7 +20,7 @@ using LifecycleControlRequest = shell::test::mojom::LifecycleControlRequest; namespace shell { -class ShellConnection; +class ServiceContext; namespace test { @@ -53,7 +53,7 @@ ApplicationRunner* runner_ = nullptr; mojo::BindingSet<LifecycleControl> bindings_; - std::unique_ptr<ShellConnection> connection_; + std::unique_ptr<ServiceContext> context_; DISALLOW_COPY_AND_ASSIGN(AppClient); };
diff --git a/services/shell/tests/lifecycle/lifecycle_unittest.cc b/services/shell/tests/lifecycle/lifecycle_unittest.cc index 4864275..830d0fc 100644 --- a/services/shell/tests/lifecycle/lifecycle_unittest.cc +++ b/services/shell/tests/lifecycle/lifecycle_unittest.cc
@@ -11,7 +11,7 @@ #include "base/process/process.h" #include "base/run_loop.h" #include "services/shell/public/cpp/identity.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/shell/public/interfaces/service_manager.mojom.h" #include "services/shell/tests/lifecycle/lifecycle_unittest.mojom.h" #include "services/shell/tests/util.h" @@ -126,21 +126,21 @@ } // namespace -class LifecycleTest : public test::ShellTest { +class LifecycleTest : public test::ServiceTest { public: - LifecycleTest() : ShellTest(kTestName) {} + LifecycleTest() : ServiceTest(kTestName) {} ~LifecycleTest() override {} protected: - // test::ShellTest: + // test::ServiceTest: void SetUp() override { - test::ShellTest::SetUp(); + test::ServiceTest::SetUp(); InitPackage(); instances_ = TrackInstances(); } void TearDown() override { instances_.reset(); - test::ShellTest::TearDown(); + test::ServiceTest::TearDown(); } bool CanRunCrashTest() {
diff --git a/services/shell/tests/lifecycle/package.cc b/services/shell/tests/lifecycle/package.cc index cfac449..3250324 100644 --- a/services/shell/tests/lifecycle/package.cc +++ b/services/shell/tests/lifecycle/package.cc
@@ -10,7 +10,7 @@ #include "mojo/public/c/system/main.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/shell/public/cpp/application_runner.h" -#include "services/shell/public/cpp/shell_connection.h" +#include "services/shell/public/cpp/service_context.h" #include "services/shell/public/interfaces/service_factory.mojom.h" #include "services/shell/tests/lifecycle/app_client.h" #include "services/shell/tests/lifecycle/lifecycle_unittest.mojom.h" @@ -26,7 +26,7 @@ PackagedApp(shell::mojom::ServiceRequest request, const DestructCallback& shell_connection_closed_callback, const DestructCallback& destruct_callback) - : connection_(new shell::ShellConnection(this, std::move(request))), + : connection_(new shell::ServiceContext(this, std::move(request))), shell_connection_closed_callback_(shell_connection_closed_callback), destruct_callback_(destruct_callback) { bindings_.set_connection_error_handler(base::Bind(&PackagedApp::BindingLost, @@ -75,7 +75,7 @@ delete this; } - std::unique_ptr<shell::ShellConnection> connection_; + std::unique_ptr<shell::ServiceContext> connection_; mojo::BindingSet<LifecycleControl> bindings_; // Run when this object's connection to the shell is closed. DestructCallback shell_connection_closed_callback_;
diff --git a/services/shell/tests/shell/BUILD.gn b/services/shell/tests/shell/BUILD.gn index d26ff7c..4996253e 100644 --- a/services/shell/tests/shell/BUILD.gn +++ b/services/shell/tests/shell/BUILD.gn
@@ -18,7 +18,7 @@ "//base", "//base/test:test_config", "//mojo/common:common_base", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/interfaces", ]
diff --git a/services/shell/tests/shell/shell_unittest.cc b/services/shell/tests/shell/shell_unittest.cc index d70e7fa..4c740592 100644 --- a/services/shell/tests/shell/shell_unittest.cc +++ b/services/shell/tests/shell/shell_unittest.cc
@@ -17,7 +17,7 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "services/shell/public/cpp/interface_factory.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/shell/public/interfaces/service_manager.mojom.h" #include "services/shell/tests/shell/shell_unittest.mojom.h" @@ -26,12 +26,12 @@ namespace { class ShellTestClient - : public test::ShellTestClient, + : public test::ServiceTestClient, public InterfaceFactory<test::mojom::CreateInstanceTest>, public test::mojom::CreateInstanceTest { public: - explicit ShellTestClient(test::ShellTest* test) - : test::ShellTestClient(test), + explicit ShellTestClient(test::ServiceTest* test) + : test::ServiceTestClient(test), target_id_(shell::mojom::kInvalidInstanceID), binding_(this) {} ~ShellTestClient() override {} @@ -39,7 +39,7 @@ uint32_t target_id() const { return target_id_; } private: - // test::ShellTestClient: + // test::ServiceTestClient: bool OnConnect(Connection* connection) override { connection->AddInterface<test::mojom::CreateInstanceTest>(this); return true; @@ -67,11 +67,11 @@ } // namespace -class ShellTest : public test::ShellTest, +class ShellTest : public test::ServiceTest, public mojom::ServiceManagerListener { public: ShellTest() - : test::ShellTest("mojo:shell_unittest"), + : test::ServiceTest("mojo:shell_unittest"), service_(nullptr), binding_(this) {} ~ShellTest() override {} @@ -122,7 +122,7 @@ } private: - // test::ShellTest: + // test::ServiceTest: std::unique_ptr<Service> CreateService() override { service_ = new ShellTestClient(this); return base::WrapUnique(service_);
diff --git a/services/shell/tests/shutdown/BUILD.gn b/services/shell/tests/shutdown/BUILD.gn index be1661c..e092cb3 100644 --- a/services/shell/tests/shutdown/BUILD.gn +++ b/services/shell/tests/shutdown/BUILD.gn
@@ -19,7 +19,7 @@ ":shutdown_service", "//base", "//base/test:test_config", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/interfaces", ]
diff --git a/services/shell/tests/shutdown/shutdown_unittest.cc b/services/shell/tests/shutdown/shutdown_unittest.cc index ea7faee..93d1c94 100644 --- a/services/shell/tests/shutdown/shutdown_unittest.cc +++ b/services/shell/tests/shutdown/shutdown_unittest.cc
@@ -4,15 +4,15 @@ #include "base/run_loop.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/shell/tests/shutdown/shutdown_unittest.mojom.h" namespace shell { namespace { -class ShutdownTest : public test::ShellTest { +class ShutdownTest : public test::ServiceTest { public: - ShutdownTest() : test::ShellTest("mojo:shutdown_unittest") {} + ShutdownTest() : test::ServiceTest("mojo:shutdown_unittest") {} ~ShutdownTest() override {} private:
diff --git a/services/ui/clipboard/BUILD.gn b/services/ui/clipboard/BUILD.gn index 0114a5b5..23044b3 100644 --- a/services/ui/clipboard/BUILD.gn +++ b/services/ui/clipboard/BUILD.gn
@@ -37,7 +37,7 @@ deps = [ "//base", "//mojo/common", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/cpp/test:run_all_shelltests", "//services/ui/public/interfaces",
diff --git a/services/ui/clipboard/clipboard_unittest.cc b/services/ui/clipboard/clipboard_unittest.cc index b01951e..a6f287c 100644 --- a/services/ui/clipboard/clipboard_unittest.cc +++ b/services/ui/clipboard/clipboard_unittest.cc
@@ -9,8 +9,8 @@ #include "base/macros.h" #include "base/run_loop.h" #include "mojo/common/common_type_converters.h" -#include "services/shell/public/cpp/shell_connection.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_context.h" +#include "services/shell/public/cpp/service_test.h" #include "services/ui/public/interfaces/clipboard.mojom.h" using mojo::Array; @@ -28,14 +28,14 @@ } // namespace -class ClipboardAppTest : public shell::test::ShellTest { +class ClipboardAppTest : public shell::test::ServiceTest { public: - ClipboardAppTest() : ShellTest("exe:mus_clipboard_unittests") {} + ClipboardAppTest() : ServiceTest("exe:mus_clipboard_unittests") {} ~ClipboardAppTest() override {} - // Overridden from shell::test::ShellTest: + // Overridden from shell::test::ServiceTest: void SetUp() override { - ShellTest::SetUp(); + ServiceTest::SetUp(); connector()->ConnectToInterface("mojo:ui", &clipboard_); ASSERT_TRUE(clipboard_);
diff --git a/services/ui/common/gpu_type_converters.cc b/services/ui/common/gpu_type_converters.cc index a09b9590..9ee911a5 100644 --- a/services/ui/common/gpu_type_converters.cc +++ b/services/ui/common/gpu_type_converters.cc
@@ -31,6 +31,7 @@ if (platform_file != -1) result->socket = mojo::WrapPlatformFile(platform_file); #endif + result->mojo_handle.reset(handle.mojo_handle); return result; } @@ -40,6 +41,11 @@ const ui::mojom::ChannelHandlePtr& handle) { if (handle.is_null()) return IPC::ChannelHandle(); + if (handle->mojo_handle.is_valid()) { + IPC::ChannelHandle channel_handle(handle->mojo_handle.release()); + channel_handle.name = handle->name; + return channel_handle; + } #if defined(OS_WIN) // On windows, a pipe handle Will NOT be marshalled over IPC. DCHECK(!handle->socket.is_valid());
diff --git a/services/ui/common/gpu_type_converters_unittest.cc b/services/ui/common/gpu_type_converters_unittest.cc index 08fc52b2..67b3047 100644 --- a/services/ui/common/gpu_type_converters_unittest.cc +++ b/services/ui/common/gpu_type_converters_unittest.cc
@@ -57,6 +57,28 @@ base::ScopedFD socped_fd3(handle.socket.fd); } #endif + + { + const std::string channel_name = "test_channel_name"; + mojo::MessagePipe message_pipe; + mojo::MessagePipeHandle mp_handle = message_pipe.handle0.release(); + EXPECT_TRUE(mp_handle.is_valid()); + IPC::ChannelHandle handle(mp_handle); + handle.name = channel_name; + + ui::mojom::ChannelHandlePtr mojo_handle = + ui::mojom::ChannelHandle::From(handle); + ASSERT_EQ(mojo_handle->name, channel_name); + ASSERT_EQ(mojo_handle->mojo_handle.get(), mp_handle); + EXPECT_FALSE(mojo_handle->socket.is_valid()); + + handle = mojo_handle.To<IPC::ChannelHandle>(); + ASSERT_EQ(handle.name, channel_name); + ASSERT_EQ(handle.mojo_handle, mp_handle); +#if defined(OS_POSIX) + ASSERT_EQ(handle.socket.fd, -1); +#endif + } } // Test for mojo TypeConverter of ui::mojom::GpuMemoryBufferHandle
diff --git a/services/ui/public/cpp/tests/BUILD.gn b/services/ui/public/cpp/tests/BUILD.gn index af29abe..150da06b 100644 --- a/services/ui/public/cpp/tests/BUILD.gn +++ b/services/ui/public/cpp/tests/BUILD.gn
@@ -40,7 +40,7 @@ deps = [ "//base", "//base/test:test_config", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/ui/common:mus_common", "//services/ui/public/cpp",
diff --git a/services/ui/public/cpp/tests/window_server_shelltest_base.cc b/services/ui/public/cpp/tests/window_server_shelltest_base.cc index ee55da4..c34ce7f 100644 --- a/services/ui/public/cpp/tests/window_server_shelltest_base.cc +++ b/services/ui/public/cpp/tests/window_server_shelltest_base.cc
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/ui/common/switches.h" #include "ui/gl/gl_switches.h" @@ -20,21 +20,21 @@ const char kTestAppName[] = "mojo:mus_ws_unittests_app"; -class WindowServerShellTestClient : public shell::test::ShellTestClient { +class WindowServerServiceTestClient : public shell::test::ServiceTestClient { public: - explicit WindowServerShellTestClient(WindowServerShellTestBase* test) - : ShellTestClient(test), test_(test) {} - ~WindowServerShellTestClient() override {} + explicit WindowServerServiceTestClient(WindowServerServiceTestBase* test) + : ServiceTestClient(test), test_(test) {} + ~WindowServerServiceTestClient() override {} private: - // shell::test::ShellTestClient: + // shell::test::ServiceTestClient: bool OnConnect(shell::Connection* connection) override { return test_->OnConnect(connection); } - WindowServerShellTestBase* test_; + WindowServerServiceTestBase* test_; - DISALLOW_COPY_AND_ASSIGN(WindowServerShellTestClient); + DISALLOW_COPY_AND_ASSIGN(WindowServerServiceTestClient); }; void EnsureCommandLineSwitch(const std::string& name) { @@ -45,17 +45,17 @@ } // namespace -WindowServerShellTestBase::WindowServerShellTestBase() - : ShellTest(kTestAppName) { +WindowServerServiceTestBase::WindowServerServiceTestBase() + : ServiceTest(kTestAppName) { EnsureCommandLineSwitch(switches::kUseTestConfig); EnsureCommandLineSwitch(::switches::kOverrideUseGLWithOSMesaForTests); } -WindowServerShellTestBase::~WindowServerShellTestBase() {} +WindowServerServiceTestBase::~WindowServerServiceTestBase() {} std::unique_ptr<shell::Service> -WindowServerShellTestBase::CreateService() { - return base::WrapUnique(new WindowServerShellTestClient(this)); +WindowServerServiceTestBase::CreateService() { + return base::WrapUnique(new WindowServerServiceTestClient(this)); } } // namespace ui
diff --git a/services/ui/public/cpp/tests/window_server_shelltest_base.h b/services/ui/public/cpp/tests/window_server_shelltest_base.h index 01d9547..ad02871 100644 --- a/services/ui/public/cpp/tests/window_server_shelltest_base.h +++ b/services/ui/public/cpp/tests/window_server_shelltest_base.h
@@ -7,23 +7,23 @@ #include "base/macros.h" #include "services/shell/public/cpp/connection.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" namespace ui { -// Base class for all window manager shelltests to perform some common setup. -class WindowServerShellTestBase : public shell::test::ShellTest { +// Base class for all window manager ServiceTests to perform some common setup. +class WindowServerServiceTestBase : public shell::test::ServiceTest { public: - WindowServerShellTestBase(); - ~WindowServerShellTestBase() override; + WindowServerServiceTestBase(); + ~WindowServerServiceTestBase() override; virtual bool OnConnect(shell::Connection* connection) = 0; private: - // shell::test::ShellTest: + // shell::test::ServiceTest: std::unique_ptr<shell::Service> CreateService() override; - DISALLOW_COPY_AND_ASSIGN(WindowServerShellTestBase); + DISALLOW_COPY_AND_ASSIGN(WindowServerServiceTestBase); }; } // namespace ui
diff --git a/services/ui/public/cpp/tests/window_server_test_base.cc b/services/ui/public/cpp/tests/window_server_test_base.cc index 40312749..1a72fdc 100644 --- a/services/ui/public/cpp/tests/window_server_test_base.cc +++ b/services/ui/public/cpp/tests/window_server_test_base.cc
@@ -65,7 +65,7 @@ } void WindowServerTestBase::SetUp() { - WindowServerShellTestBase::SetUp(); + WindowServerServiceTestBase::SetUp(); CreateWindowTreeHost(connector(), this, &host_, this);
diff --git a/services/ui/public/cpp/tests/window_server_test_base.h b/services/ui/public/cpp/tests/window_server_test_base.h index 54cf30d..9294305 100644 --- a/services/ui/public/cpp/tests/window_server_test_base.h +++ b/services/ui/public/cpp/tests/window_server_test_base.h
@@ -22,7 +22,7 @@ // has been invoked. window_manager() can be used to access the WindowServer // established as part of SetUp(). class WindowServerTestBase - : public WindowServerShellTestBase, + : public WindowServerServiceTestBase, public WindowTreeClientDelegate, public WindowManagerDelegate, public shell::InterfaceFactory<mojom::WindowTreeClient> { @@ -62,7 +62,7 @@ // testing::Test: void SetUp() override; - // WindowServerShellTestBase: + // WindowServerServiceTestBase: bool OnConnect(shell::Connection* connection) override; // WindowTreeClientDelegate:
diff --git a/services/ui/public/interfaces/channel_handle.mojom b/services/ui/public/interfaces/channel_handle.mojom index 5a4136e..a0ffc10 100644 --- a/services/ui/public/interfaces/channel_handle.mojom +++ b/services/ui/public/interfaces/channel_handle.mojom
@@ -9,5 +9,8 @@ string name; // On POSIX, it is one endpoint of a socket pair. On Windows, it is not used. - handle socket; + handle? socket; + + // Message pipe handle used for ChannelMojo. + handle<message_pipe>? mojo_handle; };
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn index 145efa77..60f5477 100644 --- a/services/ui/ws/BUILD.gn +++ b/services/ui/ws/BUILD.gn
@@ -132,14 +132,17 @@ ] if (use_ozone) { - sources -= [ - "platform_screen_impl.cc", - "platform_screen_impl.h", - ] - sources += [ - "platform_screen_impl_ozone.cc", - "platform_screen_impl_ozone.h", - ] + if (is_chromeos) { + sources -= [ + "platform_screen_impl.cc", + "platform_screen_impl.h", + ] + sources += [ + "platform_screen_impl_ozone.cc", + "platform_screen_impl_ozone.h", + ] + } + public_deps += [ "//ui/ozone:ozone" ] } } @@ -195,6 +198,7 @@ "event_dispatcher_unittest.cc", "event_matcher_unittest.cc", "focus_controller_unittest.cc", + "frame_generator_unittest.cc", "scheduled_animation_group_unittest.cc", "server_window_drawn_tracker_unittest.cc", "server_window_surface_manager_test_api.cc", @@ -222,7 +226,7 @@ "//base/test:test_support", "//cc:cc", "//mojo/public/cpp/bindings:bindings", - "//services/shell/public/cpp:shell_test_support", + "//services/shell/public/cpp:service_test_support", "//services/shell/public/cpp:sources", "//services/shell/public/cpp/test:run_all_shelltests", "//services/shell/public/interfaces",
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc index aea380b..d09b0d7 100644 --- a/services/ui/ws/frame_generator.cc +++ b/services/ui/ws/frame_generator.cc
@@ -4,6 +4,7 @@ #include "services/ui/ws/frame_generator.h" +#include "base/containers/adapters.h" #include "cc/output/compositor_frame.h" #include "cc/quads/render_pass.h" #include "cc/quads/shared_quad_state.h" @@ -118,11 +119,10 @@ const gfx::Rect absolute_bounds = window->bounds() + parent_to_root_origin_offset; - std::vector<ServerWindow*> children(window->GetChildren()); - // TODO(rjkroege, fsamuel): Make sure we're handling alpha correctly. + const ServerWindow::Windows& children = window->children(); const float combined_opacity = opacity * window->opacity(); - for (auto it = children.rbegin(); it != children.rend(); ++it) { - DrawWindowTree(pass, *it, absolute_bounds.OffsetFromOrigin(), + for (ServerWindow* child : base::Reversed(children)) { + DrawWindowTree(pass, child, absolute_bounds.OffsetFromOrigin(), combined_opacity); } @@ -148,7 +148,7 @@ bounds_at_origin.size() /* layer_bounds */, bounds_at_origin /* visible_layer_bounds */, bounds_at_origin /* clip_rect */, false /* is_clipped */, - window->opacity(), SkXfermode::kSrcOver_Mode, + combined_opacity, SkXfermode::kSrcOver_Mode, 0 /* sorting-context_id */); auto quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>(); quad->SetAll(sqs, bounds_at_origin /* rect */, @@ -169,7 +169,7 @@ bounds_at_origin.size() /* layer_bounds */, bounds_at_origin /* visible_layer_bounds */, bounds_at_origin /* clip_rect */, false /* is_clipped */, - window->opacity(), SkXfermode::kSrcOver_Mode, + combined_opacity, SkXfermode::kSrcOver_Mode, 0 /* sorting-context_id */); auto quad = pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
diff --git a/services/ui/ws/frame_generator.h b/services/ui/ws/frame_generator.h index c23e3b7d..1872f1a5 100644 --- a/services/ui/ws/frame_generator.h +++ b/services/ui/ws/frame_generator.h
@@ -27,6 +27,10 @@ namespace ws { +namespace test { +class FrameGeneratorTest; +} + class FrameGeneratorDelegate; class ServerWindow; @@ -48,6 +52,8 @@ bool is_frame_pending() { return frame_pending_; } private: + friend class ui::ws::test::FrameGeneratorTest; + void WantToDraw(); // This method initiates a top level redraw of the display.
diff --git a/services/ui/ws/frame_generator_unittest.cc b/services/ui/ws/frame_generator_unittest.cc new file mode 100644 index 0000000..0af81b4f --- /dev/null +++ b/services/ui/ws/frame_generator_unittest.cc
@@ -0,0 +1,131 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/ui/ws/frame_generator.h" + +#include <memory> + +#include "base/test/test_message_loop.h" +#include "cc/quads/render_pass.h" +#include "cc/quads/shared_quad_state.h" +#include "services/ui/gles2/gpu_state.h" +#include "services/ui/ws/platform_display_init_params.h" +#include "services/ui/ws/server_window.h" +#include "services/ui/ws/server_window_surface_manager.h" +#include "services/ui/ws/test_server_window_delegate.h" +#include "services/ui/ws/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ui { +namespace ws { +namespace test { +namespace { + +// Makes the window visible and creates the default surface for it. +void InitWindow(ServerWindow* window) { + window->SetVisible(true); + ServerWindowSurfaceManager* surface_manager = + window->GetOrCreateSurfaceManager(); + surface_manager->CreateSurface(mojom::SurfaceType::DEFAULT, + mojo::InterfaceRequest<mojom::Surface>(), + mojom::SurfaceClientPtr()); +} + +} // namespace + +class FrameGeneratorTest : public testing::Test { + public: + FrameGeneratorTest() {} + ~FrameGeneratorTest() override {} + + // Calls DrawWindowTree() on |frame_generator_| + void DrawWindowTree(cc::RenderPass* pass); + + ServerWindow* root_window() { + return frame_generator_delegate_->GetRootWindow(); + } + + TestServerWindowDelegate* test_window_delegate() { return &window_delegate_; } + + private: + // testing::Test: + void SetUp() override; + void TearDown() override; + + std::unique_ptr<FrameGenerator> frame_generator_; + std::unique_ptr<TestFrameGeneratorDelegate> frame_generator_delegate_; + TestServerWindowDelegate window_delegate_; + + // Needed so that Mojo classes can be initialized for ServerWindow use. + base::TestMessageLoop message_loop_; + + DISALLOW_COPY_AND_ASSIGN(FrameGeneratorTest); +}; + +void FrameGeneratorTest::DrawWindowTree(cc::RenderPass* pass) { + frame_generator_->DrawWindowTree( + pass, frame_generator_delegate_->GetRootWindow(), gfx::Vector2d(), 1.0f); +} + +void FrameGeneratorTest::SetUp() { + testing::Test::SetUp(); + frame_generator_delegate_.reset(new TestFrameGeneratorDelegate( + base::WrapUnique(new ServerWindow(&window_delegate_, WindowId())))); + PlatformDisplayInitParams init_params; + frame_generator_.reset(new FrameGenerator(frame_generator_delegate_.get(), + init_params.gpu_state, + init_params.surfaces_state)); + InitWindow(root_window()); +} + +void FrameGeneratorTest::TearDown() { + frame_generator_.reset(); + frame_generator_delegate_.reset(); +} + +// Tests correctness of the SharedQuadStateList generated by +// FrameGenerator::DrawWindowTree(). +TEST_F(FrameGeneratorTest, DrawWindowTree) { + ServerWindow child_window(test_window_delegate(), WindowId()); + root_window()->Add(&child_window); + InitWindow(&child_window); + const float root_opacity = .5f; + const float child_opacity = .4f; + root_window()->SetOpacity(root_opacity); + child_window.SetOpacity(child_opacity); + + std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); + DrawWindowTree(render_pass.get()); + cc::SharedQuadStateList* quad_state_list = + &render_pass->shared_quad_state_list; + + // Both child and root have a DEFAULT Surface and no underlay Surfaces, so + // there should be two SharedQuadStates in the list. + EXPECT_EQ(2u, quad_state_list->size()); + cc::SharedQuadState* root_sqs = quad_state_list->back(); + cc::SharedQuadState* child_sqs = quad_state_list->front(); + EXPECT_EQ(root_opacity, root_sqs->opacity); + // Child's SharedQuadState contains the effective opacity of the child layer, + // which should be a product of the child and the parent opacity. + EXPECT_EQ(child_opacity * root_opacity, child_sqs->opacity); + + // Create the UNDERLAY Surface for the child window, and confirm that this + // creates an extra SharedQuadState in the CompositorFrame. + child_window.GetOrCreateSurfaceManager()->CreateSurface( + mojom::SurfaceType::UNDERLAY, mojo::InterfaceRequest<mojom::Surface>(), + mojom::SurfaceClientPtr()); + + render_pass = cc::RenderPass::Create(); + DrawWindowTree(render_pass.get()); + quad_state_list = &render_pass->shared_quad_state_list; + EXPECT_EQ(3u, quad_state_list->size()); + auto it = quad_state_list->begin(); + EXPECT_EQ(child_opacity * root_opacity, (*it)->opacity); + EXPECT_EQ(child_opacity * root_opacity, (*++it)->opacity); + EXPECT_EQ(root_opacity, (*++it)->opacity); +} + +} // namespace test +} // namespace ws +} // namespace ui
diff --git a/services/ui/ws/platform_screen.h b/services/ui/ws/platform_screen.h index 3ed27930..075dc25 100644 --- a/services/ui/ws/platform_screen.h +++ b/services/ui/ws/platform_screen.h
@@ -20,6 +20,9 @@ // attached physical displays. class PlatformScreen { public: + using ConfiguredDisplayCallback = + base::Callback<void(int64_t, const gfx::Rect&)>; + virtual ~PlatformScreen() {} // Creates a PlatformScreen instance. @@ -28,9 +31,6 @@ // Initializes platform specific screen resources. virtual void Init() = 0; - using ConfiguredDisplayCallback = - base::Callback<void(int64_t, const gfx::Rect&)>; - // ConfigurePhysicalDisplay() configures a single physical display and returns // its id and bounds for it via |callback|. virtual void ConfigurePhysicalDisplay(
diff --git a/services/ui/ws/platform_screen_impl_ozone.cc b/services/ui/ws/platform_screen_impl_ozone.cc index 33331d5..498b360 100644 --- a/services/ui/ws/platform_screen_impl_ozone.cc +++ b/services/ui/ws/platform_screen_impl_ozone.cc
@@ -4,13 +4,14 @@ #include "services/ui/ws/platform_screen_impl_ozone.h" -#include "base/bind.h" -#include "base/location.h" #include "base/memory/ptr_util.h" #include "base/sys_info.h" #include "base/threading/thread_task_runner_handle.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/display/types/display_constants.h" #include "ui/display/types/display_snapshot.h" #include "ui/display/types/native_display_delegate.h" +#include "ui/gfx/geometry/rect.h" #include "ui/ozone/public/ozone_platform.h" namespace ui { @@ -18,7 +19,7 @@ namespace ws { namespace { -// TODO(rjkroege): Remove this code once ozone oxygen has the same +// TODO(rjkroege): Remove this code once ozone headless has the same // display creation semantics as ozone drm. // Some ozone platforms do not configure physical displays and so do not // callback into this class via the implementation of NativeDisplayObserver. @@ -30,96 +31,65 @@ callback.Run(1, gfx::Rect(1024, 768)); } -void GetDisplaysFinished(const std::vector<ui::DisplaySnapshot*>& displays) { - // We don't really care about list of displays, we just want the snapshots - // held by DrmDisplayManager to be updated. This only only happens when we - // call NativeDisplayDelegate::GetDisplays(). Although, this would be a good - // place to have PlatformScreen cache the snapshots if need be. -} +// Needed for DisplayConfigurator::ForceInitialConfigure. +const SkColor kChromeOsBootColor = SkColorSetRGB(0xfe, 0xfe, 0xfe); } // namespace // static std::unique_ptr<PlatformScreen> PlatformScreen::Create() { - return base::WrapUnique(new PlatformScreenImplOzone); + return base::MakeUnique<PlatformScreenImplOzone>(); } -PlatformScreenImplOzone::PlatformScreenImplOzone() : weak_ptr_factory_(this) {} +PlatformScreenImplOzone::PlatformScreenImplOzone() {} -PlatformScreenImplOzone::~PlatformScreenImplOzone() {} +PlatformScreenImplOzone::~PlatformScreenImplOzone() { + display_configurator_.RemoveObserver(this); +} void PlatformScreenImplOzone::Init() { - native_display_delegate_ = - ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate(); - native_display_delegate_->AddObserver(this); - native_display_delegate_->Initialize(); + display_configurator_.AddObserver(this); + display_configurator_.Init( + ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate(), false); } void PlatformScreenImplOzone::ConfigurePhysicalDisplay( const PlatformScreen::ConfiguredDisplayCallback& callback) { -#if defined(OS_CHROMEOS) if (base::SysInfo::IsRunningOnChromeOS()) { - // Kick off the configuration of the physical displays comprising the - // |PlatformScreenImplOzone| - - DCHECK(native_display_delegate_) << "DefaultDisplayManager::" - "OnConfigurationChanged requires a " - "native_display_delegate_ to work."; - - native_display_delegate_->GetDisplays( - base::Bind(&PlatformScreenImplOzone::OnDisplaysAquired, - weak_ptr_factory_.GetWeakPtr(), callback)); - - return; + callback_ = callback; + display_configurator_.ForceInitialConfigure(kChromeOsBootColor); + } else { + // PostTask()ed to maximize control flow similarity with the ChromeOS case. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FixedSizeScreenConfiguration, callback)); } -#endif // defined(OS_CHROMEOS) - // PostTask()ed to maximize control flow similarity with the ChromeOS case. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&FixedSizeScreenConfiguration, callback)); } -void PlatformScreenImplOzone::OnConfigurationChanged() {} +void PlatformScreenImplOzone::OnDisplayModeChanged( + const ui::DisplayConfigurator::DisplayStateList& displays) { + // TODO(kylechar): Remove checks when multiple display support is added. + CHECK(displays.size() == 1) << "Mus only supports one 1 display"; + CHECK(!callback_.is_null()); -// The display subsystem calls |OnDisplaysAquired| to deliver |displays| -// describing the attached displays. -void PlatformScreenImplOzone::OnDisplaysAquired( - const ConfiguredDisplayCallback& callback, - const std::vector<ui::DisplaySnapshot*>& displays) { - DCHECK(native_display_delegate_) << "DefaultDisplayManager::" - "OnConfigurationChanged requires a " - "native_display_delegate_ to work."; - CHECK(displays.size() == 1) << "Mus only supports one 1 display\n"; gfx::Point origin; for (auto display : displays) { - if (!display->native_mode()) { - LOG(ERROR) << "Display " << display->display_id() - << " doesn't have a native mode"; - continue; - } - // Setup each native display. This places a task on the DRM thread's - // runqueue that configures the window size correctly before the call to - // Configure. - native_display_delegate_->Configure( - *display, display->native_mode(), origin, - base::Bind(&PlatformScreenImplOzone::OnDisplayConfigured, - weak_ptr_factory_.GetWeakPtr(), callback, - display->display_id(), - gfx::Rect(origin, display->native_mode()->size()))); - origin.Offset(display->native_mode()->size().width(), 0); + const ui::DisplayMode* current_mode = display->current_mode(); + gfx::Rect bounds(origin, current_mode->size()); + + callback_.Run(display->display_id(), bounds); + + // Move the origin so that next display is to the right of current display. + origin.Offset(current_mode->size().width(), 0); } + + callback_.Reset(); } -void PlatformScreenImplOzone::OnDisplayConfigured( - const ConfiguredDisplayCallback& callback, - int64_t id, - const gfx::Rect& bounds, - bool success) { - if (success) { - native_display_delegate_->GetDisplays(base::Bind(&GetDisplaysFinished)); - callback.Run(id, bounds); - } else { - LOG(FATAL) << "Failed to configure display at " << bounds.ToString(); - } +void PlatformScreenImplOzone::OnDisplayModeChangeFailed( + const ui::DisplayConfigurator::DisplayStateList& displays, + MultipleDisplayState failed_new_state) { + LOG(ERROR) << "OnDisplayModeChangeFailed from DisplayConfigurator"; + callback_.Reset(); } } // namespace ws
diff --git a/services/ui/ws/platform_screen_impl_ozone.h b/services/ui/ws/platform_screen_impl_ozone.h index f01e16ba..e026bf6 100644 --- a/services/ui/ws/platform_screen_impl_ozone.h +++ b/services/ui/ws/platform_screen_impl_ozone.h
@@ -10,19 +10,9 @@ #include <vector> #include "base/callback.h" -#include "base/memory/weak_ptr.h" +#include "base/macros.h" #include "services/ui/ws/platform_screen.h" -#include "ui/display/types/native_display_observer.h" -#include "ui/gfx/geometry/rect.h" - -namespace gfx { -class Rect; -} - -namespace ui { -class NativeDisplayDelegate; -class DisplaySnapshot; -} +#include "ui/display/chromeos/display_configurator.h" namespace ui { namespace ws { @@ -30,38 +20,29 @@ // PlatformScreenImplOzone provides the necessary functionality to configure all // attached physical displays on the ozone platform. class PlatformScreenImplOzone : public PlatformScreen, - public ui::NativeDisplayObserver { + public ui::DisplayConfigurator::Observer { public: PlatformScreenImplOzone(); ~PlatformScreenImplOzone() override; private: - // PlatformScreen + // PlatformScreen: void Init() override; // Must not be called until after the ozone platform is // initialized. void ConfigurePhysicalDisplay( const ConfiguredDisplayCallback& callback) override; - // TODO(rjkroege): NativeDisplayObserver is misnamed as it tracks changes in - // the physical "Screen". Consider renaming it to NativeScreenObserver. - // ui::NativeDisplayObserver: - void OnConfigurationChanged() override; + // ui::DisplayConfigurator::Observer: + void OnDisplayModeChanged( + const ui::DisplayConfigurator::DisplayStateList& displays) override; + void OnDisplayModeChangeFailed( + const ui::DisplayConfigurator::DisplayStateList& displays, + MultipleDisplayState failed_new_state) override; - // Display management callback. - void OnDisplaysAquired(const ConfiguredDisplayCallback& callback, - const std::vector<ui::DisplaySnapshot*>& displays); + ui::DisplayConfigurator display_configurator_; - // The display subsystem calls |OnDisplayConfigured| for each display that has - // been successfully configured. This in turn calls |callback_| with the - // identity and bounds of each physical display. - void OnDisplayConfigured(const ConfiguredDisplayCallback& callback, - int64_t id, - const gfx::Rect& bounds, - bool success); - - std::unique_ptr<ui::NativeDisplayDelegate> native_display_delegate_; - - base::WeakPtrFactory<PlatformScreenImplOzone> weak_ptr_factory_; + // Callback to called when new displays are configured. + ConfiguredDisplayCallback callback_; DISALLOW_COPY_AND_ASSIGN(PlatformScreenImplOzone); };
diff --git a/services/ui/ws/server_window.cc b/services/ui/ws/server_window.cc index 4b2ab13..834dcd8 100644 --- a/services/ui/ws/server_window.cc +++ b/services/ui/ws/server_window.cc
@@ -190,19 +190,6 @@ return delegate_->GetRootWindow(this); } -std::vector<const ServerWindow*> ServerWindow::GetChildren() const { - std::vector<const ServerWindow*> children; - children.reserve(children_.size()); - for (size_t i = 0; i < children_.size(); ++i) - children.push_back(children_[i]); - return children; -} - -std::vector<ServerWindow*> ServerWindow::GetChildren() { - // TODO(sky): rename to children() and fix return type. - return children_; -} - ServerWindow* ServerWindow::GetChildWindow(const WindowId& window_id) { if (id_ == window_id) return this;
diff --git a/services/ui/ws/server_window.h b/services/ui/ws/server_window.h index c59efd8a..6d66668 100644 --- a/services/ui/ws/server_window.h +++ b/services/ui/ws/server_window.h
@@ -100,8 +100,6 @@ const_cast<const ServerWindow*>(this)->GetRoot()); } - std::vector<const ServerWindow*> GetChildren() const; - std::vector<ServerWindow*> GetChildren(); const Windows& children() const { return children_; } // Returns the ServerWindow object with the provided |id| if it lies in a
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc index 36cc25f..e8d648f 100644 --- a/services/ui/ws/test_utils.cc +++ b/services/ui/ws/test_utils.cc
@@ -108,6 +108,22 @@ return new TestPlatformDisplay(cursor_id_storage_); } +// TestFrameGeneratorDelegate ------------------------------------------------- + +TestFrameGeneratorDelegate::TestFrameGeneratorDelegate( + std::unique_ptr<ServerWindow> root) + : root_(std::move(root)) {} + +TestFrameGeneratorDelegate::~TestFrameGeneratorDelegate() {} + +ServerWindow* TestFrameGeneratorDelegate::GetRootWindow() { + return root_.get(); +} + +const ViewportMetrics& TestFrameGeneratorDelegate::GetViewportMetrics() { + return metrics_; +} + // WindowTreeTestApi --------------------------------------------------------- WindowTreeTestApi::WindowTreeTestApi(WindowTree* tree) : tree_(tree) {}
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h index 1162721..18ec321 100644 --- a/services/ui/ws/test_utils.h +++ b/services/ui/ws/test_utils.h
@@ -244,6 +244,26 @@ // ----------------------------------------------------------------------------- +// A stub implementation of FrameGeneratorDelegate. +class TestFrameGeneratorDelegate : public FrameGeneratorDelegate { + public: + explicit TestFrameGeneratorDelegate(std::unique_ptr<ServerWindow> root); + ~TestFrameGeneratorDelegate() override; + + // FrameGeneratorDelegate: + ServerWindow* GetRootWindow() override; + void OnCompositorFrameDrawn() override {} + const ViewportMetrics& GetViewportMetrics() override; + + private: + std::unique_ptr<ServerWindow> root_; + ViewportMetrics metrics_; + + DISALLOW_COPY_AND_ASSIGN(TestFrameGeneratorDelegate); +}; + +// ----------------------------------------------------------------------------- + class TestWindowManager : public mojom::WindowManager { public: TestWindowManager()
diff --git a/services/ui/ws/window_finder.cc b/services/ui/ws/window_finder.cc index bbd8737..09be99308 100644 --- a/services/ui/ws/window_finder.cc +++ b/services/ui/ws/window_finder.cc
@@ -4,6 +4,7 @@ #include "services/ui/ws/window_finder.h" +#include "base/containers/adapters.h" #include "services/ui/surfaces/surfaces_state.h" #include "services/ui/ws/server_window.h" #include "services/ui/ws/server_window_delegate.h" @@ -25,9 +26,8 @@ ServerWindow* FindDeepestVisibleWindowForEvents(ServerWindow* window, gfx::Point* location) { - const ServerWindow::Windows children(window->GetChildren()); - for (auto iter = children.rbegin(); iter != children.rend(); ++iter) { - ServerWindow* child = *iter; + const ServerWindow::Windows& children = window->children(); + for (ServerWindow* child : base::Reversed(children)) { if (!child->visible()) continue;
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc index 4b5e7498..7b67759 100644 --- a/services/ui/ws/window_tree.cc +++ b/services/ui/ws/window_tree.cc
@@ -756,7 +756,7 @@ if (!access_policy_->CanReorderWindow(window, relative_window, direction)) return false; - std::vector<const ServerWindow*> children = window->parent()->GetChildren(); + const ServerWindow::Windows& children = window->parent()->children(); const size_t child_i = std::find(children.begin(), children.end(), window) - children.begin(); const size_t target_i = @@ -797,9 +797,9 @@ window_id_to_client_id_map_[window->id()] = client_window_id; if (!access_policy_->CanDescendIntoWindowForWindowTree(window)) return; - std::vector<const ServerWindow*> children(window->GetChildren()); - for (size_t i = 0; i < children.size(); ++i) - GetUnknownWindowsFrom(children[i], windows); + const ServerWindow::Windows& children = window->children(); + for (ServerWindow* child : children) + GetUnknownWindowsFrom(child, windows); } bool WindowTree::RemoveFromMaps(const ServerWindow* window) { @@ -822,9 +822,9 @@ RemoveFromMaps(window); - std::vector<const ServerWindow*> children = window->GetChildren(); - for (size_t i = 0; i < children.size(); ++i) - RemoveFromKnown(children[i], local_windows); + const ServerWindow::Windows& children = window->children(); + for (ServerWindow* child : children) + RemoveFromKnown(child, local_windows); } void WindowTree::RemoveRoot(const ServerWindow* window, @@ -893,9 +893,9 @@ if (!access_policy_->CanDescendIntoWindowForWindowTree(window)) return; - std::vector<const ServerWindow*> children(window->GetChildren()); - for (size_t i = 0; i < children.size(); ++i) - GetWindowTreeImpl(children[i], windows); + const ServerWindow::Windows& children = window->children(); + for (ServerWindow* child : children) + GetWindowTreeImpl(child, windows); } void WindowTree::NotifyDrawnStateChanged(const ServerWindow* window, @@ -955,9 +955,8 @@ void WindowTree::RemoveChildrenAsPartOfEmbed(ServerWindow* window) { CHECK(window); - std::vector<ServerWindow*> children = window->GetChildren(); - for (size_t i = 0; i < children.size(); ++i) - window->Remove(children[i]); + while (!window->children().empty()) + window->Remove(window->children().front()); } void WindowTree::DispatchInputEventImpl(ServerWindow* target,
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc index 33dfc4de..31c0d683 100644 --- a/services/ui/ws/window_tree_client_unittest.cc +++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -11,7 +11,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "services/shell/public/cpp/shell_test.h" +#include "services/shell/public/cpp/service_test.h" #include "services/ui/public/cpp/tests/window_server_shelltest_base.h" #include "services/ui/public/interfaces/window_tree.mojom.h" #include "services/ui/public/interfaces/window_tree_host.mojom.h" @@ -490,7 +490,7 @@ } // namespace -class WindowTreeClientTest : public WindowServerShellTestBase { +class WindowTreeClientTest : public WindowServerServiceTestBase { public: WindowTreeClientTest() : client_id_1_(0), client_id_2_(0), root_window_id_(0) {} @@ -582,7 +582,7 @@ return client; } - // WindowServerShellTestBase: + // WindowServerServiceTestBase: bool OnConnect(shell::Connection* connection) override { connection->AddInterface(client_factory_.get()); return true; @@ -591,7 +591,7 @@ void SetUp() override { client_factory_.reset(new WindowTreeClientFactory()); - WindowServerShellTestBase::SetUp(); + WindowServerServiceTestBase::SetUp(); mojom::WindowTreeHostFactoryPtr factory; connector()->ConnectToInterface("mojo:ui", &factory); @@ -621,12 +621,12 @@ void TearDown() override { // Destroy these before the message loop is destroyed (happens in - // WindowServerShellTestBase::TearDown). + // WindowServerServiceTestBase::TearDown). wt_client1_.reset(); wt_client2_.reset(); wt_client3_.reset(); client_factory_.reset(); - WindowServerShellTestBase::TearDown(); + WindowServerServiceTestBase::TearDown(); } std::unique_ptr<TestWindowTreeClient> wt_client1_;
diff --git a/styleguide/c++/c++.md b/styleguide/c++/c++.md index 1b8e307b..e7af38be 100644 --- a/styleguide/c++/c++.md +++ b/styleguide/c++/c++.md
@@ -11,9 +11,9 @@ to automatically format C++ code. By policy, Clang's formatting of code should always be accepted in code reviews. -You can propose changes to the style guide by sending an email to -`cxx@chromium.org`. Ideally, the list will arrive at some consensus and the -wiki page will be updated to mention that consensus. If there's no consensus, +You can propose changes to this style guide by sending an email to +`cxx@chromium.org`. Ideally, the list will arrive at some consensus and you can +request review for a change to this file. If there's no consensus, `src/styleguide/c++/OWNERS` get to decide. Blink code in `third_party/WebKit` uses [Blink
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html index 1ffc465..123ecd8 100644 --- a/styleguide/c++/c++11.html +++ b/styleguide/c++/c++11.html
@@ -29,12 +29,15 @@ Guide applies to Chromium and its subprojects. Subprojects can choose to be more restrictive if they need to compile on more toolchains than Chromium.</p> +<p>This page comprises part of the more general +<a href="https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md">Chromium C++ style guide</a>.</p> + <p>You can propose to make a feature available or to ban a feature by sending an email to <a href="https://groups.google.com/a/chromium.org/forum/#!forum/cxx">cxx@chromium.org</a>. Ideally include a short blurb on what the feature is, and why you think it should or should not be allowed. Ideally, the list will arrive at some -consensus and the wiki page will be updated to mention that consensus. If +consensus and you can request review for a change to this file. If there's no consensus, <code>src/styleguide/c++/OWNERS</code> get to decide -- for divisive features, we expect the decision to be to not use the feature yet and possibly discuss it again a few months later, when we have more experience @@ -184,7 +187,7 @@ <td><code>[<i>captures</i>](<i>params</i>) -> <i>ret</i> { <i>body</i> }</code></td> <td>Anonymous functions</td> <td><a href="http://en.cppreference.com/w/cpp/language/lambda">Lambda functions</a></td> -<td>Do not bind or store lambdas outside the lifetime of the stack frame they are defined in; use <code>base::Bind</code> and <code>base::Callback</code> instead, because they offer protection against a large class of object lifetime mistakes. Don't use default captures (<code>[=]</code>, <code>[&]</code> – <a href="https://google.github.io/styleguide/cppguide.html#Lambda_expressions">Google Style Guide</a>). Lambdas are typically useful as a parameter to methods or functions that will use them immediately, such as those in <code><algorithm></code>. <a href="https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/D9UnnxBnciQ">Discussion thread</a></td> +<td>Do not bind or store capturing lambdas outside the lifetime of the stack frame they are defined in; use captureless lambda with <code>base::Bind</code> and <code>base::Callback</code> instead, because they offer protection against a large class of object lifetime mistakes. Don't use default captures (<code>[=]</code>, <code>[&]</code> – <a href="https://google.github.io/styleguide/cppguide.html#Lambda_expressions">Google Style Guide</a>). Lambdas are typically useful as a parameter to methods or functions that will use them immediately, such as those in <code><algorithm></code>. <a href="https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/D9UnnxBnciQ">Discussion thread</a></td> </tr> <tr>
diff --git a/styleguide/styleguide.md b/styleguide/styleguide.md index cbe31122..7a9429a 100644 --- a/styleguide/styleguide.md +++ b/styleguide/styleguide.md
@@ -5,7 +5,7 @@ * [Chromium C++ style guide](c++/c++.md) * [Google Objective-C style guide](https://google.github.io/styleguide/objcguide.xml) * [Java style guide for Android](https://sites.google.com/a/chromium.org/dev/developers/coding-style/java) - * [GN style guide](https://chromium.googlesource.com/chromium/src/+/master/tool) for build files + * [GN style guide](../tools/gn/docs/style_guide.md) for build files Chromium also uses these languages to a lesser degree:
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 8e477cda..6cd6fd4 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -408,6 +408,16 @@ "test": "base_unittests" }, { + "args": [ + "--override-use-gl-with-osmesa-for-tests", + "--run-in-mash", + "--test-launcher-filter-file=src/testing/buildbot/filters/mash.browser_tests.filter", + "--use-test-config" + ], + "name": "mash_browser_tests", + "test": "browser_tests" + }, + { "swarming": { "can_use_on_swarming_builders": true, "shards": 5
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter new file mode 100644 index 0000000..d0e92b9 --- /dev/null +++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -0,0 +1 @@ +BrowserTest.Title
diff --git a/testing/buildbot/filters/site-per-process.browser_tests.filter b/testing/buildbot/filters/site-per-process.browser_tests.filter index c19c6e99..cb143f5e 100644 --- a/testing/buildbot/filters/site-per-process.browser_tests.filter +++ b/testing/buildbot/filters/site-per-process.browser_tests.filter
@@ -28,6 +28,7 @@ -ExtensionApiTest.TabMove -ExtensionApiTest.TabsOnUpdated -ExtensionURLRewriteBrowserTest.NewTabPageURL +-InputImeApiTest.SendKeyEventsOnNormalPage -IsolatedAppTest.CookieIsolation -IsolatedAppTest.CrossProcessClientRedirect -IsolatedAppTest.IsolatedAppProcessModel
diff --git a/testing/libfuzzer/dictionary_generator.py b/testing/libfuzzer/dictionary_generator.py new file mode 100755 index 0000000..b720e8e --- /dev/null +++ b/testing/libfuzzer/dictionary_generator.py
@@ -0,0 +1,236 @@ +#!/usr/bin/python2 +# +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Generate a dictionary for libFuzzer or AFL-based fuzzer. + +Invoked manually using a fuzzer binary and target format/protocol specification. +Works better for text formats or protocols. For binary ones may be useless. +""" + +import argparse +import HTMLParser +import io +import logging +import os +import re +import shutil +import string +import subprocess +import sys +import tempfile + + +ENCODING_TYPES = ['ascii', 'utf_16_be', 'utf_16_le', 'utf_32_be', 'utf_32_le'] +MIN_STRING_LENGTH = 4 + + +def DecodeHTML(html_data): + """HTML-decoding of the data.""" + html_parser = HTMLParser.HTMLParser() + data = html_parser.unescape(html_data.decode('ascii', 'ignore')) + return data.encode('ascii', 'ignore') + + +def EscapeDictionaryElement(element): + """Escape all unprintable and control characters in an element.""" + element_escaped = element.encode('string_escape') + # Remove escaping for single quote because it breaks libFuzzer. + element_escaped = element_escaped.replace('\\\'', '\'') + # Add escaping for double quote. + element_escaped = element_escaped.replace('"', '\\"') + return element_escaped + + +def ExtractWordsFromBinary(filepath, min_length=MIN_STRING_LENGTH): + """Extract words (splitted strings) from a binary executable file.""" + rodata = PreprocessAndReadRodata(filepath) + words = [] + + strings_re = re.compile(r'[^\x00-\x1F\x7F-\xFF]{%d,}' % min_length) + # Use different encodings for strings extraction. + for encoding in ENCODING_TYPES: + data = rodata.decode(encoding, 'ignore').encode('ascii', 'ignore') + raw_strings = strings_re.findall(data) + for splitted_line in map(lambda line: line.split(), raw_strings): + words += splitted_line + + return set(words) + + +def ExtractWordsFromLines(lines): + """Extract all words from a list of strings.""" + words = set() + for line in lines: + for word in line.split(): + words.add(word) + + return words + + +def ExtractWordsFromSpec(filepath, is_html): + """Extract words from a specification.""" + data = ReadSpecification(filepath, is_html) + words = data.split() + return set(words) + + +def FindIndentedText(text): + """Find space-indented text blocks, e.g. code or data samples in RFCs.""" + lines = text.split('\n') + indented_blocks = [] + current_block = '' + previous_number_of_spaces = 0 + + # Go through every line and concatenate space-indented blocks into lines. + for i in xrange(0, len(lines), 1): + if not lines[i]: + # Ignore empty lines. + continue + + # Space-indented text blocks have more leading spaces than regular text. + n = FindNumberOfLeadingSpaces(lines[i]) + + if n > previous_number_of_spaces: + # Beginning of a space-indented text block, start concatenation. + current_block = lines[i][n : ] + elif n == previous_number_of_spaces and current_block: + # Or continuation of a space-indented text block, concatenate lines. + current_block += '\n' + lines[i][n : ] + + if n < previous_number_of_spaces and current_block: + # Current line is not indented, save previously concatenated lines. + indented_blocks.append(current_block) + current_block = '' + + previous_number_of_spaces = n + + return indented_blocks + + +def FindNumberOfLeadingSpaces(line): + """Calculate number of leading whitespace characters in the string.""" + n = 0 + while n < len(line) and line[n].isspace(): + n += 1 + + return n + + +def GenerateDictionary(path_to_binary, path_to_spec, strategy, is_html=False): + """Generate a dictionary for given pair of fuzzer binary and specification.""" + for filepath in [path_to_binary, path_to_spec]: + if not os.path.exists(filepath): + logging.error('%s doesn\'t exist. Exit.', filepath) + sys.exit(1) + + words_from_binary = ExtractWordsFromBinary(path_to_binary) + words_from_spec = ExtractWordsFromSpec(path_to_spec, is_html) + + dictionary_words = set() + + if 'i' in strategy: + # Strategy i: only words which are common for binary and for specification. + dictionary_words = words_from_binary.intersection(words_from_spec) + + if 'q' in strategy: + # Strategy q: add words from all quoted strings from specification. + # TODO(mmoroz): experimental and very noisy. Not recommended to use. + spec_data = ReadSpecification(path_to_spec, is_html) + quoted_strings = FindIndentedText(spec_data) + quoted_words = ExtractWordsFromLines(quoted_strings) + dictionary_words = dictionary_words.union(quoted_words) + + if 'u' in strategy: + # Strategy u: add all uppercase words from specification. + uppercase_words = set(w for w in words_from_spec if w.isupper()) + dictionary_words = dictionary_words.union(uppercase_words) + + return dictionary_words + + +def PreprocessAndReadRodata(filepath): + """Create a stripped copy of the binary and extract .rodata section.""" + stripped_file = tempfile.NamedTemporaryFile(prefix='.stripped_') + stripped_filepath = stripped_file.name + shutil.copyfile(filepath, stripped_filepath) + + # Strip all symbols to reduce amount of redundant strings. + strip_cmd = ['strip', '--strip-all', stripped_filepath] + result = subprocess.call(strip_cmd) + if result: + logging.warning('Failed to strip the binary. Using the original version.') + stripped_filepath = filepath + + # Extract .rodata section to reduce amount of redundant strings. + rodata_file = tempfile.NamedTemporaryFile(prefix='.rodata_') + rodata_filepath = rodata_file.name + objcopy_cmd = ['objcopy', '-j', '.rodata', stripped_filepath, rodata_filepath] + + # Hide output from stderr since objcopy prints a warning. + with open(os.devnull, 'w') as devnull: + result = subprocess.call(objcopy_cmd, stderr=devnull) + + if result: + logging.warning('Failed to extract .rodata section. Using the whole file.') + rodata_filepath = stripped_filepath + + with open(rodata_filepath) as file_handle: + data = file_handle.read() + + stripped_file.close() + rodata_file.close() + + return data + + +def ReadSpecification(filepath, is_html): + """Read a specification file and return its contents.""" + with open(filepath, 'r') as file_handle: + data = file_handle.read() + + if is_html: + data = DecodeHTML(data) + + return data + + +def WriteDictionary(dictionary_path, dictionary): + """Write given dictionary to a file.""" + with open(dictionary_path, 'wb') as file_handle: + file_handle.write('# This is an automatically generated dictionary.\n') + for word in dictionary: + if not word: + continue + line = '"%s"\n' % EscapeDictionaryElement(word) + file_handle.write(line) + + +def main(): + parser = argparse.ArgumentParser(description="Generate fuzzer dictionary.") + parser.add_argument('--fuzzer', required=True, + help='Path to a fuzzer binary executable. It is ' + 'recommended to use a binary built with ' + '"use_libfuzzer=false is_asan=false" to get a better ' + 'dictionary with fewer number of redundant elements.') + parser.add_argument('--spec', required=True, + help='Path to a target specification (in textual form).') + parser.add_argument('--html', default=0, + help='Decode HTML [01] (0 is default value): ' + '1 - if specification has HTML entities to be decoded.') + parser.add_argument('--out', required=True, + help='Path to a file to write a dictionary into.') + parser.add_argument('--strategy', default='iu', + help='Generation strategy [iqu] ("iu" is default value): ' + 'i - intersection, q - quoted, u - uppercase.') + args = parser.parse_args() + + dictionary = GenerateDictionary(args.fuzzer, args.spec, args.strategy, + is_html=bool(args.html)) + WriteDictionary(args.out, dictionary) + + +if __name__ == '__main__': + main()
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 92d89fa..e39b6065 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -132,6 +132,7 @@ "//base:i18n", "//url:url", ] + dict = "dicts/generated/url_parse_fuzzer.dict" } fuzzer_test("usrsctp_fuzzer") { @@ -189,7 +190,7 @@ deps = [ "//third_party/sqlite", ] - dict = "dicts/sql.dict" + dict = "dicts/generated/sqlite3_prepare_v2_fuzzer.dict" } fuzzer_test("libxml_xml_read_memory_fuzzer") { @@ -199,7 +200,7 @@ deps = [ "//third_party/libxml:libxml", ] - dict = "dicts/xml.dict" + dict = "dicts/generated/libxml_xml_read_memory_fuzzer.dict" } fuzzer_test("libpng_read_fuzzer") { @@ -218,7 +219,7 @@ deps = [ "//v8:parser_fuzzer", ] - dict = "dicts/js.dict" + dict = "dicts/generated/v8_script_parser_fuzzer.dict" seed_corpus = "//v8/test/mjsunit/regress/" }
diff --git a/testing/libfuzzer/fuzzers/dicts/generated/libxml_xml_read_memory_fuzzer.dict b/testing/libfuzzer/fuzzers/dicts/generated/libxml_xml_read_memory_fuzzer.dict new file mode 100644 index 0000000..6257038 --- /dev/null +++ b/testing/libfuzzer/fuzzers/dicts/generated/libxml_xml_read_memory_fuzzer.dict
@@ -0,0 +1,663 @@ +# +# AFL dictionary for XML +# ---------------------- +# +# Several basic syntax elements and attributes, modeled on libxml2. +# +# Created by Michal Zalewski <lcamtuf@google.com> +# + +attr_encoding=" encoding=\"1\"" +attr_generic=" a=\"1\"" +attr_href=" href=\"1\"" +attr_standalone=" standalone=\"no\"" +attr_version=" version=\"1\"" +attr_xml_base=" xml:base=\"1\"" +attr_xml_id=" xml:id=\"1\"" +attr_xml_lang=" xml:lang=\"1\"" +attr_xml_space=" xml:space=\"1\"" +attr_xmlns=" xmlns=\"1\"" + +entity_builtin="<" +entity_decimal="" +entity_external="&a;" +entity_hex="" + +string_any="ANY" +string_brackets="[]" +string_cdata="CDATA" +string_col_fallback=":fallback" +string_col_generic=":a" +string_col_include=":include" +string_dashes="--" +string_empty="EMPTY" +string_empty_dblquotes="\"\"" +string_empty_quotes="''" +string_entities="ENTITIES" +string_entity="ENTITY" +string_fixed="#FIXED" +string_id="ID" +string_idref="IDREF" +string_idrefs="IDREFS" +string_implied="#IMPLIED" +string_nmtoken="NMTOKEN" +string_nmtokens="NMTOKENS" +string_notation="NOTATION" +string_parentheses="()" +string_pcdata="#PCDATA" +string_percent="%a" +string_public="PUBLIC" +string_required="#REQUIRED" +string_schema=":schema" +string_system="SYSTEM" +string_ucs4="UCS-4" +string_utf16="UTF-16" +string_utf8="UTF-8" +string_xmlns="xmlns:" + +tag_attlist="<!ATTLIST" +tag_cdata="<![CDATA[" +tag_close="</a>" +tag_doctype="<!DOCTYPE" +tag_element="<!ELEMENT" +tag_entity="<!ENTITY" +tag_ignore="<![IGNORE[" +tag_include="<![INCLUDE[" +tag_notation="<!NOTATION" +tag_open="<a>" +tag_open_close="<a />" +tag_open_exclamation="<!" +tag_open_q="<?" +tag_sq2_close="]]>" +tag_xml_q="<?xml?>" +"http://docboo" +"http://www.w" +"UTF-16LE" +"xmlns" +"he30" +"he2" +"IET" +"FDF-10" +"aDUCS-4OPveb:" +"a>" +"UT" +"xMl" +"/usr/share/sg" +"ha07" +"http://www.oa" +"cle" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using libxml_xml_read_memory_fuzzer binary and XML 1.0 W3C Recommendation. +"WG" +"all" +"code" +"TC2." +"text" +"forbidden" +"supported" +"(UAX" +"by" +"syntax" +"notations" +"area" +"SGML," +"/" +"Content" +"conditional" +"follow" +"Document" +"find" +"MUST" +"with," +"removed" +"based" +"(" +"V.," +"outside" +"should" +"to" +"only" +"'('" +"W3C." +"8" +"quotation" +"local" +"(E)." +"do" +"QUESTION" +"FULL" +"WIDTH" +"string" +"notation" +"without" +"':'" +"between" +"space," +"Value" +"choice" +"'INCLUDE'" +"cannot" +"JIS" +"NO-BREAK" +"E62" +"ending" +"(URI):" +"(#PCDATA" +"LAO" +"resource" +"embedded" +"called" +"'<!ENTITY" +"Conditional" +"list" +"Entity" +"large" +"(GI)," +"contain" +"small" +"&MAY;" +"->" +"ASCII" +"available" +"abbreviated" +"set" +"3986\">IETF" +"\"REC\">" +"reference" +"##" +"etc." +"DTD," +"direct" +"module" +"sign" +"zero" +"Version" +"M." +"are" +"3C" +"UTF-8," +"3F" +"canonical" +"&SGML;" +"font" +"incompatible" +"B+," +"EMPTY>" +"section" +"ID," +"label" +"state" +"version" +"enumerated" +"apos" +"above" +"capital" +"new" +"(ASCII)" +"PI" +"'='" +"public" +"body" +"C" +"full" +"escaping" +"parent" +"UAX" +"error" +"component" +"here" +"ranges" +"MIDDLE" +"objects" +"address" +"path" +"Identifier" +"UTF-16," +"change" +"V2.1" +"last" +"2141\">IETF" +"root" +"ISO-10646-UCS-2" +"equal" +"against" +"[A-Z]" +"connection" +"2781\">IETF" +"attributes" +"Attribute" +"error," +"comment" +"among" +"named" +"LINE" +"point" +"color" +"character" +"marked" +"names" +"FF" +"table" +"BCP" +"DOT" +"once" +"use" +"from" +"stream" +"entities" +"MARK," +"P." +"contains" +"two" +"'ANY'" +"symbol" +"few" +"duplicate" +"CDATA," +"call" +"UCS-4," +"scope" +"type" +"empty" +"more" +"XML" +"field" +"XSLT" +"Default" +"Markup" +"validity" +"ZERO" +"Space" +"normalized" +"child" +"')*'" +"%YN;\"" +"(MUST," +"must" +"#IMPLIED>" +"sample" +"6F" +"GREEK" +"this" +"Text" +"expanded" +"single" +"value" +"will" +"(UCS)" +"FEED" +"paragraph" +"values" +"three" +"many" +"following" +"closing" +"property" +"'}'" +"F." +"LOW" +"control" +"ASCII," +"2119\">IETF" +"L." +"links" +"YN" +"process" +"attribute" +"is" +"in" +"accept" +"parse" +"middle" +"tag" +"MIME" +"allowed" +"X-0208-1997." +"UTF-7" +"']'" +"absolute" +"information" +"different" +"end" +"PI." +"Notation" +"quot" +"generic" +"unparsed" +"charset" +"namespace" +"same" +"(CDATA)" +"write" +"read" +"ISO/IEC" +"H" +"units" +"8879\">ISO" +"document" +"parameter" +"start" +"A" +"product" +"Resource" +"description" +"see" +"may" +"stop" +"after" +"'IGNORE'" +"U+FEFF," +"HTML." +"possible" +"user" +"characters" +"such" +"on" +"data" +"compatibility" +"STACS" +"a" +"All" +"I" +"undefined" +"rules" +"expression" +"markup" +"author" +"well" +"-MSM" +"element" +"')'" +")" +"xml:lang" +"y" +"position" +"the" +"first" +"left" +"decl" +"S." +"MA," +"BB" +"less" +"<body>" +"storage" +"';'" +"entity" +"symbols" +"10646\">ISO" +"stored" +"nbsp" +"COLON," +"THAI" +"(FAMILY" +"R." +"before" +"HTML" +"MIME)," +"MIME)." +"group" +"trying" +"No" +"had" +"except" +"detected" +"valid" +"usage" +"input" +"(double-hyphen)" +"has" +"match" +"(('X'" +"identical" +"..." +"V2.5" +"3023\">IETF" +"combination" +"format" +"fragment" +"URN" +"URI" +"symbol," +"SHOULD," +"declared" +"logical" +"not" +"using" +"bit" +"NDATA" +"like" +"sequence," +"term" +"name" +"Encoding" +"B," +"decimal" +"B)" +"JC)" +"(#PCDATA)" +"token" +"10744\">ISO" +"steps" +"ENTITY)" +"found" +"8879:1986(E)." +"|" +"FE" +"subset" +"profile" +"right" +"(W3C)" +"p" +"bytes" +"creation" +"(('#FIXED'" +"HH" +"elements" +"escape" +"proper" +"et" +"FINAL" +"out" +"predefined" +"provided" +"declaration" +"XML." +"container" +"network" +"'" +"space" +"SPACE" +"preserve" +"SGML" +"per" +"content" +"method" +"does" +"XML)," +"occurs" +"be" +"HTTP" +"8879:1986(E)" +"10646:2000\">ISO" +"B" +"'{'" +"RFC" +"step" +"base" +"references" +"output" +"\"MUST" +"permitted" +"definition" +"EDIT:" +"language" +"standalone" +"column" +"of" +"could" +"Tags" +"mdash" +"recognized" +"times" +"range" +"due" +"'#PCDATA'" +"hexadecimal" +"or" +"'PUBLIC'" +"N.B." +"','" +"A," +"encoding" +"xml:space" +"within" +"STOP" +"number" +"one" +"&MAY;," +"Internal" +"ISO" +"construct" +"operator" +"RETURN" +"mark" +"Empty" +"IANA" +"doesn't" +"(#PCDATA)>" +"long" +"checked" +"(C" +"indicate" +"IETF" +"unknown" +"there" +"system" +"wrapper" +"HYPHEN-MINUS," +"needed" +"2" +"too" +"literal" +"white" +"<!--" +"was" +"final" +"function" +"D." +"T." +"'?>'" +"option" +"form" +"enough" +"D21" +"collapsed" +"(XML)" +"but" +"selector" +"ampersand," +"part" +"scripts," +"DTD." +"EBCDIC" +"UTF-16LE," +"line" +"DTD" +"with" +"than" +"MAY" +"relative" +"Set" +"target" +"keyword" +"default" +"double" +"SA," +"tree" +"return," +"'['" +"carriage" +"computer" +"to," +">" +"similar" +"declare" +"result" +"and" +"files" +"UTF-16BE," +"ISBN" +"semicolon" +"up" +"defined" +"parser" +"CHARACTER" +"E14" +"an" +"UTF-8." +"as" +"warning" +"exist" +"at" +"file" +"New" +"need" +"check" +"('M'" +"conversion" +"angle" +"no" +"#IMPLIED\">" +"-" +"validating" +"invalid" +"A." +"EUC," +"instance" +"internal" +"A7" +"XHTML" +"registered" +"'|'" +"node" +"added" +"multiple" +"Name" +"XML," +"quote" +"preceding" +"object" +"AM" +"W3C" +"(WG)." +"Element" +"('L'" +"class" +"generated" +"letter" +"SARA" +"inserted" +"model" +"structure" +"'\\'" +"building" +"'NDATA'" +"backward" +"less-than" +"for" +"E11" +"failure" +"FFFE," +"required" +"rule" +"(EBNF)" +"CARRIAGE" +"bracket" +"link" +"%" +"requires" +"external" +
diff --git a/testing/libfuzzer/fuzzers/dicts/generated/sqlite3_prepare_v2_fuzzer.dict b/testing/libfuzzer/fuzzers/dicts/generated/sqlite3_prepare_v2_fuzzer.dict new file mode 100644 index 0000000..691b961a --- /dev/null +++ b/testing/libfuzzer/fuzzers/dicts/generated/sqlite3_prepare_v2_fuzzer.dict
@@ -0,0 +1,909 @@ +# +# AFL dictionary for SQL +# ---------------------- +# +# Modeled based on SQLite documentation, contains some number of SQLite +# extensions. Other dialects of SQL may benefit from customized dictionaries. +# +# If you append @1 to the file name when loading this dictionary, afl-fuzz +# will also additionally load a selection of pragma keywords that are very +# specific to SQLite (and are probably less interesting from the security +# standpoint, because they are usually not allowed in non-privileged +# contexts). +# +# Created by Michal Zalewski <lcamtuf@google.com> +# + +function_abs=" abs(1)" +function_avg=" avg(1)" +function_changes=" changes()" +function_char=" char(1)" +function_coalesce=" coalesce(1,1)" +function_count=" count(1)" +function_date=" date(1,1,1)" +function_datetime=" datetime(1,1,1)" +function_decimal=" decimal(1,1)" +function_glob=" glob(1,1)" +function_group_concat=" group_concat(1,1)" +function_hex=" hex(1)" +function_ifnull=" ifnull(1,1)" +function_instr=" instr(1,1)" +function_julianday=" julianday(1,1,1)" +function_last_insert_rowid=" last_insert_rowid()" +function_length=" length(1)" +function_like=" like(1,1)" +function_likelihood=" likelihood(1,1)" +function_likely=" likely(1)" +function_load_extension=" load_extension(1,1)" +function_lower=" lower(1)" +function_ltrim=" ltrim(1,1)" +function_max=" max(1,1)" +function_min=" min(1,1)" +function_nullif=" nullif(1,1)" +function_printf=" printf(1,1)" +function_quote=" quote(1)" +function_random=" random()" +function_randomblob=" randomblob(1)" +function_replace=" replace(1,1,1)" +function_round=" round(1,1)" +function_rtrim=" rtrim(1,1)" +function_soundex=" soundex(1)" +function_sqlite_compileoption_get=" sqlite_compileoption_get(1)" +function_sqlite_compileoption_used=" sqlite_compileoption_used(1)" +function_sqlite_source_id=" sqlite_source_id()" +function_sqlite_version=" sqlite_version()" +function_strftime=" strftime(1,1,1,1)" +function_substr=" substr(1,1,1)" +function_sum=" sum(1)" +function_time=" time(1,1,1)" +function_total=" total(1)" +function_total_changes=" total_changes()" +function_trim=" trim(1,1)" +function_typeof=" typeof(1)" +function_unicode=" unicode(1)" +function_unlikely=" unlikely(1)" +function_upper=" upper(1)" +function_varchar=" varchar(1)" +function_zeroblob=" zeroblob(1)" + +keyword_ABORT="ABORT" +keyword_ACTION="ACTION" +keyword_ADD="ADD" +keyword_AFTER="AFTER" +keyword_ALL="ALL" +keyword_ALTER="ALTER" +keyword_ANALYZE="ANALYZE" +keyword_AND="AND" +keyword_AS="AS" +keyword_ASC="ASC" +keyword_ATTACH="ATTACH" +keyword_AUTOINCREMENT="AUTOINCREMENT" +keyword_BEFORE="BEFORE" +keyword_BEGIN="BEGIN" +keyword_BETWEEN="BETWEEN" +keyword_BY="BY" +keyword_CASCADE="CASCADE" +keyword_CASE="CASE" +keyword_CAST="CAST" +keyword_CHECK="CHECK" +keyword_COLLATE="COLLATE" +keyword_COLUMN="COLUMN" +keyword_COMMIT="COMMIT" +keyword_CONFLICT="CONFLICT" +keyword_CONSTRAINT="CONSTRAINT" +keyword_CREATE="CREATE" +keyword_CROSS="CROSS" +keyword_CURRENT_DATE="CURRENT_DATE" +keyword_CURRENT_TIME="CURRENT_TIME" +keyword_CURRENT_TIMESTAMP="CURRENT_TIMESTAMP" +keyword_DATABASE="DATABASE" +keyword_DEFAULT="DEFAULT" +keyword_DEFERRABLE="DEFERRABLE" +keyword_DEFERRED="DEFERRED" +keyword_DELETE="DELETE" +keyword_DESC="DESC" +keyword_DETACH="DETACH" +keyword_DISTINCT="DISTINCT" +keyword_DROP="DROP" +keyword_EACH="EACH" +keyword_ELSE="ELSE" +keyword_END="END" +keyword_ESCAPE="ESCAPE" +keyword_EXCEPT="EXCEPT" +keyword_EXCLUSIVE="EXCLUSIVE" +keyword_EXISTS="EXISTS" +keyword_EXPLAIN="EXPLAIN" +keyword_FAIL="FAIL" +keyword_FOR="FOR" +keyword_FOREIGN="FOREIGN" +keyword_FROM="FROM" +keyword_FULL="FULL" +keyword_GLOB="GLOB" +keyword_GROUP="GROUP" +keyword_HAVING="HAVING" +keyword_IF="IF" +keyword_IGNORE="IGNORE" +keyword_IMMEDIATE="IMMEDIATE" +keyword_IN="IN" +keyword_INDEX="INDEX" +keyword_INDEXED="INDEXED" +keyword_INITIALLY="INITIALLY" +keyword_INNER="INNER" +keyword_INSERT="INSERT" +keyword_INSTEAD="INSTEAD" +keyword_INTERSECT="INTERSECT" +keyword_INTO="INTO" +keyword_IS="IS" +keyword_ISNULL="ISNULL" +keyword_JOIN="JOIN" +keyword_KEY="KEY" +keyword_LEFT="LEFT" +keyword_LIKE="LIKE" +keyword_LIMIT="LIMIT" +keyword_MATCH="MATCH" +keyword_NATURAL="NATURAL" +keyword_NO="NO" +keyword_NOT="NOT" +keyword_NOTNULL="NOTNULL" +keyword_NULL="NULL" +keyword_OF="OF" +keyword_OFFSET="OFFSET" +keyword_ON="ON" +keyword_OR="OR" +keyword_ORDER="ORDER" +keyword_OUTER="OUTER" +keyword_PLAN="PLAN" +keyword_PRAGMA="PRAGMA" +keyword_PRIMARY="PRIMARY" +keyword_QUERY="QUERY" +keyword_RAISE="RAISE" +keyword_RECURSIVE="RECURSIVE" +keyword_REFERENCES="REFERENCES" +#keyword_REGEXP="REGEXP" +keyword_REINDEX="REINDEX" +keyword_RELEASE="RELEASE" +keyword_RENAME="RENAME" +keyword_REPLACE="REPLACE" +keyword_RESTRICT="RESTRICT" +keyword_RIGHT="RIGHT" +keyword_ROLLBACK="ROLLBACK" +keyword_ROW="ROW" +keyword_SAVEPOINT="SAVEPOINT" +keyword_SELECT="SELECT" +keyword_SET="SET" +keyword_TABLE="TABLE" +keyword_TEMP="TEMP" +keyword_TEMPORARY="TEMPORARY" +keyword_THEN="THEN" +keyword_TO="TO" +keyword_TRANSACTION="TRANSACTION" +keyword_TRIGGER="TRIGGER" +keyword_UNION="UNION" +keyword_UNIQUE="UNIQUE" +keyword_UPDATE="UPDATE" +keyword_USING="USING" +keyword_VACUUM="VACUUM" +keyword_VALUES="VALUES" +keyword_VIEW="VIEW" +keyword_VIRTUAL="VIRTUAL" +keyword_WHEN="WHEN" +keyword_WHERE="WHERE" +keyword_WITH="WITH" +keyword_WITHOUT="WITHOUT" + +operator_concat=" || " +operator_ebove_eq=" >=" + +snippet_1eq1=" 1=1" +snippet_at=" @1" +snippet_backticks=" `a`" +snippet_blob=" blob" +snippet_brackets=" [a]" +snippet_colon=" :1" +snippet_comment=" /* */" +snippet_date="2001-01-01" +snippet_dollar=" $1" +snippet_dotref=" a.b" +snippet_fmtY="%Y" +snippet_int=" int" +snippet_neg1=" -1" +snippet_pair=" a,b" +snippet_parentheses=" (1)" +snippet_plus2days="+2 days" +snippet_qmark=" ?1" +snippet_semicolon=" ;" +snippet_star=" *" +snippet_string_pair=" \"a\",\"b\"" + +string_dbl_q=" \"a\"" +string_escaped_q=" 'a''b'" +string_single_q=" 'a'" + +pragma_application_id@1=" application_id" +pragma_auto_vacuum@1=" auto_vacuum" +pragma_automatic_index@1=" automatic_index" +pragma_busy_timeout@1=" busy_timeout" +pragma_cache_size@1=" cache_size" +pragma_cache_spill@1=" cache_spill" +pragma_case_sensitive_like@1=" case_sensitive_like" +pragma_checkpoint_fullfsync@1=" checkpoint_fullfsync" +pragma_collation_list@1=" collation_list" +pragma_compile_options@1=" compile_options" +pragma_count_changes@1=" count_changes" +pragma_data_store_directory@1=" data_store_directory" +pragma_database_list@1=" database_list" +pragma_default_cache_size@1=" default_cache_size" +pragma_defer_foreign_keys@1=" defer_foreign_keys" +pragma_empty_result_callbacks@1=" empty_result_callbacks" +pragma_encoding@1=" encoding" +pragma_foreign_key_check@1=" foreign_key_check" +pragma_foreign_key_list@1=" foreign_key_list" +pragma_foreign_keys@1=" foreign_keys" +pragma_freelist_count@1=" freelist_count" +pragma_full_column_names@1=" full_column_names" +pragma_fullfsync@1=" fullfsync" +pragma_ignore_check_constraints@1=" ignore_check_constraints" +pragma_incremental_vacuum@1=" incremental_vacuum" +pragma_index_info@1=" index_info" +pragma_index_list@1=" index_list" +pragma_integrity_check@1=" integrity_check" +pragma_journal_mode@1=" journal_mode" +pragma_journal_size_limit@1=" journal_size_limit" +pragma_legacy_file_format@1=" legacy_file_format" +pragma_locking_mode@1=" locking_mode" +pragma_max_page_count@1=" max_page_count" +pragma_mmap_size@1=" mmap_size" +pragma_page_count@1=" page_count" +pragma_page_size@1=" page_size" +pragma_parser_trace@1=" parser_trace" +pragma_query_only@1=" query_only" +pragma_quick_check@1=" quick_check" +pragma_read_uncommitted@1=" read_uncommitted" +pragma_recursive_triggers@1=" recursive_triggers" +pragma_reverse_unordered_selects@1=" reverse_unordered_selects" +pragma_schema_version@1=" schema_version" +pragma_secure_delete@1=" secure_delete" +pragma_short_column_names@1=" short_column_names" +pragma_shrink_memory@1=" shrink_memory" +pragma_soft_heap_limit@1=" soft_heap_limit" +pragma_stats@1=" stats" +pragma_synchronous@1=" synchronous" +pragma_table_info@1=" table_info" +pragma_temp_store@1=" temp_store" +pragma_temp_store_directory@1=" temp_store_directory" +pragma_threads@1=" threads" +pragma_user_version@1=" user_version" +pragma_vdbe_addoptrace@1=" vdbe_addoptrace" +pragma_vdbe_debug@1=" vdbe_debug" +pragma_vdbe_listing@1=" vdbe_listing" +pragma_vdbe_trace@1=" vdbe_trace" +pragma_wal_autocheckpoint@1=" wal_autocheckpoint" +pragma_wal_checkpoint@1=" wal_checkpoint" +pragma_writable_schema@1=" writable_schema" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using sqlite3_prepare_v2_fuzzer binary and ISO/IEC FCD 9075-1. +"all" +"code" +"BE" +"text" +"TP2," +"supported" +"GR4)" +"syntax" +"S151," +"S043," +"\xe2\x80\x9cCR\xe2\x80\x9d" +"(SQL/PSM)" +"query" +"expressions" +"TP2;" +"row" +"[ISO9075-14]," +"BNF." +"<SQL" +"parameters" +"title" +"S211," +"ISO/IEC:" +"BNF," +"SQL_FEATURES" +"should" +"to" +"only" +"program" +"present" +"T211," +"G," +"local" +"NY" +"columns" +"END." +"do" +"OBJECT" +"rollback" +"string" +"FEAT2." +"get" +"H" +"P001," +"between" +"RI." +"[ISO9075-11]" +"cannot" +"entries" +"referencing" +"datetime" +"[UCS]." +"BNF" +"MINUTE" +"(BNF" +"IEC," +"False" +"OF," +"level" +"did" +"W." +"list" +"large" +"SQL)" +"PSM." +"(ISO/IEC" +"SQL," +"SQL-" +"SQL." +"small" +"x" +"DEFINITION_SCHEMA;" +"view" +"Index" +"[ISO9075-3])." +"set" +"S024," +"CHANGE." +"reference" +"T1," +"OLAP." +"direct" +"(SQL/XML)." +"LARGE" +"likely" +"result" +"T341," +"ST" +"ISO/JTC" +"INSERT," +"PKG004" +"index" +"PKG006" +"PKG007" +"PKG001" +"PKG002" +"PKG008" +"supplied" +"T611," +"access" +"3" +"version" +"NULL." +"routine" +"[ISO9075-10])." +"S1" +"[UCS]," +"P003," +"C" +"terms" +"(SQL/MED)" +"JTC1/SC32" +"K" +"(SQL/JRT)" +"modify" +"reported" +"S" +"objects" +"32N1821" +"SECOND." +"key" +"UNDER" +"(ANSI)" +"rows" +"come" +"(CALL" +"change" +"P-" +"both" +"search" +"SQLSTATE," +"[ISO9075-" +"[ISO9075-14]." +"many" +"changed" +"foreign" +"Symbols" +"S023," +"connection" +"SQL\xe2\x80\x9d)," +"context" +"delete" +"changes" +"REFERENCES," +"page." +"named" +"point" +"UPDATE." +"S2" +"UPDATE," +"[ISO9075-13]" +"Y\xe2\x80\x9d" +"replace" +"\xe2\x80\x9cPSM\xe2\x80\x9d" +"SERIALIZABLE," +"names" +"E" +"PUBLIC." +"table" +"REF" +"INFORMATION_SCHEMA" +"C1." +"ID." +"use" +"[ISO9075-2]." +"from" +"USA" +"0" +"distinct" +"create" +"contains" +"due" +"ISO." +"few" +"duplicate" +"trigger" +"call" +"S111," +"expected" +"REPEATABLE" +"C1" +"DOCUMENT" +"type" +"authorization" +"more" +"XML" +"[ISO9075-3]," +"<A>," +"P" +"on" +"initial" +"name," +"[ISO9075-11])," +"QE," +"STANDARD" +"PKG010" +"TRIGGER," +"V" +"CS" +"SQL\xe2\x80\x9d:" +"IEC" +"Expression" +"F521," +"sequence:" +"must" +"none" +"SR3)" +"word" +"INTERNATIONAL" +"ANSI" +"this" +"PSM" +"PUBLIC)," +"modified" +"value" +"<" +"descriptor" +"while" +"paragraph" +"values" +"resources" +"error" +"exceptions" +"IT" +"F," +"CO," +"[ISO9075-4]," +"control" +"type," +"reserved" +"SQL:" +"<C>" +"[ISO9075-2])." +"F052," +"attribute" +"is" +"type:" +"level," +"it" +"[ISO9075-2]," +"incremental" +"MONTH," +"dropped" +"MONTH." +"allowed" +"S241," +"\xe2\x80\x9cSQL" +"TIMESTAMP" +"failed" +"SC" +"end" +"Format" +"ST." +"permission" +"V," +"length" +"same" +"[ISO10646]." +"write" +"arguments" +"F555," +"F671," +"<C>," +"<C>." +"parameter" +"NATIONAL" +"Types" +"A" +"Insert" +"32/WG" +"used" +"temporary" +"\xe2\x80\x9cOLAP\xe2\x80\x9d" +"(FCD)" +"may" +"after" +"(SQL/OLB)" +"THIS" +"Q" +"SQL/CLI" +"levels" +"two" +"characters" +"date" +"such" +"[ISO9075-9]" +"data" +"stack" +"single" +"a" +"FEAT," +"lower" +"transaction" +"in" +"database" +"EXTRACT)" +"expression" +"32N1963" +"CD" +"without" +"QE." +"1" +"CALL" +"F" +"[ISO9075-4])." +"entry" +"the" +"SUBJECT" +"N1968;" +"order" +"left" +"FEAT1," +"FEAT1." +"S081," +"YEAR" +"READ," +"SQL;" +"A," +"symbols" +"S161," +"[ISO9075-10]" +"already" +"identify" +"V." +"during" +"differs" +"(UCS)." +"Final" +"before" +"tables" +"[UCS]" +"Multiple" +"integer" +"NT," +"character" +"," +"ID\xe2\x80\x9d" +"(INFORMATION_SCHEMA)" +"source" +"add" +"other" +"TP1" +"SQLSTATE" +"has" +"match" +"KEY." +"real" +"On" +"C1," +"D" +"[ISO14651]" +"views" +"read" +"\xe2\x80\x9cGR\xe2\x80\x9d" +"L" +"primary" +"TB1." +"qualified" +"(SUBSTRING," +"T" +"compound" +"not" +"using" +"unique" +"LOB" +"name" +"term" +"sorting" +"like" +"B," +"[ISO9075-1]" +"RESULT," +"Numeric" +"MONTH" +"PURPOSES." +"[ISO9075-11]." +"mode" +"(DEFINITION_SCHEMA)." +"SQL" +"ISO" +"page" +"constraints" +"\xc2\xa9ISO/IEC" +"right" +"Java" +"sequence" +"TB1" +"TB2" +"P002," +"DAY," +"extended" +"(SQL/CLI)" +"X" +"specified" +"S051," +"clauses" +"operation" +"FEAT" +"out" +"E," +"XML." +"for" +"space" +"support" +"T041," +"[ISO9075-4]" +"content" +"I" +"does" +"STUDY" +"CHARACTER," +"B1" +"T212," +"be" +"object" +"[ISO9075-11]," +"G" +"ZONE," +"S2." +"collations" +"[ISO9075-2]:" +"<A>" +"O" +"standard" +"[ISO9075-2]" +"base" +"W" +"collation" +"HOUR," +"UNDER," +"JTC" +"C." +"definition" +"Square" +"\xe2\x80\x9cSR\xe2\x80\x9d" +"extension" +"constraint" +"column" +"of" +"C," +"F701," +"(SQL/CLI)." +"T191," +"range" +"GR" +"1," +"constructor" +"commit" +"or" +"first" +"referenced" +"statements" +"encoding" +"B1." +"clause" +"variables" +"within" +"number" +"one" +"NT" +"variable" +"because" +"references" +"another" +"blank" +"operator" +"RETURN" +"COMMITTED," +"9075-1:2011(E)" +"[ISO9075-14]" +"(SQL/OLB)." +"D1" +"exists" +"REFERENCE" +"area" +"S041," +"unknown" +"Symbol" +"there" +"system" +"long" +"ID" +"start" +"returns" +"2" +"authorized" +"statement" +"X2" +"FCD" +"STILL" +"S231," +"final" +"READ" +"schema" +"function" +"DELETE," +"B" +"TC\xe2\x80\x9d." +"declare" +"month" +"Deprecated" +"exactly" +"[ISO10646]" +"JTC1" +"but" +"9075-1:2010(E)" +"part" +"T201," +"D2." +"<B>," +"attempt" +"line" +"with" +"than" +"<B>" +"BEFORE," +"DAY." +"DATE" +"default" +"EXECUTE." +"B1," +"F191," +"tree" +"second" +"SHOULD" +"[ISO9075-13]," +"A1," +"1/SC" +"VARYING," +"<B>." +"SQL/CLI," +"were" +"1)" +"<A>." +"CLI," +"called" +"are" +"and" +"(SQL/MED)." +"[ISO9075-4]:" +"associated" +"\xe2\x80\x9cAR\xe2\x80\x9d" +"defined" +"(SQL/XML)" +"CHARACTER" +"argument" +"an" +"[ISO9075-4])" +"non-deterministic" +"as" +"Other" +"at" +"have" +"[ISO9075-4]." +"CS." +"\xe2\x80\x9cV\xe2\x80\x9d" +"Y." +"null" +"any" +"CLI" +"Function" +"NOTE" +"functions" +"UCS" +"returned" +"F411," +"no" +"TIME" +"that" +"-" +"RETURN)," +"A1" +"OLAP" +"internal" +"S071," +"[ISO9075-10]," +"T431," +"A1." +"\xe2\x80\x9cONLY" +"Y" +"SS" +"UNCOMMITTED," +"multiple" +"Name" +"truncate" +"normal" +"symbol" +"literal" +"M" +"\xe2\x80\x9c<SQL" +"prepared" +"most" +"ATOMIC," +"E." +"U" +"letter" +"PUBLIC" +"identical" +"F491," +"N" +"inserted" +"Page" +"(SQL/JRT)." +"D," +"SELECT," +"USED" +"lead" +"Sequence" +"FEAT1" +"into" +"required" +"[ISO9075-9]," +"USAGE," +"2nd" +"depth" +"R" +"ISO," +"time" +"SQL\xe2\x80\x9d," +"FEAT2" +"[ISO9075-3]" +"(SQL/PSM)." +"ISO/IEC"
diff --git a/testing/libfuzzer/fuzzers/dicts/generated/url_parse_fuzzer.dict b/testing/libfuzzer/fuzzers/dicts/generated/url_parse_fuzzer.dict new file mode 100644 index 0000000..302f590 --- /dev/null +++ b/testing/libfuzzer/fuzzers/dicts/generated/url_parse_fuzzer.dict
@@ -0,0 +1,403 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file has been generated with testing/libfuzzer/dictionary_generator.py +# using url_parse_fuzzer binary and RFC 3986. +"DNS" +"text" +"TCP" +"\"%D3%81%87%A4%95%81@%C2%85%81%83%88\"." +"[RFC2234]" +"F.," +"FORCE" +"SOCIETY" +"implementation" +"TASK" +"cache" +"WINS," +"D.1." +"to" +"only" +"HTML" +"SPONSORED" +"[RFC1630]." +"D.," +"[RFC1123]" +"resources" +"(STD" +"[RFC1808]," +"string" +"returning" +"==" +"H" +"HEREIN" +"[BCP35]" +"SP)" +"SCTP)" +"(NUL)" +"THE" +"(URI):" +"REPRESENTS" +"resource" +"A.," +"EXPRESS" +"list" +"(%2E)," +"WILL" +"J." +"INCLUDING" +"segment." +"[RFC2732]" +"(URL)\"," +"set" +"HTTP" +"IANA" +"INFORMATION" +"(%41-%5A" +"[RFC2518]" +"M." +"direct" +"(IDNA)\"," +"Only" +"Version" +"are" +"allowed." +"\"X\"" +"(SP)." +"2DIGIT" +"section" +"BUT" +"\"UTF-8," +"3" +"version" +"[RFC1034]" +"probably" +"[RFC2732]." +"metadata" +"Y.," +"C" +"WWW\"" +"FOR" +"0X" +"S" +"address" +"INPUT" +"[" +"P." +"WWW:" +"AND" +"WWW" +"[BCP35]." +"MA" +"\"AS" +"\"%\"" +"NOT" +"ANY" +"[RFC1808]" +"WARRANTY" +"useful" +"[RFC1737]." +"[STD63]," +"\"HTTP\"" +"(MIME)" +"TELNET" +"[RFC1630]" +"S." +"D.2." +"B.," +"[RFC2234]." +"[RFC2234]," +"BCP" +"[STD63];" +"use" +"LATIN" +"from" +"C." +"0" +"WARRANTIES" +"(MHTML)\"," +"ENGINEERING" +"URI;" +"few" +"(DNS)." +"expected" +"USENET" +"type" +"empty" +"XML" +"URL?\"," +"W3C/MIT" +"F" +"CA" +"STD:" +"SMTP" +"[RFC2141]," +"N" +"A)," +"NOTE:" +"CR" +"MHTML" +"must" +"ANY)," +"ALL" +"[STD63]" +"RIGHTS" +"HE/SHE" +"SP" +"[BCP19]" +"value" +"INFRINGE" +"while" +"KATAKANA" +"US-ASCII" +"W3C/IETF" +"loop" +"J.," +"2E:" +"L." +"have" +"%61-%7A)," +"is" +"PARTICULAR" +"thus" +"URI," +"parse" +"STEP" +"MIME" +"UTF-8" +"in" +"failed" +"LF" +"binary" +"ISO/IEC" +"\"A" +"(%5F)," +")" +"HTTP," +"get" +"\"A\"," +"[RFC2141]" +"BUFFER" +"ABNF" +"[RFC2557]." +"I." +"WARRANTIES," +"URN" +"EBCDIC" +"A" +"used" +"http" +"may" +"IP" +"IS" +"after" +"L" +"Q" +"'A'" +"running" +"HEXDIG" +"such" +"EBCDIC," +"data" +"[ASCII]" +"a" +"P" +"[ASCII]." +"M.," +"Names" +"the" +"[RFC0952]." +"[RFC3490]" +"US-ASCII." +"2C:" +"THAT" +"E.," +"(%2D)," +"\"URL:\"" +"WITH" +"BY" +"[UCS]," +"tables" +"[UCS]" +"TO" +"BNF" +"internal" +"P.," +"ORGANIZATION" +"\"HTTP" +"URI." +"it," +"D" +"format" +"URL" +"(0" +"URI\"" +"URI" +"K." +"URI:" +"T" +"D.W." +"not" +"R." +"LIMITED" +"\"%3A\")" +"name" +"OF" +"B." +"[RFC1736]" +"(R)," +"IPR" +"[RFC1738];" +"OUTPUT" +"LALR" +"OR" +"STD" +"[RFC3513]" +"because" +"bytes" +"DNS," +"back" +"(URI)" +"*DIGIT" +"[RFC2046]" +"[RFC3305]" +"W3C" +"E." +"for" +"space" +"ABNF\"," +"[RFC1535]." +"DQUOTE" +"I" +"does" +"'F'" +"[RFC2396]" +"be" +"K.," +"DISCLAIM" +"G" +"(UTF-16)," +"This" +"M" +"INTERNET" +"RFC" +"X3.4," +"base" +"(T):" +"IMPLIED," +"by" +"\"URL\"" +"on" +"DIGIT" +"(ABNF)" +"WEBDAV\"," +"of" +"could" +"R.," +"(ABNF:" +"S.," +"1*4HEXDIG" +"CAPITAL" +"number" +"one" +"ISO" +"FITNESS" +"\"%7E\"" +"open" +"ANSI" +"[BCP19]," +"\"%C3%80\"," +"IETF" +"support" +"\"URN" +"[RFC1123]." +"long" +"[RFC0952]" +":" +"was" +"[RFC3513]." +"[RFC2718]" +"B" +"N." +"that" +"IDNA" +"OCTET" +"but" +"R" +"POSIX" +"LETTER" +"CONTRIBUTOR," +"[RFC1738]" +"(C)" +"with" +"\"URI\"" +"16" +"default" +"double" +"\"URN\"" +"[RFC2557]" +"up" +"TCP," +"PURPOSE." +"MERCHANTABILITY" +"1)" +"IS\"" +"\"IANA" +"(URN)" +"and" +"USE" +"false" +"(IF" +"USA" +"URL," +"an" +"To" +"as" +"(%7E)" +"at" +"file" +"need" +"any" +"\"%E3%82%A2\"." +"physical" +"1*HEXDIG" +"no" +"[RFC1737]" +"-" +"invalid" +"A." +"application" +"valid" +"take" +"which" +"test" +"[RFC2732]," +"you" +"=" +"GRAVE" +"<URI>" +"[RFC2396]," +"2B:" +"period," +"UDP," +"[RFC1535]" +"T." +"(UCS)\"," +"U" +"A-F." +"T.," +"]" +"[RFC2718]." +"D." +"persistent" +"traditional" +"L.," +"As" +"IMPLIED" +"(URL)" +"ALPHA" +"[RFC3305]." +"H.," +"\"MIME" +
diff --git a/testing/libfuzzer/fuzzers/dicts/generated/v8_script_parser_fuzzer.dict b/testing/libfuzzer/fuzzers/dicts/generated/v8_script_parser_fuzzer.dict new file mode 100644 index 0000000..b4d536c --- /dev/null +++ b/testing/libfuzzer/fuzzers/dicts/generated/v8_script_parser_fuzzer.dict
@@ -0,0 +1,1656 @@ +# +# AFL dictionary for JavaScript +# ----------------------------- +# +# Contains basic reserved keywords and syntax building blocks. +# +# Created by Michal Zalewski <lcamtuf@google.com> +# + +keyword_arguments="arguments" +keyword_break="break" +keyword_case="case" +keyword_catch="catch" +keyword_const="const" +keyword_continue="continue" +keyword_debugger="debugger" +keyword_decodeURI="decodeURI" +keyword_default="default" +keyword_delete="delete" +keyword_do="do" +keyword_else="else" +keyword_escape="escape" +keyword_eval="eval" +keyword_export="export" +keyword_finally="finally" +keyword_for="for (a=0;a<2;a++)" +keyword_function="function" +keyword_if="if" +keyword_in="in" +keyword_instanceof="instanceof" +keyword_isNaN="isNaN" +keyword_let="let" +keyword_new="new" +keyword_parseInt="parseInt" +keyword_return="return" +keyword_super="super" +keyword_switch="switch" +keyword_this="this" +keyword_throw="throw" +keyword_try="try" +keyword_typeof="typeof" +keyword_var="var" +keyword_void="void" +keyword_while="while" +keyword_with="with" + +misc_1=" 1" +misc_a="a" +misc_array=" [1]" +misc_assign=" a=1" +misc_code_block=" {1}" +misc_colon_num=" 1:" +misc_colon_string=" 'a':" +misc_comma=" ," +misc_comment_block=" /* */" +misc_comment_line=" //" +misc_cond=" 1?2:3" +misc_dec=" --" +misc_div=" /" +misc_equals=" =" +misc_fn=" a()" +misc_identical=" ===" +misc_inc=" ++" +misc_minus=" -" +misc_modulo=" %" +misc_parentheses=" ()" +misc_parentheses_1=" (1)" +misc_parentheses_1x4=" (1,1,1,1)" +misc_parentheses_a=" (a)" +misc_period="." +misc_plus=" +" +misc_plus_assign=" +=" +misc_regex=" /a/g" +misc_rol=" <<<" +misc_semicolon=" ;" +misc_serialized_object=" {'a': 1}" +misc_string=" 'a'" +misc_unicode=" '\\u0001'" +misc_shl=" <<" +misc_shr=" >>" +misc_sae=" >>>" +misc_bit_or=" |" +misc_bit_and=" &" +misc_bit_xor=" ^" +misc_bit_not=" ~" + +object_Array=" Array" +object_Boolean=" Boolean" +object_Date=" Date" +object_Function=" Function" +object_Infinity=" Infinity" +object_Int8Array=" Int8Array" +object_Math=" Math" +object_NaN=" NaN" +object_Number=" Number" +object_Object=" Object" +object_RegExp=" RegExp" +object_String=" String" +object_Symbol=" Symbol" +object_false=" false" +object_null=" null" +object_true=" true" + +prop_charAt=".charAt" +prop_concat=".concat" +prop_constructor=".constructor" +prop_destructor=".destructor" +prop_length=".length" +prop_match=".match" +prop_proto=".__proto__" +prop_prototype=".prototype" +prop_slice=".slice" +prop_toCode=".toCode" +prop_toString=".toString" +prop_valueOf=".valueOf" + + +# This part has been generated with testing/libfuzzer/dictionary_generator.py +# using v8_script_parser_fuzzer binary and ECMA-262 standard 6.0. +"all" +"ECMA-404." +"contexts." +"Date.prototype.setHours" +"IsConstructor" +"forbidden" +"dynamic" +"month" +"(exclusive)" +"(OOPSLA" +"arguments)" +"consists" +"expressions" +"(which" +"(in" +"WeakSet" +"whose" +"iterator" +"PATENT" +"(for" +"equivalence" +"including" +"to" +"tail" +"program" +"under" +"immutable" +"started" +"@" +"digit" +"returned" +"very" +"activation" +"'UA-32577963-1']);" +"Classes" +"every" +"updates" +"U+200C" +"(URI):" +"condition" +"(QUOTATION" +"exponential" +"Reference" +"EXPRESS" +"list" +"prefix" +"non-extensible" +"large" +"INDIRECT," +"NY," +"enclosing" +"small" +"abbreviated" +"built-in" +"range." +"BUSINESS" +"C++," +"translating" +"surrounding" +"second" +"Version" +"pass" +"UTF-8." +"invariant" +"(LINE" +"implemented" +"INFRINGE" +"Z." +"Latin" +"incompatible" +"section" +"selected" +"supplied" +"decoding" +"version" +"run" +"above" +"Int8Array" +"method" +"\"BSD" +"full" +"escaping" +"Undefined" +"compilation" +"never" +"component" +"here" +"ranges" +"reported" +"U+007D" +"operations." +"active" +"path" +"placeholder" +"8601:2004(E)" +"search" +"White_Space" +"U+10FFFF," +"changed" +"allows" +"(see" +"SOLIDUS)" +"prior" +"real" +"successors" +"error," +"error." +"proxy" +"prints" +"via" +"shorthand" +"divide" +"replace" +"Object.defineProperties" +"Instance" +"TO" +"S," +"SUCH" +"total" +"unit" +"languages" +"executable" +"takes" +"would" +"U+003A" +"contains" +"negative" +"URI;" +"call" +"JTC" +"6" +"type" +"until" +"more" +"Date.prototype.setMinutes" +"GOODS" +"EXEMPLARY," +"expose" +"SIGN)" +"flag" +"U+000A" +"V" +"Representation" +"Alphabetic" +"hold" +"finalization" +"must" +"Array.prototype" +"PROVIDED" +"none" +"word" +"U+000D" +"hour" +"SV" +"(REVERSE" +"paragraph" +"ms" +"v" +"exceptions" +"COMMA," +"root" +"could" +"defer" +"compare" +"type." +"(with" +"JavaScript" +"states" +"minimum" +"numbers" +"keep" +"SEPARATOR)," +"absolute" +"information" +"end" +"recursive" +"Format" +"provide" +"DataView" +"HOWEVER" +"maps" +"reject" +"Promise" +"IMPLIED" +"<CR>" +"A" +"description" +"binary" +"Arrays" +"typed" +"after" +"variant" +"mapping" +"U+0024" +"hoisting" +"reflect" +"SPECIAL," +"types" +"All" +"short" +"(CHARACTER" +"postfix" +"ID_Start" +"map," +"blocks." +")" +"LICENSING" +"QUOTATION" +"order" +"DAMAGES" +"operations" +"executed" +"interpretation" +"V," +"over" +"NO-BREAK" +"expects" +"through" +"LINE" +"its" +"before" +"byteLength" +"style" +"20" +"(V," +"CreateIterResultObject" +"," +"writing" +"detected" +"verifies" +"SUBSTITUTE" +"might" +"then" +"them" +"skipped" +"combination" +"strings." +"URI" +"number" +"of:" +"nested" +"operation." +"[~U]" +"always" +"decimal" +"Date.prototype.setMonth" +"token" +"API" +"twice." +"arrow" +"each" +"types." +"side" +"(but" +"GetSuperConstructor" +"directly" +"Zone" +"UTC" +"FITNESS" +"numeric" +"expect" +"RegExp" +"loops" +"operation" +"scope)" +"Type" +"Reflect.ownKeys" +"More" +"WILL" +"by" +"mark-up" +"restricted" +"since" +"BMP" +"7" +"newly" +"Super" +"Class" +"Must" +"loop." +"Extension" +"found" +"free" +"standard" +"reason" +"base" +"byteOffset" +"Constructor" +"put" +"Block" +"thrown" +"definition" +"pairs" +"unresolved" +"created" +"starts" +"filter" +"uses" +"assign" +"already" +"features" +">>" +"encoding" +"SYMBOL" +"TC39" +"SameValue" +"primary" +"system" +"Maps" +"Handler" +"done" +"notify" +"another" +"RETURN)," +"SMALL" +"Date.prototype.setSeconds" +"script" +"top" +"least" +"ToString" +"needed" +"SymbolDescriptiveString" +"too" +"statement" +"store" +"passed" +"Language" +"OrdinaryHasInstance" +"Named" +"immediate" +"direct" +"tokens" +"execution." +"BRACKET)." +"translation" +"to:" +"kind" +"Code" +"keyword" +"double" +"enabled" +"zero" +"normalizing" +"Reflect.getOwnPropertyDescriptor" +"(NOTE" +"minus" +"debugging" +"script." +"constructors" +"bitwise" +"randomly" +"UTC," +"Reflect.has" +"initialized" +"U+005D" +"null" +"ARISING" +"UTF-8," +"contents" +"option" +"forced" +"Power" +"-" +"eagerly" +"indexes" +"also" +"internal" +"(LEFT" +"Date.prototype.setYear" +"ARE" +"REGARDING" +"added" +"object" +"most" +"optimized" +"regular" +"rejected" +"letter" +"scripts" +"Date.prototype.setDate" +"The" +"<ZWNJ>" +"brackets" +"flow" +"traditional" +"Single" +"Boolean" +"place" +"parenthesis" +"Native" +"+" +"heuristics" +"radix" +"SyntaxError" +"(N," +"syntax" +"attempts" +"O," +"relation" +"find" +"(COMMA)." +"access" +"(COMMA)," +"parameters" +"THAT" +"HTML" +"8" +"exports" +"dependent" +"account" +"Value" +"(P)" +"ToLength" +"non-integer" +"report" +"during" +"target" +"runs" +"resolve" +"THIS" +"fields" +"bytes" +"remove" +"twice" +"common" +"CET," +"parameter," +"parameter." +"automatic" +"ToObject" +"set" +"reference" +"locale" +"testing" +"<ZWNBSP>" +"Tail" +"are" +"arg" +"hash" +"(CARRIAGE" +"stringify" +"said" +"currently" +"BUT" +"future" +"various" +"OWNERSHIP" +"consecutive" +"conditions" +"available" +"C" +"1))" +"creating" +"missing" +"modify" +"weak" +"zone," +"PROCUREMENT" +"succeed" +"IS\"" +"interface" +"IMPLEMENT" +"AND" +"both" +"c" +"TypeError" +"last" +"SHALL" +"false," +"against" +"became" +"PURPOSE" +"context" +"receiver" +"exceeds" +"(MV)," +"finds" +"WARRANTY" +"point" +"header" +"globals" +"written" +"slots" +"Method" +"iterable" +"Wide" +"Date.prototype.toDateString" +"C," +"format," +"create" +"Processing" +"(SV," +"been" +"accessor" +"Early" +"TORT" +"JSON" +"UTF-16." +"basic" +"expected" +"C0" +"empty" +"Date.prototype.setUTCMilliseconds" +"CLEF)." +"precision" +"N" +"TV," +"assigning" +"exception" +"Date.prototype.setMilliseconds" +"frozen" +"Uint16Array" +"deferred" +"optimization" +"replaced" +"Object.defineProperty" +"error" +"property" +"EVENT" +"loop" +"resolved" +"USE," +"Both" +"is" +"binding" +"it" +"encountered" +"itself" +"[[Handler]]" +"containing" +"U+005F" +"ISO/IEC" +"Boolean.prototype.toString" +"flag." +"make" +"NaN" +"shorter" +"(PARAGRAPH" +"(MV," +"split" +"9" +"AT&T" +"U+005B" +"(TV)" +"used" +"keys" +"assignment" +"LIABILITY," +"NOT" +"levels" +"moving" +"user" +"characters" +"CONDUCT" +"stack" +"normalization" +"early" +"lower" +"surrogate" +"changes" +"ZERO)," +"flags" +"Names" +"y" +"entry" +"the" +"encodeURIComponent" +"ECMA" +"left" +"construct" +"quoted" +"sentence" +"||" +"overflows" +"SERVICES;" +"(F," +"Inherited" +"followed" +"32" +"yet" +"previous" +"tables" +"Assignment" +"LEFT-TO-RIGHT" +"character" +"source" +"n" +"collections" +"found," +"input" +"has" +"remaining" +"..." +"format" +"lexically" +"big" +"(O," +"possible" +"marked" +"integer" +"bit" +"enumerable" +"formal" +"ON" +"d" +"OF" +"ignore" +"steps" +"Date.prototype.toISOString" +"table." +"OR" +"right" +"old" +"Reflect.set" +"<PS>" +"creation" +"back" +"Numeric" +"apply" +"indirect" +"encodeURI" +"sourceText" +"String" +"for" +"notification" +"subclass" +"<LF>" +"track" +"Let" +"eliminate" +"either" +"be" +"<LS>" +"algorithmic" +"Calls" +"processing" +"O" +"step" +"RIGHT-TO-LEFT" +"ToNumber" +"BMP." +"method." +"from" +"Property" +"properties" +"<ZWJ>," +"Abstract" +"Argument" +"range" +"extensions" +"value." +"runtime" +"automatically" +"Common" +"IANA" +"primitive" +"statements" +"constructor." +"garbage" +"CAUSED" +"into" +"within" +"bound" +"ACM" +"parsing" +"Literal" +"Java" +"Reflect.get" +"IsRegExp" +"32-bit" +"U+005C" +"Keys" +"intrinsic" +"support" +"initial" +"handles" +"long" +"ReferenceError" +"RangeError" +"array." +"Variable" +"perform" +"analyze" +"was" +"(i.e." +"form" +"memory" +"failure" +"decodeURIComponent" +"CONTRACT," +"statement." +"objects." +"true" +"objects)" +"Left" +"arrays" +"inside" +"caller" +"maximum" +"...," +"annotations" +"LEFT" +"called" +"constant" +"defined" +"Deseret" +"iterator," +"To" +"single" +"Arguments" +"floating" +"check" +"Map" +"Only" +"no" +"TV" +"binding." +"when" +"Possible" +"invalid" +"A." +"application" +"points" +"Proxy" +"Scripts" +"test" +"Reflect.isExtensible" +"arithmetic" +"node" +"elements" +"update" +"prepared" +"class" +"AT" +"variable" +"structure" +"for-in" +"required" +"modules" +"An" +"NOTE" +"logical" +"time" +"PROFITS;" +"code)" +"requires" +"CreateDataProperty" +"non-writable" +"once" +"code" +"partial" +"FEED)," +"chain" +"FEED)." +"(MUSICAL" +"global" +"existing" +"WIDTH" +"signatures" +"per" +"computation" +"SOLIDUS)," +"U+017F" +"CLEF" +"millisecond" +"aligned" +"U+007B" +"zone" +"default," +"Object" +"environment" +"0" +"Array.prototype.concat" +"stable" +"include" +"resources" +"uninitialized" +"division" +"string" +"LOSS" +"(LATIN" +"(INCLUDING," +"Tagged" +"Keyed" +"P" +"ObjectDefineProperties" +"anonymous" +"entries" +"specific" +"minute" +"level" +"did" +"positions" +"Global" +"EvalError" +"round" +"Canonical" +"prevent" +"CODE" +"HTTP" +"INFORMATION" +"M," +"M." +"object." +"initializer" +"non-strict" +"manipulating" +"Date.prototype.setUTCMinutes" +"index" +"adds" +"appear" +"TO," +"MUSICAL" +"current" +"Float64Array" +"lazily" +"template" +"shared" +";" +"filled" +"body" +"(SOLIDUS)" +"U+2028" +"U+2029" +"Descriptor" +"objects" +"(FORM" +"[" +"UTF-16," +"implicit" +"change" +"convert" +"\"AS" +"shift" +"31" +"Date.prototype.setUTCSeconds" +"queue" +"MV" +"weekday" +"(MV)" +"{" +"Null" +"named" +"tasks" +"GetOwnPropertyKeys" +"extra" +"When" +"Construct" +"modifying" +"Languages" +"names" +"(DIGIT" +"marker" +"Import" +"bindings" +"use" +"additive" +"handled" +"&" +"illegal" +"value," +"value)" +"next" +"few" +"duplicate" +"handler" +"Date.prototype.setUTCFullYear" +"attribute" +"scope" +"String.prototype" +"F" +"Default" +"trail" +"Time" +"cases" +"ID_Continue" +"\"CODE\"," +"NON-JOINER)" +"lowercase" +"RIGHTS" +"ObjectCreate" +"modified" +"MARK" +"descriptor" +"tag" +"values" +"can" +"executor" +"following" +"meet" +"detached" +"F," +"control" +"FTP)" +"reserved" +"stream" +"escapes" +"process" +"lock" +"escaped" +"incremental" +"UTF-8" +"allowed" +"unhandled" +"block." +"for-of" +"requirements" +"UTF-32" +"means" +"write" +"INTERNATIONAL" +"instead" +"WARRANTIES," +"parameter" +"attributes," +"circular" +"map" +"may" +"clone" +"(PLUS" +"collection" +"DISCLAIMS" +"produce" +"preferred" +"Prologue" +"date" +"representations" +"Int16Array" +"data" +"annotation" +"ambiguous" +"USA," +"computations" +"bind" +"lines" +"element" +"q" +"rather" +"block" +"allow" +"representation" +"terminating" +"__proto__" +"(COLON)," +"tagged" +"@@toPrimitive" +"Uint32Array" +"Generator" +"move" +"Use" +"years" +"symbols" +"comma" +"differs" +"INCIDENTAL," +"THE" +"non-zero" +"1" +"(LF)" +"group" +"Rules" +"platform" +"Using" +"main" +"defining" +"<" +"pending" +"Date.prototype.toUTCString" +"non" +"greater" +"views" +"%JSON%" +"(FULL" +"BRACKET)" +"EVEN" +"Extensions" +"subtraction" +"SameValueZero" +"not" +"(P," +"now" +"nor" +"execute" +"name" +"Iterator" +"U+1D11E" +"(LOW" +"unrepresentable" +"trap" +"Eliminating" +"identifier" +"|" +"subset" +"(the" +"8," +"Generic" +"non-object" +"U+0000" +"static" +"(HYPHEN-MINUS)" +"year" +"operand" +"U+0008" +"transitions" +"Parameter" +"special" +"out" +"space" +"REQUIRED" +"RegExpExec" +"Set" +"Float32Array" +"Throw" +"index." +"G" +"state" +"column" +"RFC" +"completely" +"Used" +"x" +"IMPLIED," +"byte" +"remainder" +"log" +"DATA," +"backwards" +"unescape" +"language" +"ArrayBuffer" +"@@hasInstance" +"times" +"STRICT" +"length" +"separator" +"isView" +"hexadecimal" +"first" +"clause" +"variables" +"one" +"INTERRUPTION)" +"ISO" +"suspended" +"JOINER)" +"reached" +"array" +"size" +"given" +"Runtime" +"checked" +"CURLY" +"start" +"ordering" +"Symbol" +"Date.prototype.setFullYear" +"Uint8Array" +"grow" +"their" +"SEE" +"2" +"Date" +"TypedArray" +"bits" +"final" +"HasProperty" +"destructuring" +"that" +"completed" +"exactly" +"R" +"closures" +"LETTER" +"variable." +"PDF" +"copy" +"than" +"specify" +"===" +"relative" +"later." +":" +"1;" +"depends" +"accesses" +"WHETHER" +"r" +"were" +"1)" +"accessed" +"GeneratorFunction" +"URIError" +"1," +"ArrayBuffer.prototype.slice" +"result" +"and" +"Executable" +"false" +"NEGLIGENCE" +"explicit" +"argument" +"generalization" +"Field" +"Other" +"Call" +"have" +"String.prototype.charAt" +"any" +"conversion" +"Date.prototype.setUTCMonth" +"min" +"LINE)" +"(no" +"instance" +"which" +"=" +"TRV." +"begin" +"multiple" +"Name" +"normal" +"buffer" +"callable" +"connected" +"comparison" +"inserted" +"pages" +"RIGHT" +"considered" +"request" +"Module" +"Date.prototype.toString" +"OUT" +"Date.prototype.setUTCHours" +"Export" +"ECMA-404" +"STOP)," +"Array" +"}" +"selection" +"text" +"supported" +"POSSIBILITY" +"BRACKET," +"Reflect.setPrototypeOf" +"ECMA-402" +"line" +"Math" +"slot" +"We" +"based" +"(" +"cache" +"3" +"should" +"only" +"unable" +"invocation" +"SEPARATOR)" +"b" +"local" +"WARRANTIES" +"handle" +"get" +"==" +"space," +"HEREIN" +"cannot" +"words" +"progress" +"quantifier" +"interpreted" +"neither" +"secondary" +"closure" +"Right" +"resource" +"upper" +"encounters" +"yield" +"keyed" +"EST," +"Date.prototype.getYear" +"INCLUDING" +"contain" +"Reflect.preventExtensions" +"fixed" +"where" +"view" +"SOFTWARE," +"declared" +"declarations" +"RETURN" +"computed" +"exists" +"we" +"module" +"up" +"writable" +"Source" +"(BACKSPACE)," +"legacy" +"truncating" +"receiver." +"THEORY" +"invoked" +"attribute," +"U+001F" +"pattern" +"lexical" +"label" +"outside" +"toString" +"closed" +"between" +"Reflect.getPrototypeOf" +"import" +"boundary" +"reading" +"checks" +"AVAILABLE" +"FOR" +"<NUL>" +"S" +"key" +"Identifier" +"valid" +"P," +"observable" +"revoked" +"many" +"equal" +"Month" +"propagation" +"s" +"Unicode" +"Escape" +"values)" +"MapIterator" +"expression" +"values," +"Boolean.prototype.valueOf" +"comment" +"(HYPHEN-MINUS)," +"color" +"pos" +"adding" +"table" +"allocated" +"array-like" +"IS" +"addition" +"]" +"MARK)" +"mark" +"(SPACE)," +"literal" +"(SPACE)." +"non-configurable" +"U+200D" +"prototype" +">" +"enable" +"(S," +"restrictions" +"instantiated" +"Function.prototype.apply" +"external" +"WAY" +"declaration" +"CONSEQUENTIAL" +"folding" +"Date.prototype" +"an" +"E)," +"present" +"IsArray" +"/" +"contexts" +"Number" +"value" +"will" +"(UCS)" +"J.UCS" +"ADVISED" +"unpaired" +"FEED" +"ECMA-402:" +"architecture." +"parse" +"Strict" +"PARTICULAR" +"IEEE" +"comments" +"capture" +"different" +"Return" +"compiling" +"generic" +"Typed" +"same" +"configurable" +"member" +"Regular" +"mode." +"events" +"Types" +"SOFTWARE" +"string." +"extended" +"infinity" +"again" +"initialization" +"LIABLE" +"effect" +"running" +"IN" +"changing" +"validate" +"ACM," +"U+002D" +"IF" +"//" +"undefined" +"String.prototype.trim" +"argument." +"argument," +"UTC)" +"UTC." +"It" +"<table" +"ANY" +"patterns" +"without" +"extensible" +"In" +"String.prototype.charCodeAt" +"position" +"(ZERO" +"bodies" +"If" +"BE" +"(UTC)" +"less" +"being" +"captures" +"ToInteger" +"numbering" +"rest" +"unary" +"R," +"unicode" +"BY" +"captured" +"U+212A" +"generator" +"hint" +"supply" +"unsigned" +"add" +"setting" +"extends" +"4" +"usage" +"lookup" +"(A" +"match" +"Labelled" +"identical" +"Control" +"rules" +"DIRECT," +"(inclusive)" +"non-null" +"[U]" +"immediately" +"execution" +"left-hand" +"desc" +"LIMITED" +"(EQUALS" +"missing." +"B." +"user-defined" +"Bitwise" +"MATTERS" +"BRACKET" +"t" +"CLAIMS" +"multiplicative" +"output" +"OTHERWISE)" +"page" +"replacement" +"specifies" +"because" +"sequence" +"uppercase" +"conditional" +"searching" +"calling" +"INCLUDING," +"specified" +"proper" +"New" +"Date.prototype.toTimeString" +"literals" +"lead" +"[+U]" +"avoid" +"results:" +"leap" +"does" +"\"B\"," +"CreateListFromArrayLike" +"?" +"mode" +"SQUARE" +"power" +"compiler" +"WeakMap" +"(TRV)" +"A-Z" +"offset" +"regexp" +"TRV" +"ALL" +"on" +"actual" +"extension" +"Date.prototype.valueOf" +"of" +"Date.prototype.setTime" +"recognized" +"(SV)" +"(U+00DF)" +"FL," +"constructor" +"or" +"Int32Array" +"referenced" +"letters" +"No" +"Internal" +"promise" +"Function.prototype.toString" +"Reflect.defineProperty" +"operator" +"Empty" +"Week" +"(U+017F)" +"Infinity" +"additional" +"prepare" +"NO" +"*" +"ECMA-262" +"decode" +"strict" +"context." +"SIGPLAN" +"N," +"triggered" +"enough" +"TABULATION)," +"DISCLAIMED." +"ToPrimitive" +"but" +"repeated" +"construction" +"Error" +"(RIGHT" +"N2" +"promote" +"(C," +"longer" +"count" +"1024" +"UTF-16" +"embedded" +"U+002F" +"using" +"signed" +"U+002C" +"below" +"converted" +"limit" +"MERCHANTABILITY" +"<BS>" +"define" +"detailed" +"USE" +"<CR><LF>" +"Space" +"exhausted" +"combining" +"FIFO" +"general" +"as" +"optionally" +"at" +"file" +"Reflect.deleteProperty" +"trailing" +"Function" +"parameters." +"functions" +"beyond" +"Date.prototype.setUTCDate" +"virtual" +"Reflect" +"field" +"other" +"5" +"details" +"<<" +"requested" +"repeat" +"Uint8ClampedArray" +"separate" +"symbol" +"Remove" +"U" +"functions)" +"(DOLLAR" +"Object.prototype" +"calls" +"code," +"(INCLUDING" +"rule" +"strings" +"code." +"Year" +"(URL)," +"validation" +"starting" +"function,"
diff --git a/testing/libfuzzer/fuzzers/dicts/js.dict b/testing/libfuzzer/fuzzers/dicts/js.dict deleted file mode 100644 index f3a0f6c5..0000000 --- a/testing/libfuzzer/fuzzers/dicts/js.dict +++ /dev/null
@@ -1,115 +0,0 @@ -# -# AFL dictionary for JavaScript -# ----------------------------- -# -# Contains basic reserved keywords and syntax building blocks. -# -# Created by Michal Zalewski <lcamtuf@google.com> -# - -keyword_arguments="arguments" -keyword_break="break" -keyword_case="case" -keyword_catch="catch" -keyword_const="const" -keyword_continue="continue" -keyword_debugger="debugger" -keyword_decodeURI="decodeURI" -keyword_default="default" -keyword_delete="delete" -keyword_do="do" -keyword_else="else" -keyword_escape="escape" -keyword_eval="eval" -keyword_export="export" -keyword_finally="finally" -keyword_for="for (a=0;a<2;a++)" -keyword_function="function" -keyword_if="if" -keyword_in="in" -keyword_instanceof="instanceof" -keyword_isNaN="isNaN" -keyword_let="let" -keyword_new="new" -keyword_parseInt="parseInt" -keyword_return="return" -keyword_super="super" -keyword_switch="switch" -keyword_this="this" -keyword_throw="throw" -keyword_try="try" -keyword_typeof="typeof" -keyword_var="var" -keyword_void="void" -keyword_while="while" -keyword_with="with" - -misc_1=" 1" -misc_a="a" -misc_array=" [1]" -misc_assign=" a=1" -misc_code_block=" {1}" -misc_colon_num=" 1:" -misc_colon_string=" 'a':" -misc_comma=" ," -misc_comment_block=" /* */" -misc_comment_line=" //" -misc_cond=" 1?2:3" -misc_dec=" --" -misc_div=" /" -misc_equals=" =" -misc_fn=" a()" -misc_identical=" ===" -misc_inc=" ++" -misc_minus=" -" -misc_modulo=" %" -misc_parentheses=" ()" -misc_parentheses_1=" (1)" -misc_parentheses_1x4=" (1,1,1,1)" -misc_parentheses_a=" (a)" -misc_period="." -misc_plus=" +" -misc_plus_assign=" +=" -misc_regex=" /a/g" -misc_rol=" <<<" -misc_semicolon=" ;" -misc_serialized_object=" {'a': 1}" -misc_string=" 'a'" -misc_unicode=" '\\u0001'" -misc_shl=" <<" -misc_shr=" >>" -misc_sae=" >>>" -misc_bit_or=" |" -misc_bit_and=" &" -misc_bit_xor=" ^" -misc_bit_not=" ~" - -object_Array=" Array" -object_Boolean=" Boolean" -object_Date=" Date" -object_Function=" Function" -object_Infinity=" Infinity" -object_Int8Array=" Int8Array" -object_Math=" Math" -object_NaN=" NaN" -object_Number=" Number" -object_Object=" Object" -object_RegExp=" RegExp" -object_String=" String" -object_Symbol=" Symbol" -object_false=" false" -object_null=" null" -object_true=" true" - -prop_charAt=".charAt" -prop_concat=".concat" -prop_constructor=".constructor" -prop_destructor=".destructor" -prop_length=".length" -prop_match=".match" -prop_proto=".__proto__" -prop_prototype=".prototype" -prop_slice=".slice" -prop_toCode=".toCode" -prop_toString=".toString" -prop_valueOf=".valueOf"
diff --git a/testing/libfuzzer/fuzzers/dicts/sql.dict b/testing/libfuzzer/fuzzers/dicts/sql.dict deleted file mode 100644 index bf522cc4..0000000 --- a/testing/libfuzzer/fuzzers/dicts/sql.dict +++ /dev/null
@@ -1,282 +0,0 @@ -# -# AFL dictionary for SQL -# ---------------------- -# -# Modeled based on SQLite documentation, contains some number of SQLite -# extensions. Other dialects of SQL may benefit from customized dictionaries. -# -# If you append @1 to the file name when loading this dictionary, afl-fuzz -# will also additionally load a selection of pragma keywords that are very -# specific to SQLite (and are probably less interesting from the security -# standpoint, because they are usually not allowed in non-privileged -# contexts). -# -# Created by Michal Zalewski <lcamtuf@google.com> -# - -function_abs=" abs(1)" -function_avg=" avg(1)" -function_changes=" changes()" -function_char=" char(1)" -function_coalesce=" coalesce(1,1)" -function_count=" count(1)" -function_date=" date(1,1,1)" -function_datetime=" datetime(1,1,1)" -function_decimal=" decimal(1,1)" -function_glob=" glob(1,1)" -function_group_concat=" group_concat(1,1)" -function_hex=" hex(1)" -function_ifnull=" ifnull(1,1)" -function_instr=" instr(1,1)" -function_julianday=" julianday(1,1,1)" -function_last_insert_rowid=" last_insert_rowid()" -function_length=" length(1)" -function_like=" like(1,1)" -function_likelihood=" likelihood(1,1)" -function_likely=" likely(1)" -function_load_extension=" load_extension(1,1)" -function_lower=" lower(1)" -function_ltrim=" ltrim(1,1)" -function_max=" max(1,1)" -function_min=" min(1,1)" -function_nullif=" nullif(1,1)" -function_printf=" printf(1,1)" -function_quote=" quote(1)" -function_random=" random()" -function_randomblob=" randomblob(1)" -function_replace=" replace(1,1,1)" -function_round=" round(1,1)" -function_rtrim=" rtrim(1,1)" -function_soundex=" soundex(1)" -function_sqlite_compileoption_get=" sqlite_compileoption_get(1)" -function_sqlite_compileoption_used=" sqlite_compileoption_used(1)" -function_sqlite_source_id=" sqlite_source_id()" -function_sqlite_version=" sqlite_version()" -function_strftime=" strftime(1,1,1,1)" -function_substr=" substr(1,1,1)" -function_sum=" sum(1)" -function_time=" time(1,1,1)" -function_total=" total(1)" -function_total_changes=" total_changes()" -function_trim=" trim(1,1)" -function_typeof=" typeof(1)" -function_unicode=" unicode(1)" -function_unlikely=" unlikely(1)" -function_upper=" upper(1)" -function_varchar=" varchar(1)" -function_zeroblob=" zeroblob(1)" - -keyword_ABORT="ABORT" -keyword_ACTION="ACTION" -keyword_ADD="ADD" -keyword_AFTER="AFTER" -keyword_ALL="ALL" -keyword_ALTER="ALTER" -keyword_ANALYZE="ANALYZE" -keyword_AND="AND" -keyword_AS="AS" -keyword_ASC="ASC" -keyword_ATTACH="ATTACH" -keyword_AUTOINCREMENT="AUTOINCREMENT" -keyword_BEFORE="BEFORE" -keyword_BEGIN="BEGIN" -keyword_BETWEEN="BETWEEN" -keyword_BY="BY" -keyword_CASCADE="CASCADE" -keyword_CASE="CASE" -keyword_CAST="CAST" -keyword_CHECK="CHECK" -keyword_COLLATE="COLLATE" -keyword_COLUMN="COLUMN" -keyword_COMMIT="COMMIT" -keyword_CONFLICT="CONFLICT" -keyword_CONSTRAINT="CONSTRAINT" -keyword_CREATE="CREATE" -keyword_CROSS="CROSS" -keyword_CURRENT_DATE="CURRENT_DATE" -keyword_CURRENT_TIME="CURRENT_TIME" -keyword_CURRENT_TIMESTAMP="CURRENT_TIMESTAMP" -keyword_DATABASE="DATABASE" -keyword_DEFAULT="DEFAULT" -keyword_DEFERRABLE="DEFERRABLE" -keyword_DEFERRED="DEFERRED" -keyword_DELETE="DELETE" -keyword_DESC="DESC" -keyword_DETACH="DETACH" -keyword_DISTINCT="DISTINCT" -keyword_DROP="DROP" -keyword_EACH="EACH" -keyword_ELSE="ELSE" -keyword_END="END" -keyword_ESCAPE="ESCAPE" -keyword_EXCEPT="EXCEPT" -keyword_EXCLUSIVE="EXCLUSIVE" -keyword_EXISTS="EXISTS" -keyword_EXPLAIN="EXPLAIN" -keyword_FAIL="FAIL" -keyword_FOR="FOR" -keyword_FOREIGN="FOREIGN" -keyword_FROM="FROM" -keyword_FULL="FULL" -keyword_GLOB="GLOB" -keyword_GROUP="GROUP" -keyword_HAVING="HAVING" -keyword_IF="IF" -keyword_IGNORE="IGNORE" -keyword_IMMEDIATE="IMMEDIATE" -keyword_IN="IN" -keyword_INDEX="INDEX" -keyword_INDEXED="INDEXED" -keyword_INITIALLY="INITIALLY" -keyword_INNER="INNER" -keyword_INSERT="INSERT" -keyword_INSTEAD="INSTEAD" -keyword_INTERSECT="INTERSECT" -keyword_INTO="INTO" -keyword_IS="IS" -keyword_ISNULL="ISNULL" -keyword_JOIN="JOIN" -keyword_KEY="KEY" -keyword_LEFT="LEFT" -keyword_LIKE="LIKE" -keyword_LIMIT="LIMIT" -keyword_MATCH="MATCH" -keyword_NATURAL="NATURAL" -keyword_NO="NO" -keyword_NOT="NOT" -keyword_NOTNULL="NOTNULL" -keyword_NULL="NULL" -keyword_OF="OF" -keyword_OFFSET="OFFSET" -keyword_ON="ON" -keyword_OR="OR" -keyword_ORDER="ORDER" -keyword_OUTER="OUTER" -keyword_PLAN="PLAN" -keyword_PRAGMA="PRAGMA" -keyword_PRIMARY="PRIMARY" -keyword_QUERY="QUERY" -keyword_RAISE="RAISE" -keyword_RECURSIVE="RECURSIVE" -keyword_REFERENCES="REFERENCES" -#keyword_REGEXP="REGEXP" -keyword_REINDEX="REINDEX" -keyword_RELEASE="RELEASE" -keyword_RENAME="RENAME" -keyword_REPLACE="REPLACE" -keyword_RESTRICT="RESTRICT" -keyword_RIGHT="RIGHT" -keyword_ROLLBACK="ROLLBACK" -keyword_ROW="ROW" -keyword_SAVEPOINT="SAVEPOINT" -keyword_SELECT="SELECT" -keyword_SET="SET" -keyword_TABLE="TABLE" -keyword_TEMP="TEMP" -keyword_TEMPORARY="TEMPORARY" -keyword_THEN="THEN" -keyword_TO="TO" -keyword_TRANSACTION="TRANSACTION" -keyword_TRIGGER="TRIGGER" -keyword_UNION="UNION" -keyword_UNIQUE="UNIQUE" -keyword_UPDATE="UPDATE" -keyword_USING="USING" -keyword_VACUUM="VACUUM" -keyword_VALUES="VALUES" -keyword_VIEW="VIEW" -keyword_VIRTUAL="VIRTUAL" -keyword_WHEN="WHEN" -keyword_WHERE="WHERE" -keyword_WITH="WITH" -keyword_WITHOUT="WITHOUT" - -operator_concat=" || " -operator_ebove_eq=" >=" - -snippet_1eq1=" 1=1" -snippet_at=" @1" -snippet_backticks=" `a`" -snippet_blob=" blob" -snippet_brackets=" [a]" -snippet_colon=" :1" -snippet_comment=" /* */" -snippet_date="2001-01-01" -snippet_dollar=" $1" -snippet_dotref=" a.b" -snippet_fmtY="%Y" -snippet_int=" int" -snippet_neg1=" -1" -snippet_pair=" a,b" -snippet_parentheses=" (1)" -snippet_plus2days="+2 days" -snippet_qmark=" ?1" -snippet_semicolon=" ;" -snippet_star=" *" -snippet_string_pair=" \"a\",\"b\"" - -string_dbl_q=" \"a\"" -string_escaped_q=" 'a''b'" -string_single_q=" 'a'" - -pragma_application_id@1=" application_id" -pragma_auto_vacuum@1=" auto_vacuum" -pragma_automatic_index@1=" automatic_index" -pragma_busy_timeout@1=" busy_timeout" -pragma_cache_size@1=" cache_size" -pragma_cache_spill@1=" cache_spill" -pragma_case_sensitive_like@1=" case_sensitive_like" -pragma_checkpoint_fullfsync@1=" checkpoint_fullfsync" -pragma_collation_list@1=" collation_list" -pragma_compile_options@1=" compile_options" -pragma_count_changes@1=" count_changes" -pragma_data_store_directory@1=" data_store_directory" -pragma_database_list@1=" database_list" -pragma_default_cache_size@1=" default_cache_size" -pragma_defer_foreign_keys@1=" defer_foreign_keys" -pragma_empty_result_callbacks@1=" empty_result_callbacks" -pragma_encoding@1=" encoding" -pragma_foreign_key_check@1=" foreign_key_check" -pragma_foreign_key_list@1=" foreign_key_list" -pragma_foreign_keys@1=" foreign_keys" -pragma_freelist_count@1=" freelist_count" -pragma_full_column_names@1=" full_column_names" -pragma_fullfsync@1=" fullfsync" -pragma_ignore_check_constraints@1=" ignore_check_constraints" -pragma_incremental_vacuum@1=" incremental_vacuum" -pragma_index_info@1=" index_info" -pragma_index_list@1=" index_list" -pragma_integrity_check@1=" integrity_check" -pragma_journal_mode@1=" journal_mode" -pragma_journal_size_limit@1=" journal_size_limit" -pragma_legacy_file_format@1=" legacy_file_format" -pragma_locking_mode@1=" locking_mode" -pragma_max_page_count@1=" max_page_count" -pragma_mmap_size@1=" mmap_size" -pragma_page_count@1=" page_count" -pragma_page_size@1=" page_size" -pragma_parser_trace@1=" parser_trace" -pragma_query_only@1=" query_only" -pragma_quick_check@1=" quick_check" -pragma_read_uncommitted@1=" read_uncommitted" -pragma_recursive_triggers@1=" recursive_triggers" -pragma_reverse_unordered_selects@1=" reverse_unordered_selects" -pragma_schema_version@1=" schema_version" -pragma_secure_delete@1=" secure_delete" -pragma_short_column_names@1=" short_column_names" -pragma_shrink_memory@1=" shrink_memory" -pragma_soft_heap_limit@1=" soft_heap_limit" -pragma_stats@1=" stats" -pragma_synchronous@1=" synchronous" -pragma_table_info@1=" table_info" -pragma_temp_store@1=" temp_store" -pragma_temp_store_directory@1=" temp_store_directory" -pragma_threads@1=" threads" -pragma_user_version@1=" user_version" -pragma_vdbe_addoptrace@1=" vdbe_addoptrace" -pragma_vdbe_debug@1=" vdbe_debug" -pragma_vdbe_listing@1=" vdbe_listing" -pragma_vdbe_trace@1=" vdbe_trace" -pragma_wal_autocheckpoint@1=" wal_autocheckpoint" -pragma_wal_checkpoint@1=" wal_checkpoint" -pragma_writable_schema@1=" writable_schema"
diff --git a/testing/libfuzzer/zip_sources.py b/testing/libfuzzer/zip_sources.py index 5220262..946a7de 100755 --- a/testing/libfuzzer/zip_sources.py +++ b/testing/libfuzzer/zip_sources.py
@@ -6,7 +6,7 @@ """Archive all source files that are references in binary debug info. -Invoked by libfuzzer buildbots. Executes llvm-dwarfdump to parse debug info. +Invoked by libfuzzer buildbots. Executes dwarfdump to parse debug info. """ from __future__ import print_function @@ -18,7 +18,7 @@ import zipfile compile_unit_re = re.compile('.*DW_TAG_compile_unit.*') -at_name_re = re.compile('.*DW_AT_name.*debug_str\[.*\] = "(.*)".*') +at_name_re = re.compile('.*DW_AT_name.*"(.*)".*') def main(): @@ -27,15 +27,17 @@ help='binary file to read') parser.add_argument('--workdir', required=True, help='working directory to use to resolve relative paths') + parser.add_argument('--srcdir', required=True, + help='sources root directory to calculate zip entry names') parser.add_argument('--output', required=True, help='output zip file name') - parser.add_argument('--llvm-dwarfdump', required=False, - default='llvm-dwarfdump', help='path to llvm-dwarfdump utility') + parser.add_argument('--dwarfdump', required=False, + default='dwarfdump', help='path to dwarfdump utility') args = parser.parse_args() # Dump .debug_info section. out = subprocess.check_output( - [args.llvm_dwarfdump, '-debug-dump=info', args.binary]) + [args.dwarfdump, '-i', args.binary]) looking_for_unit = True compile_units = set() @@ -55,7 +57,7 @@ for compile_unit in sorted(compile_units): src_file = os.path.abspath(os.path.join(args.workdir, compile_unit)) print(src_file) - z.write(src_file, compile_unit) + z.write(src_file, os.path.relpath(src_file, args.srcdir)) if __name__ == '__main__':
diff --git a/testing/variations/fieldtrial_testing_config_linux.json b/testing/variations/fieldtrial_testing_config_linux.json index 8d935a4..053e69a 100644 --- a/testing/variations/fieldtrial_testing_config_linux.json +++ b/testing/variations/fieldtrial_testing_config_linux.json
@@ -128,6 +128,14 @@ "group_name": "Enabled" } ], + "NonValidatingReloadOnNormalReload": [ + { + "enable_features": [ + "NonValidatingReloadOnNormalReload" + ], + "group_name": "Enabled" + } + ], "OfferUploadCreditCards": [ { "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_mac.json b/testing/variations/fieldtrial_testing_config_mac.json index d79521bd..a7d2d8f3 100644 --- a/testing/variations/fieldtrial_testing_config_mac.json +++ b/testing/variations/fieldtrial_testing_config_mac.json
@@ -165,6 +165,14 @@ "group_name": "Enabled" } ], + "NonValidatingReloadOnNormalReload": [ + { + "enable_features": [ + "NonValidatingReloadOnNormalReload" + ], + "group_name": "Enabled" + } + ], "OfferUploadCreditCards": [ { "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_win.json b/testing/variations/fieldtrial_testing_config_win.json index a30a5cc..72b2a5c 100644 --- a/testing/variations/fieldtrial_testing_config_win.json +++ b/testing/variations/fieldtrial_testing_config_win.json
@@ -203,6 +203,14 @@ "group_name": "Enabled" } ], + "NonValidatingReloadOnNormalReload": [ + { + "enable_features": [ + "NonValidatingReloadOnNormalReload" + ], + "group_name": "Enabled" + } + ], "OfferUploadCreditCards": [ { "group_name": "Enabled"
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation index 5d35887..63162016 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -11,10 +11,7 @@ fast/forms/xss-auditor-doesnt-crash-on-post-submit.html [ Timeout ] fast/loader/form-state-restore-with-frames.html [ Failure ] http/tests/history/back-to-post.html [ Timeout ] - http/tests/history/post-replace-state-reload.html [ Crash Failure ] - http/tests/navigation/location-reload-after-post.php [ Crash Failure ] http/tests/navigation/post-goback-same-url.html [ Failure ] - http/tests/security/xssAuditor/script-tag-post-redirect.html [ Failure ] # Failing due to error page supression in layout tests fast/xmlhttprequest/null-document-xmlhttprequest-open.html [ Crash Timeout ] @@ -46,6 +43,7 @@ fast/history/same-document-iframes-changing-pushstate.html [ Failure ] http/tests/history/cross-origin-redirect-on-back.html [ Crash ] http/tests/navigation/back-to-dynamic-iframe.html [ Failure Crash ] + http/tests/navigation/back-to-redirect-with-frame.php [ Failure ] http/tests/navigation/history-back-across-form-submission-to-fragment.html [ Timeout ] http/tests/navigation/redirect-on-reload-updates-history-item.html [ Failure ] http/tests/navigation/same-and-different-back.html [ Crash ] @@ -84,23 +82,34 @@ http/tests/w3c/webperf/submission/Intel/resource-timing/test_resource_timing_same_origin_redirect.html [ Timeout ] imported/wpt/web-animations/animation-timeline/document-timeline.html [ Failure ] +# https://crbug.com/625765: Need to solve duplicate output from +# WebFrameTestClient::willSendRequest() that causes text failures. + http/tests/history/post-replace-state-reload.html [ Failure ] + http/tests/navigation/location-reload-after-post.php [ Failure ] + http/tests/security/xssAuditor/script-tag-post-redirect.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-allowall.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-deny.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-invalid.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-multiple-headers-conflict.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-allow.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-none.html [ Failure ] + http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-allow.html [ Failure ] + fast/loader/main-document-url-for-non-http-loads.html [ Failure ] + http/tests/cache/iframe-304-crash.html [ Failure ] + http/tests/security/frame-loading-via-document-write.html [ Failure ] + imported/wpt/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html [ Failure ] + mhtml/multi_frames_contentid.mht [ Timeout Failure ] + # https://crbug.com/555418: Move `X-Frame-Options` and CSP's `frame-ancestor` # checks up out of the renderer. http/tests/security/contentSecurityPolicy/1.1/child-src/frame-redirect-blocked.html [ Timeout ] http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked.html [ Failure ] http/tests/security/contentSecurityPolicy/frame-src-redirect-blocked.html [ Timeout ] http/tests/security/contentSecurityPolicy/redirect-does-not-match-paths.html [ Timeout ] - http/tests/security/XFrameOptions/x-frame-options-allowall.html [ Failure ] http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-in-body.html [ Failure ] http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-allow.html [ Failure ] http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag-parent-same-origin-deny.html [ Failure ] http/tests/security/XFrameOptions/x-frame-options-deny-meta-tag.html [ Failure ] - http/tests/security/XFrameOptions/x-frame-options-deny.html [ Failure Crash ] - http/tests/security/XFrameOptions/x-frame-options-invalid.html [ Failure ] - http/tests/security/XFrameOptions/x-frame-options-multiple-headers-conflict.html [ Failure Crash ] - http/tests/security/XFrameOptions/x-frame-options-multiple-headers-sameorigin-allow.html [ Failure Crash ] - http/tests/security/XFrameOptions/x-frame-options-none.html [ Failure ] - http/tests/security/XFrameOptions/x-frame-options-parent-same-origin-allow.html [ Failure ] # https://crbug.com/576270: Move mixed-content checks that happen during # navigation to the browser @@ -119,13 +128,10 @@ # Untriaged navigation compositing/gestures/gesture-tapHighlight-simple-navigate.html [ Failure ] - fast/dom/location-new-window-no-crash.html [ Crash ] fast/loader/document-destruction-within-unload.html [ Crash ] - fast/loader/main-document-url-for-non-http-loads.html [ Failure ] fast/loader/scroll-position-restored-on-reload-at-load-event.html [ Failure ] fast/loader/stateobjects/pushstate-with-fragment-urls-and-hashchange.html [ Crash Timeout ] fast/loader/subframe-removes-itself.html [ Failure ] - http/tests/cache/iframe-304-crash.html [ Crash Failure ] http/tests/cache/smil-usecounter-in-cached-image.html [ Failure ] http/tests/cookies/same-site/popup-same-site-post.html [ Failure ] http/tests/cookies/same-site/popup-same-site.html [ Failure ] @@ -139,7 +145,6 @@ http/tests/loading/redirect-with-no-location-crash.html [ Failure ] http/tests/loading/slow-parsing-subframe.html [ Failure ] http/tests/loading/text-content-type-with-binary-extension.html [ Timeout Failure ] - http/tests/navigation/back-to-redirect-with-frame.php [ Failure ] http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] http/tests/navigation/forward-to-fragment-fires-onload.html [ Timeout ] http/tests/navigation/response204.html [ Timeout ] @@ -150,7 +155,6 @@ http/tests/navigation/scrollstate-after-location-reload.html [ Timeout ] # Untriaged security - http/tests/security/frame-loading-via-document-write.html [ Failure ] http/tests/security/isolatedWorld/bypass-main-world-csp-iframes.html [ Failure ] # Untriaged other @@ -169,8 +173,6 @@ http/tests/misc/window-dot-stop.html [ Failure ] http/tests/misc/window-open-then-write.html [ Timeout ] imported/wpt/html/semantics/embedded-content/the-object-element/object-attributes.html [ Failure ] - imported/wpt/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-003.html [ Failure ] - mhtml/multi_frames_contentid.mht [ Timeout Failure ] plugins/object-onfocus-mutation-crash.html [ Timeout ] svg/custom/anchor-on-use.svg [ Failure ] svg/dynamic-updates/SVGAElement-dom-href-attr.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index 74ca9aa..9d84010 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -302,8 +302,8 @@ compositing/masks/masked-ancestor.html [ Failure ] compositing/masks/multiple-masks.html [ Failure ] compositing/masks/simple-composited-mask.html [ Failure ] -compositing/overflow-trumps-transform-style.html [ Failure ] compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure ] +compositing/overflow/accelerated-scrolling-with-clip-path-text.html [ Failure ] compositing/overflow/accelerated-scrolling-with-clip-path.html [ Failure ] compositing/overflow/ancestor-with-clip-path.html [ Failure ] compositing/overflow/avoid-ancestor-clip-for-scroll-children.html [ Failure ] @@ -326,8 +326,6 @@ compositing/overflow/overflow-scaled-descendant-overlapping.html [ Crash Timeout ] compositing/overflow/overflow-scroll-with-pointer-events-toggle.html [ Failure ] compositing/overflow/overflow-scrollbar-layers.html [ Failure ] -compositing/overflow/reflected-overlay-scrollbars-should-appear-without-compositing.html [ Crash ] -compositing/overflow/reflected-overlay-scrollbars-should-respect-ancestor-clip.html [ Crash ] compositing/overflow/reparented-scrollbars-non-sc-anc.html [ Failure ] compositing/overflow/resize-painting.html [ Failure ] compositing/overflow/scroll-ancestor-update.html [ Failure ] @@ -340,48 +338,40 @@ compositing/overflow/selection-gaps-after-removing-scrolling-contents.html [ Failure ] compositing/overflow/selection-gaps-toggling-with-scrolling-contents.html [ Failure ] compositing/overflow/selection-gaps-toggling.html [ Failure ] -compositing/overflow/text-color-change.html [ Failure ] compositing/overflow/text-match-highlight.html [ Failure ] compositing/overflow/textarea-scroll-touch.html [ Failure ] compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure ] -compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Crash ] compositing/overflow/updating-scrolling-container-and-content.html [ Failure ] -compositing/overflow/updating-scrolling-container.html [ Failure ] compositing/overflow/updating-scrolling-content.html [ Failure ] -compositing/overlap-blending/reflection-opacity-huge.html [ Crash ] compositing/overlap-test-with-filter.html [ Failure ] compositing/perpendicular-layer-sorting.html [ Failure ] -compositing/plugins/webplugin-reflection.html [ Crash ] +compositing/plugins/webplugin-reflection.html [ Failure ] compositing/preserve-3d-toggle.html [ Failure ] -compositing/reflections/animation-inside-reflection.html [ Crash ] -compositing/reflections/backface-hidden-reflection.html [ Crash ] -compositing/reflections/become-simple-composited-reflection.html [ Crash ] -compositing/reflections/compositing-change-inside-reflection.html [ Crash ] -compositing/reflections/deeply-nested-reflections.html [ Crash ] -compositing/reflections/empty-reflection-with-mask.html [ Crash ] -compositing/reflections/enable-disable-compositing-reflection.html [ Crash ] -compositing/reflections/load-video-in-reflection.html [ Crash ] -compositing/reflections/masked-reflection-on-composited.html [ Crash ] -compositing/reflections/nested-reflection-anchor-point.html [ Crash ] -compositing/reflections/nested-reflection-animated.html [ Crash ] -compositing/reflections/nested-reflection-mask-change.html [ Crash ] -compositing/reflections/nested-reflection-on-overflow.html [ Crash ] -compositing/reflections/nested-reflection-opacity.html [ Crash ] -compositing/reflections/nested-reflection-size-change.html [ Crash ] -compositing/reflections/nested-reflection-transformed.html [ Crash ] -compositing/reflections/nested-reflection-transformed2.html [ Crash ] -compositing/reflections/nested-reflection-transition.html [ Crash ] -compositing/reflections/nested-reflection.html [ Crash ] -compositing/reflections/reflection-in-composited.html [ Crash ] -compositing/reflections/reflection-on-composited.html [ Crash ] -compositing/reflections/reflection-opacity.html [ Crash ] -compositing/reflections/reflection-ordering.html [ Crash ] -compositing/reflections/reflection-positioning.html [ Crash ] -compositing/reflections/reflection-positioning2.html [ Crash ] -compositing/reflections/remove-add-reflection.html [ Crash ] -compositing/reflections/remove-reflection.html [ Crash ] -compositing/reflections/simple-composited-reflections.html [ Crash ] -compositing/reflections/transform-inside-reflection.html [ Crash ] +compositing/reflections/animation-inside-reflection.html [ Failure ] +compositing/reflections/compositing-change-inside-reflection.html [ Failure ] +compositing/reflections/deeply-nested-reflections.html [ Failure ] +compositing/reflections/enable-disable-compositing-reflection.html [ Failure ] +compositing/reflections/load-video-in-reflection.html [ Failure ] +compositing/reflections/masked-reflection-on-composited.html [ Failure ] +compositing/reflections/nested-reflection-anchor-point.html [ Failure ] +compositing/reflections/nested-reflection-animated.html [ Failure ] +compositing/reflections/nested-reflection-mask-change.html [ Failure ] +compositing/reflections/nested-reflection-on-overflow.html [ Failure ] +compositing/reflections/nested-reflection-opacity.html [ Failure ] +compositing/reflections/nested-reflection-size-change.html [ Failure ] +compositing/reflections/nested-reflection-transformed.html [ Failure ] +compositing/reflections/nested-reflection-transformed2.html [ Failure ] +compositing/reflections/nested-reflection-transition.html [ Failure ] +compositing/reflections/nested-reflection.html [ Failure ] +compositing/reflections/reflection-in-composited.html [ Failure ] +compositing/reflections/reflection-on-composited.html [ Failure ] +compositing/reflections/reflection-opacity.html [ Failure ] +compositing/reflections/reflection-ordering.html [ Failure ] +compositing/reflections/reflection-positioning.html [ Failure ] +compositing/reflections/reflection-positioning2.html [ Failure ] +compositing/reflections/remove-add-reflection.html [ Failure ] +compositing/reflections/simple-composited-reflections.html [ Failure ] +compositing/reflections/transform-inside-reflection.html [ Failure ] compositing/render-surface-alpha-blending.html [ Failure ] compositing/rendering-contexts.html [ Failure ] compositing/repaint/become-overlay-composited-layer.html [ Failure ] @@ -465,16 +455,13 @@ compositing/squashing/squash-transform-repainting-child.html [ Failure ] compositing/squashing/squash-transform-repainting-transformed-child.html [ Failure ] compositing/squashing/squash-transform.html [ Failure ] -compositing/squashing/squash-with-ancestor-reflection.html [ Crash ] compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ] compositing/squashing/squashed-repaints.html [ Failure ] compositing/squashing/squashing-inside-perspective.html [ Failure ] compositing/squashing/squashing-inside-preserve-3d-element.html [ Failure ] compositing/squashing/squashing-print.html [ Crash Timeout ] -compositing/squashing/squashing-reflection-disallowed.html [ Crash ] compositing/squashing/squashing-sparsity-heuristic.html [ Failure ] compositing/squashing/tricky-element-removal-crash.html [ Failure ] -compositing/squashing/vertical-writing-mode-squashed.html [ Failure ] compositing/tiled-layers-hidpi.html [ Failure ] compositing/transitions/scale-transition-no-start.html [ Failure ] compositing/update-paint-phases.html [ Failure ] @@ -491,13 +478,12 @@ compositing/visibility/visibility-simple-webgl-layer.html [ Failure ] compositing/webgl/webgl-no-alpha.html [ Failure ] compositing/webgl/webgl-nonpremultiplied-blend.html [ Failure ] -compositing/webgl/webgl-reflection.html [ Crash ] +compositing/webgl/webgl-reflection.html [ Failure ] compositing/webgl/webgl-repaint.html [ Failure ] compositing/webgl/webgl-with-accelerated-background-color.html [ Failure ] compositing/will-change/composited-layers.html [ Failure ] compositing/will-change/containing-block-added.html [ Failure ] compositing/will-change/containing-block-removed.html [ Failure ] -compositing/writing-mode-rl-overflow.html [ Failure ] fast/backgrounds/animated-svg-as-mask.html [ Failure ] fast/backgrounds/background-inherit-color-bug.html [ Failure ] fast/backgrounds/background-leakage-transforms.html [ Failure ] @@ -1703,44 +1689,22 @@ svg/animations/animateMotion-accumulate-2a.svg [ Failure ] svg/animations/animateMotion-accumulate-2b.svg [ Failure ] svg/animations/filter-primitive-region.html [ Failure ] -svg/animations/mozilla/animateMotion-by-1.svg [ Failure ] -svg/animations/mozilla/animateMotion-from-to-1.svg [ Failure ] -svg/as-background-image/animated-svg-as-background.html [ Crash ] svg/as-background-image/svg-transformed-background.html [ Failure ] svg/as-background-image/tiled-background-image.html [ Crash Timeout ] -svg/as-image/animated-svg-as-image-visited-link.html [ Crash ] svg/as-image/default-font-settings-external.html [ Failure ] svg/as-image/default-font-size.html [ Failure ] svg/as-image/default-monospace-font.html [ Failure ] svg/as-image/default-sans-serif-font.html [ Failure ] -svg/as-image/image-change-with-equal-sizes.html [ Crash ] svg/as-image/image-preserveAspectRatio-all.svg [ Failure ] svg/as-image/image-respects-pageScaleFactor.html [ Crash Timeout ] svg/as-image/img-preserveAspectRatio-support-1.html [ Failure ] svg/as-image/img-preserveAspectRatio-support-2.html [ Failure ] -svg/as-image/smil-usecounter-in-css-image.html [ Crash ] -svg/as-image/svg-as-image-canvas.html [ Crash ] -svg/as-image/svg-as-image-intrinsic-size.html [ Crash ] svg/as-image/svg-as-image-object-fit-cover.html [ Failure ] -svg/as-image/svg-as-image-with-relative-size.html [ Failure ] -svg/as-image/svg-canvas-link-not-colored.html [ Crash ] -svg/as-image/svg-canvas-not-tainted.html [ Crash ] -svg/as-image/svg-canvas-svg-with-image-with-link-tainted.html [ Crash ] -svg/as-image/svg-canvas-xhtml-tainted.html [ Crash ] -svg/as-image/svg-image-leak-cached-data.html [ Crash ] -svg/as-image/svg-image-with-css-animation.html [ Crash ] -svg/as-image/svg-image-with-data-uri.html [ Failure ] -svg/as-image/svg-image-with-nested-data-uri.html [ Crash Failure ] svg/as-image/svgview-references.html [ Failure ] -svg/as-list-image/svg-list-image-intrinsic-size-zoom.html [ Crash ] -svg/as-object/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] -svg/as-object/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] svg/as-object/embedded-svg-immediate-offsetWidth-query.html [ Failure ] -svg/as-object/embedded-svg-size-changes-no-layout-triggers.html [ Failure ] svg/as-object/embedded-svg-size-changes.html [ Failure ] svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] svg/as-object/nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] -svg/as-object/nested-embedded-svg-size-changes.html [ Failure ] svg/as-object/object-box-sizing-no-width-height.html [ Failure ] svg/batik/filters/feTile.svg [ Failure ] svg/batik/filters/filterRegions.svg [ Failure ] @@ -1751,7 +1715,7 @@ svg/batik/paints/patternRegions-positioned-objects.svg [ Failure ] svg/batik/paints/patternRegions.svg [ Failure ] svg/batik/text/longTextOnPath.svg [ Failure Timeout ] -svg/batik/text/smallFonts.svg [ Failure ] +svg/batik/text/smallFonts.svg [ Failure Timeout ] svg/batik/text/textAnchor.svg [ Failure ] svg/batik/text/textAnchor2.svg [ Failure ] svg/batik/text/textAnchor3.svg [ Failure ] @@ -1778,14 +1742,7 @@ svg/batik/text/verticalText.svg [ Failure ] svg/batik/text/verticalTextOnPath.svg [ Failure ] svg/batik/text/xmlSpace.svg [ Failure ] -svg/canvas/canvas-default-object-sizing.html [ Crash ] -svg/canvas/canvas-draw-image-globalalpha.html [ Crash ] -svg/canvas/canvas-draw-image-size.html [ Crash ] -svg/canvas/canvas-draw-image-svg-fragment.html [ Crash ] -svg/canvas/canvas-draw-pattern-size.html [ Crash ] svg/canvas/canvas-draw-pattern-svg-fragment.html [ Crash Timeout ] -svg/canvas/canvas-pattern-svg.html [ Crash ] -svg/canvas/image-svg-intrinsic-size.html [ Crash ] svg/carto.net/button.svg [ Failure ] svg/carto.net/colourpicker.svg [ Failure ] svg/carto.net/combobox.svg [ Failure ] @@ -1844,7 +1801,6 @@ svg/clip-path/nested-clip-in-mask-path-based-clipping.svg [ Failure ] svg/clip-path/opacity-assertion.svg [ Failure ] svg/clip-path/transformed-clip.svg [ Failure ] -svg/css/css-box-min-width.html [ Failure ] svg/css/path-gradient-stroke-shadow.svg [ Failure ] svg/css/rect-gradient-stroke-shadow.svg [ Failure ] svg/css/svg-resource-fragment-identifier-img-src.html [ Crash Timeout ] @@ -1899,7 +1855,6 @@ svg/custom/font-face-cascade-order.svg [ Failure ] svg/custom/foreign-object-skew.svg [ Failure ] svg/custom/foreignObject-crash-on-hover.xml [ Failure ] -svg/custom/foreignObject-font-size-on-zoom.html [ Failure ] svg/custom/fractional-rects.svg [ Failure ] svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Failure ] svg/custom/getscreenctm-in-scrollable-div-area.xhtml [ Failure ] @@ -1915,15 +1870,11 @@ svg/custom/grayscale-gradient-mask.svg [ Failure ] svg/custom/group-opacity.svg [ Failure ] svg/custom/hit-test-unclosed-subpaths.svg [ Failure ] -svg/custom/hit-test-with-br.xhtml [ Failure ] svg/custom/image-parent-translation.xhtml [ Failure ] -svg/custom/image-rescale.svg [ Failure ] svg/custom/image-small-width-height.svg [ Failure ] -svg/custom/image-with-aspect-ratio-stretch.svg [ Failure ] svg/custom/image-with-preserveAspectRatio-none.html [ Failure ] svg/custom/image-with-transform-clip-filter.svg [ Failure ] svg/custom/inline-svg-in-xhtml.xml [ Failure ] -svg/custom/intersection-list-transforms.svg [ Failure ] svg/custom/invalid-css.svg [ Failure ] svg/custom/invalid-fill-hex.svg [ Failure ] svg/custom/invalid-gradient-with-xlink.svg [ Failure ] @@ -1941,13 +1892,11 @@ svg/custom/js-late-mask-creation.svg [ Failure ] svg/custom/js-late-pattern-and-object-creation.svg [ Failure ] svg/custom/js-late-pattern-creation.svg [ Failure ] -svg/custom/js-repaint-rect-on-path-with-stroke.svg [ Failure ] svg/custom/js-update-bounce.svg [ Failure ] svg/custom/js-update-container.svg [ Failure ] svg/custom/js-update-stop-linked-gradient.svg [ Failure ] svg/custom/junk-data.svg [ Failure ] svg/custom/lazy-attach-use.html [ Failure ] -svg/custom/linking-a-03-b-all.svg [ Failure ] svg/custom/linking-a-03-b-preserveAspectRatio.svg [ Failure ] svg/custom/linking-a-03-b-transform.svg [ Failure ] svg/custom/linking-a-03-b-viewBox-transform.svg [ Failure ] @@ -1979,12 +1928,10 @@ svg/custom/mouse-move-on-svg-container.xhtml [ Failure ] svg/custom/mouse-move-on-svg-root-standalone.svg [ Failure ] svg/custom/mouse-move-on-svg-root.xhtml [ Failure ] -svg/custom/no-fixed-in-svg-assert.html [ Crash ] svg/custom/no-inherited-dashed-stroke.xhtml [ Failure ] svg/custom/non-circular-marker-reference.svg [ Failure ] svg/custom/non-opaque-filters.svg [ Failure ] svg/custom/non-scaling-stroke.svg [ Failure ] -svg/custom/object-sizing-no-width-height-change-content-box-size.xhtml [ Failure ] svg/custom/object-sizing-no-width-height.xhtml [ Failure ] svg/custom/object-sizing.xhtml [ Failure ] svg/custom/path-bad-data.svg [ Failure ] @@ -1994,7 +1941,6 @@ svg/custom/pattern-cycle-detection.svg [ Failure ] svg/custom/pattern-deep-referencing.svg [ Failure ] svg/custom/pattern-incorrect-tiling.svg [ Failure ] -svg/custom/pattern-no-pixelation.svg [ Failure ] svg/custom/pattern-rotate-gaps.svg [ Failure ] svg/custom/pattern-rotate.svg [ Failure ] svg/custom/pattern-scaling.svg [ Failure ] @@ -2003,7 +1949,7 @@ svg/custom/pointer-events-image-css-transform.svg [ Failure ] svg/custom/pointer-events-image.svg [ Failure ] svg/custom/pointer-events-path.svg [ Failure ] -svg/custom/pointer-events-text-css-transform.svg [ Crash ] +svg/custom/pointer-events-text-css-transform.svg [ Crash Timeout ] svg/custom/pointer-events-text.svg [ Failure ] svg/custom/preserve-aspect-ratio-syntax.svg [ Failure ] svg/custom/recursive-clippath.svg [ Failure ] @@ -2012,16 +1958,12 @@ svg/custom/recursive-mask.svg [ Failure ] svg/custom/recursive-pattern.svg [ Failure ] svg/custom/relative-sized-content-with-resources.xhtml [ Failure ] -svg/custom/relative-sized-content.xhtml [ Failure ] -svg/custom/relative-sized-deep-shadow-tree-content.xhtml [ Failure ] -svg/custom/relative-sized-image.xhtml [ Failure ] svg/custom/relative-sized-inner-svg.xhtml [ Failure ] -svg/custom/relative-sized-shadow-tree-content-with-symbol.xhtml [ Failure ] -svg/custom/relative-sized-shadow-tree-content.xhtml [ Failure ] svg/custom/relative-sized-use-on-symbol.xhtml [ Failure ] svg/custom/relative-sized-use-without-attributes-on-symbol.xhtml [ Failure ] svg/custom/repaint-moving-svg-and-div.xhtml [ Failure ] svg/custom/repaint-shadow.svg [ Failure ] +svg/custom/resource-client-removal.svg [ Failure ] svg/custom/resource-invalidate-on-target-update.svg [ Failure ] svg/custom/resources-css-scaled.html [ Failure ] svg/custom/root-container-opacity-clip-viewBox.svg [ Failure ] @@ -2037,18 +1979,10 @@ svg/custom/stroked-pattern.svg [ Failure ] svg/custom/style-attribute-font-size.svg [ Failure ] svg/custom/subpaths-moveto-only-rendering.svg [ Failure ] -svg/custom/svg-float-border-padding.xml [ Failure ] -svg/custom/svg-image-container-size.html [ Failure ] -svg/custom/svg-image-initial-size.html [ Failure ] svg/custom/svg-image-par-none-no-intrinsic-size.html [ Failure ] -svg/custom/svg-image-par-resize.html [ Crash ] svg/custom/svg-overflow-types.svg [ Failure ] -svg/custom/svg-root-padding-border-margin.html [ Failure ] svg/custom/SVGMatrix-interface.svg [ Failure ] -svg/custom/SVGNumber-interface.svg [ Failure ] -svg/custom/SVGPoint-interface.svg [ Failure ] svg/custom/SVGPoint-matrixTransform.svg [ Failure ] -svg/custom/SVGRect-interface.svg [ Failure ] svg/custom/text-clip.svg [ Failure ] svg/custom/text-ctm.svg [ Failure ] svg/custom/text-decoration-visibility.svg [ Failure ] @@ -2069,14 +2003,12 @@ svg/custom/text-x-override-in-tspan-child.svg [ Failure ] svg/custom/text-xy-updates-SVGList.xhtml [ Failure ] svg/custom/text-xy-updates.svg [ Failure ] -svg/custom/transform-scale-parse.svg [ Failure ] svg/custom/transformed-outlines.svg [ Failure ] svg/custom/transformed-pattern-clamp-svg-root.svg [ Failure ] svg/custom/transformed-text-pattern.html [ Failure ] svg/custom/transformedMaskFails.svg [ Failure ] svg/custom/use-attribute-invalidations.html [ Failure ] svg/custom/use-clipped-hit.svg [ Failure ] -svg/custom/use-clipped-transform.svg [ Failure ] svg/custom/use-css-no-effect-on-shadow-tree.svg [ Failure ] svg/custom/use-detach.svg [ Failure ] svg/custom/use-disappears-after-style-update.svg [ Failure ] @@ -2084,18 +2016,12 @@ svg/custom/use-event-handler-on-referenced-element.svg [ Failure ] svg/custom/use-event-handler-on-use-element.svg [ Failure ] svg/custom/use-events-crash.svg [ Failure ] -svg/custom/use-extern-href.svg [ Failure ] svg/custom/use-font-face-crash.svg [ Failure ] svg/custom/use-forward-refs.svg [ Failure ] -svg/custom/use-href-null-ns-precedence-dynamic.html [ Failure ] -svg/custom/use-image-in-g.svg [ Failure ] -svg/custom/use-in-symbol-with-offset.svg [ Failure ] svg/custom/use-modify-container-in-target.svg [ Failure ] svg/custom/use-modify-target-container.svg [ Failure ] svg/custom/use-modify-target-symbol.svg [ Failure ] -svg/custom/use-nested-sibling-symbols.html [ Failure ] svg/custom/use-nested-transform.svg [ Failure ] -svg/custom/use-nested.svg [ Failure ] svg/custom/use-on-clip-path-with-transformation.svg [ Failure ] svg/custom/use-on-disallowed-foreign-object-1.svg [ Failure ] svg/custom/use-on-disallowed-foreign-object-2.svg [ Failure ] @@ -2103,8 +2029,6 @@ svg/custom/use-on-disallowed-foreign-object-4.svg [ Failure ] svg/custom/use-on-disallowed-foreign-object-5.svg [ Failure ] svg/custom/use-on-disallowed-foreign-object-6.svg [ Failure ] -svg/custom/use-on-g-containing-foreignObject-and-image.svg [ Failure ] -svg/custom/use-on-g-containing-symbol.html [ Failure ] svg/custom/use-on-g-containing-use.svg [ Failure ] svg/custom/use-on-g.svg [ Failure ] svg/custom/use-on-non-svg-namespaced-element.svg [ Failure ] @@ -2121,13 +2045,6 @@ svg/custom/use-recursion-4.svg [ Failure ] svg/custom/use-referencing-nonexisting-symbol.svg [ Failure ] svg/custom/use-setAttribute-crash.svg [ Failure ] -svg/custom/use-symbol-overflow.svg [ Failure ] -svg/custom/use-transfer-width-height-properties-to-svg.svg [ Failure ] -svg/custom/use-transfer-width-height-properties-to-svg1.svg [ Failure ] -svg/custom/use-transfer-width-height-properties-to-svg2.svg [ Failure ] -svg/custom/use-transfer-width-height-properties-to-symbol.svg [ Failure ] -svg/custom/use-transfer-width-height-properties-to-symbol1.svg [ Failure ] -svg/custom/use-transfer-width-height-properties-to-symbol2.svg [ Failure ] svg/custom/use-transform.svg [ Failure ] svg/custom/viewBox-hit.svg [ Failure ] svg/custom/viewbox-syntax.svg [ Failure ] @@ -2506,6 +2423,7 @@ svg/filters/filter-hidden-content.svg [ Failure ] svg/filters/filter-huge-clamping.svg [ Failure ] svg/filters/filter-on-filter-for-text.svg [ Failure ] +svg/filters/filter-on-svg-root-w-layer.html [ Failure ] svg/filters/filter-on-tspan.svg [ Failure ] svg/filters/filter-placement-issue.svg [ Failure ] svg/filters/filter-refresh.svg [ Failure ] @@ -2522,6 +2440,9 @@ svg/filters/subRegion-in-userSpace.svg [ Failure ] svg/filters/subRegion-one-effect.svg [ Failure ] svg/filters/subRegion-two-effects.svg [ Failure ] +svg/filters/svg-element-invalid-filter.html [ Failure ] +svg/filters/svg-filter-child-box-reflect.html [ Failure ] +svg/filters/svg-filter-root-box-reflect.html [ Failure ] svg/foreignObject/clip.html [ Failure ] svg/foreignObject/filter-repaint.svg [ Failure ] svg/foreignObject/filter.html [ Failure ] @@ -2529,7 +2450,6 @@ svg/foreignObject/svg-document-as-direct-child.svg [ Failure ] svg/foreignObject/svg-document-in-html-document.svg [ Failure ] svg/foreignObject/transformed-text-invalidation.html [ Failure ] -svg/hittest/singular-transform-3.html [ Crash ] svg/hixie/data-types/001.xml [ Failure ] svg/hixie/dynamic/002.xml [ Failure ] svg/hixie/error/002.xml [ Failure ] @@ -2552,6 +2472,7 @@ svg/hixie/perf/003.xml [ Failure ] svg/hixie/perf/004.xml [ Failure ] svg/hixie/perf/005.xml [ Failure ] +svg/hixie/perf/006.xml [ Failure ] svg/hixie/perf/007.xml [ Failure ] svg/hixie/text/001.xml [ Crash Timeout ] svg/hixie/text/002.xml [ Failure ] @@ -2561,12 +2482,10 @@ svg/hixie/viewbox/preserveAspectRatio/002.xml [ Failure ] svg/in-html/circle.html [ Failure ] svg/in-html/overflow-repaint.html [ Failure ] -svg/markers/marker-orientation-02.svg [ Failure ] svg/markers/marker-orientation-minus-one.html [ Failure ] svg/masking/mask-type-alpha.svg [ Failure ] svg/masking/mask-type-luminance.svg [ Failure ] svg/masking/mask-type-not-set.svg [ Failure ] -svg/overflow/overflow-on-foreignObject.svg [ Failure ] svg/overflow/overflow-on-inner-svg-element-defaults.svg [ Failure ] svg/overflow/overflow-on-inner-svg-element.svg [ Failure ] svg/overflow/overflow-on-outermost-svg-element-defaults.svg [ Failure ] @@ -2578,10 +2497,6 @@ svg/overflow/overflow-on-outermost-svg-element-in-xhtml-scroll.xhtml [ Failure ] svg/overflow/overflow-x-hidden-on-outermost-svg-element.svg [ Failure ] svg/overflow/overflow-y-hidden-on-outermost-svg-element.svg [ Failure ] -svg/parser/svg-parser-argument-whitespace.html [ Failure ] -svg/repaint/buffered-rendering-dynamic-image.html [ Crash ] -svg/repaint/buffered-rendering-static-image.html [ Crash ] -svg/repaint/container-repaint.svg [ Failure ] svg/repaint/filter-child-repaint.svg [ Failure ] svg/repaint/filter-repaint.svg [ Failure ] svg/repaint/focus-element.html [ Failure ] @@ -2600,7 +2515,6 @@ svg/repaint/text-pattern-update.html [ Failure ] svg/repaint/tspan-pattern-update.html [ Failure ] svg/stroke/non-scaling-stroke-gradient-text.html [ Failure ] -svg/stroke/non-scaling-stroke-paintserver-same-as-fill.html [ Failure ] svg/stroke/non-scaling-stroke-text-decoration.html [ Failure ] svg/stroke/non-scaling-stroke-text.html [ Failure ] svg/stroke/non-scaling-stroke-zero-length-subpath-linecaps.html [ Failure ] @@ -2624,7 +2538,6 @@ svg/text/ligature-queries.html [ Failure ] svg/text/modify-text-node-in-tspan.html [ Failure ] svg/text/non-bmp-positioning-lists.svg [ Failure ] -svg/text/non-invertible-matrix-text.svg [ Failure ] svg/text/obb-paintserver.html [ Failure ] svg/text/remove-text-node-from-tspan.html [ Failure ] svg/text/remove-tspan-from-text.html [ Failure ] @@ -2702,14 +2615,12 @@ svg/text/tspan-dynamic-positioning.svg [ Failure ] svg/text/tspan-multiple-outline.svg [ Failure ] svg/transforms/animated-path-inside-transformed-html.xhtml [ Failure ] -svg/transforms/change-transform-origin-css.xhtml [ Failure ] -svg/transforms/change-transform-origin-presentation-attribute.xhtml [ Failure ] -svg/transforms/change-transform-to-none-text.html [ Crash ] +svg/transforms/change-transform-to-none-text.html [ Failure ] svg/transforms/svg-css-transforms-clip-path.xhtml [ Failure ] svg/transforms/svg-css-transforms.xhtml [ Failure ] svg/transforms/text-with-mask-with-svg-transform.svg [ Failure ] svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ] -svg/transforms/transform-origin-css-property.xhtml [ Failure ] +svg/transforms/text-with-pattern-with-svg-transform.svg [ Failure ] svg/transforms/transformed-text-fill-gradient.html [ Failure ] svg/transforms/transformed-text-fill-pattern.html [ Failure ] svg/transforms/will-change-transform.svg [ Failure ] @@ -2863,6 +2774,7 @@ svg/W3C-SVG-1.1/coords-trans-05-t.svg [ Failure ] svg/W3C-SVG-1.1/coords-trans-06-t.svg [ Failure ] svg/W3C-SVG-1.1/coords-units-01-b.svg [ Failure ] +svg/W3C-SVG-1.1/coords-units-02-b.svg [ Failure ] svg/W3C-SVG-1.1/coords-viewattr-01-b.svg [ Failure ] svg/W3C-SVG-1.1/coords-viewattr-02-b.svg [ Failure ] svg/W3C-SVG-1.1/coords-viewattr-03-b.svg [ Failure ] @@ -3055,7 +2967,6 @@ svg/zoom/page/absolute-sized-document-no-scrollbars.svg [ Failure ] svg/zoom/page/absolute-sized-document-scrollbars.svg [ Failure ] svg/zoom/page/relative-sized-document-scrollbars.svg [ Failure ] -svg/zoom/page/zoom-background-image-tiled.html [ Crash ] svg/zoom/page/zoom-clip-path.html [ Failure ] svg/zoom/page/zoom-coords-viewattr-01-b.svg [ Failure ] svg/zoom/page/zoom-foreign-content.svg [ Failure ] @@ -3065,10 +2976,7 @@ svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Crash Failure Timeout ] svg/zoom/page/zoom-mask-with-percentages.svg [ Failure ] svg/zoom/page/zoom-replaced-intrinsic-ratio-001.htm [ Failure ] -svg/zoom/page/zoom-svg-as-background-with-relative-size-and-viewBox.html [ Crash ] -svg/zoom/page/zoom-svg-as-image.html [ Crash ] svg/zoom/page/zoom-svg-as-object.html [ Failure ] -svg/zoom/page/zoom-svg-as-relative-image.html [ Crash ] svg/zoom/page/zoom-svg-float-border-padding.xml [ Failure ] svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ] svg/zoom/page/zoom-svg-through-object-with-absolute-size.xhtml [ Failure ] @@ -3077,7 +2985,6 @@ svg/zoom/page/zoom-svg-through-object-with-override-size.html [ Failure ] svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure ] svg/zoom/text/zoom-coords-viewattr-01-b.svg [ Failure ] -svg/zoom/text/zoom-em-units.html [ Failure ] svg/zoom/text/zoom-foreignObject.svg [ Failure ] svg/zoom/text/zoom-hixie-mixed-008.xml [ Failure ] svg/zoom/text/zoom-hixie-mixed-009.xml [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index 60ec6db..e280da8 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -62,6 +62,7 @@ # Mac does not have menu key. [ Mac ] editing/spelling/spelling-on-context-menu-key.html [ WontFix ] +[ Mac ] fast/events/context-menu-key-shift-f10-modifiers.html [ WontFix ] [ Mac ] fast/events/menu-key-context-menu-document.html [ WontFix ] [ Mac ] fast/events/menu-key-context-menu.html [ WontFix ] [ Mac ] fast/events/menu-key-context-menu-position.html [ WontFix ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 0d0e9b15..2f1c133 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -130,6 +130,8 @@ crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-distribute-to-scroll-chain-descendant.html [ Pass Failure ] crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html [ Pass Failure ] +crbug.com/620618 svg/custom/alignment-baseline-modes.svg [ NeedsRebaseline ] + crbug.com/381730 http/tests/navigation/pending-location-change-assert.html [ Failure Pass ] crbug.com/518883 crbug.com/390452 http/tests/security/isolatedWorld/media-query-wrapper-leaks.html [ Failure Pass Timeout ] crbug.com/518987 http/tests/xmlhttprequest/navigation-abort-detaches-frame.html [ Pass Timeout ] @@ -850,7 +852,8 @@ crbug.com/600087 virtual/gpu-rasterization/fast/images/pixel-crack-image-background-webkit-transform-scale.html [ Timeout ] -crbug.com/624233 [ Win10 ] virtual/gpu-rasterization/fast/images/color-profile-background-clip-text.html [ Failure ] +# Flaky on Win10 and Win7 +crbug.com/624233 [ Win ] virtual/gpu-rasterization/fast/images/color-profile-background-clip-text.html [ Failure ] crbug.com/385014 crbug.com/410145 accessibility/canvas-fallback-content-2.html [ Pass Failure Timeout ] @@ -905,77 +908,58 @@ crbug.com/482229 compositing/layer-creation/fixed-position-under-transform.html [ Failure ] -crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html [ Skip ] + # These fail in the leak detector: http://crbug.com/612924#c4 -crbug.com/612924 [ Linux ] imported/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html [ Skip ] +crbug.com/619060 [ Linux ] imported/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html [ Skip ] +crbug.com/619060 [ Linux ] imported/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html [ Skip ] -# Probably needs a rebaseline, marking as failing for now: http://crbug.com/612924#c6 -# Feature owner needs to investigate. -crbug.com/471824 imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html [ Failure Timeout ] +# The commented lines here for Mac is due to the fact that there is a more +# generic skip rule in the next block of rules. However, when they get fixed +# these should be uncommented as there is no touch support on Mac. +crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointerenter_nohover-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointercancel_touch-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointertype_touch-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html [ Skip ] +crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html [ Skip ] +# crbug.com/613672 [ Mac ] imported/wpt/pointerevents/pointerevent_pointerleave_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_capture_mouse-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_capture_suppressing_mouse-manual.html [ Skip ] -crbug.com/471824 imported/wpt/pointerevents/pointerevent_constructor.html [ Failure ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_lostpointercapture_is_first-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointercancel_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerdown-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerenter_does_not_bubble-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerenter-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerenter_nohover-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_descendant_over-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_descendants-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_does_not_bubble-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_mouse-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_pen-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerleave_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointermove-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointermove_pointertype-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerout-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerout_pen-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerout_received_once-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerover-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointertype_mouse-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointertype_pen-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointertype_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerup-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_pointerup_pointertype-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_setpointercapture_disconnected-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_setpointercapture_relatedtarget-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-illegal.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-keyboard-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-none-css_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-span-test_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_touch-action-verification.html [ Skip ] -crbug.com/612924 imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html [ Skip ] +# These are crashing on Linux debug builds and timing out on Mac as it doesn't support touch +crbug.com/620236 imported/wpt/pointerevents/pointerevent_pointertype_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html [ Skip ] + +crbug.com/619060 imported/wpt/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html [ Skip ] +crbug.com/619060 imported/wpt/pointerevents/pointerevent_lostpointercapture_is_first-manual.html [ Skip ] +crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointercancel_touch-manual.html [ Skip ] +crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerenter_nohover-manual.html [ Skip ] +crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html [ Skip ] +crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html [ Skip ] +crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-keyboard-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-none-css_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-span-test_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ Skip ] + +crbug.com/583413 imported/wpt/pointerevents/pointerevent_pointerleave_pen-manual.html [ Failure ] + # These testcases are incorrect, mark them as failing until they're fixed in the testsuite. # https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html @@ -1247,8 +1231,6 @@ crbug.com/399951 http/tests/mime/javascript-mimetype-usecounters.html [ Pass Failure ] -crbug.com/602193 inspector/extensions/extensions-resources.html [ Pass Failure ] - crbug.com/579493 http/tests/security/xss-DENIED-xsl-document-securityOrigin.xml [ Timeout ] crbug.com/572723 [ Linux Mac10.9 ] inspector/sources/debugger/debugger-disable-enable.html [ Pass Failure Timeout ] @@ -1260,8 +1242,6 @@ crbug.com/577380 [ Linux Debug ] http/tests/serviceworker/chromium/registration-stress.html [ Failure ] -crbug.com/607101 [ Mac ] fast/text/first-letter-bad-line-boxes-crash.html [ Timeout Pass ] - crbug.com/587136 [ Linux Debug ] http/tests/security/xss-DENIED-cross-origin-stack-overflow.html [ Timeout Pass ] crbug.com/587593 [ Android ] fast/js/pic/cached-single-entry-transition.html [ Pass Failure ] @@ -1380,6 +1360,10 @@ crbug.com/621892 css3/filters/effect-saturate-hw.html [ Pass Failure ] crbug.com/621892 css3/filters/effect-sepia-hw.html [ Pass Failure ] +crbug.com/612278 svg/as-background-image/background-repeat.html [ NeedsRebaseline ] +crbug.com/612278 ietestcenter/css3/bordersbackgrounds/background-size-aspect-ratio.htm [ NeedsRebaseline ] +crbug.com/612278 fast/backgrounds/background-repeat-with-background-color.html [ NeedsRebaseline ] + crbug.com/622672 [ Mac ] virtual/threaded/fast/scroll-behavior/overflow-interrupted-scroll.html [ Pass Failure ] crbug.com/624430 [ Win10 ] fast/text/font-features/caps-casemapping.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto1-expected.html b/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto1-expected.html index 80c929d..c1e9397 100644 --- a/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto1-expected.html +++ b/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto1-expected.html
@@ -9,7 +9,7 @@ padding: 50px; border: 50px solid transparent; background-image: url(resources/circle.png); - background-size: 111px 84px; + background-size: 111px 88px; background-repeat: repeat; background-origin: border-box; background-clip: border-box;
diff --git a/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto2-expected.html b/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto2-expected.html index 10069941..a59eca2 100644 --- a/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto2-expected.html +++ b/third_party/WebKit/LayoutTests/css3/background/background-repeat-round-auto2-expected.html
@@ -9,7 +9,7 @@ padding: 50px; border: 50px solid transparent; background-image: url(resources/circle.png); - background-size: 123px 100px; + background-size: 125px 100px; background-repeat: repeat; background-origin: border-box; background-clip: border-box;
diff --git a/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto1-expected.html b/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto1-expected.html index 70c05ec..6cb020b 100644 --- a/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto1-expected.html +++ b/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto1-expected.html
@@ -14,7 +14,7 @@ border: 50px solid blue; padding: 50px; -webkit-mask-image: url(resources/circle.png); - -webkit-mask-size: 111px 84px; + -webkit-mask-size: 111px 88px; -webkit-mask-repeat: repeat; -webkit-mask-origin: border-box; -webkit-mask-clip: border-box;
diff --git a/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto2-expected.html b/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto2-expected.html index 7d1cf43..e2ef0054 100644 --- a/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto2-expected.html +++ b/third_party/WebKit/LayoutTests/css3/masking/mask-repeat-round-auto2-expected.html
@@ -14,7 +14,7 @@ border: 50px solid blue; padding: 50px; -webkit-mask-image: url(resources/circle.png); - -webkit-mask-size: 123px 100px; + -webkit-mask-size: 125px 100px; -webkit-mask-repeat: repeat; -webkit-mask-origin: border-box; -webkit-mask-clip: border-box;
diff --git a/third_party/WebKit/LayoutTests/custom-elements/spec/custom-elements-registry/when_defined.html b/third_party/WebKit/LayoutTests/custom-elements/spec/custom-elements-registry/when_defined.html index 133c512b..649c339 100644 --- a/third_party/WebKit/LayoutTests/custom-elements/spec/custom-elements-registry/when_defined.html +++ b/third_party/WebKit/LayoutTests/custom-elements/spec/custom-elements-registry/when_defined.html
@@ -2,6 +2,7 @@ <title>Custom Elements: CustomElementsRegistry.whenDefined</title> <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> +<script src="../resources/custom-elements-helpers.js"></script> <body> <div id="log"></div> <script> @@ -58,6 +59,43 @@ assert_true(afterDefined, 'promise after defined should be resolved.'); assert_true(notDefined, 'promise for not defined name should not be resolved.'); }).catch(reason => { throw reason })); + + // Calling whenDefined() with invalid names should throw "SyntaxError"DOMException + // https://html.spec.whatwg.org/multipage/scripting.html#valid-custom-element-name + let invalid_names = [ + 'annotation-xml', + 'color-profile', + 'font-face', + 'font-face-src', + 'font-face-uri', + 'font-face-format', + 'font-face-name', + 'missing-glyph', + 'div', 'p', + 'nothtmlbutnohyphen', + '-not-initial-a-z', '0not-initial-a-z', 'Not-initial-a-z', + 'intermediate-UPPERCASE-letters', + 'bad-\u00b6', 'bad-\u00b8', 'bad-\u00bf', 'bad-\u00d7', 'bad-\u00f7', + 'bad-\u037e', 'bad-\u037e', 'bad-\u2000', 'bad-\u200e', 'bad-\u203e', + 'bad-\u2041', 'bad-\u206f', 'bad-\u2190', 'bad-\u2bff', 'bad-\u2ff0', + 'bad-\u3000', 'bad-\ud800', 'bad-\uf8ff', 'bad-\ufdd0', 'bad-\ufdef', + 'bad-\ufffe', 'bad-\uffff', 'bad-' + String.fromCodePoint(0xf0000) + ]; + + invalid_names.forEach((name) => { + promise_test((t) => { + return create_window_in_test(t) + .then((w) => { + return promise_rejects_with_dom_exception_syntax_error(w, t, w.customElements.whenDefined(name)); + }); + }, 'whenDefined() called with invalid name ' + name + ' should throw "SyntaxError"DOMException'); + }); + + function promise_rejects_with_dom_exception_syntax_error(global_context, test, promise, description) { + return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { + assert_throws_dom_exception(global_context, 'SYNTAX_ERR', function () { throw e; }) + }); + } })(); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/custom-elements/spec/define-element.html b/third_party/WebKit/LayoutTests/custom-elements/spec/define-element.html index 8021adb..3dd01c67 100644 --- a/third_party/WebKit/LayoutTests/custom-elements/spec/define-element.html +++ b/third_party/WebKit/LayoutTests/custom-elements/spec/define-element.html
@@ -12,19 +12,6 @@ 'use strict'; -function assert_throws_dom_exception(global_context, code, func, description) { - let exception; - assert_throws(code, () => { - try { - func.call(this); - } catch(e) { - exception = e; - throw e; - } - }, description); - assert_true(exception instanceof global_context.DOMException, 'DOMException on the appropriate window'); -} - test_with_window((w) => { assert_throws(TypeError.prototype, () => { w.customElements.define('a-a', 42);
diff --git a/third_party/WebKit/LayoutTests/custom-elements/spec/resources/custom-elements-helpers.js b/third_party/WebKit/LayoutTests/custom-elements/spec/resources/custom-elements-helpers.js index 885677d..c4a9e6c 100644 --- a/third_party/WebKit/LayoutTests/custom-elements/spec/resources/custom-elements-helpers.js +++ b/third_party/WebKit/LayoutTests/custom-elements/spec/resources/custom-elements-helpers.js
@@ -20,3 +20,16 @@ }); }, name); } + +function assert_throws_dom_exception(global_context, code, func, description) { + let exception; + assert_throws(code, () => { + try { + func.call(this); + } catch(e) { + exception = e; + throw e; + } + }, description); + assert_true(exception instanceof global_context.DOMException, 'DOMException on the appropriate window'); +} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.html b/third_party/WebKit/LayoutTests/editing/assert_selection.html index 324ba8c7..1dc66d6 100644 --- a/third_party/WebKit/LayoutTests/editing/assert_selection.html +++ b/third_party/WebKit/LayoutTests/editing/assert_selection.html
@@ -2,7 +2,6 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="assert_selection.js"></script> -<div id="log"></div> <script> function checked_assert_selection(input, command, output) { try {
diff --git a/third_party/WebKit/LayoutTests/editing/assert_selection.js b/third_party/WebKit/LayoutTests/editing/assert_selection.js index 014aa440..2ee74145 100644 --- a/third_party/WebKit/LayoutTests/editing/assert_selection.js +++ b/third_party/WebKit/LayoutTests/editing/assert_selection.js
@@ -509,6 +509,8 @@ constructor(sampleText) { /** @const @type {!HTMLIFame} */ this.iframe_ = document.createElement('iframe'); + if (!document.body) + document.body = document.createElement("body"); document.body.appendChild(this.iframe_); /** @const @type {!HTMLDocument} */ this.document_ = this.iframe_.contentDocument;
diff --git a/third_party/WebKit/LayoutTests/editing/inserting/insert-div-018.html b/third_party/WebKit/LayoutTests/editing/inserting/insert-div-018.html index e0db6ad2..580ff06 100644 --- a/third_party/WebKit/LayoutTests/editing/inserting/insert-div-018.html +++ b/third_party/WebKit/LayoutTests/editing/inserting/insert-div-018.html
@@ -1,44 +1,24 @@ -<html> -<head> - -<style> -body { - font-size: 24px; -} -.editing { - border: 2px solid red; - padding: 12px; -} -div { - border: 2px solid blue; - padding: 12px; -} - -</style> -<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script> - +<!doctype html> +<body> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> <script> - -function editingTest() { - moveSelectionBackwardByCharacterCommand(); - insertParagraphCommand(); -} - +test(() => { + assert_selection( + [ + '<div contenteditable>', + '<div style="height:12px"></div>', + 'bar|<div>baz</div>', + '</div>', + ].join(''), + 'insertParagraph', + [ + '<div contenteditable>', + '<div style="height:12px"></div>', + 'bar<div>|<br><div>baz</div></div>', + '</div>', + ].join(''), + 'Insert BR befor <div>baz</div>'); +}); </script> - -<title>Editing Test</title> -</head> -<body contenteditable id="root"> - -Test inserting paragraphs: should see an empty blue box below "bar" - -<div style="border: none; height: 12px"></div> - -bar<div class="editing" id="test">baz</div> - -<script> -runEditingTest(); -</script> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/backgrounds/background-repeat-with-background-color.html b/third_party/WebKit/LayoutTests/fast/backgrounds/background-repeat-with-background-color.html index adc7e1c..ea85b19 100644 --- a/third_party/WebKit/LayoutTests/fast/backgrounds/background-repeat-with-background-color.html +++ b/third_party/WebKit/LayoutTests/fast/backgrounds/background-repeat-with-background-color.html
@@ -4,7 +4,7 @@ <style> div { display: inline-block; - width: 110px; + width: 130px; height: 110px; margin: 10px; background-color: green;
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values-expected.txt index f35339b..ea819be 100644 --- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values-expected.txt
@@ -484,6 +484,75 @@ padding-left: 20px +Resolved values for element "ruby" with display "block": +line-height: normal +width: 452px +height: 0px +top: 0px +right: -50px +bottom: 0px +left: 50px +margin-top: 0px +margin-right: 0px +margin-bottom: 0px +margin-left: 0px +padding-top: 0px +padding-right: 0px +padding-bottom: 0px +padding-left: 0px + +Resolved values for element "ruby" with display "inline": +line-height: normal +width: auto +height: auto +top: 0px +right: auto +bottom: 0px +left: 10% +margin-top: 0px +margin-right: 0px +margin-bottom: 0px +margin-left: 0px +padding-top: 0px +padding-right: 0px +padding-bottom: 0px +padding-left: 0px + +Resolved values for element "ruby" with display "inline-block": +line-height: normal +width: 0px +height: 0px +top: 0px +right: -50px +bottom: 0px +left: 50px +margin-top: 0px +margin-right: 0px +margin-bottom: 0px +margin-left: 0px +padding-top: 0px +padding-right: 0px +padding-bottom: 0px +padding-left: 0px + +Resolved values for element "ruby" with display "none": +line-height: normal +width: auto +height: auto +top: auto +right: auto +bottom: auto +left: 10% +margin-top: 0px +margin-right: 0px +margin-bottom: 0px +margin-left: 0px +padding-top: 0px +padding-right: 0px +padding-bottom: 0px +padding-left: 0px + + Fixed Percents EMs @@ -491,3 +560,4 @@ Mixed Relative Positioned Absolute Positioned +
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values.html b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values.html index 806dc5d..842b5f9 100644 --- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values.html +++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/getComputedStyle-resolved-values.html
@@ -101,6 +101,11 @@ padding: 20px; } + #ruby { + left: 10%; + position: relative; + } + </style> <script> @@ -163,6 +168,7 @@ test('mixed'); test('rel_positioned'); test('abs_positioned'); + test('ruby'); } </script> </head> @@ -195,5 +201,8 @@ <div class="outer" id="abs_container"> <div class="testbox" id="abs_positioned">Absolute Positioned</div> </div> + <div class="outer"> + <ruby class="testbox" id="ruby"></ruby> + </div> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-html-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-html-crash-expected.txt new file mode 100644 index 0000000..7d8d089 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-html-crash-expected.txt
@@ -0,0 +1 @@ +This test should not crash
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-html-crash.html b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-html-crash.html new file mode 100644 index 0000000..db8ae5f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-html-crash.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<script> +if (window.internals) { + internals.settings.setCSSStickyPositionEnabled(true); +} +</script> + +<html> +<style> +html { + position: sticky; +} +</style> +<script> +if (window.testRunner) + testRunner.dumpAsText(); +</script> +</head> +<p>This test should not crash</p> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus-multiple-times.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus-multiple-times.html index fa02a005..6abf6df 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus-multiple-times.html +++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus-multiple-times.html
@@ -33,6 +33,9 @@ <body> <button id="outer-button" autofocus></button> <dialog id="dlg"> + <!-- Unfocusable elements with [autofocus] should be ignored. --> + <input autofocus disabled> + <textarea autofocus hidden></textarea> <input id="input1"></input> <input id="input2" autofocus></input> </dialog>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus.html index ff093fa..421f7f0c2 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus.html +++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLDialogElement/dialog-autofocus.html
@@ -51,6 +51,9 @@ <button id="outer-button" autofocus></button> <dialog id="dialog"> <button></button> + <!-- Unfocusable elements with [autofocus] should be ignored. --> + <input autofocus disabled> + <textarea autofocus hidden></textarea> <dialog> <button autofocus></button> </dialog>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/focus-navigation-in-plugin.html b/third_party/WebKit/LayoutTests/fast/dom/focus-navigation-in-plugin.html new file mode 100644 index 0000000..2512dcb --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/focus-navigation-in-plugin.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<input id="outer-before"> +<object data="resources/plugin-focus-subframe.html" type="text/html" id="obj"></object> +<embed src="resources/plugin-focus-subframe.html" type="text/html" id="emb"></embed> +<input id="outer-after"> +<script> +function PressTab() { + eventSender.keyDown('\t'); +} + +function PressShiftTab() { + eventSender.keyDown('\t', ['shiftKey']); +} + +function testFocusNavigation() { + test(() => { + var before = document.querySelector('#outer-before'); + var after = document.querySelector('#outer-after'); + + before.focus(); + + // 'plugin-focus-subframe.html' has 2 focus areas. + var expected = ['outer-before', 'obj', 'obj', 'emb', 'emb', 'outer-after']; + + var i; + for (i = 0; i < 5; ++i) { + assert_equals(document.activeElement.id, expected[i]); + PressTab(); + } + assert_equals(document.activeElement, after, '#after'); + + expected.reverse(); + for (i = 0; i < 5; ++i) { + assert_equals(document.activeElement.id, expected[i]); + PressShiftTab(); + } + assert_equals(document.activeElement, before, '#before'); + + }, "Focus should navigate to <option>/<embed>"); +} + +if (window.testRunner) { + window.addEventListener('load', testFocusNavigation, false); +} +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/resources/plugin-focus-subframe.html b/third_party/WebKit/LayoutTests/fast/dom/resources/plugin-focus-subframe.html new file mode 100644 index 0000000..1a0a9e2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/resources/plugin-focus-subframe.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +</head> +<body> + <input placeholder="subframe-before"> + <input placeholder="subframe-after"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/context-menu-key-shift-f10-modifiers.html b/third_party/WebKit/LayoutTests/fast/events/context-menu-key-shift-f10-modifiers.html new file mode 100644 index 0000000..4d57740 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/context-menu-key-shift-f10-modifiers.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Test Context Menu Key, Shift+F10 with Modifiers</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<a href="#" id="anchor">Anchor</a> +<script> +test(function() { + assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.'); + + var contextMenuFired = false; + var anchor = document.getElementById('anchor'); + anchor.addEventListener('contextmenu', () => contextMenuFired = true); + + function testContextMenuEvent(key, modifiers, shouldFire) { + contextMenuFired = false; + anchor.focus(); + eventSender.keyDown(key, modifiers); + // Esc key to hide context menu + eventSender.keyDown("Escape"); + assert_equals(contextMenuFired, shouldFire, `${key}+${modifiers} opens Context Menu:${shouldFire}.`); + } + + testContextMenuEvent('ContextMenu', [], true); + testContextMenuEvent('ContextMenu', ['numLockOn'], true); + testContextMenuEvent('ContextMenu', ['capsLockOn'], true); + testContextMenuEvent('ContextMenu', ['altKey'], false); + testContextMenuEvent('ContextMenu', ['ctrlKey'], false); + testContextMenuEvent('ContextMenu', ['shiftKey'], false); + + testContextMenuEvent('F10', ['shiftKey'], true); + testContextMenuEvent('F10', ['shiftKey', 'numLockOn'], true); + testContextMenuEvent('F10', ['shiftKey', 'capsLockOn'], true); + testContextMenuEvent('F10', ['shiftKey', 'altKey'], false); + testContextMenuEvent('F10', ['shiftKey', 'ctrlKey'], false); +}, 'Context Menu keys should allow NumLock/CapsLock/etc but not other modifiers.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-data.html b/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-data.html deleted file mode 100644 index a704bdb..0000000 --- a/third_party/WebKit/LayoutTests/fast/events/inputevents/before-input-data.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<title>InputEvent: beforeinput data</title> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -</head> -<body> -<input type="text" id="txt"> -<script> -test(function() { - var lastData = ''; - var txt = document.getElementById('txt'); - txt.addEventListener('beforeinput', function(event) { - lastData = event.data; - }); - if (!window.eventSender) { - document.write('This test requires eventSender'); - } else { - function testKeyDownData(key, modifiers, data) { - eventSender.keyDown(key, modifiers); - assert_equals(lastData, data, `${modifiers.toString()}+${key} should produce data: ${data}`); - } - - txt.focus(); - // Typing - testKeyDownData('a', [], 'a'); - testKeyDownData('4', [], '4'); - testKeyDownData('Backspace', [], ''); - // TODO(chongz): eventSender.keyDown('a', ['shiftKey']) should produce shifted character. - // https://crbug.com/604488 - // testKeyDownData('l', ['shiftKey'], 'L'); - // testKeyDownData('6', ['shiftKey'], '^'); - testKeyDownData(' ', [], ' '); - } -}, 'Testing beforeinput data'); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/inputevents/inputevent-data-keyboard.html b/third_party/WebKit/LayoutTests/fast/events/inputevents/inputevent-data-keyboard.html new file mode 100644 index 0000000..edeb17c9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/inputevents/inputevent-data-keyboard.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> +<title>InputEvent: data field from keyboard</title> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +</head> +<body> +<p id="txt" contenteditable></p> +<script> +test(function() { + assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.'); + + const NOT_FIRED = 'NOT_FIRED'; + var beforeinputData = NOT_FIRED; + var inputData = NOT_FIRED; + + var txt = document.getElementById('txt'); + txt.addEventListener('beforeinput', event => beforeinputData = event.data); + txt.addEventListener('input', event => inputData = event.data); + + function testKeyDownData(key, modifiers, data) { + beforeinputData = NOT_FIRED; + inputData = NOT_FIRED; + eventSender.keyDown(key, modifiers); + assert_equals(beforeinputData, data, `${modifiers.toString()}+${key} should produce beforeinput data: ${data}`); + assert_equals(inputData, data, `${modifiers.toString()}+${key} should produce input data: ${data}`); + } + + txt.focus(); + // Typing + testKeyDownData('a', [], 'a'); + testKeyDownData('4', [], '4'); + testKeyDownData('Backspace', [], ''); + testKeyDownData('L', ['shiftKey'], 'L'); + testKeyDownData('^', ['shiftKey'], '^'); + testKeyDownData(' ', [], ' '); +}, 'Testing data field from keyboard'); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/offsetX-offsetY-svg.html b/third_party/WebKit/LayoutTests/fast/events/offsetX-offsetY-svg.html new file mode 100644 index 0000000..586ed89 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/offsetX-offsetY-svg.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<title>MouseEvent.offsetX/offsetY for an SVG element is always relative to the outermost <svg> CSS layout box</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<style> +svg { + border: 10px solid blue; + border-width: 20px 40px 30px 10px; +} +</style> +<svg width="400" height="400" viewBox="0 0 400000 400000"> + <rect x="40000" y="60000" width="80000" height="80000" fill="blue"/> + <rect x="160000" y="180000" width="80000" height="80000" fill="blue" stroke="lightblue" stroke-width="10000"/> +</svg> +<script> +function check_offset(test, element, clientX, clientY, expectedOffsetX, expectedOffsetY) { + element.onclick = test.step_func(function(event) { + assert_equals(event.offsetX, expectedOffsetX, 'offsetX'); + assert_equals(event.offsetY, expectedOffsetY, 'offsetY'); + }); + var mouseEvent = new MouseEvent('click', { clientX: clientX, clientY: clientY }); + element.dispatchEvent(mouseEvent); +} + +test(function(t) { + var rects = document.querySelectorAll('rect'); + var svgBoundingRect = document.querySelector('svg').getBoundingClientRect(); + var offsetBase = { x: svgBoundingRect.left + 10, y: svgBoundingRect.top + 20 }; + check_offset(t, rects[0], offsetBase.x + 80, offsetBase.y + 100, 80, 100); + check_offset(t, rects[1], offsetBase.x + 200, offsetBase.y + 220, 200, 220); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-global.html b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-global.html index 5f8c979c..d41a66b6 100644 --- a/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-global.html +++ b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-global.html
@@ -27,14 +27,14 @@ // With a global handler, no other handlers should matter var elements = [document.getElementById('description'), element, document.getElementById('tests')]; for (var i = 0; i < elements.length; i++) - elements[i].addEventListener('touchmove', listener, false); + elements[i].addEventListener('touchmove', listener, {passive: false}); if (window.internals) internals.forceCompositingUpdate(document); logRects(name, true); for (var i = 0; i < elements.length; i++) - elements[i].removeEventListener('touchmove', listener, false); + elements[i].removeEventListener('touchmove', listener, {passive: false}); } function runOverlayTest() {
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects-iframe-doc.html b/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects-iframe-doc.html index f012a4e..f7987a8 100644 --- a/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects-iframe-doc.html +++ b/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects-iframe-doc.html
@@ -24,7 +24,7 @@ function handler() {}; frameElement.addHandlers = function() { - document.addEventListener('touchstart', handler, false); + document.addEventListener('touchstart', handler, {passive: false}); } frameElement.removeHandlers = function() { document.removeEventListener('touchstart', handler, false);
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects.js b/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects.js index 99892127..6b827a7 100644 --- a/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects.js +++ b/third_party/WebKit/LayoutTests/fast/events/touch/resources/compositor-touch-hit-rects.js
@@ -28,7 +28,7 @@ var preRunHandlerForTest = {}; function testElement(element) { - element.addEventListener('touchstart', listener, false); + element.addEventListener('touchstart', listener, {passive: false}); // Run any test-specific handler AFTER adding the touch event listener // (which itself causes rects to be recomputed).
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/touch-event-cancelable.html b/third_party/WebKit/LayoutTests/fast/events/touch/touch-event-cancelable.html index 5d972836..0691cfa 100644 --- a/third_party/WebKit/LayoutTests/fast/events/touch/touch-event-cancelable.html +++ b/third_party/WebKit/LayoutTests/fast/events/touch/touch-event-cancelable.html
@@ -15,7 +15,7 @@ shouldBeFalse('touchEvent.defaultPrevented'); console.log('Calling preventDefault on TouchEvent with cancelable=' + event.cancelable); touchEvent.preventDefault(); -}, false); +}, {passive: false}); if (window.eventSender) { eventSender.addTouchPoint(152, 152);
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/touch-target-move-documents.html b/third_party/WebKit/LayoutTests/fast/events/touch/touch-target-move-documents.html index c7eca01..eea9092 100644 --- a/third_party/WebKit/LayoutTests/fast/events/touch/touch-target-move-documents.html +++ b/third_party/WebKit/LayoutTests/fast/events/touch/touch-target-move-documents.html
@@ -32,7 +32,7 @@ var events = ['touchstart', 'touchmove', 'touchend']; for (var i = 0; i < events.length; i++) { for (var j = 0; j < targets.length; j++) { - targets[j].addEventListener(events[i], logEvent); + targets[j].addEventListener(events[i], logEvent, {passive: false}); } }
diff --git a/third_party/WebKit/LayoutTests/fast/scrolling/set-root-scroller.html b/third_party/WebKit/LayoutTests/fast/scrolling/set-root-scroller.html index ca9cdd4..177d339 100644 --- a/third_party/WebKit/LayoutTests/fast/scrolling/set-root-scroller.html +++ b/third_party/WebKit/LayoutTests/fast/scrolling/set-root-scroller.html
@@ -20,7 +20,13 @@ overflow: auto; } - #spacer { + #parent { + width: 100%; + height: 100%; + overflow: auto; + } + + .spacer { width: 2000px; height: 2000px; } @@ -35,10 +41,13 @@ } </style> -<div id="container"> - <div id="spacer"> - <span id="spanner">TEST</span> +<div id="parent"> + <div id="container"> + <div class="spacer"> + <span id="spanner">TEST</span> + </div> </div> + <div class="spacer"></div> </div> <div id="rootspacer"></div> @@ -46,77 +55,112 @@ <script src="../../resources/testharnessreport.js"></script> <script> + var parentScroller = document.querySelector('#parent'); + var container = document.querySelector('#container'); + var spanner = document.querySelector('#spanner'); + test(function() { assert_false(typeof document.rootScroller === 'undefined'); }, 'setRootScroller API enabled'); - // TODO(bokan): Break this test up, failing asserts are hard to find. test(function() { - // Setting the container object should succeed. - assert_equals(document.rootScroller, null); - var container = document.querySelector('#container'); - document.rootScroller = container; - assert_equals(document.rootScroller, container); + // Setting the container object should succeed. + assert_equals(document.rootScroller, null); + document.rootScroller = container; + assert_equals(document.rootScroller, container); + document.rootScroller = null; + assert_equals(document.rootScroller, null); + }, 'Setter and getter on a valid element works'); - // Trying to set the <span> should succeed even though it's not a valid - // scroller. - var spanner = document.querySelector('#spanner'); - document.rootScroller = spanner; - assert_equals(document.rootScroller, spanner); + test(function() { + // Trying to set the <span> should succeed even though it's not a valid + // scroller. + document.rootScroller = spanner; + assert_equals(document.rootScroller, spanner); + }, 'Can set a non-scrolling element as the rootScroller'); - // Scroll the container <div> past the end. The scrolls should not chain - // past the rootScroller to the scrollingElement. - document.rootScroller = container; - if (typeof eventSender !== 'undefined') { - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); + test(function() { + // Scroll the container <div> past the end. The scrolls should not chain + // past the rootScroller to the parentScroller element. + document.rootScroller = container; + if (typeof eventSender !== 'undefined') { + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollUpdate(-300, -300); - assert_equals(container.scrollTop, 2000 - 600); - assert_equals(container.scrollLeft, 2000 - 800); - assert_equals(document.scrollingElement.scrollTop, 0); - assert_equals(document.scrollingElement.scrollLeft, 0); - } + assert_equals(container.scrollTop, 2000 - 600); + assert_equals(container.scrollLeft, 2000 - 800); - // Making the current rootScroller an invalid scroller should fallback to - // the default element, the documentElement, but the rootScroller property - // should remain the same. - container.style.width = "95%"; - assert_equals(document.rootScroller, container); + // The container is now fully scrolled. Normally, further scroll + // events would chain up to the parent element but, because the + // container is the root scroller, we shouldn't chain up past it. + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); - // Now scrolling over the <div> should scroll the scrollingElement since the - // rootElement is invalid (doesn't fill the viewport). - if (typeof eventSender !== 'undefined') { - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); - eventSender.gestureScrollBegin(500, 500); - eventSender.gestureScrollUpdate(-300, -300); - eventSender.gestureScrollEnd(0, 0); + assert_equals(container.scrollTop, 2000 - 600); + assert_equals(container.scrollLeft, 2000 - 800); + assert_equals(parentScroller.scrollTop, 0); + assert_equals(parentScroller.scrollLeft, 0); + } + }, "Scrolls don't chain past root scroller element"); - assert_equals(document.scrollingElement.scrollTop, 400); - assert_equals(document.scrollingElement.scrollLeft, 200); - } + test(function() { + document.rootScroller = container; + container.scrollTop = 999; + container.scrollLeft = 998; - // Don't output the text in spanner. - document.querySelector('#spanner').style.display = 'none'; + // Window.scrollX and scrollY should reflect the scroll offset of the + // rootScroller + assert_equals(container.scrollTop, 999); + assert_equals(container.scrollLeft, 998); + assert_equals(window.scrollY, container.scrollTop); + assert_equals(window.scrollX, container.scrollLeft); + assert_equals(document.scrollingElement.scrollTop, container.scrollTop); + assert_equals(document.scrollingElement.scrollLeft, container.scrollLeft); - }, 'Test the setRootScroller API basic functionality'); + }, "document.scrollingElement and window scroll API reflect rootScroller offsets"); + + test(function() { + // Making the current rootScroller an invalid scroller (by making it not + // fill the viewport) should fallback to the default element, the + // documentElement, but the rootScroller property should remain the same. + document.rootScroller = container; + container.style.width = "95%"; + assert_equals(document.rootScroller, container); + + // Reset parentScroller's offsets, make container fully scrolled. + parentScroller.scrollTop = 0; + parentScroller.scrollLeft = 0; + container.scrollTop = 10000; + container.scrollLeft = 10000; + + // Now scrolling over the container should scroll the scrollingElement + // since the rootElement is invalid (doesn't fill the viewport). + if (typeof eventSender !== 'undefined') { + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + eventSender.gestureScrollBegin(500, 500); + eventSender.gestureScrollUpdate(-300, -300); + eventSender.gestureScrollEnd(0, 0); + + assert_equals(parentScroller.scrollTop, 900); + assert_equals(parentScroller.scrollLeft, 900); + } + }, "Setting an invalid rootScroller should reset to using the documentElement."); </script>
diff --git a/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html b/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html index 5c9f28c..c81fdcb 100644 --- a/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html +++ b/third_party/WebKit/LayoutTests/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html
@@ -18,7 +18,7 @@ testRunner.dumpAsText(); window.onload = function () { - document.addEventListener('touchstart', function() { }); + document.addEventListener('touchstart', function() { }, {passive: false}); consoleWrite("Should have single rect on document before fullscreen"); window.internals.forceCompositingUpdate(document);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js index b5d0b04..29bcfbe 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js
@@ -12,7 +12,7 @@ var initialize_ExtensionsTest = function() { -WebInspector.extensionServer._overridePlatformExtensionAPIForTest = function(extensionInfo, inspectedTabId) +WebInspector.extensionServer._overridePlatformExtensionAPIForTest = function(extensionInfo, inspectedTabId, themeName) { WebInspector.extensionServer._registerHandler("evaluateForTestInFrontEnd", onEvaluate); @@ -20,6 +20,7 @@ { window.webInspector = coreAPI; window._extensionServerForTests = extensionServer; + coreAPI.panels.themeName = "themeNameForTest"; } return platformExtensionAPI.toString(); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js index 56701bf..c21526c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -962,9 +962,9 @@ InspectorTest.WorkerAgent = target.workerAgent(); InspectorTest.consoleModel = target.consoleModel; - InspectorTest.networkManager = target.networkManager; + InspectorTest.networkManager = WebInspector.NetworkManager.fromTarget(target); InspectorTest.resourceTreeModel = target.resourceTreeModel; - InspectorTest.networkLog = target.networkLog; + InspectorTest.networkLog = WebInspector.NetworkLog.fromTarget(target); InspectorTest.debuggerModel = WebInspector.DebuggerModel.fromTarget(target); InspectorTest.runtimeModel = target.runtimeModel; InspectorTest.domModel = WebInspector.DOMModel.fromTarget(target);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html index 28ab6ef..8939041 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html
@@ -8,7 +8,7 @@ function createNetworkRequest(mimeType, content, statusCode) { InspectorTest.addResult("Creating a NetworkRequest with mimeType: " + mimeType); - var request = new WebInspector.NetworkRequest(WebInspector.mainTarget, 0, 'http://localhost'); + var request = new WebInspector.NetworkRequest(WebInspector.targetManager.mainTarget(), 0, 'http://localhost'); InspectorTest.addResult("Content: " + content.replace(/\0/g, "**NULL**")); request.mimeType = mimeType; request._content = content; @@ -85,4 +85,4 @@ <body onload="runTest()"> <p>Tests to make sure the proper view is used for the data that is received in network panel.</p> </body> -</html> \ No newline at end of file +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering-expected.txt new file mode 100644 index 0000000..bdfdf97 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering-expected.txt
@@ -0,0 +1,52 @@ +Tests that info explanations are placed after regular explanations. + +<DIV class=security-explanation security-explanation-secure > + <DIV class=security-property security-property-secure > + </DIV> + <DIV class=security-explanation-text > + <DIV class=security-explanation-title > +Valid Certificate + </DIV> + <DIV > +The connection to this site is using a valid, trusted server certificate. + </DIV> + <BUTTON is=text-button type=button class=security-certificate-button > +View certificate + <#document-fragment > + <STYLE type=text/css > + </STYLE> + <STYLE type=text/css > + </STYLE> + <STYLE type=text/css > + </STYLE> + <CONTENT > + </CONTENT> + </#document-fragment> + </BUTTON> + </DIV> +</DIV> +<DIV class=security-explanation security-explanation-secure > + <DIV class=security-property security-property-secure > + </DIV> + <DIV class=security-explanation-text > + <DIV class=security-explanation-title > +Secure Resources + </DIV> + <DIV > +All resources on this page are served securely. + </DIV> + </DIV> +</DIV> +<DIV class=security-explanation security-explanation-info > + <DIV class=security-property security-property-info > + </DIV> + <DIV class=security-explanation-text > + <DIV class=security-explanation-title > +Public-Key Pinning Bypassed + </DIV> + <DIV > +Public-key pinning was bypassed by a local root certificate. + </DIV> + </DIV> +</DIV> +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html new file mode 100644 index 0000000..686b363 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
@@ -0,0 +1,42 @@ +<html> +<head> +<script src="../inspector-test.js"></script> +<script src="../security-test.js"></script> +<script> +function test() +{ + var mixedContentStatus = { ranInsecureContent: false, displayedInsecureContent: false}; + + // Explanations from https://cbc.badssl.com/ as of 2016-06-13. + // We explicitly place the explanation with the security state "info" + // first to make sure it gets reordered. + var explanations = [ + { + "description": "Public-key pinning was bypassed by a local root certificate.", + "securityState": "info", + "summary": "Public-Key Pinning Bypassed" + }, + { + "certificateId": 1, + "description": "The connection to this site is using a valid, trusted server certificate.", + "securityState": "secure", + "summary": "Valid Certificate" + } + ]; + + InspectorTest.mainTarget.model(WebInspector.SecurityModel).dispatchEventToListeners(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, new WebInspector.PageSecurityState(SecurityAgent.SecurityState.Secure, explanations, mixedContentStatus, true)); + + var request = new WebInspector.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null); + InspectorTest.dispatchRequestFinished(request); + + var explanations = WebInspector.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation"); + for (var i = 0; i < explanations.length; i++) + InspectorTest.dumpDeepInnerHTML(explanations[i]); + InspectorTest.completeTest(); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests that info explanations are placed after regular explanations.</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-initsegmentreceived-alg.html b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-initsegmentreceived-alg.html index c7aa122d..69ff7bc 100644 --- a/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-initsegmentreceived-alg.html +++ b/third_party/WebKit/LayoutTests/http/tests/media/media-source/mediasource-initsegmentreceived-alg.html
@@ -107,6 +107,46 @@ loadMediaAndVerifyAddedTracks(test, mediaElement, segmentInfo, sourceBuffer, mediaData, expectedAudioTrackInfo, expectedVideoTrackInfo, test.step_func_done()); }, "Track defaults processing in the init segment algorithm (no bytestream ids)"); + mediasource_test(function(test, mediaElement, mediaSource) + { + var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_VIDEO_TYPE); + var manifestFilenameA = subType + '/test-a-128k-44100Hz-1ch-manifest.json'; + var manifestFilenameV = subType + '/test-v-128k-320x240-30fps-10kfr-manifest.json'; + + MediaSourceUtil.fetchManifestAndData(test, manifestFilenameA, function(typeA, dataA) + { + MediaSourceUtil.fetchManifestAndData(test, manifestFilenameV, function(typeV, dataV) + { + var sourceBufferA = mediaSource.addSourceBuffer(typeA); + var sourceBufferV = mediaSource.addSourceBuffer(typeV); + sourceBufferA.trackDefaults = new TrackDefaultList([new TrackDefault("audio", "", "audio-label-for-track-bsid1", ["main"], "1")]); + sourceBufferV.trackDefaults = new TrackDefaultList([new TrackDefault("video", "", "video-label-for-track-bsid1", ["main"], "1")]); + + test.expectEvent(mediaElement.audioTracks, "addtrack", "mediaElement.audioTracks addtrack event"); + test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done."); + test.expectEvent(sourceBufferA, "updateend", "initSegment append ended."); + test.expectEvent(sourceBufferV, "updateend", "initSegment append ended."); + sourceBufferA.appendBuffer(dataA); + sourceBufferV.appendBuffer(dataV); + test.waitForExpectedEvents(function() + { + assert_equals(mediaElement.audioTracks.length, 1, "mediaElement.audioTracks.length"); + assert_equals(mediaElement.videoTracks.length, 1, "mediaElement.audioTracks.length"); + assert_equals(sourceBufferA.audioTracks.length, 1, "sourceBufferA.audioTracks.length"); + assert_equals(sourceBufferA.videoTracks.length, 0, "sourceBufferA.videoTracks.length"); + assert_equals(sourceBufferV.audioTracks.length, 0, "sourceBufferV.audioTracks.length"); + assert_equals(sourceBufferV.videoTracks.length, 1, "sourceBufferV.videoTracks.length"); + // Verify that audio track bytestream id == video track bytestream id == "1" + assert_equals(sourceBufferA.audioTracks[0].label, "audio-label-for-track-bsid1", "audio track bytestream id is 1"); + assert_equals(sourceBufferV.videoTracks[0].label, "video-label-for-track-bsid1", "video track bytestream id is 1"); + // Track ids generated for media tracks must be unique, even though the tracks have identical bytestream ids. + assert_not_equals(sourceBufferA.audioTracks[0].id, sourceBufferV.videoTracks[0].id, "track ids must be unique"); + test.done(); + }); + }); + }); + }, "Two source buffers with clashing bytestream track ids"); + </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-worker.php b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-worker.php index 1f2ebbbc..81bdd1bf 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-worker.php +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-worker.php
@@ -8,6 +8,8 @@ header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); +$extra_body = ''; + if ($mode == 'init') { // Set a normal mimetype. // Set cookie value to 'normal' so the next fetch will work in 'normal' mode. @@ -20,11 +22,21 @@ setcookie('mode', 'error'); } else if ($mode == 'error') { // Set a disallowed mimetype. - // Unset and delete cookie to clean up the test setting. + // Set cookie value to 'syntax-error' so the next fetch will work in 'syntax-error' mode. header('Content-Type:text/html'); + setcookie('mode', 'syntax-error'); +} else if ($mode == 'syntax-error') { + // Set cookie value to 'throw-install' so the next fetch will work in 'throw-install' mode. + header('Content-Type:application/javascript'); + setcookie('mode', 'throw-install'); + $extra_body = 'badsyntax(isbad;'; +} else if ($mode == 'throw-install') { + // Unset and delete cookie to clean up the test setting. + header('Content-Type:application/javascript'); unset($_COOKIE['mode']); setcookie('mode', '', time() - 3600); + $extra_body = "addEventListener('install', function(e) { throw new Error('boom'); });"; } // Return a different script for each access. -echo '// ' . microtime(); +echo '/* ', microtime(), ' */ ', $extra_body; ?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/update.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/update.html index 61a8a2df..82db192 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/update.html +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/update.html
@@ -9,7 +9,6 @@ var worker_url = 'resources/update-worker.php'; var expected_url = normalizeURL(worker_url); var registration; - return service_worker_unregister_and_register(t, worker_url, scope) .then(function(r) { registration = r; @@ -69,7 +68,52 @@ 'promise reject with a SecurityError.'); assert_equals(registration.active.scriptURL, expected_url, 'active should still exist after update failure.'); - return service_worker_unregister_and_done(t, scope); + + // A new worker(generated by update-worker.py) should be found. + // The returned promise should reject as update-worker.py returns + // a worker script with a syntax error. + return registration.update(); + }) + .then( + function() { assert_unreached("update() should reject."); }, + function(e) { + assert_throws({name: 'TypeError'}, function () { throw e; }, + 'A script syntax error should make update() ' + + 'promise reject with a TypeError.'); + assert_equals(registration.active.scriptURL, expected_url, + 'active should still exist after update failure.'); + + // A new worker(generated by update-worker.py) should be found. + // The returned promise should not reject, even though + // update-worker.py returns a worker script that throws in the + // install event handler. + return Promise.all([registration.update(), + wait_for_update(t, registration)]); + }) + .then(function() { + assert_equals(registration.installing.scriptURL, expected_url, + 'installing should be set after update resolves (throw-install).'); + assert_equals(registration.waiting, null, + 'waiting should still be null after update resolves (throw-install).'); + assert_equals(registration.active.scriptURL, expected_url, + 'active should still exist after update found (throw-install).'); + + // We need to hold a client alive so that unregister() below doesn't + // remove the registration before update() has had a chance to look + // at the pending uninstall flag. + return with_iframe(scope); + }) + .then(function(frame) { + return Promise.all([registration.unregister(), + registration.update()]); + }) + .then( + function() { assert_unreached("update() should reject."); }, + function(e) { + assert_throws({name: 'TypeError'}, function () { throw e; }, + 'Calling update() while the uninstalling flag is ' + + 'set should return a promise that rejects with an ' + + 'TypeError.'); }); }, 'Update a registration.'); </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 7ec0c9fe..e495d128 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -370,6 +370,7 @@ interface IDBObserver method constructor method observe + method unobserve interface IDBObserverChangesRecord getter key getter type
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt index 264f086..21a14ab5 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/update-the-source-set-expected.txt
@@ -1,8 +1,8 @@ CONSOLE WARNING: <source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead. CONSOLE ERROR: Failed parsing 'srcset' attribute value since it has multiple 'x' descriptors or a mix of 'x' and 'w'/'h' descriptors. CONSOLE ERROR: Dropped srcset candidate data:,b -CONSOLE ERROR: line 128: Failed parsing 'srcset' attribute value since it has multiple 'x' descriptors or a mix of 'x' and 'w'/'h' descriptors. -CONSOLE ERROR: line 128: Dropped srcset candidate data:,b +CONSOLE ERROR: line 138: Failed parsing 'srcset' attribute value since it has multiple 'x' descriptors or a mix of 'x' and 'w'/'h' descriptors. +CONSOLE ERROR: line 138: Dropped srcset candidate data:,b This is a testharness.js-based test. PASS <img data-expect=""> PASS <img src="" data-expect="">
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js index 64c08a9..0dba6f20 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js +++ b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js
@@ -66,9 +66,19 @@ return !!document.querySelector('script[src*="/resources/testharness"]'); } + function injectSyntheticInput() { var path = window.location.pathname; if (path.match(/imported\/wpt\/.*\.html$/)) { + // Set a global variable for the address of automated input script if they need to use it. + var automated_input_scripts_folder = path.replace(/imported\/wpt\/(.*)\.html$/, 'imported/wpt_automation'); + + importAutomationScript = function(relativePath) { + var common_script = document.createElement('script'); + common_script.setAttribute('src', automated_input_scripts_folder + relativePath); + document.head.appendChild(common_script); + } + path = path.replace(/imported\/wpt\/(.*)\.html$/, "imported/wpt_automation/$1-input.js"); var input_script = document.createElement('script'); input_script.setAttribute('src', path);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js index 2948039..d8ef5a6 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js
@@ -1,2 +1,6 @@ -if (window.eventSender) - eventSender.mouseMoveTo(200, 220); +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-input.js new file mode 100644 index 0000000..2c681ca2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-input.js
@@ -0,0 +1,10 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveIntoTarget('target1'); + mouseDragInTargets(['btnCapture', 'target1', 'target0']); + + // To handle delayed capturing + mouseMoveIntoTarget('target0'); +}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-input.js new file mode 100644 index 0000000..44ed0d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-input.js
@@ -0,0 +1,11 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveIntoTarget('target1'); + mouseDragInTargets(['btnCapture', 'target1', 'target0', 'target1']); + + // To handle delayed capturing + mouseMoveIntoTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_common_input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_common_input.js new file mode 100644 index 0000000..2604f69 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_common_input.js
@@ -0,0 +1,106 @@ +// This file contains the commonly used functions in pointerevent tests. + +// Mouse actions +function mouseMoveToDocument() { + if (window.eventSender) + eventSender.mouseMoveTo(0, 0); +} + +function mouseMoveIntoTarget(targetId) { + if (window.eventSender) { + var target = document.getElementById(targetId); + var targetRect = target.getBoundingClientRect(); + eventSender.mouseMoveTo(targetRect.left+5, targetRect.top+5); + } +} + +function mouseClickInTarget(targetId) { + if (window.eventSender) { + mouseMoveIntoTarget(targetId); + eventSender.mouseDown(0); + eventSender.mouseUp(0); + } +} + +function mouseDragInTargets(targetIdList) { + if (window.eventSender) { + var target = document.getElementById(targetIdList[0]); + mouseMoveIntoTarget(targetIdList[0]); + eventSender.mouseDown(0); + for (var i=1; i<targetIdList.length; i++) + mouseMoveIntoTarget(targetIdList[i]); + eventSender.mouseUp(0); + } +} + +function mouseDragInTarget(targetId) { + if (window.eventSender) { + var target = document.getElementById(targetId); + mouseMoveIntoTarget(targetId); + eventSender.mouseDown(0); + mouseMoveIntoTarget(targetId); + eventSender.mouseUp(0); + } +} + +function mouseScrollUp() { + if (window.eventSender) + eventSender.continuousMouseScrollBy(-50, 0); + +} + +function mouseScrollLeft() { + if (window.eventSender) + eventSender.continuousMouseScrollBy(0, -50); +} + +// Touch actions +function touchTapInTarget(targetId) { + if (window.chrome && chrome.gpuBenchmarking) { + var target = document.getElementById(targetId); + var targetRect = target.getBoundingClientRect(); + chrome.gpuBenchmarking.tap(targetRect.left+5, targetRect.top+5); + } +} + +function touchScrollUpInTarget(targetId) { + if (window.chrome && chrome.gpuBenchmarking) { + var target = document.getElementById(targetId); + var targetRect = target.getBoundingClientRect(); + chrome.gpuBenchmarking.smoothDrag(targetRect.left, targetRect.bottom-5, targetRect.left, targetRect.top+5); + } +} + +function touchScrollLeftInTarget(targetId) { + if (window.chrome && chrome.gpuBenchmarking) { + var target = document.getElementById(targetId); + var targetRect = target.getBoundingClientRect(); + chrome.gpuBenchmarking.smoothDrag(targetRect.right-5, targetRect.top+5, targetRect.left+5, targetRect.top+5); + } +} + +// Pen actions +function penMoveIntoTarget(target) { + var targetRect = target.getBoundingClientRect(); + eventSender.mouseMoveTo(targetRect.left+5, targetRect.top+5, [], "pen", 0); +} + +function penClickIntoTarget(target) { + penMoveIntoTarget(target); + eventSender.mouseDown(0, [], "pen", 0); + eventSender.mouseUp(0, [], "pen", 0); +} + +// Keyboard actions +function keyboardScrollUp() { + if (window.eventSender) + eventSender.keyDown('downArrow'); +} + +function keyboardScrollLeft() { + if (window.eventSender) + eventSender.keyDown('rightArrow'); +} + +// Defined in every test +inject_input();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-input.js new file mode 100644 index 0000000..18b1ecc0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseDragInTarget('btnCapture'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-input.js new file mode 100644 index 0000000..744912c --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-input.js
@@ -0,0 +1,9 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('btnCapture'); + + // To handle delayed capturing + mouseMoveIntoTarget('btnCapture'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js new file mode 100644 index 0000000..14dd4b5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); +} + +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js new file mode 100644 index 0000000..c08ae78 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js new file mode 100644 index 0000000..316468b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js new file mode 100644 index 0000000..05cf1b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchTapInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-input.js new file mode 100644 index 0000000..14dd4b5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); +} + +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-input.js new file mode 100644 index 0000000..05cf1b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchTapInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-input.js new file mode 100644 index 0000000..8fbc0a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseClickInTarget('target1'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-input.js new file mode 100644 index 0000000..a159a18 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-input.js
@@ -0,0 +1,9 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + if (window.eventSender) + eventSender.mouseMoveTo(100, 200); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-input.js new file mode 100644 index 0000000..316468b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-input.js new file mode 100644 index 0000000..316468b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js new file mode 100644 index 0000000..66bffa4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js
@@ -0,0 +1,10 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + if (window.eventSender) { + var target0 = document.getElementById('target0'); + penMoveIntoTarget(target0); + eventSender.mouseMoveTo(0, 0, [], "pen", 0); + } +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-input.js new file mode 100644 index 0000000..05cf1b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchTapInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-input.js new file mode 100644 index 0000000..c08ae78 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js new file mode 100644 index 0000000..0c31fb73 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseDragInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-input.js new file mode 100644 index 0000000..ebbe93e3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); + mouseMoveIntoTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-input.js new file mode 100644 index 0000000..316468b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js new file mode 100644 index 0000000..d73a444 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-input.js new file mode 100644 index 0000000..05cf1b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchTapInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-input.js new file mode 100644 index 0000000..66bffa4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-input.js
@@ -0,0 +1,10 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + if (window.eventSender) { + var target0 = document.getElementById('target0'); + penMoveIntoTarget(target0); + eventSender.mouseMoveTo(0, 0, [], "pen", 0); + } +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-input.js new file mode 100644 index 0000000..316468b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-input.js new file mode 100644 index 0000000..c08ae78 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-input.js new file mode 100644 index 0000000..cb9da76 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-input.js
@@ -0,0 +1,9 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + if (window.chrome && chrome.gpuBenchmarking) { + var target0 = document.getElementById('target0'); + penClickIntoTarget(target0); + } +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-input.js new file mode 100644 index 0000000..05cf1b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchTapInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-input.js new file mode 100644 index 0000000..0c31fb73 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseDragInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-input.js new file mode 100644 index 0000000..0c31fb73 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseDragInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-input.js new file mode 100644 index 0000000..d73a444 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-input.js new file mode 100644 index 0000000..dae01ba --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-input.js
@@ -0,0 +1,9 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('btnCapture'); + + // To Handle delayed capturing + mouseMoveIntoTarget('btnCapture'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-input.js new file mode 100644 index 0000000..316468b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target0'); + mouseMoveToDocument(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-input.js new file mode 100644 index 0000000..d8ef5a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-input.js
@@ -0,0 +1,6 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-input.js new file mode 100644 index 0000000..3ccadf2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseMoveIntoTarget('target1'); + mouseDragInTargets(['btnCapture', 'target0']); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js new file mode 100644 index 0000000..4fffdcf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-input.js new file mode 100644 index 0000000..4fffdcf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-input.js new file mode 100644 index 0000000..ba21768 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); + keyboardScrollUp(); + keyboardScrollLeft(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-input.js new file mode 100644 index 0000000..71eafbc --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + mouseClickInTarget('target0'); + mouseScrollUp(); + mouseScrollLeft(); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-input.js new file mode 100644 index 0000000..4fffdcf --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-input.js
@@ -0,0 +1,7 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-input.js new file mode 100644 index 0000000..d972b5a3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-input.js
@@ -0,0 +1,8 @@ +importAutomationScript('/pointerevents/pointerevent_common_input.js'); + +function inject_input() { + touchScrollUpInTarget('target0'); + touchScrollLeftInTarget('target0'); + touchTapInTarget('btnComplete'); +} +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/input/emulateTouchFromMouseEvent.html b/third_party/WebKit/LayoutTests/inspector-protocol/input/emulateTouchFromMouseEvent.html index f141e8c..802f29f 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/input/emulateTouchFromMouseEvent.html +++ b/third_party/WebKit/LayoutTests/inspector-protocol/input/emulateTouchFromMouseEvent.html
@@ -3,9 +3,9 @@ <script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> <script> -window.addEventListener("touchstart", logEvent); +window.addEventListener("touchstart", logEvent, {passive: false}); +window.addEventListener("touchmove", logEvent, {passive: false}); window.addEventListener("touchend", logEvent); -window.addEventListener("touchmove", logEvent); window.addEventListener("touchcancel", logEvent); function logEvent(event)
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.css b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.css new file mode 100644 index 0000000..c1b4b8b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.css
@@ -0,0 +1,2 @@ +@media (min-width: 6px){#container{border:1px solid blue;color:blue}} +/*# sourceMappingURL=styles-do-not-detach-sourcemap-on-edits.css.map */
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.css.map b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.css.map new file mode 100644 index 0000000..c932ea4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.css.map
@@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA,uBAAwB,CACpB,UAAW,CACP,MAAM,CAAE,cAAc,CACtB,KAAK,CAAE,IAAI", +"sources": ["styles-do-not-detach-sourcemap-on-edits.scss"], +"names": [], +"file": "styles-do-not-detach-sourcemap-on-edits.css" +}
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.scss b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.scss new file mode 100644 index 0000000..9b7eeef --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/resources/styles-do-not-detach-sourcemap-on-edits.scss
@@ -0,0 +1,6 @@ +@media (min-width: 6px) { + #container { + border: 1px solid blue; + color: blue; + } +}
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt new file mode 100644 index 0000000..c0e5b1e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-do-not-detach-sourcemap-on-edits-expected.txt
@@ -0,0 +1,82 @@ +Tests that source map is not detached on edits. crbug.com/257778 + +container. + +Running: editProperty +[expanded] +element.style { () + +[expanded] +@media (min-width: 6px) +#container { (styles-do-not-d…n-edits.scss:2 -> styles-do-not-detach-sourcemap-on-edits.scss:2:5) + border: 1px solid blue; + color: blue; + +[expanded] +div { (user agent stylesheet) + display: block; + + +Running: editSelector +[expanded] +element.style { () + +[expanded] +@media (min-width: 6px) +#container { (styles-do-not-d…n-edits.scss:2 -> styles-do-not-detach-sourcemap-on-edits.scss:2:5) + border: 1px solid blue; +/-- overloaded --/ NAME: VALUE; + +[expanded] +div { (user agent stylesheet) + display: block; + + +Running: editMedia +[expanded] +element.style { () + +[expanded] +@media (min-width: 6px) +#container, SELECTOR { (styles-do-not-d…n-edits.scss:2 -> styles-do-not-detach-sourcemap-on-edits.scss:2:5) + border: 1px solid blue; +/-- overloaded --/ NAME: VALUE; + +[expanded] +div { (user agent stylesheet) + display: block; + + +Running: addRule +[expanded] +element.style { () + +[expanded] +@media (max-width: 9999999px) +#container, SELECTOR { (styles-do-not-d…n-edits.scss:2 -> styles-do-not-detach-sourcemap-on-edits.scss:2:5) + border: 1px solid blue; +/-- overloaded --/ NAME: VALUE; + +[expanded] +div { (user agent stylesheet) + display: block; + + +Running: finish +[expanded] +element.style { () + +[expanded] [no-affect] +NEW-RULE { (styles-do-not-d…n-edits.scss:4 -> styles-do-not-detach-sourcemap-on-edits.scss:4:20) + +[expanded] +@media (max-width: 9999999px) +#container, SELECTOR { (styles-do-not-d…n-edits.scss:2 -> styles-do-not-detach-sourcemap-on-edits.scss:2:5) + border: 1px solid blue; +/-- overloaded --/ NAME: VALUE; + +[expanded] +div { (user agent stylesheet) + display: block; + +
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-do-not-detach-sourcemap-on-edits.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-do-not-detach-sourcemap-on-edits.html new file mode 100644 index 0000000..1a4fedc5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-do-not-detach-sourcemap-on-edits.html
@@ -0,0 +1,89 @@ +<html> +<head> + +<link rel="stylesheet" href="./resources/styles-do-not-detach-sourcemap-on-edits.css"> +<script src="../../../http/tests/inspector/debugger-test.js"></script> +<script src="../../../http/tests/inspector/elements-test.js"></script> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script> + +function test() +{ + InspectorTest.waitForScriptSource("styles-do-not-detach-sourcemap-on-edits.scss", onSourceMapLoaded); + + function onSourceMapLoaded() + { + InspectorTest.selectNodeAndWaitForStyles("container", onNodeSelected); + } + + function onNodeSelected() + { + InspectorTest.runTestSuite(testSuite); + } + + var testSuite = [ + function editProperty(next) + { + InspectorTest.dumpSelectedElementStyles(true, false, true); + + var treeItem = InspectorTest.getMatchedStylePropertyTreeItem("color"); + treeItem.applyStyleText("NAME: VALUE", true); + InspectorTest.waitForStyles("container", next); + }, + + function editSelector(next) + { + InspectorTest.dumpSelectedElementStyles(true, false, true); + + var section = InspectorTest.firstMatchedStyleSection(); + section.startEditingSelector(); + section._selectorElement.textContent = "#container, SELECTOR"; + InspectorTest.waitForSelectorCommitted(next); + section._selectorElement.dispatchEvent(InspectorTest.createKeyEvent("Enter")); + }, + + function editMedia(next) + { + InspectorTest.dumpSelectedElementStyles(true, false, true); + + var section = InspectorTest.firstMatchedStyleSection(); + var mediaTextElement = InspectorTest.firstMediaTextElementInSection(section); + mediaTextElement.click(); + mediaTextElement.textContent = "(max-width: 9999999px)"; + InspectorTest.waitForMediaTextCommitted(next); + mediaTextElement.dispatchEvent(InspectorTest.createKeyEvent("Enter")); + }, + + function addRule(next) + { + InspectorTest.dumpSelectedElementStyles(true, false, true); + + var styleSheetHeader = InspectorTest.cssModel.styleSheetHeaders().find(header => header.resourceURL().indexOf("styles-do-not-detach-sourcemap-on-edits.css") !== -1); + if (!styleSheetHeader) { + InspectorTest.addResult("ERROR: failed to find style sheet!"); + InspectorTest.completeTest(); + return; + } + InspectorTest.addNewRuleInStyleSheet(styleSheetHeader, "NEW-RULE", next); + }, + + function finish(next) + { + InspectorTest.dumpSelectedElementStyles(true, false, true); + next(); + }, + ]; +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests that source map is not detached on edits. crbug.com/257778 +</p> + +<div id="container">container.</div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-edit-property-after-invalid-rule.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-edit-property-after-invalid-rule.html index ce787fd..fbdd285 100644 --- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-edit-property-after-invalid-rule.html +++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-edit-property-after-invalid-rule.html
@@ -19,17 +19,17 @@ function test() { InspectorTest.selectNodeAndWaitForStyles("container", step1); - + function step1() { InspectorTest.addResult("Initial value"); InspectorTest.dumpSelectedElementStyles(true, false, true); - + var treeItem = InspectorTest.getMatchedStylePropertyTreeItem("padding"); treeItem.applyStyleText("padding: 20px", false); InspectorTest.waitForStyles("container", step2); } - + function step2() { InspectorTest.addResult("After changing property");
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt index ae39265..47c994c4 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt
@@ -46,6 +46,7 @@ removeListener : <function> } } + themeName : "themeNameForTest" } resources : { onFinished : {
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel-expected.txt b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel-expected.txt index 20afde0b..6ad7ff8 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel-expected.txt
@@ -69,5 +69,7 @@ status bar item 0, icon: ".../inspector/resources/button1-updated.png", tooltip: 'Button One tooltip', disabled: false status bar item 1, icon: ".../inspector/resources/button2.png", tooltip: 'Button Two updated tooltip', disabled: false button2 clicked +RUNNING TEST: extension_testThemeName +Theme name: themeNameForTest All tests done.
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html index e9d6010..9e4b20a 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html +++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
@@ -120,6 +120,12 @@ } } +function extension_testThemeName(nextTest) +{ + output("Theme name: " + webInspector.panels.themeName); + nextTest(); +} + function extension_testCreatePanel(nextTest) { var expectOnShown = false; @@ -215,7 +221,7 @@ panel.onSearch.addListener(callback); extension_showPanel("extension"); - + function performSearch(query) { var panel = WebInspector.inspectorView.currentPanel();
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html index 117e222..31573919 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html +++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html
@@ -4,7 +4,6 @@ <script src="../../http/tests/inspector/console-test.js"></script> <script src="../../http/tests/inspector/extensions-test.js"></script> <script src="../../http/tests/inspector/debugger-test.js"></script> - <script type="text/javascript"> function loadFrame(callback) { @@ -25,8 +24,10 @@ InspectorTest.clickOnURL = function() { WebInspector.ConsolePanel.show(); + WebInspector.ConsoleView.instance()._updateMessageList(); var xpathResult = document.evaluate("//a[starts-with(., 'test-script.js')]", - WebInspector.panels.console.element, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null); + WebInspector.ConsoleView.instance().element, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null); + var click = document.createEvent("MouseEvent"); click.initMouseEvent("click", true, true); xpathResult.singleNodeValue.dispatchEvent(click);
diff --git a/third_party/WebKit/LayoutTests/inspector/input-event-warning-expected.txt b/third_party/WebKit/LayoutTests/inspector/input-event-warning-expected.txt index 4ced2c4..51d6c697 100644 --- a/third_party/WebKit/LayoutTests/inspector/input-event-warning-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/input-event-warning-expected.txt
@@ -1,7 +1,7 @@ Tests that console warnings are issued for a blocked event listener and that there is no crash when an offending listener is removed by the handler. There should be no warnings above this line -Handling of 'wheel' input event was delayed for <number> ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responive. -Handling of 'touchstart' input event was delayed for <number> ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responive. -Handling of 'touchmove' input event was delayed for <number> ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responive. +Handling of 'wheel' input event was delayed for <number> ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responsive. +Handling of 'touchstart' input event was delayed for <number> ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responsive. +Handling of 'touchmove' input event was delayed for <number> ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responsive.
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html b/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html index 84eb6c51..0ece6db 100644 --- a/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html +++ b/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html
@@ -16,7 +16,7 @@ var urls = document.evaluate("//tbody/tr/td[position()=1]/@title", dataGrid, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var outputStrings = []; - for (var request of WebInspector.targetManager.mainTarget().networkLog._requests) { + for (var request of WebInspector.NetworkLog.fromTarget(WebInspector.targetManager.mainTarget())._requests) { var line = request.displayName + ":" + request.statusCode + " " + request.statusText if (request.failed) line += "(failed)";
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js index c52f23a..5fcd616 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-breakpoints/breakpoint-manager.js
@@ -48,6 +48,8 @@ return this._target; }, + _targetDisposed: function() { }, + debuggerEnabled: function() { return true;
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details-expected.txt index e043b9d2..0ad0a51 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details-expected.txt
@@ -3,41 +3,70 @@ Running: testIterNotStarted iterNotStarted: type = object, subtype = generator -functionName: "gen" -lineNumber: 14 -columnNumber: 13 -scriptId is valid: true -status: suspended +[[GeneratorStatus]] = suspended +[[GeneratorFunction]] = function* gen() +{ + yield 1; + yield 2; + yield 3; +} +[[GeneratorReceiver]] = Window +lineNumber = 13 +columnNumber = 13 +script is valid: yes Running: testIterSuspended iterSuspended: type = object, subtype = generator -functionName: "gen" -lineNumber: 16 -columnNumber: 4 -scriptId is valid: true -status: suspended +[[GeneratorStatus]] = suspended +[[GeneratorFunction]] = function* gen() +{ + yield 1; + yield 2; + yield 3; +} +[[GeneratorReceiver]] = Window +lineNumber = 15 +columnNumber = 4 +script is valid: yes Running: testIterClosed iterClosed: type = object, subtype = generator -functionName: "gen" -lineNumber: 14 -columnNumber: 13 -scriptId is valid: true -status: closed +[[GeneratorStatus]] = closed +[[GeneratorFunction]] = function* gen() +{ + yield 1; + yield 2; + yield 3; +} +[[GeneratorReceiver]] = Window +lineNumber = 13 +columnNumber = 13 +script is valid: yes Running: testIterObjGenerator iterObjGenerator: type = object, subtype = generator -functionName: "generator" -lineNumber: 25 -columnNumber: 8 -scriptId is valid: true -status: suspended +[[GeneratorStatus]] = suspended +[[GeneratorFunction]] = function* () + { + yield 11; + yield 12; + yield 13; + } +[[GeneratorReceiver]] = Object +lineNumber = 24 +columnNumber = 8 +script is valid: yes Running: testAnonymousGenIter anonymousGenIter: type = object, subtype = generator -functionName: "" -lineNumber: 39 -columnNumber: 4 -scriptId is valid: true -status: suspended +[[GeneratorStatus]] = suspended +[[GeneratorFunction]] = function* () { + yield 21; + yield 22; + yield 23; +} +[[GeneratorReceiver]] = Window +lineNumber = 38 +columnNumber = 4 +script is valid: yes
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details.html index 5f5af6d8..a63a2f3 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-generator-details.html
@@ -42,15 +42,6 @@ function test() { - function dumpGeneratorObjectDetails(details) - { - InspectorTest.addResult("functionName: \"" + details.functionName + "\""); - InspectorTest.addResult("lineNumber: " + (details.location.lineNumber + 1)); - InspectorTest.addResult("columnNumber: " + details.location.columnNumber); - InspectorTest.addResult("scriptId is valid: " + !!details.location.scriptId); - InspectorTest.addResult("status: " + details.status); - } - function performStandardTestCase(pageExpression, next) { InspectorTest.evaluateInPage(pageExpression, didEvaluate); @@ -58,15 +49,27 @@ function didEvaluate(remote) { InspectorTest.addResult(pageExpression + ": type = " + remote.type + ", subtype = " + remote.subtype); - InspectorTest.DebuggerAgent.getGeneratorObjectDetails(remote.objectId, didGetDetails); + remote.getOwnPropertiesPromise().then(dumpInternalProperties); } - function didGetDetails(error, response) + function dumpInternalProperties(properties) { - InspectorTest.assertTrue(!error, "FAIL: " + error); - dumpGeneratorObjectDetails(response); + InspectorTest.assertTrue(properties && properties.internalProperties, "FAIL: no properties"); + for (var prop of properties.internalProperties) { + if (prop.name !== "[[GeneratorLocation]]") + InspectorTest.addResult(prop.name + " = " + prop.value.description); + else + dumpLocation(prop.value.value); + } next(); } + + function dumpLocation(location) + { + InspectorTest.addResult("lineNumber = " + location.lineNumber); + InspectorTest.addResult("columnNumber = " + location.columnNumber); + InspectorTest.addResult("script is valid: " + (location.scriptId ? "yes" : "no")); + } } var expressions = [
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model-expected.txt index 155411e..7a147a3 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model-expected.txt
@@ -69,3 +69,5 @@ Last evaluation source url for snippet: snippets:///1_1 Snippet execution result: 4 +Running: testDangerousNames +
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html index 82678cd..4f2a1bd 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/script-snippet-model.html
@@ -281,6 +281,30 @@ evaluateSnippetAndDumpEvaluationDetails(uiSourceCode, context, next); } }, + + function testDangerousNames(next) + { + resetSnippetsSettings(); + + WebInspector.scriptSnippetModel.project().createFile("", null, "", step2.bind(this)); + + function step2(uiSourceCode) + { + uiSourceCode.rename("toString", function() { }); + InspectorTest.showUISourceCode(uiSourceCode,step3.bind(this)); + } + + function step3() + { + WebInspector.scriptSnippetModel.project().createFile("", null, "", step4.bind(this)); + } + + function step4(uiSourceCode) + { + uiSourceCode.rename("myfile.toString", function() { }); + InspectorTest.showUISourceCode(uiSourceCode,next); + } + } ]); }; </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-generator-location.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-generator-location.html index 6c41f6c..2a159f4 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-generator-location.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-generator-location.html
@@ -35,7 +35,19 @@ function didEvaluate(remote) { - panel._showGeneratorLocation(remote); + remote.getOwnPropertiesPromise().then(revealLocation.bind(null, remote)); + } + + function revealLocation(remote, properties) + { + var loc; + for (var prop of properties.internalProperties) { + if (prop.name === "[[GeneratorLocation]]") { + loc = prop.value.value; + break; + } + } + WebInspector.Revealer.reveal(remote.debuggerModel().createRawLocationByScriptId(loc.scriptId, loc.lineNumber, loc.columnNumber)); } function showUISourceCodeHook(uiSourceCode, lineNumber, columnNumber, forceShowInPanel)
diff --git a/third_party/WebKit/LayoutTests/media/video-defaultmuted-expected.txt b/third_party/WebKit/LayoutTests/media/video-defaultmuted-expected.txt deleted file mode 100644 index d718364..0000000 --- a/third_party/WebKit/LayoutTests/media/video-defaultmuted-expected.txt +++ /dev/null
@@ -1,72 +0,0 @@ -Test 'muted' content attribute - - - -*** Test with 'muted' content attribute - -RUN(video = document.createElement('video')) -RUN(video.setAttribute('controls', 'controls')) -RUN(video.setAttribute('muted', 'muted')) - -*** Test before setting src, IDL attribute should default to false -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'true') OK - -EVENT(loadedmetadata) - -*** After setting url, content attribute should have set IDL attribute -EXPECTED (video.muted == 'true') OK -EXPECTED (video.defaultMuted == 'true') OK - -*** Change 'defaultMuted', IDL attribute should not change but content attribute should. -RUN(video.defaultMuted = false) -EXPECTED (video.muted == 'true') OK -EXPECTED (video.defaultMuted == 'false') OK -EXPECTED (video.hasAttribute('muted') == 'false') OK - -*** Change 'muted' IDL attribute, content attribute should not change -RUN(video.muted = false) -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'false') OK -EXPECTED (video.hasAttribute('muted') == 'false') OK - -*** Remove 'muted' content attribute, it should have no effect on IDL attribute -RUN(video.removeAttribute('muted')) -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'false') OK - - -*** Test without 'muted' content attribute - -RUN(video = document.createElement('video')) -RUN(video.setAttribute('controls', 'controls')) - -*** Test before setting src, IDL attribute should default to false -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'false') OK - -EVENT(loadedmetadata) - -*** After setting url, content attribute should have set IDL attribute -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'false') OK - -*** Change 'defaultMuted', IDL attribute should not change but content attribute should. -RUN(video.defaultMuted = true) -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'true') OK -EXPECTED (video.hasAttribute('muted') == 'true') OK - -*** Change 'muted' IDL attribute, content attribute should not change -RUN(video.muted = false) -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'true') OK -EXPECTED (video.hasAttribute('muted') == 'true') OK - -*** Add 'muted' content attribute, it should have no effect on IDL attribute -RUN(video.setAttribute('muted', 'muted')) -EXPECTED (video.muted == 'false') OK -EXPECTED (video.defaultMuted == 'true') OK - -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-defaultmuted.html b/third_party/WebKit/LayoutTests/media/video-defaultmuted.html index f58e5ce8..67623dd 100644 --- a/third_party/WebKit/LayoutTests/media/video-defaultmuted.html +++ b/third_party/WebKit/LayoutTests/media/video-defaultmuted.html
@@ -1,92 +1,38 @@ -<!doctype html> -<html> - <head> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> - <script src=media-file.js></script> - <script> - var index = 0; +<!DOCTYPE html> +<title>Test "defaultMuted" IDL, "muted" IDL and content attributes.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<script> +test(function() { + var video = document.createElement("video"); + // Test that "defaultMuted" IDL attribute reflects "muted" content attribute and + // that "muted" IDL attribute is not affected by content attribute. + assert_false(video.muted); + assert_false(video.defaultMuted); + video.setAttribute("muted", "muted"); + assert_false(video.muted); + assert_true(video.defaultMuted); + video.removeAttribute("muted", "muted"); + assert_false(video.muted); + assert_false(video.defaultMuted); - function testMuted(expectedMuted, expectedDefaultMuted) - { - testExpected("video.muted", expectedMuted); - testExpected("video.defaultMuted", expectedDefaultMuted); - } + // Test that "muted" IDL attribute is not affected by "defaultMuted" IDL attribute. + video.defaultMuted = true; + assert_false(video.muted); +}, "Test 'defaultMuted' and 'muted' IDL attributes"); - function test(defaultMuted) - { - consoleWrite("<br><br><b>*** Test <em>" + (defaultMuted ? "with" : "without") + "</em> 'muted' content attribute</b><br>"); +async_test(function(t) { + var video = document.createElement("video"); + // Set "muted" content attribute and it should set "muted" IDL attribute on video load. + // This is wrong per spec. See https://crbug.com/350303 for details. + video.setAttribute("muted", "muted"); - run("video = document.createElement('video')"); - run("video.setAttribute('controls', 'controls')"); - video.setAttribute('width', '300'); - if (defaultMuted) - run("video.setAttribute('muted', 'muted')"); - document.getElementById('parent').appendChild(video); + video.onloadedmetadata = t.step_func_done(function() { + // "muted" IDL attribute should have been set. + assert_true(video.muted); + }); - consoleWrite("<br>*** Test before setting src, IDL attribute should default to false"); - testMuted(false, defaultMuted); - - var loadedmetadata = function(evt) - { - consoleWrite("<br>EVENT(" + evt.type + ")"); - - consoleWrite("<br>*** After setting url, content attribute should have set IDL attribute"); - testMuted(defaultMuted, defaultMuted); - - consoleWrite("<br>*** Change 'defaultMuted', IDL attribute should not change but content attribute should."); - var newDefaultMuted = !defaultMuted; - run("video.defaultMuted = " + newDefaultMuted); - testMuted(defaultMuted, newDefaultMuted); - testExpected("video.hasAttribute('muted')", newDefaultMuted); - - consoleWrite("<br>*** Change 'muted' IDL attribute, content attribute should not change"); - run("video.muted = false"); - testMuted(false, newDefaultMuted); - testExpected("video.hasAttribute('muted')", newDefaultMuted); - - var action = defaultMuted ? "Remove" : "Add"; - consoleWrite("<br>*** " + action + " 'muted' content attribute, it should have no effect on IDL attribute"); - if (defaultMuted) - run("video.removeAttribute('muted')"); - else - run("video.setAttribute('muted', 'muted')"); - testMuted(false, video.hasAttribute('muted')); - - runNextTest(); - } - video.addEventListener('loadedmetadata', loadedmetadata); - video.src = findMediaFile("audio", "content/test"); - } - - function runNextTest() - { - if (video) { - video.parentNode.removeChild(video); - video = null; - } - - switch (++index) - { - case 1: - test(true); - break; - case 2: - test(false); - break; - case 3: - consoleWrite(""); - endTest(); - break; - } - } - - </script> - </head> - - <body onload="runNextTest()"> - <div id="parent"></div> - <p>Test 'muted' content attribute<p> - </body> -</html> + video.src = findMediaFile("audio", "content/test"); +}, "Test 'muted' content and IDL attributes on video load"); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime-expected.txt b/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime-expected.txt deleted file mode 100644 index 2cf8a59..0000000 --- a/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -Test currentTime values when setting from seeking event. - - -loadedmetadata() -doNextSeek() 0 -doNextSeek() seeking to 1.00 -seeking 1.00 -doNextSeek() 1 -doNextSeek() seeking to 1.50 -seeking 1.50 -doNextSeek() 2 -doNextSeek() seeking to 1.50 -seeking 1.50 -doNextSeek() 3 -seeked 1.50 -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime.html b/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime.html index b125afdc..fe5e533 100644 --- a/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime.html +++ b/third_party/WebKit/LayoutTests/media/video-double-seek-currentTime.html
@@ -1,84 +1,32 @@ <!DOCTYPE html> -<html> - <head> - <script src=media-file.js></script> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> - <script> - var seekCount = 0; - var expectedSeek = 0; - var video; +<title>Test double seek currentTime.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<video></video> +<script> +// Seek to same time twice and make sure "seeking" is fired twice and that +// "seeked" is fired only once with the "currentTime" being the time set. +async_test(function(t) { + var timeToTest = 1.5; + var video = document.querySelector("video"); - function seeking(e) - { - consoleWrite("seeking " + e.target.currentTime.toFixed(2)); + var watcher = new EventWatcher(t, video, ["loadedmetadata", "seeking", "seeked"]); + watcher.wait_for("loadedmetadata").then(t.step_func(function() { + video.currentTime = 1.0; + return watcher.wait_for("seeking"); + })).then(t.step_func(function() { + video.currentTime = timeToTest; + return watcher.wait_for("seeking"); + })).then(t.step_func(function() { + video.currentTime = timeToTest; + return watcher.wait_for("seeking"); + })).then(t.step_func(function() { + return watcher.wait_for("seeked"); + })).then(t.step_func_done(function() { + assert_equals(video.currentTime, timeToTest); + })); - doNextSeek(e.target); - } - - function seeked(e) - { - consoleWrite("seeked " + e.target.currentTime.toFixed(2)); - - video = e.target; - var now = e.target.currentTime.toFixed(2); - var expected = expectedSeek.toFixed(2); - if (now != expected) { - failTest("Expected " + expectedSeek + " got " + now); - return; - } - endTest(); - } - - function doNextSeek(video) - { - consoleWrite("doNextSeek() " + seekCount); - - var newSeekPoint = -1; - switch (seekCount) { - case 0: - newSeekPoint = 1; - break; - case 1: - newSeekPoint = 1.5; - break; - case 2: - newSeekPoint = 1.5; - break; - }; - - if (newSeekPoint >= 0) { - consoleWrite('doNextSeek() seeking to ' + newSeekPoint.toFixed(2)); - expectedSeek = newSeekPoint; - video.currentTime = newSeekPoint; - } - seekCount++; - } - - function loadedmetadata(e) - { - consoleWrite("loadedmetadata()"); - doNextSeek(e.target); - } - - function onWindowLoad(e) - { - video = document.getElementById('video'); - - video.src = findMediaFile("video", "content/test"); - video.addEventListener('seeking', seeking); - video.addEventListener('seeked', seeked); - video.addEventListener('loadedmetadata', loadedmetadata); - video.load(); - } - - window.addEventListener('load', onWindowLoad, false); - </script> - </head> - <body> - <video controls id="video"></video> - <p>Test currentTime values when setting from seeking event.</p> - <br/> - </body> -</html> + video.src = findMediaFile("video", "content/test"); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-loop-expected.txt b/third_party/WebKit/LayoutTests/media/video-loop-expected.txt deleted file mode 100644 index 2e5fa75..0000000 --- a/third_party/WebKit/LayoutTests/media/video-loop-expected.txt +++ /dev/null
@@ -1,63 +0,0 @@ -Test looping by: - -Play to end with 'loop' set to true. -When 'seeked' event fires, verify that time has jumped back and movie is playing. -Set 'loop' to false and play again. -Verify that 'ended' event fires. -++ Test setting/removing the attribute. -EXPECTED (video.getAttribute('loop') == 'null') OK -EXPECTED (video.loop == 'false') OK -RUN(video.loop = true) -EXPECTED (video.loop == 'true') OK -EXPECTED (video.getAttribute('loop') != 'null') OK -RUN(video.removeAttribute('loop')) -EXPECTED (video.loop == 'false') OK - -++ Set 'loop' to true and begin playing. -RUN(video.loop = true) - -EVENT(play) - -++ seek to near the end, wait for 'seeked' event to announce loop. -EXPECTED (video.paused == 'false') OK -RUN(video.pause()) -RUN(video.currentTime = video.duration - 0.4) - -EVENT(pause) -EVENT(seeked) - -++ first seek completed, beginning playback. -EXPECTED (video.paused == 'true') OK -EXPECTED (video.ended == 'false') OK -RUN(video.play()) - -EVENT(play) -EVENT(seeked) - -++ second seek completed because video looped, toggle 'loop' and seek to near end again. -EXPECTED (video.paused == 'false') OK -EXPECTED (video.ended == 'false') OK -RUN(video.pause()) -EXPECTED (mediaElement.currentTime >= '0') OK -EXPECTED (mediaElement.currentTime < 'mediaElement.duration') OK -RUN(video.loop = false) -RUN(video.currentTime = video.duration - 0.4) - -EVENT(pause) -EVENT(seeked) - -++ third seek completed, beginning playback for the last time. -EXPECTED (video.paused == 'true') OK -EXPECTED (video.ended == 'false') OK -RUN(video.play()) - -EVENT(play) -EVENT(pause) -EVENT(ended) - -++ played to end and stopped. -EXPECTED (video.ended == 'true') OK -EXPECTED (mediaElement.currentTime == 'mediaElement.duration') OK - -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-loop-from-ended-expected.txt b/third_party/WebKit/LayoutTests/media/video-loop-from-ended-expected.txt deleted file mode 100644 index 37d35a6..0000000 --- a/third_party/WebKit/LayoutTests/media/video-loop-from-ended-expected.txt +++ /dev/null
@@ -1,49 +0,0 @@ -Test looping edge case to verify http://crbug.com/364442. Steps: - -Seek toward end of video (for faster testing). -Play video to end with 'loop' set to false. -Once ended, set 'loop' to true. -Call play. -Verify that 'seeked' event fires, seeking back to the beginning. -Pause video and end test. - -++ Video is initially paused and 'loop' unset. -EXPECTED (video.paused == 'true') OK -EXPECTED (video.loop == 'false') OK - -++ Seek to just before the end of the video and play. -RUN(video.currentTime = video.duration - .5) -RUN(video.play()) - -EVENT(play) -EVENT(ended) - -++ Verify played to end and stopped. -EXPECTED (video.ended == 'true') OK -EXPECTED (video.paused == 'true') OK -EXPECTED (video.currentTime == 'video.duration') OK - -++ With playback ended, set 'loop' attribute. This will cause ended == false; looping video cannot be 'ended', only paused. -EXPECTED (video.loop == 'false') OK -RUN(video.loop = true) -EXPECTED (video.loop == 'true') OK -EXPECTED (video.ended == 'false') OK -EXPECTED (video.paused == 'true') OK - -++ Play video with 'loop' set. Expect seek back to start. -RUN(video.play()) - -EVENT(play) -EVENT(seeked) - -++ Observed seek. Verify current time decreased and still playing. -EXPECTED (video.loop == 'true') OK -EXPECTED (video.paused == 'false') OK -EXPECTED (video.ended == 'false') OK -EXPECTED (video.currentTime < 'video.duration') OK - -++ Pausing now that test is over to prevent additional unwanted looping. -RUN(video.pause()) - -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-loop-from-ended.html b/third_party/WebKit/LayoutTests/media/video-loop-from-ended.html index bc4b771..a441d48 100644 --- a/third_party/WebKit/LayoutTests/media/video-loop-from-ended.html +++ b/third_party/WebKit/LayoutTests/media/video-loop-from-ended.html
@@ -1,89 +1,55 @@ <!DOCTYPE html> -<html> - <head> - <script src=media-file.js></script> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> +<title>Test looping edge case to verify http://crbug.com/364442.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<video></video> +<script> +// Seek towards end of video (for faster testing). +// Play video to end with "loop" set to false. +// Once ended, set "loop" to true. Call play. +// Verify that "seeked" event fires, seeking back to the beginning. +// Pause video and end test. +async_test(function(t) { + var video = document.querySelector("video"); - <script> - function start() - { - findMediaElement(); - var mediaFile = findMediaFile("video", "content/test"); - video.src = mediaFile; + video.onloadedmetadata = t.step_func(function() { + // Video is initially paused and "loop" unset. + assert_true(video.paused); + assert_false(video.loop); + // Seek to just before the end of the video and play. + video.currentTime = video.duration - 0.5; + video.onended = t.step_func(function() { + // Verify played to end and stopped. + assert_true(video.ended); + assert_true(video.paused); + assert_equals(video.currentTime, video.duration); - consoleWrite("<br><em>++ Video is initially paused and 'loop' unset.</em>"); - testExpected("video.paused", true) - testExpected("video.loop", false); + // With playback ended, set "loop" attribute. This will cause ended == false. + // looping video cannot be "ended", only paused. + assert_false(video.loop); + video.loop = true; + assert_true(video.loop); + assert_false(video.ended); + assert_true(video.paused); - seekThenPlayWhenReady(); - } + video.onseeked = t.step_func_done(function() { + // Observed seek. Verify current time decreased and still playing. + assert_true(video.loop) + assert_false(video.paused); + assert_false(video.ended); + assert_less_than(video.currentTime, video.duration); + // Pausing now that test is over to prevent additional unwanted looping. + video.pause(); + }); - function seekThenPlayWhenReady() { - if (video.readyState < HTMLMediaElement.HAVE_METADATA) { - setTimeout(seekThenPlayWhenReady, 100); - return; - } + // Play video with "loop" set. Expect seek back to start. + video.play(); + }); - consoleWrite("<br><em>++ Seek to just before the end of the video and play.</em>"); - run("video.currentTime = video.duration - .5"); - waitForEvent("play"); - waitForEvent("ended", ended); - run("video.play()"); - consoleWrite(""); - } + video.play(); + }); - function ended() - { - consoleWrite("<br><em>++ Verify played to end and stopped.</em>"); - testExpected("video.ended", true); - testExpected("video.paused", true); - // Using reportExpected to avoid logging floating point value which may differ across engines. - reportExpected(video.currentTime == video.duration, "video.currentTime", "==", "video.duration", video.currentTime); - - consoleWrite("<br><em>++ With playback ended, set 'loop' attribute. This will cause ended == false; looping video cannot be 'ended', only paused.</em>"); - testExpected("video.loop", false); - run("video.loop = true"); - testExpected("video.loop", true); - testExpected("video.ended", false); - testExpected("video.paused", true); - - consoleWrite("<br><em>++ Play video with 'loop' set. Expect seek back to start.<em>"); - waitForEvent("seeked", seeked); - run("video.play()"); - consoleWrite(""); - } - - function seeked() - { - consoleWrite("<br><em>++ Observed seek. Verify current time decreased and still playing.</em>"); - testExpected("video.loop", true); - testExpected("video.paused", false); - testExpected("video.ended", false); - // Using reportExpected to avoid logging floating point value which may differ across engines. - reportExpected(video.currentTime < video.duration, "video.currentTime", "<", "video.duration", video.currentTime); - - consoleWrite("<br><em>++ Pausing now that test is over to prevent additional unwanted looping.</em>"); - run("video.pause()"); - consoleWrite(""); - endTest(); - } - </script> - - </head> - <body> - <video controls></video> - <p><b>Test looping edge case to verify http://crbug.com/364442. Steps:</b> - <ol> - <li>Seek toward end of video (for faster testing).</li> - <li>Play video to end with 'loop' set to false.</li> - <li>Once ended, set 'loop' to true.</li> - <li>Call play.</li> - <li>Verify that 'seeked' event fires, seeking back to the beginning.</li> - <li>Pause video and end test.</li> - </ol> - </p> - <script>start()</script> - </body> -</html> + video.src = findMediaFile("video", "content/test"); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-loop.html b/third_party/WebKit/LayoutTests/media/video-loop.html index 3cdfbda3..4aee3df 100644 --- a/third_party/WebKit/LayoutTests/media/video-loop.html +++ b/third_party/WebKit/LayoutTests/media/video-loop.html
@@ -1,124 +1,73 @@ <!DOCTYPE html> -<html> - <head> - <script src=media-file.js></script> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> +<title>Test video looping.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<video autoplay></video> +<script> +// Test looping by: +// Play to end with "loop" set to true. +// When "seeked" event fires, verify that time has jumped back and movie is playing. +// Set "loop" to false and play again. +// Verify that "ended" event fires. +async_test(function(t) { + var video = document.querySelector("video"); + // Test setting/removing the attribute. + assert_equals(video.getAttribute("loop"), null); + assert_false(video.loop); - <script> - var seekCount = 0; - var playCount = 0; + video.loop = true; + assert_true(video.loop); + assert_not_equals(video.getAttribute("loop"), null); - function play() - { - if (video.readyState < HTMLMediaElement.HAVE_METADATA) { - setTimeout(play, 100); - return; - } + video.removeAttribute("loop"); + assert_false(video.loop); - if (++playCount > 1) - return; + video.onplay = t.step_func(function() { + video.onplay = null; + assert_false(video.paused); - consoleWrite("<br><em>++ seek to near the end, wait for 'seeked' event to announce loop.</em>"); - testExpected("video.paused", false); - - // Pause playback so the movie can't possibly loop before the seeked event fires - run("video.pause()"); - waitForEvent("seeked", seeked); - run("video.currentTime = video.duration - 0.4"); - consoleWrite(""); + // Pause playback so the movie can't possibly loop before the seeked event fires. + video.pause(); + // seek to near the end, wait for "seeked" event to announce loop. + var seekCount = 0; + video.onseeked = t.step_func(function() { + switch (++seekCount) { + case 1: + // first seek completed, beginning playback. + assert_true(video.paused); + assert_false(video.ended); + video.play(); + break; + case 2: + // second seek completed because video looped, toggle "loop" and seek to near end again. + assert_false(video.paused); + assert_false(video.ended); + video.pause(); + assert_greater_than_equal(video.currentTime, 0); + assert_less_than(video.currentTime, video.duration); + video.loop = false; + video.currentTime = video.duration - 0.4; + break; + case 3: + // third seek completed, beginning playback for the last time. + assert_true(video.paused); + assert_false(video.ended); + video.play(); + break; } + }); - function seeked() - { - switch (++seekCount) - { - case 1: - consoleWrite("<br><em>++ first seek completed, beginning playback.</em>"); - testExpected("video.paused", true); - testExpected("video.ended", false); - run("video.play()"); - consoleWrite(""); - break; - case 2: - consoleWrite("<br><em>++ second seek completed because video looped, toggle 'loop' and seek to near end again.</em>"); - testExpected("video.paused", false); - testExpected("video.ended", false); - run("video.pause()"); + video.currentTime = video.duration - 0.4; + }); - testExpected("mediaElement.currentTime", 0, '>='); + video.onended = t.step_func_done(function() { + assert_true(video.ended); + assert_equals(video.currentTime, video.duration); + }); - // don't use "testExpected()" so we won't log the actual duration as the floating point result may differ with different engines - reportExpected(mediaElement.currentTime < mediaElement.duration, "mediaElement.currentTime", "<", "mediaElement.duration", mediaElement.currentTime); - run("video.loop = false"); - run("video.currentTime = video.duration - 0.4"); - consoleWrite(""); - break; - case 3: - consoleWrite("<br><em>++ third seek completed, beginning playback for the last time.</em>"); - testExpected("video.paused", true); - testExpected("video.ended", false); - run("video.play()"); - consoleWrite(""); - break; - default: - failTest("Video should have only seeked three times."); - break; - - } - } - - function ended() - { - consoleWrite("<br><em>++ played to end and stopped.</em>"); - testExpected("video.ended", true); - - // don't use "testExpected()" so we won't log the actual duration as the floating point result may differ with different engines - reportExpected(mediaElement.currentTime == mediaElement.duration, "mediaElement.currentTime", "==", "mediaElement.duration", mediaElement.currentTime); - - consoleWrite(""); - endTest(); - } - - function start() - { - findMediaElement(); - - consoleWrite("<em>++ Test setting/removing the attribute.</em>"); - testExpected("video.getAttribute('loop')", null); - testExpected("video.loop", false); - - run("video.loop = true"); - testExpected("video.loop", true); - testExpected("video.getAttribute('loop')", null, "!="); - - run("video.removeAttribute('loop')"); - testExpected("video.loop", false); - - waitForEvent('pause'); - waitForEvent('play', play); - waitForEvent("ended", ended); - - consoleWrite("<br><em>++ Set 'loop' to true and begin playing.</em>"); - var mediaFile = findMediaFile("video", "content/test"); - run("video.loop = true"); - video.src = mediaFile; - consoleWrite(""); - } - </script> - - </head> - <body> - <video controls autoplay ></video> - <p><b>Test looping by:</b> - <ol> - <li>Play to end with 'loop' set to true.</li> - <li>When 'seeked' event fires, verify that time has jumped back and movie is playing.</li> - <li>Set 'loop' to false and play again.</li> - <li>Verify that 'ended' event fires.</li> - </ol> - </p> - <script>start()</script> - </body> -</html> + // Set "loop" to true and begin playing. + video.loop = true; + video.src = findMediaFile("video", "content/test"); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-size-expected.txt b/third_party/WebKit/LayoutTests/media/video-size-expected.txt deleted file mode 100644 index 8e19077..0000000 --- a/third_party/WebKit/LayoutTests/media/video-size-expected.txt +++ /dev/null
@@ -1,38 +0,0 @@ -Test <video> element size with and without 'src' and 'poster' attributes. - -Testing movie with no 'src' and no 'poster', with 'width' and 'height' attributes. -EXPECTED (video.clientWidth == '640') OK -EXPECTED (video.clientHeight == '480') OK -EXPECTED (video.videoWidth == '0') OK -EXPECTED (video.videoHeight == '0') OK - -Removing 'width' and 'height' attributes. -Testing movie with no 'src' and no 'poster', with NO 'width' and 'height' attributes, should be default size. -EXPECTED (video.clientWidth == '300') OK -EXPECTED (video.clientHeight == '150') OK -EXPECTED (video.videoWidth == '0') OK -EXPECTED (video.videoHeight == '0') OK - -Setting 'poster' to "content/abe.png" -Testing movie with 'poster' but no 'src', should be image size. -EXPECTED (video.clientWidth == '76') OK -EXPECTED (video.clientHeight == '103') OK -EXPECTED (video.videoWidth == '0') OK -EXPECTED (video.videoHeight == '0') OK - -Setting 'src' to "content/test.[extension]" -Testing movie with 'poster' and 'src', should be <video> size. -EXPECTED (video.clientWidth == '320') OK -EXPECTED (video.clientHeight == '240') OK -EXPECTED (video.videoWidth == '320') OK -EXPECTED (video.videoHeight == '240') OK - -Setting 'src' to "content/bogus.[extension]" 'poster' to "content/greenbox.png" -Testing movie with 'poster' and invalid 'src', should be image size. -EXPECTED (video.clientWidth == '25') OK -EXPECTED (video.clientHeight == '25') OK -EXPECTED (video.videoWidth == '0') OK -EXPECTED (video.videoHeight == '0') OK - -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-size.html b/third_party/WebKit/LayoutTests/media/video-size.html index 9446d96d..462bddd 100644 --- a/third_party/WebKit/LayoutTests/media/video-size.html +++ b/third_party/WebKit/LayoutTests/media/video-size.html
@@ -1,131 +1,97 @@ -<html> - <head> - <title><video> element size and resize test</title> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> - <script src=media-file.js></script> +<!DOCTYPE html> +<title>Test "video" element size with and without "src" and "poster" attributes.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<body> +<script> +var movieInfo = [ + { + src: null, + poster: null, + description: "no 'src' and no 'poster', with 'width' and 'height' attributes", + width: 640, + height: 480, + videoWidth: 0, + videoHeight: 0, + setSize: true + }, + { + src: null, + poster: null, + description: "no 'src' and no 'poster', with no 'width' and 'height' attributes, should be default size", + width: 300, + height: 150, + videoWidth: 0, + videoHeight: 0 + }, + { + src: null, + poster: "content/abe.png", + description: "'poster' but no 'src', should be 'poster' size", + width: 76, + height: 103, + videoWidth: 0, + videoHeight: 0 + }, + { + src: "content/test", + poster: "content/abe.png", + description: "'poster' and 'src', should be 'video' size", + width: 320, + height: 240, + videoWidth: 320, + videoHeight: 240 + }, + { + src: "content/bogus", + poster: "content/greenbox.png", + description: "'poster' and invalid 'src', should be 'poster' size", + width: 25, + height: 25, + videoWidth: 0, + videoHeight: 0 + } +]; - <script> - var movieInfo = - { - current:0, - movies: - [ - { - src:null, - poster:null, - description:"no 'src' and no 'poster', with 'width' and 'height' attributes", - width:640, - height:480, - videoWidth:0, - videoHeight:0 - }, - { - src:null, - poster:null, - description:"no 'src' and no 'poster', with NO 'width' and 'height' attributes, should be default size", - width:300, - height:150, - videoWidth:0, - videoHeight:0 - }, - { - src:null, - poster:"content/abe.png", - description:"'poster' but no 'src', should be image size", - width:76, - height:103, - videoWidth:0, - videoHeight:0 - }, - { - src:"content/test", - poster:"content/abe.png", - description:"'poster' and 'src', should be <video> size", - width:320, - height:240, - videoWidth:320, - videoHeight:240 - }, - { - src:"content/bogus", - poster:"content/greenbox.png", - description:"'poster' and invalid 'src', should be image size", - width:25, - height:25, - videoWidth:0, - videoHeight:0 - }, - ] - }; +movieInfo.forEach(function(movie) { + async_test(function(t) { + if (movie.poster) { + var image = document.createElement("img"); + image.src = movie.poster; + document.body.appendChild(image); + image.onload = t.step_func(runTest); + } else { + runTest(); + } - function setupNextConfiguration() - { - consoleWrite(""); - if (movieInfo.current >= movieInfo.movies.length) - { - endTest(); - return; - } - - var movie = movieInfo.movies[movieInfo.current]; - if (movie.src || movie.poster) { - var desc = "<b>Setting "; - if (movie.src && relativeURL(video.src) != movie.src) { - video.src = findMediaFile("video", movie.src); - desc += "'src' to <em>\""+ movie.src + ".[extension]\"</em> "; - } - if (movie.poster && relativeURL(video.poster) != movie.poster) { - video.poster = movie.poster; - desc += "'poster' to <em>\""+ movie.poster + "\"</em>"; - } - consoleWrite(desc + "</b>"); - } - - // Remove width/height attributes if present - if (video.width || video.height) { - consoleWrite("<b>Removing 'width' and 'height' attributes.</b>"); - video.removeAttribute('width'); - video.removeAttribute('height'); - } - - if (!movie.src || movie.src.indexOf('bogus') >= 0) - setTimeout(testMovie, 100); + function runTest() { + var video = document.createElement("video"); + document.body.appendChild(video); + if (movie.setSize) { + video.setAttribute("width", "640"); + video.setAttribute("height", "480"); } - function testMovie() - { - if (movieInfo.current >= movieInfo.movies.length) - return; + if (movie.src) + video.src = findMediaFile("video", movie.src); - var temp = document.body.offsetWidth; - var movie = movieInfo.movies[movieInfo.current]; + if (movie.poster) + video.poster = movie.poster; - var desc = "<b>Testing movie with " + movie.description + ".</b>"; - consoleWrite(desc); + video.onloadedmetadata = t.step_func_done(testMovieSize); - testExpected("video.clientWidth", movie.width); - testExpected("video.clientHeight", movie.height); - testExpected("video.videoWidth", movie.videoWidth); - testExpected("video.videoHeight", movie.videoHeight); - - movieInfo.current++; - setupNextConfiguration(); + if (!movie.src || movie.src.indexOf("bogus") >= 0) { + setTimeout(t.step_func_done(testMovieSize), 0); } - function test() - { - findMediaElement(); - testMovie(); + function testMovieSize() { + assert_equals(video.clientWidth, movie.width); + assert_equals(video.clientHeight, movie.height); + assert_equals(video.videoWidth, movie.videoWidth); + assert_equals(video.videoHeight, movie.videoHeight); } - </script> - </head> - - <body onload="setTimeout(test, 100)"> - - <video controls width=640 height=480 onloadedmetadata="testMovie()"></video> - <p>Test <video> element size with and without 'src' and 'poster' attributes.</p> - - </body> -</html> + } + }, movie.description); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback-expected.txt b/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback-expected.txt deleted file mode 100644 index 2b3d6797..0000000 --- a/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -Test 'timeupdate' events are posted while playing but not while paused. - -RUN(video.play()) - -EVENT(play) -EVENT(waiting) -EVENT(loadstart) -EVENT(durationchange) -EVENT(loadedmetadata) -EVENT(loadeddata) -EVENT(canplay) -EVENT(playing) - -RUN(video.pause()) -EVENT(pause) - -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback.html b/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback.html index 9d3c06914..b5a3e4cf 100644 --- a/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback.html +++ b/third_party/WebKit/LayoutTests/media/video-timeupdate-during-playback.html
@@ -1,58 +1,25 @@ -<html> -<body> +<!DOCTYPE html> +<title>Test "timeupdate" events are posted while playing but not while paused.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<video></video> +<script> +async_test(function(t) { + var video = document.querySelector("video"); + video.src = findMediaFile("video", "content/test"); - <video controls></video> + video.onplaying = t.step_func(function() { + video.ontimeupdate = t.step_func(function() { + video.pause(); + }); + }); - <p> - Test 'timeupdate' events are posted while playing but not while paused. - </p> - <script src=media-file.js></script> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> - <script> - setSrcByTagName("video", findMediaFile("video", "content/test")); + video.onpause = t.step_func(function() { + video.ontimeupdate = t.unreached_func(); + setTimeout(t.step_func_done(), 250); + }); - var timeupdateEventCount = 0; - var countWhilePlaying = 0; - - function someTimeLater() - { - if (countWhilePlaying != timeupdateEventCount) - failTest("'timeupdate' events posted after pausing"); - endTest(); - } - - function pause() - { - countWhilePlaying = timeupdateEventCount; - setTimeout(someTimeLater, 400) ; - consoleWrite(""); - } - - function playing() - { - setTimeout(function () { run("video.pause()"); }, 500) ; - consoleWrite(""); - } - - mediaElement.addEventListener("timeupdate", function () { ++timeupdateEventCount; }); - - waitForEvent('error'); - waitForEvent("loadstart"); - waitForEvent("waiting"); - waitForEvent("ratechange"); - waitForEvent("durationchange"); - waitForEvent("loadedmetadata"); - waitForEvent("loadeddata"); - waitForEvent("canplay"); - waitForEvent("pause", pause); - waitForEvent("play"); - waitForEvent("playing", playing); - - run("video.play()"); - consoleWrite(""); - </script> - -</body> -</html> + video.play(); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html index 3a65ab1..f580608 100644 --- a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html +++ b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html
@@ -246,6 +246,18 @@ ['Empty supported payment method identifiers should throw TypeError.', null, function() { new PaymentRequest([{'supportedMethods': []}], buildDetails()) }], + ['Duplicate supported payment method identifiers should throw TypeError.', null, function() { + new PaymentRequest([{'supportedMethods': ['foo', 'foo']}], buildDetails(), {}) + }], + ['Duplicate supported payment method identifiers should throw TypeError.', null, function() { + new PaymentRequest([{'supportedMethods': ['foo']}, {'supportedMethods': ['foo']}], buildDetails(), {}) + }], + ['Duplicate supported payment method identifiers in modifiers should throw TypeError.', null, function() { + new PaymentRequest([{'supportedMethods': ['foo']}], {'total': buildItem(), 'modifiers': [{'supportedMethods': ['foo', 'foo']}]}) + }], + ['Duplicate supported payment method identifiers in modifiers should throw TypeError.', null, function() { + new PaymentRequest([{'supportedMethods': ['foo']}], {'total': buildItem(), 'modifiers': [{'supportedMethods': ['foo']}, {'supportedMethods': ['foo']}]}) + }], ['Empty details should throw', null, function() { new PaymentRequest([{'supportedMethods': ['foo']}], {}) }],
diff --git a/third_party/WebKit/LayoutTests/platform/android/editing/inserting/insert-div-018-expected.png b/third_party/WebKit/LayoutTests/platform/android/editing/inserting/insert-div-018-expected.png deleted file mode 100644 index 1ae4159a..0000000 --- a/third_party/WebKit/LayoutTests/platform/android/editing/inserting/insert-div-018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/inserting/insert-div-018-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/inserting/insert-div-018-expected.png deleted file mode 100644 index 2fed467c..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/inserting/insert-div-018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/inserting/insert-div-018-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/inserting/insert-div-018-expected.txt deleted file mode 100644 index e96239a3..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/editing/inserting/insert-div-018-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow (anonymous) at (0,0) size 784x28 - LayoutText {#text} at (0,0) size 656x27 - text run at (0,0) width 656: "Test inserting paragraphs: should see an empty blue box below \"bar\"" - LayoutBlockFlow {DIV} at (0,28) size 784x36 - LayoutBlockFlow (anonymous) at (0,64) size 784x28 - LayoutText {#text} at (0,0) size 31x27 - text run at (0,0) width 31: "bar" - LayoutBlockFlow {DIV} at (0,92) size 784x112 [border: (2px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,14) size 756x28 - LayoutBR {BR} at (0,0) size 0x27 - LayoutBlockFlow {DIV} at (14,42) size 756x56 [border: (2px solid #FF0000)] - LayoutText {#text} at (14,14) size 33x27 - text run at (14,14) width 33: "baz" -caret: position 0 of child 0 {BR} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/inserting/insert-div-018-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/inserting/insert-div-018-expected.png deleted file mode 100644 index 7c76bda..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/inserting/insert-div-018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/inserting/insert-div-018-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/inserting/insert-div-018-expected.txt deleted file mode 100644 index 39d69d7..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/editing/inserting/insert-div-018-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow (anonymous) at (0,0) size 784x28 - LayoutText {#text} at (0,0) size 660x28 - text run at (0,0) width 660: "Test inserting paragraphs: should see an empty blue box below \"bar\"" - LayoutBlockFlow {DIV} at (0,28) size 784x36 - LayoutBlockFlow (anonymous) at (0,64) size 784x28 - LayoutText {#text} at (0,0) size 31x28 - text run at (0,0) width 31: "bar" - LayoutBlockFlow {DIV} at (0,92) size 784x112 [border: (2px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,14) size 756x28 - LayoutBR {BR} at (0,0) size 0x28 - LayoutBlockFlow {DIV} at (14,42) size 756x56 [border: (2px solid #FF0000)] - LayoutText {#text} at (14,14) size 34x28 - text run at (14,14) width 34: "baz" -caret: position 0 of child 0 {BR} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/inserting/insert-div-018-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/inserting/insert-div-018-expected.png deleted file mode 100644 index 0586480b..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/inserting/insert-div-018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/inserting/insert-div-018-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/inserting/insert-div-018-expected.txt deleted file mode 100644 index 5d8abfc..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/editing/inserting/insert-div-018-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification -EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow (anonymous) at (0,0) size 784x27 - LayoutText {#text} at (0,0) size 660x26 - text run at (0,0) width 660: "Test inserting paragraphs: should see an empty blue box below \"bar\"" - LayoutBlockFlow {DIV} at (0,27) size 784x36 - LayoutBlockFlow (anonymous) at (0,63) size 784x27 - LayoutText {#text} at (0,0) size 31x26 - text run at (0,0) width 31: "bar" - LayoutBlockFlow {DIV} at (0,90) size 784x110 [border: (2px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,14) size 756x27 - LayoutBR {BR} at (0,0) size 0x26 - LayoutBlockFlow {DIV} at (14,41) size 756x55 [border: (2px solid #FF0000)] - LayoutText {#text} at (14,14) size 34x26 - text run at (14,14) width 34: "baz" -caret: position 0 of child 0 {BR} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/resources/testharnessreport.js index 64c08a9..0dba6f20 100644 --- a/third_party/WebKit/LayoutTests/resources/testharnessreport.js +++ b/third_party/WebKit/LayoutTests/resources/testharnessreport.js
@@ -66,9 +66,19 @@ return !!document.querySelector('script[src*="/resources/testharness"]'); } + function injectSyntheticInput() { var path = window.location.pathname; if (path.match(/imported\/wpt\/.*\.html$/)) { + // Set a global variable for the address of automated input script if they need to use it. + var automated_input_scripts_folder = path.replace(/imported\/wpt\/(.*)\.html$/, 'imported/wpt_automation'); + + importAutomationScript = function(relativePath) { + var common_script = document.createElement('script'); + common_script.setAttribute('src', automated_input_scripts_folder + relativePath); + document.head.appendChild(common_script); + } + path = path.replace(/imported\/wpt\/(.*)\.html$/, "imported/wpt_automation/$1-input.js"); var input_script = document.createElement('script'); input_script.setAttribute('src', path);
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/crashes/offsetParent-layoutObject-lifecycle.html b/third_party/WebKit/LayoutTests/shadow-dom/crashes/offsetParent-layoutObject-lifecycle.html new file mode 100644 index 0000000..8a1d08d --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/crashes/offsetParent-layoutObject-lifecycle.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<script src='../../resources/testharness.js'></script> +<script src='../../resources/testharnessreport.js'></script> +<script> +// This case is created from reproduction case by cloudfuzzer. +window.addEventListener('load', () => { + test(() => { + var link = document.createElement('link'); + link.setAttribute('rel','import'); + document.head.appendChild(link); + + var style = document.createElement('style'); + style.textContent = '@import url(x)'; + document.head.appendChild(style); + + var frame = document.createElement('frame'); + document.body.appendChild(frame); + + // This could cause crash. + frame.offsetHeight; + assert_true(true, 'This test must run without crash.'); + }, "HTMLElement.offsetHeight should not cause crash."); +}, false); +</script> +<body></body>
diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/resources/observer.js b/third_party/WebKit/LayoutTests/storage/indexeddb/resources/observer.js index 635e3ae3..341ab497 100644 --- a/third_party/WebKit/LayoutTests/storage/indexeddb/resources/observer.js +++ b/third_party/WebKit/LayoutTests/storage/indexeddb/resources/observer.js
@@ -5,22 +5,31 @@ function callback(){}; async_test(function(t) { - var description = 'observers constructor test'; - var dbname = location.pathname + ' - ' + description; - var openRequest = indexedDB.open(dbname); - var obs1 = new IDBObserver(callback, {transaction: true, values: true}); - openRequest.onupgradeneeded = t.step_func(function() { - var db = openRequest.result; - db.createObjectStore('store'); - }); - openRequest.onsuccess = t.step_func(function() { - var db = openRequest.result; - var tx = db.transaction('store', 'readwrite'); - obs1.observe(db, tx); - t.done(); - }); + var description = 'observer addition and removal test'; + var dbname = location.pathname + ' - ' + description; + var openRequest = indexedDB.open(dbname); + var obs1 = new IDBObserver(callback, {transaction: true, values: true}); + var obs2 = new IDBObserver(callback, {transaction: true, values: true}); -}, 'observers constructor test'); + openRequest.onupgradeneeded = t.step_func(function() { + var db = openRequest.result; + db.createObjectStore('store'); + }); + openRequest.onsuccess = t.step_func(function() { + var db = openRequest.result; + var tx = db.transaction('store', 'readwrite'); + var store = tx.objectStore('store'); + var put_request = store.put(1,1); + obs1.observe(db, tx); + obs1.unobserve(db); + obs1.observe(db, tx); + obs2.observe(db, tx); + tx.oncomplete = t.step_func(function(){ + obs1.unobserve(db); + t.done(); + }); + }); +}, 'observer addition and removal test'); done();
diff --git a/third_party/WebKit/LayoutTests/svg/css/css-keyword-properties.html b/third_party/WebKit/LayoutTests/svg/css/css-keyword-properties.html new file mode 100644 index 0000000..6ef8f25 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/css/css-keyword-properties.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title>CSS keywords for SVG properties</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../css-parser/resources/property-parsing-test.js"></script> +<script> +function assert_valid_keywords(property, keywords) { + for (var keyword of keywords) + assert_valid_value(property, keyword); +} + +// alignment-baseline: auto | baseline | before-edge | text-before-edge | middle | +// central | after-edge | text-after-edge | ideographic | alphabetic | +// hanging | mathematical +assert_valid_keywords('alignmentBaseline', [ + 'auto', 'baseline', 'before-edge', 'text-before-edge', 'middle', + 'central', 'after-edge', 'text-after-edge', 'ideographic', 'alphabetic', + 'hanging', 'mathematical' +]); + +// dominant-baseline: auto | use-script | no-change | reset-size | ideographic | +// alphabetic | hanging | mathematical | central | middle | +// text-after-edge | text-before-edge +assert_valid_keywords('dominantBaseline', [ + 'auto', 'use-script', 'no-change', 'reset-size', 'ideographic', + 'alphabetic', 'hanging', 'mathematical', 'central', 'middle', + 'text-after-edge', 'text-before-edge' +]); +</script>
diff --git a/third_party/WebKit/LayoutTests/svg/filters/color-interpolation-filters-style-update-expected.html b/third_party/WebKit/LayoutTests/svg/filters/color-interpolation-filters-style-update-expected.html new file mode 100644 index 0000000..9b92a24 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/filters/color-interpolation-filters-style-update-expected.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<svg> + <filter id="f" style="color-interpolation-filters: sRGB"> + <feColorMatrix type="hueRotate" values="120"/> + </filter> + <rect fill="red" width="100" height="100" filter="url(#f)"/> +</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/filters/color-interpolation-filters-style-update.html b/third_party/WebKit/LayoutTests/svg/filters/color-interpolation-filters-style-update.html new file mode 100644 index 0000000..683e1a05 --- /dev/null +++ b/third_party/WebKit/LayoutTests/svg/filters/color-interpolation-filters-style-update.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<svg> + <filter id="f"> + <feColorMatrix type="hueRotate" values="120"/> + </filter> + <rect fill="red" width="100" height="100" filter="url(#f)"/> +</svg> +<script> +runAfterLayoutAndPaint(function() { + document.getElementById('f').style.colorInterpolationFilters = 'sRGB'; +}, true); +</script>
diff --git a/third_party/WebKit/LayoutTests/tables/invalid-background-url-crash.html b/third_party/WebKit/LayoutTests/tables/invalid-background-url-crash.html new file mode 100644 index 0000000..569ea7d --- /dev/null +++ b/third_party/WebKit/LayoutTests/tables/invalid-background-url-crash.html
@@ -0,0 +1,12 @@ +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<body onload="window.open()"> + <table background="http://tLayp%e3s"^1"></table> +</body> + +<script> +if (window.testRunner) + testRunner.setCanOpenWindows(); +test(() => {}, 'This test passes if it does not crash.'); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/webaudio/audiolistener-automation-position.html b/third_party/WebKit/LayoutTests/webaudio/audiolistener-automation-position.html index f8c22e0c..40717ac 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audiolistener-automation-position.html +++ b/third_party/WebKit/LayoutTests/webaudio/audiolistener-automation-position.html
@@ -180,13 +180,9 @@ var prefix = 'Distance model: "' + options.distanceModel.model + '"'; prefix += ', rolloff: ' + options.distanceModel.rolloff; - success = Should(prefix + ": left channel", actualLeft, { - verbose: true - }) + success = Should(prefix + ": left channel", actualLeft) .beCloseToArray(expectedLeft, 0) && success; - success = Should(prefix + ": right channel", actualRight, { - verbose: true - }) + success = Should(prefix + ": right channel", actualRight) .beCloseToArray(expectedRight, 0) && success; var message = 'Moving AudioListener with distance model: "';
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-automation-clamping.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-automation-clamping.html index 5b9d5622..fac9315 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audioparam-automation-clamping.html +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-automation-clamping.html
@@ -89,9 +89,9 @@ x => x != 0); // Verify that the expected clamping range is a subset of the actual range. - success = Should("Actual Clamp start (" + actualClampStart + ")", + success = Should("Actual Clamp start", actualClampStart).beLessThanOrEqualTo(clampStartFrame) && success; - success == Should("Actual Clamp end (" + actualClampEnd + ")", + success == Should("Actual Clamp end", actualClampEnd).beGreaterThanOrEqualTo(clampEndFrame) && success; if (success)
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html index f5bbf22..37efafef 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html
@@ -215,9 +215,8 @@ // Verify the ramp part of the curve startIndex += length; length = expected.rampPart.length; - success = Should(prefix, result.slice(startIndex, startIndex + length), { - verbose: true - }).beCloseToArray(expected.rampPart, thresholdRamp) && success; + success = Should(prefix, result.slice(startIndex, startIndex + length)) + .beCloseToArray(expected.rampPart, thresholdRamp) && success; // Verify that the end of the curve after the ramp (if any) is a constant. startIndex += length;
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-duration.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-duration.html index adbcacd..50be73c 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-duration.html +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-duration.html
@@ -52,7 +52,9 @@ var message = "setValueCurve([" + curve + "], 0, " + duration + ")"; - success = Should("Max amplitude of " + message, max).beLessThanOrEqualTo(expectedMax); + success = Should("Max amplitude of " + message, max, { + brief: true + }).beLessThanOrEqualTo(expectedMax); if (success) testPassed(message + " correctly rendered.")
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurveAtTime-interpolation.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurveAtTime-interpolation.html index 312aee2..f5cd558 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurveAtTime-interpolation.html +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurveAtTime-interpolation.html
@@ -209,10 +209,16 @@ source.start(); // Some consistency checks on the test parameters - Should("Check: Curve end time", config.curveStartTime + config.curveDuration) + Should("Check: Curve end time", config.curveStartTime + config.curveDuration, { + brief: true + }) .beLessThanOrEqualTo(testDurationSec); - Should("Check: Full gain start time", config.fullGainTime).beLessThanOrEqualTo(testDurationSec); - Should("Check: Full gain start time", config.fullGainTime).beGreaterThanOrEqualTo(config.curveStartTime + config.curveDuration); + Should("Check: Full gain start time", config.fullGainTime, { + brief: true + }).beLessThanOrEqualTo(testDurationSec); + Should("Check: Full gain start time", config.fullGainTime, { + brief: true + }).beGreaterThanOrEqualTo(config.curveStartTime + config.curveDuration); // Rock and roll! return context.startRendering().then(checkResult(config)); @@ -239,7 +245,9 @@ } } - success = success && Should("SNR", SNR).beGreaterThanOrEqualTo(config.snrThreshold); + success = success && Should("SNR", SNR, { + brief: true + }).beGreaterThanOrEqualTo(config.snrThreshold); if (maxDiff <= config.maxErrorThreshold) { testPassed("Max difference is less than or equal to " + config.maxErrorThreshold + ".");
diff --git a/third_party/WebKit/LayoutTests/webaudio/iirfilter.html b/third_party/WebKit/LayoutTests/webaudio/iirfilter.html index 5f1e42c..2488bce0 100644 --- a/third_party/WebKit/LayoutTests/webaudio/iirfilter.html +++ b/third_party/WebKit/LayoutTests/webaudio/iirfilter.html
@@ -166,7 +166,7 @@ // Threshold isn't exactly zero due to round-off in the single-precision IIRFilterNode // computations versus the double-precision Javascript computations. - Should('IIR 1-pole output', actual, {verbose: true}) + Should('IIR 1-pole output', actual) .beCloseToArray(expected, {relativeThreshold: 5.723e-8}); }).then(done); }); @@ -224,13 +224,14 @@ // even if the threshold passes. Thus, only print out a very small number of elements // of the array where we have tested that they are consistent. Should("IIRFilter for Biquad " + filterType, actual, { - precision: 5, - verbose: true + precision: 5 }) .beCloseToArray(expected, errorThreshold); var snr = 10*Math.log10(computeSNR(actual, expected)); - Should("SNR for IIRFIlter for Biquad " + filterType, snr).beGreaterThanOrEqualTo(snrThreshold); + Should("SNR for IIRFIlter for Biquad " + filterType, snr, { + brief: true + }).beGreaterThanOrEqualTo(snrThreshold); }).then(done); }; } @@ -361,7 +362,9 @@ }); success = Should("Max difference between IIR and Biquad on channel " + channel, - maxError).beLessThanOrEqualTo(errorThresholds[channel]); + maxError, { + brief: true + }).beLessThanOrEqualTo(errorThresholds[channel]); } if (success) { @@ -547,7 +550,6 @@ Should("4-th order IIRFilter (biquad ref)", actual, { - verbose: true, precision: 5 }) .beCloseToArray(expected, { @@ -557,7 +559,9 @@ }); var snr = 10*Math.log10(computeSNR(actual, expected)); - Should("SNR of 4-th order IIRFilter (biquad ref)", snr) + Should("SNR of 4-th order IIRFilter (biquad ref)", snr, { + brief: true + }) .beGreaterThanOrEqualTo(108.947); }).then(done); });
diff --git a/third_party/WebKit/LayoutTests/webaudio/osc-low-freq.html b/third_party/WebKit/LayoutTests/webaudio/osc-low-freq.html index de25c3b..6adda537 100644 --- a/third_party/WebKit/LayoutTests/webaudio/osc-low-freq.html +++ b/third_party/WebKit/LayoutTests/webaudio/osc-low-freq.html
@@ -52,7 +52,9 @@ var snr = 10 * Math.log10(signal / noise); - Should("SNR of " + desiredFrequencyHz + " Hz sine wave", snr).beGreaterThanOrEqualTo(snrThreshold); + Should("SNR of " + desiredFrequencyHz + " Hz sine wave", snr, { + brief: true + }).beGreaterThanOrEqualTo(snrThreshold); testPassed("PeriodicWave coefficients that must be ignored were correctly ignored."); }
diff --git a/third_party/WebKit/LayoutTests/webaudio/osc-negative-freq.html b/third_party/WebKit/LayoutTests/webaudio/osc-negative-freq.html index 467063f..41fa7154 100644 --- a/third_party/WebKit/LayoutTests/webaudio/osc-negative-freq.html +++ b/third_party/WebKit/LayoutTests/webaudio/osc-negative-freq.html
@@ -138,7 +138,6 @@ Should("Sum of positive and negative frequency custom oscillators", actual, { - verbose: true, precision: 6 }) .beCloseToArray(expected, 4.7684e-7);
diff --git a/third_party/WebKit/LayoutTests/webaudio/panner-automation-position.html b/third_party/WebKit/LayoutTests/webaudio/panner-automation-position.html index 34e3b21..56fad32 100644 --- a/third_party/WebKit/LayoutTests/webaudio/panner-automation-position.html +++ b/third_party/WebKit/LayoutTests/webaudio/panner-automation-position.html
@@ -251,13 +251,9 @@ if (options.errorThreshold) errorThreshold = options.errorThreshold[channelCount - 1] - Should(prefix + "distanceModel: " + info + ", left channel", data0, { - verbose: true - }) + Should(prefix + "distanceModel: " + info + ", left channel", data0) .beCloseToArray(expected0, errorThreshold); - Should(prefix + "distanceModel: " + info + ", right channel", data1, { - verbose: true - }) + Should(prefix + "distanceModel: " + info + ", right channel", data1) .beCloseToArray(expected1, errorThreshold); }); }
diff --git a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-byte-data.html b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-byte-data.html index 270c5f9..7e789f09 100644 --- a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-byte-data.html +++ b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-byte-data.html
@@ -71,8 +71,12 @@ var indexMax = floatData.findIndex(function (x) { return x > 1; }); var indexMin = floatData.findIndex(function (x) { return x < -1; }); - Should("Index of first sample greater than +1", indexMax).beGreaterThanOrEqualTo(0); - Should("Index of first sample less than -1", indexMin).beGreaterThanOrEqualTo(0); + Should("Index of first sample greater than +1", indexMax, { + brief: true + }).beGreaterThanOrEqualTo(0); + Should("Index of first sample less than -1", indexMin, { + brief: true + }).beGreaterThanOrEqualTo(0); // Verify explicitly that clipping happened correctly at the above indices. Should("Clip " + floatData[indexMax].toPrecision(6) + ": byteData[" + indexMax + "]", @@ -81,9 +85,7 @@ byteData[indexMin]).beEqualTo(0); // Verify that all other samples are computed correctly. - Should("Byte data", byteData, { - verbose: true - }).beEqualToArray(expected); + Should("Byte data", byteData).beEqualToArray(expected); }).then(context.resume.bind(context)) src.start();
diff --git a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-downmix.html b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-downmix.html index edb1df4..5148c4c 100644 --- a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-downmix.html +++ b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-downmix.html
@@ -102,9 +102,7 @@ // Verify the time domain data is correct. var prefix = "Analyser downmix " + options.message + " to mono" - success = Should(prefix + " time data", timeData, { - verbose: true - }) + success = Should(prefix + " time data", timeData) .beEqualToArray(renderedBuffer.getChannelData(0).subarray(0, analyser.fftSize)); var expectedTimeData = renderedBuffer.getChannelData(0).subarray(0, analyser.fftSize);
diff --git a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data-smoothing.html b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data-smoothing.html index 9564433..10bbed3 100644 --- a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data-smoothing.html +++ b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data-smoothing.html
@@ -72,9 +72,8 @@ var expectedByteData = convertFloatToByte(smoothedFloatResult.map(linearToDb), analyser.minDecibels, analyser.maxDecibels); - success = Should(analyser.fftSize + "-point byte FFT", byteFreqData, { - verbose: true - }).beCloseToArray(expectedByteData, 0) && success; + success = Should(analyser.fftSize + "-point byte FFT", byteFreqData) + .beCloseToArray(expectedByteData, 0) && success; }).then(context.resume.bind(context)); @@ -111,9 +110,8 @@ var expectedByteData = convertFloatToByte(smoothedFloatResult.map(linearToDb), analyser.minDecibels, analyser.maxDecibels); - success = Should(analyser.fftSize + "-point byte FFT", byteFreqData, { - verbose: true - }).beCloseToArray(expectedByteData, 0) && success; + success = Should(analyser.fftSize + "-point byte FFT", byteFreqData) + .beCloseToArray(expectedByteData, 0) && success; }).then(context.resume.bind(context));
diff --git a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data.html b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data.html index acaf585b..030c8d2 100644 --- a/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data.html +++ b/third_party/WebKit/LayoutTests/webaudio/realtimeanalyser-freq-data.html
@@ -184,9 +184,13 @@ var minValue = Math.min(...expected); var maxValue = Math.max(...expected); - basicTestsPassed = Should("Min FFT value", minValue) + basicTestsPassed = Should("Min FFT value", minValue, { + brief: true + }) .beLessThanOrEqualTo(analyser.minDecibels) && basicTestsPassed; - basicTestsPassed = Should("Max FFT value", maxValue) + basicTestsPassed = Should("Max FFT value", maxValue, { + brief: true + }) .beGreaterThanOrEqualTo(analyser.maxDecibels) && basicTestsPassed; // Test the byte frequency data. @@ -198,9 +202,8 @@ var expectedByteData = convertFloatToByte(expected, analyser.minDecibels, analyser.maxDecibels); - basicTestsPassed = Should(analyser.fftSize + "-point byte FFT", byteFreqData, { - verbose: true - }).beCloseToArray(expectedByteData, 0) && basicTestsPassed; + basicTestsPassed = Should(analyser.fftSize + "-point byte FFT", byteFreqData) + .beCloseToArray(expectedByteData, 0) && basicTestsPassed; }).then(context.resume.bind(context));
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js b/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js index ebc337b2..c248762 100644 --- a/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js +++ b/third_party/WebKit/LayoutTests/webaudio/resources/audio-testing.js
@@ -420,7 +420,7 @@ // If true, verbose output for the failure case is printed, for methods where this makes // sense. - this.verbose = opts.verbose; + this.verbose = !opts.brief; // If set, this is the precision with which numbers will be printed. this.PRINT_PRECISION = opts.precision; @@ -1046,7 +1046,8 @@ return function (desc, target, opts) { var _opts = { numberOfErrorLog: 8, - numberOfArrayLog: 16 + numberOfArrayLog: 16, + verbose: true }; if (opts instanceof Object) { @@ -1054,8 +1055,8 @@ _opts.numberOfErrorLog = opts.numberOfErrorLog; if (opts.hasOwnProperty('numberOfArrayLog')) _opts.numberOfArrayLog = opts.numberOfArrayLog; - if (opts.hasOwnProperty('verbose')) - _opts.verbose = opts.verbose; + if (opts.hasOwnProperty('brief')) + _opts.brief = opts.brief; if (opts.hasOwnProperty('precision')) _opts.precision = opts.precision; }
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 49078d7..69cd1b8 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -390,6 +390,7 @@ [Worker] attribute @@toStringTag [Worker] method constructor [Worker] method observe +[Worker] method unobserve [Worker] interface IDBObserverChangesRecord [Worker] attribute @@toStringTag [Worker] getter key
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 6ef0f843..b979613 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3474,6 +3474,7 @@ attribute @@toStringTag method constructor method observe + method unobserve interface IDBObserverChanges attribute @@toStringTag getter database
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt index d989d70..5f4b3e3c6 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -377,6 +377,7 @@ [Worker] attribute @@toStringTag [Worker] method constructor [Worker] method observe +[Worker] method unobserve [Worker] interface IDBObserverChangesRecord [Worker] attribute @@toStringTag [Worker] getter key
diff --git a/third_party/WebKit/PerformanceTests/Canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html b/third_party/WebKit/PerformanceTests/Canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html index c35f28c..c6777c36 100644 --- a/third_party/WebKit/PerformanceTests/Canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html +++ b/third_party/WebKit/PerformanceTests/Canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html
@@ -46,7 +46,7 @@ function ensureComplete() { // Using destCanvas2D as a source image is just to flush out the content when // accelerated 2D canvas is in use. - dummyCtx2D.drawImage(destCanvas2D, 0, 0, 1, 1, 0, 0, 1, 1); + dummyCtx2D.drawImage(canvas2D, 0, 0, 1, 1, 0, 0, 1, 1); } window.onload = function () {
diff --git a/third_party/WebKit/PerformanceTests/Canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html b/third_party/WebKit/PerformanceTests/Canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html index baa2c3d..d3d7bcc 100644 --- a/third_party/WebKit/PerformanceTests/Canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html +++ b/third_party/WebKit/PerformanceTests/Canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html
@@ -45,7 +45,7 @@ function ensureComplete() { // Using destCanvas2D as a source image is just to flush out the content when // accelerated 2D canvas is in use. - dummyCtx2D.drawImage(destCanvas2D, 0, 0, 1, 1, 0, 0, 1, 1); + dummyCtx2D.drawImage(canvas2D, 0, 0, 1, 1, 0, 0, 1, 1); } window.onload = function () {
diff --git a/third_party/WebKit/Source/bindings/core/v8/CallbackPromiseAdapter.h b/third_party/WebKit/Source/bindings/core/v8/CallbackPromiseAdapter.h index ee01896..97c401d 100644 --- a/third_party/WebKit/Source/bindings/core/v8/CallbackPromiseAdapter.h +++ b/third_party/WebKit/Source/bindings/core/v8/CallbackPromiseAdapter.h
@@ -187,6 +187,7 @@ ScriptPromiseResolver* resolver = this->resolver(); if (!resolver->getExecutionContext() || resolver->getExecutionContext()->activeDOMObjectsAreStopped()) return; + ScriptState::Scope scope(resolver->getScriptState()); resolver->reject(T::take(resolver, pass(result))); } };
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h index cb32c689..eabb4a2 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
@@ -908,7 +908,7 @@ // Attaches |environment| to |function| and returns it. inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Local<v8::Value> environment, v8::Isolate* isolate) { - return v8::Function::New(isolate, function, environment); + return v8::Function::New(isolate->GetCurrentContext(), function, environment, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(); } // FIXME: This will be soon embedded in the generated code.
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp b/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp index 633e5e0..71812424 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8LazyEventListener.cpp
@@ -183,8 +183,8 @@ // source returned (sometimes a RegExp is applied as well) for some // other use. That fails miserably if the actual wrapper source is // returned. - v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8LazyEventListenerToString); - if (toStringFunction.IsEmpty()) + v8::Local<v8::Function> toStringFunction; + if (!v8::Function::New(scriptState->context(), V8LazyEventListenerToString, v8::Local<v8::Value>(), 0, v8::ConstructorBehavior::kThrow).ToLocal(&toStringFunction)) return; String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n " + m_code + "\n}"; V8HiddenValue::setHiddenValue(scriptState, wrappedFunction, V8HiddenValue::toStringString(isolate()), v8String(isolate(), toStringString));
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp index ba9345e..f85a045 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -123,7 +123,7 @@ } v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(true); - v8::Local<v8::Value> result = v8::Function::New(isolate, throwStackOverflowException)->Call(v8::Undefined(isolate), 0, 0); + v8::Local<v8::Value> result = v8::Function::New(isolate->GetCurrentContext(), throwStackOverflowException, v8::Local<v8::Value>(), 0, v8::ConstructorBehavior::kThrow).ToLocalChecked()->Call(v8::Undefined(isolate), 0, 0); V8PerIsolateData::from(isolate)->setIsHandlingRecursionLevelError(false); return result; }
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp index 0ad55527..c6cb296 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -272,11 +272,13 @@ } // If Origin Trials have been registered before the V8 context was ready, // then inject them into the context now - ExecutionContext* executionContext = m_scriptState->getExecutionContext(); - if (executionContext) { - OriginTrialContext* originTrialContext = OriginTrialContext::from(executionContext); - if (originTrialContext) - originTrialContext->initializePendingFeatures(); + if (m_world->isMainWorld()) { + ExecutionContext* executionContext = m_scriptState->getExecutionContext(); + if (executionContext) { + OriginTrialContext* originTrialContext = OriginTrialContext::from(executionContext); + if (originTrialContext) + originTrialContext->initializePendingFeatures(); + } } return true; }
diff --git a/third_party/WebKit/Source/bindings/scripts/idl_definitions.py b/third_party/WebKit/Source/bindings/scripts/idl_definitions.py index c66920b..1428577 100644 --- a/third_party/WebKit/Source/bindings/scripts/idl_definitions.py +++ b/third_party/WebKit/Source/bindings/scripts/idl_definitions.py
@@ -137,6 +137,10 @@ callback_function.accept(visitor) for dictionary in self.dictionaries.itervalues(): dictionary.accept(visitor) + for enumeration in self.enumerations.itervalues(): + enumeration.accept(visitor) + for implement in self.implements: + implement.accept(visitor) for typedef in self.typedefs.itervalues(): typedef.accept(visitor) @@ -254,6 +258,9 @@ for child in node.GetChildren(): self.values.append(child.GetName()) + def accept(self, visitor): + visitor.visit_enumeration(self) + ################################################################################ # Typedefs @@ -837,6 +844,9 @@ self.left_interface = node.GetName() self.right_interface = node.GetProperty('REFERENCE') + def accept(self, visitor): + visitor.visit_implement(self) + ################################################################################ # Extended attributes @@ -1092,6 +1102,12 @@ def visit_dictionary_member(self, member): self.visit_typed_object(member) + def visit_enumeration(self, enumeration): + pass + + def visit_implement(self, implement): + pass + def visit_interface(self, interface): pass
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.h b/third_party/WebKit/Source/core/animation/StringKeyframe.h index fa161e6..51c343b0 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.h +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.h
@@ -50,12 +50,12 @@ class CSSPropertySpecificKeyframe : public Keyframe::PropertySpecificKeyframe { public: - static PassRefPtr<CSSPropertySpecificKeyframe> create(double offset, PassRefPtr<TimingFunction> easing, CSSValue* value, EffectModel::CompositeOperation composite) + static PassRefPtr<CSSPropertySpecificKeyframe> create(double offset, PassRefPtr<TimingFunction> easing, const CSSValue* value, EffectModel::CompositeOperation composite) { return adoptRef(new CSSPropertySpecificKeyframe(offset, easing, value, composite)); } - CSSValue* value() const { return m_value.get(); } + const CSSValue* value() const { return m_value.get(); } bool populateAnimatableValue(CSSPropertyID, Element&, const ComputedStyle& baseStyle, const ComputedStyle* parentStyle) const final; const PassRefPtr<AnimatableValue> getAnimatableValue() const final { return m_animatableValueCache.get(); } @@ -65,9 +65,9 @@ PassRefPtr<Keyframe::PropertySpecificKeyframe> neutralKeyframe(double offset, PassRefPtr<TimingFunction> easing) const final; private: - CSSPropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, CSSValue* value, EffectModel::CompositeOperation composite) + CSSPropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, const CSSValue* value, EffectModel::CompositeOperation composite) : Keyframe::PropertySpecificKeyframe(offset, easing, composite) - , m_value(value) + , m_value(const_cast<CSSValue*>(value)) { } virtual PassRefPtr<Keyframe::PropertySpecificKeyframe> cloneWithOffset(double offset) const; @@ -75,6 +75,7 @@ void populateAnimatableValueCaches(CSSPropertyID, Keyframe::PropertySpecificKeyframe&, Element*, CSSValue& fromCSSValue, CSSValue& toCSSValue) const; + // TODO(sashab): Make this a const CSSValue. Persistent<CSSValue> m_value; mutable RefPtr<AnimatableValue> m_animatableValueCache; };
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index aad436ff..a5e5d17 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -2010,10 +2010,14 @@ 'page/TouchDisambiguation.cpp', 'page/TouchDisambiguation.h', 'page/WindowFeatures.cpp', + 'page/scrolling/ChildViewportScrollCallback.cpp', + 'page/scrolling/ChildViewportScrollCallback.h', 'page/scrolling/OverscrollController.cpp', 'page/scrolling/OverscrollController.h', 'page/scrolling/RootScrollerController.cpp', 'page/scrolling/RootScrollerController.h', + 'page/scrolling/RootViewportScrollCallback.cpp', + 'page/scrolling/RootViewportScrollCallback.h', 'page/scrolling/ScrollingCoordinator.cpp', 'page/scrolling/ScrollingCoordinator.h', 'page/scrolling/SnapCoordinator.cpp', @@ -3136,6 +3140,8 @@ 'html/forms/MultipleFieldsTemporalInputTypeView.h', 'html/forms/NumberInputType.cpp', 'html/forms/NumberInputType.h', + 'html/forms/OptionList.cpp', + 'html/forms/OptionList.h', 'html/forms/PasswordInputType.cpp', 'html/forms/PasswordInputType.h', 'html/forms/RadioButtonGroupScope.cpp', @@ -4116,6 +4122,7 @@ 'html/canvas/CanvasFontCacheTest.cpp', 'html/forms/EmailInputTypeTest.cpp', 'html/forms/FileInputTypeTest.cpp', + 'html/forms/OptionListTest.cpp', 'html/forms/StepRangeTest.cpp', 'html/parser/AtomicHTMLTokenTest.cpp', 'html/parser/CompactHTMLTokenTest.cpp', @@ -4125,6 +4132,7 @@ 'html/parser/HTMLPreloadScannerTest.cpp', 'html/parser/HTMLResourcePreloaderTest.cpp', 'html/parser/HTMLSrcsetParserTest.cpp', + 'html/parser/HTMLTokenizerTest.cpp', 'html/parser/HTMLTreeBuilderSimulatorTest.cpp', 'html/shadow/MediaControlsTest.cpp', 'html/track/vtt/BufferedLineReaderTest.cpp', @@ -4184,6 +4192,7 @@ 'paint/PaintPropertyTreeBuilderTest.cpp', 'paint/TableCellPainterTest.cpp', 'paint/TextPainterTest.cpp', + 'paint/VideoPainterTest.cpp', 'streams/ReadableStreamOperationsTest.cpp', 'streams/ReadableStreamReaderTest.cpp', 'streams/ReadableStreamTest.cpp',
diff --git a/third_party/WebKit/Source/core/css/CSSImageValue.cpp b/third_party/WebKit/Source/core/css/CSSImageValue.cpp index 076639a9..074de691 100644 --- a/third_party/WebKit/Source/core/css/CSSImageValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSImageValue.cpp
@@ -80,7 +80,7 @@ void CSSImageValue::restoreCachedResourceIfNeeded(Document& document) const { - if (m_isCachePending || !m_cachedImage || !document.fetcher()) + if (m_isCachePending || !m_cachedImage || !document.fetcher() || m_absoluteURL.isNull()) return; if (document.fetcher()->cachedResource(KURL(ParsedURLString, m_absoluteURL))) return;
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp index 2d066f0..0fe51e79e 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp +++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -207,17 +207,24 @@ if (opposite.isAuto()) return CSSPrimitiveValue::create(0, CSSPrimitiveValue::UnitType::Pixels); - if (opposite.hasPercent()) { - LayoutUnit containingBlockSize = - (propertyID == CSSPropertyLeft || propertyID == CSSPropertyRight) ? - toLayoutBox(layoutObject)->containingBlockLogicalWidthForContent() : - toLayoutBox(layoutObject)->containingBlockLogicalHeightForGetComputedStyle(); - return zoomAdjustedPixelValue(-floatValueForLength(opposite, containingBlockSize), style); + if (opposite.hasPercent() || opposite.isCalculated()) { + if (layoutObject->isBox()) { + LayoutUnit containingBlockSize = + (propertyID == CSSPropertyLeft || propertyID == CSSPropertyRight) ? + toLayoutBox(layoutObject)->containingBlockLogicalWidthForContent() : + toLayoutBox(layoutObject)->containingBlockLogicalHeightForGetComputedStyle(); + return zoomAdjustedPixelValue(-floatValueForLength(opposite, containingBlockSize), style); + } + // FIXME: fall back to auto for position:relative, display:inline + return CSSPrimitiveValue::createIdentifier(CSSValueAuto); } - return zoomAdjustedPixelValue(-opposite.pixels(), style); + + // Length doesn't provide operator -, so multiply by -1. + opposite *= -1.f; + return zoomAdjustedPixelValueForLength(opposite, style); } - if (layoutObject->isOutOfFlowPositioned()) { + if (layoutObject->isOutOfFlowPositioned() && layoutObject->isBox()) { // For fixed and absolute positioned elements, the top, left, bottom, and right // are defined relative to the corresponding sides of the containing block. LayoutBlock* container = layoutObject->containingBlock();
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp index bab67578..7719e27b 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
@@ -475,8 +475,8 @@ // auto | baseline | before-edge | text-before-edge | middle | // central | after-edge | text-after-edge | ideographic | alphabetic | // hanging | mathematical - return valueID == CSSValueAuto || valueID == CSSValueBaseline || valueID == CSSValueMiddle - || (valueID >= CSSValueBeforeEdge && valueID <= CSSValueMathematical); + return valueID == CSSValueAuto || valueID == CSSValueAlphabetic || valueID == CSSValueBaseline + || valueID == CSSValueMiddle || (valueID >= CSSValueBeforeEdge && valueID <= CSSValueMathematical); case CSSPropertyAll: return false; // Only accepts css-wide keywords case CSSPropertyBackgroundRepeatX: // repeat | no-repeat @@ -523,7 +523,7 @@ // auto | use-script | no-change | reset-size | ideographic | // alphabetic | hanging | mathematical | central | middle | // text-after-edge | text-before-edge - return valueID == CSSValueAuto || valueID == CSSValueMiddle + return valueID == CSSValueAuto || valueID == CSSValueAlphabetic || valueID == CSSValueMiddle || (valueID >= CSSValueUseScript && valueID <= CSSValueResetSize) || (valueID >= CSSValueCentral && valueID <= CSSValueMathematical); case CSSPropertyEmptyCells: // show | hide
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 24fa070..179c4229 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -195,11 +195,12 @@ #include "core/page/FrameTree.h" #include "core/page/Page.h" #include "core/page/PointerLockController.h" +#include "core/page/scrolling/ChildViewportScrollCallback.h" #include "core/page/scrolling/RootScrollerController.h" +#include "core/page/scrolling/RootViewportScrollCallback.h" #include "core/page/scrolling/ScrollStateCallback.h" #include "core/page/scrolling/ScrollingCoordinator.h" #include "core/page/scrolling/SnapCoordinator.h" -#include "core/page/scrolling/ViewportScrollCallback.h" #include "core/svg/SVGDocumentExtensions.h" #include "core/svg/SVGScriptElement.h" #include "core/svg/SVGTitleElement.h" @@ -460,17 +461,7 @@ m_fetcher = ResourceFetcher::create(nullptr); } - ViewportScrollCallback* applyScroll = nullptr; - if (isInMainFrame()) { - applyScroll = RootScrollerController::createViewportApplyScroll( - &frameHost()->topControls(), &frameHost()->overscrollController()); - } else { - applyScroll = - RootScrollerController::createViewportApplyScroll(nullptr, nullptr); - } - - m_rootScrollerController = - RootScrollerController::create(*this, applyScroll); + m_rootScrollerController = RootScrollerController::create(*this); // We depend on the url getting immediately set in subframes, but we // also depend on the url NOT getting immediately set in opened windows. @@ -600,6 +591,11 @@ m_rootScrollerController->set(newScroller); } +void Document::initializeRootScroller(ViewportScrollCallback* callback) +{ + m_rootScrollerController->setViewportScrollCallback(callback); +} + Element* Document::rootScroller() const { return m_rootScrollerController->get(); @@ -5726,8 +5722,9 @@ if (!frame() || !frame()->page()) return; m_associatedFormControls.add(element); + // We add a slight delay because this could be called rapidly. if (!m_didAssociateFormControlsTimer.isActive()) - m_didAssociateFormControlsTimer.startOneShot(0, BLINK_FROM_HERE); + m_didAssociateFormControlsTimer.startOneShot(0.3, BLINK_FROM_HERE); } void Document::removeFormAssociation(Element* element)
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 048bb13..e0bc025 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -167,6 +167,7 @@ class TouchList; class TransformSource; class TreeWalker; +class ViewportScrollCallback; class VisitedLinkState; class VisualViewport; class WebGLRenderingContext; @@ -1083,6 +1084,7 @@ bool containsV1ShadowTree() const { return m_shadowCascadeOrder == ShadowCascadeOrder::ShadowCascadeV1; } + void initializeRootScroller(ViewportScrollCallback*); Element* rootScroller() const; void setRootScroller(Element*, ExceptionState&); const Element* effectiveRootScroller() const;
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp index 6ae5e2c..a8337a8d 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -121,7 +121,7 @@ m_pendingScript = nullptr; } -// Helper function. Must take a lowercase language as input. +// Helper function static bool isLegacySupportedJavaScriptLanguage(const String& language) { // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3. @@ -131,19 +131,24 @@ // We want to accept all the values that either of these browsers accept, but not other values. // FIXME: This function is not HTML5 compliant. These belong in the MIME registry as "text/javascript<version>" entries. - DCHECK_EQ(language, language.lower()); - return language == "javascript" - || language == "javascript1.0" - || language == "javascript1.1" - || language == "javascript1.2" - || language == "javascript1.3" - || language == "javascript1.4" - || language == "javascript1.5" - || language == "javascript1.6" - || language == "javascript1.7" - || language == "livescript" - || language == "ecmascript" - || language == "jscript"; + typedef HashSet<String, CaseFoldingHash> LanguageSet; + DEFINE_STATIC_LOCAL(LanguageSet, languages, ()); + if (languages.isEmpty()) { + languages.add("javascript"); + languages.add("javascript1.0"); + languages.add("javascript1.1"); + languages.add("javascript1.2"); + languages.add("javascript1.3"); + languages.add("javascript1.4"); + languages.add("javascript1.5"); + languages.add("javascript1.6"); + languages.add("javascript1.7"); + languages.add("livescript"); + languages.add("ecmascript"); + languages.add("jscript"); + } + + return languages.contains(language); } void ScriptLoader::dispatchErrorEvent() @@ -158,30 +163,29 @@ setHaveFiredLoadEvent(true); } -bool ScriptLoader::isValidScriptTypeAndLanguage(const String& type, const String& language, LegacyTypeSupport supportLegacyTypes) +bool ScriptLoader::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes) const { // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used here to maintain backwards compatibility with existing layout tests. The specific violations are: // - Allowing type=javascript. type= should only support MIME types, such as text/javascript. // - Allowing a different set of languages for language= and type=. language= supports Javascript 1.1 and 1.4-1.6, but type= does not. + + String type = client()->typeAttributeValue(); + String language = client()->languageAttributeValue(); + if (type.isEmpty() && language.isEmpty()) + return true; // Assume text/javascript. if (type.isEmpty()) { - String lowerLanguage = language.lower(); - return language.isEmpty() // assume text/javascript. - || MIMETypeRegistry::isSupportedJavaScriptMIMEType("text/" + lowerLanguage) - || isLegacySupportedJavaScriptLanguage(lowerLanguage); + type = "text/" + language.lower(); + if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySupportedJavaScriptLanguage(language)) + return true; } else if (RuntimeEnabledFeatures::moduleScriptsEnabled() && type == "module") { return true; - } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLegacySupportedJavaScriptLanguage(type.lower()))) { + } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLegacySupportedJavaScriptLanguage(type))) { return true; } return false; } -bool ScriptLoader::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes) const -{ - return isValidScriptTypeAndLanguage(client()->typeAttributeValue(), client()->languageAttributeValue(), supportLegacyTypes); -} - // http://dev.w3.org/html5/spec/Overview.html#prepare-a-script bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes) { @@ -340,10 +344,9 @@ void ScriptLoader::logScriptMimetype(ScriptResource* resource, LocalFrame* frame, String mimetype) { - String lowerMimetype = mimetype.lower(); - bool text = lowerMimetype.startsWith("text/"); - bool application = lowerMimetype.startsWith("application/"); - bool expectedJs = MIMETypeRegistry::isSupportedJavaScriptMIMEType(lowerMimetype) || (text && isLegacySupportedJavaScriptLanguage(lowerMimetype.substring(5))); + bool text = mimetype.lower().startsWith("text/"); + bool application = mimetype.lower().startsWith("application/"); + bool expectedJs = MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimetype) || (text && isLegacySupportedJavaScriptLanguage(mimetype.substring(5))); bool sameOrigin = m_element->document().getSecurityOrigin()->canRequest(m_resource->url()); if (expectedJs) { return;
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.h b/third_party/WebKit/Source/core/dom/ScriptLoader.h index 1fc84c7d..0af9f42 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.h +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.h
@@ -50,8 +50,6 @@ Element* element() const { return m_element; } enum LegacyTypeSupport { DisallowLegacyTypeInTypeAttribute, AllowLegacyTypeInTypeAttribute }; - static bool isValidScriptTypeAndLanguage(const String& typeAttributeValue, const String& languageAttributeValue, LegacyTypeSupport supportLegacyTypes); - bool prepareScript(const TextPosition& scriptStartPosition = TextPosition::minimumPosition(), LegacyTypeSupport = DisallowLegacyTypeInTypeAttribute); String scriptCharset() const { return m_characterEncoding; }
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index caf368c..46f0e4e9 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -752,8 +752,7 @@ DCHECK(composition); dispatchEditableContentChangedEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement()); // TODO(chongz): Filter empty InputType after spec is finalized. - // TODO(chongz): Fill in |data| field. - dispatchInputEventEditableContentChanged(composition->startingRootEditableElement(), composition->endingRootEditableElement(), inputTypeFromCommand(cmd), emptyString(), isComposingFromCommand(cmd)); + dispatchInputEventEditableContentChanged(composition->startingRootEditableElement(), composition->endingRootEditableElement(), inputTypeFromCommand(cmd), cmd->textDataForInputEvent(), isComposingFromCommand(cmd)); VisibleSelection newSelection(cmd->endingSelection()); // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
diff --git a/third_party/WebKit/Source/core/editing/EphemeralRange.cpp b/third_party/WebKit/Source/core/editing/EphemeralRange.cpp index 5558185..aa36e1d 100644 --- a/third_party/WebKit/Source/core/editing/EphemeralRange.cpp +++ b/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
@@ -27,6 +27,7 @@ DCHECK_EQ(m_startPosition.document(), m_endPosition.document()); DCHECK(m_startPosition.inShadowIncludingDocument()); DCHECK(m_endPosition.inShadowIncludingDocument()); + DCHECK_LE(m_startPosition, m_endPosition); } template <typename Strategy>
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp index 29a7b6b8..08dfe81 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -349,7 +349,7 @@ EXPECT_EQ(24u, controller().getSelectionOffsets().end()); } -TEST_F(InputMethodControllerTest, CompositionFireBeforeInput) +TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) { document().settings()->setScriptEnabled(true); Element* editable = insertHTMLElement("<div id='sample' contentEditable='true'></div>", "sample"); @@ -376,8 +376,42 @@ document().setTitle(emptyString()); controller().confirmComposition(); - // Last 'beforeinput' should also be inside composition scope. + // Last pair of InputEvent should also be inside composition scope. EXPECT_STREQ("beforeinput.isComposing:true;input.isComposing:true;", document().title().utf8().data()); } +TEST_F(InputMethodControllerTest, CompositionInputEventData) +{ + document().settings()->setScriptEnabled(true); + Element* editable = insertHTMLElement("<div id='sample' contentEditable='true'></div>", "sample"); + Element* script = document().createElement("script", ASSERT_NO_EXCEPTION); + script->setInnerHTML( + "document.getElementById('sample').addEventListener('beforeinput', function(event) {" + " document.title = `beforeinput.data:${event.data};`;" + "});" + "document.getElementById('sample').addEventListener('input', function(event) {" + " document.title += `input.data:${event.data};`;" + "});", + ASSERT_NO_EXCEPTION); + document().body()->appendChild(script, ASSERT_NO_EXCEPTION); + document().view()->updateAllLifecyclePhases(); + + // Simulate composition in the |contentEditable|. + Vector<CompositionUnderline> underlines; + underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0)); + editable->focus(); + + document().setTitle(emptyString()); + controller().setComposition("n", underlines, 0, 1); + EXPECT_STREQ("beforeinput.data:n;input.data:n;", document().title().utf8().data()); + + document().setTitle(emptyString()); + controller().setComposition("ni", underlines, 0, 1); + EXPECT_STREQ("beforeinput.data:ni;input.data:ni;", document().title().utf8().data()); + + document().setTitle(emptyString()); + controller().confirmComposition(); + EXPECT_STREQ("beforeinput.data:ni;input.data:ni;", document().title().utf8().data()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp index 3450391..8a188371 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditCommand.cpp
@@ -53,6 +53,11 @@ return EditActionUnspecified; } +String EditCommand::textDataForInputEvent() const +{ + return emptyString(); +} + static inline EditCommandComposition* compositionIfPossible(EditCommand* command) { if (!command->isCompositeEditCommand())
diff --git a/third_party/WebKit/Source/core/editing/commands/EditCommand.h b/third_party/WebKit/Source/core/editing/commands/EditCommand.h index e1a5df1..91ecb82 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditCommand.h +++ b/third_party/WebKit/Source/core/editing/commands/EditCommand.h
@@ -55,6 +55,9 @@ // The |EditingState*| argument must not be nullptr. virtual void doApply(EditingState*) = 0; + // |TypingCommand| will return the text of the last |m_commands|. + virtual String textDataForInputEvent() const; + DECLARE_VIRTUAL_TRACE(); protected:
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp index 174c39d..c54fdf7e 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.cpp
@@ -44,6 +44,11 @@ { } +String InsertTextCommand::textDataForInputEvent() const +{ + return m_text; +} + Position InsertTextCommand::positionInsideTextNode(const Position& p, EditingState* editingState) { Position pos = p;
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.h b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.h index b922761..b255335 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.h +++ b/third_party/WebKit/Source/core/editing/commands/InsertTextCommand.h
@@ -43,6 +43,8 @@ return new InsertTextCommand(document, text, selectInsertedText, rebalanceType); } + String textDataForInputEvent() const final; + private: InsertTextCommand(Document&, const String& text, bool selectInsertedText, RebalanceType);
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp index 23111d3..2e6cbfa2 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -1313,7 +1313,7 @@ if (editingState->isAborted()) return; - if (m_sanitizeFragment) { + if (m_sanitizeFragment && insertedNodes.firstNodeInserted()) { applyCommandToComposite(SimplifyMarkupCommand::create(document(), insertedNodes.firstNodeInserted(), insertedNodes.pastLastLeaf()), editingState); if (editingState->isAborted()) return;
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp index 2613cb5..201f984 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommandTest.cpp
@@ -25,6 +25,34 @@ class ReplaceSelectionCommandTest : public EditingTestBase { }; +// This is a regression test for https://crbug.com/619131 +TEST_F(ReplaceSelectionCommandTest, pastingEmptySpan) +{ + document().setDesignMode("on"); + setBodyContent("foo"); + + LocalFrame* frame = document().frame(); + frame->selection().setSelection( + VisibleSelection(Position(document().body(), 0))); + + DocumentFragment* fragment = document().createDocumentFragment(); + fragment->appendChild(document().createElement("span", ASSERT_NO_EXCEPTION)); + + // |options| are taken from |Editor::replaceSelectionWithFragment()| with + // |selectReplacement| and |smartReplace|. + ReplaceSelectionCommand::CommandOptions options = + ReplaceSelectionCommand::PreventNesting | + ReplaceSelectionCommand::SanitizeFragment | + ReplaceSelectionCommand::SelectReplacement | + ReplaceSelectionCommand::SmartReplace; + ReplaceSelectionCommand* command = + ReplaceSelectionCommand::create(document(), fragment, options); + + EXPECT_TRUE(command->apply()) + << "the replace command should have succeeded"; + EXPECT_EQ("foo", document().body()->innerHTML()) << "no DOM tree mutation"; +} + // This is a regression test for https://crbug.com/121163 TEST_F(ReplaceSelectionCommandTest, styleTagsInPastedHeadIncludedInContent) {
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp index 03a4cfb..8e56bf043 100644 --- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -122,6 +122,13 @@ TypingCommand::create(document, ForwardDeleteKey, "", options, granularity)->apply(); } +String TypingCommand::textDataForInputEvent() const +{ + if (m_commands.isEmpty()) + return m_textToInsert; + return m_commands.last()->textDataForInputEvent(); +} + void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand* typingCommand, LocalFrame* frame) { DCHECK(frame);
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h index 7eb723f..30d3554 100644 --- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.h +++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.h
@@ -79,6 +79,8 @@ ETypingCommand commandTypeOfOpenCommand() const { return m_commandType; } TextCompositionType compositionType() const { return m_compositionType; } + // |TypingCommand| may contain multiple |InsertTextCommand|, should return |textDataForInputEvent()| of the last one. + String textDataForInputEvent() const final; private: static TypingCommand* create(Document& document, ETypingCommand command, const String& text = "", Options options = 0, TextGranularity granularity = CharacterGranularity)
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp index 12cd193..45fc8ee 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp +++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -679,6 +679,7 @@ void SpellChecker::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary) { + DCHECK(frame().selection().isAvailable()); TRACE_EVENT0("blink", "SpellChecker::updateMarkersForWordsAffectedByEditing"); if (!isSpellCheckingEnabledFor(frame().selection().selection())) return; @@ -735,6 +736,17 @@ if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.isNull() || endOfLastWord.isNull()) return; + const Position& removeMarkerStart = startOfFirstWord.deepEquivalent(); + const Position& removeMarkerEnd = endOfLastWord.deepEquivalent(); + if (removeMarkerStart > removeMarkerEnd) { + // editing/inserting/insert-br-008.html and more reach here. + // TODO(yosin): To avoid |DCHECK(removeMarkerStart <= removeMarkerEnd)| + // in |EphemeralRange| constructor, we have this if-statement. Once we + // fix |startOfWord()| and |endOfWord()|, we should remove this + // if-statement. + return; + } + // Now we remove markers on everything between startOfFirstWord and endOfLastWord. // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the // resulted words even we only edit one of them. For example, assuming autocorrection changes "avantgarde" to "avant @@ -743,7 +755,7 @@ // of marker that contains the word in question, and remove marker on that whole range. Document* document = frame().document(); DCHECK(document); - const EphemeralRange wordRange(startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent()); + const EphemeralRange wordRange(removeMarkerStart, removeMarkerEnd); document->markers().removeMarkers(wordRange, DocumentMarker::MisspellingMarkers(), DocumentMarkerController::RemovePartiallyOverlappingMarker); } @@ -864,14 +876,14 @@ VisiblePosition oldStart(oldSelection.visibleStart()); VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); - if (oldAdjacentWords != newAdjacentWords) { - if (isContinuousSpellCheckingEnabled()) { - VisibleSelection selectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart)); - markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSentence); - } else { - markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords); - } + if (oldAdjacentWords == newAdjacentWords) + return; + if (isContinuousSpellCheckingEnabled()) { + VisibleSelection selectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart)); + markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSentence); + return; } + markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords); } static Node* findFirstMarkable(Node* node)
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp b/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp index 19c2e95..7ba54bf 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp +++ b/third_party/WebKit/Source/core/editing/spellcheck/TextCheckingHelper.cpp
@@ -199,9 +199,16 @@ EphemeralRange TextCheckingParagraph::offsetAsRange() const { DCHECK(m_checkingRange.isNotNull()); - if (m_offsetAsRange.isNull()) - m_offsetAsRange = EphemeralRange(paragraphRange().startPosition(), checkingRange().startPosition()); - + if (m_offsetAsRange.isNotNull()) + return m_offsetAsRange; + const Position& paragraphStart = paragraphRange().startPosition(); + const Position& checkingStart = checkingRange().startPosition(); + if (paragraphStart <= checkingStart) { + m_offsetAsRange = EphemeralRange(paragraphStart, checkingStart); + return m_offsetAsRange; + } + // editing/pasteboard/paste-table-001.html and more reach here. + m_offsetAsRange = EphemeralRange(checkingStart, paragraphStart); return m_offsetAsRange; }
diff --git a/third_party/WebKit/Source/core/events/AddEventListenerOptions.idl b/third_party/WebKit/Source/core/events/AddEventListenerOptions.idl index a7d157c..cce9d59 100644 --- a/third_party/WebKit/Source/core/events/AddEventListenerOptions.idl +++ b/third_party/WebKit/Source/core/events/AddEventListenerOptions.idl
@@ -5,5 +5,5 @@ // https://dom.spec.whatwg.org/#dictdef-addeventlisteneroptions dictionary AddEventListenerOptions : EventListenerOptions { - [RuntimeEnabled=PassiveEventListeners] boolean passive; + boolean passive; };
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp index 92bd274..c9316bd7 100644 --- a/third_party/WebKit/Source/core/events/EventTarget.cpp +++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -67,10 +67,15 @@ return nullptr; } -bool isScrollBlockingEvent(const AtomicString& eventType) +bool isTouchScrollBlockingEvent(const AtomicString& eventType) { return eventType == EventTypeNames::touchstart - || eventType == EventTypeNames::touchmove + || eventType == EventTypeNames::touchmove; +} + +bool isScrollBlockingEvent(const AtomicString& eventType) +{ + return isTouchScrollBlockingEvent(eventType) || eventType == EventTypeNames::mousewheel || eventType == EventTypeNames::wheel; } @@ -105,7 +110,7 @@ String messageText = String::format( "Handling of '%s' input event was delayed for %ld ms due to main thread being busy. " - "Consider marking event handler as 'passive' to make the page more responive.", + "Consider marking event handler as 'passive' to make the page more responsive.", event->type().getString().utf8().data(), lround(delayedSeconds * 1000)); v8::Local<v8::Function> function = eventListenerEffectiveFunction(v8Listener->isolate(), handler); @@ -199,7 +204,7 @@ } } - if (RuntimeEnabledFeatures::passiveDocumentEventListenersEnabled()) { + if (RuntimeEnabledFeatures::passiveDocumentEventListenersEnabled() && isTouchScrollBlockingEvent(eventType)) { if (!options.hasPassive()) { if (Node* node = toNode()) { if (node->isDocumentNode() || node->document().documentElement() == node || node->document().body() == node) {
diff --git a/third_party/WebKit/Source/core/events/MouseRelatedEvent.cpp b/third_party/WebKit/Source/core/events/MouseRelatedEvent.cpp index 1fdb6af..8f0ff4f 100644 --- a/third_party/WebKit/Source/core/events/MouseRelatedEvent.cpp +++ b/third_party/WebKit/Source/core/events/MouseRelatedEvent.cpp
@@ -132,6 +132,22 @@ m_hasCachedRelativePosition = false; } +static const LayoutObject* findTargetLayoutObject(Node*& targetNode) +{ + LayoutObject* layoutObject = targetNode->layoutObject(); + if (!layoutObject || !layoutObject->isSVG()) + return layoutObject; + // If this is an SVG node, compute the offset to the padding box of the + // outermost SVG root (== the closest ancestor that has a CSS layout box.) + while (!layoutObject->isSVGRoot()) + layoutObject = layoutObject->parent(); + // Update the target node to point to the SVG root. + targetNode = layoutObject->node(); + DCHECK(!targetNode + || (targetNode->isSVGElement() && toSVGElement(*targetNode).isOutermostSVGSVGElement())); + return layoutObject; +} + void MouseRelatedEvent::computeRelativePosition() { Node* targetNode = target() ? target()->toNode() : nullptr; @@ -146,13 +162,13 @@ targetNode->document().updateStyleAndLayoutIgnorePendingStylesheets(); // Adjust offsetLocation to be relative to the target's padding box. - if (LayoutObject* r = targetNode->layoutObject()) { - FloatPoint localPos = r->absoluteToLocal(FloatPoint(absoluteLocation()), UseTransforms); + if (const LayoutObject* layoutObject = findTargetLayoutObject(targetNode)) { + FloatPoint localPos = layoutObject->absoluteToLocal(FloatPoint(absoluteLocation()), UseTransforms); // Adding this here to address crbug.com/570666. Basically we'd like to // find the local coordinates relative to the padding box not the border box. - if (r->isBoxModelObject()) { - LayoutBoxModelObject* layoutBox = toLayoutBoxModelObject(r); + if (layoutObject->isBoxModelObject()) { + const LayoutBoxModelObject* layoutBox = toLayoutBoxModelObject(layoutObject); localPos.move(-layoutBox->borderLeft(), -layoutBox->borderTop()); }
diff --git a/third_party/WebKit/Source/core/events/UIEvent.idl b/third_party/WebKit/Source/core/events/UIEvent.idl index 235ec54d3e..bbf6c47 100644 --- a/third_party/WebKit/Source/core/events/UIEvent.idl +++ b/third_party/WebKit/Source/core/events/UIEvent.idl
@@ -24,7 +24,7 @@ ] interface UIEvent : Event { readonly attribute Window? view; readonly attribute long detail; - [RuntimeEnabled=InputDeviceCapabilities] readonly attribute InputDeviceCapabilities? sourceCapabilities; + readonly attribute InputDeviceCapabilities? sourceCapabilities; // https://w3c.github.io/uievents/#idl-interface-UIEvent-initializers // TODO(foolip): None of the initUIEvent() arguments should be optional.
diff --git a/third_party/WebKit/Source/core/events/UIEventInit.idl b/third_party/WebKit/Source/core/events/UIEventInit.idl index e1f9cbe..a994a6b 100644 --- a/third_party/WebKit/Source/core/events/UIEventInit.idl +++ b/third_party/WebKit/Source/core/events/UIEventInit.idl
@@ -7,5 +7,5 @@ dictionary UIEventInit : EventInit { Window? view = null; long detail = 0; - [RuntimeEnabled=InputDeviceCapabilities] InputDeviceCapabilities? sourceCapabilities = null; -}; \ No newline at end of file + InputDeviceCapabilities? sourceCapabilities = null; +};
diff --git a/third_party/WebKit/Source/core/fetch/MultipartImageResourceParserTest.cpp b/third_party/WebKit/Source/core/fetch/MultipartImageResourceParserTest.cpp index 6512ee43..549e7a5 100644 --- a/third_party/WebKit/Source/core/fetch/MultipartImageResourceParserTest.cpp +++ b/third_party/WebKit/Source/core/fetch/MultipartImageResourceParserTest.cpp
@@ -89,7 +89,6 @@ }; for (size_t i = 0; i < WTF_ARRAY_LENGTH(tests); ++i) { WebURLResponse response; - response.initialize(); size_t end = 0; bool result = Platform::current()->parseMultipartHeadersFromBody(tests[i].data, strlen(tests[i].data), &response, &end); EXPECT_EQ(tests[i].result, result); @@ -100,7 +99,6 @@ TEST(MultipartResponseTest, ParseMultipartHeaders) { WebURLResponse webResponse; - webResponse.initialize(); webResponse.addHTTPHeaderField(WebString::fromLatin1("foo"), WebString::fromLatin1("bar")); webResponse.addHTTPHeaderField(WebString::fromLatin1("range"), WebString::fromLatin1("piyo")); webResponse.addHTTPHeaderField(WebString::fromLatin1("content-length"), WebString::fromLatin1("999")); @@ -121,7 +119,6 @@ TEST(MultipartResponseTest, ParseMultipartHeadersContentCharset) { WebURLResponse webResponse; - webResponse.initialize(); const char data[] = "content-type: text/html; charset=utf-8\n\n"; size_t end = 0;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp index 88dc902..3bb812e 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp
@@ -238,7 +238,6 @@ WrappedResourceRequest requestIn(request); WebURLResponse responseOut; - responseOut.initialize(); WebURLError errorOut; WebData dataOut; m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut);
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 9853026..2d84b43a 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -78,6 +78,8 @@ #include "core/page/FocusController.h" #include "core/page/FrameTree.h" #include "core/page/Page.h" +#include "core/page/scrolling/ChildViewportScrollCallback.h" +#include "core/page/scrolling/RootViewportScrollCallback.h" #include "core/page/scrolling/ScrollingCoordinator.h" #include "core/paint/FramePainter.h" #include "core/paint/PaintLayer.h" @@ -165,9 +167,7 @@ , m_scrollAnchor(this) , m_needsScrollbarsUpdate(false) , m_suppressAdjustViewSize(false) - , m_inPluginUpdate(false) - , m_inForcedLayoutByChildEmbeddedReplacedContent(false) - , m_allowsLayoutInvalidationAfterLayoutClean(false) + , m_allowsLayoutInvalidationAfterLayoutClean(true) { ASSERT(m_frame); init(); @@ -772,7 +772,6 @@ // correct size, which LayoutSVGRoot::computeReplacedLogicalWidth/Height rely on, when laying // out for the first time, or when the LayoutSVGRoot size has changed dynamically (eg. via <script>). FrameView* frameView = ownerLayoutObject->frame()->view(); - TemporaryChange<bool> t(frameView->m_inForcedLayoutByChildEmbeddedReplacedContent, true); // Mark the owner layoutObject as needing layout. ownerLayoutObject->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::Unknown); @@ -939,8 +938,6 @@ TRACE_EVENT0("blink,benchmark", "FrameView::layout"); TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "Layout"); - TemporaryChange<bool> allowsLayoutInvalidation(m_allowsLayoutInvalidationAfterLayoutClean, true); - if (m_autoSizeInfo) m_autoSizeInfo->autoSizeIfNeeded(); @@ -1229,9 +1226,6 @@ if (widget->isFrameView()) { FrameView* frameView = toFrameView(widget); bool didNeedLayout = frameView->needsLayout(); - // LayoutPart::updateWidgetGeometry() may invalidate and update layout of the sub-FrameView. This is - // allowed, but layout should be clean after updateWidgetGeometry unless the FrameView is throttled. - TemporaryChange<bool> allowLayoutInvalidation(frameView->m_allowsLayoutInvalidationAfterLayoutClean, true); part->updateWidgetGeometry(); if (!didNeedLayout && !frameView->shouldThrottleRendering()) frameView->checkDoesNotNeedLayout(); @@ -1825,36 +1819,14 @@ void FrameView::checkLayoutInvalidationIsAllowed() const { - CHECK(!m_inPluginUpdate); + if (m_allowsLayoutInvalidationAfterLayoutClean) + return; if (!m_frame->document()) return; - // TODO(crbug.com/442939): These are hacks to support embedded SVG. This is called from - // FrameView::forceLayoutParentViewIfNeeded() and the dirty layout will be cleaned up immediately. - // This is for the parent view of the view containing the embedded SVG. - if (m_inForcedLayoutByChildEmbeddedReplacedContent) - return; - // This is for the view containing the embedded SVG. - if (embeddedReplacedContent()) { - if (const LayoutObject* ownerLayoutObject = m_frame->ownerLayoutObject()) { - if (LocalFrame* frame = ownerLayoutObject->frame()) { - if (frame->view()->m_inForcedLayoutByChildEmbeddedReplacedContent) - return; - } - } - } - - CHECK(lifecycle().stateAllowsLayoutInvalidation()); - - if (m_allowsLayoutInvalidationAfterLayoutClean) - return; - // If we are updating all lifecycle phases beyond LayoutClean, we don't expect dirty layout after LayoutClean. - if (FrameView* rootFrameView = m_frame->localFrameRoot()->view()) { - if (rootFrameView->m_currentUpdateLifecyclePhasesTargetState > DocumentLifecycle::LayoutClean) - CHECK(lifecycle().state() < DocumentLifecycle::LayoutClean); - } + CHECK(lifecycle().state() < DocumentLifecycle::LayoutClean); } void FrameView::scheduleRelayout() @@ -2392,13 +2364,31 @@ void FrameView::didAttachDocument() { + FrameHost* frameHost = m_frame->host(); + DCHECK(frameHost); + + DCHECK(m_frame->document()); + + ViewportScrollCallback* viewportScrollCallback = nullptr; + if (m_frame->isMainFrame()) { - DCHECK(m_frame->host()); - ScrollableArea& visualViewport = m_frame->host()->visualViewport(); + ScrollableArea& visualViewport = frameHost->visualViewport(); ScrollableArea* layoutViewport = layoutViewportScrollableArea(); DCHECK(layoutViewport); - m_viewportScrollableArea = RootFrameViewport::create(visualViewport, *layoutViewport); + + RootFrameViewport* rootFrameViewport = + RootFrameViewport::create(visualViewport, *layoutViewport); + m_viewportScrollableArea = rootFrameViewport; + + viewportScrollCallback = RootViewportScrollCallback::create( + &frameHost->topControls(), + &frameHost->overscrollController(), + *rootFrameViewport); + } else { + viewportScrollCallback = ChildViewportScrollCallback::create(); } + + m_frame->document()->initializeRootScroller(viewportScrollCallback); } void FrameView::updateScrollCorner() @@ -2535,6 +2525,11 @@ } if (LayoutViewItem view = layoutViewItem()) { + forAllNonThrottledFrameViews([](FrameView& frameView) { + frameView.checkDoesNotNeedLayout(); + frameView.m_allowsLayoutInvalidationAfterLayoutClean = false; + }); + { TRACE_EVENT1("devtools.timeline", "UpdateLayerTree", "data", InspectorUpdateLayerTreeEvent::data(m_frame.get())); @@ -2543,7 +2538,7 @@ view.compositor()->updateIfNeededRecursive(); scrollContentsIfNeededRecursive(); - ASSERT(lifecycle().state() >= DocumentLifecycle::CompositingClean); + DCHECK(lifecycle().state() >= DocumentLifecycle::CompositingClean); if (targetState >= DocumentLifecycle::PrePaintClean) { if (!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) @@ -2568,10 +2563,15 @@ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) pushPaintArtifactToCompositor(); - ASSERT(!view.hasPendingSelection()); - ASSERT((m_frame->document()->printing() && lifecycle().state() == DocumentLifecycle::PaintInvalidationClean) + DCHECK(!view.hasPendingSelection()); + DCHECK((m_frame->document()->printing() && lifecycle().state() == DocumentLifecycle::PaintInvalidationClean) || lifecycle().state() == DocumentLifecycle::PaintClean); } + + forAllNonThrottledFrameViews([](FrameView& frameView) { + frameView.checkDoesNotNeedLayout(); + frameView.m_allowsLayoutInvalidationAfterLayoutClean = true; + }); } updateViewportIntersectionsForSubtree(targetState); @@ -2696,6 +2696,8 @@ m_frame->document()->updateStyleAndLayoutTree(); CHECK(!shouldThrottleRendering()); + CHECK(m_frame->document()->isActive()); + CHECK(!m_nestedLayoutCount); if (needsLayout()) layout(); @@ -2707,15 +2709,12 @@ // TODO(leviw): This currently runs the entire lifecycle on plugin WebViews. We // should have a way to only run these other Documents to the same lifecycle stage // as this frame. - { - TemporaryChange<bool> t(m_inPluginUpdate, true); - const ChildrenWidgetSet* viewChildren = children(); - for (const Member<Widget>& child : *viewChildren) { - if ((*child).isPluginContainer()) - toPluginView(child.get())->updateAllLifecyclePhases(); - } - checkDoesNotNeedLayout(); + const ChildrenWidgetSet* viewChildren = children(); + for (const Member<Widget>& child : *viewChildren) { + if ((*child).isPluginContainer()) + toPluginView(child.get())->updateAllLifecyclePhases(); } + checkDoesNotNeedLayout(); // FIXME: Calling layout() shouldn't trigger script execution or have any // observable effects on the frame tree but we're not quite there yet.
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h index d6b20250c..808842b6 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.h +++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -915,8 +915,6 @@ bool m_needsScrollbarsUpdate; bool m_suppressAdjustViewSize; - bool m_inPluginUpdate; - bool m_inForcedLayoutByChildEmbeddedReplacedContent; bool m_allowsLayoutInvalidationAfterLayoutClean; // For testing.
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp index 8b2e6c2a..2eed1f5a 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp +++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp
@@ -18,6 +18,11 @@ { } +void RootFrameViewport::setLayoutViewport(ScrollableArea& newLayoutViewport) +{ + m_layoutViewport = &newLayoutViewport; +} + void RootFrameViewport::updateScrollAnimator() { scrollAnimator().setCurrentPosition(toFloatPoint(scrollOffsetFromScrollAnimators()));
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.h b/third_party/WebKit/Source/core/frame/RootFrameViewport.h index 2b0a4d9..1342700f 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewport.h +++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.h
@@ -31,6 +31,8 @@ DECLARE_VIRTUAL_TRACE(); + void setLayoutViewport(ScrollableArea&); + // ScrollableArea Implementation void setScrollPosition(const DoublePoint&, ScrollType, ScrollBehavior = ScrollBehaviorInstant) override; LayoutRect scrollIntoView(
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp index e0edd0c..87ff48b 100644 --- a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp +++ b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp
@@ -441,4 +441,38 @@ EXPECT_POINT_EQ(DoublePoint(10, 10), layoutViewport->scrollPositionDouble()); } +// Tests that setting an alternate layout viewport scrolls the alternate +// instead of the original. +TEST_F(RootFrameViewportTest, SetAlternateLayoutViewport) +{ + IntSize viewportSize(100, 100); + RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(200, 300)); + VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); + + RootFrameViewStub* alternateScroller = RootFrameViewStub::create(viewportSize, IntSize(600, 500)); + + RootFrameViewport* rootFrameViewport = + RootFrameViewport::create(*visualViewport, *layoutViewport); + + visualViewport->setScale(2); + + rootFrameViewport->setScrollPosition(DoublePoint(100, 100), UserScroll); + EXPECT_POINT_EQ(DoublePoint(50, 50), visualViewport->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(50, 50), layoutViewport->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(100, 100), rootFrameViewport->scrollPositionDouble()); + + rootFrameViewport->setLayoutViewport(*alternateScroller); + EXPECT_POINT_EQ(DoublePoint(50, 50), visualViewport->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(0, 0), alternateScroller->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(50, 50), rootFrameViewport->scrollPositionDouble()); + + rootFrameViewport->setScrollPosition(DoublePoint(200, 200), UserScroll); + EXPECT_POINT_EQ(DoublePoint(50, 50), visualViewport->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(150, 150), alternateScroller->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(200, 200), rootFrameViewport->scrollPositionDouble()); + EXPECT_POINT_EQ(DoublePoint(50, 50), layoutViewport->scrollPositionDouble()); + + EXPECT_POINT_EQ(DoublePoint(550, 450), rootFrameViewport->maximumScrollPositionDouble()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp index 34f11635..b4283a1 100644 --- a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp +++ b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp
@@ -91,6 +91,9 @@ if (port == m_port) return true; + if (m_port == 80 && (port == 443 || (port == 0 && defaultPortForProtocol(url.protocol()) == 443))) + return true; + if (!port) return isDefaultPortForProtocol(m_port, url.protocol());
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp index 016f20a..012ba8b 100644 --- a/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp +++ b/third_party/WebKit/Source/core/frame/csp/CSPSourceTest.cpp
@@ -71,7 +71,7 @@ EXPECT_FALSE(source.matches(KURL(base, "http://example.com:9000/foo/"), ResourceRequest::RedirectStatus::NoRedirect)); } -TEST_F(CSPSourceTest, InsecureSourceMatchesSecure) +TEST_F(CSPSourceTest, InsecureSchemeMatchesSecureScheme) { KURL base; CSPSource source(csp.get(), "http", "", 0, "/", CSPSource::NoWildcard, CSPSource::HasWildcard); @@ -83,7 +83,7 @@ EXPECT_FALSE(source.matches(KURL(base, "ftp://example.com:8000/"))); } -TEST_F(CSPSourceTest, InsecureHostMatchesSecure) +TEST_F(CSPSourceTest, InsecureHostSchemeMatchesSecureScheme) { KURL base; CSPSource source(csp.get(), "http", "example.com", 0, "/", CSPSource::NoWildcard, CSPSource::HasWildcard); @@ -94,4 +94,28 @@ EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:8000/"))); } +TEST_F(CSPSourceTest, InsecureHostSchemePortMatchesSecurePort) +{ + KURL base; + CSPSource source(csp.get(), "http", "example.com", 80, "/", CSPSource::NoWildcard, CSPSource::NoWildcard); + EXPECT_TRUE(source.matches(KURL(base, "http://example.com/"))); + EXPECT_TRUE(source.matches(KURL(base, "http://example.com:80/"))); + EXPECT_TRUE(source.matches(KURL(base, "http://example.com:443/"))); + EXPECT_TRUE(source.matches(KURL(base, "https://example.com/"))); + EXPECT_TRUE(source.matches(KURL(base, "https://example.com:80/"))); + EXPECT_TRUE(source.matches(KURL(base, "https://example.com:443/"))); + + EXPECT_FALSE(source.matches(KURL(base, "http://example.com:8443/"))); + EXPECT_FALSE(source.matches(KURL(base, "https://example.com:8443/"))); + + EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com/"))); + EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com:80/"))); + EXPECT_FALSE(source.matches(KURL(base, "http://not-example.com:443/"))); + EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com/"))); + EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:80/"))); + EXPECT_FALSE(source.matches(KURL(base, "https://not-example.com:443/"))); +} + + + } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp b/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp index 00e598d..3131829 100644 --- a/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLDialogElement.cpp
@@ -55,7 +55,7 @@ Element* element = toElement(node); if (element->isFormControlElement()) { HTMLFormControlElement* control = toHTMLFormControlElement(node); - if (control->isAutofocusable()) { + if (control->isAutofocusable() && control->isFocusable()) { control->focus(); return; }
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp index 9ad44bc..5160f599 100644 --- a/third_party/WebKit/Source/core/html/HTMLElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -1054,33 +1054,33 @@ int HTMLElement::offsetLeftForBinding() { - document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); + Element* offsetParent = unclosedOffsetParent(); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) - return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetLeft(unclosedOffsetParent())), layoutObject->styleRef()).round(); + return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetLeft(offsetParent)), layoutObject->styleRef()).round(); return 0; } int HTMLElement::offsetTopForBinding() { - document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); + Element* offsetParent = unclosedOffsetParent(); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) - return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetTop(unclosedOffsetParent())), layoutObject->styleRef()).round(); + return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetTop(offsetParent)), layoutObject->styleRef()).round(); return 0; } int HTMLElement::offsetWidthForBinding() { - document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); + Element* offsetParent = unclosedOffsetParent(); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) - return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetWidth(unclosedOffsetParent())), layoutObject->styleRef()).round(); + return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetWidth(offsetParent)), layoutObject->styleRef()).round(); return 0; } int HTMLElement::offsetHeightForBinding() { - document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); + Element* offsetParent = unclosedOffsetParent(); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) - return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetHeight(unclosedOffsetParent())), layoutObject->styleRef()).round(); + return adjustLayoutUnitForAbsoluteZoom(LayoutUnit(layoutObject->pixelSnappedOffsetHeight(offsetParent)), layoutObject->styleRef()).round(); return 0; }
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h index 1f9eed4..975a9ff 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h +++ b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.h
@@ -92,6 +92,7 @@ void setSandboxFlags(SandboxFlags); bool loadOrRedirectSubframe(const KURL&, const AtomicString& frameName, bool replaceCurrentItem); + bool isKeyboardFocusable() const override; private: // Intentionally private to prevent redundant checks when the type is @@ -99,7 +100,6 @@ bool isLocal() const override { return true; } bool isRemote() const override { return false; } - bool isKeyboardFocusable() const override; bool isFrameOwnerElement() const final { return true; } virtual ReferrerPolicy referrerPolicyAttribute() { return ReferrerPolicyDefault; }
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp index 08e4899..f307a3f 100644 --- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -32,7 +32,6 @@ #include "core/dom/shadow/ShadowRoot.h" #include "core/fetch/ImageResource.h" #include "core/frame/Settings.h" -#include "core/html/FormData.h" #include "core/html/HTMLDocument.h" #include "core/html/HTMLImageLoader.h" #include "core/html/HTMLMetaElement.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.h b/third_party/WebKit/Source/core/html/HTMLObjectElement.h index e1eedf6d..6721fc9 100644 --- a/third_party/WebKit/Source/core/html/HTMLObjectElement.h +++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.h
@@ -31,6 +31,9 @@ class HTMLFormElement; +// Inheritance of FormAssociatedElement was used for NPAPI form association, but is still +// kept here so that legacy APIs such as form attribute can keep working according to the spec. +// See: https://html.spec.whatwg.org/multipage/embedded-content.html#the-object-element class CORE_EXPORT HTMLObjectElement final : public HTMLPlugInElement, public FormAssociatedElement { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(HTMLObjectElement);
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp index db0e19a6..b62b61d 100644 --- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -375,9 +375,9 @@ bool HTMLPlugInElement::isKeyboardFocusable() const { - if (!document().isActive()) - return false; - return pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->supportsKeyboardFocus(); + if (HTMLFrameOwnerElement::isKeyboardFocusable()) + return true; + return document().isActive() && pluginWidget() && pluginWidget()->isPluginView() && toPluginView(pluginWidget())->supportsKeyboardFocus(); } bool HTMLPlugInElement::hasCustomFocusLogic() const
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp index 66ac700..fb051148 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -145,7 +145,7 @@ if (optionIndex == selectedIndex()) return; - selectOption(optionIndex, DeselectOtherOptions | MakeOptionDirty | (fireOnChangeNow ? DispatchInputAndChangeEvent : 0)); + selectOption(item(optionIndex), DeselectOtherOptions | MakeOptionDirty | (fireOnChangeNow ? DispatchInputAndChangeEvent : 0)); } bool HTMLSelectElement::hasPlaceholderLabelOption() const @@ -283,6 +283,7 @@ // We clear the previously selected option(s) when needed, to guarantee // calling setSelectedIndex() only once. int optionIndex = 0; + HTMLOptionElement* option = nullptr; if (value.isNull()) { optionIndex = -1; } else { @@ -291,8 +292,10 @@ for (auto& item : listItems()) { if (!isHTMLOptionElement(item)) continue; - if (toHTMLOptionElement(item)->value() == value) + if (toHTMLOptionElement(item)->value() == value) { + option = toHTMLOptionElement(item); break; + } optionIndex++; } if (optionIndex >= static_cast<int>(listItems().size())) @@ -306,7 +309,7 @@ SelectOptionFlags flags = DeselectOtherOptions | MakeOptionDirty; if (sendEvents) flags |= DispatchInputAndChangeEvent; - selectOption(optionIndex, flags); + selectOption(option, flags); if (sendEvents && previousSelectedIndex != selectedIndex() && !usesMenuList()) listBoxOnChange(); @@ -880,17 +883,13 @@ if (multiple()) return; HTMLOptionElement* firstEnabledOption = nullptr; - int firstEnabledOptionIndex = -1; HTMLOptionElement* lastSelectedOption = nullptr; bool didChange = false; int optionIndex = 0; // We can't use HTMLSelectElement::options here because this function is // called in Node::insertedInto and Node::removedFrom before invalidating // node collections. - for (auto& item : listItems()) { - if (!isHTMLOptionElement(item)) - continue; - HTMLOptionElement* option = toHTMLOptionElement(item); + for (const auto& option : optionList()) { if (option->selected()) { if (lastSelectedOption) { lastSelectedOption->setSelectedState(false); @@ -900,7 +899,6 @@ } if (!firstEnabledOption && !option->isDisabledFormControl()) { firstEnabledOption = option; - firstEnabledOptionIndex = optionIndex; if (reason == ResetReasonSelectedOptionRemoved) { // There must be no selected OPTIONs. break; @@ -909,7 +907,7 @@ ++optionIndex; } if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnabledOption->selected()) { - selectOption(firstEnabledOption, firstEnabledOptionIndex, reason == ResetReasonSelectedOptionRemoved ? 0 : DeselectOtherOptions); + selectOption(firstEnabledOption, reason == ResetReasonSelectedOptionRemoved ? 0 : DeselectOtherOptions); lastSelectedOption = firstEnabledOption; didChange = true; } @@ -945,7 +943,7 @@ void HTMLSelectElement::setSelectedIndex(int index) { - selectOption(index, DeselectOtherOptions | MakeOptionDirty); + selectOption(item(index), DeselectOtherOptions | MakeOptionDirty); } void HTMLSelectElement::setSuggestedOption(HTMLOptionElement* option) @@ -1054,25 +1052,14 @@ m_lastOnChangeSelection.clear(); } -void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) -{ - selectOption(optionIndex < 0 ? nullptr : item(optionIndex), flags); -} - -void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlags flags) -{ - selectOption(option, option ? option->index() : -1, flags); -} - // TODO(tkent): This function is not efficient. It contains multiple O(N) // operations. crbug.com/577989. -void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex, SelectOptionFlags flags) +void HTMLSelectElement::selectOption(HTMLOptionElement* element, SelectOptionFlags flags) { TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); - ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0)); - // selectedIndex() is O(N). - if (isAutofilled() && selectedIndex() != optionIndex) + // selectedOption() is O(N). + if (isAutofilled() && selectedOption() != element) setAutofilled(false); if (element) { @@ -1095,6 +1082,14 @@ setActiveSelectionEnd(element); } + // Need to update m_lastOnChangeOption before + // LayoutMenuList::updateFromElement. + bool shouldDispatchEvents = false; + if (usesMenuList()) { + shouldDispatchEvents = (flags & DispatchInputAndChangeEvent) && m_lastOnChangeOption != element; + m_lastOnChangeOption = element; + } + // For the menu list case, this is what makes the selected element appear. if (LayoutObject* layoutObject = this->layoutObject()) layoutObject->updateFromElement(); @@ -1106,16 +1101,16 @@ setNeedsValidityCheck(); if (usesMenuList()) { - if (flags & DispatchInputAndChangeEvent) - dispatchInputAndChangeEventForMenuList(); - else - m_lastOnChangeOption = element; + if (shouldDispatchEvents) { + dispatchInputEvent(); + dispatchFormControlChangeEvent(); + } if (LayoutObject* layoutObject = this->layoutObject()) { - // Need to check usesMenuList() again because - // dispatchInputAndChangeEventForMenuList() might change the status. + // Need to check usesMenuList() again because event handlers might + // change the status. if (usesMenuList()) { - // didSetSelectedIndex() is O(N) because of optionToListIndex. - toLayoutMenuList(layoutObject)->didSetSelectedIndex(optionIndex); + // didSelectOption() is O(N) because of HTMLOptionElement::index(). + toLayoutMenuList(layoutObject)->didSelectOption(element); } } } @@ -1244,11 +1239,13 @@ if (index < itemsSize && isHTMLOptionElement(items[index]) && toHTMLOptionElement(items[index])->value() == state[0]) { toHTMLOptionElement(items[index])->setSelectedState(true); toHTMLOptionElement(items[index])->setDirty(true); + m_lastOnChangeOption = toHTMLOptionElement(items[index]); } else { size_t foundIndex = searchOptionsForValue(state[0], 0, itemsSize); if (foundIndex != kNotFound) { toHTMLOptionElement(items[foundIndex])->setSelectedState(true); toHTMLOptionElement(items[foundIndex])->setDirty(true); + m_lastOnChangeOption = toHTMLOptionElement(items[foundIndex]); } } } else { @@ -1279,7 +1276,7 @@ void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) { bool oldMultiple = m_multiple; - int oldSelectedIndex = selectedIndex(); + HTMLOptionElement* oldSelectedOption = selectedOption(); m_multiple = !value.isNull(); setNeedsValidityCheck(); lazyReattachIfAttached(); @@ -1289,8 +1286,8 @@ // Preserving the first selection is compatible with Firefox and // WebKit. However Edge seems to "ask for a reset" simply. As of 2016 // March, the HTML specification says nothing about this. - if (oldSelectedIndex >= 0) - selectOption(oldSelectedIndex, DeselectOtherOptions); + if (oldSelectedOption) + selectOption(oldSelectedOption, DeselectOtherOptions); else resetToDefaultSelection(); } @@ -1793,7 +1790,10 @@ int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhead::CycleFirstChar); if (index < 0) return; - selectOption(listToOptionIndex(index), DeselectOtherOptions | MakeOptionDirty | DispatchInputAndChangeEvent); + HTMLOptionElement* option = nullptr; + if (static_cast<size_t>(index) < listItems().size() && isHTMLOptionElement(listItems()[index])) + option = toHTMLOptionElement(listItems()[index]); + selectOption(option, DeselectOtherOptions | MakeOptionDirty | DispatchInputAndChangeEvent); if (!usesMenuList()) listBoxOnChange(); } @@ -1804,26 +1804,22 @@ if (!focused()) accessKeyAction(false); - const ListItems& items = listItems(); - int listIndex = optionToListIndex(index); - if (listIndex < 0) - return; - HTMLElement& element = *items[listIndex]; - if (!isHTMLOptionElement(element)) + HTMLOptionElement* option = item(index); + if (!option) return; EventQueueScope scope; // If this index is already selected, unselect. otherwise update the // selected index. SelectOptionFlags flags = DispatchInputAndChangeEvent | (multiple() ? 0 : DeselectOtherOptions); - if (toHTMLOptionElement(element).selected()) { + if (option->selected()) { if (usesMenuList()) - selectOption(-1, flags); + selectOption(nullptr, flags); else - toHTMLOptionElement(element).setSelectedState(false); + option->setSelectedState(false); } else { - selectOption(index, flags); + selectOption(option, flags); } - toHTMLOptionElement(element).setDirty(true); + option->setDirty(true); if (usesMenuList()) return; listBoxOnChange(); @@ -1975,13 +1971,17 @@ layoutObject()->updateFromElement(); } -int HTMLSelectElement::optionIndexToBeShown() const +HTMLOptionElement* HTMLSelectElement::optionToBeShown() const { - if (m_indexToSelectOnCancel >= 0) - return listToOptionIndex(m_indexToSelectOnCancel); + if (m_indexToSelectOnCancel >= 0 && static_cast<size_t>(m_indexToSelectOnCancel) < listItems().size() && isHTMLOptionElement(listItems()[m_indexToSelectOnCancel])) + return toHTMLOptionElement(listItems()[m_indexToSelectOnCancel]); if (m_suggestedOption) - return m_suggestedOption->index(); - return selectedIndex(); + return m_suggestedOption; + // TODO(tkent): We should not call optionToBeShown() in multiple() case. + if (multiple()) + return selectedOption(); + DCHECK_EQ(selectedOption(), m_lastOnChangeOption); + return m_lastOnChangeOption; } void HTMLSelectElement::valueChanged(unsigned listIndex)
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h index cdc4fe9..3bb86d9 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -31,6 +31,7 @@ #include "core/html/HTMLContentElement.h" #include "core/html/HTMLFormControlElementWithState.h" #include "core/html/HTMLOptionsCollection.h" +#include "core/html/forms/OptionList.h" #include "core/html/forms/TypeAhead.h" #include "wtf/Vector.h" @@ -83,14 +84,23 @@ String suggestedValue() const; void setSuggestedValue(const String&); + // |options| and |selectedOptions| are not safe to be used in in + // HTMLOptionElement::removedFrom() and insertedInto() because their cache + // is inconsistent in these functions. HTMLOptionsCollection* options(); HTMLCollection* selectedOptions(); + // This is similar to |options| HTMLCollection. But this is safe in + // HTMLOptionElement::removedFrom() and insertedInto(). + // OptionList supports only forward iteration. + OptionList optionList() { return OptionList(*this); } + void optionElementChildrenChanged(const HTMLOptionElement&); void invalidateSelectedItems(); using ListItems = HeapVector<Member<HTMLElement>>; + // We prefer |optionList()| to |listItems()|. const ListItems& listItems() const; void accessKeyAction(bool sendMouseEvents) override; @@ -150,7 +160,7 @@ void provisionalSelectionChanged(unsigned); void popupDidHide(); bool popupIsVisible() const { return m_popupIsVisible; } - int optionIndexToBeShown() const; + HTMLOptionElement* optionToBeShown() const; void showPopup(); void hidePopup(); PopupMenu* popup() const { return m_popup.get(); } @@ -219,9 +229,7 @@ MakeOptionDirty = 1 << 2, }; typedef unsigned SelectOptionFlags; - void selectOption(int optionIndex, SelectOptionFlags); void selectOption(HTMLOptionElement*, SelectOptionFlags); - void selectOption(HTMLOptionElement*, int optionIndex, SelectOptionFlags); void deselectItemsWithoutValidation(HTMLElement* elementToExclude = 0); void parseMultipleAttribute(const AtomicString&); HTMLOptionElement* lastSelectedOption() const;
diff --git a/third_party/WebKit/Source/core/html/forms/OptionList.cpp b/third_party/WebKit/Source/core/html/forms/OptionList.cpp new file mode 100644 index 0000000..06f4f6f --- /dev/null +++ b/third_party/WebKit/Source/core/html/forms/OptionList.cpp
@@ -0,0 +1,40 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/html/forms/OptionList.h" + +#include "core/dom/ElementTraversal.h" +#include "core/html/HTMLOptionElement.h" +#include "core/html/HTMLSelectElement.h" + +namespace blink { + +void OptionListIterator::advance(HTMLOptionElement* previous) +{ + // This function returns only + // - An OPTION child of m_select, or + // - An OPTION child of an OPTGROUP child of m_select. + + Element* current; + if (previous) { + DCHECK_EQ(previous->ownerSelectElement(), m_select); + current = ElementTraversal::nextSkippingChildren(*previous, m_select); + } else { + current = ElementTraversal::firstChild(*m_select); + } + while (current) { + if (isHTMLOptionElement(current)) { + m_current = toHTMLOptionElement(current); + return; + } + if (isHTMLOptGroupElement(current) && current->parentNode() == m_select) { + if ((m_current = Traversal<HTMLOptionElement>::firstChild(*current))) + return; + } + current = ElementTraversal::nextSkippingChildren(*current, m_select); + } + m_current = nullptr; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/html/forms/OptionList.h b/third_party/WebKit/Source/core/html/forms/OptionList.h new file mode 100644 index 0000000..07a36cf7 --- /dev/null +++ b/third_party/WebKit/Source/core/html/forms/OptionList.h
@@ -0,0 +1,56 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef OptionList_h +#define OptionList_h + +#include "core/CoreExport.h" +#include "platform/heap/Handle.h" + +namespace blink { + +class HTMLSelectElement; +class HTMLOptionElement; + +class CORE_EXPORT OptionListIterator final { + STACK_ALLOCATED(); +public: + explicit OptionListIterator(HTMLSelectElement* select) : m_select(select) + { + if (m_select) + advance(nullptr); + } + HTMLOptionElement* operator*() { return m_current; } + void operator++() + { + if (m_current) + advance(m_current); + } + bool operator==(const OptionListIterator& other) const { return m_current == other.m_current; } + bool operator!=(const OptionListIterator& other) const { return !(*this == other); } + +private: + void advance(HTMLOptionElement* current); + + Member<HTMLSelectElement> m_select; + Member<HTMLOptionElement> m_current; // nullptr means we reached to the end. +}; + +// OptionList class is a lightweight version of HTMLOptionsCollection. +class OptionList final { + STACK_ALLOCATED(); +public: + explicit OptionList(HTMLSelectElement& select) : m_select(select) {} + using Iterator = OptionListIterator; + Iterator begin() { return Iterator(m_select); } + Iterator end() { return Iterator(nullptr); } + +private: + Member<HTMLSelectElement> m_select; +}; + +} // namespace blink + +#endif +
diff --git a/third_party/WebKit/Source/core/html/forms/OptionListTest.cpp b/third_party/WebKit/Source/core/html/forms/OptionListTest.cpp new file mode 100644 index 0000000..15bdafdd2 --- /dev/null +++ b/third_party/WebKit/Source/core/html/forms/OptionListTest.cpp
@@ -0,0 +1,89 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/html/forms/OptionList.h" + +#include "core/html/HTMLDocument.h" +#include "core/html/HTMLOptionElement.h" +#include "core/html/HTMLSelectElement.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +namespace { + +AtomicString id(const HTMLOptionElement* option) +{ + return option->fastGetAttribute(HTMLNames::idAttr); +} + +} // namespace + +class OptionListTest : public ::testing::Test { +protected: + void SetUp() override + { + HTMLDocument* document = HTMLDocument::create(); + HTMLSelectElement* select = HTMLSelectElement::create(*document); + document->appendChild(select); + m_select = select; + } + HTMLSelectElement& select() const { return *m_select; } + +private: + Persistent<HTMLSelectElement> m_select; +}; + +TEST_F(OptionListTest, Empty) +{ + OptionList list = select().optionList(); + EXPECT_EQ(list.end(), list.begin()) << "OptionList should iterate over empty SELECT successfully"; +} + +TEST_F(OptionListTest, OptionOnly) +{ + select().setInnerHTML("text<input><option id=o1></option><input><option id=o2></option><input>", ASSERT_NO_EXCEPTION); + HTMLElement* div = toHTMLElement(select().document().createElement("div", ASSERT_NO_EXCEPTION)); + div->setInnerHTML("<option id=o3></option>", ASSERT_NO_EXCEPTION); + select().appendChild(div); + OptionList list = select().optionList(); + OptionList::Iterator iter = list.begin(); + EXPECT_EQ("o1", id(*iter)); + ++iter; + EXPECT_EQ("o2", id(*iter)); + ++iter; + // No "o3" because it's in DIV. + EXPECT_EQ(list.end(), iter); +} + +TEST_F(OptionListTest, Optgroup) +{ + select().setInnerHTML("<optgroup><option id=g11></option><option id=g12></option></optgroup>" + "<optgroup><option id=g21></option></optgroup>" + "<optgroup></optgroup>" + "<option id=o1></option>" + "<optgroup><option id=g41></option></optgroup>", ASSERT_NO_EXCEPTION); + OptionList list = select().optionList(); + OptionList::Iterator iter = list.begin(); + EXPECT_EQ("g11", id(*iter)); + ++iter; + EXPECT_EQ("g12", id(*iter)); + ++iter; + EXPECT_EQ("g21", id(*iter)); + ++iter; + EXPECT_EQ("o1", id(*iter)); + ++iter; + EXPECT_EQ("g41", id(*iter)); + ++iter; + EXPECT_EQ(list.end(), iter); + + toHTMLElement(select().firstChild())->setInnerHTML( + "<optgroup><option id=gg11></option></optgroup>" + "<option id=g11></option>", ASSERT_NO_EXCEPTION); + list = select().optionList(); + iter = list.begin(); + EXPECT_EQ("g11", id(*iter)) << "Nested OPTGROUP should be ignored."; +} + +} // naemespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h b/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h index 3c28c83c..52948ef 100644 --- a/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h +++ b/third_party/WebKit/Source/core/html/parser/AtomicHTMLToken.h
@@ -235,10 +235,8 @@ if (attribute.nameAsVector().isEmpty()) continue; - ASSERT(attribute.nameRange().start); - ASSERT(attribute.nameRange().end); - ASSERT(attribute.valueRange().start); - ASSERT(attribute.valueRange().end); + attribute.nameRange().checkValid(); + attribute.valueRange().checkValid(); AtomicString value(attribute.value8BitIfNecessary()); const QualifiedName& name = nameForAttribute(attribute);
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLInputStream.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLInputStream.cpp index 56f10af2..971a71d 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLInputStream.cpp +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLInputStream.cpp
@@ -90,8 +90,10 @@ m_current.append(SegmentedString(m_segments[i])); } - if (!unparsedInput.isEmpty()) - m_current.prepend(SegmentedString(unparsedInput)); + if (!unparsedInput.isEmpty()) { + m_current.prepend(SegmentedString(unparsedInput), + SegmentedString::PrependType::NewInput); + } if (isClosed && !m_current.isClosed()) m_current.close();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp index 43fc4eb..cd8005ab 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLEntityParser.cpp
@@ -97,7 +97,8 @@ source.push(consumedCharacters[1]); source.push(consumedCharacters[0]); } else - source.prepend(SegmentedString(String(consumedCharacters))); + source.prepend(SegmentedString(String(consumedCharacters)), + SegmentedString::PrependType::Unconsume); } static bool consumeNamedEntity(SegmentedString& source, DecodedHTMLEntity& decodedEntity, bool& notEnoughCharacters, UChar additionalAllowedCharacter, UChar& cc)
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp index a6b5992..14ecba3 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -34,7 +34,6 @@ #include "core/css/MediaValuesCached.h" #include "core/css/parser/SizesAttributeParser.h" #include "core/dom/Document.h" -#include "core/dom/ScriptLoader.h" #include "core/fetch/IntegrityMetadata.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -222,6 +221,7 @@ } } + TextPosition position = TextPosition(source.currentLine(), source.currentColumn()); FetchRequest::ResourceWidth resourceWidth; float sourceSize = m_sourceSize; @@ -272,10 +272,6 @@ // explanation. else if (match(attributeName, integrityAttr)) SubresourceIntegrity::parseIntegrityAttribute(attributeValue, m_integrityMetadata); - else if (match(attributeName, typeAttr)) - m_typeAttributeValue = attributeValue; - else if (match(attributeName, languageAttr)) - m_languageAttributeValue = attributeValue; } template<typename NameType> @@ -444,8 +440,6 @@ return false; if (match(m_tagImpl, inputTag) && !m_inputIsImage) return false; - if (match(m_tagImpl, scriptTag) && !ScriptLoader::isValidScriptTypeAndLanguage(m_typeAttributeValue, m_languageAttributeValue, ScriptLoader::AllowLegacyTypeInTypeAttribute)) - return false; return true; } @@ -477,8 +471,6 @@ String m_imgSrcUrl; String m_srcsetAttributeValue; String m_asAttributeValue; - String m_typeAttributeValue; - String m_languageAttributeValue; float m_sourceSize; bool m_sourceSizeSet; FetchRequest::DeferOption m_defer;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp index 8932e764..bc584d1e 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
@@ -414,33 +414,4 @@ test(testCase); } -// The preload scanner should follow the same policy that the ScriptLoader does -// with regard to the type and language attribute. -TEST_F(HTMLPreloadScannerTest, testScriptTypeAndLanguage) -{ - TestCase testCases[] = { - // Allow empty src and language attributes. - {"http://example.test", "<script src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - {"http://example.test", "<script type='' language='' src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - // Allow standard language and type attributes. - {"http://example.test", "<script type='text/javascript' src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - {"http://example.test", "<script type='text/javascript' language='javascript' src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - // Allow legacy languages in the "language" attribute with an empty - // type. - {"http://example.test", "<script language='javascript1.1' src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - // Allow legacy languages in the "type" attribute. - {"http://example.test", "<script type='javascript' src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - {"http://example.test", "<script type='javascript1.7' src='test.js'></script>", "test.js", "http://example.test/", Resource::Script, 0}, - // Do not allow invalid types in the "type" attribute. - {"http://example.test", "<script type='invalid' src='test.js'></script>", nullptr, "http://example.test/", Resource::Script, 0}, - {"http://example.test", "<script type='asdf' src='test.js'></script>", nullptr, "http://example.test/", Resource::Script, 0}, - // Do not allow invalid languages. - {"http://example.test", "<script language='french' src='test.js'></script>", nullptr, "http://example.test/", Resource::Script, 0}, - {"http://example.test", "<script language='python' src='test.js'></script>", nullptr, "http://example.test/", Resource::Script, 0}, - }; - - for (const auto& testCase : testCases) - test(testCase); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLToken.h b/third_party/WebKit/Source/core/html/parser/HTMLToken.h index 679a187..3f0d7637 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLToken.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLToken.h
@@ -81,6 +81,32 @@ class Range { DISALLOW_NEW(); public: + static constexpr int kInvalidOffset = -1; + + inline void clear() + { +#if ENABLE(ASSERT) + start = kInvalidOffset; + end = kInvalidOffset; +#endif + } + + // Check Range instance that is actively being parsed. + inline void checkValidStart() const + { + DCHECK(start != kInvalidOffset); + DCHECK_GE(start, 0); + } + + // Check Range instance which finished parse. + inline void checkValid() const + { + checkValidStart(); + DCHECK(end != kInvalidOffset); + DCHECK_GE(end, 0); + DCHECK_LE(start, end); + } + int start; int end; }; @@ -122,8 +148,8 @@ void clear() { m_type = Uninitialized; + m_range.clear(); m_range.start = 0; - m_range.end = 0; m_baseOffset = 0; // Don't call Vector::clear() as that would destroy the // alloced VectorBuffer. If the innerHTML'd content has @@ -314,45 +340,43 @@ ASSERT(m_type == StartTag || m_type == EndTag); m_attributes.grow(m_attributes.size() + 1); m_currentAttribute = &m_attributes.last(); -#if ENABLE(ASSERT) - m_currentAttribute->mutableNameRange().start = 0; - m_currentAttribute->mutableNameRange().end = 0; - m_currentAttribute->mutableValueRange().start = 0; - m_currentAttribute->mutableValueRange().end = 0; -#endif + m_currentAttribute->mutableNameRange().clear(); + m_currentAttribute->mutableValueRange().clear(); } void beginAttributeName(int offset) { m_currentAttribute->mutableNameRange().start = offset - m_baseOffset; + m_currentAttribute->nameRange().checkValidStart(); } void endAttributeName(int offset) { int index = offset - m_baseOffset; m_currentAttribute->mutableNameRange().end = index; + m_currentAttribute->nameRange().checkValid(); m_currentAttribute->mutableValueRange().start = index; m_currentAttribute->mutableValueRange().end = index; } void beginAttributeValue(int offset) { + m_currentAttribute->mutableValueRange().clear(); m_currentAttribute->mutableValueRange().start = offset - m_baseOffset; -#if ENABLE(ASSERT) - m_currentAttribute->mutableValueRange().end = 0; -#endif + m_currentAttribute->valueRange().checkValidStart(); } void endAttributeValue(int offset) { m_currentAttribute->mutableValueRange().end = offset - m_baseOffset; + m_currentAttribute->valueRange().checkValid(); } void appendToAttributeName(UChar character) { ASSERT(character); ASSERT(m_type == StartTag || m_type == EndTag); - ASSERT(m_currentAttribute->nameRange().start); + m_currentAttribute->nameRange().checkValidStart(); m_currentAttribute->appendToName(character); } @@ -360,7 +384,7 @@ { ASSERT(character); ASSERT(m_type == StartTag || m_type == EndTag); - ASSERT(m_currentAttribute->valueRange().start); + m_currentAttribute->valueRange().checkValidStart(); m_currentAttribute->appendToValue(character); }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTokenizerTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTokenizerTest.cpp new file mode 100644 index 0000000..1b98177a --- /dev/null +++ b/third_party/WebKit/Source/core/html/parser/HTMLTokenizerTest.cpp
@@ -0,0 +1,32 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/html/parser/HTMLTokenizer.h" + +#include "core/html/parser/HTMLParserOptions.h" +#include "core/html/parser/HTMLToken.h" +#include "testing/gtest/include/gtest/gtest.h" + +#include <memory> + +namespace blink { + +// This is a regression test for crbug.com/619141 +TEST(HTMLTokenizerTest, ZeroOffsetAttributeNameRange) +{ + HTMLParserOptions options; + std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::create(options); + HTMLToken token; + + SegmentedString input("<script "); + EXPECT_FALSE(tokenizer->nextToken(input, token)); + + EXPECT_EQ(HTMLToken::StartTag, token.type()); + + SegmentedString input2("type='javascript'"); + // Below should not fail ASSERT + EXPECT_FALSE(tokenizer->nextToken(input2, token)); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp index 2e22bf0..6949fe78 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -86,6 +86,16 @@ return nullptr; } +ScriptPromise ImageBitmapFactories::createImageBitmapFromBlob(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmapSource* bitmapSource, const IntRect& cropRect, const ImageBitmapOptions& options) +{ + Blob* blob = static_cast<Blob*>(bitmapSource); + ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), cropRect, options, scriptState); + ScriptPromise promise = loader->promise(); + from(eventTarget).addLoader(loader); + loader->loadBlobAsync(eventTarget.getExecutionContext(), blob); + return promise; +} + ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, const ImageBitmapSourceUnion& bitmapSource, const ImageBitmapOptions& options, ExceptionState& exceptionState) { UseCounter::Feature feature = UseCounter::CreateImageBitmap; @@ -93,14 +103,8 @@ ImageBitmapSource* bitmapSourceInternal = toImageBitmapSourceInternal(bitmapSource, exceptionState, false); if (!bitmapSourceInternal) return ScriptPromise(); - if (bitmapSourceInternal->isBlob()) { - Blob* blob = static_cast<Blob*>(bitmapSourceInternal); - ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), IntRect(), options, scriptState); - ScriptPromise promise = loader->promise(); - from(eventTarget).addLoader(loader); - loader->loadBlobAsync(eventTarget.getExecutionContext(), blob); - return promise; - } + if (bitmapSourceInternal->isBlob()) + return createImageBitmapFromBlob(scriptState, eventTarget, bitmapSourceInternal, IntRect(), options); IntSize srcSize = bitmapSourceInternal->bitmapSourceSize(); return createImageBitmap(scriptState, eventTarget, bitmapSourceInternal, 0, 0, srcSize.width(), srcSize.height(), options, exceptionState); } @@ -122,12 +126,7 @@ exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); return ScriptPromise(); } - Blob* blob = static_cast<Blob*>(bitmapSource); - ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), IntRect(sx, sy, sw, sh), options, scriptState); - ScriptPromise promise = loader->promise(); - from(eventTarget).addLoader(loader); - loader->loadBlobAsync(eventTarget.getExecutionContext(), blob); - return promise; + return createImageBitmapFromBlob(scriptState, eventTarget, bitmapSource, IntRect(sx, sy, sw, sh), options); } return bitmapSource->createImageBitmap(scriptState, eventTarget, sx, sy, sw, sh, options, exceptionState);
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h index 80df930..d17c2cc 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
@@ -62,6 +62,7 @@ static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, const ImageBitmapSourceUnion&, const ImageBitmapOptions&, ExceptionState&); static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, const ImageBitmapSourceUnion&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&); static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageBitmapSource*, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&); + static ScriptPromise createImageBitmapFromBlob(ScriptState*, EventTarget&, ImageBitmapSource*, const IntRect&, const ImageBitmapOptions&); virtual ~ImageBitmapFactories() { }
diff --git a/third_party/WebKit/Source/core/input/InputDeviceCapabilities.idl b/third_party/WebKit/Source/core/input/InputDeviceCapabilities.idl index 0b73ea7b..98ef633 100644 --- a/third_party/WebKit/Source/core/input/InputDeviceCapabilities.idl +++ b/third_party/WebKit/Source/core/input/InputDeviceCapabilities.idl
@@ -11,7 +11,6 @@ [ Constructor(optional InputDeviceCapabilitiesInit deviceInitDict), - RuntimeEnabled=InputDeviceCapabilities, ] interface InputDeviceCapabilities { // Whether this device dispatches touch events for movement. This is used to detect
diff --git a/third_party/WebKit/Source/core/input/InputDeviceCapabilitiesInit.idl b/third_party/WebKit/Source/core/input/InputDeviceCapabilitiesInit.idl index e7ae86d..6dc6147 100644 --- a/third_party/WebKit/Source/core/input/InputDeviceCapabilitiesInit.idl +++ b/third_party/WebKit/Source/core/input/InputDeviceCapabilitiesInit.idl
@@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -[ - RuntimeEnabled=InputDeviceCapabilities, -] dictionary InputDeviceCapabilitiesInit { +dictionary InputDeviceCapabilitiesInit { boolean firesTouchEvents = false; };
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp index 75f9c12..dabdbe5 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -141,9 +141,9 @@ return v8::MaybeLocal<v8::Function>(); if (!data->Set(context, v8String(isolate, "useCapture"), v8Boolean(useCapture, isolate)).FromMaybe(false)) return v8::MaybeLocal<v8::Function>(); - v8::Local<v8::Function> removeFunction = v8::Function::New(isolate, removeEventListenerCallback, data); + v8::Local<v8::Function> removeFunction = v8::Function::New(context, removeEventListenerCallback, data, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(); v8::Local<v8::Function> toStringFunction; - if (v8::Function::New(context, returnDataCallback, v8String(isolate, "function remove() { [Command Line API] }")).ToLocal(&toStringFunction)) + if (v8::Function::New(context, returnDataCallback, v8String(isolate, "function remove() { [Command Line API] }"), 0, v8::ConstructorBehavior::kThrow).ToLocal(&toStringFunction)) removeFunction->Set(v8String(context->GetIsolate(), "toString"), toStringFunction); return removeFunction; }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorHighlight.cpp b/third_party/WebKit/Source/core/inspector/InspectorHighlight.cpp index 2cf7381..b69bf787 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorHighlight.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorHighlight.cpp
@@ -12,6 +12,7 @@ #include "core/layout/LayoutObject.h" #include "core/layout/shapes/ShapeOutsideInfo.h" #include "core/style/ComputedStyleConstants.h" +#include "platform/HostWindow.h" #include "platform/graphics/Path.h" namespace blink { @@ -27,9 +28,11 @@ std::unique_ptr<protocol::ListValue> release() { return std::move(m_path); } - void appendPath(const Path& path) + void appendPath(const Path& path, float scale) { - path.apply(this, &PathBuilder::appendPathElement); + Path transformPath(path); + transformPath.transform(AffineTransform().scale(scale)); + transformPath.apply(this, &PathBuilder::appendPathElement); } protected: @@ -90,10 +93,10 @@ , m_layoutObject(layoutObject) , m_shapeOutsideInfo(shapeOutsideInfo) { } - static std::unique_ptr<protocol::ListValue> buildPath(FrameView& view, LayoutObject& layoutObject, const ShapeOutsideInfo& shapeOutsideInfo, const Path& path) + static std::unique_ptr<protocol::ListValue> buildPath(FrameView& view, LayoutObject& layoutObject, const ShapeOutsideInfo& shapeOutsideInfo, const Path& path, float scale) { ShapePathBuilder builder(view, layoutObject, shapeOutsideInfo); - builder.appendPath(path); + builder.appendPath(path, scale); return builder.release(); } @@ -213,11 +216,12 @@ } // namespace -InspectorHighlight::InspectorHighlight() +InspectorHighlight::InspectorHighlight(float scale) : m_highlightPaths(protocol::ListValue::create()) , m_showRulers(false) , m_showExtensionLines(false) , m_displayAsMaterial(false) + , m_scale(scale) { } @@ -234,7 +238,11 @@ , m_showRulers(highlightConfig.showRulers) , m_showExtensionLines(highlightConfig.showExtensionLines) , m_displayAsMaterial(highlightConfig.displayAsMaterial) + , m_scale(1.f) { + FrameView* frameView = node->document().view(); + if (frameView) + m_scale = 1.f / frameView->getHostWindow()->windowToViewportScalar(1.f); appendPathsForShapeOutside(node, highlightConfig); appendNodeHighlight(node, highlightConfig); if (appendElementInfo && node->isElementNode()) @@ -249,7 +257,7 @@ { Path path = quadToPath(quad); PathBuilder builder; - builder.appendPath(path); + builder.appendPath(path, m_scale); appendPath(builder.release(), fillColor, outlineColor, name); } @@ -288,9 +296,9 @@ return; } - appendPath(ShapePathBuilder::buildPath(*node->document().view(), *node->layoutObject(), *shapeOutsideInfo, paths.shape), config.shape, Color::transparent); + appendPath(ShapePathBuilder::buildPath(*node->document().view(), *node->layoutObject(), *shapeOutsideInfo, paths.shape, m_scale), config.shape, Color::transparent); if (paths.marginShape.length()) - appendPath(ShapePathBuilder::buildPath(*node->document().view(), *node->layoutObject(), *shapeOutsideInfo, paths.marginShape), config.shapeMargin, Color::transparent); + appendPath(ShapePathBuilder::buildPath(*node->document().view(), *node->layoutObject(), *shapeOutsideInfo, paths.marginShape, m_scale), config.shapeMargin, Color::transparent); } void InspectorHighlight::appendNodeHighlight(Node* node, const InspectorHighlightConfig& highlightConfig) @@ -362,8 +370,8 @@ if (const ShapeOutsideInfo* shapeOutsideInfo = shapeOutsideInfoForNode(node, &paths, &boundsQuad)) { (*model)->setShapeOutside(protocol::DOM::ShapeOutsideInfo::create() .setBounds(buildArrayForQuad(boundsQuad)) - .setShape(protocol::Array<protocol::Value>::parse(ShapePathBuilder::buildPath(*view, *layoutObject, *shapeOutsideInfo, paths.shape).get(), &errors)) - .setMarginShape(protocol::Array<protocol::Value>::parse(ShapePathBuilder::buildPath(*view, *layoutObject, *shapeOutsideInfo, paths.marginShape).get(), &errors)) + .setShape(protocol::Array<protocol::Value>::parse(ShapePathBuilder::buildPath(*view, *layoutObject, *shapeOutsideInfo, paths.shape, 1.f).get(), &errors)) + .setMarginShape(protocol::Array<protocol::Value>::parse(ShapePathBuilder::buildPath(*view, *layoutObject, *shapeOutsideInfo, paths.marginShape, 1.f).get(), &errors)) .build()); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorHighlight.h b/third_party/WebKit/Source/core/inspector/InspectorHighlight.h index d8e1ef86..632d766 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorHighlight.h +++ b/third_party/WebKit/Source/core/inspector/InspectorHighlight.h
@@ -46,7 +46,7 @@ STACK_ALLOCATED(); public: InspectorHighlight(Node*, const InspectorHighlightConfig&, bool appendElementInfo); - InspectorHighlight(); + explicit InspectorHighlight(float scale); ~InspectorHighlight(); static bool getBoxModel(Node*, std::unique_ptr<protocol::DOM::BoxModel>*); @@ -67,6 +67,7 @@ bool m_showRulers; bool m_showExtensionLines; bool m_displayAsMaterial; + float m_scale; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp index f76be3e..80e3085 100644 --- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp +++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
@@ -173,12 +173,12 @@ { v8::Local<v8::String> funcName = v8String(context->GetIsolate(), name); v8::Local<v8::Function> func; - if (!v8::Function::New(context, callback, v8::External::New(context->GetIsolate(), this)).ToLocal(&func)) + if (!v8::Function::New(context, callback, v8::External::New(context->GetIsolate(), this), 0, v8::ConstructorBehavior::kThrow).ToLocal(&func)) return; func->SetName(funcName); v8::Local<v8::String> returnValue = v8String(context->GetIsolate(), description); v8::Local<v8::Function> toStringFunction; - if (v8::Function::New(context, returnDataCallback, returnValue).ToLocal(&toStringFunction)) + if (v8::Function::New(context, returnDataCallback, returnValue, 0, v8::ConstructorBehavior::kThrow).ToLocal(&toStringFunction)) func->Set(v8String(context->GetIsolate(), "toString"), toStringFunction); if (!object->Set(context, funcName, func).FromMaybe(false)) return; @@ -241,7 +241,7 @@ v8::Local<v8::Function> ThreadDebugger::eventLogFunction() { if (m_eventLogFunction.IsEmpty()) - m_eventLogFunction.Reset(m_isolate, v8::Function::New(m_isolate, logCallback, v8::External::New(m_isolate, this))); + m_eventLogFunction.Reset(m_isolate, v8::Function::New(m_isolate->GetCurrentContext(), logCallback, v8::External::New(m_isolate, this), 0, v8::ConstructorBehavior::kThrow).ToLocalChecked()); return m_eventLogFunction.Get(m_isolate); }
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 20bc399..eb201e2 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4188,6 +4188,10 @@ "hidden": true, "types": [ { + "id": "BrowserContextID", + "type": "string" + }, + { "id": "TargetID", "type": "string" }, @@ -4204,6 +4208,50 @@ ], "commands": [ { + "name": "createBrowserContext", + "description": "Creates a new empty BrowserContext. Similar to an incognito profile but you can have more than one.", + "returns": [ + { "name": "browserContextId", "$ref": "BrowserContextID", "description": "The id of the context created." } + ], + "handlers": ["browser"] + }, + { + "name": "disposeBrowserContext", + "description": "Deletes a BrowserContext, will fail of any open page uses it.", + "parameters": [ + { "name": "browserContextId", "$ref": "BrowserContextID" } + ], + "returns": [ + { "name": "success", "type": "boolean" } + ], + "handlers": ["browser"] + }, + { + "name": "createTarget", + "description": "Creates a new page.", + "parameters": [ + { "name": "initialUrl", "type": "string", "description": "The initial URL the page will be navigated to." }, + { "name": "width", "type": "integer", "description": "Window width (headless chrome only).", "optional": true }, + { "name": "height", "type": "integer", "description": "Window height (headless chrome only).", "optional": true }, + { "name": "browserContextId", "$ref": "BrowserContextID", "description": "The browser context to create the page in (headless chrome only).", "optional": true } + ], + "returns": [ + { "name": "targetId", "$ref": "TargetID", "description": "The id of the page opened." } + ], + "handlers": ["browser"] + }, + { + "name": "closeTarget", + "description": "Closes the target. If the target is a page that gets closed too.", + "parameters": [ + { "name": "targetId", "$ref": "TargetID" } + ], + "returns": [ + { "name": "success", "type": "boolean" } + ], + "handlers": ["browser"] + }, + { "name": "getTargets", "returns": [ { "name": "targetInfo", "type": "array", "items": { "$ref": "TargetInfo" } } @@ -4248,5 +4296,83 @@ "handlers": ["browser"] } ] + }, + { + "domain": "SystemInfo", + "description": "The SystemInfo domain defines methods and events for querying low-level system information.", + "hidden": true, + "types": [ + { + "id": "GPUDevice", + "type": "object", + "properties": [ + { "name": "vendorId", "type": "number", "description": "PCI ID of the GPU vendor, if available; 0 otherwise." }, + { "name": "deviceId", "type": "number", "description": "PCI ID of the GPU device, if available; 0 otherwise." }, + { "name": "vendorString", "type": "string", "description": "String description of the GPU vendor, if the PCI ID is not available." }, + { "name": "deviceString", "type": "string", "description": "String description of the GPU device, if the PCI ID is not available." } + ], + "description": "Describes a single graphics processor (GPU)." + }, + { + "id": "GPUInfo", + "type": "object", + "properties": [ + { "name": "devices", "type": "array", "items": { "$ref": "GPUDevice" }, "description": "The graphics devices on the system. Element 0 is the primary GPU." }, + { "name": "auxAttributes", "type": "object", "optional": "true", "description": "An optional dictionary of additional GPU related attributes." }, + { "name": "featureStatus", "type": "object", "optional": "true", "description": "An optional dictionary of graphics features and their status." }, + { "name": "driverBugWorkarounds", "type": "array", "items": { "type": "string" }, "description": "An optional array of GPU driver bug workarounds." } + ], + "description": "Provides information about the GPU(s) on the system." + } + ], + "commands": [ + { + "name": "getInfo", + "async": true, + "description": "Returns information about the system.", + "returns": [ + { "name": "gpu", "$ref": "GPUInfo", "description": "Information about the GPUs on the system." }, + { "name": "modelName", "type": "string", "description": "A platform-dependent description of the model of the machine. On Mac OS, this is, for example, 'MacBookPro'. Will be the empty string if not supported." }, + { "name": "modelVersion", "type": "string", "description": "A platform-dependent description of the version of the machine. On Mac OS, this is, for example, '10.1'. Will be the empty string if not supported." } + ], + "handlers": ["browser"] + } + ] + }, + { + "domain": "Tethering", + "description": "The Tethering domain defines methods and events for browser port binding.", + "hidden": true, + "commands": [ + { + "name": "bind", + "async": true, + "description": "Request browser port binding.", + "parameters": [ + { "name": "port", "type": "integer", "description": "Port number to bind." } + ], + "handlers": ["browser"] + }, + { + "name": "unbind", + "async": true, + "description": "Request browser port unbinding.", + "parameters": [ + { "name": "port", "type": "integer", "description": "Port number to unbind." } + ], + "handlers": ["browser"] + } + ], + "events": [ + { + "name": "accepted", + "description": "Informs that port was successfully bound and got a specified connection id.", + "parameters": [ + {"name": "port", "type": "integer", "description": "Port number that was successfully bound." }, + {"name": "connectionId", "type": "string", "description": "Connection id to be used." } + ], + "handlers": ["browser"] + } + ] }] }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp index 0db1696e..3f70ca65 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -635,7 +635,7 @@ LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); LayoutRect containerContentRect = containingBlock->layoutOverflowRect(); - LayoutUnit maxContainerWidth = containingBlock->containingBlockLogicalWidthForContent(); + LayoutUnit maxContainerWidth = containingBlock->isLayoutView() ? containingBlock->logicalWidth() : containingBlock->containingBlockLogicalWidthForContent(); // Sticky positioned element ignore any override logical width on the containing block (as they don't call // containingBlockLogicalWidthForContent). It's unclear whether this is totally fine. // Compute the container-relative area within which the sticky element is allowed to move.
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp index 840cd19..7bdedffe 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -863,8 +863,6 @@ PaintLayerScrollableArea::PreventRelayoutScope preventRelayoutScope(layoutScope); - dirtyForLayoutFromPercentageHeightDescendants(layoutScope); - m_orderIterator.first(); LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore(); while (computeNextFlexLine(orderedChildren, sumFlexBaseSize, totalFlexGrow, totalFlexShrink, totalWeightedFlexShrink, sumHypotheticalMainSize, relayoutChildren)) { @@ -1606,8 +1604,8 @@ resetAutoMarginsAndLogicalTopInCrossAxis(*child); } // We may have already forced relayout for orthogonal flowing children in computeInnerFlexBaseSizeForChild. - bool forceChildRelayout = relayoutChildren && !childFlexBaseSizeRequiresLayout(*child); - if (child->isLayoutBlock() && toLayoutBlock(*child).hasPercentHeightDescendants() && m_relaidOutChildren.contains(child)) { + bool forceChildRelayout = relayoutChildren && !m_relaidOutChildren.contains(child); + if (child->isLayoutBlock() && toLayoutBlock(*child).hasPercentHeightDescendants()) { // Have to force another relayout even though the child is sized correctly, because // its descendants are not sized correctly yet. Our previous layout of the child was // done without an override height set. So, redo it here.
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp index a5e44c0a..b0e9753 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
@@ -178,19 +178,14 @@ void LayoutMenuList::updateFromElement() { - setTextFromOption(selectElement()->optionIndexToBeShown()); -} - -void LayoutMenuList::setTextFromOption(int optionIndex) -{ HTMLSelectElement* select = selectElement(); - const HeapVector<Member<HTMLElement>>& listItems = select->listItems(); - const int size = listItems.size(); - + HTMLOptionElement* option = select->optionToBeShown(); String text = emptyString(); m_optionStyle.clear(); - if (selectElement()->multiple()) { + if (select->multiple()) { + const HeapVector<Member<HTMLElement>>& listItems = select->listItems(); + const int size = listItems.size(); unsigned selectedCount = 0; int firstSelectedIndex = -1; for (int i = 0; i < size; ++i) { @@ -218,19 +213,15 @@ ASSERT(!m_optionStyle); } } else { - const int i = select->optionToListIndex(optionIndex); - if (i >= 0 && i < size) { - Element* element = listItems[i]; - if (isHTMLOptionElement(*element)) { - text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel(); - m_optionStyle = element->mutableComputedStyle(); - } + if (option) { + text = option->textIndentedToRespectGroupLabel(); + m_optionStyle = option->mutableComputedStyle(); } } setText(text.stripWhiteSpace()); - didUpdateActiveOption(optionIndex); + didUpdateActiveOption(option); } void LayoutMenuList::setText(const String& s) @@ -289,23 +280,22 @@ LayoutBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues); } -void LayoutMenuList::didSetSelectedIndex(int optionIndex) +void LayoutMenuList::didSelectOption(HTMLOptionElement* option) { - didUpdateActiveOption(optionIndex); + didUpdateActiveOption(option); } -void LayoutMenuList::didUpdateActiveOption(int optionIndex) +void LayoutMenuList::didUpdateActiveOption(HTMLOptionElement* option) { if (!document().existingAXObjectCache()) return; + int optionIndex = option ? option->index() : -1; if (m_lastActiveIndex == optionIndex) return; m_lastActiveIndex = optionIndex; - HTMLSelectElement* select = selectElement(); - int listIndex = select->optionToListIndex(optionIndex); - if (listIndex < 0 || listIndex >= static_cast<int>(select->listItems().size())) + if (optionIndex < 0) return; // We skip sending accessiblity notifications for the very first option, otherwise
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.h b/third_party/WebKit/Source/core/layout/LayoutMenuList.h index fa96089f..743f94c1 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMenuList.h +++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.h
@@ -39,7 +39,7 @@ ~LayoutMenuList() override; HTMLSelectElement* selectElement() const; - void didSetSelectedIndex(int optionIndex); + void didSelectOption(HTMLOptionElement*); String text() const; const char* name() const override { return "LayoutMenuList"; } @@ -79,13 +79,12 @@ void createInnerBlock(); void adjustInnerStyle(); void setText(const String&); - void setTextFromOption(int optionIndex); void updateInnerBlockHeight(); void updateOptionsWidth() const; float computeTextWidth(const TextRun&, const ComputedStyle&) const; void setIndexToSelectOnCancel(int listIndex); - void didUpdateActiveOption(int optionIndex); + void didUpdateActiveOption(HTMLOptionElement*); LayoutText* m_buttonText; LayoutBlock* m_innerBlock;
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index 5255bb3..4dc1e45 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -2374,7 +2374,7 @@ // Paint the whole layer if "mainFrameClipsContent" is false, meaning that WebPreferences::record_whole_document is true. bool shouldPaintWholePage = !m_owningLayer.layoutObject()->document().settings()->mainFrameClipsContent(); if (shouldPaintWholePage - || (graphicsLayer != m_graphicsLayer.get() && graphicsLayer != m_squashingLayer.get() && graphicsLayer != m_squashingLayer.get() && graphicsLayer != m_scrollingContentsLayer.get())) + || (graphicsLayer != m_graphicsLayer.get() && graphicsLayer != m_squashingLayer.get() && graphicsLayer != m_scrollingContentsLayer.get())) return wholeLayerRect; IntRect newInterestRect = recomputeInterestRect(graphicsLayer);
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp index c2aa8c5..3c1b8d9e 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilterPrimitive.cpp
@@ -50,6 +50,8 @@ if (newStyle.lightingColor() != oldStyle->svgStyle().lightingColor()) toLayoutSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr); } + if (newStyle.colorInterpolationFilters() != oldStyle->svgStyle().colorInterpolationFilters()) + toLayoutSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::color_interpolation_filtersAttr); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 7672e99..d73172a9 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -321,7 +321,7 @@ TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceSendRequest", TRACE_EVENT_SCOPE_THREAD, "data", InspectorSendRequestEvent::data(identifier, frame(), request)); InspectorInstrumentation::willSendRequest(frame(), identifier, masterDocumentLoader(), request, redirectResponse, initiatorInfo); if (frame()->frameScheduler()) - frame()->frameScheduler()->incrementPendingResourceLoadCount(); + frame()->frameScheduler()->didStartLoading(identifier); } void FrameFetchContext::dispatchDidReceiveResponse(unsigned long identifier, const ResourceResponse& response, WebURLRequest::FrameType frameType, WebURLRequest::RequestContext requestContext, Resource* resource) @@ -372,7 +372,7 @@ TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceFinish", TRACE_EVENT_SCOPE_THREAD, "data", InspectorResourceFinishEvent::data(identifier, finishTime, false)); InspectorInstrumentation::didFinishLoading(frame(), identifier, finishTime, encodedDataLength); if (frame()->frameScheduler()) - frame()->frameScheduler()->decrementPendingResourceLoadCount(); + frame()->frameScheduler()->didStopLoading(identifier); } void FrameFetchContext::dispatchDidFail(unsigned long identifier, const ResourceError& error, bool isInternalRequest) @@ -385,7 +385,7 @@ if (!isInternalRequest) frame()->console().didFailLoading(identifier, error); if (frame()->frameScheduler()) - frame()->frameScheduler()->decrementPendingResourceLoadCount(); + frame()->frameScheduler()->didStopLoading(identifier); } void FrameFetchContext::dispatchDidLoadResourceFromMemoryCache(unsigned long identifier, Resource* resource, WebURLRequest::FrameType frameType, WebURLRequest::RequestContext requestContext)
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 026c90b..71242fc 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -860,7 +860,7 @@ static NavigationType determineNavigationType(FrameLoadType frameLoadType, bool isFormSubmission, bool haveEvent) { - bool isReload = frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadBypassingCache; + bool isReload = frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadMainResource || frameLoadType == FrameLoadTypeReloadBypassingCache; bool isBackForward = isBackForwardLoadType(frameLoadType); if (isFormSubmission) return (isReload || isBackForward) ? NavigationTypeFormResubmitted : NavigationTypeFormSubmitted;
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp index 1ee913c9..3056a2a4 100644 --- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp +++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -396,7 +396,6 @@ timing.initialize(); WebURLResponse response; - response.initialize(); response.setURL(url); response.setHTTPStatusCode(301); response.setLoadTiming(timing); @@ -414,7 +413,6 @@ timing.initialize(); WebURLResponse response; - response.initialize(); response.setURL(url); response.setHTTPStatusCode(301); response.setLoadTiming(timing);
diff --git a/third_party/WebKit/Source/core/page/scrolling/ChildViewportScrollCallback.cpp b/third_party/WebKit/Source/core/page/scrolling/ChildViewportScrollCallback.cpp new file mode 100644 index 0000000..3ac8d9f1 --- /dev/null +++ b/third_party/WebKit/Source/core/page/scrolling/ChildViewportScrollCallback.cpp
@@ -0,0 +1,44 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/page/scrolling/ChildViewportScrollCallback.h" + +#include "core/page/scrolling/ScrollState.h" +#include "platform/geometry/FloatSize.h" +#include "platform/scroll/ScrollTypes.h" +#include "platform/scroll/ScrollableArea.h" + +namespace blink { + +ChildViewportScrollCallback::ChildViewportScrollCallback() +{ +} + +ChildViewportScrollCallback::~ChildViewportScrollCallback() +{ +} + +DEFINE_TRACE(ChildViewportScrollCallback) +{ + visitor->trace(m_scroller); + ViewportScrollCallback::trace(visitor); +} + + +void ChildViewportScrollCallback::handleEvent(ScrollState* state) +{ + DCHECK(state); + + if (!m_scroller) + return; + + performNativeScroll(*state, *m_scroller); +} + +void ChildViewportScrollCallback::setScroller(ScrollableArea* scroller) +{ + m_scroller = scroller; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/page/scrolling/ChildViewportScrollCallback.h b/third_party/WebKit/Source/core/page/scrolling/ChildViewportScrollCallback.h new file mode 100644 index 0000000..bab9d870 --- /dev/null +++ b/third_party/WebKit/Source/core/page/scrolling/ChildViewportScrollCallback.h
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ChildViewportScrollCallback_h +#define ChildViewportScrollCallback_h + +#include "core/page/scrolling/ViewportScrollCallback.h" +#include "platform/heap/Handle.h" + +namespace blink { + +class ScrollableArea; +class ScrollState; + +// The ViewportScrollCallback used by non-root Frames, i.e. iframes. This is +// essentially a no-op implementation that simply scrolls the frame since +// iframes don't have any additional scrolling actions, unlike the root frame +// which moves the top controls and provides overscroll glow. +class ChildViewportScrollCallback : public ViewportScrollCallback { +public: + static ChildViewportScrollCallback* create() + { + return new ChildViewportScrollCallback(); + } + + virtual ~ChildViewportScrollCallback(); + + void handleEvent(ScrollState*) override; + void setScroller(ScrollableArea*) override; + + DECLARE_VIRTUAL_TRACE(); + +private: + ChildViewportScrollCallback(); + + WeakMember<ScrollableArea> m_scroller; +}; + +} // namespace blink + +#endif // ChildViewportScrollCallback_h
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp index 3822b25..9bac01d 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
@@ -27,8 +27,12 @@ LayoutBox* box = toLayoutBox(element.layoutObject()); + // For a FrameView, we use the layoutViewport rather than the + // getScrollableArea() since that could be the RootFrameViewport. The + // rootScroller's ScrollableArea will be swapped in as the layout viewport + // in RootFrameViewport so we need to ensure we get the layout viewport. if (box->isDocumentElement()) - return element.document().view()->getScrollableArea(); + return element.document().view()->layoutViewportScrollableArea(); return static_cast<PaintInvalidationCapableScrollableArea*>( box->getScrollableArea()); @@ -73,15 +77,8 @@ } // namespace -ViewportScrollCallback* RootScrollerController::createViewportApplyScroll( - TopControls* topControls, OverscrollController* overscrollController) -{ - return new ViewportScrollCallback(topControls, overscrollController); -} - -RootScrollerController::RootScrollerController(Document& document, ViewportScrollCallback* applyScrollCallback) +RootScrollerController::RootScrollerController(Document& document) : m_document(&document) - , m_viewportApplyScroll(applyScrollCallback) { } @@ -114,6 +111,12 @@ updateEffectiveRootScroller(); } +void RootScrollerController::setViewportScrollCallback(ViewportScrollCallback* callback) +{ + m_viewportApplyScroll = callback; + moveViewportApplyScroll(m_effectiveRootScroller); +} + void RootScrollerController::updateEffectiveRootScroller() { bool rootScrollerValid = @@ -126,34 +129,35 @@ if (m_effectiveRootScroller == newEffectiveRootScroller) return; - moveViewportApplyScroll(newEffectiveRootScroller); - m_effectiveRootScroller = newEffectiveRootScroller; + if (moveViewportApplyScroll(newEffectiveRootScroller)) + m_effectiveRootScroller = newEffectiveRootScroller; } -void RootScrollerController::moveViewportApplyScroll(Element* target) +bool RootScrollerController::moveViewportApplyScroll(Element* target) { - if (!m_viewportApplyScroll) - return; + if (!m_viewportApplyScroll || !target) + return false; + + ScrollableArea* targetScroller = scrollableAreaFor(*target); + if (!targetScroller) + return false; if (m_effectiveRootScroller) m_effectiveRootScroller->removeApplyScroll(); - ScrollableArea* targetScroller = - target ? scrollableAreaFor(*target) : nullptr; - - if (targetScroller) { - // Use disable-native-scroll since the ViewportScrollCallback needs to - // apply scroll actions both before (TopControls) and after (overscroll) - // scrolling the element so it will apply scroll to the element itself. - target->setApplyScroll( - m_viewportApplyScroll, - "disable-native-scroll"); - } + // Use disable-native-scroll since the ViewportScrollCallback needs to + // apply scroll actions both before (TopControls) and after (overscroll) + // scrolling the element so it will apply scroll to the element itself. + target->setApplyScroll(m_viewportApplyScroll, "disable-native-scroll"); // Ideally, scroll customization would pass the current element to scroll to // the apply scroll callback but this doesn't happen today so we set it - // through a back door here. + // through a back door here. This is also needed by the + // RootViewportScrollCallback to swap the target into the layout viewport + // in RootFrameViewport. m_viewportApplyScroll->setScroller(targetScroller); + + return true; } Element* RootScrollerController::defaultEffectiveRootScroller()
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h index b42428a..dd497226 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
@@ -12,8 +12,6 @@ class Document; class Element; -class OverscrollController; -class TopControls; class ViewportScrollCallback; // Manages the root scroller associated with a given document. The root scroller @@ -38,24 +36,15 @@ class CORE_EXPORT RootScrollerController : public GarbageCollected<RootScrollerController> { public: - // Creates a RootScrollerController for the given document. An optional - // ViewportScrollCallback can be provided. If it is, RootScrollerController - // will ensure that the effectiveRootScroller element always has this set as - // the apply scroll callback. - static RootScrollerController* create( - Document& document, - ViewportScrollCallback* applyScrollCallback) + // Creates a RootScrollerController for the given document. You should use + // setViewportScrollCallback to provide this class with a scroll callback + // that RootScrollerController will keep applied to the current RootScroller + // so that special actions can occur on scrolling. + static RootScrollerController* create(Document& document) { - return new RootScrollerController(document, applyScrollCallback); + return new RootScrollerController(document); } - // Creates an apply scroll callback that handles viewport actions like - // TopControls movement and Overscroll. The TopControls and - // OverscrollController are given to the ViewportScrollCallback but are not - // owned or kept alive by it. - static ViewportScrollCallback* createViewportApplyScroll( - TopControls*, OverscrollController*); - DECLARE_TRACE(); // Sets the element that will be used as the root scroller. This can be @@ -89,20 +78,30 @@ return m_viewportApplyScroll; } + void setViewportScrollCallback(ViewportScrollCallback*); + private: - RootScrollerController(Document&, ViewportScrollCallback*); + RootScrollerController(Document&); Element* defaultEffectiveRootScroller(); // Ensures the effective root scroller is currently valid and replaces it // with the default if not. void updateEffectiveRootScroller(); - void moveViewportApplyScroll(Element* target); + + // Returns true if the move was successful. + bool moveViewportApplyScroll(Element* target); WeakMember<Document> m_document; Member<ViewportScrollCallback> m_viewportApplyScroll; WeakMember<Element> m_rootScroller; + + // The element currently being used as the root scroller. If + // m_viewportApplyScroll has been set, this element is guaranteed to have it + // set as its applyScroll callback. This can be nullptr during + // initialization and will not be set until m_viewportApplyScroll is + // provided. WeakMember<Element> m_effectiveRootScroller; };
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootViewportScrollCallback.cpp b/third_party/WebKit/Source/core/page/scrolling/RootViewportScrollCallback.cpp new file mode 100644 index 0000000..d1a5206f --- /dev/null +++ b/third_party/WebKit/Source/core/page/scrolling/RootViewportScrollCallback.cpp
@@ -0,0 +1,108 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/page/scrolling/RootViewportScrollCallback.h" + +#include "core/frame/FrameHost.h" +#include "core/frame/FrameView.h" +#include "core/frame/RootFrameViewport.h" +#include "core/frame/Settings.h" +#include "core/frame/TopControls.h" +#include "core/page/scrolling/OverscrollController.h" +#include "core/page/scrolling/ScrollState.h" +#include "platform/geometry/FloatSize.h" +#include "platform/scroll/ScrollableArea.h" + +namespace blink { + +RootViewportScrollCallback::RootViewportScrollCallback( + TopControls* topControls, + OverscrollController* overscrollController, + RootFrameViewport& rootFrameViewport) + : m_topControls(topControls) + , m_overscrollController(overscrollController) + , m_rootFrameViewport(&rootFrameViewport) +{ +} + +RootViewportScrollCallback::~RootViewportScrollCallback() +{ +} + +DEFINE_TRACE(RootViewportScrollCallback) +{ + visitor->trace(m_topControls); + visitor->trace(m_overscrollController); + visitor->trace(m_rootFrameViewport); + ViewportScrollCallback::trace(visitor); +} + +bool RootViewportScrollCallback::shouldScrollTopControls(const FloatSize& delta, + ScrollGranularity granularity) const +{ + if (granularity != ScrollByPixel && granularity != ScrollByPrecisePixel) + return false; + + if (!m_rootFrameViewport) + return false; + + DoublePoint maxScroll = m_rootFrameViewport->maximumScrollPositionDouble(); + DoublePoint scrollPosition = m_rootFrameViewport->scrollPositionDouble(); + + // Always give the delta to the top controls if the scroll is in + // the direction to show the top controls. If it's in the + // direction to hide the top controls, only give the delta to the + // top controls when the frame can scroll. + return delta.height() < 0 || scrollPosition.y() < maxScroll.y(); +} + +bool RootViewportScrollCallback::scrollTopControls(ScrollState& state) +{ + // Scroll top controls. + if (m_topControls) { + if (state.isBeginning()) + m_topControls->scrollBegin(); + + FloatSize delta(state.deltaX(), state.deltaY()); + ScrollGranularity granularity = + ScrollGranularity(static_cast<int>(state.deltaGranularity())); + if (shouldScrollTopControls(delta, granularity)) { + FloatSize remainingDelta = m_topControls->scrollBy(delta); + FloatSize consumed = delta - remainingDelta; + state.consumeDeltaNative(consumed.width(), consumed.height()); + return !consumed.isZero(); + } + } + + return false; +} + +void RootViewportScrollCallback::handleEvent(ScrollState* state) +{ + DCHECK(state); + if (!m_rootFrameViewport) + return; + + bool topControlsDidScroll = scrollTopControls(*state); + + ScrollResult result = performNativeScroll(*state, *m_rootFrameViewport); + + // We consider top controls movement to be scrolling. + result.didScrollY |= topControlsDidScroll; + + // Handle Overscroll. + if (m_overscrollController) { + FloatPoint position(state->positionX(), state->positionY()); + FloatSize velocity(state->velocityX(), state->velocityY()); + m_overscrollController->handleOverscroll(result, position, velocity); + } +} + +void RootViewportScrollCallback::setScroller(ScrollableArea* scroller) +{ + DCHECK(scroller); + m_rootFrameViewport->setLayoutViewport(*scroller); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootViewportScrollCallback.h b/third_party/WebKit/Source/core/page/scrolling/RootViewportScrollCallback.h new file mode 100644 index 0000000..a1a7ebb --- /dev/null +++ b/third_party/WebKit/Source/core/page/scrolling/RootViewportScrollCallback.h
@@ -0,0 +1,59 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RootViewportScrollCallback_h +#define RootViewportScrollCallback_h + +#include "core/page/scrolling/ViewportScrollCallback.h" +#include "platform/heap/Handle.h" +#include "platform/scroll/ScrollTypes.h" + +namespace blink { + +class FloatSize; +class ScrollableArea; +class ScrollState; +class TopControls; +class OverscrollController; +class RootFrameViewport; + +// The ViewportScrollCallback used by the one root frame on the page. This +// callback provides scrolling of the frame as well as associated actions like +// top controls movement and overscroll glow. +class RootViewportScrollCallback : public ViewportScrollCallback { +public: + // The TopControls and OverscrollController are given to the + // RootViewportScrollCallback but are not owned or kept alive by it. + static RootViewportScrollCallback* create( + TopControls* topControls, + OverscrollController* overscrollController, + RootFrameViewport& rootFrameViewport) + { + return new RootViewportScrollCallback( + topControls, overscrollController, rootFrameViewport); + } + + virtual ~RootViewportScrollCallback(); + + void handleEvent(ScrollState*) override; + void setScroller(ScrollableArea*) override; + + DECLARE_VIRTUAL_TRACE(); + +private: + // RootViewportScrollCallback does not assume ownership of TopControls or of + // OverscrollController. + RootViewportScrollCallback(TopControls*, OverscrollController*, RootFrameViewport&); + + bool shouldScrollTopControls(const FloatSize&, ScrollGranularity) const; + bool scrollTopControls(ScrollState&); + + WeakMember<TopControls> m_topControls; + WeakMember<OverscrollController> m_overscrollController; + WeakMember<RootFrameViewport> m_rootFrameViewport; +}; + +} // namespace blink + +#endif // RootViewportScrollCallback_h
diff --git a/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.cpp b/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.cpp index f8cc13a..0c0e1d83 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.cpp
@@ -4,101 +4,28 @@ #include "core/page/scrolling/ViewportScrollCallback.h" -#include "core/frame/FrameHost.h" -#include "core/frame/FrameView.h" -#include "core/frame/Settings.h" -#include "core/frame/TopControls.h" -#include "core/page/scrolling/OverscrollController.h" #include "core/page/scrolling/ScrollState.h" -#include "platform/geometry/FloatSize.h" #include "platform/scroll/ScrollableArea.h" namespace blink { -ViewportScrollCallback::ViewportScrollCallback( - TopControls* topControls, OverscrollController* overscrollController) - : m_topControls(topControls) - , m_overscrollController(overscrollController) +ScrollResult ViewportScrollCallback::performNativeScroll( + ScrollState& state, ScrollableArea& scroller) { -} - -ViewportScrollCallback::~ViewportScrollCallback() -{ -} - -DEFINE_TRACE(ViewportScrollCallback) -{ - visitor->trace(m_topControls); - visitor->trace(m_overscrollController); - visitor->trace(m_scroller); - ScrollStateCallback::trace(visitor); -} - -bool ViewportScrollCallback::shouldScrollTopControls(const FloatSize& delta, - ScrollGranularity granularity) const -{ - if (granularity != ScrollByPixel && granularity != ScrollByPrecisePixel) - return false; - - if (!m_scroller) - return false; - - DoublePoint maxScroll = m_scroller->maximumScrollPositionDouble(); - DoublePoint scrollPosition = m_scroller->scrollPositionDouble(); - - // Always give the delta to the top controls if the scroll is in - // the direction to show the top controls. If it's in the - // direction to hide the top controls, only give the delta to the - // top controls when the frame can scroll. - return delta.height() < 0 || scrollPosition.y() < maxScroll.y(); -} - -void ViewportScrollCallback::handleEvent(ScrollState* state) -{ - FloatSize delta(state->deltaX(), state->deltaY()); + FloatSize delta(state.deltaX(), state.deltaY()); ScrollGranularity granularity = - ScrollGranularity(static_cast<int>(state->deltaGranularity())); - FloatSize remainingDelta = delta; + ScrollGranularity(static_cast<int>(state.deltaGranularity())); - // Scroll top controls. - if (m_topControls) { - if (state->isBeginning()) - m_topControls->scrollBegin(); - - if (shouldScrollTopControls(delta, granularity)) - remainingDelta = m_topControls->scrollBy(delta); - } - - bool topControlsConsumedScroll = remainingDelta.height() != delta.height(); - - // Scroll the element's scrollable area. - if (!m_scroller) - return; - - ScrollResult result = m_scroller->userScroll(granularity, remainingDelta); - - // We consider top controls movement to be scrolling. - result.didScrollY |= topControlsConsumedScroll; - - // Handle Overscroll. - if (m_overscrollController) { - FloatPoint position(state->positionX(), state->positionY()); - FloatSize velocity(state->velocityX(), state->velocityY()); - m_overscrollController->handleOverscroll(result, position, velocity); - } + ScrollResult result = scroller.userScroll(granularity, delta); // The viewport consumes everything. // TODO(bokan): This isn't actually consuming everything but doing so breaks - // the main thread pull-to-refresh action. I need to figure out where that - // gets activated. crbug.com/607210. - state->consumeDeltaNative( - state->deltaX() - result.unusedScrollDeltaX, - state->deltaY() - result.unusedScrollDeltaY); -} + // the main thread pull-to-refresh action. crbug.com/607210. + state.consumeDeltaNative( + delta.width() - result.unusedScrollDeltaX, + delta.height() - result.unusedScrollDeltaY); -void ViewportScrollCallback::setScroller(ScrollableArea* scroller) -{ - m_scroller = scroller; + return result; } } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.h b/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.h index 6fa6d1a..a27c0d4 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.h +++ b/third_party/WebKit/Source/core/page/scrolling/ViewportScrollCallback.h
@@ -11,33 +11,34 @@ namespace blink { -class FloatSize; -class FrameHost; -class Element; class ScrollableArea; class ScrollState; -class TopControls; -class OverscrollController; +// ViewportScrollCallback is an interface that's used by the +// RootScrollerController to apply scrolls to the designated rootScroller +// element. It is a ScrollStateCallback, meaning that it's applied during the +// applyScroll step of ScrollCustomization and child classes must implement +// handleEvent in order to actually do the scrolling as well as any possible +// associated actions. +// +// ScrollCustomization generally relies on using the nativeApplyScroll to +// scroll the element; however, the rootScroller may need to execute actions +// both before and after the native scroll which is currently unsupported. +// Because of this, the ViewportScrollCallback can scroll the Element directly. +// This is accomplished by descendant classes implementing the setScroller +// method which RootScrollerController will call to fill the callback with the +// appropriate ScrollableArea to use. class ViewportScrollCallback : public ScrollStateCallback { public: - // ViewportScrollCallback does not assume ownership of TopControls or of - // OverscrollController. - ViewportScrollCallback(TopControls*, OverscrollController*); - ~ViewportScrollCallback(); + virtual ~ViewportScrollCallback() {} - void handleEvent(ScrollState*) override; + virtual void setScroller(ScrollableArea*) = 0; - void setScroller(ScrollableArea*); - - DECLARE_VIRTUAL_TRACE(); - -private: - bool shouldScrollTopControls(const FloatSize&, ScrollGranularity) const; - - WeakMember<TopControls> m_topControls; - WeakMember<OverscrollController> m_overscrollController; - WeakMember<ScrollableArea> m_scroller; + DEFINE_INLINE_VIRTUAL_TRACE() { + ScrollStateCallback::trace(visitor); + } +protected: + ScrollResult performNativeScroll(ScrollState&, ScrollableArea&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp index 16803f4..a2fc110 100644 --- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp +++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp
@@ -354,13 +354,14 @@ LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosition(), availableWidth); if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > LayoutUnit() && fillTileSize.width() > LayoutUnit()) { int nrTiles = std::max(1, roundToInt(positioningAreaSize.width() / fillTileSize.width())); - - fillTileSize.setWidth(positioningAreaSize.width() / nrTiles); + LayoutUnit roundedWidth = positioningAreaSize.width() / nrTiles; // Maintain aspect ratio if background-size: auto is set if (fillLayer.size().size.height().isAuto() && backgroundRepeatY != RoundFill) { - fillTileSize.setHeight(fillTileSize.height() * positioningAreaSize.width() / (nrTiles * fillTileSize.width())); + fillTileSize.setHeight(fillTileSize.height() * roundedWidth / fillTileSize.width()); } + fillTileSize.setWidth(roundedWidth); + setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect)); setPhaseX(tileSize().width() ? LayoutUnit(roundf(tileSize().width() - fmodf((computedXPosition + left), tileSize().width()))) @@ -371,13 +372,13 @@ LayoutUnit computedYPosition = roundedMinimumValueForLength(fillLayer.yPosition(), availableHeight); if (backgroundRepeatY == RoundFill && positioningAreaSize.height() > LayoutUnit() && fillTileSize.height() > LayoutUnit()) { int nrTiles = std::max(1, roundToInt(positioningAreaSize.height() / fillTileSize.height())); - - fillTileSize.setHeight(positioningAreaSize.height() / nrTiles); - + LayoutUnit roundedHeight = positioningAreaSize.height() / nrTiles; // Maintain aspect ratio if background-size: auto is set if (fillLayer.size().size.width().isAuto() && backgroundRepeatX != RoundFill) { - fillTileSize.setWidth(fillTileSize.width() * positioningAreaSize.height() / (nrTiles * fillTileSize.height())); + fillTileSize.setWidth(fillTileSize.width() * roundedHeight / fillTileSize.height()); } + fillTileSize.setHeight(roundedHeight); + setTileSize(applySubPixelHeuristicToImageSize(fillTileSize, m_destRect)); setPhaseY(tileSize().height() ? LayoutUnit(roundf(tileSize().height() - fmodf((computedYPosition + top), tileSize().height())))
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp index cab7bfb..f1a452f 100644 --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -39,7 +39,7 @@ return &gTextBlobCache->add(&inlineTextBox, nullptr).storedValue->value; } -static bool paintsMarkerHighlights(const LayoutObject& layoutObject) +bool InlineTextBoxPainter::paintsMarkerHighlights(const LayoutObject& layoutObject) { return layoutObject.node() && layoutObject.document().markers().hasMarkers(layoutObject.node()); }
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h index 15a43e2..b468693d 100644 --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.h
@@ -22,6 +22,7 @@ class Font; class GraphicsContext; class InlineTextBox; +class LayoutObject; class LayoutPoint; class LayoutTextCombine; @@ -39,6 +40,7 @@ void paintTextMatchMarkerBackground(const PaintInfo&, const LayoutPoint& boxOrigin, DocumentMarker*, const ComputedStyle&, const Font&); static void removeFromTextBlobCache(const InlineTextBox&); + static bool paintsMarkerHighlights(const LayoutObject&); private: enum class PaintOptions { Normal, CombinedText };
diff --git a/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp b/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp index 5bd3b81..c0eb0e53 100644 --- a/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp +++ b/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp
@@ -112,9 +112,11 @@ // the opposite direction to enclosing, and in the y direction, the edges // are exactly on a half-pixel boundary. The numbers chosen map nicely to // both float and LayoutUnit, to make equality checking reliable. + // + // The final cull rect should be the enclosing int rect of this rect. FloatRect rect(20.75, -5.5, 5.375, 10); - EXPECT_EQ(rect, drawAndGetCullRect(rootPaintController(), layoutView(), rect)); - EXPECT_EQ(rect, drawAndGetCullRect(rootPaintController(), layoutView(), LayoutRect(rect))); + EXPECT_EQ(enclosingIntRect(rect), drawAndGetCullRect(rootPaintController(), layoutView(), rect)); + EXPECT_EQ(enclosingIntRect(rect), drawAndGetCullRect(rootPaintController(), layoutView(), LayoutRect(rect))); } #if 0 // TODO(wangxianzhu): Rewrite this test for slimmingPaintInvalidation.
diff --git a/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp index 93f1068..71497f1 100644 --- a/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.cpp
@@ -38,6 +38,23 @@ return !paintInfo.isPrinting() && m_svgInlineTextBox.getSelectionState() != SelectionNone; } +FloatRect SVGInlineTextBoxPainter::boundsForDrawingRecorder( + const LayoutPoint& paintOffset, bool includeSelectionRect) const +{ + // We compute the paint rect with what looks like the logical values, to match the + // computation in SVGInlineTextBox::calculateBoundaries, and the fact that vertical (etc) + // layouts are handled by SVGTextLayoutEngine. + LayoutRect bounds( + m_svgInlineTextBox.topLeft(), + LayoutSize(m_svgInlineTextBox.logicalWidth(), m_svgInlineTextBox.logicalHeight())); + if (includeSelectionRect) { + bounds.unite(m_svgInlineTextBox.localSelectionRect( + m_svgInlineTextBox.start(), m_svgInlineTextBox.start() + m_svgInlineTextBox.len())); + } + bounds.moveBy(paintOffset); + return FloatRect(bounds); +} + void SVGInlineTextBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); @@ -49,7 +66,8 @@ // We're explicitly not supporting composition & custom underlines and custom highlighters -- unlike InlineTextBox. // If we ever need that for SVG, it's very easy to refactor and reuse the code. - if (paintInfo.phase == PaintPhaseSelection && !shouldPaintSelection(paintInfo)) + bool haveSelection = shouldPaintSelection(paintInfo); + if (!haveSelection && paintInfo.phase == PaintPhaseSelection) return; LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(*LineLayoutAPIShim::layoutObjectFrom(m_svgInlineTextBox.getLineLayoutItem())); @@ -61,8 +79,10 @@ LayoutObject& parentLayoutObject = *LineLayoutAPIShim::layoutObjectFrom(m_svgInlineTextBox.parent()->getLineLayoutItem()); const ComputedStyle& style = parentLayoutObject.styleRef(); - // TODO(chrishtr): passing the cull rect is incorrect. - DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, displayItemType, FloatRect(paintInfo.cullRect().m_rect)); + bool includeSelectionRect = paintInfo.phase != PaintPhaseSelection + && (haveSelection || InlineTextBoxPainter::paintsMarkerHighlights(textLayoutObject)); + DrawingRecorder recorder(paintInfo.context, m_svgInlineTextBox, displayItemType, + boundsForDrawingRecorder(paintOffset, includeSelectionRect)); InlineTextBoxPainter(m_svgInlineTextBox).paintDocumentMarkers( paintInfo, paintOffset, style, textLayoutObject.scaledFont(), DocumentMarkerPaintPhase::Background);
diff --git a/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.h b/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.h index 5704099f..73e4615 100644 --- a/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.h +++ b/third_party/WebKit/Source/core/paint/SVGInlineTextBoxPainter.h
@@ -45,6 +45,7 @@ private: bool shouldPaintSelection(const PaintInfo&) const; + FloatRect boundsForDrawingRecorder(const LayoutPoint&, bool includeSelectionRect) const; void paintTextFragments(const PaintInfo&, LayoutObject&); void paintDecoration(const PaintInfo&, TextDecoration, const SVGTextFragment&); bool setupTextPaint(const PaintInfo&, const ComputedStyle&, LayoutSVGResourceMode, SkPaint&);
diff --git a/third_party/WebKit/Source/core/paint/VideoPainter.cpp b/third_party/WebKit/Source/core/paint/VideoPainter.cpp index dbeece3f..49ea54a 100644 --- a/third_party/WebKit/Source/core/paint/VideoPainter.cpp +++ b/third_party/WebKit/Source/core/paint/VideoPainter.cpp
@@ -13,6 +13,7 @@ #include "core/paint/PaintInfo.h" #include "platform/geometry/LayoutPoint.h" #include "platform/graphics/paint/ClipRecorder.h" +#include "platform/graphics/paint/ForeignLayerDisplayItem.h" namespace blink { @@ -39,11 +40,25 @@ if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutVideo, paintInfo.phase)) return; - LayoutObjectDrawingRecorder drawingRecorder(context, m_layoutVideo, paintInfo.phase, contentRect); // Video frames are only painted in software for printing or capturing node images via web APIs. bool forceSoftwareVideoPaint = paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers; + bool paintWithForeignLayer = + !displayingPoster && !forceSoftwareVideoPaint + && RuntimeEnabledFeatures::slimmingPaintV2Enabled(); + if (paintWithForeignLayer) { + if (WebLayer* layer = m_layoutVideo.mediaElement()->platformLayer()) { + IntRect pixelSnappedRect = pixelSnappedIntRect(contentRect); + recordForeignLayer( + context, m_layoutVideo, DisplayItem::ForeignLayerVideo, layer, + pixelSnappedRect.location(), pixelSnappedRect.size()); + return; + } + } + + LayoutObjectDrawingRecorder drawingRecorder(context, m_layoutVideo, paintInfo.phase, contentRect); + if (displayingPoster || !forceSoftwareVideoPaint) { // This will display the poster image, if one is present, and otherwise paint nothing. ImagePainter(m_layoutVideo).paintIntoRect(context, rect);
diff --git a/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp b/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp new file mode 100644 index 0000000..29551ff --- /dev/null +++ b/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp
@@ -0,0 +1,166 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/paint/VideoPainter.h" + +#include "core/frame/FrameView.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLMediaElement.h" +#include "core/loader/EmptyClients.h" +#include "core/testing/DummyPageHolder.h" +#include "platform/graphics/compositing/PaintArtifactCompositor.h" +#include "platform/testing/UnitTestHelpers.h" +#include "platform/testing/WebLayerTreeViewImplForTesting.h" +#include "public/platform/Platform.h" +#include "public/platform/WebCompositorSupport.h" +#include "public/platform/WebLayer.h" +#include "public/platform/WebMediaPlayer.h" +#include "public/platform/WebSize.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Integration tests of video painting code (in SPv2 mode). + +namespace blink { +namespace { + +class StubChromeClient : public EmptyChromeClient { +public: + StubChromeClient(WebLayerTreeViewImplForTesting::LayerListPolicy layerListPolicy) + : m_layerTreeView(layerListPolicy) + { + m_layerTreeView.setRootLayer(*m_paintArtifactCompositor.getWebLayer()); + } + + bool hasLayer(const WebLayer& layer) { return m_layerTreeView.hasLayer(layer); } + + // ChromeClient + void didPaint(const PaintArtifact& artifact) + { + m_paintArtifactCompositor.update(artifact); + } + +private: + WebLayerTreeViewImplForTesting m_layerTreeView; + PaintArtifactCompositor m_paintArtifactCompositor; +}; + +class StubWebMediaPlayer : public WebMediaPlayer { +public: + StubWebMediaPlayer(WebMediaPlayerClient* client) + : m_client(client) {} + + const WebLayer* getWebLayer() { return m_webLayer.get(); } + + // WebMediaPlayer + void load(LoadType, const WebMediaPlayerSource&, CORSMode) + { + m_networkState = NetworkStateLoaded; + m_client->networkStateChanged(); + m_readyState = ReadyStateHaveEnoughData; + m_client->readyStateChanged(); + m_webLayer = wrapUnique(Platform::current()->compositorSupport()->createLayer()); + m_client->setWebLayer(m_webLayer.get()); + } + void play() override {} + void pause() override {} + bool supportsSave() const override { return false; } + void seek(double seconds) override {} + void setRate(double) override {} + void setVolume(double) override {} + WebTimeRanges buffered() const override { return WebTimeRanges(); } + WebTimeRanges seekable() const override { return WebTimeRanges(); } + void setSinkId(const WebString& sinkId, const WebSecurityOrigin&, WebSetSinkIdCallbacks*) override {} + bool hasVideo() const override { return false; } + bool hasAudio() const override { return false; } + WebSize naturalSize() const override { return WebSize(0, 0); } + bool paused() const override { return false; } + bool seeking() const override { return false; } + double duration() const override { return 0.0; } + double currentTime() const override { return 0.0; } + NetworkState getNetworkState() const override { return m_networkState; } + ReadyState getReadyState() const override { return m_readyState; } + WebString getErrorMessage() override { return WebString(); } + bool didLoadingProgress() override { return false; } + bool hasSingleSecurityOrigin() const override { return true; } + bool didPassCORSAccessCheck() const override { return true; } + double mediaTimeForTimeValue(double timeValue) const override { return timeValue; } + unsigned decodedFrameCount() const override { return 0; } + unsigned droppedFrameCount() const override { return 0; } + size_t audioDecodedByteCount() const override { return 0; } + size_t videoDecodedByteCount() const override { return 0; } + void paint(WebCanvas*, const WebRect&, unsigned char alpha, SkXfermode::Mode) override {} + +private: + WebMediaPlayerClient* m_client; + std::unique_ptr<WebLayer> m_webLayer; + NetworkState m_networkState = NetworkStateEmpty; + ReadyState m_readyState = ReadyStateHaveNothing; +}; + +class StubFrameLoaderClient : public EmptyFrameLoaderClient { +public: + // FrameLoaderClient + std::unique_ptr<WebMediaPlayer> createWebMediaPlayer(HTMLMediaElement&, const WebMediaPlayerSource&, WebMediaPlayerClient* client) override + { + return wrapUnique(new StubWebMediaPlayer(client)); + } +}; + +class VideoPainterTestForSPv2 : public ::testing::TestWithParam<WebLayerTreeViewImplForTesting::LayerListPolicy> { +protected: + void SetUp() override + { + RuntimeEnabledFeatures::setSlimmingPaintV2Enabled(true); + m_chromeClient = new StubChromeClient(GetParam()); + m_frameLoaderClient = new StubFrameLoaderClient; + Page::PageClients clients; + fillWithEmptyClients(clients); + clients.chromeClient = m_chromeClient.get(); + m_pageHolder = DummyPageHolder::create(IntSize(800, 600), &clients, m_frameLoaderClient.get(), + [](Settings& settings) { settings.setAcceleratedCompositingEnabled(true); }); + document().view()->setParentVisible(true); + document().view()->setSelfVisible(true); + document().setURL(KURL(KURL(), "https://example.com/")); + } + + void TearDown() override + { + m_featuresBackup.restore(); + } + + Document& document() { return m_pageHolder->document(); } + bool hasLayerAttached(const WebLayer& layer) { return m_chromeClient->hasLayer(layer); } + +private: + RuntimeEnabledFeatures::Backup m_featuresBackup; + Persistent<StubChromeClient> m_chromeClient; + Persistent<StubFrameLoaderClient> m_frameLoaderClient; + std::unique_ptr<DummyPageHolder> m_pageHolder; +}; + +INSTANTIATE_TEST_CASE_P(, VideoPainterTestForSPv2, ::testing::Values( + WebLayerTreeViewImplForTesting::DontUseLayerLists, + WebLayerTreeViewImplForTesting::UseLayerLists)); + +TEST_P(VideoPainterTestForSPv2, VideoLayerAppearsInLayerTree) +{ + // Insert a <video> and allow it to begin loading. + document().body()->setInnerHTML("<video width=300 height=200 src=test.ogv>", ASSERT_NO_EXCEPTION); + testing::runPendingTasks(); + + // Force the page to paint. + document().view()->updateAllLifecyclePhases(); + + // Fetch the layer associated with the <video>, and check that it was + // correctly configured in the layer tree. + HTMLMediaElement* element = toHTMLMediaElement(document().body()->firstChild()); + StubWebMediaPlayer* player = static_cast<StubWebMediaPlayer*>(element->webMediaPlayer()); + const WebLayer* layer = player->getWebLayer(); + ASSERT_TRUE(layer); + EXPECT_TRUE(hasLayerAttached(*layer)); + EXPECT_EQ(WebSize(300, 200), layer->bounds()); +} + +} // namespace +} // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGFEBlendElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEBlendElement.cpp index 070ac3f..ff30498 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEBlendElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEBlendElement.cpp
@@ -113,8 +113,7 @@ if (attrName == SVGNames::modeAttr) return blend->setBlendMode(toWebBlendMode(m_mode->currentValue()->enumValue())); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEBlendElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.cpp index 2dd476e..1155c44 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEColorMatrixElement.cpp
@@ -67,8 +67,7 @@ if (attrName == SVGNames::valuesAttr) return colorMatrix->setValues(m_values->currentValue()->toFloatVector()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEColorMatrixElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFECompositeElement.cpp b/third_party/WebKit/Source/core/svg/SVGFECompositeElement.cpp index 37aa025..869cb4a 100644 --- a/third_party/WebKit/Source/core/svg/SVGFECompositeElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFECompositeElement.cpp
@@ -93,8 +93,7 @@ if (attrName == SVGNames::k4Attr) return composite->setK4(m_k4->currentValue()->value()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); }
diff --git a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp index 1cf1488..0b168f17 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp
@@ -151,9 +151,7 @@ return convolveMatrix->setTargetOffset(targetPoint()); if (attrName == SVGNames::preserveAlphaAttr) return convolveMatrix->setPreserveAlpha(m_preserveAlpha->currentValue()->value()); - - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEConvolveMatrixElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.cpp index f148e7c0..e83d6514 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEDiffuseLightingElement.cpp
@@ -86,8 +86,7 @@ if (attrName == SVGNames::limitingConeAngleAttr) return lightSource->setLimitingConeAngle(lightElement->limitingConeAngle()->currentValue()->value()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEDiffuseLightingElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.cpp index b36f09e..dabb9d0 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEDisplacementMapElement.cpp
@@ -74,8 +74,7 @@ if (attrName == SVGNames::scaleAttr) return displacementMap->setScale(m_scale->currentValue()->value()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEDisplacementMapElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.cpp index 6bf775c..f1dd4aa 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEDropShadowElement.cpp
@@ -73,9 +73,7 @@ dropShadow->setShadowOpacity(svgStyle.floodOpacity()); return true; } - - NOTREACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEDropShadowElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFEFloodElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEFloodElement.cpp index f0ce9e7a..f13540b 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEFloodElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEFloodElement.cpp
@@ -46,8 +46,7 @@ if (attrName == SVGNames::flood_opacityAttr) return flood->setFloodOpacity(style.svgStyle().floodOpacity()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } FilterEffect* SVGFEFloodElement::build(SVGFilterBuilder*, Filter* filter)
diff --git a/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.cpp index c3fd89f0..7ad0d9c7 100644 --- a/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFEMorphologyElement.cpp
@@ -68,9 +68,7 @@ bool isRadiusYChanged = morphology->setRadiusY(radiusY()->currentValue()->value()); return isRadiusXChanged || isRadiusYChanged; } - - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFEMorphologyElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.cpp b/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.cpp index 2f90a33d..838b9c1 100644 --- a/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFESpecularLightingElement.cpp
@@ -92,8 +92,7 @@ if (attrName == SVGNames::limitingConeAngleAttr) return lightSource->setLimitingConeAngle(lightElement->limitingConeAngle()->currentValue()->value()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFESpecularLightingElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.cpp b/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.cpp index 7e7db1ce..23e44da 100644 --- a/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFETurbulenceElement.cpp
@@ -89,8 +89,7 @@ if (attrName == SVGNames::numOctavesAttr) return turbulence->setNumOctaves(m_numOctaves->currentValue()->value()); - ASSERT_NOT_REACHED(); - return false; + return SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(effect, attrName); } void SVGFETurbulenceElement::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp b/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp index d519fa5..aa3c99c 100644 --- a/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFilterPrimitiveStandardAttributes.cpp
@@ -25,6 +25,7 @@ #include "core/layout/svg/LayoutSVGResourceContainer.h" #include "core/layout/svg/LayoutSVGResourceFilterPrimitive.h" #include "core/svg/SVGLength.h" +#include "core/svg/graphics/filters/SVGFilterBuilder.h" #include "platform/graphics/filters/FilterEffect.h" namespace blink { @@ -62,11 +63,16 @@ SVGElement::trace(visitor); } -bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect*, const QualifiedName&) +bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) { - // When all filters support this method, it will be changed to a pure virtual method. - ASSERT_NOT_REACHED(); - return false; + DCHECK(attrName == SVGNames::color_interpolation_filtersAttr); + DCHECK(layoutObject()); + EColorInterpolation colorInterpolation = layoutObject()->styleRef().svgStyle().colorInterpolationFilters(); + ColorSpace resolvedColorSpace = SVGFilterBuilder::resolveColorSpace(colorInterpolation); + if (resolvedColorSpace == effect->operatingColorSpace()) + return false; + effect->setOperatingColorSpace(resolvedColorSpace); + return true; } void SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(const QualifiedName& attrName)
diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp index ba326a9..b88584a 100644 --- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp +++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp
@@ -158,6 +158,11 @@ return parentColorInterpolation; } +ColorSpace SVGFilterBuilder::resolveColorSpace(EColorInterpolation colorInterpolation) +{ + return colorInterpolation == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB; +} + void SVGFilterBuilder::buildGraph(Filter* filter, SVGFilterElement& filterElement, const FloatRect& referenceBox) { EColorInterpolation filterColorInterpolation = colorInterpolationForElement(filterElement, CI_AUTO); @@ -177,7 +182,7 @@ effectElement->setStandardAttributes(effect); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), referenceBox)); EColorInterpolation colorInterpolation = colorInterpolationForElement(*effectElement, filterColorInterpolation); - effect->setOperatingColorSpace(colorInterpolation == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); + effect->setOperatingColorSpace(resolveColorSpace(colorInterpolation)); if (effectElement->taintsOrigin(effect->inputsTaintOrigin())) effect->setOriginTainted();
diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h index 37603db..3e6ce02 100644 --- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h +++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.h
@@ -21,6 +21,7 @@ #ifndef SVGFilterBuilder_h #define SVGFilterBuilder_h +#include "core/style/SVGComputedStyleDefs.h" #include "platform/graphics/filters/FilterEffect.h" #include "platform/heap/Handle.h" #include "wtf/HashMap.h" @@ -88,6 +89,8 @@ FilterEffect* getEffectById(const AtomicString& id) const; FilterEffect* lastEffect() const { return m_lastEffect.get(); } + static ColorSpace resolveColorSpace(EColorInterpolation); + private: void add(const AtomicString& id, FilterEffect*); void addBuiltinEffects();
diff --git a/third_party/WebKit/Source/devtools/PRESUBMIT.py b/third_party/WebKit/Source/devtools/PRESUBMIT.py index f740637..48c11e1 100644 --- a/third_party/WebKit/Source/devtools/PRESUBMIT.py +++ b/third_party/WebKit/Source/devtools/PRESUBMIT.py
@@ -69,10 +69,10 @@ # should be added to the list of triggers. devtools_front_end = input_api.os_path.join("devtools", "front_end") if (any(devtools_front_end in path for path in local_paths) or - any("protocol.json" in path for path in local_paths) or - any("compile_frontend.py" in path for path in local_paths) or - any("InjectedScriptSource.js" in path for path in local_paths) or - any("DebuggerScript.js" in path for path in local_paths)): + any("_protocol.json" in path for path in local_paths) or + any("compile_frontend.py" in path for path in local_paths) or + any("InjectedScriptSource.js" in path for path in local_paths) or + any("DebuggerScript.js" in path for path in local_paths)): lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "compile_frontend.py") out, _ = input_api.subprocess.Popen(
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi index dba0285b..97666e3 100644 --- a/third_party/WebKit/Source/devtools/devtools.gypi +++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -561,6 +561,7 @@ 'front_end/network/NetworkDataGridNode.js', 'front_end/network/NetworkItemView.js', 'front_end/network/NetworkLogView.js', + 'front_end/network/NetworkLogViewColumns.js', 'front_end/network/NetworkOverview.js', 'front_end/network/NetworkPanel.js', 'front_end/network/NetworkTimeCalculator.js',
diff --git a/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js b/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js index 9d16eac..be7afd4 100644 --- a/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js +++ b/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js
@@ -71,7 +71,8 @@ resultCallback(mainResourceURL, results); } - var requests = target.networkLog.requests().slice(); + var networkLog = WebInspector.NetworkLog.fromTarget(target); + var requests = networkLog ? networkLog.requests().slice() : []; var compositeProgress = new WebInspector.CompositeProgress(this._progress); var subprogresses = []; for (var i = 0; i < categories.length; ++i)
diff --git a/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js b/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js index b715e96..57f4fd2 100644 --- a/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js +++ b/third_party/WebKit/Source/devtools/front_end/common/ResourceType.js
@@ -195,114 +195,114 @@ /** * @param {string} url - * @return {string} + * @return {string|undefined} */ WebInspector.ResourceType.mimeFromURL = function(url) { var name = WebInspector.ParsedURL.extractName(url); - if (WebInspector.ResourceType.mimeTypeByName[name]) { - return WebInspector.ResourceType.mimeTypeByName[name]; + if (WebInspector.ResourceType._mimeTypeByName.has(name)) { + return WebInspector.ResourceType._mimeTypeByName.get(name); } var ext = WebInspector.ParsedURL.extractExtension(url).toLowerCase(); - return WebInspector.ResourceType.mimeTypeByExtension[ext]; + return WebInspector.ResourceType._mimeTypeByExtension.get(ext); } -WebInspector.ResourceType.mimeTypeByName = { +WebInspector.ResourceType._mimeTypeByName = new Map([ // CoffeeScript - "Cakefile": "text/x-coffeescript" -} + ["Cakefile", "text/x-coffeescript"] +]); -WebInspector.ResourceType.mimeTypeByExtension = { +WebInspector.ResourceType._mimeTypeByExtension = new Map([ // Web extensions - "js": "text/javascript", - "css": "text/css", - "html": "text/html", - "htm": "text/html", - "xml": "application/xml", - "xsl": "application/xml", + ["js", "text/javascript"], + ["css", "text/css"], + ["html", "text/html"], + ["htm", "text/html"], + ["xml", "application/xml"], + ["xsl", "application/xml"], - // HTML Embedded Scripts: ASP, JSP - "asp": "application/x-aspx", - "aspx": "application/x-aspx", - "jsp": "application/x-jsp", + // HTML Embedded Scripts, ASP], JSP + ["asp", "application/x-aspx"], + ["aspx", "application/x-aspx"], + ["jsp", "application/x-jsp"], // C/C++ - "c": "text/x-c++src", - "cc": "text/x-c++src", - "cpp": "text/x-c++src", - "h": "text/x-c++src", - "m": "text/x-c++src", - "mm": "text/x-c++src", + ["c", "text/x-c++src"], + ["cc", "text/x-c++src"], + ["cpp", "text/x-c++src"], + ["h", "text/x-c++src"], + ["m", "text/x-c++src"], + ["mm", "text/x-c++src"], // CoffeeScript - "coffee": "text/x-coffeescript", + ["coffee", "text/x-coffeescript"], // Dart - "dart": "text/javascript", + ["dart", "text/javascript"], // TypeScript - "ts": "text/typescript", - "tsx": "text/typescript", + ["ts", "text/typescript"], + ["tsx", "text/typescript"], // JSON - "json": "application/json", - "gyp": "application/json", - "gypi": "application/json", + ["json", "application/json"], + ["gyp", "application/json"], + ["gypi", "application/json"], // C# - "cs": "text/x-csharp", + ["cs", "text/x-csharp"], // Java - "java": "text/x-java", + ["java", "text/x-java"], // Less - "less": "text/x-less", + ["less", "text/x-less"], // PHP - "php": "text/x-php", - "phtml": "application/x-httpd-php", + ["php", "text/x-php"], + ["phtml", "application/x-httpd-php"], // Python - "py": "text/x-python", + ["py", "text/x-python"], // Shell - "sh": "text/x-sh", + ["sh", "text/x-sh"], // SCSS - "scss": "text/x-scss", + ["scss", "text/x-scss"], // Video Text Tracks. - "vtt": "text/vtt", + ["vtt", "text/vtt"], // LiveScript - "ls": "text/x-livescript", + ["ls", "text/x-livescript"], // ClojureScript - "cljs": "text/x-clojure", - "cljc": "text/x-clojure", - "cljx": "text/x-clojure", + ["cljs", "text/x-clojure"], + ["cljc", "text/x-clojure"], + ["cljx", "text/x-clojure"], // Stylus - "styl": "text/x-styl", + ["styl", "text/x-styl"], // JSX - "jsx": "text/jsx", + ["jsx", "text/jsx"], // Image - "jpeg": "image/jpeg", - "jpg": "image/jpeg", - "svg": "image/svg", - "gif": "image/gif", - "webp": "image/webp", - "png": "image/png", - "ico": "image/ico", - "tiff": "image/tiff", - "tif": "image/tif", - "bmp": "image/bmp", + ["jpeg", "image/jpeg"], + ["jpg", "image/jpeg"], + ["svg", "image/svg"], + ["gif", "image/gif"], + ["webp", "image/webp"], + ["png", "image/png"], + ["ico", "image/ico"], + ["tiff", "image/tiff"], + ["tif", "image/tif"], + ["bmp", "image/bmp"], // Font - "ttf": "font/opentype", - "otf": "font/opentype", - "ttc": "font/opentype", - "woff": "application/font-woff" -} + ["ttf", "font/opentype"], + ["otf", "font/opentype"], + ["ttc", "font/opentype"], + ["woff", "application/font-woff"] +]);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js index f2baae21..4b9b2fe 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
@@ -112,23 +112,6 @@ } /** - * @param {?WebInspector.DebuggerModel.GeneratorObjectDetails} response - * @this {WebInspector.ObjectPopoverHelper} - */ - function didGetGeneratorObjectDetails(response) - { - if (!response || popover.disposed) - return; - - var rawLocation = response.location; - var sourceURL = response.sourceURL; - if (rawLocation && sourceURL) { - var link = this._lazyLinkifier().linkifyRawLocation(rawLocation, sourceURL, "function-location-link"); - this._titleElement.appendChild(link); - } - } - - /** * @param {!WebInspector.RemoteObject} result * @param {boolean} wasThrown * @param {!Element=} anchorOverride @@ -176,20 +159,16 @@ popoverContentElement = createElement("div"); this._titleElement = popoverContentElement.createChild("div", "monospace"); this._titleElement.createChild("span", "source-frame-popover-title").textContent = description; - var section = new WebInspector.ObjectPropertiesSection(result, ""); + var section = new WebInspector.ObjectPropertiesSection(result, "", this._lazyLinkifier()); section.element.classList.add("source-frame-popover-tree"); section.titleLessMode(); popoverContentElement.appendChild(section.element); - - if (result.subtype === "generator") - result.generatorObjectDetails(didGetGeneratorObjectDetails.bind(this)); } var popoverWidth = 300; var popoverHeight = 250; popover.showForAnchor(popoverContentElement, anchorElement, popoverWidth, popoverHeight); } } - this._queryObject(element, didQueryObject.bind(this), this._popoverObjectGroup); },
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js index 5f9d406..8a90167 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -29,18 +29,19 @@ * @extends {TreeOutlineInShadow} * @param {!WebInspector.RemoteObject} object * @param {?string|!Element=} title + * @param {!WebInspector.Linkifier=} linkifier * @param {?string=} emptyPlaceholder * @param {boolean=} ignoreHasOwnProperty * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties */ -WebInspector.ObjectPropertiesSection = function(object, title, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) +WebInspector.ObjectPropertiesSection = function(object, title, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) { this._object = object; this._editable = true; TreeOutlineInShadow.call(this); this.hideOverflow(); this.setFocusable(false); - this._objectTreeElement = new WebInspector.ObjectPropertiesSection.RootElement(object, emptyPlaceholder, ignoreHasOwnProperty, extraProperties); + this._objectTreeElement = new WebInspector.ObjectPropertiesSection.RootElement(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties); this.appendChild(this._objectTreeElement); if (typeof title === "string" || !title) this.element.createChild("span").textContent = title || ""; @@ -58,10 +59,11 @@ /** * @param {!WebInspector.RemoteObject} object + * @param {!WebInspector.Linkifier=} linkifier * @param {boolean=} skipProto * @return {!Element} */ -WebInspector.ObjectPropertiesSection.defaultObjectPresentation = function(object, skipProto) +WebInspector.ObjectPropertiesSection.defaultObjectPresentation = function(object, linkifier, skipProto) { var componentRoot = createElementWithClass("span", "source-code"); var shadowRoot = WebInspector.createShadowRootWithCoreStyles(componentRoot, "components/objectValue.css"); @@ -69,7 +71,7 @@ if (!object.hasChildren) return componentRoot; - var objectPropertiesSection = new WebInspector.ObjectPropertiesSection(object, componentRoot); + var objectPropertiesSection = new WebInspector.ObjectPropertiesSection(object, componentRoot, linkifier); objectPropertiesSection.editable = false; if (skipProto) objectPropertiesSection.skipProto(); @@ -150,11 +152,12 @@ * @constructor * @extends {TreeElement} * @param {!WebInspector.RemoteObject} object + * @param {!WebInspector.Linkifier=} linkifier * @param {?string=} emptyPlaceholder * @param {boolean=} ignoreHasOwnProperty * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties */ -WebInspector.ObjectPropertiesSection.RootElement = function(object, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) +WebInspector.ObjectPropertiesSection.RootElement = function(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) { this._object = object; this._extraProperties = extraProperties || []; @@ -166,6 +169,7 @@ this.selectable = false; this.toggleOnClick = true; this.listItemElement.classList.add("object-properties-section-root-element"); + this._linkifier = linkifier; } WebInspector.ObjectPropertiesSection.RootElement.prototype = { @@ -194,7 +198,7 @@ onpopulate: function() { - WebInspector.ObjectPropertyTreeElement._populate(this, this._object, !!this.treeOutline._skipProto, this._emptyPlaceholder, this._ignoreHasOwnProperty, this._extraProperties); + WebInspector.ObjectPropertyTreeElement._populate(this, this._object, !!this.treeOutline._skipProto, this._linkifier, this._emptyPlaceholder, this._ignoreHasOwnProperty, this._extraProperties); }, __proto__: TreeElement.prototype @@ -204,8 +208,9 @@ * @constructor * @extends {TreeElement} * @param {!WebInspector.RemoteObjectProperty} property + * @param {!WebInspector.Linkifier=} linkifier */ -WebInspector.ObjectPropertyTreeElement = function(property) +WebInspector.ObjectPropertyTreeElement = function(property, linkifier) { this.property = property; @@ -215,6 +220,7 @@ this.selectable = false; /** @type {!Array.<!Object>} */ this._highlightChanges = []; + this._linkifier = linkifier; } WebInspector.ObjectPropertyTreeElement.prototype = { @@ -268,7 +274,7 @@ console.assert(propertyValue); var skipProto = this.treeOutline ? this.treeOutline._skipProto : true; var targetValue = this.property.name !== "__proto__" ? propertyValue : this.property.parentObject; - WebInspector.ObjectPropertyTreeElement._populate(this, propertyValue, skipProto, undefined, undefined, undefined, targetValue); + WebInspector.ObjectPropertyTreeElement._populate(this, propertyValue, skipProto, this._linkifier, undefined, undefined, undefined, targetValue); }, /** @@ -309,7 +315,7 @@ separatorElement.textContent = ": "; if (this.property.value) { - this.valueElement = WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport(this.property.value, this.property.wasThrown, this.listItemElement); + this.valueElement = WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport(this.property.value, this.property.wasThrown, this.listItemElement, this._linkifier); this.valueElement.addEventListener("contextmenu", this._contextMenuFired.bind(this, this.property), false); } else if (this.property.getter) { this.valueElement = WebInspector.ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(this.property.parentObject, [this.property.name], this._onInvokeGetterClick.bind(this)); @@ -498,16 +504,17 @@ * @param {!TreeElement} treeElement * @param {!WebInspector.RemoteObject} value * @param {boolean} skipProto + * @param {!WebInspector.Linkifier=} linkifier * @param {?string=} emptyPlaceholder * @param {boolean=} flattenProtoChain * @param {!Array.<!WebInspector.RemoteObjectProperty>=} extraProperties * @param {!WebInspector.RemoteObject=} targetValue */ -WebInspector.ObjectPropertyTreeElement._populate = function(treeElement, value, skipProto, emptyPlaceholder, flattenProtoChain, extraProperties, targetValue) +WebInspector.ObjectPropertyTreeElement._populate = function(treeElement, value, skipProto, linkifier, emptyPlaceholder, flattenProtoChain, extraProperties, targetValue) { if (value.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) { treeElement.removeChildren(); - WebInspector.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1); + WebInspector.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1, linkifier); return; } @@ -526,7 +533,7 @@ properties.push(extraProperties[i]); WebInspector.ObjectPropertyTreeElement.populateWithProperties(treeElement, properties, internalProperties, - skipProto, targetValue || value, emptyPlaceholder); + skipProto, targetValue || value, linkifier, emptyPlaceholder); } if (flattenProtoChain) @@ -541,9 +548,10 @@ * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties * @param {boolean} skipProto * @param {?WebInspector.RemoteObject} value + * @param {!WebInspector.Linkifier=} linkifier * @param {?string=} emptyPlaceholder */ -WebInspector.ObjectPropertyTreeElement.populateWithProperties = function(treeNode, properties, internalProperties, skipProto, value, emptyPlaceholder) { +WebInspector.ObjectPropertyTreeElement.populateWithProperties = function(treeNode, properties, internalProperties, skipProto, value, linkifier, emptyPlaceholder) { properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); for (var i = 0; i < properties.length; ++i) { @@ -553,29 +561,29 @@ if (property.isAccessorProperty()) { if (property.name !== "__proto__" && property.getter) { property.parentObject = value; - treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(property)); + treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(property, linkifier)); } if (property.isOwn) { if (property.getter) { var getterProperty = new WebInspector.RemoteObjectProperty("get " + property.name, property.getter); getterProperty.parentObject = value; - treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(getterProperty)); + treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(getterProperty, linkifier)); } if (property.setter) { var setterProperty = new WebInspector.RemoteObjectProperty("set " + property.name, property.setter); setterProperty.parentObject = value; - treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(setterProperty)); + treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(setterProperty, linkifier)); } } } else { property.parentObject = value; - treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(property)); + treeNode.appendChild(new WebInspector.ObjectPropertyTreeElement(property, linkifier)); } } if (internalProperties) { for (var i = 0; i < internalProperties.length; i++) { internalProperties[i].parentObject = value; - var treeElement = new WebInspector.ObjectPropertyTreeElement(internalProperties[i]); + var treeElement = new WebInspector.ObjectPropertyTreeElement(internalProperties[i], linkifier); if (internalProperties[i].name === "[[Entries]]") { treeElement.setExpandable(true); treeElement.expand(); @@ -598,7 +606,7 @@ } } if (!hasTargetFunction) - treeNode.appendChild(new WebInspector.FunctionScopeMainTreeElement(value)); + treeNode.appendChild(new WebInspector.FunctionScopeMainTreeElement(value, linkifier)); } WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder); } @@ -647,13 +655,15 @@ * @constructor * @extends {TreeElement} * @param {!WebInspector.RemoteObject} remoteObject + * @param {!WebInspector.Linkifier=} linkifier */ -WebInspector.FunctionScopeMainTreeElement = function(remoteObject) +WebInspector.FunctionScopeMainTreeElement = function(remoteObject, linkifier) { TreeElement.call(this, "<function scope>", true); this.toggleOnClick = true; this.selectable = false; this._remoteObject = remoteObject; + this._linkifier = linkifier; } WebInspector.FunctionScopeMainTreeElement.prototype = { @@ -711,7 +721,7 @@ var property = new WebInspector.RemoteObjectProperty(title, remoteObject); property.writable = false; property.parentObject = null; - this.appendChild(new WebInspector.ObjectPropertyTreeElement(property)); + this.appendChild(new WebInspector.ObjectPropertyTreeElement(property, this._linkifier)); } else { var scopeRef = new WebInspector.ScopeRef(i, undefined); var remoteObject = runtimeModel.createScopeRemoteObject(scope.object, scopeRef); @@ -759,8 +769,9 @@ * @param {number} fromIndex * @param {number} toIndex * @param {number} propertyCount + * @param {!WebInspector.Linkifier=} linkifier */ -WebInspector.ArrayGroupingTreeElement = function(object, fromIndex, toIndex, propertyCount) +WebInspector.ArrayGroupingTreeElement = function(object, fromIndex, toIndex, propertyCount, linkifier) { TreeElement.call(this, String.sprintf("[%d \u2026 %d]", fromIndex, toIndex), true); this.toggleOnClick = true; @@ -770,6 +781,7 @@ this._object = object; this._readOnly = true; this._propertyCount = propertyCount; + this._linkifier = linkifier; } WebInspector.ArrayGroupingTreeElement._bucketThreshold = 100; @@ -781,10 +793,11 @@ * @param {!WebInspector.RemoteObject} object * @param {number} fromIndex * @param {number} toIndex + * @param {!WebInspector.Linkifier=} linkifier */ -WebInspector.ArrayGroupingTreeElement._populateArray = function(treeNode, object, fromIndex, toIndex) +WebInspector.ArrayGroupingTreeElement._populateArray = function(treeNode, object, fromIndex, toIndex, linkifier) { - WebInspector.ArrayGroupingTreeElement._populateRanges(treeNode, object, fromIndex, toIndex, true); + WebInspector.ArrayGroupingTreeElement._populateRanges(treeNode, object, fromIndex, toIndex, true, linkifier); } /** @@ -793,9 +806,10 @@ * @param {number} fromIndex * @param {number} toIndex * @param {boolean} topLevel + * @param {!WebInspector.Linkifier=} linkifier * @this {WebInspector.ArrayGroupingTreeElement} */ -WebInspector.ArrayGroupingTreeElement._populateRanges = function(treeNode, object, fromIndex, toIndex, topLevel) +WebInspector.ArrayGroupingTreeElement._populateRanges = function(treeNode, object, fromIndex, toIndex, topLevel, linkifier) { object.callFunctionJSON(packRanges, [ { value: fromIndex }, @@ -889,20 +903,20 @@ return; var ranges = /** @type {!Array.<!Array.<number>>} */ (result.ranges); if (ranges.length === 1) { - WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, ranges[0][0], ranges[0][1]); + WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, ranges[0][0], ranges[0][1], linkifier); } else { for (var i = 0; i < ranges.length; ++i) { var fromIndex = ranges[i][0]; var toIndex = ranges[i][1]; var count = ranges[i][2]; if (fromIndex === toIndex) - WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, fromIndex, toIndex); + WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier); else - treeNode.appendChild(new WebInspector.ArrayGroupingTreeElement(object, fromIndex, toIndex, count)); + treeNode.appendChild(new WebInspector.ArrayGroupingTreeElement(object, fromIndex, toIndex, count, linkifier)); } } if (topLevel) - WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties(treeNode, object, result.skipGetOwnPropertyNames); + WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties(treeNode, object, result.skipGetOwnPropertyNames, linkifier); } } @@ -911,9 +925,10 @@ * @param {!WebInspector.RemoteObject} object * @param {number} fromIndex * @param {number} toIndex + * @param {!WebInspector.Linkifier=} linkifier * @this {WebInspector.ArrayGroupingTreeElement} */ -WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeNode, object, fromIndex, toIndex) +WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeNode, object, fromIndex, toIndex, linkifier) { object.callFunction(buildArrayFragment, [{value: fromIndex}, {value: toIndex}, {value: WebInspector.ArrayGroupingTreeElement._sparseIterationThreshold}], processArrayFragment.bind(this)); @@ -965,7 +980,7 @@ properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); for (var i = 0; i < properties.length; ++i) { properties[i].parentObject = this._object; - var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i]); + var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i], linkifier); childTreeElement._readOnly = true; treeNode.appendChild(childTreeElement); } @@ -976,9 +991,10 @@ * @param {!TreeElement} treeNode * @param {!WebInspector.RemoteObject} object * @param {boolean} skipGetOwnPropertyNames + * @param {!WebInspector.Linkifier=} linkifier * @this {WebInspector.ArrayGroupingTreeElement} */ -WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(treeNode, object, skipGetOwnPropertyNames) +WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(treeNode, object, skipGetOwnPropertyNames, linkifier) { object.callFunction(buildObjectFragment, [{value: skipGetOwnPropertyNames}], processObjectFragment.bind(this)); @@ -1029,7 +1045,7 @@ properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); for (var i = 0; i < properties.length; ++i) { properties[i].parentObject = this._object; - var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i]); + var childTreeElement = new WebInspector.ObjectPropertyTreeElement(properties[i], linkifier); childTreeElement._readOnly = true; treeNode.appendChild(childTreeElement); } @@ -1040,10 +1056,10 @@ onpopulate: function() { if (this._propertyCount >= WebInspector.ArrayGroupingTreeElement._bucketThreshold) { - WebInspector.ArrayGroupingTreeElement._populateRanges(this, this._object, this._fromIndex, this._toIndex, false); + WebInspector.ArrayGroupingTreeElement._populateRanges(this, this._object, this._fromIndex, this._toIndex, false, this._linkifier); return; } - WebInspector.ArrayGroupingTreeElement._populateAsFragment(this, this._object, this._fromIndex, this._toIndex); + WebInspector.ArrayGroupingTreeElement._populateAsFragment(this, this._object, this._fromIndex, this._toIndex, this._linkifier); }, onattach: function() @@ -1102,25 +1118,27 @@ * @param {!WebInspector.RemoteObject} value * @param {boolean} wasThrown * @param {!Element=} parentElement + * @param {!WebInspector.Linkifier=} linkifier * @return {!Element} */ -WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport = function(value, wasThrown, parentElement) +WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport = function(value, wasThrown, parentElement, linkifier) { if (value.customPreview()) { var result = (new WebInspector.CustomPreviewComponent(value)).element; result.classList.add("object-properties-section-custom-section"); return result } - return WebInspector.ObjectPropertiesSection.createValueElement(value, wasThrown, parentElement); + return WebInspector.ObjectPropertiesSection.createValueElement(value, wasThrown, parentElement, linkifier); } /** * @param {!WebInspector.RemoteObject} value * @param {boolean} wasThrown * @param {!Element=} parentElement + * @param {!WebInspector.Linkifier=} linkifier * @return {!Element} */ -WebInspector.ObjectPropertiesSection.createValueElement = function(value, wasThrown, parentElement) +WebInspector.ObjectPropertiesSection.createValueElement = function(value, wasThrown, parentElement, linkifier) { var valueElement = createElementWithClass("span", "value"); var type = value.type; @@ -1174,6 +1192,9 @@ valueElement.title = description || ""; } + if (type === "object" && subtype === "internal#location" && linkifier) + return linkifier.linkifyScriptLocation(value.target(), value.value.scriptId, "", value.value.lineNumber, value.value.columnNumber); + function mouseMove() { WebInspector.DOMModel.highlightObjectAsDOMNode(value);
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js index cc77784..adf4bad 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -423,7 +423,7 @@ var note = titleElement.createChild("span", "object-state-note"); note.classList.add("info-note"); note.title = WebInspector.UIString("Object value at left was snapshotted when logged, value below was evaluated just now."); - var section = new WebInspector.ObjectPropertiesSection(obj, titleElement); + var section = new WebInspector.ObjectPropertiesSection(obj, titleElement, this._linkifier); section.enableContextMenu(); elem.appendChild(section.element); section.element.classList.add("console-view-object-properties-section");
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js index 3f8150e..64f379b 100644 --- a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js +++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js
@@ -978,6 +978,7 @@ chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow; chrome.devtools.network = coreAPI.network; chrome.devtools.panels = coreAPI.panels; + chrome.devtools.panels.themeName = themeName; // default to expose experimental APIs for now. if (extensionInfo.exposeExperimentalAPIs !== false) { @@ -998,27 +999,30 @@ /** * @param {!ExtensionDescriptor} extensionInfo * @param {string} inspectedTabId + * @param {string} themeName * @return {string} */ -function buildPlatformExtensionAPI(extensionInfo, inspectedTabId) +function buildPlatformExtensionAPI(extensionInfo, inspectedTabId, themeName) { return "var extensionInfo = " + JSON.stringify(extensionInfo) + ";" + "var tabId = " + inspectedTabId + ";" + + "var themeName = '" + themeName + "';" + platformExtensionAPI.toString(); } /** * @param {!ExtensionDescriptor} extensionInfo * @param {string} inspectedTabId + * @param {string} themeName * @return {string} */ -function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId) +function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId, themeName) { return "(function(injectedScriptId){ " + "var extensionServer;" + defineCommonExtensionSymbols.toString() + ";" + injectedExtensionAPI.toString() + ";" + - buildPlatformExtensionAPI(extensionInfo, inspectedTabId) + ";" + + buildPlatformExtensionAPI(extensionInfo, inspectedTabId, themeName) + ";" + "platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" + "return {};" + "})";
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js index 3130bbc6..26fc6ca 100644 --- a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js +++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js
@@ -764,7 +764,7 @@ var extensionOrigin = originMatch[1]; if (!this._registeredExtensions[extensionOrigin]) { // See ExtensionAPI.js for details. - InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, buildExtensionAPIInjectedScript(extensionInfo, this._inspectedTabId)); + InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, buildExtensionAPIInjectedScript(extensionInfo, this._inspectedTabId, WebInspector.themeSupport.themeName())); this._registeredExtensions[extensionOrigin] = { name: name }; } var iframe = createElement("iframe");
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index f9f215d..8c8748bf 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -308,7 +308,12 @@ WebInspector.RemoteDebuggingTerminatedScreen.show(event.data.reason); } - var targetType = Runtime.queryParam("isSharedWorker") ? WebInspector.Target.Type.ServiceWorker : WebInspector.Target.Type.Page; + var targetType = WebInspector.Target.Type.Page; + if (Runtime.queryParam("isSharedWorker")) + targetType = WebInspector.Target.Type.ServiceWorker; + else if (Runtime.queryParam("v8only")) + targetType = WebInspector.Target.Type.JSInspector; + this._mainTarget = WebInspector.targetManager.createTarget(WebInspector.UIString("Main"), targetType, connection, null); console.timeStamp("Main._mainTargetCreated"); this._registerShortcuts(); @@ -317,7 +322,7 @@ InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ReloadInspectedPage, this._reloadInspectedPage, this); InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.EvaluateForTestInFrontend, this._evaluateForTestInFrontend, this); - if (this._mainTarget.isServiceWorker() || this._mainTarget.isPage()) + if (this._mainTarget.isServiceWorker() || this._mainTarget.isPage() || this._mainTarget.isJSInspector()) this._mainTarget.runtimeAgent().run(); this._mainTarget.inspectorAgent().enable();
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js index 36fcba3..5bc99b0 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -51,13 +51,7 @@ this._progressBarContainer = progressBarContainer; this._networkLogLargeRowsSetting = networkLogLargeRowsSetting; - var defaultColumnsVisibility = WebInspector.NetworkLogView._defaultColumnsVisibility; - this._columnsVisibilitySetting = WebInspector.settings.createSetting("networkLogColumnsVisibility", defaultColumnsVisibility); - var savedColumnsVisibility = this._columnsVisibilitySetting.get(); - var columnsVisibility = {}; - for (var columnId in defaultColumnsVisibility) - columnsVisibility[columnId] = savedColumnsVisibility.hasOwnProperty(columnId) ? savedColumnsVisibility[columnId] : defaultColumnsVisibility[columnId]; - this._columnsVisibilitySetting.set(columnsVisibility); + this._columns = new WebInspector.NetworkLogViewColumns(this, networkLogLargeRowsSetting); /** @type {!Map.<string, !WebInspector.NetworkDataGridNode>} */ this._nodesByRequestId = new Map(); @@ -68,8 +62,6 @@ /** @type {number} */ this._mainRequestDOMContentLoadedTime = -1; this._matchedRequestCount = 0; - /** @type {!Array<{time: number, element: !Element}>} */ - this._eventDividers = []; this._highlightedSubstringChanges = []; /** @type {!Array.<!WebInspector.NetworkLogView.Filter>} */ @@ -81,11 +73,8 @@ this._currentMatchedRequestIndex = -1; /** @type {!WebInspector.Linkifier} */ - this._popupLinkifier = new WebInspector.Linkifier(); - /** @type {!WebInspector.Linkifier} */ this.linkifier = new WebInspector.Linkifier(); - this._gridMode = true; this._recording = false; this._preserveLog = false; @@ -109,11 +98,7 @@ WebInspector.NetworkLogView._isMatchingSearchQuerySymbol = Symbol("isMatchingSearchQuery"); WebInspector.NetworkLogView.HTTPSchemas = {"http": true, "https": true, "ws": true, "wss": true}; -WebInspector.NetworkLogView._responseHeaderColumns = ["Cache-Control", "Connection", "Content-Encoding", "Content-Length", "ETag", "Keep-Alive", "Last-Modified", "Server", "Vary"]; -WebInspector.NetworkLogView._defaultColumnsVisibility = { - method: false, status: true, protocol: false, scheme: false, domain: false, remoteAddress: false, type: true, initiator: true, cookies: false, setCookies: false, size: true, time: true, priority: false, connectionId: false, - "Cache-Control": false, "Connection": false, "Content-Encoding": false, "Content-Length": false, "ETag": false, "Keep-Alive": false, "Last-Modified": false, "Server": false, "Vary": false -}; + WebInspector.NetworkLogView._defaultRefreshDelay = 200; WebInspector.NetworkLogView._waterfallMinOvertime = 1; @@ -151,37 +136,6 @@ /** @type {!Array.<string>} */ WebInspector.NetworkLogView._searchKeys = Object.values(WebInspector.NetworkLogView.FilterType); -/** @type {!Object.<string, string>} */ -WebInspector.NetworkLogView._columnTitles = { - "name": WebInspector.UIString("Name"), - "method": WebInspector.UIString("Method"), - "status": WebInspector.UIString("Status"), - "protocol": WebInspector.UIString("Protocol"), - "scheme": WebInspector.UIString("Scheme"), - "domain": WebInspector.UIString("Domain"), - "remoteAddress": WebInspector.UIString("Remote Address"), - "type": WebInspector.UIString("Type"), - "initiator": WebInspector.UIString("Initiator"), - "cookies": WebInspector.UIString("Cookies"), - "setCookies": WebInspector.UIString("Set-Cookies"), - "size": WebInspector.UIString("Size"), - "time": WebInspector.UIString("Time"), - "connectionId": WebInspector.UIString("Connection Id"), - "priority": WebInspector.UIString("Priority"), - "timeline": WebInspector.UIString("Timeline"), - - // Response header columns - "Cache-Control": WebInspector.UIString("Cache-Control"), - "Connection": WebInspector.UIString("Connection"), - "Content-Encoding": WebInspector.UIString("Content-Encoding"), - "Content-Length": WebInspector.UIString("Content-Length"), - "ETag": WebInspector.UIString("ETag"), - "Keep-Alive": WebInspector.UIString("Keep-Alive"), - "Last-Modified": WebInspector.UIString("Last-Modified"), - "Server": WebInspector.UIString("Server"), - "Vary": WebInspector.UIString("Vary") -}; - WebInspector.NetworkLogView.prototype = { /** * @param {boolean} recording @@ -211,7 +165,9 @@ target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.Load, this._loadEventFired, this); target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._domContentLoadedEventFired, this); } - target.networkLog.requests().forEach(this._appendRequest.bind(this)); + var networkLog = WebInspector.NetworkLog.fromTarget(target); + if (networkLog) + networkLog.requests().forEach(this._appendRequest.bind(this)); }, /** @@ -240,7 +196,7 @@ this._timeFilter = WebInspector.NetworkLogView._requestTimeFilter.bind(null, start, end); this._timeCalculator.setWindow(new WebInspector.NetworkTimeBoundary(start, end)); } - this._updateDividersIfNeeded(); + this._columns.updateDividersIfNeeded(); this._filterRequests(); }, @@ -286,7 +242,7 @@ */ _filterChanged: function(event) { - this._removeAllNodeHighlights(); + this.removeAllNodeHighlights(); this._parseFilterQuery(this._textFilterUI.value()); this._filterRequests(); }, @@ -295,16 +251,16 @@ { this.element.id = "network-container"; - this._createSortingFunctions(); - this._createCalculators(); + /** @type {!WebInspector.NetworkTransferTimeCalculator} */ + this._timeCalculator = new WebInspector.NetworkTransferTimeCalculator(); + /** @type {!WebInspector.NetworkTransferDurationCalculator} */ + this._durationCalculator = new WebInspector.NetworkTransferDurationCalculator(); + this._calculator = this._timeCalculator; + this._createTable(); - this._createTimelineGrid(); this._summaryBarElement = this.element.createChild("div", "network-summary-bar"); this._updateRowsSize(); - - this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), this._onHidePopover.bind(this)); - this.switchViewMode(true); }, _showRecordingHint: function() @@ -345,144 +301,10 @@ return [this._dataGrid.scrollContainer]; }, - _createTimelineGrid: function() - { - this._timelineGrid = new WebInspector.TimelineGrid(); - this._timelineGrid.element.classList.add("network-timeline-grid"); - this._dataGrid.element.appendChild(this._timelineGrid.element); - }, - _createTable: function() { - var columns = []; - columns.push({ - id: "name", - titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path")), - title: WebInspector.NetworkLogView._columnTitles["name"], - weight: 20 - }); - - columns.push({ - id: "method", - title: WebInspector.NetworkLogView._columnTitles["method"], - weight: 6 - }); - - columns.push({ - id: "status", - titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text")), - title: WebInspector.NetworkLogView._columnTitles["status"], - weight: 6 - }); - - columns.push({ - id: "protocol", - title: WebInspector.NetworkLogView._columnTitles["protocol"], - weight: 6 - }); - - columns.push({ - id: "scheme", - title: WebInspector.NetworkLogView._columnTitles["scheme"], - weight: 6 - }); - - columns.push({ - id: "domain", - title: WebInspector.NetworkLogView._columnTitles["domain"], - weight: 6 - }); - - columns.push({ - id: "remoteAddress", - title: WebInspector.NetworkLogView._columnTitles["remoteAddress"], - weight: 10, - align: WebInspector.DataGrid.Align.Right - }); - - columns.push({ - id: "type", - title: WebInspector.NetworkLogView._columnTitles["type"], - weight: 6 - }); - - columns.push({ - id: "initiator", - title: WebInspector.NetworkLogView._columnTitles["initiator"], - weight: 10 - }); - - columns.push({ - id: "cookies", - title: WebInspector.NetworkLogView._columnTitles["cookies"], - weight: 6, - align: WebInspector.DataGrid.Align.Right - }); - - columns.push({ - id: "setCookies", - title: WebInspector.NetworkLogView._columnTitles["setCookies"], - weight: 6, - align: WebInspector.DataGrid.Align.Right - }); - - columns.push({ - id: "size", - titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Content")), - title: WebInspector.NetworkLogView._columnTitles["size"], - weight: 6, - align: WebInspector.DataGrid.Align.Right - }); - - columns.push({ - id: "time", - titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Latency")), - title: WebInspector.NetworkLogView._columnTitles["time"], - weight: 6, - align: WebInspector.DataGrid.Align.Right - }); - - columns.push({ - id: "priority", - title: WebInspector.NetworkLogView._columnTitles["priority"], - weight: 6 - }); - - columns.push({ - id: "connectionId", - title: WebInspector.NetworkLogView._columnTitles["connectionId"], - weight: 6 - }); - - var responseHeaderColumns = WebInspector.NetworkLogView._responseHeaderColumns; - for (var i = 0; i < responseHeaderColumns.length; ++i) { - var headerName = responseHeaderColumns[i]; - var descriptor = { - id: headerName, - title: WebInspector.NetworkLogView._columnTitles[headerName], - weight: 6 - }; - if (headerName === "Content-Length") - descriptor.align = WebInspector.DataGrid.Align.Right; - columns.push(descriptor); - } - - columns.push({ - id: "timeline", - title: WebInspector.NetworkLogView._columnTitles["timeline"], - sortable: false, - weight: 40, - sort: WebInspector.DataGrid.Order.Ascending - }); - - for (var column of columns) { - column.sortable = column.id !== "timeline"; - column.nonSelectable = column.id !== "name"; - } - - this._dataGrid = new WebInspector.SortableDataGrid(columns); + this._dataGrid = this._columns.createGrid(this._timeCalculator, this._durationCalculator); this._dataGrid.setStickToBottom(true); - this._updateColumns(); this._dataGrid.setName("networkLog"); this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last); this._dataGrid.element.classList.add("network-log-grid"); @@ -490,14 +312,6 @@ this._dataGrid.element.addEventListener("mousedown", this._dataGridMouseDown.bind(this), true); this._dataGrid.element.addEventListener("mousemove", this._dataGridMouseMove.bind(this), true); this._dataGrid.element.addEventListener("mouseleave", this._highlightInitiatorChain.bind(this, null), true); - this._dataGrid.asWidget().show(this.element); - - // Event listeners need to be added _after_ we attach to the document, so that owner document is properly update. - this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortItems, this); - this._dataGrid.addEventListener(WebInspector.DataGrid.Events.ColumnsResized, this._updateDividersIfNeeded, this); - - this._patchTimelineHeader(); - this._dataGrid.sortNodes(this._sortingFunctions.startTime, false); }, /** @@ -554,158 +368,6 @@ } }, - /** - * @param {string} title - * @param {string} subtitle - * @return {!DocumentFragment} - */ - _makeHeaderFragment: function(title, subtitle) - { - var fragment = createDocumentFragment(); - fragment.createTextChild(title); - var subtitleDiv = fragment.createChild("div", "network-header-subtitle"); - subtitleDiv.createTextChild(subtitle); - return fragment; - }, - - _patchTimelineHeader: function() - { - var timelineSorting = createElement("select"); - - var option = createElement("option"); - option.value = "startTime"; - option.label = WebInspector.UIString("Timeline"); - option.disabled = true; - timelineSorting.appendChild(option); - - option = createElement("option"); - option.value = "startTime"; - option.label = WebInspector.UIString("Timeline \u2013 Start Time"); - option.sortOrder = WebInspector.DataGrid.Order.Ascending; - timelineSorting.appendChild(option); - - option = createElement("option"); - option.value = "responseTime"; - option.label = WebInspector.UIString("Timeline \u2013 Response Time"); - option.sortOrder = WebInspector.DataGrid.Order.Ascending; - timelineSorting.appendChild(option); - - option = createElement("option"); - option.value = "endTime"; - option.label = WebInspector.UIString("Timeline \u2013 End Time"); - option.sortOrder = WebInspector.DataGrid.Order.Ascending; - timelineSorting.appendChild(option); - - option = createElement("option"); - option.value = "duration"; - option.label = WebInspector.UIString("Timeline \u2013 Total Duration"); - option.sortOrder = WebInspector.DataGrid.Order.Descending; - timelineSorting.appendChild(option); - - option = createElement("option"); - option.value = "latency"; - option.label = WebInspector.UIString("Timeline \u2013 Latency"); - option.sortOrder = WebInspector.DataGrid.Order.Descending; - timelineSorting.appendChild(option); - - var header = this._dataGrid.headerTableHeader("timeline"); - header.replaceChild(timelineSorting, header.firstChild); - header.createChild("div", "sort-order-icon-container").createChild("div", "sort-order-icon"); - - timelineSorting.selectedIndex = 1; - timelineSorting.addEventListener("click", function(event) { event.consume(); }, false); - timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false); - this._timelineSortSelector = timelineSorting; - }, - - _createSortingFunctions: function() - { - this._sortingFunctions = {}; - this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator; - this._sortingFunctions.method = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "requestMethod"); - this._sortingFunctions.status = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "statusCode"); - this._sortingFunctions.protocol = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "protocol"); - this._sortingFunctions.scheme = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "scheme"); - this._sortingFunctions.domain = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "domain"); - this._sortingFunctions.remoteAddress = WebInspector.NetworkDataGridNode.RemoteAddressComparator; - this._sortingFunctions.type = WebInspector.NetworkDataGridNode.TypeComparator; - this._sortingFunctions.initiator = WebInspector.NetworkDataGridNode.InitiatorComparator; - this._sortingFunctions.cookies = WebInspector.NetworkDataGridNode.RequestCookiesCountComparator; - this._sortingFunctions.setCookies = WebInspector.NetworkDataGridNode.ResponseCookiesCountComparator; - this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator; - this._sortingFunctions.time = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "duration"); - this._sortingFunctions.connectionId = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "connectionId"); - this._sortingFunctions.priority = WebInspector.NetworkDataGridNode.InitialPriorityComparator; - this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "startTime"); - this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "startTime"); - this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "endTime"); - this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "responseReceivedTime"); - this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "duration"); - this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "latency"); - - this._sortingFunctions["Cache-Control"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Cache-Control"); - this._sortingFunctions["Connection"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Connection"); - this._sortingFunctions["Content-Encoding"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Content-Encoding"); - this._sortingFunctions["Content-Length"] = WebInspector.NetworkDataGridNode.ResponseHeaderNumberComparator.bind(null, "Content-Length"); - this._sortingFunctions["ETag"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "ETag"); - this._sortingFunctions["Keep-Alive"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Keep-Alive"); - this._sortingFunctions["Last-Modified"] = WebInspector.NetworkDataGridNode.ResponseHeaderDateComparator.bind(null, "Last-Modified"); - this._sortingFunctions["Server"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Server"); - this._sortingFunctions["Vary"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Vary"); - }, - - _createCalculators: function() - { - /** @type {!WebInspector.NetworkTransferTimeCalculator} */ - this._timeCalculator = new WebInspector.NetworkTransferTimeCalculator(); - /** @type {!WebInspector.NetworkTransferDurationCalculator} */ - this._durationCalculator = new WebInspector.NetworkTransferDurationCalculator(); - - /** @type {!Object.<string, !WebInspector.NetworkTimeCalculator>} */ - this._calculators = {}; - this._calculators.timeline = this._timeCalculator; - this._calculators.startTime = this._timeCalculator; - this._calculators.endTime = this._timeCalculator; - this._calculators.responseTime = this._timeCalculator; - this._calculators.duration = this._durationCalculator; - this._calculators.latency = this._durationCalculator; - - this._calculator = this._timeCalculator; - }, - - _sortItems: function() - { - this._removeAllNodeHighlights(); - var columnIdentifier = this._dataGrid.sortColumnIdentifier(); - if (columnIdentifier === "timeline") { - this._sortByTimeline(); - return; - } - var sortingFunction = this._sortingFunctions[columnIdentifier]; - if (!sortingFunction) - return; - - this._dataGrid.sortNodes(sortingFunction, !this._dataGrid.isSortOrderAscending()); - this._highlightNthMatchedRequestForSearch(this._updateMatchCountAndFindMatchIndex(this._currentMatchedRequestNode), false); - this._timelineSortSelector.selectedIndex = 0; - }, - - _sortByTimeline: function() - { - this._removeAllNodeHighlights(); - var selectedIndex = this._timelineSortSelector.selectedIndex; - if (!selectedIndex) - selectedIndex = 1; // Sort by start time by default. - var selectedOption = this._timelineSortSelector[selectedIndex]; - var value = selectedOption.value; - - this._setCalculator(this._calculators[value]); - var sortingFunction = this._sortingFunctions[value]; - this._dataGrid.sortNodes(sortingFunction); - this._highlightNthMatchedRequestForSearch(this._updateMatchCountAndFindMatchIndex(this._currentMatchedRequestNode), false); - this._dataGrid.markColumnAsSortedBy("timeline", selectedOption.sortOrder); - }, - _updateSummaryBar: function() { var requestsNumber = this._nodesByRequestId.size; @@ -778,7 +440,7 @@ summaryBar.title = text; }, - _scheduleRefresh: function() + scheduleRefresh: function() { if (this._needsRefresh) return; @@ -789,38 +451,12 @@ this._refreshTimeout = setTimeout(this.refresh.bind(this), WebInspector.NetworkLogView._defaultRefreshDelay); }, - _updateDividersIfNeeded: function() - { - if (!this.isShowing()) { - this._scheduleRefresh(); - return; - } - - var timelineOffset = this._dataGrid.columnOffset("timeline"); - // Position timline grid location. - if (timelineOffset) - this._timelineGrid.element.style.left = timelineOffset + "px"; - - var calculator = this.calculator(); - calculator.setDisplayWindow(this._timelineGrid.dividersElement.clientWidth); - this._timelineGrid.updateDividers(calculator, 75); - - if (calculator.startAtZero) { - // If our current sorting method starts at zero, that means it shows all - // requests starting at the same point, and so onLoad event and DOMContent - // event lines really wouldn't make much sense here, so don't render them. - return; - } - - this._updateEventDividers(); - }, - /** * @param {!Array<number>} times */ addFilmStripFrames: function(times) { - this._addEventDividers(times, "network-frame-divider"); + this._columns.addEventDividers(times, "network-frame-divider"); }, /** @@ -838,33 +474,6 @@ divider.element.classList.toggle("network-frame-divider-selected", false); }, - /** - * @param {!Array<number>} times - * @param {string} className - */ - _addEventDividers: function(times, className) - { - for (var i = 0; i < times.length; ++i) { - var element = createElementWithClass("div", "network-event-divider " + className); - this._timelineGrid.addEventDivider(element); - this._eventDividers.push({time: times[i], element: element}); - } - // Update event dividers immediately - this._updateEventDividers(); - // Schedule refresh in case dividers change the calculator span. - this._scheduleRefresh(); - }, - - _updateEventDividers: function() - { - var calculator = this.calculator(); - for (var divider of this._eventDividers) { - var timePercent = calculator.computePercentageFromEventTime(divider.time); - divider.element.classList.toggle("invisible", timePercent < 0); - divider.element.style.left = timePercent + "%"; - } - }, - _refreshIfNeeded: function() { if (this._needsRefresh) @@ -898,7 +507,7 @@ /** * @param {!WebInspector.NetworkTimeCalculator} x */ - _setCalculator: function(x) + setCalculator: function(x) { if (!x || this._calculator === x) return; @@ -907,9 +516,9 @@ this._calculator.reset(); if (this._calculator.startAtZero) - this._timelineGrid.hideEventDividers(); + this._columns.hideEventDividers(); else - this._timelineGrid.showEventDividers(); + this._columns.showEventDividers(); this._invalidateAllItems(); }, @@ -925,7 +534,7 @@ var data = /** @type {number} */ (event.data); if (data) { this._mainRequestLoadTime = data; - this._addEventDividers([data], "network-red-divider"); + this._columns.addEventDividers([data], "network-red-divider"); } }, @@ -939,7 +548,7 @@ var data = /** @type {number} */ (event.data); if (data) { this._mainRequestDOMContentLoadedTime = data; - this._addEventDividers([data], "network-blue-divider"); + this._columns.addEventDividers([data], "network-blue-divider"); } }, @@ -950,7 +559,7 @@ willHide: function() { - this._popoverHelper.hidePopover(); + this._columns.willHide(); }, refresh: function() @@ -961,7 +570,7 @@ delete this._refreshTimeout; } - this._removeAllNodeHighlights(); + this.removeAllNodeHighlights(); var oldBoundary = this.calculator().boundary(); this._timeCalculator.updateBoundariesForEventTime(this._mainRequestLoadTime); @@ -1010,7 +619,7 @@ if (!this.calculator().boundary().equals(oldBoundary)) { // The boundaries changed, so all item graphs are stale. - this._updateDividersIfNeeded(); + this._columns.updateDividersIfNeeded(); var nodes = this._nodesByRequestId.valuesArray(); for (var i = 0; i < nodes.length; ++i) nodes[i].refreshGraph(); @@ -1026,8 +635,8 @@ this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.RequestSelected, null); this._clearSearchMatchedList(); - if (this._popoverHelper) - this._popoverHelper.hidePopover(); + + this._columns.reset(); this._timeFilter = null; this._calculator.reset(); @@ -1045,11 +654,9 @@ this._mainRequestLoadTime = -1; this._mainRequestDOMContentLoadedTime = -1; this._eventDividers = []; - this._timelineGrid.removeEventDividers(); if (this._dataGrid) { this._dataGrid.rootNode().removeChildren(); - this._updateDividersIfNeeded(); this._updateSummaryBar(); } }, @@ -1150,7 +757,7 @@ this._staleRequestIds[request.requestId] = true; this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.UpdateRequest, request); - this._scheduleRefresh(); + this.scheduleRefresh(); }, /** @@ -1166,7 +773,8 @@ // Pick provisional load requests. var requestsToPick = []; - var requests = frame.target().networkLog.requests(); + var networkLog = WebInspector.NetworkLog.fromTarget(frame.target()); + var requests = networkLog ? networkLog.requests() : []; for (var i = 0; i < requests.length; ++i) { var request = requests[i]; if (request.loaderId === loaderId) @@ -1193,20 +801,7 @@ */ switchViewMode: function(gridMode) { - if (this._gridMode === gridMode) - return; - this._gridMode = gridMode; - - if (gridMode) { - if (this._dataGrid.selectedNode) - this._dataGrid.selectedNode.selected = false; - } else { - this._removeAllNodeHighlights(); - this._popoverHelper.hidePopover(); - } - - this.element.classList.toggle("brief-mode", !gridMode); - this._updateColumns(); + this._columns.switchViewMode(gridMode); }, /** @@ -1222,120 +817,18 @@ var largeRows = !!this._networkLogLargeRowsSetting.get(); this._rowHeight = largeRows ? 41 : 21; this._dataGrid.element.classList.toggle("small", !largeRows); - this._timelineGrid.element.classList.toggle("small", !largeRows); this._dataGrid.scheduleUpdate(); }, /** - * @param {!Element} element - * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} - */ - _getPopoverAnchor: function(element, event) - { - if (!this._gridMode) - return; - var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label"); - if (anchor && anchor.parentElement.request && anchor.parentElement.request.timing) - return anchor; - anchor = element.enclosingNodeOrSelfWithClass("network-script-initiated"); - if (anchor && anchor.request) { - var initiator = /** @type {!WebInspector.NetworkRequest} */ (anchor.request).initiator(); - if (initiator && initiator.stack) - return anchor; - } - }, - - /** - * @param {!Element} anchor - * @param {!WebInspector.Popover} popover - */ - _showPopover: function(anchor, popover) - { - var content; - if (anchor.classList.contains("network-script-initiated")) { - var request = /** @type {!WebInspector.NetworkRequest} */ (anchor.request); - var initiator = /** @type {!NetworkAgent.Initiator} */ (request.initiator()); - content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(request.target(), this._popupLinkifier, initiator.stack); - popover.setCanShrink(true); - } else { - content = WebInspector.RequestTimingView.createTimingTable(anchor.parentElement.request, this._timeCalculator.minimumBoundary()); - popover.setCanShrink(false); - } - popover.showForAnchor(content, anchor); - }, - - _onHidePopover: function() - { - this._popupLinkifier.reset(); - }, - - _updateColumns: function() - { - if (!this._dataGrid) - return; - var gridMode = this._gridMode; - var visibleColumns = {"name": true}; - if (gridMode) - visibleColumns["timeline"] = true; - if (gridMode) { - var columnsVisibility = this._columnsVisibilitySetting.get(); - for (var columnIdentifier in columnsVisibility) - visibleColumns[columnIdentifier] = columnsVisibility[columnIdentifier]; - } - - this._dataGrid.setColumnsVisiblity(visibleColumns); - }, - - /** - * @param {string} columnIdentifier - */ - _toggleColumnVisibility: function(columnIdentifier) - { - var columnsVisibility = this._columnsVisibilitySetting.get(); - columnsVisibility[columnIdentifier] = !columnsVisibility[columnIdentifier]; - this._columnsVisibilitySetting.set(columnsVisibility); - - this._updateColumns(); - }, - - /** - * @return {!Array.<string>} - */ - _getConfigurableColumnIDs: function() - { - if (this._configurableColumnIDs) - return this._configurableColumnIDs; - - var columnTitles = WebInspector.NetworkLogView._columnTitles; - function compare(id1, id2) - { - return columnTitles[id1].compareTo(columnTitles[id2]); - } - - var columnIDs = Object.keys(this._columnsVisibilitySetting.get()); - this._configurableColumnIDs = columnIDs.sort(compare); - return this._configurableColumnIDs; - }, - - /** * @param {!Event} event */ _contextMenu: function(event) { - var contextMenu = new WebInspector.ContextMenu(event); - - if (this._gridMode && event.target.isSelfOrDescendant(this._dataGrid.headerTableBody)) { - var columnsVisibility = this._columnsVisibilitySetting.get(); - var columnIDs = this._getConfigurableColumnIDs(); - var columnTitles = WebInspector.NetworkLogView._columnTitles; - for (var i = 0; i < columnIDs.length; ++i) { - var columnIdentifier = columnIDs[i]; - contextMenu.appendCheckboxItem(columnTitles[columnIdentifier], this._toggleColumnVisibility.bind(this, columnIdentifier), !!columnsVisibility[columnIdentifier]); - } - contextMenu.show(); + // TODO(allada) Fix datagrid's contextmenu so NetworkLogViewColumns can attach it's own contextmenu event + if (this._columns.contextMenu(event)) return; - } + var contextMenu = new WebInspector.ContextMenu(event); var gridNode = this._dataGrid.dataGridNodeFromNode(event.target); var request = gridNode && gridNode.request(); @@ -1514,12 +1007,17 @@ _removeAllHighlights: function() { - this._removeAllNodeHighlights(); + this.removeAllNodeHighlights(); for (var i = 0; i < this._highlightedSubstringChanges.length; ++i) WebInspector.revertDomChanges(this._highlightedSubstringChanges[i]); this._highlightedSubstringChanges = []; }, + dataGridSorted: function() + { + this._highlightNthMatchedRequestForSearch(this._updateMatchCountAndFindMatchIndex(this._currentMatchedRequestNode), false); + }, + /** * @param {number} n * @param {boolean} reveal @@ -1826,7 +1324,7 @@ */ revealAndHighlightRequest: function(request) { - this._removeAllNodeHighlights(); + this.removeAllNodeHighlights(); var node = this._nodesByRequestId.get(request.requestId); if (node) { @@ -1835,7 +1333,7 @@ } }, - _removeAllNodeHighlights: function() + removeAllNodeHighlights: function() { if (this._highlightedNode) { this._highlightedNode.element().classList.remove("highlighted-row");
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js new file mode 100644 index 0000000..0355e2d --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -0,0 +1,618 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @constructor + * @param {!WebInspector.NetworkLogView} networkLogView + * @param {!WebInspector.Setting} networkLogLargeRowsSetting + */ +WebInspector.NetworkLogViewColumns = function(networkLogView, networkLogLargeRowsSetting) +{ + this._networkLogView = networkLogView; + + var defaultColumnsVisibility = WebInspector.NetworkLogViewColumns._defaultColumnsVisibility; + /** @type {!WebInspector.Setting} */ + this._columnsVisibilitySetting = WebInspector.settings.createSetting("networkLogColumnsVisibility", defaultColumnsVisibility); + var savedColumnsVisibility = this._columnsVisibilitySetting.get(); + /** @type {!Object.<boolean>} */ + var columnsVisibility = {}; + for (var columnId in defaultColumnsVisibility) + columnsVisibility[columnId] = savedColumnsVisibility.hasOwnProperty(columnId) ? savedColumnsVisibility[columnId] : defaultColumnsVisibility[columnId]; + this._columnsVisibilitySetting.set(columnsVisibility); + + networkLogLargeRowsSetting.addChangeListener(this._updateRowsSize, this); + + /** @type {!Array<{time: number, element: !Element}>} */ + this._eventDividers = []; + + this._gridMode = true; + + /** @type {?WebInspector.DataGrid} */ + this._dataGrid = null; + /** @type {!Array.<!WebInspector.ColumnConfig>} */ + this._columns = []; + /** @type {!Object.<string, function(!WebInspector.NetworkDataGridNode, !WebInspector.NetworkDataGridNode) : number>} */ + this._sortingFunctions = {}; + /** @type {!Object.<string, !WebInspector.NetworkTimeCalculator>} */ + this._calculators = {}; + /** @type {?Element} */ + this._timelineSortSelector = null; + + /** @type {?WebInspector.TimelineGrid} */ + this._timelineGrid = null; + + /** @type {!WebInspector.Linkifier} */ + this._popupLinkifier = new WebInspector.Linkifier(); +} + +WebInspector.NetworkLogViewColumns._responseHeaderColumns = ["Cache-Control", "Connection", "Content-Encoding", "Content-Length", "ETag", "Keep-Alive", "Last-Modified", "Server", "Vary"]; +WebInspector.NetworkLogViewColumns._defaultColumnsVisibility = { + method: false, status: true, protocol: false, scheme: false, domain: false, remoteAddress: false, type: true, initiator: true, cookies: false, setCookies: false, size: true, time: true, priority: false, connectionId: false, + "Cache-Control": false, "Connection": false, "Content-Encoding": false, "Content-Length": false, "ETag": false, "Keep-Alive": false, "Last-Modified": false, "Server": false, "Vary": false +}; + +/** + * @typedef {{ + * id: string, + * title: string, + * titleDOMFragment: !DocumentFragment, + * sortable: boolean, + * weight: number, + * sort: (?WebInspector.DataGrid.Order|undefined), + * align: (?WebInspector.DataGrid.Align|undefined), + * }} + */ +WebInspector.ColumnConfig; + +/** @type {!Object.<string, string>} */ +WebInspector.NetworkLogViewColumns._columnTitles = { + "name": WebInspector.UIString("Name"), + "method": WebInspector.UIString("Method"), + "status": WebInspector.UIString("Status"), + "protocol": WebInspector.UIString("Protocol"), + "scheme": WebInspector.UIString("Scheme"), + "domain": WebInspector.UIString("Domain"), + "remoteAddress": WebInspector.UIString("Remote Address"), + "type": WebInspector.UIString("Type"), + "initiator": WebInspector.UIString("Initiator"), + "cookies": WebInspector.UIString("Cookies"), + "setCookies": WebInspector.UIString("Set-Cookies"), + "size": WebInspector.UIString("Size"), + "time": WebInspector.UIString("Time"), + "connectionId": WebInspector.UIString("Connection Id"), + "priority": WebInspector.UIString("Priority"), + "timeline": WebInspector.UIString("Timeline"), + + // Response header columns + "Cache-Control": WebInspector.UIString("Cache-Control"), + "Connection": WebInspector.UIString("Connection"), + "Content-Encoding": WebInspector.UIString("Content-Encoding"), + "Content-Length": WebInspector.UIString("Content-Length"), + "ETag": WebInspector.UIString("ETag"), + "Keep-Alive": WebInspector.UIString("Keep-Alive"), + "Last-Modified": WebInspector.UIString("Last-Modified"), + "Server": WebInspector.UIString("Server"), + "Vary": WebInspector.UIString("Vary") +}; + +WebInspector.NetworkLogViewColumns.prototype = { + willHide: function() + { + this._popoverHelper.hidePopover(); + }, + + reset: function() + { + if (this._popoverHelper) + this._popoverHelper.hidePopover(); + this._timelineGrid.removeEventDividers(); + this.updateDividersIfNeeded(); + }, + + /** + * @param {!WebInspector.NetworkTransferTimeCalculator} timeCalculator + * @param {!WebInspector.NetworkTransferDurationCalculator} durationCalculator + * @return {!WebInspector.SortableDataGrid} dataGrid + */ + createGrid: function(timeCalculator, durationCalculator) + { + this._createSortingFunctions(); + this._popoverHelper = new WebInspector.PopoverHelper(this._networkLogView.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), this._onHidePopover.bind(this)); + + this._calculators.timeline = timeCalculator; + this._calculators.startTime = timeCalculator; + this._calculators.endTime = timeCalculator; + this._calculators.responseTime = timeCalculator; + this._calculators.duration = durationCalculator; + this._calculators.latency = durationCalculator; + + var columns = []; + columns.push({ + id: "name", + titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path")), + title: WebInspector.NetworkLogViewColumns._columnTitles["name"], + weight: 20 + }); + + columns.push({ + id: "method", + title: WebInspector.NetworkLogViewColumns._columnTitles["method"], + weight: 6 + }); + + columns.push({ + id: "status", + titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text")), + title: WebInspector.NetworkLogViewColumns._columnTitles["status"], + weight: 6 + }); + + columns.push({ + id: "protocol", + title: WebInspector.NetworkLogViewColumns._columnTitles["protocol"], + weight: 6 + }); + + columns.push({ + id: "scheme", + title: WebInspector.NetworkLogViewColumns._columnTitles["scheme"], + weight: 6 + }); + + columns.push({ + id: "domain", + title: WebInspector.NetworkLogViewColumns._columnTitles["domain"], + weight: 6 + }); + + columns.push({ + id: "remoteAddress", + title: WebInspector.NetworkLogViewColumns._columnTitles["remoteAddress"], + weight: 10, + align: WebInspector.DataGrid.Align.Right + }); + + columns.push({ + id: "type", + title: WebInspector.NetworkLogViewColumns._columnTitles["type"], + weight: 6 + }); + + columns.push({ + id: "initiator", + title: WebInspector.NetworkLogViewColumns._columnTitles["initiator"], + weight: 10 + }); + + columns.push({ + id: "cookies", + title: WebInspector.NetworkLogViewColumns._columnTitles["cookies"], + weight: 6, + align: WebInspector.DataGrid.Align.Right + }); + + columns.push({ + id: "setCookies", + title: WebInspector.NetworkLogViewColumns._columnTitles["setCookies"], + weight: 6, + align: WebInspector.DataGrid.Align.Right + }); + + columns.push({ + id: "size", + titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Content")), + title: WebInspector.NetworkLogViewColumns._columnTitles["size"], + weight: 6, + align: WebInspector.DataGrid.Align.Right + }); + + columns.push({ + id: "time", + titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Latency")), + title: WebInspector.NetworkLogViewColumns._columnTitles["time"], + weight: 6, + align: WebInspector.DataGrid.Align.Right + }); + + columns.push({ + id: "priority", + title: WebInspector.NetworkLogViewColumns._columnTitles["priority"], + weight: 6 + }); + + columns.push({ + id: "connectionId", + title: WebInspector.NetworkLogViewColumns._columnTitles["connectionId"], + weight: 6 + }); + + var responseHeaderColumns = WebInspector.NetworkLogViewColumns._responseHeaderColumns; + for (var i = 0; i < responseHeaderColumns.length; ++i) { + var headerName = responseHeaderColumns[i]; + var descriptor = { + id: headerName, + title: WebInspector.NetworkLogViewColumns._columnTitles[headerName], + weight: 6 + }; + if (headerName === "Content-Length") + descriptor.align = WebInspector.DataGrid.Align.Right; + columns.push(descriptor); + } + + columns.push({ + id: "timeline", + title: WebInspector.NetworkLogViewColumns._columnTitles["timeline"], + sortable: false, + weight: 40, + sort: WebInspector.DataGrid.Order.Ascending + }); + + for (var column of columns) { + column.sortable = column.id !== "timeline"; + column.nonSelectable = column.id !== "name"; + } + this._columns = columns; + + this._networkLogView.switchViewMode(true); + + this._dataGrid = new WebInspector.SortableDataGrid(this._columns); + + this._dataGrid.asWidget().show(this._networkLogView.element); + + this._timelineGrid = new WebInspector.TimelineGrid(); + this._timelineGrid.element.classList.add("network-timeline-grid"); + this._dataGrid.element.appendChild(this._timelineGrid.element); + + this._updateColumns(); + this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortItems, this); + this._dataGrid.sortNodes(this._sortingFunctions.startTime, false); + this._patchTimelineHeader(); + + this._dataGrid.addEventListener(WebInspector.DataGrid.Events.ColumnsResized, this.updateDividersIfNeeded, this); + + return this._dataGrid; + }, + + _createSortingFunctions: function() + { + this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator; + this._sortingFunctions.method = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "requestMethod"); + this._sortingFunctions.status = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "statusCode"); + this._sortingFunctions.protocol = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "protocol"); + this._sortingFunctions.scheme = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "scheme"); + this._sortingFunctions.domain = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "domain"); + this._sortingFunctions.remoteAddress = WebInspector.NetworkDataGridNode.RemoteAddressComparator; + this._sortingFunctions.type = WebInspector.NetworkDataGridNode.TypeComparator; + this._sortingFunctions.initiator = WebInspector.NetworkDataGridNode.InitiatorComparator; + this._sortingFunctions.cookies = WebInspector.NetworkDataGridNode.RequestCookiesCountComparator; + this._sortingFunctions.setCookies = WebInspector.NetworkDataGridNode.ResponseCookiesCountComparator; + this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator; + this._sortingFunctions.time = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "duration"); + this._sortingFunctions.connectionId = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "connectionId"); + this._sortingFunctions.priority = WebInspector.NetworkDataGridNode.InitialPriorityComparator; + this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "startTime"); + this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "startTime"); + this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "endTime"); + this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "responseReceivedTime"); + this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "duration"); + this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "latency"); + + this._sortingFunctions["Cache-Control"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Cache-Control"); + this._sortingFunctions["Connection"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Connection"); + this._sortingFunctions["Content-Encoding"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Content-Encoding"); + this._sortingFunctions["Content-Length"] = WebInspector.NetworkDataGridNode.ResponseHeaderNumberComparator.bind(null, "Content-Length"); + this._sortingFunctions["ETag"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "ETag"); + this._sortingFunctions["Keep-Alive"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Keep-Alive"); + this._sortingFunctions["Last-Modified"] = WebInspector.NetworkDataGridNode.ResponseHeaderDateComparator.bind(null, "Last-Modified"); + this._sortingFunctions["Server"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Server"); + this._sortingFunctions["Vary"] = WebInspector.NetworkDataGridNode.ResponseHeaderStringComparator.bind(null, "Vary"); + }, + + _sortItems: function() + { + this._networkLogView.removeAllNodeHighlights(); + var columnIdentifier = this._dataGrid.sortColumnIdentifier(); + if (!columnIdentifier) + return; + if (columnIdentifier === "timeline") { + this._sortByTimeline(); + return; + } + var sortingFunction = this._sortingFunctions[columnIdentifier]; + if (!sortingFunction) + return; + + this._dataGrid.sortNodes(sortingFunction, !this._dataGrid.isSortOrderAscending()); + this._timelineSortSelector.selectedIndex = 0; + this._networkLogView.dataGridSorted(); + }, + + _sortByTimeline: function() + { + this._networkLogView.removeAllNodeHighlights(); + var selectedIndex = this._timelineSortSelector.selectedIndex; + if (!selectedIndex) + selectedIndex = 1; // Sort by start time by default. + var selectedOption = this._timelineSortSelector[selectedIndex]; + var value = selectedOption.value; + + this._networkLogView.setCalculator(this._calculators[value]); + var sortingFunction = this._sortingFunctions[value]; + this._dataGrid.sortNodes(sortingFunction); + + this._networkLogView.dataGridSorted(); + + this._dataGrid.markColumnAsSortedBy("timeline", selectedOption.sortOrder); + }, + + _patchTimelineHeader: function() + { + var timelineSorting = createElement("select"); + + var option = createElement("option"); + option.value = "startTime"; + option.label = WebInspector.UIString("Timeline"); + option.disabled = true; + timelineSorting.appendChild(option); + + option = createElement("option"); + option.value = "startTime"; + option.label = WebInspector.UIString("Timeline \u2013 Start Time"); + option.sortOrder = WebInspector.DataGrid.Order.Ascending; + timelineSorting.appendChild(option); + + option = createElement("option"); + option.value = "responseTime"; + option.label = WebInspector.UIString("Timeline \u2013 Response Time"); + option.sortOrder = WebInspector.DataGrid.Order.Ascending; + timelineSorting.appendChild(option); + + option = createElement("option"); + option.value = "endTime"; + option.label = WebInspector.UIString("Timeline \u2013 End Time"); + option.sortOrder = WebInspector.DataGrid.Order.Ascending; + timelineSorting.appendChild(option); + + option = createElement("option"); + option.value = "duration"; + option.label = WebInspector.UIString("Timeline \u2013 Total Duration"); + option.sortOrder = WebInspector.DataGrid.Order.Descending; + timelineSorting.appendChild(option); + + option = createElement("option"); + option.value = "latency"; + option.label = WebInspector.UIString("Timeline \u2013 Latency"); + option.sortOrder = WebInspector.DataGrid.Order.Descending; + timelineSorting.appendChild(option); + + var header = this._dataGrid.headerTableHeader("timeline"); + header.replaceChild(timelineSorting, header.firstChild); + header.createChild("div", "sort-order-icon-container").createChild("div", "sort-order-icon"); + + timelineSorting.selectedIndex = 1; + timelineSorting.addEventListener("click", function(event) { event.consume(); }, false); + timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false); + this._timelineSortSelector = timelineSorting; + }, + + _updateColumns: function() + { + if (!this._dataGrid) + return; + var gridMode = this._gridMode; + var visibleColumns = {"name": true}; + if (gridMode) + visibleColumns["timeline"] = true; + if (gridMode) { + var columnsVisibility = this._columnsVisibilitySetting.get(); + for (var columnIdentifier in columnsVisibility) + visibleColumns[columnIdentifier] = columnsVisibility[columnIdentifier]; + } + + this._dataGrid.setColumnsVisiblity(visibleColumns); + }, + + /** + * @param {boolean} gridMode + */ + switchViewMode: function(gridMode) + { + if (this._gridMode === gridMode) + return; + this._gridMode = gridMode; + + if (gridMode) { + if (this._dataGrid.selectedNode) + this._dataGrid.selectedNode.selected = false; + } else { + this._networkLogView.removeAllNodeHighlights(); + this._popoverHelper.hidePopover(); + } + + this._networkLogView.element.classList.toggle("brief-mode", !gridMode); + this._updateColumns(); + }, + + /** + * @param {string} columnIdentifier + */ + _toggleColumnVisibility: function(columnIdentifier) + { + var columnsVisibility = this._columnsVisibilitySetting.get(); + columnsVisibility[columnIdentifier] = !columnsVisibility[columnIdentifier]; + this._columnsVisibilitySetting.set(columnsVisibility); + + this._updateColumns(); + }, + + /** + * @return {!Array.<string>} + */ + _getConfigurableColumnIDs: function() + { + if (this._configurableColumnIDs) + return this._configurableColumnIDs; + + var columnTitles = WebInspector.NetworkLogViewColumns._columnTitles; + function compare(id1, id2) + { + return columnTitles[id1].compareTo(columnTitles[id2]); + } + + var columnIDs = Object.keys(this._columnsVisibilitySetting.get()); + this._configurableColumnIDs = columnIDs.sort(compare); + return this._configurableColumnIDs; + }, + + /** + * @param {string} title + * @param {string} subtitle + * @return {!DocumentFragment} + */ + _makeHeaderFragment: function(title, subtitle) + { + var fragment = createDocumentFragment(); + fragment.createTextChild(title); + var subtitleDiv = fragment.createChild("div", "network-header-subtitle"); + subtitleDiv.createTextChild(subtitle); + return fragment; + }, + + /** + * @param {!Event} event + * @return {boolean} + */ + contextMenu: function(event) + { + if (!this._gridMode || !event.target.isSelfOrDescendant(this._dataGrid.headerTableBody)) + return false; + + var contextMenu = new WebInspector.ContextMenu(event); + + var columnsVisibility = this._columnsVisibilitySetting.get(); + var columnIDs = this._getConfigurableColumnIDs(); + var columnTitles = WebInspector.NetworkLogViewColumns._columnTitles; + for (var i = 0; i < columnIDs.length; ++i) { + var columnIdentifier = columnIDs[i]; + contextMenu.appendCheckboxItem(columnTitles[columnIdentifier], this._toggleColumnVisibility.bind(this, columnIdentifier), !!columnsVisibility[columnIdentifier]); + } + contextMenu.show(); + return true; + }, + + updateDividersIfNeeded: function() + { + if (!this._networkLogView.isShowing()) { + this._networkLogView.scheduleRefresh(); + return; + } + + var timelineOffset = this._dataGrid.columnOffset("timeline"); + // Position timline grid location. + if (timelineOffset) + this._timelineGrid.element.style.left = timelineOffset + "px"; + + var calculator = this._networkLogView.calculator(); + calculator.setDisplayWindow(this._timelineGrid.dividersElement.clientWidth); + this._timelineGrid.updateDividers(calculator, 75); + + if (calculator.startAtZero) { + // If our current sorting method starts at zero, that means it shows all + // requests starting at the same point, and so onLoad event and DOMContent + // event lines really wouldn't make much sense here, so don't render them. + return; + } + + this._updateEventDividers(); + }, + + /** + * @param {!Element} element + * @param {!Event} event + * @return {!Element|!AnchorBox|undefined} + */ + _getPopoverAnchor: function(element, event) + { + if (!this._gridMode) + return; + var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label"); + if (anchor && anchor.parentElement.request && anchor.parentElement.request.timing) + return anchor; + anchor = element.enclosingNodeOrSelfWithClass("network-script-initiated"); + if (anchor && anchor.request) { + var initiator = /** @type {!WebInspector.NetworkRequest} */ (anchor.request).initiator(); + if (initiator && initiator.stack) + return anchor; + } + }, + + /** + * @param {!Element} anchor + * @param {!WebInspector.Popover} popover + */ + _showPopover: function(anchor, popover) + { + var content; + if (anchor.classList.contains("network-script-initiated")) { + var request = /** @type {!WebInspector.NetworkRequest} */ (anchor.request); + var initiator = /** @type {!NetworkAgent.Initiator} */ (request.initiator()); + content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(request.target(), this._popupLinkifier, initiator.stack); + popover.setCanShrink(true); + } else { + content = WebInspector.RequestTimingView.createTimingTable(anchor.parentElement.request, this._networkLogView.timeCalculator().minimumBoundary()); + popover.setCanShrink(false); + } + popover.showForAnchor(content, anchor); + }, + + _onHidePopover: function() + { + this._popupLinkifier.reset(); + }, + + /** + * @param {!Array<number>} times + * @param {string} className + */ + addEventDividers: function(times, className) + { + for (var i = 0; i < times.length; ++i) { + var element = createElementWithClass("div", "network-event-divider " + className); + this._timelineGrid.addEventDivider(element); + this._eventDividers.push({time: times[i], element: element}); + } + // Update event dividers immediately + this._updateEventDividers(); + // Schedule refresh in case dividers change the calculator span. + this._networkLogView.scheduleRefresh(); + }, + + _updateEventDividers: function() + { + var calculator = this._networkLogView.calculator(); + for (var divider of this._eventDividers) { + var timePercent = calculator.computePercentageFromEventTime(divider.time); + divider.element.classList.toggle("invisible", timePercent < 0); + divider.element.style.left = timePercent + "%"; + } + }, + + hideEventDividers: function() + { + this._timelineGrid.hideEventDividers(); + }, + + showEventDividers: function() + { + this._timelineGrid.showEventDividers(); + }, + + /** + * @param {!WebInspector.Event} event + */ + _updateRowsSize: function(event) + { + this._timelineGrid.element.classList.toggle("small", !event.data); + } +} \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/network/module.json b/third_party/WebKit/Source/devtools/front_end/network/module.json index 8e1945e5..63f5ac7 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/module.json +++ b/third_party/WebKit/Source/devtools/front_end/network/module.json
@@ -107,6 +107,7 @@ "NetworkItemView.js", "NetworkTimeCalculator.js", "NetworkLogView.js", + "NetworkLogViewColumns.js", "NetworkOverview.js", "RequestCookiesView.js", "RequestHeadersView.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js index f8ac937..1f3dae0 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
@@ -384,7 +384,7 @@ case "key": case "primaryKey": cell.removeChildren(); - var objectElement = WebInspector.ObjectPropertiesSection.defaultObjectPresentation(value, true); + var objectElement = WebInspector.ObjectPropertiesSection.defaultObjectPresentation(value, undefined, true); cell.appendChild(objectElement); break; default:
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js index 2ff6091..74c4c81 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
@@ -37,9 +37,12 @@ this._toolbar.appendToolbarItem(WebInspector.NetworkConditionsSelector.createOfflineToolbarCheckbox()); var forceUpdate = new WebInspector.ToolbarCheckbox(WebInspector.UIString("Update on reload"), WebInspector.UIString("Force update Service Worker on page reload"), this._manager.forceUpdateOnReloadSetting()); this._toolbar.appendToolbarItem(forceUpdate); - var fallbackToNetwork = new WebInspector.ToolbarCheckbox(WebInspector.UIString("Bypass for network"), WebInspector.UIString("Bypass Service Worker and load resources from the network"), target.networkManager.bypassServiceWorkerSetting()); - this._toolbar.appendToolbarItem(fallbackToNetwork); - this._toolbar.appendSpacer(); + var networkManager = this._target && WebInspector.NetworkManager.fromTarget(this._target); + if (networkManager) { + var fallbackToNetwork = new WebInspector.ToolbarCheckbox(WebInspector.UIString("Bypass for network"), WebInspector.UIString("Bypass Service Worker and load resources from the network"), networkManager.bypassServiceWorkerSetting()); + this._toolbar.appendToolbarItem(fallbackToNetwork); + this._toolbar.appendSpacer(); + } this._showAllCheckbox = new WebInspector.ToolbarCheckbox(WebInspector.UIString("Show all"), WebInspector.UIString("Show all Service Workers regardless of the origin")); this._showAllCheckbox.inputElement.addEventListener("change", this._updateSectionVisibility.bind(this), false); this._toolbar.appendToolbarItem(this._showAllCheckbox);
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js index dea9998..5ee2239f 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
@@ -260,7 +260,7 @@ var originalAndDetach = originalAndDetachIfSuccess.bind(this, header); if (!sourceMap.editable()) - return originalAndDetach(); + return original(); return /** @type {!Promise<boolean>} */(sourceMap.editCompiled([range], [text]) .then(onEditingDone.bind(this)) @@ -418,7 +418,7 @@ return false; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, range, text, selectorPayload); - this._fireStyleSheetChangedAndDetach(styleSheetId, edit); + this._fireStyleSheetChanged(styleSheetId, edit); return true; } @@ -448,7 +448,7 @@ return false; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, range, text, payload); - this._fireStyleSheetChangedAndDetach(styleSheetId, edit); + this._fireStyleSheetChanged(styleSheetId, edit); return true; } @@ -682,7 +682,7 @@ return false; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, range, newMediaText, mediaPayload); - this._fireStyleSheetChangedAndDetach(styleSheetId, edit); + this._fireStyleSheetChanged(styleSheetId, edit); return true; } @@ -716,7 +716,7 @@ return null; this._domModel.markUndoableState(); var edit = new WebInspector.CSSModel.Edit(styleSheetId, ruleLocation, ruleText, rulePayload); - this._fireStyleSheetChangedAndDetach(styleSheetId, edit); + this._fireStyleSheetChanged(styleSheetId, edit); return new WebInspector.CSSStyleRule(this, rulePayload); } }, @@ -786,18 +786,6 @@ /** * @param {!CSSAgent.StyleSheetId} styleSheetId - * @param {!WebInspector.CSSModel.Edit=} edit - */ - _fireStyleSheetChangedAndDetach: function(styleSheetId, edit) - { - this.dispatchEventToListeners(WebInspector.CSSModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, edit: edit }); - var header = this.styleSheetHeaderForId(styleSheetId); - if (header) - this._detachSourceMap(header); - }, - - /** - * @param {!CSSAgent.StyleSheetId} styleSheetId * @return {!Promise<string>} */ _ensureOriginalStyleSheetText: function(styleSheetId) @@ -1096,7 +1084,7 @@ */ styleSheetChanged: function(styleSheetId) { - this._cssModel._fireStyleSheetChangedAndDetach(styleSheetId); + this._cssModel._fireStyleSheetChanged(styleSheetId); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js index 782a8d1..523ecabc 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
@@ -269,7 +269,8 @@ this._messageId = messageId || 0; this._relatedMessageId = relatedMessageId || 0; - this.request = requestId ? target.networkLog.requestForId(requestId) : null; + var networkLog = target && WebInspector.NetworkLog.fromTarget(target); + this.request = (requestId && networkLog) ? networkLog.requestForId(requestId) : null; if (this.request) { var initiator = this.request.initiator();
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index d8fa712..aa928e59 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -39,7 +39,6 @@ target.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this)); this._agent = target.debuggerAgent(); - WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.TargetDisposed, this._targetDisposed, this); /** @type {?WebInspector.DebuggerPausedDetails} */ this._debuggerPausedDetails = null; @@ -62,9 +61,6 @@ /** @typedef {{location: ?WebInspector.DebuggerModel.Location, sourceURL: ?string, functionName: string, scopeChain: (Array.<!DebuggerAgent.Scope>|null)}} */ WebInspector.DebuggerModel.FunctionDetails; -/** @typedef {{location: ?WebInspector.DebuggerModel.Location, sourceURL: ?string, functionName: string, status: string}} */ -WebInspector.DebuggerModel.GeneratorObjectDetails; - /** * Keep these in sync with WebCore::V8Debugger * @@ -717,34 +713,6 @@ }, /** - * @param {!WebInspector.RemoteObject} remoteObject - * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback - */ - generatorObjectDetails: function(remoteObject, callback) - { - this._agent.getGeneratorObjectDetails(remoteObject.objectId, didGetDetails.bind(this)); - - /** - * @param {?Protocol.Error} error - * @param {!DebuggerAgent.GeneratorObjectDetails} response - * @this {WebInspector.DebuggerModel} - */ - function didGetDetails(error, response) - { - if (error) { - console.error(error); - callback(null); - return; - } - var location = response.location; - var script = location && this.scriptForId(location.scriptId); - var rawLocation = script ? this.createRawLocation(script, location.lineNumber, location.columnNumber || 0) : null; - var sourceURL = script ? script.contentURL() : null; - callback({location: rawLocation, sourceURL: sourceURL, functionName: response.functionName, status: response.status}); - } - }, - - /** * @param {!DebuggerAgent.BreakpointId} breakpointId * @param {function(!WebInspector.Event)} listener * @param {!Object=} thisObject @@ -786,14 +754,8 @@ } }, - /** - * @param {!WebInspector.Event} event - */ - _targetDisposed: function(event) + dispose: function() { - var target = /** @type {!WebInspector.Target} */ (event.data); - if (target !== this.target()) - return; WebInspector.moduleSetting("pauseOnExceptionEnabled").removeChangeListener(this._pauseOnExceptionStateChanged, this); WebInspector.moduleSetting("pauseOnCaughtException").removeChangeListener(this._pauseOnExceptionStateChanged, this); WebInspector.moduleSetting("enableAsyncStackTraces").removeChangeListener(this.asyncStackTracesStateChanged, this);
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/HAREntry.js b/third_party/WebKit/Source/devtools/front_end/sdk/HAREntry.js index 5219b89..5978ef00 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/HAREntry.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/HAREntry.js
@@ -66,7 +66,7 @@ if (this._request.connectionId !== "0") entry.connection = this._request.connectionId; - var page = this._request.target().networkLog.pageLoadForRequest(this._request); + var page = this._request.networkLog().pageLoadForRequest(this._request); if (page) entry.pageref = "page_" + page.id; return entry; @@ -328,7 +328,7 @@ var pages = []; for (var i = 0; i < this._requests.length; ++i) { var request = this._requests[i]; - var page = request.target().networkLog.pageLoadForRequest(request); + var page = request.networkLog().pageLoadForRequest(request); if (!page || seenIdentifiers[page.id]) continue; seenIdentifiers[page.id] = true;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js index 7c0afd8..35c0860 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkLog.js
@@ -30,29 +30,40 @@ /** * @constructor - * @extends {WebInspector.SDKObject} + * @extends {WebInspector.SDKModel} * @param {!WebInspector.Target} target + * @param {!WebInspector.NetworkManager} networkManager */ -WebInspector.NetworkLog = function(target) +WebInspector.NetworkLog = function(target, networkManager) { - WebInspector.SDKObject.call(this, target); + WebInspector.SDKModel.call(this, WebInspector.NetworkLog, target); this._requests = []; this._requestForId = {}; - target.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this); target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this); target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.Load, this._onLoad, this); target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._onDOMContentLoaded, this); } /** + * @param {!WebInspector.Target} target + * @return {?WebInspector.NetworkLog} + */ +WebInspector.NetworkLog.fromTarget = function(target) +{ + return /** @type {?WebInspector.NetworkLog} */ (target.model(WebInspector.NetworkLog)); +} + +/** * @param {string} url * @return {?WebInspector.NetworkRequest} */ WebInspector.NetworkLog.requestForURL = function(url) { for (var target of WebInspector.targetManager.targets()) { - var result = target.networkLog.requestForURL(url); + var networkLog = WebInspector.NetworkLog.fromTarget(target); + var result = networkLog && networkLog.requestForURL(url); if (result) return result; } @@ -66,7 +77,9 @@ { var result = []; for (var target of WebInspector.targetManager.targets()) { - result = result.concat(target.networkLog.requests()); + var networkLog = WebInspector.NetworkLog.fromTarget(target); + if (networkLog) + result = result.concat(networkLog.requests()); } return result; } @@ -162,7 +175,7 @@ return this._requestForId[requestId]; }, - __proto__: WebInspector.SDKObject.prototype + __proto__: WebInspector.SDKModel.prototype } /**
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 a8da7ce..811ee9b 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -81,6 +81,15 @@ "text/vtt": {"texttrack": true}, } +/** + * @param {!WebInspector.Target} target + * @return {?WebInspector.NetworkManager} + */ +WebInspector.NetworkManager.fromTarget = function(target) +{ + return /** @type {?WebInspector.NetworkManager} */ (target.model(WebInspector.NetworkManager)); +} + /** @typedef {{download: number, upload: number, latency: number, title: string}} */ WebInspector.NetworkManager.Conditions; /** @type {!WebInspector.NetworkManager.Conditions} */
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js index 2ed32a5..ffcbb8e3 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
@@ -44,6 +44,8 @@ { WebInspector.SDKObject.call(this, target); + this._networkLog = /** @type {!WebInspector.NetworkLog} */ (WebInspector.NetworkLog.fromTarget(target)); + this._networkManager = /** @type {!WebInspector.NetworkManager} */ (WebInspector.NetworkManager.fromTarget(target)); this._requestId = requestId; this.url = url; this._documentURL = documentURL; @@ -1124,7 +1126,7 @@ initiatorRequest: function() { if (this._initiatorRequest === undefined) - this._initiatorRequest = this.target().networkLog.requestForURL(this.initiatorInfo().url); + this._initiatorRequest = this._networkLog.requestForURL(this.initiatorInfo().url); return this._initiatorRequest; }, @@ -1207,5 +1209,21 @@ this.target().networkAgent().replayXHR(this.requestId); }, + /** + * @return {!WebInspector.NetworkLog} + */ + networkLog: function() + { + return this._networkLog; + }, + + /** + * @return {!WebInspector.NetworkManager} + */ + networkManager: function() + { + return this._networkManager; + }, + __proto__: WebInspector.SDKObject.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js index 5dd6a30..f59a6b0d 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -306,14 +306,6 @@ { this.functionDetails(success); } - }, - - /** - * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback - */ - generatorObjectDetails: function(callback) - { - callback(null); } } @@ -877,15 +869,6 @@ this._debuggerModel.functionDetails(this, callback); }, - /** - * @override - * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback - */ - generatorObjectDetails: function(callback) - { - this._debuggerModel.generatorObjectDetails(this, callback); - }, - __proto__: WebInspector.RemoteObject.prototype };
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js index 0539a60..8f5b5c55 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
@@ -32,13 +32,17 @@ * @constructor * @extends {WebInspector.SDKModel} * @param {!WebInspector.Target} target + * @param {?WebInspector.NetworkManager} networkManager */ -WebInspector.ResourceTreeModel = function(target) +WebInspector.ResourceTreeModel = function(target, networkManager) { WebInspector.SDKModel.call(this, WebInspector.ResourceTreeModel, target); - - target.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); - target.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, this._onRequestUpdateDropped, this); + if (networkManager) { + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, + this._onRequestFinished, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, + this._onRequestUpdateDropped, this); + } this._agent = target.pageAgent(); this._agent.enable();
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js index f79d7fb3..ebaf360 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js
@@ -34,7 +34,8 @@ WebInspector.Target.Type = { Page: 1, DedicatedWorker: 2, - ServiceWorker: 4 + ServiceWorker: 4, + JSInspector: 8 } WebInspector.Target._nextId = 1; @@ -106,7 +107,7 @@ */ isWorker: function() { - return this.isDedicatedWorker() || this.isServiceWorker(); + return this.isDedicatedWorker() || this.isServiceWorker() || this.isJSInspector(); }, /** @@ -128,12 +129,28 @@ /** * @return {boolean} */ + isJSInspector: function() + { + return this._type === WebInspector.Target.Type.JSInspector; + }, + + /** + * @return {boolean} + */ hasJSContext: function() { return !this.isServiceWorker(); }, /** + * @return {boolean} + */ + supportsWorkers: function() + { + return this.isPage() || this.isServiceWorker(); + }, + + /** * @return {?WebInspector.Target} */ parentTarget: function() @@ -150,9 +167,6 @@ _dispose: function() { this._targetManager.dispatchEventToListeners(WebInspector.TargetManager.Events.TargetDisposed, this); - this.networkManager.dispose(); - this.cpuProfilerModel.dispose(); - WebInspector.ServiceWorkerCacheModel.fromTarget(this).dispose(); if (this.workerManager) this.workerManager.dispose(); }, @@ -218,6 +232,7 @@ { WebInspector.SDKObject.call(this, target); target._modelByConstructor.set(modelClass, this); + WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.TargetDisposed, this._targetDisposed, this); } WebInspector.SDKModel.prototype = { @@ -237,5 +252,19 @@ return Promise.resolve(); }, + dispose: function() { }, + + /** + * @param {!WebInspector.Event} event + */ + _targetDisposed: function(event) + { + var target = /** @type {!WebInspector.Target} */ (event.data); + if (target !== this._target) + return; + this.dispose(); + WebInspector.targetManager.removeEventListener(WebInspector.TargetManager.Events.TargetDisposed, this._targetDisposed, this); + }, + __proto__: WebInspector.SDKObject.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js index 51994bd4..7e09dff 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
@@ -196,12 +196,16 @@ /** @type {!WebInspector.ConsoleModel} */ target.consoleModel = new WebInspector.ConsoleModel(target); - /** @type {!WebInspector.NetworkManager} */ - target.networkManager = new WebInspector.NetworkManager(target); + + var networkManager = null; + if (!target.isJSInspector()) + networkManager = new WebInspector.NetworkManager(target); + /** @type {!WebInspector.ResourceTreeModel} */ - target.resourceTreeModel = new WebInspector.ResourceTreeModel(target); - /** @type {!WebInspector.NetworkLog} */ - target.networkLog = new WebInspector.NetworkLog(target); + target.resourceTreeModel = new WebInspector.ResourceTreeModel(target, networkManager); + + if (networkManager) + new WebInspector.NetworkLog(target, networkManager); /** @type {!WebInspector.RuntimeModel} */ target.runtimeModel = new WebInspector.RuntimeModel(target); @@ -214,7 +218,7 @@ } /** @type {?WebInspector.WorkerManager} */ - target.workerManager = !target.isDedicatedWorker() ? new WebInspector.WorkerManager(target) : null; + target.workerManager = target.supportsWorkers() ? new WebInspector.WorkerManager(target) : null; /** @type {!WebInspector.CPUProfilerModel} */ target.cpuProfilerModel = new WebInspector.CPUProfilerModel(target); /** @type {!WebInspector.HeapProfilerModel} */
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js index 63927d4d4..a2bf52c 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -172,7 +172,7 @@ var securityDetails = request.securityDetails(); if (securityDetails) { originState.securityDetails = securityDetails; - originState.certificateDetailsPromise = request.target().networkManager.certificateDetailsPromise(securityDetails.certificateId); + originState.certificateDetailsPromise = request.networkManager().certificateDetailsPromise(securityDetails.certificateId); } this._origins.set(origin, originState); @@ -249,8 +249,11 @@ this._target = target; target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this); - target.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResponseReceived, this._onResponseReceived, this); - target.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); + var networkManager = WebInspector.NetworkManager.fromTarget(target); + if (networkManager) { + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResponseReceived, this._onResponseReceived, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); + } var securityModel = WebInspector.SecurityModel.fromTarget(target); securityModel.addEventListener(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, this._onSecurityStateChanged, this); @@ -553,7 +556,10 @@ this._panel = panel; this._summarySection = this.contentElement.createChild("div", "security-summary"); - this._securityExplanations = this.contentElement.createChild("div", "security-explanation-list"); + + // Info explanations should appear after all others. + this._securityExplanationsMain = this.contentElement.createChild("div", "security-explanation-list"); + this._securityExplanationsExtra = this.contentElement.createChild("div", "security-explanation-list security-explanations-extra"); // Fill the security summary section. this._summarySection.createChild("div", "security-summary-section-title").textContent = WebInspector.UIString("Security Overview"); @@ -572,12 +578,13 @@ WebInspector.SecurityMainView.prototype = { /** + * @param {!Element} parent * @param {!SecurityAgent.SecurityStateExplanation} explanation * @return {!Element} */ - _addExplanation: function(explanation) + _addExplanation: function(parent, explanation) { - var explanationSection = this._securityExplanations.createChild("div", "security-explanation"); + var explanationSection = parent.createChild("div", "security-explanation"); explanationSection.classList.add("security-explanation-" + explanation.securityState); explanationSection.createChild("div", "security-property").classList.add("security-property-" + explanation.securityState); @@ -627,9 +634,15 @@ refreshExplanations: function() { - this._securityExplanations.removeChildren(); - for (var explanation of this._explanations) - this._addExplanation(explanation); + this._securityExplanationsMain.removeChildren(); + this._securityExplanationsExtra.removeChildren(); + for (var explanation of this._explanations) { + if (explanation.securityState === SecurityAgent.SecurityState.Info) { + this._addExplanation(this._securityExplanationsExtra, explanation); + } else { + this._addExplanation(this._securityExplanationsMain, explanation); + } + } this._addMixedContentExplanations(); }, @@ -641,13 +654,13 @@ if (this._mixedContentStatus && (this._mixedContentStatus.ranInsecureContent || this._mixedContentStatus.displayedInsecureContent)) { if (this._mixedContentStatus.ranInsecureContent) - this._addMixedContentExplanation(this._mixedContentStatus.ranInsecureContentStyle, WebInspector.UIString("Active Mixed Content"), WebInspector.UIString("You have recently allowed insecure content (such as scripts or iframes) to run on this site."), WebInspector.NetworkLogView.MixedContentFilterValues.BlockOverridden, showBlockOverriddenMixedContentInNetworkPanel); + this._addMixedContentExplanation(this._securityExplanationsMain, this._mixedContentStatus.ranInsecureContentStyle, WebInspector.UIString("Active Mixed Content"), WebInspector.UIString("You have recently allowed insecure content (such as scripts or iframes) to run on this site."), WebInspector.NetworkLogView.MixedContentFilterValues.BlockOverridden, showBlockOverriddenMixedContentInNetworkPanel); if (this._mixedContentStatus.displayedInsecureContent) - this._addMixedContentExplanation(this._mixedContentStatus.displayedInsecureContentStyle, WebInspector.UIString("Mixed Content"), WebInspector.UIString("The site includes HTTP resources."), WebInspector.NetworkLogView.MixedContentFilterValues.Displayed, showDisplayedMixedContentInNetworkPanel); + this._addMixedContentExplanation(this._securityExplanationsMain, this._mixedContentStatus.displayedInsecureContentStyle, WebInspector.UIString("Mixed Content"), WebInspector.UIString("The site includes HTTP resources."), WebInspector.NetworkLogView.MixedContentFilterValues.Displayed, showDisplayedMixedContentInNetworkPanel); } if (this._mixedContentStatus && (!this._mixedContentStatus.displayedInsecureContent && !this._mixedContentStatus.ranInsecureContent)) { - this._addExplanation(/** @type {!SecurityAgent.SecurityStateExplanation} */ ({ + this._addExplanation(this._securityExplanationsMain, /** @type {!SecurityAgent.SecurityStateExplanation} */ ({ "securityState": SecurityAgent.SecurityState.Secure, "summary": WebInspector.UIString("Secure Resources"), "description": WebInspector.UIString("All resources on this page are served securely.") @@ -655,7 +668,7 @@ } if (this._panel.filterRequestCount(WebInspector.NetworkLogView.MixedContentFilterValues.Blocked) > 0) - this._addMixedContentExplanation(SecurityAgent.SecurityState.Info, WebInspector.UIString("Blocked mixed content"), WebInspector.UIString("Your page requested insecure resources that were blocked."), WebInspector.NetworkLogView.MixedContentFilterValues.Blocked, showBlockedMixedContentInNetworkPanel); + this._addMixedContentExplanation(this._securityExplanationsExtra, SecurityAgent.SecurityState.Info, WebInspector.UIString("Blocked mixed content"), WebInspector.UIString("Your page requested insecure resources that were blocked."), WebInspector.NetworkLogView.MixedContentFilterValues.Blocked, showBlockedMixedContentInNetworkPanel); /** * @param {!Event} e @@ -701,13 +714,14 @@ }, /** + * @param {!Element} parent * @param {!SecurityAgent.SecurityState} securityState * @param {string} summary * @param {string} description * @param {!WebInspector.NetworkLogView.MixedContentFilterValues} filterKey * @param {!Function} networkFilterFn */ - _addMixedContentExplanation: function(securityState, summary, description, filterKey, networkFilterFn) + _addMixedContentExplanation: function(parent, securityState, summary, description, filterKey, networkFilterFn) { var mixedContentExplanation = /** @type {!SecurityAgent.SecurityStateExplanation} */ ({ "securityState": securityState, @@ -716,7 +730,7 @@ }); var filterRequestCount = this._panel.filterRequestCount(filterKey); - var requestsAnchor = this._addExplanation(mixedContentExplanation).createChild("div", "security-mixed-content link"); + var requestsAnchor = this._addExplanation(parent, mixedContentExplanation).createChild("div", "security-mixed-content link"); if (filterRequestCount > 0) { requestsAnchor.textContent = WebInspector.UIString("View %d request%s in Network Panel", filterRequestCount, (filterRequestCount > 1 ? "s" : "")); } else {
diff --git a/third_party/WebKit/Source/devtools/front_end/security/mainView.css b/third_party/WebKit/Source/devtools/front_end/security/mainView.css index 1f6449a..df51db5d 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/mainView.css +++ b/third_party/WebKit/Source/devtools/front_end/security/mainView.css
@@ -144,13 +144,17 @@ .security-explanation-text { flex: auto; white-space: normal; + max-width: 400px; } -.security-explanation-info { - border-bottom: none; +.security-explanations-extra .security-explanation { background-color: transparent; } +.security-explanations-extra .security-explanation:only-child { + border-bottom: none; +} + .security-certificate-button { margin-top: 8px; }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js index 6b0dc58..f0a14e92 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/ScopeChainSidebarPane.js
@@ -32,6 +32,7 @@ { WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope")); this._expandController = new WebInspector.ObjectPropertiesSectionExpandController(); + this._linkifier = new WebInspector.Linkifier(); } WebInspector.ScopeChainSidebarPane._pathSymbol = Symbol("path"); @@ -42,6 +43,7 @@ */ update: function(callFrame) { + this._linkifier.reset(); WebInspector.SourceMapNamesResolver.resolveThisObject(callFrame) .then(this._innerUpdate.bind(this, callFrame)); }, @@ -120,7 +122,7 @@ titleElement.createChild("div", "scope-chain-sidebar-pane-section-subtitle").textContent = subtitle; titleElement.createChild("div", "scope-chain-sidebar-pane-section-title").textContent = title; - var section = new WebInspector.ObjectPropertiesSection(WebInspector.SourceMapNamesResolver.resolveScopeInObject(scope), titleElement, emptyPlaceholder, true, extraProperties); + var section = new WebInspector.ObjectPropertiesSection(WebInspector.SourceMapNamesResolver.resolveScopeInObject(scope), titleElement, this._linkifier, emptyPlaceholder, true, extraProperties); this._expandController.watchSection(title + (subtitle ? ":" + subtitle : ""), section); if (scope.type() === DebuggerAgent.ScopeType.Global)
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js index bef7691..955d19d3 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
@@ -582,15 +582,6 @@ this._object.functionDetails(callback); }, - /** - * @override - * @param {function(?WebInspector.DebuggerModel.GeneratorObjectDetails)} callback - */ - generatorObjectDetails: function(callback) - { - this._object.generatorObjectDetails(callback); - }, - __proto__: WebInspector.RemoteObject.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js index f4bef52..3cb238a 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -952,8 +952,6 @@ contextMenu.appendItem(WebInspector.UIString.capitalize("Store as ^global ^variable"), this._saveToTempVariable.bind(this, remoteObject)); if (remoteObject.type === "function") contextMenu.appendItem(WebInspector.UIString.capitalize("Show ^function ^definition"), this._showFunctionDefinition.bind(this, remoteObject)); - if (remoteObject.subtype === "generator") - contextMenu.appendItem(WebInspector.UIString.capitalize("Show ^generator ^location"), this._showGeneratorLocation.bind(this, remoteObject)); }, /** @@ -1042,21 +1040,13 @@ */ _showFunctionDefinition: function(remoteObject) { - remoteObject.debuggerModel().functionDetails(remoteObject, this._didGetFunctionOrGeneratorObjectDetails.bind(this)); - }, - - /** - * @param {!WebInspector.RemoteObject} remoteObject - */ - _showGeneratorLocation: function(remoteObject) - { - remoteObject.debuggerModel().generatorObjectDetails(remoteObject, this._didGetFunctionOrGeneratorObjectDetails.bind(this)); + remoteObject.debuggerModel().functionDetails(remoteObject, this._didGetFunctionDetails.bind(this)); }, /** * @param {?{location: ?WebInspector.DebuggerModel.Location}} response */ - _didGetFunctionOrGeneratorObjectDetails: function(response) + _didGetFunctionDetails: function(response) { if (!response || !response.location) return;
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js index f5b6762..f2e23b75 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -54,6 +54,8 @@ this._expandController = new WebInspector.ObjectPropertiesSectionExpandController(); WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext, this.refreshExpressions, this); + + this._linkifier = new WebInspector.Linkifier(); } WebInspector.WatchExpressionsSidebarPane.prototype = { @@ -129,6 +131,7 @@ _rebuildWatchExpressions: function() { + this._linkifier.reset(); this._bodyElement.removeChildren(); this._watchExpressions = []; this._emptyElement = this._bodyElement.createChild("div", "info"); @@ -150,7 +153,7 @@ _createWatchExpression: function(expression) { this._emptyElement.classList.add("hidden"); - var watchExpression = new WebInspector.WatchExpression(expression, this._expandController); + var watchExpression = new WebInspector.WatchExpression(expression, this._expandController, this._linkifier); watchExpression.addEventListener(WebInspector.WatchExpression.Events.ExpressionUpdated, this._watchExpressionUpdated.bind(this)); this._bodyElement.appendChild(watchExpression.element()); this._watchExpressions.push(watchExpression); @@ -218,13 +221,15 @@ * @extends {WebInspector.Object} * @param {?string} expression * @param {!WebInspector.ObjectPropertiesSectionExpandController} expandController + * @param {!WebInspector.Linkifier} linkifier */ -WebInspector.WatchExpression = function(expression, expandController) +WebInspector.WatchExpression = function(expression, expandController, linkifier) { this._expression = expression; this._expandController = expandController; this._element = createElementWithClass("div", "watch-expression monospace"); this._editing = false; + this._linkifier = linkifier; this._createWatchExpression(null, false); this.update(); @@ -352,7 +357,7 @@ titleElement.classList.add("dimmed"); this._valueElement.textContent = WebInspector.UIString("<not available>"); } else { - this._valueElement = WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport(result, wasThrown, titleElement); + this._valueElement = WebInspector.ObjectPropertiesSection.createValueElementWithCustomSupport(result, wasThrown, titleElement, this._linkifier); } var separatorElement = createElementWithClass("span", "watch-expressions-separator"); separatorElement.textContent = ": "; @@ -362,7 +367,7 @@ this._objectPropertiesSection = null; if (!wasThrown && result && result.hasChildren && !result.customPreview()) { headerElement.classList.add("watch-expression-object-header"); - this._objectPropertiesSection = new WebInspector.ObjectPropertiesSection(result, headerElement); + this._objectPropertiesSection = new WebInspector.ObjectPropertiesSection(result, headerElement, this._linkifier); this._objectPresentationElement = this._objectPropertiesSection.element; this._expandController.watchSection(/** @type {string} */ (this._expression), this._objectPropertiesSection); var objectTreeElement = this._objectPropertiesSection.objectTreeElement();
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 9858353..48a123b 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -1720,6 +1720,14 @@ }, /** + * @return {string} + */ + themeName: function() + { + return this._themeName; + }, + + /** * @param {!Element} element */ injectHighlightStyleSheets: function(element)
diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json index 4f6b96a1..d790d5db 100644 --- a/third_party/WebKit/Source/devtools/protocol.json +++ b/third_party/WebKit/Source/devtools/protocol.json
@@ -1,7 +1,7 @@ The protocol.json has split into separate files. https://crbug.com/580337 One for the browser, one for a V8 javascript environment: - src/content/browser/devtools/browser_protocol.json + src/third_party/WebKit/Source/core/inspector/browser_protocol.json src/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json Browsable here:
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObserver.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBObserver.cpp index 219b818..db4a1ea 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBObserver.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBObserver.cpp
@@ -7,8 +7,12 @@ #include "bindings/core/v8/ExceptionState.h" #include "bindings/modules/v8/ToV8ForModules.h" #include "bindings/modules/v8/V8BindingForModules.h" +#include "core/dom/ExceptionCode.h" +#include "modules/indexeddb/IDBDatabase.h" #include "modules/indexeddb/IDBObserverCallback.h" #include "modules/indexeddb/IDBObserverInit.h" +#include "modules/indexeddb/IDBTransaction.h" +#include "modules/indexeddb/WebIDBObserverImpl.h" namespace blink { @@ -25,9 +29,53 @@ { } +IDBObserver::~IDBObserver() {} + void IDBObserver::observe(IDBDatabase* database, IDBTransaction* transaction, ExceptionState& exceptionState) { - // TODO(palakj): Finish implementation. + if (transaction->isFinished() || transaction->isFinishing()) { + exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); + return; + } + if (!transaction->isActive()) { + exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); + return; + } + if (!database->backend()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return; + } + + std::unique_ptr<WebIDBObserverImpl> observer = WebIDBObserverImpl::create(this); + WebIDBObserverImpl* observerPtr = observer.get(); + int32_t observerId = database->backend()->addObserver(std::move(observer), transaction->id()); + m_observerIds.insert(observerId); + observerPtr->setId(observerId); +} + +void IDBObserver::unobserve(IDBDatabase* database, ExceptionState& exceptionState) +{ + if (!database->backend()) { + exceptionState.throwDOMException(InvalidStateError, IDBDatabase::databaseClosedErrorMessage); + return; + } + auto it = m_observerIds.begin(); + std::vector<int32_t> observerIdsToRemove; + while (it != m_observerIds.end()) { + if (database->backend()->containsObserverId(*it)) { + observerIdsToRemove.push_back(*it); + it = m_observerIds.erase(it); + } else { + it++; + } + } + if (!observerIdsToRemove.empty()) + database->backend()->removeObservers(observerIdsToRemove); +} + +void IDBObserver::removeObserver(int32_t id) +{ + m_observerIds.erase(id); } DEFINE_TRACE(IDBObserver)
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObserver.h b/third_party/WebKit/Source/modules/indexeddb/IDBObserver.h index 538995bc..c8500567 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBObserver.h +++ b/third_party/WebKit/Source/modules/indexeddb/IDBObserver.h
@@ -6,23 +6,29 @@ #define IDBObserver_h #include "bindings/core/v8/ScriptWrappable.h" -#include "modules/indexeddb/IDBDatabase.h" -#include "modules/indexeddb/IDBTransaction.h" +#include "modules/ModulesExport.h" #include "platform/heap/Handle.h" +#include <set> namespace blink { +class ExceptionState; +class IDBDatabase; class IDBObserverCallback; class IDBObserverInit; +class IDBTransaction; -class IDBObserver final : public GarbageCollected<IDBObserver>, public ScriptWrappable { +class MODULES_EXPORT IDBObserver final : public GarbageCollectedFinalized<IDBObserver>, public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: static IDBObserver* create(IDBObserverCallback&, const IDBObserverInit&); + ~IDBObserver(); // API methods void observe(IDBDatabase*, IDBTransaction*, ExceptionState&); + void unobserve(IDBDatabase*, ExceptionState&); + void removeObserver(int32_t id); DECLARE_TRACE(); @@ -33,6 +39,7 @@ bool m_transaction; bool m_values; bool m_noRecords; + std::set<int32_t> m_observerIds; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBObserver.idl b/third_party/WebKit/Source/modules/indexeddb/IDBObserver.idl index ab4d856..3723dbc 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBObserver.idl +++ b/third_party/WebKit/Source/modules/indexeddb/IDBObserver.idl
@@ -11,4 +11,5 @@ RuntimeEnabled=IDBObserver ] interface IDBObserver { [RaisesException] void observe(IDBDatabase db, IDBTransaction tx); + [RaisesException] void unobserve(IDBDatabase db); };
diff --git a/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h b/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h index 30445548..5d460252 100644 --- a/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h +++ b/third_party/WebKit/Source/modules/indexeddb/MockWebIDBDatabase.h
@@ -9,6 +9,7 @@ #include "modules/indexeddb/IDBKeyRange.h" #include "public/platform/modules/indexeddb/WebIDBDatabase.h" #include "public/platform/modules/indexeddb/WebIDBKeyRange.h" +#include "public/platform/modules/indexeddb/WebIDBObserver.h" #include <gmock/gmock.h> #include <memory> @@ -29,6 +30,11 @@ MOCK_METHOD1(commit, void(long long transactionId)); MOCK_METHOD7(createIndex, void(long long transactionId, long long objectStoreId, long long indexId, const WebString& name, const WebIDBKeyPath&, bool unique, bool multiEntry)); MOCK_METHOD3(deleteIndex, void(long long transactionId, long long objectStoreId, long long indexId)); + + // Gmock does not support movable type, so cannot use MOCK_METHOD for addObserver. Issue: https://github.com/google/googletest/issues/395. + int32_t addObserver(std::unique_ptr<WebIDBObserver>, long long transactionId) { return -1; } + MOCK_CONST_METHOD1(containsObserverId, bool(int32_t id)); + MOCK_METHOD1(removeObservers, void(const std::vector<int32_t>& observerIdsToRemove)); MOCK_METHOD6(get, void(long long transactionId, long long objectStoreId, long long indexId, const WebIDBKeyRange&, bool keyOnly, WebIDBCallbacks*)); MOCK_METHOD7(getAll, void(long long transactionId, long long objectStoreId, long long indexId, const WebIDBKeyRange&, long long maxCount, bool keyOnly, WebIDBCallbacks*)); MOCK_METHOD9(put, void(long long transactionId, long long objectStoreId, const WebData& value, const WebVector<WebBlobInfo>&, const WebIDBKey&, WebIDBPutMode, WebIDBCallbacks*, const WebVector<long long>& indexIds, const WebVector<WebIndexKeys>&));
diff --git a/third_party/WebKit/Source/modules/indexeddb/WebIDBObserverImpl.cpp b/third_party/WebKit/Source/modules/indexeddb/WebIDBObserverImpl.cpp new file mode 100644 index 0000000..3610e284 --- /dev/null +++ b/third_party/WebKit/Source/modules/indexeddb/WebIDBObserverImpl.cpp
@@ -0,0 +1,37 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "modules/indexeddb/WebIDBObserverImpl.h" + +#include "modules/indexeddb/IDBObserver.h" +#include "wtf/PtrUtil.h" + +namespace blink { + +// static +std::unique_ptr<WebIDBObserverImpl> WebIDBObserverImpl::create(IDBObserver* observer) +{ + return wrapUnique(new WebIDBObserverImpl(observer)); +} + +WebIDBObserverImpl::WebIDBObserverImpl(IDBObserver* observer) + : m_id(kInvalidObserverId) + , m_observer(observer) +{ +} + +// Remove observe call id from IDBObserver. +WebIDBObserverImpl::~WebIDBObserverImpl() +{ + if (m_id != kInvalidObserverId) + m_observer->removeObserver(m_id); +} + +void WebIDBObserverImpl::setId(int32_t id) +{ + DCHECK_EQ(kInvalidObserverId, m_id); + m_id = id; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/indexeddb/WebIDBObserverImpl.h b/third_party/WebKit/Source/modules/indexeddb/WebIDBObserverImpl.h new file mode 100644 index 0000000..97c53bb --- /dev/null +++ b/third_party/WebKit/Source/modules/indexeddb/WebIDBObserverImpl.h
@@ -0,0 +1,36 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebIDBObserverImpl_h +#define WebIDBObserverImpl_h + +#include "platform/heap/Persistent.h" +#include "public/platform/modules/indexeddb/WebIDBObserver.h" + +namespace blink { + +class IDBObserver; + +class WebIDBObserverImpl final : public WebIDBObserver { + USING_FAST_MALLOC(WebIDBObserverImpl); + +public: + static std::unique_ptr<WebIDBObserverImpl> create(IDBObserver*); + + ~WebIDBObserverImpl() override; + + void setId(int32_t); + +private: + enum { kInvalidObserverId = -1 }; + + explicit WebIDBObserverImpl(IDBObserver*); + + int32_t m_id; + Persistent<IDBObserver> m_observer; +}; + +} // namespace blink + +#endif // WebIDBObserverImpl_h
diff --git a/third_party/WebKit/Source/modules/modules.gypi b/third_party/WebKit/Source/modules/modules.gypi index b5e2a07..94c2d46 100644 --- a/third_party/WebKit/Source/modules/modules.gypi +++ b/third_party/WebKit/Source/modules/modules.gypi
@@ -1223,6 +1223,8 @@ 'indexeddb/WebIDBCallbacksImpl.h', 'indexeddb/WebIDBDatabaseCallbacksImpl.cpp', 'indexeddb/WebIDBDatabaseCallbacksImpl.h', + 'indexeddb/WebIDBObserverImpl.cpp', + 'indexeddb/WebIDBObserverImpl.h', 'installedapp/InstalledAppController.cpp', 'installedapp/InstalledAppController.h', 'installedapp/NavigatorInstalledApp.cpp', @@ -1636,8 +1638,6 @@ 'vr/VRStageParameters.h', 'wake_lock/ScreenWakeLock.cpp', 'wake_lock/ScreenWakeLock.h', - 'webaudio/AbstractAudioContext.cpp', - 'webaudio/AbstractAudioContext.h', 'webaudio/AnalyserNode.cpp', 'webaudio/AnalyserNode.h', 'webaudio/AsyncAudioDecoder.cpp', @@ -1674,6 +1674,8 @@ 'webaudio/AudioSourceNode.h', 'webaudio/AudioSummingJunction.cpp', 'webaudio/AudioSummingJunction.h', + 'webaudio/BaseAudioContext.cpp', + 'webaudio/BaseAudioContext.h', 'webaudio/BiquadDSPKernel.cpp', 'webaudio/BiquadDSPKernel.h', 'webaudio/BiquadFilterNode.cpp',
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp index e3da8a5..294efb8b 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -25,6 +25,7 @@ #include "mojo/public/cpp/bindings/wtf_array.h" #include "platform/mojo/MojoHelper.h" #include "public/platform/ServiceRegistry.h" +#include "wtf/HashSet.h" #include <utility> namespace mojo { @@ -224,11 +225,19 @@ return; } + HashSet<String> uniqueMethods; for (const auto& modifier : modifiers) { if (modifier.supportedMethods().isEmpty()) { exceptionState.throwTypeError("Must specify at least one payment method identifier"); return; } + for (const auto& method : modifier.supportedMethods()) { + if (uniqueMethods.contains(method)) { + exceptionState.throwTypeError("Duplicate payment method identifiers are not allowed"); + return; + } + uniqueMethods.add(method); + } if (modifier.hasTotal()) { validateShippingOptionOrPaymentItem(modifier.total(), exceptionState); @@ -289,11 +298,19 @@ return; } + HashSet<String> uniqueMethods; for (const auto& pmd : paymentMethodData) { if (pmd.supportedMethods().isEmpty()) { exceptionState.throwTypeError("Must specify at least one payment method identifier"); return; } + for (const auto& method : pmd.supportedMethods()) { + if (uniqueMethods.contains(method)) { + exceptionState.throwTypeError("Duplicate payment method identifiers are not allowed"); + return; + } + uniqueMethods.add(method); + } String stringifiedData = ""; if (pmd.hasData() && !pmd.data().isEmpty()) {
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp index 4a376381..ea8ea6cf 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.cpp
@@ -30,6 +30,8 @@ #include "modules/serviceworkers/ServiceWorkerError.h" +#include "bindings/core/v8/ScriptPromiseResolver.h" +#include "bindings/core/v8/ToV8.h" #include "core/dom/DOMException.h" #include "core/dom/ExceptionCode.h" @@ -37,49 +39,81 @@ namespace blink { -static DOMException* createException(ExceptionCode code, const String& defaultMessage, const String& message) +namespace { + +struct ExceptionParams { + ExceptionParams(ExceptionCode code, const String& defaultMessage = String(), const String& message = String()) + : code(code), message(message.isEmpty() ? defaultMessage : message) {} + + ExceptionCode code; + String message; +}; + +ExceptionParams getExceptionParams(const WebServiceWorkerError& webError) { - return DOMException::create(code, message.isEmpty() ? defaultMessage : message); + switch (webError.errorType) { + case WebServiceWorkerError::ErrorTypeAbort: + return ExceptionParams(AbortError, "The Service Worker operation was aborted.", webError.message); + case WebServiceWorkerError::ErrorTypeActivate: + // Not currently returned as a promise rejection. + // TODO: Introduce new ActivateError type to ExceptionCodes? + return ExceptionParams(AbortError, "The Service Worker activation failed.", webError.message); + case WebServiceWorkerError::ErrorTypeDisabled: + return ExceptionParams(NotSupportedError, "Service Worker support is disabled.", webError.message); + case WebServiceWorkerError::ErrorTypeInstall: + // TODO: Introduce new InstallError type to ExceptionCodes? + return ExceptionParams(AbortError, "The Service Worker installation failed.", webError.message); + case WebServiceWorkerError::ErrorTypeScriptEvaluateFailed: + return ExceptionParams(AbortError, "The Service Worker script failed to evaluate.", webError.message); + case WebServiceWorkerError::ErrorTypeNavigation: + // ErrorTypeNavigation should have bailed out before calling this. + ASSERT_NOT_REACHED(); + return ExceptionParams(UnknownError); + case WebServiceWorkerError::ErrorTypeNetwork: + return ExceptionParams(NetworkError, "The Service Worker failed by network.", webError.message); + case WebServiceWorkerError::ErrorTypeNotFound: + return ExceptionParams(NotFoundError, "The specified Service Worker resource was not found.", webError.message); + case WebServiceWorkerError::ErrorTypeSecurity: + return ExceptionParams(SecurityError, "The Service Worker security policy prevented an action.", webError.message); + case WebServiceWorkerError::ErrorTypeState: + return ExceptionParams(InvalidStateError, "The Service Worker state was not valid.", webError.message); + case WebServiceWorkerError::ErrorTypeTimeout: + return ExceptionParams(AbortError, "The Service Worker operation timed out.", webError.message); + case WebServiceWorkerError::ErrorTypeUnknown: + return ExceptionParams(UnknownError, "An unknown error occurred within Service Worker.", webError.message); + case WebServiceWorkerError::ErrorTypeType: + // ErrorTypeType should have been handled before reaching this point. + ASSERT_NOT_REACHED(); + return ExceptionParams(UnknownError); + } + ASSERT_NOT_REACHED(); + return ExceptionParams(UnknownError); } +} // namespace + // static DOMException* ServiceWorkerError::take(ScriptPromiseResolver*, const WebServiceWorkerError& webError) { - switch (webError.errorType) { - case WebServiceWorkerError::ErrorTypeAbort: - return createException(AbortError, "The Service Worker operation was aborted.", webError.message); - case WebServiceWorkerError::ErrorTypeActivate: - // Not currently returned as a promise rejection. - // FIXME: Introduce new ActivateError type to ExceptionCodes? - return createException(AbortError, "The Service Worker activation failed.", webError.message); - case WebServiceWorkerError::ErrorTypeDisabled: - return createException(NotSupportedError, "Service Worker support is disabled.", webError.message); - case WebServiceWorkerError::ErrorTypeInstall: - // FIXME: Introduce new InstallError type to ExceptionCodes? - return createException(AbortError, "The Service Worker installation failed.", webError.message); - case WebServiceWorkerError::ErrorTypeNavigation: - // ErrorTypeNavigation should have bailed out before calling this. - ASSERT_NOT_REACHED(); - return DOMException::create(UnknownError); + ExceptionParams params = getExceptionParams(webError); + ASSERT(params.code != UnknownError); + return DOMException::create(params.code, params.message); +} + +// static +v8::Local<v8::Value> ServiceWorkerErrorForUpdate::take(ScriptPromiseResolver* resolver, const WebServiceWorkerError& webError) +{ + ScriptState* scriptState = resolver->getScriptState(); + switch(webError.errorType) { case WebServiceWorkerError::ErrorTypeNetwork: - return createException(NetworkError, "The Service Worker failed by network.", webError.message); case WebServiceWorkerError::ErrorTypeNotFound: - return createException(NotFoundError, "The specified Service Worker resource was not found.", webError.message); - case WebServiceWorkerError::ErrorTypeSecurity: - return createException(SecurityError, "The Service Worker security policy prevented an action.", webError.message); - case WebServiceWorkerError::ErrorTypeState: - return createException(InvalidStateError, "The Service Worker state was not valid.", webError.message); - case WebServiceWorkerError::ErrorTypeTimeout: - return createException(AbortError, "The Service Worker operation timed out.", webError.message); - case WebServiceWorkerError::ErrorTypeUnknown: - return createException(UnknownError, "An unknown error occurred within Service Worker.", webError.message); - case WebServiceWorkerError::ErrorTypeType: - // ErrorTypeType should have been handled before reaching this point. - ASSERT_NOT_REACHED(); - return DOMException::create(UnknownError); + case WebServiceWorkerError::ErrorTypeScriptEvaluateFailed: + // According to the spec, these errors during update should result in + // a TypeError. + return V8ThrowException::createTypeError(scriptState->isolate(), getExceptionParams(webError).message); + default: + return toV8(ServiceWorkerError::take(resolver, webError), scriptState->context()->Global(), scriptState->isolate()); } - ASSERT_NOT_REACHED(); - return DOMException::create(UnknownError); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h index 9145d11..5a15fa4 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerError.h
@@ -34,6 +34,8 @@ #include "platform/heap/Handle.h" #include "public/platform/modules/serviceworker/WebServiceWorkerError.h" +#include <v8.h> + namespace blink { class DOMException; @@ -47,6 +49,13 @@ static DOMException* take(ScriptPromiseResolver*, const WebServiceWorkerError& webError); }; +class ServiceWorkerErrorForUpdate : public ServiceWorkerError { + STATIC_ONLY(ServiceWorkerErrorForUpdate); +public: + // For CallbackPromiseAdapter + static v8::Local<v8::Value> take(ScriptPromiseResolver* resolver, const WebServiceWorkerError& webError); +}; + } // namespace blink #endif // ServiceWorkerError_h
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp index 1582384..85fbce82 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerRegistration.cpp
@@ -79,7 +79,7 @@ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); - m_handle->registration()->update(client->provider(), new CallbackPromiseAdapter<void, ServiceWorkerError>(resolver)); + m_handle->registration()->update(client->provider(), new CallbackPromiseAdapter<void, ServiceWorkerErrorForUpdate>(resolver)); return promise; }
diff --git a/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.cpp b/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.cpp index 2c42f90..3062214e 100644 --- a/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.cpp +++ b/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.cpp
@@ -4,6 +4,7 @@ #include "modules/wake_lock/ScreenWakeLock.h" +#include "core/dom/Document.h" #include "core/frame/LocalFrame.h" #include "core/frame/Screen.h" #include "core/page/PageVisibilityState.h" @@ -39,17 +40,14 @@ // static ScreenWakeLock* ScreenWakeLock::from(LocalFrame* frame) { - return static_cast<ScreenWakeLock*>(Supplement<LocalFrame>::from(frame, supplementName())); -} - -// static -void ScreenWakeLock::provideTo(LocalFrame& frame, ServiceRegistry* registry) -{ - DCHECK(RuntimeEnabledFeatures::wakeLockEnabled()); - Supplement<LocalFrame>::provideTo( - frame, - ScreenWakeLock::supplementName(), - registry ? new ScreenWakeLock(frame, registry) : nullptr); + if (!RuntimeEnabledFeatures::wakeLockEnabled()) + return nullptr; + ScreenWakeLock* supplement = static_cast<ScreenWakeLock*>(Supplement<LocalFrame>::from(frame, supplementName())); + if (!supplement) { + supplement = new ScreenWakeLock(*frame); + Supplement<LocalFrame>::provideTo(*frame, supplementName(), supplement); + } + return supplement; } void ScreenWakeLock::pageVisibilityChanged() @@ -57,14 +55,7 @@ notifyService(); } -void ScreenWakeLock::didCommitLoad(LocalFrame* committedFrame) -{ - // Reset wake lock flag for this frame if it is the one being navigated. - if (committedFrame == frame()) - setKeepAwake(false); -} - -void ScreenWakeLock::willDetachFrameHost() +void ScreenWakeLock::contextDestroyed() { setKeepAwake(false); } @@ -73,17 +64,17 @@ { Supplement<LocalFrame>::trace(visitor); PageLifecycleObserver::trace(visitor); - LocalFrameLifecycleObserver::trace(visitor); + ContextLifecycleObserver::trace(visitor); } -ScreenWakeLock::ScreenWakeLock(LocalFrame& frame, ServiceRegistry* registry) - : PageLifecycleObserver(frame.page()) - , LocalFrameLifecycleObserver(&frame) +ScreenWakeLock::ScreenWakeLock(LocalFrame& frame) + : ContextLifecycleObserver(frame.document()) + , PageLifecycleObserver(frame.page()) , m_keepAwake(false) { DCHECK(!m_service.is_bound()); - DCHECK(registry); - registry->connectToRemoteService(mojo::GetProxy(&m_service)); + DCHECK(frame.serviceRegistry()); + frame.serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_service)); } bool ScreenWakeLock::keepAwake() const @@ -108,7 +99,7 @@ if (!m_service) return; - if (m_keepAwake && frame()->page() && frame()->page()->isPageVisible()) + if (m_keepAwake && page() && page()->isPageVisible()) m_service->RequestWakeLock(); else m_service->CancelWakeLock();
diff --git a/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.h b/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.h index eeddc68..1e9e9ca 100644 --- a/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.h +++ b/third_party/WebKit/Source/modules/wake_lock/ScreenWakeLock.h
@@ -5,7 +5,7 @@ #ifndef ScreenWakeLock_h #define ScreenWakeLock_h -#include "core/frame/LocalFrameLifecycleObserver.h" +#include "core/dom/ContextLifecycleObserver.h" #include "core/page/PageLifecycleObserver.h" #include "modules/ModulesExport.h" #include "public/platform/modules/wake_lock/wake_lock_service.mojom-blink.h" @@ -17,7 +17,7 @@ class Screen; class ServiceRegistry; -class MODULES_EXPORT ScreenWakeLock final : public GarbageCollectedFinalized<ScreenWakeLock>, public Supplement<LocalFrame>, public PageLifecycleObserver, public LocalFrameLifecycleObserver { +class MODULES_EXPORT ScreenWakeLock final : public GarbageCollectedFinalized<ScreenWakeLock>, public Supplement<LocalFrame>, public ContextLifecycleObserver, public PageLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(ScreenWakeLock); WTF_MAKE_NONCOPYABLE(ScreenWakeLock); public: @@ -26,21 +26,17 @@ static const char* supplementName(); static ScreenWakeLock* from(LocalFrame*); - static void provideTo(LocalFrame&, ServiceRegistry*); ~ScreenWakeLock() = default; DECLARE_VIRTUAL_TRACE(); private: - ScreenWakeLock(LocalFrame&, ServiceRegistry*); + explicit ScreenWakeLock(LocalFrame&); // Inherited from PageLifecycleObserver. void pageVisibilityChanged() override; - void didCommitLoad(LocalFrame*) override; - - // Inherited from LocalFrameLifecycleObserver. - void willDetachFrameHost() override; + void contextDestroyed() override; bool keepAwake() const; void setKeepAwake(bool);
diff --git a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp index 4340364..6f33807 100644 --- a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.cpp
@@ -113,13 +113,13 @@ // ---------------------------------------------------------------- -AnalyserNode::AnalyserNode(AbstractAudioContext& context) +AnalyserNode::AnalyserNode(BaseAudioContext& context) : AudioBasicInspectorNode(context) { setHandler(AnalyserHandler::create(*this, context.sampleRate())); } -AnalyserNode* AnalyserNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +AnalyserNode* AnalyserNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h index dd373b1..5999f7aa 100644 --- a/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AnalyserNode.h
@@ -31,7 +31,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class AnalyserHandler final : public AudioBasicInspectorHandler { @@ -76,7 +76,7 @@ class AnalyserNode final : public AudioBasicInspectorNode { DEFINE_WRAPPERTYPEINFO(); public: - static AnalyserNode* create(AbstractAudioContext&, ExceptionState&); + static AnalyserNode* create(BaseAudioContext&, ExceptionState&); unsigned fftSize() const; void setFftSize(unsigned size, ExceptionState&); @@ -93,7 +93,7 @@ void getByteTimeDomainData(DOMUint8Array*); private: - AnalyserNode(AbstractAudioContext&); + AnalyserNode(BaseAudioContext&); AnalyserHandler& analyserHandler() const; };
diff --git a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp index 360ad1ad..12aa3b88 100644 --- a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
@@ -23,10 +23,10 @@ */ #include "core/dom/DOMArrayBuffer.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AsyncAudioDecoder.h" #include "modules/webaudio/AudioBuffer.h" #include "modules/webaudio/AudioBufferCallback.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/CrossThreadFunctional.h" #include "platform/audio/AudioBus.h" #include "platform/audio/AudioFileReader.h" @@ -45,7 +45,7 @@ { } -void AsyncAudioDecoder::decodeAsync(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver* resolver, AbstractAudioContext* context) +void AsyncAudioDecoder::decodeAsync(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver* resolver, BaseAudioContext* context) { ASSERT(isMainThread()); ASSERT(audioData); @@ -55,7 +55,7 @@ m_thread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&AsyncAudioDecoder::decode, wrapCrossThreadPersistent(audioData), sampleRate, wrapCrossThreadPersistent(successCallback), wrapCrossThreadPersistent(errorCallback), wrapCrossThreadPersistent(resolver), wrapCrossThreadPersistent(context))); } -void AsyncAudioDecoder::decode(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver* resolver, AbstractAudioContext* context) +void AsyncAudioDecoder::decode(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver* resolver, BaseAudioContext* context) { RefPtr<AudioBus> bus = createBusFromInMemoryAudioFile(audioData->data(), audioData->byteLength(), false, sampleRate); @@ -64,7 +64,7 @@ Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&AsyncAudioDecoder::notifyComplete, wrapCrossThreadPersistent(audioData), wrapCrossThreadPersistent(successCallback), wrapCrossThreadPersistent(errorCallback), bus.release(), wrapCrossThreadPersistent(resolver), wrapCrossThreadPersistent(context))); } -void AsyncAudioDecoder::notifyComplete(DOMArrayBuffer*, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBus* audioBus, ScriptPromiseResolver* resolver, AbstractAudioContext* context) +void AsyncAudioDecoder::notifyComplete(DOMArrayBuffer*, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBus* audioBus, ScriptPromiseResolver* resolver, BaseAudioContext* context) { ASSERT(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h index b05694c..2d2c301 100644 --- a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h +++ b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.h
@@ -32,7 +32,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioBuffer; class AudioBufferCallback; class AudioBus; @@ -52,12 +52,12 @@ // Must be called on the main thread. |decodeAsync| and callees must not modify any of the // parameters except |audioData|. They are used to associate this decoding instance with the // caller to process the decoding appropriately when finished. - void decodeAsync(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver* , AbstractAudioContext*); + void decodeAsync(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver* , BaseAudioContext*); private: AudioBuffer* createAudioBufferFromAudioBus(AudioBus*); - static void decode(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver*, AbstractAudioContext*); - static void notifyComplete(DOMArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBus*, ScriptPromiseResolver*, AbstractAudioContext*); + static void decode(DOMArrayBuffer* audioData, float sampleRate, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ScriptPromiseResolver*, BaseAudioContext*); + static void notifyComplete(DOMArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, AudioBus*, ScriptPromiseResolver*, BaseAudioContext*); std::unique_ptr<WebThread> m_thread; };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.cpp index c71427c..f9343a1 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.cpp
@@ -23,9 +23,9 @@ */ #include "modules/webaudio/AudioBasicInspectorNode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" namespace blink { @@ -50,7 +50,7 @@ { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); AudioNode::connect(destination, outputIndex, inputIndex, exceptionState); static_cast<AudioBasicInspectorHandler&>(handler()).updatePullStatus(); @@ -62,7 +62,7 @@ { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); AudioNode::disconnect(outputIndex, exceptionState); static_cast<AudioBasicInspectorHandler&>(handler()).updatePullStatus();
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h b/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h index 4a27e79..cbad7c18 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicInspectorNode.h
@@ -29,12 +29,12 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; // AudioBasicInspectorNode is an AudioNode with one input and one output where the output might not necessarily connect to another node's input. // If the output is not connected to any other node, then the AudioBasicInspectorNode's processIfNecessary() function will be called automatically by -// AbstractAudioContext before the end of each render quantum so that it can inspect the audio stream. +// BaseAudioContext before the end of each render quantum so that it can inspect the audio stream. class AudioBasicInspectorHandler : public AudioHandler { public: AudioBasicInspectorHandler(NodeType, AudioNode&, float sampleRate, unsigned outputChannelCount); @@ -46,12 +46,12 @@ void updatePullStatus(); private: - bool m_needAutomaticPull; // When setting to true, AudioBasicInspectorHandler will be pulled automaticlly by AbstractAudioContext before the end of each render quantum. + bool m_needAutomaticPull; // When setting to true, AudioBasicInspectorHandler will be pulled automaticlly by BaseAudioContext before the end of each render quantum. }; class AudioBasicInspectorNode : public AudioNode { protected: - explicit AudioBasicInspectorNode(AbstractAudioContext& context) : AudioNode(context) { } + explicit AudioBasicInspectorNode(BaseAudioContext& context) : AudioNode(context) { } private: // TODO(tkent): Should AudioBasicInspectorNode override other variants of
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp index 535d1a1..3d6b926 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioBasicProcessorHandlerTest.cpp
@@ -27,7 +27,7 @@ class MockProcessorNode final : public AudioNode { public: - MockProcessorNode(AbstractAudioContext& context) + MockProcessorNode(BaseAudioContext& context) : AudioNode(context) { setHandler(AudioBasicProcessorHandler::create(AudioHandler::NodeTypeWaveShaper, *this, 48000, wrapUnique(new MockAudioProcessor()))); @@ -43,7 +43,7 @@ AudioBasicProcessorHandler& handler = static_cast<AudioBasicProcessorHandler&>(node->handler()); EXPECT_TRUE(handler.processor()); EXPECT_TRUE(handler.processor()->isInitialized()); - AbstractAudioContext::AutoLocker locker(context); + BaseAudioContext::AutoLocker locker(context); handler.dispose(); // The AudioProcessor should live after dispose() and should not be // finalized because an audio thread is using it.
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp index c171de6b..7fdeda0 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioBuffer.cpp
@@ -31,7 +31,7 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/audio/AudioBus.h" #include "platform/audio/AudioFileReader.h" #include "platform/audio/AudioUtilities.h" @@ -41,7 +41,7 @@ AudioBuffer* AudioBuffer::create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) { - if (!AudioUtilities::isValidAudioBufferSampleRate(sampleRate) || numberOfChannels > AbstractAudioContext::maxNumberOfChannels() || !numberOfChannels || !numberOfFrames) + if (!AudioUtilities::isValidAudioBufferSampleRate(sampleRate) || numberOfChannels > BaseAudioContext::maxNumberOfChannels() || !numberOfChannels || !numberOfFrames) return nullptr; AudioBuffer* buffer = new AudioBuffer(numberOfChannels, numberOfFrames, sampleRate); @@ -53,7 +53,7 @@ AudioBuffer* AudioBuffer::create(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) { - if (!numberOfChannels || numberOfChannels > AbstractAudioContext::maxNumberOfChannels()) { + if (!numberOfChannels || numberOfChannels > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( NotSupportedError, ExceptionMessages::indexOutsideRange( @@ -61,7 +61,7 @@ numberOfChannels, 1u, ExceptionMessages::InclusiveBound, - AbstractAudioContext::maxNumberOfChannels(), + BaseAudioContext::maxNumberOfChannels(), ExceptionMessages::InclusiveBound)); return nullptr; }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp index f660a33..bcdae9a 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
@@ -26,9 +26,9 @@ #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/frame/UseCounter.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioBufferSourceNode.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/FloatConversion.h" #include "platform/audio/AudioUtilities.h" #include "wtf/MathExtras.h" @@ -344,7 +344,7 @@ } // The context must be locked since changing the buffer can re-configure the number of channels that are output. - AbstractAudioContext::AutoLocker contextLocker(context()); + BaseAudioContext::AutoLocker contextLocker(context()); // This synchronizes with process(). MutexLocker processLocker(m_processLock); @@ -355,7 +355,7 @@ // This should not be possible since AudioBuffers can't be created with too many channels // either. - if (numberOfChannels > AbstractAudioContext::maxNumberOfChannels()) { + if (numberOfChannels > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( NotSupportedError, ExceptionMessages::indexOutsideRange( @@ -363,7 +363,7 @@ numberOfChannels, 1u, ExceptionMessages::InclusiveBound, - AbstractAudioContext::maxNumberOfChannels(), + BaseAudioContext::maxNumberOfChannels(), ExceptionMessages::InclusiveBound)); return; } @@ -508,9 +508,9 @@ double AudioBufferSourceHandler::computePlaybackRate() { - // Incorporate buffer's sample-rate versus AbstractAudioContext's sample-rate. + // Incorporate buffer's sample-rate versus BaseAudioContext's sample-rate. // Normally it's not an issue because buffers are loaded at the - // AbstractAudioContext's sample-rate, but we can handle it in any case. + // BaseAudioContext's sample-rate, but we can handle it in any case. double sampleRateFactor = 1.0; if (buffer()) { // Use doubles to compute this to full accuracy. @@ -584,7 +584,7 @@ } // ---------------------------------------------------------------- -AudioBufferSourceNode::AudioBufferSourceNode(AbstractAudioContext& context) +AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext& context) : AudioScheduledSourceNode(context) , m_playbackRate(AudioParam::create(context, ParamTypeAudioBufferSourcePlaybackRate, 1.0)) , m_detune(AudioParam::create(context, ParamTypeAudioBufferSourceDetune, 0.0)) @@ -596,7 +596,7 @@ m_detune->handler())); } -AudioBufferSourceNode* AudioBufferSourceNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +AudioBufferSourceNode* AudioBufferSourceNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h index 70de4a2..9f83f002 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h
@@ -37,7 +37,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; // AudioBufferSourceNode is an AudioNode representing an audio source from an in-memory audio asset represented by an AudioBuffer. // It generally will be used for short sounds which require a high degree of scheduling flexibility (can playback in rhythmically perfect ways). @@ -141,7 +141,7 @@ class AudioBufferSourceNode final : public AudioScheduledSourceNode { DEFINE_WRAPPERTYPEINFO(); public: - static AudioBufferSourceNode* create(AbstractAudioContext&, ExceptionState&); + static AudioBufferSourceNode* create(BaseAudioContext&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); AudioBufferSourceHandler& audioBufferSourceHandler() const; @@ -162,7 +162,7 @@ void start(double when, double grainOffset, double grainDuration, ExceptionState&); private: - AudioBufferSourceNode(AbstractAudioContext&); + AudioBufferSourceNode(BaseAudioContext&); Member<AudioParam> m_playbackRate; Member<AudioParam> m_detune;
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp index 123d777..6e2f7a8 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
@@ -26,7 +26,7 @@ static unsigned s_hardwareContextCount = 0; static unsigned s_contextId = 0; -AbstractAudioContext* AudioContext::create(Document& document, ExceptionState& exceptionState) +BaseAudioContext* AudioContext::create(Document& document, ExceptionState& exceptionState) { ASSERT(isMainThread()); @@ -82,7 +82,7 @@ } AudioContext::AudioContext(Document& document) - : AbstractAudioContext(&document) + : BaseAudioContext(&document) , m_contextId(s_contextId++) { } @@ -97,7 +97,7 @@ DEFINE_TRACE(AudioContext) { visitor->trace(m_closeResolver); - AbstractAudioContext::trace(visitor); + BaseAudioContext::trace(visitor); } ScriptPromise AudioContext::suspendContext(ScriptState* scriptState) @@ -196,7 +196,7 @@ bool AudioContext::isContextClosed() const { - return m_closeResolver || AbstractAudioContext::isContextClosed(); + return m_closeResolver || BaseAudioContext::isContextClosed(); } void AudioContext::stopRendering()
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.h b/third_party/WebKit/Source/modules/webaudio/AudioContext.h index 33fc7684..1dcda97e 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.h
@@ -7,7 +7,7 @@ #include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromiseResolver.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/heap/Handle.h" namespace blink { @@ -16,11 +16,11 @@ class ExceptionState; class ScriptState; -// This is an AbstractAudioContext which actually plays sound, unlike an +// This is an BaseAudioContext which actually plays sound, unlike an // OfflineAudioContext which renders sound into a buffer. -class AudioContext : public AbstractAudioContext { +class AudioContext : public BaseAudioContext { public: - static AbstractAudioContext* create(Document&, ExceptionState&); + static BaseAudioContext* create(Document&, ExceptionState&); ~AudioContext() override; DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.idl b/third_party/WebKit/Source/modules/webaudio/AudioContext.idl index aa56438..7b528c5 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioContext.idl +++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.idl
@@ -34,7 +34,7 @@ Constructor, ConstructorCallWith=Document, DependentLifetime, - ImplementedAs=AbstractAudioContext, + ImplementedAs=BaseAudioContext, NoInterfaceObject, RaisesException=Constructor, ] interface AudioContext : EventTarget {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp index f5eea24..b54d9b0 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp
@@ -23,9 +23,9 @@ */ #include "modules/webaudio/AudioDestinationNode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/audio/AudioUtilities.h" #include "platform/audio/DenormalDisabler.h" #include "wtf/Atomics.h" @@ -107,7 +107,7 @@ // ---------------------------------------------------------------- -AudioDestinationNode::AudioDestinationNode(AbstractAudioContext& context) +AudioDestinationNode::AudioDestinationNode(BaseAudioContext& context) : AudioNode(context) { }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h index a25e598b..2ecd418 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h
@@ -34,7 +34,7 @@ namespace blink { class AudioBus; -class AbstractAudioContext; +class BaseAudioContext; class AudioDestinationHandler : public AudioHandler, public AudioIOCallback { public: @@ -99,7 +99,7 @@ unsigned long maxChannelCount() const; protected: - AudioDestinationNode(AbstractAudioContext&); + AudioDestinationNode(BaseAudioContext&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp b/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp index 5badcca3..dacfa90 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp
@@ -34,7 +34,7 @@ namespace blink { -AudioListener::AudioListener(AbstractAudioContext& context) +AudioListener::AudioListener(BaseAudioContext& context) : m_positionX(AudioParam::create(context, ParamTypeAudioListenerPositionX, 0.0)) , m_positionY(AudioParam::create(context, ParamTypeAudioListenerPositionY, 0.0)) , m_positionZ(AudioParam::create(context, ParamTypeAudioListenerPositionZ, 0.0))
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioListener.h b/third_party/WebKit/Source/modules/webaudio/AudioListener.h index 457090e..70ffad1 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioListener.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioListener.h
@@ -45,7 +45,7 @@ class AudioListener : public GarbageCollectedFinalized<AudioListener>, public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static AudioListener* create(AbstractAudioContext& context) + static AudioListener* create(BaseAudioContext& context) { return new AudioListener(context); } @@ -143,7 +143,7 @@ DECLARE_TRACE(); private: - AudioListener(AbstractAudioContext&); + AudioListener(BaseAudioContext&); void setPosition(const FloatPoint3D&); void setOrientation(const FloatPoint3D&);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp index bc6ccd61..bbcd5208 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
@@ -26,10 +26,10 @@ #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/inspector/InstanceCounters.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" #include "modules/webaudio/AudioParam.h" +#include "modules/webaudio/BaseAudioContext.h" #include "wtf/Atomics.h" #if DEBUG_AUDIONODE_REFERENCES @@ -110,7 +110,7 @@ return m_node; } -AbstractAudioContext* AudioHandler::context() const +BaseAudioContext* AudioHandler::context() const { return m_context; } @@ -208,9 +208,9 @@ void AudioHandler::setChannelCount(unsigned long channelCount, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); - if (channelCount > 0 && channelCount <= AbstractAudioContext::maxNumberOfChannels()) { + if (channelCount > 0 && channelCount <= BaseAudioContext::maxNumberOfChannels()) { if (m_channelCount != channelCount) { m_channelCount = channelCount; if (m_channelCountMode != Max) @@ -224,7 +224,7 @@ channelCount, 1, ExceptionMessages::InclusiveBound, - AbstractAudioContext::maxNumberOfChannels(), + BaseAudioContext::maxNumberOfChannels(), ExceptionMessages::InclusiveBound)); } } @@ -246,7 +246,7 @@ void AudioHandler::setChannelCountMode(const String& mode, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); ChannelCountMode oldMode = m_channelCountMode; @@ -279,7 +279,7 @@ void AudioHandler::setChannelInterpretation(const String& interpretation, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); AudioBus::ChannelInterpretation oldMode = m_channelInterpretation; @@ -395,7 +395,7 @@ { if (m_isDisabled && m_connectionRefCount > 0) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); m_isDisabled = false; for (auto& output : m_outputs) @@ -527,7 +527,7 @@ } // ---------------------------------------------------------------- -AudioNode::AudioNode(AbstractAudioContext& context) +AudioNode::AudioNode(BaseAudioContext& context) : m_context(context) , m_handler(nullptr) { @@ -537,9 +537,9 @@ void AudioNode::dispose() { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); handler().dispose(); - if (context()->contextState() == AbstractAudioContext::Running) + if (context()->contextState() == BaseAudioContext::Running) context()->deferredTaskHandler().addRenderingOrphanHandler(m_handler.release()); } @@ -562,7 +562,7 @@ EventTargetWithInlineData::trace(visitor); } -AbstractAudioContext* AudioNode::context() const +BaseAudioContext* AudioNode::context() const { return m_context; } @@ -570,7 +570,7 @@ AudioNode* AudioNode::connect(AudioNode* destination, unsigned outputIndex, unsigned inputIndex, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if (context()->isContextClosed()) { exceptionState.throwDOMException( @@ -632,7 +632,7 @@ void AudioNode::connect(AudioParam* param, unsigned outputIndex, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if (context()->isContextClosed()) { exceptionState.throwDOMException( @@ -699,7 +699,7 @@ void AudioNode::disconnect() { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // Disconnect all outgoing connections. for (unsigned i = 0; i < numberOfOutputs(); ++i) @@ -709,7 +709,7 @@ void AudioNode::disconnect(unsigned outputIndex, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // Sanity check on the output index. if (outputIndex >= numberOfOutputs()) { @@ -731,7 +731,7 @@ void AudioNode::disconnect(AudioNode* destination, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); unsigned numberOfDisconnections = 0; @@ -756,7 +756,7 @@ void AudioNode::disconnect(AudioNode* destination, unsigned outputIndex, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if (outputIndex >= numberOfOutputs()) { // The output index is out of range. Throw an exception. @@ -791,7 +791,7 @@ void AudioNode::disconnect(AudioNode* destination, unsigned outputIndex, unsigned inputIndex, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if (outputIndex >= numberOfOutputs()) { exceptionState.throwDOMException( @@ -831,7 +831,7 @@ void AudioNode::disconnect(AudioParam* destinationParam, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // The number of disconnection made. unsigned numberOfDisconnections = 0; @@ -855,7 +855,7 @@ void AudioNode::disconnect(AudioParam* destinationParam, unsigned outputIndex, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if (outputIndex >= handler().numberOfOutputs()) { // The output index is out of range. Throw an exception. @@ -883,7 +883,7 @@ void AudioNode::disconnectWithoutException(unsigned outputIndex) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // Sanity check input and output indices. if (outputIndex >= handler().numberOfOutputs())
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/third_party/WebKit/Source/modules/webaudio/AudioNode.h index 9d7fda8..2c12012 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
@@ -39,14 +39,14 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioNode; class AudioNodeInput; class AudioNodeOutput; class AudioParam; class ExceptionState; -// An AudioNode is the basic building block for handling audio within an AbstractAudioContext. +// An AudioNode is the basic building block for handling audio within an BaseAudioContext. // It may be an audio source, an intermediate processing module, or an audio destination. // Each AudioNode can have inputs and/or outputs. An AudioSourceNode has no inputs and a single output. // An AudioDestinationNode has one input and no outputs and represents the final destination to the audio hardware. @@ -105,11 +105,11 @@ // nullptr after dispose(). We must not call node() in an audio rendering // thread. AudioNode* node() const; - // context() returns a valid object until the AbstractAudioContext dies, and returns + // context() returns a valid object until the BaseAudioContext dies, and returns // nullptr otherwise. This always returns a valid object in an audio // rendering thread, and inside dispose(). We must not call context() in // the destructor. - virtual AbstractAudioContext* context() const; + virtual BaseAudioContext* context() const; void clearContext() { m_context = nullptr; } enum ChannelCountMode { @@ -245,10 +245,10 @@ UntracedMember<AudioNode> m_node; // This untraced member is safe because this is cleared for all of live - // AudioHandlers when the AbstractAudioContext dies. Do not access m_context + // AudioHandlers when the BaseAudioContext dies. Do not access m_context // directly, use context() instead. // See http://crbug.com/404527 for the detail. - UntracedMember<AbstractAudioContext> m_context; + UntracedMember<BaseAudioContext> m_context; float m_sampleRate; Vector<std::unique_ptr<AudioNodeInput>> m_inputs; @@ -295,7 +295,7 @@ void disconnect(AudioNode*, unsigned outputIndex, unsigned inputIndex, ExceptionState&); void disconnect(AudioParam*, ExceptionState&); void disconnect(AudioParam*, unsigned outputIndex, ExceptionState&); - AbstractAudioContext* context() const; + BaseAudioContext* context() const; unsigned numberOfInputs() const; unsigned numberOfOutputs() const; unsigned long channelCount() const; @@ -316,7 +316,7 @@ void disconnectWithoutException(unsigned outputIndex); protected: - explicit AudioNode(AbstractAudioContext&); + explicit AudioNode(BaseAudioContext&); // This should be called in a constructor. void setHandler(PassRefPtr<AudioHandler>); @@ -328,7 +328,7 @@ // Returns true if the specified AudioParam was connected. bool disconnectFromOutputIfConnected(unsigned outputIndex, AudioParam&); - Member<AbstractAudioContext> m_context; + Member<BaseAudioContext> m_context; RefPtr<AudioHandler> m_handler; // Represents audio node graph with Oilpan references. N-th HeapHashSet // represents a set of AudioNode objects connected to this AudioNode's N-th
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp index ed17124..0a26595 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioNodeOutput.cpp
@@ -22,9 +22,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "wtf/PtrUtil.h" #include "wtf/Threading.h" #include <memory> @@ -43,7 +43,7 @@ , m_renderingFanOutCount(0) , m_renderingParamFanOutCount(0) { - ASSERT(numberOfChannels <= AbstractAudioContext::maxNumberOfChannels()); + DCHECK_LE(numberOfChannels, BaseAudioContext::maxNumberOfChannels()); m_internalBus = AudioBus::create(numberOfChannels, AudioHandler::ProcessingSizeInFrames); } @@ -66,7 +66,7 @@ void AudioNodeOutput::setNumberOfChannels(unsigned numberOfChannels) { - ASSERT(numberOfChannels <= AbstractAudioContext::maxNumberOfChannels()); + DCHECK_LE(numberOfChannels, BaseAudioContext::maxNumberOfChannels()); ASSERT(deferredTaskHandler().isGraphOwner()); m_desiredNumberOfChannels = numberOfChannels;
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp index 892c6829..b92edfcd 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp
@@ -39,7 +39,7 @@ const double AudioParamHandler::DefaultSmoothingConstant = 0.05; const double AudioParamHandler::SnapThreshold = 0.001; -AudioParamHandler::AudioParamHandler(AbstractAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, float maxValue) +AudioParamHandler::AudioParamHandler(BaseAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, float maxValue) : AudioSummingJunction(context.deferredTaskHandler()) , m_paramType(paramType) , m_intrinsicValue(defaultValue) @@ -338,13 +338,13 @@ // ---------------------------------------------------------------- -AudioParam::AudioParam(AbstractAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, float maxValue) +AudioParam::AudioParam(BaseAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, float maxValue) : m_handler(AudioParamHandler::create(context, paramType, defaultValue, minValue, maxValue)) , m_context(context) { } -AudioParam* AudioParam::create(AbstractAudioContext& context, AudioParamType paramType, double defaultValue) +AudioParam* AudioParam::create(BaseAudioContext& context, AudioParamType paramType, double defaultValue) { // Default nominal range is most negative float to most positive. This basically means any // value is valid, except that floating-point infinities are excluded. @@ -352,7 +352,7 @@ return new AudioParam(context, paramType, defaultValue, -limit, limit); } -AudioParam* AudioParam::create(AbstractAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, float maxValue) +AudioParam* AudioParam::create(BaseAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, float maxValue) { DCHECK_LE(minValue, maxValue); return new AudioParam(context, paramType, defaultValue, minValue, maxValue);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.h b/third_party/WebKit/Source/modules/webaudio/AudioParam.h index ebdc00bd..1afd6b33 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.h
@@ -31,9 +31,9 @@ #include "bindings/core/v8/ScriptWrappable.h" #include "core/dom/DOMTypedArray.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioParamTimeline.h" #include "modules/webaudio/AudioSummingJunction.h" +#include "modules/webaudio/BaseAudioContext.h" #include "wtf/PassRefPtr.h" #include "wtf/ThreadSafeRefCounted.h" #include "wtf/text/WTFString.h" @@ -100,7 +100,7 @@ static const double SnapThreshold; static PassRefPtr<AudioParamHandler> create( - AbstractAudioContext& context, + BaseAudioContext& context, AudioParamType paramType, double defaultValue, float minValue, @@ -157,7 +157,7 @@ void updateHistograms(float newValue); private: - AudioParamHandler(AbstractAudioContext&, AudioParamType, double defaultValue, float min, float max); + AudioParamHandler(BaseAudioContext&, AudioParamType, double defaultValue, float min, float max); void warnIfOutsideRange(float value, float minValue, float maxValue); @@ -191,14 +191,14 @@ class AudioParam final : public GarbageCollectedFinalized<AudioParam>, public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static AudioParam* create(AbstractAudioContext&, AudioParamType, double defaultValue); - static AudioParam* create(AbstractAudioContext&, AudioParamType, double defaultValue, float minValue, float maxValue); + static AudioParam* create(BaseAudioContext&, AudioParamType, double defaultValue); + static AudioParam* create(BaseAudioContext&, AudioParamType, double defaultValue, float minValue, float maxValue); DECLARE_TRACE(); // |handler| always returns a valid object. AudioParamHandler& handler() const { return *m_handler; } // |context| always returns a valid object. - AbstractAudioContext* context() const { return m_context; } + BaseAudioContext* context() const { return m_context; } AudioParamType getParamType() const { return handler().getParamType(); } void setParamType(AudioParamType); @@ -219,12 +219,12 @@ AudioParam* cancelScheduledValues(double startTime, ExceptionState&); private: - AudioParam(AbstractAudioContext&, AudioParamType, double defaultValue, float min, float max); + AudioParam(BaseAudioContext&, AudioParamType, double defaultValue, float min, float max); void warnIfOutsideRange(const String& paramMethd, float value); RefPtr<AudioParamHandler> m_handler; - Member<AbstractAudioContext> m_context; + Member<BaseAudioContext> m_context; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h index 4fee607..679ef89 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h
@@ -30,8 +30,8 @@ #define AudioParamTimeline_h #include "core/dom/DOMTypedArray.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioDestinationNode.h" +#include "modules/webaudio/BaseAudioContext.h" #include "wtf/Forward.h" #include "wtf/Threading.h" #include "wtf/Vector.h"
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp index 8e479f5..10d92836 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp
@@ -27,7 +27,7 @@ #include "core/dom/CrossThreadTask.h" #include "core/dom/ExceptionCode.h" #include "modules/EventModules.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/audio/AudioUtilities.h" #include "wtf/MathExtras.h" #include <algorithm> @@ -225,7 +225,7 @@ // ---------------------------------------------------------------- -AudioScheduledSourceNode::AudioScheduledSourceNode(AbstractAudioContext& context) +AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext& context) : AudioSourceNode(context) , ActiveScriptWrappable(this) {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h index 39c6d82..3b38e62 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.h
@@ -34,7 +34,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioBus; class AudioScheduledSourceHandler : public AudioHandler { @@ -138,7 +138,7 @@ DEFINE_INLINE_VIRTUAL_TRACE() { AudioSourceNode::trace(visitor); } protected: - explicit AudioScheduledSourceNode(AbstractAudioContext&); + explicit AudioScheduledSourceNode(BaseAudioContext&); AudioScheduledSourceHandler& audioScheduledSourceHandler() const; };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h b/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h index e0c9f39d..16628505 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioSourceNode.h
@@ -33,12 +33,12 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioSourceNode : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - AudioSourceNode(AbstractAudioContext& context) + AudioSourceNode(BaseAudioContext& context) : AudioNode(context) { } };
diff --git a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp similarity index 75% rename from third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp rename to third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp index f3e0445..2ebf22d 100644 --- a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -22,7 +22,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "bindings/core/v8/Dictionary.h" #include "bindings/core/v8/ExceptionMessages.h" @@ -87,7 +87,7 @@ } // anonymous namespace -AbstractAudioContext* AbstractAudioContext::create(Document& document, ExceptionState& exceptionState) +BaseAudioContext* BaseAudioContext::create(Document& document, ExceptionState& exceptionState) { return AudioContext::create(document, exceptionState); } @@ -96,7 +96,7 @@ // and OfflineAudioContext respectively. // Constructor for rendering to the audio hardware. -AbstractAudioContext::AbstractAudioContext(Document* document) +BaseAudioContext::BaseAudioContext(Document* document) : ActiveScriptWrappable(this) , ActiveDOMObject(document) , m_destinationNode(nullptr) @@ -124,7 +124,7 @@ } // Constructor for offline (non-realtime) rendering. -AbstractAudioContext::AbstractAudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) +BaseAudioContext::BaseAudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) : ActiveScriptWrappable(this) , ActiveDOMObject(document) , m_destinationNode(nullptr) @@ -147,18 +147,18 @@ m_userGestureRequired = true; } -AbstractAudioContext::~AbstractAudioContext() +BaseAudioContext::~BaseAudioContext() { deferredTaskHandler().contextWillBeDestroyed(); // AudioNodes keep a reference to their context, so there should be no way to be in the destructor if there are still AudioNodes around. - ASSERT(!isDestinationInitialized()); - ASSERT(!m_activeSourceNodes.size()); - ASSERT(!m_finishedSourceHandlers.size()); - ASSERT(!m_isResolvingResumePromises); - ASSERT(!m_resumeResolvers.size()); + DCHECK(!isDestinationInitialized()); + DCHECK(!m_activeSourceNodes.size()); + DCHECK(!m_finishedSourceHandlers.size()); + DCHECK(!m_isResolvingResumePromises); + DCHECK(!m_resumeResolvers.size()); } -void AbstractAudioContext::initialize() +void BaseAudioContext::initialize() { if (isDestinationInitialized()) return; @@ -173,7 +173,7 @@ } } -void AbstractAudioContext::clear() +void BaseAudioContext::clear() { m_destinationNode.clear(); // The audio rendering thread is dead. Nobody will schedule AudioHandler @@ -182,9 +182,9 @@ m_isCleared = true; } -void AbstractAudioContext::uninitialize() +void BaseAudioContext::uninitialize() { - ASSERT(isMainThread()); + DCHECK(isMainThread()); if (!isDestinationInitialized()) return; @@ -200,37 +200,37 @@ rejectPendingResolvers(); didClose(); - ASSERT(m_listener); + DCHECK(m_listener); m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); clear(); } -void AbstractAudioContext::stop() +void BaseAudioContext::stop() { uninitialize(); } -bool AbstractAudioContext::hasPendingActivity() const +bool BaseAudioContext::hasPendingActivity() const { // There's no pending activity if the audio context has been cleared. return !m_isCleared; } -AudioDestinationNode* AbstractAudioContext::destination() const +AudioDestinationNode* BaseAudioContext::destination() const { // Cannot be called from the audio thread because this method touches objects managed by Oilpan, // and the audio thread is not managed by Oilpan. - ASSERT(!isAudioThread()); + DCHECK(!isAudioThread()); return m_destinationNode; } -void AbstractAudioContext::throwExceptionForClosedState(ExceptionState& exceptionState) +void BaseAudioContext::throwExceptionForClosedState(ExceptionState& exceptionState) { exceptionState.throwDOMException(InvalidStateError, "AudioContext has been closed."); } -AudioBuffer* AbstractAudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) +AudioBuffer* BaseAudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) { // It's ok to call createBuffer, even if the context is closed because the AudioBuffer doesn't // really "belong" to any particular context. @@ -278,17 +278,17 @@ return buffer; } -ScriptPromise AbstractAudioContext::decodeAudioData(ScriptState* scriptState, DOMArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ExceptionState& exceptionState) +ScriptPromise BaseAudioContext::decodeAudioData(ScriptState* scriptState, DOMArrayBuffer* audioData, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback, ExceptionState& exceptionState) { - ASSERT(isMainThread()); - ASSERT(audioData); + DCHECK(isMainThread()); + DCHECK(audioData); ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); float rate = isContextClosed() ? closedContextSampleRate() : sampleRate(); - ASSERT(rate > 0); + DCHECK_GT(rate, 0); m_decodeAudioResolvers.add(resolver); m_audioDecoder.decodeAsync(audioData, rate, successCallback, errorCallback, resolver, this); @@ -296,9 +296,9 @@ return promise; } -void AbstractAudioContext::handleDecodeAudioData(AudioBuffer* audioBuffer, ScriptPromiseResolver* resolver, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback) +void BaseAudioContext::handleDecodeAudioData(AudioBuffer* audioBuffer, ScriptPromiseResolver* resolver, AudioBufferCallback* successCallback, AudioBufferCallback* errorCallback) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); if (audioBuffer) { // Resolve promise successfully and run the success callback @@ -314,13 +314,13 @@ } // We've resolved the promise. Remove it now. - ASSERT(m_decodeAudioResolvers.contains(resolver)); + DCHECK(m_decodeAudioResolvers.contains(resolver)); m_decodeAudioResolvers.remove(resolver); } -AudioBufferSourceNode* AbstractAudioContext::createBufferSource(ExceptionState& exceptionState) +AudioBufferSourceNode* BaseAudioContext::createBufferSource(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); AudioBufferSourceNode* node = AudioBufferSourceNode::create(*this, exceptionState); @@ -330,21 +330,21 @@ return node; } -MediaElementAudioSourceNode* AbstractAudioContext::createMediaElementSource(HTMLMediaElement* mediaElement, ExceptionState& exceptionState) +MediaElementAudioSourceNode* BaseAudioContext::createMediaElementSource(HTMLMediaElement* mediaElement, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return MediaElementAudioSourceNode::create(*this, *mediaElement, exceptionState); } -MediaStreamAudioSourceNode* AbstractAudioContext::createMediaStreamSource(MediaStream* mediaStream, ExceptionState& exceptionState) +MediaStreamAudioSourceNode* BaseAudioContext::createMediaStreamSource(MediaStream* mediaStream, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return MediaStreamAudioSourceNode::create(*this, *mediaStream, exceptionState); } -MediaStreamAudioDestinationNode* AbstractAudioContext::createMediaStreamDestination(ExceptionState& exceptionState) +MediaStreamAudioDestinationNode* BaseAudioContext::createMediaStreamDestination(ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -352,30 +352,30 @@ return MediaStreamAudioDestinationNode::create(*this, 2, exceptionState); } -ScriptProcessorNode* AbstractAudioContext::createScriptProcessor(ExceptionState& exceptionState) +ScriptProcessorNode* BaseAudioContext::createScriptProcessor(ExceptionState& exceptionState) { DCHECK(isMainThread()); return ScriptProcessorNode::create(*this, exceptionState); } -ScriptProcessorNode* AbstractAudioContext::createScriptProcessor(size_t bufferSize, ExceptionState& exceptionState) +ScriptProcessorNode* BaseAudioContext::createScriptProcessor(size_t bufferSize, ExceptionState& exceptionState) { DCHECK(isMainThread()); return ScriptProcessorNode::create(*this, bufferSize, exceptionState); } -ScriptProcessorNode* AbstractAudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionState& exceptionState) +ScriptProcessorNode* BaseAudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionState& exceptionState) { DCHECK(isMainThread()); return ScriptProcessorNode::create(*this, bufferSize, numberOfInputChannels, exceptionState); } -ScriptProcessorNode* AbstractAudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState& exceptionState) +ScriptProcessorNode* BaseAudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return ScriptProcessorNode::create( *this, @@ -385,135 +385,135 @@ exceptionState); } -StereoPannerNode* AbstractAudioContext::createStereoPanner(ExceptionState& exceptionState) +StereoPannerNode* BaseAudioContext::createStereoPanner(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return StereoPannerNode::create(*this, exceptionState); } -BiquadFilterNode* AbstractAudioContext::createBiquadFilter(ExceptionState& exceptionState) +BiquadFilterNode* BaseAudioContext::createBiquadFilter(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return BiquadFilterNode::create(*this, exceptionState); } -WaveShaperNode* AbstractAudioContext::createWaveShaper(ExceptionState& exceptionState) +WaveShaperNode* BaseAudioContext::createWaveShaper(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return WaveShaperNode::create(*this, exceptionState); } -PannerNode* AbstractAudioContext::createPanner(ExceptionState& exceptionState) +PannerNode* BaseAudioContext::createPanner(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return PannerNode::create(*this, exceptionState); } -ConvolverNode* AbstractAudioContext::createConvolver(ExceptionState& exceptionState) +ConvolverNode* BaseAudioContext::createConvolver(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return ConvolverNode::create(*this, exceptionState); } -DynamicsCompressorNode* AbstractAudioContext::createDynamicsCompressor(ExceptionState& exceptionState) +DynamicsCompressorNode* BaseAudioContext::createDynamicsCompressor(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return DynamicsCompressorNode::create(*this, exceptionState); } -AnalyserNode* AbstractAudioContext::createAnalyser(ExceptionState& exceptionState) +AnalyserNode* BaseAudioContext::createAnalyser(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return AnalyserNode::create(*this, exceptionState); } -GainNode* AbstractAudioContext::createGain(ExceptionState& exceptionState) +GainNode* BaseAudioContext::createGain(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return GainNode::create(*this, exceptionState); } -DelayNode* AbstractAudioContext::createDelay(ExceptionState& exceptionState) +DelayNode* BaseAudioContext::createDelay(ExceptionState& exceptionState) { DCHECK(isMainThread()); return DelayNode::create(*this, exceptionState); } -DelayNode* AbstractAudioContext::createDelay(double maxDelayTime, ExceptionState& exceptionState) +DelayNode* BaseAudioContext::createDelay(double maxDelayTime, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return DelayNode::create(*this, maxDelayTime, exceptionState); } -ChannelSplitterNode* AbstractAudioContext::createChannelSplitter(ExceptionState& exceptionState) +ChannelSplitterNode* BaseAudioContext::createChannelSplitter(ExceptionState& exceptionState) { DCHECK(isMainThread()); return ChannelSplitterNode::create(*this, exceptionState); } -ChannelSplitterNode* AbstractAudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionState& exceptionState) +ChannelSplitterNode* BaseAudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return ChannelSplitterNode::create(*this, numberOfOutputs, exceptionState); } -ChannelMergerNode* AbstractAudioContext::createChannelMerger(ExceptionState& exceptionState) +ChannelMergerNode* BaseAudioContext::createChannelMerger(ExceptionState& exceptionState) { DCHECK(isMainThread()); return ChannelMergerNode::create(*this, exceptionState); } -ChannelMergerNode* AbstractAudioContext::createChannelMerger(size_t numberOfInputs, ExceptionState& exceptionState) +ChannelMergerNode* BaseAudioContext::createChannelMerger(size_t numberOfInputs, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return ChannelMergerNode::create(*this, numberOfInputs, exceptionState); } -OscillatorNode* AbstractAudioContext::createOscillator(ExceptionState& exceptionState) +OscillatorNode* BaseAudioContext::createOscillator(ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return OscillatorNode::create(*this, exceptionState); } -PeriodicWave* AbstractAudioContext::createPeriodicWave(DOMFloat32Array* real, DOMFloat32Array* imag, ExceptionState& exceptionState) +PeriodicWave* BaseAudioContext::createPeriodicWave(DOMFloat32Array* real, DOMFloat32Array* imag, ExceptionState& exceptionState) { DCHECK(isMainThread()); return PeriodicWave::create(*this, real, imag, false, exceptionState); } -PeriodicWave* AbstractAudioContext::createPeriodicWave(DOMFloat32Array* real, DOMFloat32Array* imag, const PeriodicWaveConstraints& options, ExceptionState& exceptionState) +PeriodicWave* BaseAudioContext::createPeriodicWave(DOMFloat32Array* real, DOMFloat32Array* imag, const PeriodicWaveConstraints& options, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); bool disable = options.hasDisableNormalization() ? options.disableNormalization() : false; return PeriodicWave::create(*this, real, imag, disable, exceptionState); } -IIRFilterNode* AbstractAudioContext::createIIRFilter(Vector<double> feedforwardCoef, Vector<double> feedbackCoef, ExceptionState& exceptionState) +IIRFilterNode* BaseAudioContext::createIIRFilter(Vector<double> feedforwardCoef, Vector<double> feedbackCoef, ExceptionState& exceptionState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); return IIRFilterNode::create(*this, feedforwardCoef, feedbackCoef, exceptionState); } -PeriodicWave* AbstractAudioContext::periodicWave(int type) +PeriodicWave* BaseAudioContext::periodicWave(int type) { switch (type) { case OscillatorHandler::SINE: @@ -537,12 +537,12 @@ m_periodicWaveTriangle = PeriodicWave::createTriangle(sampleRate()); return m_periodicWaveTriangle; default: - ASSERT_NOT_REACHED(); + NOTREACHED(); return nullptr; } } -void AbstractAudioContext::recordUserGestureState() +void BaseAudioContext::recordUserGestureState() { DEFINE_STATIC_LOCAL(EnumerationHistogram, userGestureHistogram, ("WebAudio.UserGesture", UserGestureRecordMax)); @@ -561,7 +561,7 @@ m_userGestureRequired = false; } -String AbstractAudioContext::state() const +String BaseAudioContext::state() const { // These strings had better match the strings for AudioContextState in AudioContext.idl. switch (m_contextState) { @@ -572,25 +572,25 @@ case Closed: return "closed"; } - ASSERT_NOT_REACHED(); + NOTREACHED(); return ""; } -void AbstractAudioContext::setContextState(AudioContextState newState) +void BaseAudioContext::setContextState(AudioContextState newState) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); // Validate the transitions. The valid transitions are Suspended->Running, Running->Suspended, // and anything->Closed. switch (newState) { case Suspended: - ASSERT(m_contextState == Running); + DCHECK_EQ(m_contextState, Running); break; case Running: - ASSERT(m_contextState == Suspended); + DCHECK_EQ(m_contextState, Suspended); break; case Closed: - ASSERT(m_contextState != Closed); + DCHECK_NE(m_contextState, Closed); break; } @@ -603,23 +603,23 @@ // Notify context that state changed if (getExecutionContext()) - getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&AbstractAudioContext::notifyStateChange, wrapPersistent(this))); + getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&BaseAudioContext::notifyStateChange, wrapPersistent(this))); } -void AbstractAudioContext::notifyStateChange() +void BaseAudioContext::notifyStateChange() { dispatchEvent(Event::create(EventTypeNames::statechange)); } -void AbstractAudioContext::notifySourceNodeFinishedProcessing(AudioHandler* handler) +void BaseAudioContext::notifySourceNodeFinishedProcessing(AudioHandler* handler) { - ASSERT(isAudioThread()); + DCHECK(isAudioThread()); m_finishedSourceHandlers.append(handler); } -void AbstractAudioContext::removeFinishedSourceNodes() +void BaseAudioContext::removeFinishedSourceNodes() { - ASSERT(isMainThread()); + DCHECK(isMainThread()); AutoLocker locker(this); // Quadratic worst case, but sizes of both vectors are considered // manageable, especially |m_finishedSourceNodes| is likely to be short. @@ -631,10 +631,10 @@ m_finishedSourceNodes.clear(); } -void AbstractAudioContext::releaseFinishedSourceNodes() +void BaseAudioContext::releaseFinishedSourceNodes() { ASSERT(isGraphOwner()); - ASSERT(isAudioThread()); + DCHECK(isAudioThread()); bool didRemove = false; for (AudioHandler* handler : m_finishedSourceHandlers) { for (AudioNode* node : m_activeSourceNodes) { @@ -649,30 +649,30 @@ } } if (didRemove) - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&AbstractAudioContext::removeFinishedSourceNodes, wrapCrossThreadPersistent(this))); + Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&BaseAudioContext::removeFinishedSourceNodes, wrapCrossThreadPersistent(this))); m_finishedSourceHandlers.clear(); } -void AbstractAudioContext::notifySourceNodeStartedProcessing(AudioNode* node) +void BaseAudioContext::notifySourceNodeStartedProcessing(AudioNode* node) { - ASSERT(isMainThread()); + DCHECK(isMainThread()); AutoLocker locker(this); m_activeSourceNodes.append(node); node->handler().makeConnection(); } -void AbstractAudioContext::releaseActiveSourceNodes() +void BaseAudioContext::releaseActiveSourceNodes() { - ASSERT(isMainThread()); + DCHECK(isMainThread()); for (auto& sourceNode : m_activeSourceNodes) sourceNode->handler().breakConnection(); m_activeSourceNodes.clear(); } -void AbstractAudioContext::handleStoppableSourceNodes() +void BaseAudioContext::handleStoppableSourceNodes() { ASSERT(isGraphOwner()); @@ -691,9 +691,9 @@ } } -void AbstractAudioContext::handlePreRenderTasks() +void BaseAudioContext::handlePreRenderTasks() { - ASSERT(isAudioThread()); + DCHECK(isAudioThread()); // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes). // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes. @@ -712,9 +712,9 @@ } } -void AbstractAudioContext::handlePostRenderTasks() +void BaseAudioContext::handlePostRenderTasks() { - ASSERT(isAudioThread()); + DCHECK(isAudioThread()); // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed @@ -733,9 +733,9 @@ } } -void AbstractAudioContext::resolvePromisesForResumeOnMainThread() +void BaseAudioContext::resolvePromisesForResumeOnMainThread() { - ASSERT(isMainThread()); + DCHECK(isMainThread()); AutoLocker locker(this); for (auto& resolver : m_resumeResolvers) { @@ -751,10 +751,10 @@ m_isResolvingResumePromises = false; } -void AbstractAudioContext::resolvePromisesForResume() +void BaseAudioContext::resolvePromisesForResume() { - // This runs inside the AbstractAudioContext's lock when handling pre-render tasks. - ASSERT(isAudioThread()); + // This runs inside the BaseAudioContext's lock when handling pre-render tasks. + DCHECK(isAudioThread()); ASSERT(isGraphOwner()); // Resolve any pending promises created by resume(). Only do this if we haven't already started @@ -762,11 +762,11 @@ // promises in the main thread. if (!m_isResolvingResumePromises && m_resumeResolvers.size() > 0) { m_isResolvingResumePromises = true; - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&AbstractAudioContext::resolvePromisesForResumeOnMainThread, wrapCrossThreadPersistent(this))); + Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&BaseAudioContext::resolvePromisesForResumeOnMainThread, wrapCrossThreadPersistent(this))); } } -void AbstractAudioContext::rejectPendingDecodeAudioDataResolvers() +void BaseAudioContext::rejectPendingDecodeAudioDataResolvers() { // Now reject any pending decodeAudioData resolvers for (auto& resolver : m_decodeAudioResolvers) @@ -774,9 +774,9 @@ m_decodeAudioResolvers.clear(); } -void AbstractAudioContext::rejectPendingResolvers() +void BaseAudioContext::rejectPendingResolvers() { - ASSERT(isMainThread()); + DCHECK(isMainThread()); // Audio context is closing down so reject any resume promises that are still pending. @@ -789,21 +789,21 @@ rejectPendingDecodeAudioDataResolvers(); } -const AtomicString& AbstractAudioContext::interfaceName() const +const AtomicString& BaseAudioContext::interfaceName() const { return EventTargetNames::AudioContext; } -ExecutionContext* AbstractAudioContext::getExecutionContext() const +ExecutionContext* BaseAudioContext::getExecutionContext() const { return ActiveDOMObject::getExecutionContext(); } -void AbstractAudioContext::startRendering() +void BaseAudioContext::startRendering() { // This is called for both online and offline contexts. - ASSERT(isMainThread()); - ASSERT(m_destinationNode); + DCHECK(isMainThread()); + DCHECK(m_destinationNode); recordUserGestureState(); @@ -813,7 +813,7 @@ } } -DEFINE_TRACE(AbstractAudioContext) +DEFINE_TRACE(BaseAudioContext) { visitor->trace(m_destinationNode); visitor->trace(m_listener); @@ -829,7 +829,7 @@ ActiveDOMObject::trace(visitor); } -SecurityOrigin* AbstractAudioContext::getSecurityOrigin() const +SecurityOrigin* BaseAudioContext::getSecurityOrigin() const { if (getExecutionContext()) return getExecutionContext()->getSecurityOrigin();
diff --git a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h similarity index 95% rename from third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h rename to third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h index 942b7ff..585dec1 100644 --- a/third_party/WebKit/Source/modules/webaudio/AbstractAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
@@ -22,8 +22,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AbstractAudioContext_h -#define AbstractAudioContext_h +#ifndef BaseAudioContext_h +#define BaseAudioContext_h #include "bindings/core/v8/ActiveScriptWrappable.h" #include "bindings/core/v8/ScriptPromise.h" @@ -79,11 +79,11 @@ class StereoPannerNode; class WaveShaperNode; -// AbstractAudioContext is the cornerstone of the web audio API and all AudioNodes are created from it. +// BaseAudioContext is the cornerstone of the web audio API and all AudioNodes are created from it. // For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism. -class MODULES_EXPORT AbstractAudioContext : public EventTargetWithInlineData, public ActiveScriptWrappable, public ActiveDOMObject { - USING_GARBAGE_COLLECTED_MIXIN(AbstractAudioContext); +class MODULES_EXPORT BaseAudioContext : public EventTargetWithInlineData, public ActiveScriptWrappable, public ActiveDOMObject { + USING_GARBAGE_COLLECTED_MIXIN(BaseAudioContext); DEFINE_WRAPPERTYPEINFO(); public: // The state of an audio context. On creation, the state is Suspended. The state is Running if @@ -97,9 +97,9 @@ }; // Create an AudioContext for rendering to the audio hardware. - static AbstractAudioContext* create(Document&, ExceptionState&); + static BaseAudioContext* create(Document&, ExceptionState&); - ~AbstractAudioContext() override; + ~BaseAudioContext() override; DECLARE_VIRTUAL_TRACE(); @@ -216,7 +216,7 @@ // Keeps track of the number of connections made. void incrementConnectionCount() { - ASSERT(isMainThread()); + DCHECK(isMainThread()); m_connectionCount++; } @@ -268,8 +268,8 @@ void recordUserGestureState(); protected: - explicit AbstractAudioContext(Document*); - AbstractAudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); + explicit BaseAudioContext(Document*); + BaseAudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate); void initialize(); void uninitialize(); @@ -350,7 +350,7 @@ // Graph locking. RefPtr<DeferredTaskHandler> m_deferredTaskHandler; - // The state of the AbstractAudioContext. + // The state of the BaseAudioContext. AudioContextState m_contextState; AsyncAudioDecoder m_audioDecoder; @@ -379,4 +379,4 @@ } // namespace blink -#endif // AbstractAudioContext_h +#endif // BaseAudioContext_h
diff --git a/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp b/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp index 7053583..8daf32d 100644 --- a/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.cpp
@@ -30,7 +30,7 @@ namespace blink { -BiquadFilterNode::BiquadFilterNode(AbstractAudioContext& context) +BiquadFilterNode::BiquadFilterNode(BaseAudioContext& context) : AudioNode(context) , m_frequency(AudioParam::create(context, ParamTypeBiquadFilterFrequency, 350.0, 0, context.sampleRate() / 2)) , m_q(AudioParam::create(context, ParamTypeBiquadFilterQ, 1.0)) @@ -54,7 +54,7 @@ setType("lowpass"); } -BiquadFilterNode* BiquadFilterNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +BiquadFilterNode* BiquadFilterNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h b/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h index f75c80c..96a56e5 100644 --- a/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h +++ b/third_party/WebKit/Source/modules/webaudio/BiquadFilterNode.h
@@ -31,7 +31,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioParam; class BiquadFilterNode final : public AudioNode { @@ -49,7 +49,7 @@ ALLPASS = 7 }; - static BiquadFilterNode* create(AbstractAudioContext&, ExceptionState&); + static BiquadFilterNode* create(BaseAudioContext&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); @@ -66,7 +66,7 @@ void getFrequencyResponse(const DOMFloat32Array* frequencyHz, DOMFloat32Array* magResponse, DOMFloat32Array* phaseResponse); private: - BiquadFilterNode(AbstractAudioContext&); + BiquadFilterNode(BaseAudioContext&); BiquadProcessor* getBiquadProcessor() const; bool setType(unsigned); // Returns true on success.
diff --git a/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp b/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp index ecdecdb..c19aad8 100644 --- a/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.cpp
@@ -31,9 +31,9 @@ #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" namespace blink { @@ -94,7 +94,7 @@ void ChannelMergerHandler::setChannelCount(unsigned long channelCount, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // channelCount must be 1. if (channelCount != 1) { @@ -107,7 +107,7 @@ void ChannelMergerHandler::setChannelCountMode(const String& mode, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // channcelCountMode must be 'explicit'. if (mode != "explicit") { @@ -119,13 +119,13 @@ // ---------------------------------------------------------------- -ChannelMergerNode::ChannelMergerNode(AbstractAudioContext& context, unsigned numberOfInputs) +ChannelMergerNode::ChannelMergerNode(BaseAudioContext& context, unsigned numberOfInputs) : AudioNode(context) { setHandler(ChannelMergerHandler::create(*this, context.sampleRate(), numberOfInputs)); } -ChannelMergerNode* ChannelMergerNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +ChannelMergerNode* ChannelMergerNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -133,7 +133,7 @@ return create(context, 6, exceptionState); } -ChannelMergerNode* ChannelMergerNode::create(AbstractAudioContext& context, unsigned numberOfInputs, ExceptionState& exceptionState) +ChannelMergerNode* ChannelMergerNode::create(BaseAudioContext& context, unsigned numberOfInputs, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -142,7 +142,7 @@ return nullptr; } - if (!numberOfInputs || numberOfInputs > AbstractAudioContext::maxNumberOfChannels()) { + if (!numberOfInputs || numberOfInputs > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( IndexSizeError, ExceptionMessages::indexOutsideRange<size_t>( @@ -150,7 +150,7 @@ numberOfInputs, 1, ExceptionMessages::InclusiveBound, - AbstractAudioContext::maxNumberOfChannels(), + BaseAudioContext::maxNumberOfChannels(), ExceptionMessages::InclusiveBound)); return nullptr; }
diff --git a/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h b/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h index 009ba99..2a76ce2 100644 --- a/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h +++ b/third_party/WebKit/Source/modules/webaudio/ChannelMergerNode.h
@@ -34,7 +34,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ChannelMergerHandler final : public AudioHandler { public: @@ -51,11 +51,11 @@ class ChannelMergerNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static ChannelMergerNode* create(AbstractAudioContext&, ExceptionState&); - static ChannelMergerNode* create(AbstractAudioContext&, unsigned numberOfInputs, ExceptionState&); + static ChannelMergerNode* create(BaseAudioContext&, ExceptionState&); + static ChannelMergerNode* create(BaseAudioContext&, unsigned numberOfInputs, ExceptionState&); private: - ChannelMergerNode(AbstractAudioContext&, unsigned numberOfInputs); + ChannelMergerNode(BaseAudioContext&, unsigned numberOfInputs); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp b/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp index 0b6d715..b4c87c43 100644 --- a/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.cpp
@@ -26,9 +26,9 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" namespace blink { @@ -74,13 +74,13 @@ // ---------------------------------------------------------------- -ChannelSplitterNode::ChannelSplitterNode(AbstractAudioContext& context, unsigned numberOfOutputs) +ChannelSplitterNode::ChannelSplitterNode(BaseAudioContext& context, unsigned numberOfOutputs) : AudioNode(context) { setHandler(ChannelSplitterHandler::create(*this, context.sampleRate(), numberOfOutputs)); } -ChannelSplitterNode* ChannelSplitterNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +ChannelSplitterNode* ChannelSplitterNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -88,7 +88,7 @@ return create(context, 6, exceptionState); } -ChannelSplitterNode* ChannelSplitterNode::create(AbstractAudioContext& context, unsigned numberOfOutputs, ExceptionState& exceptionState) +ChannelSplitterNode* ChannelSplitterNode::create(BaseAudioContext& context, unsigned numberOfOutputs, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -97,7 +97,7 @@ return nullptr; } - if (!numberOfOutputs || numberOfOutputs > AbstractAudioContext::maxNumberOfChannels()) { + if (!numberOfOutputs || numberOfOutputs > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( IndexSizeError, ExceptionMessages::indexOutsideRange<size_t>( @@ -105,7 +105,7 @@ numberOfOutputs, 1, ExceptionMessages::InclusiveBound, - AbstractAudioContext::maxNumberOfChannels(), + BaseAudioContext::maxNumberOfChannels(), ExceptionMessages::InclusiveBound)); return nullptr; }
diff --git a/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h b/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h index d210c89..1c094f7 100644 --- a/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h +++ b/third_party/WebKit/Source/modules/webaudio/ChannelSplitterNode.h
@@ -30,7 +30,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ChannelSplitterHandler final : public AudioHandler { public: @@ -46,11 +46,11 @@ class ChannelSplitterNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static ChannelSplitterNode* create(AbstractAudioContext&, ExceptionState&); - static ChannelSplitterNode* create(AbstractAudioContext&, unsigned numberOfOutputs, ExceptionState&); + static ChannelSplitterNode* create(BaseAudioContext&, ExceptionState&); + static ChannelSplitterNode* create(BaseAudioContext&, unsigned numberOfOutputs, ExceptionState&); private: - ChannelSplitterNode(AbstractAudioContext&, unsigned numberOfOutputs); + ChannelSplitterNode(BaseAudioContext&, unsigned numberOfOutputs); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp index dee1806..2f2b30e7d 100644 --- a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.cpp
@@ -167,13 +167,13 @@ // ---------------------------------------------------------------- -ConvolverNode::ConvolverNode(AbstractAudioContext& context) +ConvolverNode::ConvolverNode(BaseAudioContext& context) : AudioNode(context) { setHandler(ConvolverHandler::create(*this, context.sampleRate())); } -ConvolverNode* ConvolverNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +ConvolverNode* ConvolverNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h index d27be4e..bf73e60 100644 --- a/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h +++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNode.h
@@ -75,7 +75,7 @@ class MODULES_EXPORT ConvolverNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static ConvolverNode* create(AbstractAudioContext&, ExceptionState&); + static ConvolverNode* create(BaseAudioContext&, ExceptionState&); AudioBuffer* buffer() const; void setBuffer(AudioBuffer*, ExceptionState&); @@ -83,7 +83,7 @@ void setNormalize(bool); private: - ConvolverNode(AbstractAudioContext&); + ConvolverNode(BaseAudioContext&); ConvolverHandler& convolverHandler() const; FRIEND_TEST_ALL_PREFIXES(ConvolverNodeTest, ReverbLifetime);
diff --git a/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp index ff2545cd..18563b2 100644 --- a/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ConvolverNodeTest.cpp
@@ -19,7 +19,7 @@ EXPECT_FALSE(handler.m_reverb); node->setBuffer(AudioBuffer::create(2, 1, 48000), ASSERT_NO_EXCEPTION); EXPECT_TRUE(handler.m_reverb); - AbstractAudioContext::AutoLocker locker(context); + BaseAudioContext::AutoLocker locker(context); handler.dispose(); // m_reverb should live after dispose() because an audio thread is using it. EXPECT_TRUE(handler.m_reverb);
diff --git a/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp index a6fc982..280a5a5 100644 --- a/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.cpp
@@ -26,7 +26,7 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/Logging.h" namespace blink { @@ -138,13 +138,13 @@ // ---------------------------------------------------------------- -DefaultAudioDestinationNode::DefaultAudioDestinationNode(AbstractAudioContext& context) +DefaultAudioDestinationNode::DefaultAudioDestinationNode(BaseAudioContext& context) : AudioDestinationNode(context) { setHandler(DefaultAudioDestinationHandler::create(*this)); } -DefaultAudioDestinationNode* DefaultAudioDestinationNode::create(AbstractAudioContext* context) +DefaultAudioDestinationNode* DefaultAudioDestinationNode::create(BaseAudioContext* context) { return new DefaultAudioDestinationNode(*context); }
diff --git a/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h index 4940ac8..ac57af9 100644 --- a/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h +++ b/third_party/WebKit/Source/modules/webaudio/DefaultAudioDestinationNode.h
@@ -31,7 +31,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class DefaultAudioDestinationHandler final : public AudioDestinationHandler { @@ -61,10 +61,10 @@ class DefaultAudioDestinationNode final : public AudioDestinationNode { public: - static DefaultAudioDestinationNode* create(AbstractAudioContext*); + static DefaultAudioDestinationNode* create(BaseAudioContext*); private: - explicit DefaultAudioDestinationNode(AbstractAudioContext&); + explicit DefaultAudioDestinationNode(BaseAudioContext&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp index 3decf57..f4f79b8 100644 --- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
@@ -263,7 +263,7 @@ // Some handlers might live because of their cross thread tasks. } -DeferredTaskHandler::AutoLocker::AutoLocker(AbstractAudioContext* context) +DeferredTaskHandler::AutoLocker::AutoLocker(BaseAudioContext* context) : m_handler(context->deferredTaskHandler()) { m_handler.lock();
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h index 1594e99..afd32cc 100644 --- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h +++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.h
@@ -38,7 +38,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class OfflineAudioContext; class AudioHandler; class AudioNodeOutput; @@ -46,15 +46,15 @@ // DeferredTaskHandler manages the major part of pre- and post- rendering tasks, // and provides a lock mechanism against the audio rendering graph. A -// DeferredTaskHandler object is created when an AbstractAudioContext object is created. +// DeferredTaskHandler object is created when an BaseAudioContext object is created. // -// DeferredTaskHandler outlives the AbstractAudioContext only if all of the following +// DeferredTaskHandler outlives the BaseAudioContext only if all of the following // conditions match: // - An audio rendering thread is running, // - It is requested to stop, // - The audio rendering thread calls requestToDeleteHandlersOnMainThread(), // - It posts a task of deleteHandlersOnMainThread(), and -// - GC happens and it collects the AbstractAudioContext before the task execution. +// - GC happens and it collects the BaseAudioContext before the task execution. // class MODULES_EXPORT DeferredTaskHandler final : public ThreadSafeRefCounted<DeferredTaskHandler> { public: @@ -64,7 +64,7 @@ void handleDeferredTasks(); void contextWillBeDestroyed(); - // AbstractAudioContext can pull node(s) at the end of each render quantum even when + // BaseAudioContext can pull node(s) at the end of each render quantum even when // they are not connected to any downstream nodes. These two methods are // called by the nodes who want to add/remove themselves into/from the // automatic pull lists. @@ -135,7 +135,7 @@ { m_handler.lock(); } - explicit AutoLocker(AbstractAudioContext*); + explicit AutoLocker(BaseAudioContext*); ~AutoLocker() { m_handler.unlock(); }
diff --git a/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp b/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp index eb35ee1..5e9a141 100644 --- a/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DelayNode.cpp
@@ -35,7 +35,7 @@ const double maximumAllowedDelayTime = 180; -DelayNode::DelayNode(AbstractAudioContext& context, double maxDelayTime) +DelayNode::DelayNode(BaseAudioContext& context, double maxDelayTime) : AudioNode(context) , m_delayTime(AudioParam::create(context, ParamTypeDelayDelayTime, 0.0, 0.0, maxDelayTime)) { @@ -50,7 +50,7 @@ maxDelayTime)))); } -DelayNode* DelayNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +DelayNode* DelayNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -58,7 +58,7 @@ return create(context, 1, exceptionState); } -DelayNode* DelayNode::create(AbstractAudioContext& context, double maxDelayTime, ExceptionState& exceptionState) +DelayNode* DelayNode::create(BaseAudioContext& context, double maxDelayTime, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/DelayNode.h b/third_party/WebKit/Source/modules/webaudio/DelayNode.h index a697871a..1ebcc41 100644 --- a/third_party/WebKit/Source/modules/webaudio/DelayNode.h +++ b/third_party/WebKit/Source/modules/webaudio/DelayNode.h
@@ -29,19 +29,19 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class DelayNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static DelayNode* create(AbstractAudioContext&, ExceptionState&); - static DelayNode* create(AbstractAudioContext&, double maxDelayTime, ExceptionState&); + static DelayNode* create(BaseAudioContext&, ExceptionState&); + static DelayNode* create(BaseAudioContext&, double maxDelayTime, ExceptionState&); DECLARE_VIRTUAL_TRACE(); AudioParam* delayTime(); private: - DelayNode(AbstractAudioContext&, double maxDelayTime); + DelayNode(BaseAudioContext&, double maxDelayTime); Member<AudioParam> m_delayTime; };
diff --git a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp index d12764d70..f13f67c 100644 --- a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.cpp
@@ -126,7 +126,7 @@ // ---------------------------------------------------------------- -DynamicsCompressorNode::DynamicsCompressorNode(AbstractAudioContext& context) +DynamicsCompressorNode::DynamicsCompressorNode(BaseAudioContext& context) : AudioNode(context) , m_threshold(AudioParam::create(context, ParamTypeDynamicsCompressorThreshold, -24, -100, 0)) , m_knee(AudioParam::create(context, ParamTypeDynamicsCompressorKnee, 30, 0, 40)) @@ -144,7 +144,7 @@ m_release->handler())); } -DynamicsCompressorNode* DynamicsCompressorNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +DynamicsCompressorNode* DynamicsCompressorNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h index 27e2201..25c1ab3 100644 --- a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h +++ b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNode.h
@@ -33,7 +33,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class DynamicsCompressor; class MODULES_EXPORT DynamicsCompressorHandler final : public AudioHandler { @@ -81,7 +81,7 @@ class MODULES_EXPORT DynamicsCompressorNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static DynamicsCompressorNode* create(AbstractAudioContext&, ExceptionState&); + static DynamicsCompressorNode* create(BaseAudioContext&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); AudioParam* threshold() const; @@ -92,7 +92,7 @@ AudioParam* release() const; private: - DynamicsCompressorNode(AbstractAudioContext&); + DynamicsCompressorNode(BaseAudioContext&); DynamicsCompressorHandler& dynamicsCompressorHandler() const; Member<AudioParam> m_threshold;
diff --git a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp index e04a567..4f3379d 100644 --- a/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/DynamicsCompressorNodeTest.cpp
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "core/testing/DummyPageHolder.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "modules/webaudio/DynamicsCompressorNode.h" #include "modules/webaudio/OfflineAudioContext.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,7 +18,7 @@ DynamicsCompressorNode* node = context->createDynamicsCompressor(ASSERT_NO_EXCEPTION); DynamicsCompressorHandler& handler = node->dynamicsCompressorHandler(); EXPECT_TRUE(handler.m_dynamicsCompressor); - AbstractAudioContext::AutoLocker locker(context); + BaseAudioContext::AutoLocker locker(context); handler.dispose(); // m_dynamicsCompressor should live after dispose() because an audio thread // is using it.
diff --git a/third_party/WebKit/Source/modules/webaudio/GainNode.cpp b/third_party/WebKit/Source/modules/webaudio/GainNode.cpp index 01b1380..5921dfb 100644 --- a/third_party/WebKit/Source/modules/webaudio/GainNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/GainNode.cpp
@@ -119,14 +119,14 @@ // ---------------------------------------------------------------- -GainNode::GainNode(AbstractAudioContext& context) +GainNode::GainNode(BaseAudioContext& context) : AudioNode(context) , m_gain(AudioParam::create(context, ParamTypeGainGain, 1.0)) { setHandler(GainHandler::create(*this, context.sampleRate(), m_gain->handler())); } -GainNode* GainNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +GainNode* GainNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/GainNode.h b/third_party/WebKit/Source/modules/webaudio/GainNode.h index 7fea960..0f8cffbbd 100644 --- a/third_party/WebKit/Source/modules/webaudio/GainNode.h +++ b/third_party/WebKit/Source/modules/webaudio/GainNode.h
@@ -32,7 +32,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; // GainNode is an AudioNode with one input and one output which applies a gain (volume) change to the audio signal. // De-zippering (smoothing) is applied when the gain value is changed dynamically. @@ -59,13 +59,13 @@ class GainNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static GainNode* create(AbstractAudioContext&, ExceptionState&); + static GainNode* create(BaseAudioContext&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); AudioParam* gain() const; private: - GainNode(AbstractAudioContext&); + GainNode(BaseAudioContext&); Member<AudioParam> m_gain; };
diff --git a/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp b/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp index 98d008e..38bf3bc 100644 --- a/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp
@@ -7,14 +7,14 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioBasicProcessorHandler.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/Histogram.h" #include "wtf/PtrUtil.h" namespace blink { -IIRFilterNode::IIRFilterNode(AbstractAudioContext& context, const Vector<double> feedforwardCoef, const Vector<double> feedbackCoef) +IIRFilterNode::IIRFilterNode(BaseAudioContext& context, const Vector<double> feedforwardCoef, const Vector<double> feedbackCoef) : AudioNode(context) { setHandler(AudioBasicProcessorHandler::create( @@ -30,7 +30,7 @@ } IIRFilterNode* IIRFilterNode::create( - AbstractAudioContext& context, + BaseAudioContext& context, const Vector<double> feedforwardCoef, const Vector<double> feedbackCoef, ExceptionState& exceptionState)
diff --git a/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.h b/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.h index 761e7e3..1a7f4f3a 100644 --- a/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.h +++ b/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.h
@@ -11,14 +11,14 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class IIRFilterNode : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: static IIRFilterNode* create( - AbstractAudioContext&, + BaseAudioContext&, const Vector<double> feedforward, const Vector<double> feedback, ExceptionState&); @@ -30,7 +30,7 @@ void getFrequencyResponse(const DOMFloat32Array* frequencyHz, DOMFloat32Array* magResponse, DOMFloat32Array* phaseResponse, ExceptionState&); private: - IIRFilterNode(AbstractAudioContext&, const Vector<double> denominator, const Vector<double> numerator); + IIRFilterNode(BaseAudioContext&, const Vector<double> denominator, const Vector<double> numerator); IIRProcessor* iirProcessor() const; };
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp index f4309bb..9659b09 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp
@@ -25,8 +25,8 @@ #include "core/dom/CrossThreadTask.h" #include "core/html/HTMLMediaElement.h" #include "core/inspector/ConsoleMessage.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "modules/webaudio/MediaElementAudioSourceNode.h" #include "platform/Logging.h" #include "platform/audio/AudioUtilities.h" @@ -72,7 +72,7 @@ void MediaElementAudioSourceHandler::setFormat(size_t numberOfChannels, float sourceSampleRate) { if (numberOfChannels != m_sourceNumberOfChannels || sourceSampleRate != m_sourceSampleRate) { - if (!numberOfChannels || numberOfChannels > AbstractAudioContext::maxNumberOfChannels() || !AudioUtilities::isValidAudioBufferSampleRate(sourceSampleRate)) { + if (!numberOfChannels || numberOfChannels > BaseAudioContext::maxNumberOfChannels() || !AudioUtilities::isValidAudioBufferSampleRate(sourceSampleRate)) { // process() will generate silence for these uninitialized values. DLOG(ERROR) << "setFormat(" << numberOfChannels << ", " << sourceSampleRate << ") - unhandled format change"; // Synchronize with process(). @@ -99,7 +99,7 @@ { // The context must be locked when changing the number of output channels. - AbstractAudioContext::AutoLocker contextLocker(context()); + BaseAudioContext::AutoLocker contextLocker(context()); // Do any necesssary re-configuration to the output's number of channels. output(0).setNumberOfChannels(numberOfChannels); @@ -201,13 +201,13 @@ // ---------------------------------------------------------------- -MediaElementAudioSourceNode::MediaElementAudioSourceNode(AbstractAudioContext& context, HTMLMediaElement& mediaElement) +MediaElementAudioSourceNode::MediaElementAudioSourceNode(BaseAudioContext& context, HTMLMediaElement& mediaElement) : AudioSourceNode(context) { setHandler(MediaElementAudioSourceHandler::create(*this, mediaElement)); } -MediaElementAudioSourceNode* MediaElementAudioSourceNode::create(AbstractAudioContext& context, HTMLMediaElement& mediaElement, ExceptionState& exceptionState) +MediaElementAudioSourceNode* MediaElementAudioSourceNode::create(BaseAudioContext& context, HTMLMediaElement& mediaElement, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h index 20fa9a6..f1b64e2 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h +++ b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.h
@@ -34,7 +34,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class HTMLMediaElement; class MediaElementAudioSourceHandler final : public AudioHandler { @@ -100,7 +100,7 @@ DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(MediaElementAudioSourceNode); public: - static MediaElementAudioSourceNode* create(AbstractAudioContext&, HTMLMediaElement&, ExceptionState&); + static MediaElementAudioSourceNode* create(BaseAudioContext&, HTMLMediaElement&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); MediaElementAudioSourceHandler& mediaElementAudioSourceHandler() const; @@ -113,7 +113,7 @@ void unlock() override; private: - MediaElementAudioSourceNode(AbstractAudioContext&, HTMLMediaElement&); + MediaElementAudioSourceNode(BaseAudioContext&, HTMLMediaElement&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp index efa097e7..ed2c72d3 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.cpp
@@ -26,8 +26,8 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/UUID.h" #include "platform/mediastream/MediaStreamCenter.h" #include "public/platform/WebRTCPeerConnectionHandler.h" @@ -103,7 +103,7 @@ // TODO(hongchan): There might be a data race here since both threads // have access to m_mixBus. if (!exceptionState.hadException() && this->channelCount() != oldChannelCount && isInitialized()) { - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); m_mixBus = AudioBus::create(channelCount, ProcessingSizeInFrames); m_source->setAudioFormat(channelCount, context()->sampleRate()); } @@ -116,13 +116,13 @@ // ---------------------------------------------------------------- -MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AbstractAudioContext& context, size_t numberOfChannels) +MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(BaseAudioContext& context, size_t numberOfChannels) : AudioBasicInspectorNode(context) { setHandler(MediaStreamAudioDestinationHandler::create(*this, numberOfChannels)); } -MediaStreamAudioDestinationNode* MediaStreamAudioDestinationNode::create(AbstractAudioContext& context, size_t numberOfChannels, ExceptionState& exceptionState) +MediaStreamAudioDestinationNode* MediaStreamAudioDestinationNode::create(BaseAudioContext& context, size_t numberOfChannels, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h index 2267b15..abeaf17 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h +++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioDestinationNode.h
@@ -32,7 +32,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class MediaStreamAudioDestinationHandler final : public AudioBasicInspectorHandler { public: @@ -64,11 +64,11 @@ class MediaStreamAudioDestinationNode final : public AudioBasicInspectorNode { DEFINE_WRAPPERTYPEINFO(); public: - static MediaStreamAudioDestinationNode* create(AbstractAudioContext&, size_t numberOfChannels, ExceptionState&); + static MediaStreamAudioDestinationNode* create(BaseAudioContext&, size_t numberOfChannels, ExceptionState&); MediaStream* stream() const; private: - MediaStreamAudioDestinationNode(AbstractAudioContext&, size_t numberOfChannels); + MediaStreamAudioDestinationNode(BaseAudioContext&, size_t numberOfChannels); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp index e976165..bc503d7 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.cpp
@@ -25,8 +25,8 @@ #include "modules/webaudio/MediaStreamAudioSourceNode.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/Logging.h" #include "wtf/Locker.h" #include <memory> @@ -61,7 +61,7 @@ { if (numberOfChannels != m_sourceNumberOfChannels || sourceSampleRate != sampleRate()) { // The sample-rate must be equal to the context's sample-rate. - if (!numberOfChannels || numberOfChannels > AbstractAudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate()) { + if (!numberOfChannels || numberOfChannels > BaseAudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate()) { // process() will generate silence for these uninitialized values. DLOG(ERROR) << "setFormat(" << numberOfChannels << ", " << sourceSampleRate << ") - unhandled format change"; m_sourceNumberOfChannels = 0; @@ -75,7 +75,7 @@ { // The context must be locked when changing the number of output channels. - AbstractAudioContext::AutoLocker contextLocker(context()); + BaseAudioContext::AutoLocker contextLocker(context()); // Do any necesssary re-configuration to the output's number of channels. output(0).setNumberOfChannels(numberOfChannels); @@ -111,13 +111,13 @@ // ---------------------------------------------------------------- -MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AbstractAudioContext& context, MediaStream& mediaStream, MediaStreamTrack* audioTrack, std::unique_ptr<AudioSourceProvider> audioSourceProvider) +MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(BaseAudioContext& context, MediaStream& mediaStream, MediaStreamTrack* audioTrack, std::unique_ptr<AudioSourceProvider> audioSourceProvider) : AudioSourceNode(context) { setHandler(MediaStreamAudioSourceHandler::create(*this, mediaStream, audioTrack, std::move(audioSourceProvider))); } -MediaStreamAudioSourceNode* MediaStreamAudioSourceNode::create(AbstractAudioContext& context, MediaStream& mediaStream, ExceptionState& exceptionState) +MediaStreamAudioSourceNode* MediaStreamAudioSourceNode::create(BaseAudioContext& context, MediaStream& mediaStream, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h index d0f448d..9b22353 100644 --- a/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h +++ b/third_party/WebKit/Source/modules/webaudio/MediaStreamAudioSourceNode.h
@@ -35,7 +35,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class MediaStreamAudioSourceHandler final : public AudioHandler { public: @@ -73,7 +73,7 @@ DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(MediaStreamAudioSourceNode); public: - static MediaStreamAudioSourceNode* create(AbstractAudioContext&, MediaStream&, ExceptionState&); + static MediaStreamAudioSourceNode* create(BaseAudioContext&, MediaStream&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); MediaStreamAudioSourceHandler& mediaStreamAudioSourceHandler() const; @@ -83,7 +83,7 @@ void setFormat(size_t numberOfChannels, float sampleRate) override; private: - MediaStreamAudioSourceNode(AbstractAudioContext&, MediaStream&, MediaStreamTrack*, std::unique_ptr<AudioSourceProvider>); + MediaStreamAudioSourceNode(BaseAudioContext&, MediaStream&, MediaStreamTrack*, std::unique_ptr<AudioSourceProvider>); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp index d8db167..442ccda 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -57,7 +57,7 @@ return nullptr; } - if (numberOfChannels > AbstractAudioContext::maxNumberOfChannels()) { + if (numberOfChannels > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( IndexSizeError, ExceptionMessages::indexOutsideRange<unsigned>( @@ -65,7 +65,7 @@ numberOfChannels, 0, ExceptionMessages::InclusiveBound, - AbstractAudioContext::maxNumberOfChannels(), + BaseAudioContext::maxNumberOfChannels(), ExceptionMessages::InclusiveBound)); return nullptr; } @@ -114,7 +114,7 @@ } OfflineAudioContext::OfflineAudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionState& exceptionState) - : AbstractAudioContext(document, numberOfChannels, numberOfFrames, sampleRate) + : BaseAudioContext(document, numberOfChannels, numberOfFrames, sampleRate) , m_isRenderingStarted(false) , m_totalRenderFrames(numberOfFrames) { @@ -144,7 +144,7 @@ visitor->trace(m_renderTarget); visitor->trace(m_completeResolver); visitor->trace(m_scheduledSuspends); - AbstractAudioContext::trace(visitor); + BaseAudioContext::trace(visitor); } ScriptPromise OfflineAudioContext::startOfflineRendering(ScriptState* scriptState) @@ -205,7 +205,7 @@ ScriptPromise OfflineAudioContext::suspendContext(ScriptState* scriptState) { // This CANNOT be called on OfflineAudioContext; this is only to implement - // the pure virtual interface from AbstractAudioContext. + // the pure virtual interface from BaseAudioContext. RELEASE_NOTREACHED(); return ScriptPromise();
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h index e347a644..a3051138 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
@@ -26,7 +26,7 @@ #define OfflineAudioContext_h #include "modules/ModulesExport.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "wtf/HashMap.h" namespace blink { @@ -34,7 +34,7 @@ class ExceptionState; class OfflineAudioDestinationHandler; -class MODULES_EXPORT OfflineAudioContext final : public AbstractAudioContext { +class MODULES_EXPORT OfflineAudioContext final : public BaseAudioContext { DEFINE_WRAPPERTYPEINFO(); public: static OfflineAudioContext* create(ExecutionContext*, unsigned numberOfChannels, unsigned numberOfFrames, float sampleRate, ExceptionState&); @@ -51,7 +51,7 @@ ScriptPromise suspendContext(ScriptState*, double); ScriptPromise resumeContext(ScriptState*) final; - // This is to implement the pure virtual method from AbstractAudioContext. + // This is to implement the pure virtual method from BaseAudioContext. // CANNOT be called from an OfflineAudioContext. ScriptPromise suspendContext(ScriptState*) final; @@ -64,7 +64,7 @@ // Fire completion event when the rendering is finished. void fireCompletionEvent(); - // This is same with the online version in AbstractAudioContext class except + // This is same with the online version in BaseAudioContext class except // for returning a boolean value after checking the scheduled suspends. bool handlePreOfflineRenderTasks();
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp index eda9d5e..32c5a6f 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
@@ -23,9 +23,9 @@ */ #include "core/dom/CrossThreadTask.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "modules/webaudio/OfflineAudioContext.h" #include "modules/webaudio/OfflineAudioDestinationNode.h" #include "platform/audio/AudioBus.h" @@ -314,13 +314,13 @@ // ---------------------------------------------------------------- -OfflineAudioDestinationNode::OfflineAudioDestinationNode(AbstractAudioContext& context, AudioBuffer* renderTarget) +OfflineAudioDestinationNode::OfflineAudioDestinationNode(BaseAudioContext& context, AudioBuffer* renderTarget) : AudioDestinationNode(context) { setHandler(OfflineAudioDestinationHandler::create(*this, renderTarget)); } -OfflineAudioDestinationNode* OfflineAudioDestinationNode::create(AbstractAudioContext* context, AudioBuffer* renderTarget) +OfflineAudioDestinationNode* OfflineAudioDestinationNode::create(BaseAudioContext* context, AudioBuffer* renderTarget) { return new OfflineAudioDestinationNode(*context, renderTarget); }
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h index b4a4716..6eb2259 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.h
@@ -35,7 +35,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioBus; class OfflineAudioContext; @@ -117,10 +117,10 @@ class OfflineAudioDestinationNode final : public AudioDestinationNode { public: - static OfflineAudioDestinationNode* create(AbstractAudioContext*, AudioBuffer* renderTarget); + static OfflineAudioDestinationNode* create(BaseAudioContext*, AudioBuffer* renderTarget); private: - OfflineAudioDestinationNode(AbstractAudioContext&, AudioBuffer* renderTarget); + OfflineAudioDestinationNode(BaseAudioContext&, AudioBuffer* renderTarget); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp b/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp index ae98a06..ebbbd472 100644 --- a/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OscillatorNode.cpp
@@ -330,7 +330,7 @@ // ---------------------------------------------------------------- -OscillatorNode::OscillatorNode(AbstractAudioContext& context) +OscillatorNode::OscillatorNode(BaseAudioContext& context) : AudioScheduledSourceNode(context) // Use musical pitch standard A440 as a default. , m_frequency(AudioParam::create(context, ParamTypeOscillatorFrequency, 440, @@ -342,7 +342,7 @@ setHandler(OscillatorHandler::create(*this, context.sampleRate(), m_frequency->handler(), m_detune->handler())); } -OscillatorNode* OscillatorNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +OscillatorNode* OscillatorNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h b/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h index f515946e..9714472f 100644 --- a/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h +++ b/third_party/WebKit/Source/modules/webaudio/OscillatorNode.h
@@ -34,7 +34,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class PeriodicWave; @@ -99,7 +99,7 @@ class OscillatorNode final : public AudioScheduledSourceNode { DEFINE_WRAPPERTYPEINFO(); public: - static OscillatorNode* create(AbstractAudioContext&, ExceptionState&); + static OscillatorNode* create(BaseAudioContext&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); String type() const; @@ -109,7 +109,7 @@ void setPeriodicWave(PeriodicWave*); private: - OscillatorNode(AbstractAudioContext&); + OscillatorNode(BaseAudioContext&); OscillatorHandler& oscillatorHandler() const; Member<AudioParam> m_frequency;
diff --git a/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp b/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp index 44ccd79b..5f4d35f 100644 --- a/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/PannerNode.cpp
@@ -27,10 +27,10 @@ #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioBufferSourceNode.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/Histogram.h" #include "platform/audio/HRTFPanner.h" #include "wtf/MathExtras.h" @@ -134,7 +134,7 @@ // HRTFDatabase should be loaded before proceeding when the panning model is HRTF. if (m_panningModel == Panner::PanningModelHRTF && !listener()->isHRTFDatabaseLoaded()) { if (context()->hasRealtimeConstraint()) { - // Some AbstractAudioContexts cannot block on the HRTFDatabase loader. + // Some BaseAudioContexts cannot block on the HRTFDatabase loader. destination->zero(); return; } @@ -563,7 +563,7 @@ void PannerHandler::setChannelCount(unsigned long channelCount, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // A PannerNode only supports 1 or 2 channels if (channelCount > 0 && channelCount <= 2) { @@ -588,7 +588,7 @@ void PannerHandler::setChannelCountMode(const String& mode, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); ChannelCountMode oldMode = m_channelCountMode; @@ -640,7 +640,7 @@ } // ---------------------------------------------------------------- -PannerNode::PannerNode(AbstractAudioContext& context) +PannerNode::PannerNode(BaseAudioContext& context) : AudioNode(context) , m_positionX(AudioParam::create(context, ParamTypePannerPositionX, 0.0)) , m_positionY(AudioParam::create(context, ParamTypePannerPositionY, 0.0)) @@ -660,7 +660,7 @@ m_orientationZ->handler())); } -PannerNode* PannerNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +PannerNode* PannerNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/PannerNode.h b/third_party/WebKit/Source/modules/webaudio/PannerNode.h index ca5fde4..3eda63e 100644 --- a/third_party/WebKit/Source/modules/webaudio/PannerNode.h +++ b/third_party/WebKit/Source/modules/webaudio/PannerNode.h
@@ -38,7 +38,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; // PannerNode is an AudioNode with one input and one output. // It positions a sound in 3D space, with the exact effect dependent on the panning model. @@ -123,7 +123,7 @@ AudioParamHandler& orientationY, AudioParamHandler& orientationZ); - // AbstractAudioContext's listener + // BaseAudioContext's listener AudioListener* listener(); bool setPanningModel(unsigned); // Returns true on success. @@ -207,7 +207,7 @@ class PannerNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static PannerNode* create(AbstractAudioContext&, ExceptionState&); + static PannerNode* create(BaseAudioContext&, ExceptionState&); PannerHandler& pannerHandler() const; DECLARE_VIRTUAL_TRACE(); @@ -242,7 +242,7 @@ void setConeOuterGain(double); private: - PannerNode(AbstractAudioContext&); + PannerNode(BaseAudioContext&); Member<AudioParam> m_positionX; Member<AudioParam> m_positionY;
diff --git a/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp b/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp index fdd7ebd..69321b1 100644 --- a/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp +++ b/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp
@@ -29,7 +29,7 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" +#include "modules/webaudio/BaseAudioContext.h" #include "modules/webaudio/OscillatorNode.h" #include "modules/webaudio/PeriodicWave.h" #include "platform/audio/FFTFrame.h" @@ -52,7 +52,7 @@ using namespace VectorMath; PeriodicWave* PeriodicWave::create( - AbstractAudioContext& context, + BaseAudioContext& context, DOMFloat32Array* real, DOMFloat32Array* imag, bool disableNormalization,
diff --git a/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h b/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h index a5629b9..1e34ba64 100644 --- a/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h +++ b/third_party/WebKit/Source/modules/webaudio/PeriodicWave.h
@@ -38,7 +38,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class PeriodicWave final : public GarbageCollectedFinalized<PeriodicWave>, public ScriptWrappable { @@ -51,7 +51,7 @@ // Creates an arbitrary periodic wave given the frequency components (Fourier coefficients). static PeriodicWave* create( - AbstractAudioContext&, + BaseAudioContext&, DOMFloat32Array* real, DOMFloat32Array* imag, bool normalize,
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp index 35604ca..935354e 100644 --- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
@@ -27,11 +27,11 @@ #include "core/dom/CrossThreadTask.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioBuffer.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" #include "modules/webaudio/AudioProcessingEvent.h" +#include "modules/webaudio/BaseAudioContext.h" #include "public/platform/Platform.h" namespace blink { @@ -49,7 +49,7 @@ if (m_bufferSize < ProcessingSizeInFrames) m_bufferSize = ProcessingSizeInFrames; - ASSERT(numberOfInputChannels <= AbstractAudioContext::maxNumberOfChannels()); + DCHECK_LE(numberOfInputChannels, BaseAudioContext::maxNumberOfChannels()); addInput(); addOutput(numberOfOutputChannels); @@ -213,7 +213,7 @@ void ScriptProcessorHandler::setChannelCount(unsigned long channelCount, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if (channelCount != m_channelCount) { exceptionState.throwDOMException( @@ -225,7 +225,7 @@ void ScriptProcessorHandler::setChannelCountMode(const String& mode, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); if ((mode == "max") || (mode == "clamped-max")) { exceptionState.throwDOMException( @@ -236,7 +236,7 @@ // ---------------------------------------------------------------- -ScriptProcessorNode::ScriptProcessorNode(AbstractAudioContext& context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels) +ScriptProcessorNode::ScriptProcessorNode(BaseAudioContext& context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels) : AudioNode(context) , ActiveScriptWrappable(this) { @@ -260,7 +260,7 @@ } ScriptProcessorNode* ScriptProcessorNode::create( - AbstractAudioContext& context, + BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -271,7 +271,7 @@ } ScriptProcessorNode* ScriptProcessorNode::create( - AbstractAudioContext& context, + BaseAudioContext& context, size_t bufferSize, ExceptionState& exceptionState) { @@ -282,7 +282,7 @@ } ScriptProcessorNode* ScriptProcessorNode::create( - AbstractAudioContext& context, + BaseAudioContext& context, size_t bufferSize, unsigned numberOfInputChannels, ExceptionState& exceptionState) @@ -294,7 +294,7 @@ } ScriptProcessorNode* ScriptProcessorNode::create( - AbstractAudioContext& context, + BaseAudioContext& context, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, @@ -314,21 +314,21 @@ return nullptr; } - if (numberOfInputChannels > AbstractAudioContext::maxNumberOfChannels()) { + if (numberOfInputChannels > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( IndexSizeError, "number of input channels (" + String::number(numberOfInputChannels) + ") exceeds maximum (" - + String::number(AbstractAudioContext::maxNumberOfChannels()) + ")."); + + String::number(BaseAudioContext::maxNumberOfChannels()) + ")."); return nullptr; } - if (numberOfOutputChannels > AbstractAudioContext::maxNumberOfChannels()) { + if (numberOfOutputChannels > BaseAudioContext::maxNumberOfChannels()) { exceptionState.throwDOMException( IndexSizeError, "number of output channels (" + String::number(numberOfInputChannels) + ") exceeds maximum (" - + String::number(AbstractAudioContext::maxNumberOfChannels()) + ")."); + + String::number(BaseAudioContext::maxNumberOfChannels()) + ")."); return nullptr; }
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h index 28a186c..a018e487 100644 --- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h +++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.h
@@ -36,7 +36,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class AudioBuffer; // ScriptProcessorNode is an AudioNode which allows for arbitrary synthesis or processing directly using JavaScript. @@ -103,10 +103,10 @@ // latency. Higher numbers will be necessary to avoid audio breakup and // glitches. // The value chosen must carefully balance between latency and audio quality. - static ScriptProcessorNode* create(AbstractAudioContext&, ExceptionState&); - static ScriptProcessorNode* create(AbstractAudioContext&, size_t bufferSize, ExceptionState&); - static ScriptProcessorNode* create(AbstractAudioContext&, size_t bufferSize, unsigned numberOfInputChannels, ExceptionState&); - static ScriptProcessorNode* create(AbstractAudioContext&, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, ExceptionState&); + static ScriptProcessorNode* create(BaseAudioContext&, ExceptionState&); + static ScriptProcessorNode* create(BaseAudioContext&, size_t bufferSize, ExceptionState&); + static ScriptProcessorNode* create(BaseAudioContext&, size_t bufferSize, unsigned numberOfInputChannels, ExceptionState&); + static ScriptProcessorNode* create(BaseAudioContext&, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, ExceptionState&); DEFINE_ATTRIBUTE_EVENT_LISTENER(audioprocess); size_t bufferSize() const; @@ -117,7 +117,7 @@ DEFINE_INLINE_VIRTUAL_TRACE() { AudioNode::trace(visitor); } private: - ScriptProcessorNode(AbstractAudioContext&, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels); + ScriptProcessorNode(BaseAudioContext&, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp index d22af2d..51d8108 100644 --- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNodeTest.cpp
@@ -18,7 +18,7 @@ ScriptProcessorHandler& handler = static_cast<ScriptProcessorHandler&>(node->handler()); EXPECT_EQ(2u, handler.m_inputBuffers.size()); EXPECT_EQ(2u, handler.m_outputBuffers.size()); - AbstractAudioContext::AutoLocker locker(context); + BaseAudioContext::AutoLocker locker(context); handler.dispose(); // Buffers should live after dispose() because an audio thread is using // them.
diff --git a/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.cpp b/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.cpp index b957b8fe..4962c83 100644 --- a/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.cpp
@@ -7,9 +7,9 @@ #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioNodeInput.h" #include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/BaseAudioContext.h" #include "platform/audio/StereoPanner.h" #include "wtf/MathExtras.h" @@ -83,7 +83,7 @@ void StereoPannerHandler::setChannelCount(unsigned long channelCount, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); // A PannerNode only supports 1 or 2 channels if (channelCount > 0 && channelCount <= 2) { @@ -108,7 +108,7 @@ void StereoPannerHandler::setChannelCountMode(const String& mode, ExceptionState& exceptionState) { ASSERT(isMainThread()); - AbstractAudioContext::AutoLocker locker(context()); + BaseAudioContext::AutoLocker locker(context()); ChannelCountMode oldMode = m_channelCountMode; @@ -134,14 +134,14 @@ // ---------------------------------------------------------------- -StereoPannerNode::StereoPannerNode(AbstractAudioContext& context) +StereoPannerNode::StereoPannerNode(BaseAudioContext& context) : AudioNode(context) , m_pan(AudioParam::create(context, ParamTypeStereoPannerPan, 0, -1, 1)) { setHandler(StereoPannerHandler::create(*this, context.sampleRate(), m_pan->handler())); } -StereoPannerNode* StereoPannerNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +StereoPannerNode* StereoPannerNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread());
diff --git a/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h b/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h index 4837c43..c450d47 100644 --- a/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h +++ b/third_party/WebKit/Source/modules/webaudio/StereoPannerNode.h
@@ -14,7 +14,7 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; // StereoPannerNode is an AudioNode with one input and one output. It is // specifically designed for equal-power stereo panning. @@ -43,13 +43,13 @@ class StereoPannerNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static StereoPannerNode* create(AbstractAudioContext&, ExceptionState&); + static StereoPannerNode* create(BaseAudioContext&, ExceptionState&); DECLARE_VIRTUAL_TRACE(); AudioParam* pan() const; private: - StereoPannerNode(AbstractAudioContext&); + StereoPannerNode(BaseAudioContext&); Member<AudioParam> m_pan; };
diff --git a/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp b/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp index 2f02f608..204d29e 100644 --- a/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/StereoPannerNodeTest.cpp
@@ -17,7 +17,7 @@ StereoPannerNode* node = context->createStereoPanner(ASSERT_NO_EXCEPTION); StereoPannerHandler& handler = static_cast<StereoPannerHandler&>(node->handler()); EXPECT_TRUE(handler.m_stereoPanner); - AbstractAudioContext::AutoLocker locker(context); + BaseAudioContext::AutoLocker locker(context); handler.dispose(); // m_stereoPanner should live after dispose() because an audio thread is // using it.
diff --git a/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp b/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp index ae9ae322..c0046ed 100644 --- a/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp +++ b/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.cpp
@@ -25,14 +25,14 @@ #include "bindings/core/v8/ExceptionMessages.h" #include "bindings/core/v8/ExceptionState.h" #include "core/dom/ExceptionCode.h" -#include "modules/webaudio/AbstractAudioContext.h" #include "modules/webaudio/AudioBasicProcessorHandler.h" +#include "modules/webaudio/BaseAudioContext.h" #include "modules/webaudio/WaveShaperNode.h" #include "wtf/PtrUtil.h" namespace blink { -WaveShaperNode::WaveShaperNode(AbstractAudioContext& context) +WaveShaperNode::WaveShaperNode(BaseAudioContext& context) : AudioNode(context) { setHandler(AudioBasicProcessorHandler::create(AudioHandler::NodeTypeWaveShaper, *this, context.sampleRate(), wrapUnique(new WaveShaperProcessor(context.sampleRate(), 1)))); @@ -40,7 +40,7 @@ handler().initialize(); } -WaveShaperNode* WaveShaperNode::create(AbstractAudioContext& context, ExceptionState& exceptionState) +WaveShaperNode* WaveShaperNode::create(BaseAudioContext& context, ExceptionState& exceptionState) { DCHECK(isMainThread()); @@ -86,7 +86,7 @@ // This is to synchronize with the changes made in // AudioBasicProcessorNode::checkNumberOfChannelsForInput() where we can // initialize() and uninitialize(). - AbstractAudioContext::AutoLocker contextLocker(context()); + BaseAudioContext::AutoLocker contextLocker(context()); if (type == "none") { getWaveShaperProcessor()->setOversample(WaveShaperProcessor::OverSampleNone);
diff --git a/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h b/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h index bfaf39f9..b089ca88 100644 --- a/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h +++ b/third_party/WebKit/Source/modules/webaudio/WaveShaperNode.h
@@ -31,13 +31,13 @@ namespace blink { -class AbstractAudioContext; +class BaseAudioContext; class ExceptionState; class WaveShaperNode final : public AudioNode { DEFINE_WRAPPERTYPEINFO(); public: - static WaveShaperNode* create(AbstractAudioContext&, ExceptionState&); + static WaveShaperNode* create(BaseAudioContext&, ExceptionState&); // setCurve() is called on the main thread. void setCurve(DOMFloat32Array*, ExceptionState&); @@ -47,7 +47,7 @@ String oversample() const; private: - explicit WaveShaperNode(AbstractAudioContext&); + explicit WaveShaperNode(BaseAudioContext&); WaveShaperProcessor* getWaveShaperProcessor() const; };
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h index 68959acd..9867f46 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContext.h
@@ -32,7 +32,6 @@ CanvasRenderingContext::ContextType getContextType() const override { return CanvasRenderingContext::ContextWebgl2; } ImageBitmap* transferToImageBitmap(ExceptionState&) final; - unsigned version() const override { return 2; } String contextName() const override { return "WebGL2RenderingContext"; } void registerContextExtensions() override; void setCanvasGetContextResult(RenderingContext&) final;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp index a9e38544..7580935 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -115,7 +115,7 @@ }; WebGL2RenderingContextBase::WebGL2RenderingContextBase(HTMLCanvasElement* passedCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes) - : WebGLRenderingContextBase(passedCanvas, std::move(contextProvider), requestedAttributes) + : WebGLRenderingContextBase(passedCanvas, std::move(contextProvider), requestedAttributes, 2) { m_supportedInternalFormatsStorage.insert(kSupportedInternalFormatsStorage, kSupportedInternalFormatsStorage + WTF_ARRAY_LENGTH(kSupportedInternalFormatsStorage)); m_supportedInternalFormatsStorage.insert(kCompressedTextureFormatsETC2EAC, kCompressedTextureFormatsETC2EAC + WTF_ARRAY_LENGTH(kCompressedTextureFormatsETC2EAC));
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp index c2509ac..846ddbb 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.cpp
@@ -123,12 +123,12 @@ } WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes) - : WebGLRenderingContextBase(passedCanvas, std::move(contextProvider), requestedAttributes) + : WebGLRenderingContextBase(passedCanvas, std::move(contextProvider), requestedAttributes, 1) { } WebGLRenderingContext::WebGLRenderingContext(OffscreenCanvas* passedOffscreenCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes) - : WebGLRenderingContextBase(passedOffscreenCanvas, std::move(contextProvider), requestedAttributes) + : WebGLRenderingContextBase(passedOffscreenCanvas, std::move(contextProvider), requestedAttributes, 1) { }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h index d3d7b2bd..de964da 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContext.h
@@ -53,7 +53,6 @@ CanvasRenderingContext::ContextType getContextType() const override { return CanvasRenderingContext::ContextWebgl; } ImageBitmap* transferToImageBitmap(ExceptionState&) final; - unsigned version() const override { return 1; } String contextName() const override { return "WebGLRenderingContext"; } void registerContextExtensions() override; void setCanvasGetContextResult(RenderingContext&) final;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index f516c0d..ebed1a6 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -885,15 +885,21 @@ } // namespace -WebGLRenderingContextBase::WebGLRenderingContextBase(OffscreenCanvas* passedOffscreenCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes) - : WebGLRenderingContextBase(nullptr, passedOffscreenCanvas, std::move(contextProvider), requestedAttributes) +WebGLRenderingContextBase::WebGLRenderingContextBase(OffscreenCanvas* passedOffscreenCanvas, + std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, + const WebGLContextAttributes& requestedAttributes, unsigned version) + : WebGLRenderingContextBase(nullptr, passedOffscreenCanvas, std::move(contextProvider), requestedAttributes, version) { } -WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes) - : WebGLRenderingContextBase(passedCanvas, nullptr, std::move(contextProvider), requestedAttributes) +WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, + std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, + const WebGLContextAttributes& requestedAttributes, unsigned version) + : WebGLRenderingContextBase(passedCanvas, nullptr, std::move(contextProvider), requestedAttributes, version) { } -WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, OffscreenCanvas* passedOffscreenCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const WebGLContextAttributes& requestedAttributes) +WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, + OffscreenCanvas* passedOffscreenCanvas, std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, + const WebGLContextAttributes& requestedAttributes, unsigned version) : CanvasRenderingContext(passedCanvas, passedOffscreenCanvas) , m_isHidden(false) , m_contextLostMode(NotLostContext) @@ -913,6 +919,7 @@ , m_isOESTextureHalfFloatFormatsTypesAdded(false) , m_isWebGLDepthTextureFormatsTypesAdded(false) , m_isEXTsRGBFormatsTypesAdded(false) + , m_version(version) { ASSERT(contextProvider); @@ -952,6 +959,14 @@ bool wantStencilBuffer = m_requestedAttributes.stencil(); bool wantAntialiasing = m_requestedAttributes.antialias(); DrawingBuffer::PreserveDrawingBuffer preserve = m_requestedAttributes.preserveDrawingBuffer() ? DrawingBuffer::Preserve : DrawingBuffer::Discard; + DrawingBuffer::WebGLVersion webGLVersion = DrawingBuffer::WebGL1; + if (version() == 1) { + webGLVersion = DrawingBuffer::WebGL1; + } else if (version() == 2) { + webGLVersion = DrawingBuffer::WebGL2; + } else { + NOTREACHED(); + } return DrawingBuffer::create( std::move(contextProvider), clampedCanvasSize(), @@ -960,7 +975,8 @@ wantDepthBuffer, wantStencilBuffer, wantAntialiasing, - preserve); + preserve, + webGLVersion); } void WebGLRenderingContextBase::initializeNewContext() @@ -5482,10 +5498,6 @@ for (size_t i = 0; i < string.length(); ++i) { // line-continuation character \ is supported in WebGL 2.0. if (isWebGL2OrHigher() && string[i] == '\\') { - if (i + 1 >= string.length() || (string[i + 1] != '\n' && string[i + 1] != '\r')) { - synthesizeGLError(GL_INVALID_VALUE, "shaderSource", "line-continuation character is not immediately preceding a new-line"); - return false; - } continue; } if (!validateCharacter(string[i])) {
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h index a78cbf82..5d31262 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -131,7 +131,6 @@ public: ~WebGLRenderingContextBase() override; - virtual unsigned version() const = 0; virtual String contextName() const = 0; virtual void registerContextExtensions() = 0; @@ -143,6 +142,8 @@ static std::unique_ptr<WebGraphicsContext3DProvider> createWebGraphicsContext3DProvider(ScriptState*, WebGLContextAttributes, unsigned webGLVersion); static void forceNextWebGLContextCreationToFail(); + unsigned version() const { return m_version; } + int drawingBufferWidth() const; int drawingBufferHeight() const; @@ -430,8 +431,8 @@ friend class ScopedTexture2DRestorer; friend class ScopedFramebufferRestorer; - WebGLRenderingContextBase(HTMLCanvasElement*, std::unique_ptr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&); - WebGLRenderingContextBase(OffscreenCanvas*, std::unique_ptr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&); + WebGLRenderingContextBase(HTMLCanvasElement*, std::unique_ptr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&, unsigned); + WebGLRenderingContextBase(OffscreenCanvas*, std::unique_ptr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&, unsigned); PassRefPtr<DrawingBuffer> createDrawingBuffer(std::unique_ptr<WebGraphicsContext3DProvider>); void setupFlags(); @@ -1107,10 +1108,12 @@ static const char* getTexImageFunctionName(TexImageFunctionID); private: - WebGLRenderingContextBase(HTMLCanvasElement*, OffscreenCanvas*, std::unique_ptr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&); + WebGLRenderingContextBase(HTMLCanvasElement*, OffscreenCanvas*, std::unique_ptr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&, unsigned); static std::unique_ptr<WebGraphicsContext3DProvider> createContextProviderInternal(HTMLCanvasElement*, ScriptState*, WebGLContextAttributes, unsigned); void texImageCanvasByGPU(HTMLCanvasElement*, GLuint, GLenum, GLenum, GLint); void texImageBitmapByGPU(ImageBitmap*, GLuint, GLenum, GLenum, GLint, bool); + + const unsigned m_version; }; DEFINE_TYPE_CASTS(WebGLRenderingContextBase, CanvasRenderingContext, context, context->is3d(), context.is3d());
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index d5afa1e..e0c6480 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -106,7 +106,6 @@ ImageRenderingPixelated status=stable IndexedDBExperimental status=experimental InertTopControls status=experimental -InputDeviceCapabilities status=stable InputEvent status=experimental InputModeAttribute status=experimental InputMultipleFieldsUI status=stable @@ -155,8 +154,7 @@ OverlayScrollbars PagePopup status=stable PaintOptimizations status=stable -PassiveDocumentEventListeners -PassiveEventListeners status=stable +PassiveDocumentEventListeners status=experimental PassPaintVisualRectToCompositor PathOpsSVGClipping status=stable PaymentRequest status=experimental
diff --git a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp index 7a5173e..592c323 100644 --- a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp +++ b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
@@ -39,6 +39,7 @@ #include "public/platform/WebURL.h" #include "public/platform/WebURLLoadTiming.h" #include "wtf/Allocator.h" +#include "wtf/Assertions.h" #include "wtf/PtrUtil.h" #include "wtf/RefPtr.h" #include <memory> @@ -76,39 +77,54 @@ m_resourceResponse = &m_resourceResponseAllocation; } - WebURLResponsePrivateImpl(const WebURLResponsePrivate* p) - : m_resourceResponseAllocation(*p->m_resourceResponse) + WebURLResponsePrivateImpl(const WebURLResponsePrivate& p) + : m_resourceResponseAllocation(*p.m_resourceResponse) { m_resourceResponse = &m_resourceResponseAllocation; } - virtual void dispose() { delete this; } + ~WebURLResponsePrivateImpl() override {} private: - virtual ~WebURLResponsePrivateImpl() { } - ResourceResponse m_resourceResponseAllocation; }; -void WebURLResponse::initialize() +WebURLResponse::~WebURLResponse() { - assign(new WebURLResponsePrivateImpl()); } -void WebURLResponse::reset() +WebURLResponse::WebURLResponse() + : m_owningPrivate(new WebURLResponsePrivateImpl()) + , m_private(m_owningPrivate.get()) { - assign(0); } -void WebURLResponse::assign(const WebURLResponse& r) +WebURLResponse::WebURLResponse(const WebURLResponse& r) + : m_owningPrivate(new WebURLResponsePrivateImpl(*r.m_private)) + , m_private(m_owningPrivate.get()) { +} + +WebURLResponse::WebURLResponse(const WebURL& url) + : WebURLResponse() +{ + setURL(url); +} + +WebURLResponse& WebURLResponse::operator=(const WebURLResponse& r) +{ + // Copying subclasses that have different m_private ownership semantics + // via this operator is just not supported. + DCHECK(m_owningPrivate); + DCHECK(m_private->m_resourceResponse); if (&r != this) - assign(r.m_private ? new WebURLResponsePrivateImpl(r.m_private) : 0); + *m_private->m_resourceResponse = *r.m_private->m_resourceResponse; + return *this; } bool WebURLResponse::isNull() const { - return !m_private || m_private->m_resourceResponse->isNull(); + return m_private->m_resourceResponse->isNull(); } WebURL WebURLResponse::url() const @@ -342,17 +358,13 @@ ResourceResponse& WebURLResponse::toMutableResourceResponse() { - ASSERT(m_private); - ASSERT(m_private->m_resourceResponse); - + DCHECK(m_private->m_resourceResponse); return *m_private->m_resourceResponse; } const ResourceResponse& WebURLResponse::toResourceResponse() const { - ASSERT(m_private); - ASSERT(m_private->m_resourceResponse); - + DCHECK(m_private->m_resourceResponse); return *m_private->m_resourceResponse; } @@ -511,15 +523,10 @@ m_private->m_resourceResponse->setExtraData(ExtraDataContainer::create(extraData)); } -void WebURLResponse::assign(WebURLResponsePrivate* p) +WebURLResponse::WebURLResponse(WebURLResponsePrivate* p) + : m_private(p) { - // Subclasses may call this directly so a self-assignment check is needed - // here as well as in the public assign method. - if (m_private == p) - return; - if (m_private) - m_private->dispose(); - m_private = p; + DCHECK(p); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebURLResponsePrivate.h b/third_party/WebKit/Source/platform/exported/WebURLResponsePrivate.h index 81cb5c06..1f068fa 100644 --- a/third_party/WebKit/Source/platform/exported/WebURLResponsePrivate.h +++ b/third_party/WebKit/Source/platform/exported/WebURLResponsePrivate.h
@@ -41,10 +41,8 @@ class WebURLResponsePrivate { WTF_MAKE_NONCOPYABLE(WebURLResponsePrivate); public: - WebURLResponsePrivate() : m_resourceResponse(0) { } - - // Called by WebURLResponse when it no longer needs this object. - virtual void dispose() = 0; + WebURLResponsePrivate() : m_resourceResponse(nullptr) {} + virtual ~WebURLResponsePrivate() {} ResourceResponse* m_resourceResponse; };
diff --git a/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h b/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h index 0f9c75a..806600a 100644 --- a/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h +++ b/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h
@@ -37,44 +37,27 @@ namespace blink { +// WrappedResourceResponse doesn't take ownership of given ResourceResponse, +// but just holds a pointer to it. It is not copyable (as WebURLResponsePrivate +// is non-copyable). class WrappedResourceResponse : public WebURLResponse { public: - ~WrappedResourceResponse() - { - reset(); // Need to drop reference to m_handle - } + ~WrappedResourceResponse() {} - WrappedResourceResponse() { } - - WrappedResourceResponse(ResourceResponse& resourceResponse) - { - bind(resourceResponse); - } - - WrappedResourceResponse(const ResourceResponse& resourceResponse) - { - bind(resourceResponse); - } - - void bind(ResourceResponse& resourceResponse) + explicit WrappedResourceResponse(ResourceResponse& resourceResponse) + : WebURLResponse(&m_handle) { m_handle.m_resourceResponse = &resourceResponse; - assign(&m_handle); } - void bind(const ResourceResponse& resourceResponse) + explicit WrappedResourceResponse(const ResourceResponse& resourceResponse) + : WrappedResourceResponse(const_cast<ResourceResponse&>(resourceResponse)) { - bind(*const_cast<ResourceResponse*>(&resourceResponse)); } private: - class Handle : public WebURLResponsePrivate { - DISALLOW_NEW(); - public: - virtual void dispose() { m_resourceResponse = 0; } - }; - - Handle m_handle; + // This is pointed by m_private. + WebURLResponsePrivate m_handle; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp index f921797..11b5738 100644 --- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp +++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurface.cpp
@@ -72,7 +72,7 @@ void RecordingImageBufferSurface::fallBackToRasterCanvas(FallbackReason reason) { ASSERT(m_fallbackFactory); - DCHECK(reason != FallbackReasonUnknown); + CHECK(reason != FallbackReasonUnknown); if (m_fallbackSurface) { ASSERT(!m_currentFrame);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp index 40ecd354..da950babf 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
@@ -11,8 +11,11 @@ #include "cc/playback/display_item_list_settings.h" #include "cc/playback/drawing_display_item.h" #include "cc/playback/transform_display_item.h" +#include "cc/trees/clip_node.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/property_tree.h" +#include "cc/trees/transform_node.h" #include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/paint/ClipPaintPropertyNode.h" #include "platform/graphics/paint/DisplayItem.h" @@ -236,7 +239,7 @@ transformTree.clear(); cc::TransformNode& transformNode = *transformTree.Node(transformTree.Insert(cc::TransformNode(), kRealRootNodeId)); DCHECK_EQ(transformNode.id, kSecondaryRootNodeId); - transformNode.data.source_node_id = transformNode.parent_id; + transformNode.source_node_id = transformNode.parent_id; transformTree.SetTargetId(transformNode.id, kRealRootNodeId); transformTree.SetContentTargetId(transformNode.id, kRealRootNodeId); @@ -253,8 +256,8 @@ cc::EffectNode& effectNode = *effectTree.Node(effectTree.Insert(cc::EffectNode(), kRealRootNodeId)); DCHECK_EQ(effectNode.id, kSecondaryRootNodeId); effectNode.owner_id = ownerId; - effectNode.data.clip_id = clipNode.id; - effectNode.data.has_render_surface = true; + effectNode.clip_id = clipNode.id; + effectNode.has_render_surface = true; cc::ScrollTree& scrollTree = propertyTrees->scroll_tree; scrollTree.clear(); @@ -345,9 +348,11 @@ , m_rootLayer(rootLayer) {} int compositorIdForTransformNode(const TransformPaintPropertyNode*); + int compositorIdForClipNode(const ClipPaintPropertyNode*); private: cc::TransformTree& transformTree() { return m_propertyTrees.transform_tree; } + cc::ClipTree& clipTree() { return m_propertyTrees.clip_tree; } // Property trees which should be updated by the manager. cc::PropertyTrees& m_propertyTrees; @@ -356,8 +361,9 @@ // have any actual children, but at present must exist in the tree. cc::Layer* m_rootLayer; - // Map from Blink-side transform nodes to cc transform node indices. + // Maps from Blink-side property tree nodes to cc property node indices. HashMap<const TransformPaintPropertyNode*, int> m_transformNodeMap; + HashMap<const ClipPaintPropertyNode*, int> m_clipNodeMap; }; int PropertyTreeManager::compositorIdForTransformNode(const TransformPaintPropertyNode* transformNode) @@ -376,15 +382,15 @@ cc::TransformNode& compositorNode = *transformTree().Node(id); transformTree().SetTargetId(id, kRealRootNodeId); transformTree().SetContentTargetId(id, kRealRootNodeId); - compositorNode.data.source_node_id = parentId; + compositorNode.source_node_id = parentId; FloatPoint3D origin = transformNode->origin(); - compositorNode.data.pre_local.matrix().setTranslate( + compositorNode.pre_local.matrix().setTranslate( -origin.x(), -origin.y(), -origin.z()); - compositorNode.data.local.matrix() = TransformationMatrix::toSkMatrix44(transformNode->matrix()); - compositorNode.data.post_local.matrix().setTranslate( + compositorNode.local.matrix() = TransformationMatrix::toSkMatrix44(transformNode->matrix()); + compositorNode.post_local.matrix().setTranslate( origin.x(), origin.y(), origin.z()); - compositorNode.data.needs_local_transform_update = true; + compositorNode.needs_local_transform_update = true; m_rootLayer->AddChild(dummyLayer); dummyLayer->SetTransformTreeIndex(id); @@ -399,6 +405,43 @@ return id; } +int PropertyTreeManager::compositorIdForClipNode(const ClipPaintPropertyNode* clipNode) +{ + if (!clipNode) + return kSecondaryRootNodeId; + + auto it = m_clipNodeMap.find(clipNode); + if (it != m_clipNodeMap.end()) + return it->value; + + scoped_refptr<cc::Layer> dummyLayer = cc::Layer::Create(); + int parentId = compositorIdForClipNode(clipNode->parent()); + int id = clipTree().Insert(cc::ClipNode(), parentId); + + cc::ClipNode& compositorNode = *clipTree().Node(id); + compositorNode.owner_id = dummyLayer->id(); + + // TODO(jbroman): Don't discard rounded corners. + compositorNode.clip = clipNode->clipRect().rect(); + compositorNode.transform_id = compositorIdForTransformNode(clipNode->localTransformSpace()); + compositorNode.target_id = kRealRootNodeId; + compositorNode.applies_local_clip = true; + compositorNode.layers_are_clipped = true; + compositorNode.layers_are_clipped_when_surfaces_disabled = true; + + m_rootLayer->AddChild(dummyLayer); + dummyLayer->SetTransformTreeIndex(compositorNode.transform_id); + dummyLayer->SetClipTreeIndex(id); + dummyLayer->SetEffectTreeIndex(kSecondaryRootNodeId); + dummyLayer->SetScrollTreeIndex(kRealRootNodeId); + dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); + + auto result = m_clipNodeMap.set(clipNode, id); + DCHECK(result.isNewEntry); + clipTree().set_needs_update(true); + return id; +} + } // namespace void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintArtifact) @@ -421,12 +464,14 @@ scoped_refptr<cc::Layer> layer = layerForPaintChunk(paintArtifact, paintChunk, layerOffset); int transformId = propertyTreeManager.compositorIdForTransformNode(paintChunk.properties.transform.get()); + int clipId = propertyTreeManager.compositorIdForClipNode(paintChunk.properties.clip.get()); + layer->set_offset_to_transform_parent(layerOffset); m_rootLayer->AddChild(layer); layer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); layer->SetTransformTreeIndex(transformId); - layer->SetClipTreeIndex(kSecondaryRootNodeId); + layer->SetClipTreeIndex(clipId); layer->SetEffectTreeIndex(kSecondaryRootNodeId); layer->SetScrollTreeIndex(kRealRootNodeId);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp index 457411c..4640c277 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -8,6 +8,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "cc/layers/layer.h" #include "cc/test/fake_output_surface.h" +#include "cc/trees/clip_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" #include "platform/RuntimeEnabledFeatures.h" @@ -518,6 +519,171 @@ contentLayerAt(1)->transform_tree_index()); } +TEST_F(PaintArtifactCompositorTestWithPropertyTrees, OneClip) +{ + RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(100, 100, 300, 200)); + + TestPaintArtifact artifact; + artifact.chunk(nullptr, clip, nullptr) + .rectDrawing(FloatRect(220, 80, 300, 200), Color::black); + update(artifact.build()); + + ASSERT_EQ(1u, contentLayerCount()); + const cc::Layer* layer = contentLayerAt(0); + EXPECT_THAT(layer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 300, 200), Color::black))); + EXPECT_EQ(translation(220, 80), layer->screen_space_transform()); + + const cc::ClipNode* clipNode = propertyTrees().clip_tree.Node(layer->clip_tree_index()); + EXPECT_TRUE(clipNode->applies_local_clip); + EXPECT_TRUE(clipNode->layers_are_clipped); + EXPECT_EQ(gfx::RectF(100, 100, 300, 200), clipNode->clip); +} + +TEST_F(PaintArtifactCompositorTestWithPropertyTrees, NestedClips) +{ + RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(100, 100, 700, 700)); + RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(200, 200, 700, 100), clip1); + + TestPaintArtifact artifact; + artifact.chunk(nullptr, clip1, nullptr) + .rectDrawing(FloatRect(300, 350, 100, 100), Color::white); + artifact.chunk(nullptr, clip2, nullptr) + .rectDrawing(FloatRect(300, 350, 100, 100), Color::lightGray); + artifact.chunk(nullptr, clip1, nullptr) + .rectDrawing(FloatRect(300, 350, 100, 100), Color::darkGray); + artifact.chunk(nullptr, clip2, nullptr) + .rectDrawing(FloatRect(300, 350, 100, 100), Color::black); + update(artifact.build()); + + ASSERT_EQ(4u, contentLayerCount()); + + const cc::Layer* whiteLayer = contentLayerAt(0); + EXPECT_THAT(whiteLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 100, 100), Color::white))); + EXPECT_EQ(translation(300, 350), whiteLayer->screen_space_transform()); + + const cc::Layer* lightGrayLayer = contentLayerAt(1); + EXPECT_THAT(lightGrayLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 100, 100), Color::lightGray))); + EXPECT_EQ(translation(300, 350), lightGrayLayer->screen_space_transform()); + + const cc::Layer* darkGrayLayer = contentLayerAt(2); + EXPECT_THAT(darkGrayLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 100, 100), Color::darkGray))); + EXPECT_EQ(translation(300, 350), darkGrayLayer->screen_space_transform()); + + const cc::Layer* blackLayer = contentLayerAt(3); + EXPECT_THAT(blackLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 100, 100), Color::black))); + EXPECT_EQ(translation(300, 350), blackLayer->screen_space_transform()); + + EXPECT_EQ(whiteLayer->clip_tree_index(), darkGrayLayer->clip_tree_index()); + const cc::ClipNode* outerClip = propertyTrees().clip_tree.Node(whiteLayer->clip_tree_index()); + EXPECT_TRUE(outerClip->applies_local_clip); + EXPECT_TRUE(outerClip->layers_are_clipped); + EXPECT_EQ(gfx::RectF(100, 100, 700, 700), outerClip->clip); + + EXPECT_EQ(lightGrayLayer->clip_tree_index(), blackLayer->clip_tree_index()); + const cc::ClipNode* innerClip = propertyTrees().clip_tree.Node(blackLayer->clip_tree_index()); + EXPECT_TRUE(innerClip->applies_local_clip); + EXPECT_TRUE(innerClip->layers_are_clipped); + EXPECT_EQ(gfx::RectF(200, 200, 700, 100), innerClip->clip); + EXPECT_EQ(outerClip->id, innerClip->parent_id); +} + +TEST_F(PaintArtifactCompositorTestWithPropertyTrees, DeeplyNestedClips) +{ + Vector<RefPtr<ClipPaintPropertyNode>> clips; + for (unsigned i = 1; i <= 10; i++) { + clips.append(ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i), + clips.isEmpty() ? nullptr : clips.last())); + } + + TestPaintArtifact artifact; + artifact.chunk(nullptr, clips.last(), nullptr) + .rectDrawing(FloatRect(0, 0, 200, 200), Color::white); + update(artifact.build()); + + // Check the drawing layer. + ASSERT_EQ(1u, contentLayerCount()); + const cc::Layer* drawingLayer = contentLayerAt(0); + EXPECT_THAT(drawingLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 200, 200), Color::white))); + EXPECT_EQ(gfx::Transform(), drawingLayer->screen_space_transform()); + + // Check the clip nodes. + const cc::ClipNode* clipNode = propertyTrees().clip_tree.Node(drawingLayer->clip_tree_index()); + for (auto it = clips.rbegin(); it != clips.rend(); ++it) { + const ClipPaintPropertyNode* paintClipNode = it->get(); + EXPECT_TRUE(clipNode->applies_local_clip); + EXPECT_TRUE(clipNode->layers_are_clipped); + EXPECT_EQ(paintClipNode->clipRect().rect(), clipNode->clip); + clipNode = propertyTrees().clip_tree.Node(clipNode->parent_id); + } +} + +TEST_F(PaintArtifactCompositorTestWithPropertyTrees, SiblingClips) +{ + RefPtr<ClipPaintPropertyNode> commonClip = ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(0, 0, 800, 600)); + RefPtr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(0, 0, 400, 600), commonClip); + RefPtr<ClipPaintPropertyNode> clip2 = ClipPaintPropertyNode::create( + nullptr, FloatRoundedRect(400, 0, 400, 600), commonClip); + + TestPaintArtifact artifact; + artifact.chunk(nullptr, clip1, nullptr) + .rectDrawing(FloatRect(0, 0, 640, 480), Color::white); + artifact.chunk(nullptr, clip2, nullptr) + .rectDrawing(FloatRect(0, 0, 640, 480), Color::black); + update(artifact.build()); + + ASSERT_EQ(2u, contentLayerCount()); + + const cc::Layer* whiteLayer = contentLayerAt(0); + EXPECT_THAT(whiteLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 640, 480), Color::white))); + EXPECT_EQ(gfx::Transform(), whiteLayer->screen_space_transform()); + const cc::ClipNode* whiteClip = propertyTrees().clip_tree.Node(whiteLayer->clip_tree_index()); + EXPECT_TRUE(whiteClip->applies_local_clip); + EXPECT_TRUE(whiteClip->layers_are_clipped); + ASSERT_EQ(gfx::RectF(0, 0, 400, 600), whiteClip->clip); + + const cc::Layer* blackLayer = contentLayerAt(1); + EXPECT_THAT(blackLayer->GetPicture(), + Pointee(drawsRectangle(FloatRect(0, 0, 640, 480), Color::black))); + EXPECT_EQ(gfx::Transform(), blackLayer->screen_space_transform()); + const cc::ClipNode* blackClip = propertyTrees().clip_tree.Node(blackLayer->clip_tree_index()); + EXPECT_TRUE(blackClip->applies_local_clip); + EXPECT_TRUE(blackClip->layers_are_clipped); + ASSERT_EQ(gfx::RectF(400, 0, 400, 600), blackClip->clip); + + EXPECT_EQ(whiteClip->parent_id, blackClip->parent_id); + const cc::ClipNode* commonClipNode = propertyTrees().clip_tree.Node(whiteClip->parent_id); + EXPECT_TRUE(commonClipNode->applies_local_clip); + EXPECT_TRUE(commonClipNode->layers_are_clipped); + ASSERT_EQ(gfx::RectF(0, 0, 800, 600), commonClipNode->clip); +} + +TEST_F(PaintArtifactCompositorTestWithPropertyTrees, ForeignLayerPassesThrough) +{ + scoped_refptr<cc::Layer> layer = cc::Layer::Create(); + + TestPaintArtifact artifact; + artifact.chunk(PaintChunkProperties()) + .foreignLayer(FloatPoint(50, 100), IntSize(400, 300), layer); + update(artifact.build()); + + ASSERT_EQ(1u, contentLayerCount()); + EXPECT_EQ(layer, contentLayerAt(0)); + EXPECT_EQ(gfx::Size(400, 300), layer->bounds()); + EXPECT_EQ(translation(50, 100), layer->screen_space_transform()); +} } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index 6b4d710d..d8f5af2 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -81,7 +81,10 @@ } // namespace -PassRefPtr<DrawingBuffer> DrawingBuffer::create(std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, const IntSize& size, bool premultipliedAlpha, bool wantAlphaChannel, bool wantDepthBuffer, bool wantStencilBuffer, bool wantAntialiasing, PreserveDrawingBuffer preserve) +PassRefPtr<DrawingBuffer> DrawingBuffer::create(std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, + const IntSize& size, bool premultipliedAlpha, bool wantAlphaChannel, + bool wantDepthBuffer, bool wantStencilBuffer, bool wantAntialiasing, + PreserveDrawingBuffer preserve, WebGLVersion webGLVersion) { ASSERT(contextProvider); @@ -112,7 +115,9 @@ if (discardFramebufferSupported) extensionsUtil->ensureExtensionEnabled("GL_EXT_discard_framebuffer"); - RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(contextProvider), std::move(extensionsUtil), discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha, preserve, wantDepthBuffer, wantStencilBuffer)); + RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(std::move(contextProvider), std::move(extensionsUtil), + discardFramebufferSupported, wantAlphaChannel, premultipliedAlpha, + preserve, webGLVersion, wantDepthBuffer, wantStencilBuffer)); if (!drawingBuffer->initialize(size, multisampleSupported)) { drawingBuffer->beginDestruction(); return PassRefPtr<DrawingBuffer>(); @@ -132,9 +137,11 @@ bool wantAlphaChannel, bool premultipliedAlpha, PreserveDrawingBuffer preserve, + WebGLVersion webGLVersion, bool wantDepth, bool wantStencil) : m_preserveDrawingBuffer(preserve) + , m_webGLVersion(webGLVersion) , m_contextProvider(std::move(contextProvider)) , m_gl(m_contextProvider->contextGL()) , m_extensionsUtil(std::move(extensionsUtil)) @@ -284,7 +291,8 @@ m_gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments); } } else { - m_gl->CopyTextureCHROMIUM(m_colorBuffer.textureId, frontColorBufferMailbox->textureInfo.textureId, frontColorBufferMailbox->textureInfo.parameters.internalColorFormat, GL_UNSIGNED_BYTE, GL_FALSE, GL_FALSE, GL_FALSE); + m_gl->CopySubTextureCHROMIUM(m_colorBuffer.textureId, frontColorBufferMailbox->textureInfo.textureId, + 0, 0, 0, 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE); } restoreFramebufferBindings(); @@ -477,6 +485,7 @@ m_antiAliasingMode = ScreenSpaceAntialiasing; } } + m_storageTextureSupported = m_webGLVersion > WebGL1 || m_extensionsUtil->supportsExtension("GL_EXT_texture_storage"); m_sampleCount = std::min(4, maxSampleCount); m_gl->GenFramebuffers(1, &m_fbo); @@ -799,7 +808,7 @@ // multisampled renderbuffers and the alpha channel can be overwritten. // Clear the alpha channel of |m_fbo|. if (defaultBufferRequiresAlphaChannelToBePreserved() - && contextProvider()->getCapabilities().disable_webgl_multisampling_color_mask_usage) { + && contextProvider()->getCapabilities().disable_multisampling_color_mask_usage) { m_gl->ClearColor(0, 0, 0, 1); m_gl->ColorMask(false, false, false, true); m_gl->Clear(GL_COLOR_BUFFER_BIT); @@ -941,10 +950,21 @@ } } -void DrawingBuffer::texImage2DResourceSafe(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint unpackAlignment) +void DrawingBuffer::allocateConditionallyImmutableTexture(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type) { - ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8); - m_gl->TexImage2D(target, level, internalformat, width, height, border, format, type, 0); + if (m_storageTextureSupported) { + GLenum internalStorageFormat = GL_NONE; + if (internalformat == GL_RGB) { + internalStorageFormat = GL_RGB8; + } else if (internalformat == GL_RGBA) { + internalStorageFormat = GL_RGBA8; + } else { + NOTREACHED(); + } + m_gl->TexStorage2DEXT(GL_TEXTURE_2D, 1, internalStorageFormat, width, height); + return; + } + m_gl->TexImage2D(target, 0, internalformat, width, height, border, format, type, 0); } void DrawingBuffer::deleteChromiumImageForTexture(TextureInfo* info) @@ -1006,13 +1026,13 @@ DrawingBuffer::TextureInfo DrawingBuffer::createDefaultTextureAndAllocateMemory(const IntSize& size) { - TextureParameters parameters = defaultTextureParameters(); - GLuint textureId = createColorTexture(parameters); - texImage2DResourceSafe(parameters.target, 0, parameters.creationInternalColorFormat, size.width(), size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE); - DrawingBuffer::TextureInfo info; - info.textureId = textureId; + TextureParameters parameters = defaultTextureParameters(); info.parameters = parameters; + info.textureId = createColorTexture(parameters); + allocateConditionallyImmutableTexture(parameters.target, parameters.creationInternalColorFormat, + size.width(), size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE); + info.immutable = m_storageTextureSupported; return info; } @@ -1020,11 +1040,19 @@ { ASSERT(info->textureId); if (!RuntimeEnabledFeatures::webGLImageChromiumEnabled()) { + if (info->immutable) { + DCHECK(m_storageTextureSupported); + m_gl->DeleteTextures(1, &info->textureId); + info->textureId = createColorTexture(info->parameters); + } m_gl->BindTexture(info->parameters.target, info->textureId); - texImage2DResourceSafe(info->parameters.target, 0, info->parameters.creationInternalColorFormat, size.width(), size.height(), 0, info->parameters.colorFormat, GL_UNSIGNED_BYTE); + allocateConditionallyImmutableTexture(info->parameters.target, info->parameters.creationInternalColorFormat, + size.width(), size.height(), 0, info->parameters.colorFormat, GL_UNSIGNED_BYTE); + info->immutable = m_storageTextureSupported; return; } + DCHECK(!info->immutable); deleteChromiumImageForTexture(info); info->imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(size.width(), size.height(), info->parameters.creationInternalColorFormat, GC3D_SCANOUT_CHROMIUM); if (info->imageId) {
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h index e0a19da5..c6d86e4e 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -72,6 +72,10 @@ Preserve, Discard }; + enum WebGLVersion { + WebGL1, + WebGL2, + }; static PassRefPtr<DrawingBuffer> create( std::unique_ptr<WebGraphicsContext3DProvider>, @@ -81,7 +85,8 @@ bool wantDepthBuffer, bool wantStencilBuffer, bool wantAntialiasing, - PreserveDrawingBuffer); + PreserveDrawingBuffer, + WebGLVersion); static void forceNextDrawingBufferCreationToFail(); ~DrawingBuffer() override; @@ -227,6 +232,7 @@ bool wantAlphaChannel, bool premultipliedAlpha, PreserveDrawingBuffer, + WebGLVersion, bool wantsDepth, bool wantsStencil); @@ -253,6 +259,7 @@ DISALLOW_NEW(); GLuint textureId = 0; GLuint imageId = 0; + bool immutable = false; // A GpuMemoryBuffer is a concept that the compositor understands. and // is able to operate on. The id is scoped to renderer process. @@ -321,9 +328,8 @@ // Helper function to flip a bitmap vertically. void flipVertically(uint8_t* data, int width, int height); - // Helper to texImage2D with pixel==0 case: pixels are initialized to 0. - // By default, alignment is 4, the OpenGL default setting. - void texImage2DResourceSafe(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint alignment = 4); + // Allocate a storage texture if possible. Otherwise, allocate a regular texture. + void allocateConditionallyImmutableTexture(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type); // Allocate buffer storage to be sent to compositor using either texImage2D or CHROMIUM_image based on available support. void deleteChromiumImageForTexture(TextureInfo*); @@ -358,6 +364,7 @@ GLenum getMultisampledRenderbufferFormat(); const PreserveDrawingBuffer m_preserveDrawingBuffer; + const WebGLVersion m_webGLVersion; bool m_scissorEnabled = false; GLuint m_texture2DBinding = 0; GLuint m_drawFramebufferBinding = 0; @@ -376,6 +383,7 @@ const bool m_wantAlphaChannel; const bool m_premultipliedAlpha; bool m_hasImplicitStencilBuffer = false; + bool m_storageTextureSupported = false; struct FrontBufferInfo { TextureInfo texInfo; WebExternalTextureMailbox mailbox;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index e8ac977..2c55c92 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -230,7 +230,9 @@ } DrawingBufferForTests(std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, std::unique_ptr<Extensions3DUtil> extensionsUtil, PreserveDrawingBuffer preserve) - : DrawingBuffer(std::move(contextProvider), std::move(extensionsUtil), false /* discardFramebufferSupported */, true /* wantAlphaChannel */, false /* premultipliedAlpha */, preserve, false /* wantDepth */, false /* wantStencil */) + : DrawingBuffer(std::move(contextProvider), std::move(extensionsUtil), false /* discardFramebufferSupported */, + true /* wantAlphaChannel */, false /* premultipliedAlpha */, preserve, WebGL1, + false /* wantDepth */, false /* wantStencil */) , m_live(0) { } @@ -727,7 +729,8 @@ wantDepthBuffer, wantStencilBuffer, wantAntialiasing, - preserve); + preserve, + DrawingBuffer::WebGL1); // When we request a depth or a stencil buffer, we will get both. EXPECT_EQ(cases[i].requestDepth || cases[i].requestStencil, drawingBuffer->hasDepthBuffer());
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp index c786690..12eeecba 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
@@ -132,6 +132,7 @@ { switch (type) { DEBUG_STRING_CASE(ForeignLayerPlugin); + DEBUG_STRING_CASE(ForeignLayerVideo); DEFAULT_CASE; } }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h index 94f60a1..05778d1 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -121,7 +121,8 @@ ForeignLayerFirst, ForeignLayerPlugin = ForeignLayerFirst, - ForeignLayerLast = ForeignLayerPlugin, + ForeignLayerVideo, + ForeignLayerLast = ForeignLayerVideo, ClipFirst, ClipBoxPaintPhaseFirst = ClipFirst,
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp index 4558b88..d75455f 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp
@@ -32,7 +32,7 @@ return true; } -DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClient& displayItemClient, DisplayItem::Type displayItemType, const FloatRect& cullRect) +DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClient& displayItemClient, DisplayItem::Type displayItemType, const FloatRect& floatCullRect) : m_context(context) , m_displayItemClient(displayItemClient) , m_displayItemType(displayItemType) @@ -55,6 +55,9 @@ context.setInDrawingRecorder(true); #endif + // Use the enclosing int rect, since pixel-snapping may be applied to the bounds of the object during painting. Potentially expanding + // the cull rect by a pixel or two also does not affect correctness, and is very unlikely to matter for performance. + IntRect cullRect = enclosingIntRect(floatCullRect); context.beginRecording(cullRect); #if ENABLE(ASSERT) @@ -63,13 +66,12 @@ // cull rect clipping is enabled, make this explicit. This allows us to identify potential // incorrect cull rects that might otherwise be masked due to Skia internal optimizations. context.save(); - IntRect verificationClip = enclosingIntRect(cullRect); // Expand the verification clip by one pixel to account for Skia's SkCanvas::getClipBounds() // expansion, used in testing cull rects. // TODO(schenney) This is not the best place to do this. Ideally, we would expand by one pixel // in device (pixel) space, but to do that we would need to add the verification mode to Skia. - verificationClip.inflate(1); - context.clipRect(verificationClip, NotAntiAliased, SkRegion::kIntersect_Op); + cullRect.inflate(1); + context.clipRect(cullRect, NotAntiAliased, SkRegion::kIntersect_Op); } #endif }
diff --git a/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp index 4462fdde..06e4ac4 100644 --- a/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp +++ b/third_party/WebKit/Source/platform/testing/URLTestHelpers.cpp
@@ -72,7 +72,6 @@ timing.initialize(); WebURLResponse response; - response.initialize(); response.setMIMEType("image/png"); response.setHTTPStatusCode(404); response.setLoadTiming(timing);
diff --git a/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp b/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp index b840999..287d11b 100644 --- a/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp +++ b/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.cpp
@@ -22,6 +22,18 @@ { } +static cc::LayerTreeSettings settingsForLayerListPolicy(WebLayerTreeViewImplForTesting::LayerListPolicy policy) +{ + cc::LayerTreeSettings settings = WebLayerTreeViewImplForTesting::defaultLayerTreeSettings(); + settings.use_layer_lists = policy == WebLayerTreeViewImplForTesting::UseLayerLists; + return settings; +} + +WebLayerTreeViewImplForTesting::WebLayerTreeViewImplForTesting(LayerListPolicy policy) + : WebLayerTreeViewImplForTesting(settingsForLayerListPolicy(policy)) +{ +} + WebLayerTreeViewImplForTesting::WebLayerTreeViewImplForTesting(const cc::LayerTreeSettings& settings) { cc::LayerTreeHost::InitParams params; @@ -48,6 +60,11 @@ return settings; } +bool WebLayerTreeViewImplForTesting::hasLayer(const WebLayer& layer) +{ + return layer.ccLayer()->layer_tree_host() == m_layerTreeHost.get(); +} + void WebLayerTreeViewImplForTesting::setRootLayer(const blink::WebLayer& root) { m_layerTreeHost->SetRootLayer(static_cast<const cc_blink::WebLayerImpl*>(&root)->layer());
diff --git a/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.h b/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.h index 8cb8694..25ec408 100644 --- a/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.h +++ b/third_party/WebKit/Source/platform/testing/WebLayerTreeViewImplForTesting.h
@@ -28,11 +28,14 @@ WTF_MAKE_NONCOPYABLE(WebLayerTreeViewImplForTesting); public: WebLayerTreeViewImplForTesting(); + enum LayerListPolicy { DontUseLayerLists, UseLayerLists }; + explicit WebLayerTreeViewImplForTesting(LayerListPolicy); explicit WebLayerTreeViewImplForTesting(const cc::LayerTreeSettings&); ~WebLayerTreeViewImplForTesting() override; static cc::LayerTreeSettings defaultLayerTreeSettings(); cc::LayerTreeHost* layerTreeHost() { return m_layerTreeHost.get(); } + bool hasLayer(const WebLayer&); // blink::WebLayerTreeView implementation. void setRootLayer(const blink::WebLayer&) override;
diff --git a/third_party/WebKit/Source/platform/text/SegmentedString.cpp b/third_party/WebKit/Source/platform/text/SegmentedString.cpp index ec3507e..944a177 100644 --- a/third_party/WebKit/Source/platform/text/SegmentedString.cpp +++ b/third_party/WebKit/Source/platform/text/SegmentedString.cpp
@@ -87,22 +87,21 @@ return; } - prepend(SegmentedString(String(&c, 1))); + prepend(SegmentedString(String(&c, 1)), PrependType::Unconsume); } -void SegmentedString::prepend(const SegmentedSubstring& s) +void SegmentedString::prepend(const SegmentedSubstring& s, PrependType type) { ASSERT(!s.numberOfCharactersConsumed()); if (!s.length()) return; - // FIXME: We're assuming that the prepend were originally consumed by - // this SegmentedString. We're also ASSERTing that s is a fresh - // SegmentedSubstring. These assumptions are sufficient for our - // current use, but we might need to handle the more elaborate - // cases in the future. + // FIXME: We're also ASSERTing that s is a fresh SegmentedSubstring. + // The assumption is sufficient for our current use, but we might + // need to handle the more elaborate cases in the future. m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed(); - m_numberOfCharactersConsumedPriorToCurrentString -= s.length(); + if (type == PrependType::Unconsume) + m_numberOfCharactersConsumedPriorToCurrentString -= s.length(); if (!m_currentString.length()) { m_currentString = s; updateAdvanceFunctionPointers(); @@ -136,15 +135,15 @@ m_currentChar = m_currentString.length() ? m_currentString.getCurrentChar() : 0; } -void SegmentedString::prepend(const SegmentedString& s) +void SegmentedString::prepend(const SegmentedString& s, PrependType type) { if (s.isComposite()) { Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin(); Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend(); for (; it != e; ++it) - prepend(*it); + prepend(*it, type); } - prepend(s.m_currentString); + prepend(s.m_currentString, type); m_currentChar = m_currentString.length() ? m_currentString.getCurrentChar() : 0; }
diff --git a/third_party/WebKit/Source/platform/text/SegmentedString.h b/third_party/WebKit/Source/platform/text/SegmentedString.h index cd71e6a..8a80cdb1 100644 --- a/third_party/WebKit/Source/platform/text/SegmentedString.h +++ b/third_party/WebKit/Source/platform/text/SegmentedString.h
@@ -211,7 +211,11 @@ void close(); void append(const SegmentedString&); - void prepend(const SegmentedString&); + enum class PrependType { + NewInput = 0, + Unconsume = 1, + }; + void prepend(const SegmentedString&, PrependType); bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); } void setExcludeLineNumbers(); @@ -323,7 +327,7 @@ }; void append(const SegmentedSubstring&); - void prepend(const SegmentedSubstring&); + void prepend(const SegmentedSubstring&, PrependType); void advance8(); void advance16(); @@ -399,7 +403,7 @@ LookAheadResult result = DidNotMatch; if (consumedString.startsWith(string, caseSensitivity)) result = DidMatch; - prepend(SegmentedString(consumedString)); + prepend(SegmentedString(consumedString), PrependType::Unconsume); return result; }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js b/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js index 85d214e0..5b534f3 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js +++ b/third_party/WebKit/Source/platform/v8_inspector/DebuggerScript.js
@@ -92,9 +92,9 @@ /** * @param {Object} object - * @return {?GeneratorObjectDetails} + * @return {?RawLocation} */ -DebuggerScript.getGeneratorObjectDetails = function(object) +DebuggerScript.getGeneratorObjectLocation = function(object) { var mirror = MakeMirror(object, true /* transient */); if (!mirror.isGenerator()) @@ -103,21 +103,16 @@ var funcMirror = generatorMirror.func(); if (!funcMirror.resolved()) return null; - var result = { - "function": funcMirror.value(), - "functionName": funcMirror.debugName(), - "status": generatorMirror.status() - }; - var script = funcMirror.script(); var location = generatorMirror.sourceLocation() || funcMirror.sourceLocation(); + var script = funcMirror.script(); if (script && location) { - result["location"] = { - "scriptId": String(script.id()), - "lineNumber": location.line, - "columnNumber": location.column + return { + scriptId: "" + script.id(), + lineNumber: location.line, + columnNumber: location.column }; } - return result; + return null; } /**
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp index cd467e6..c2bcdab1 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp
@@ -52,7 +52,6 @@ using blink::protocol::Array; using blink::protocol::Debugger::CallFrame; using blink::protocol::Debugger::FunctionDetails; -using blink::protocol::Debugger::GeneratorObjectDetails; using blink::protocol::Runtime::PropertyDescriptor; using blink::protocol::Runtime::InternalPropertyDescriptor; using blink::protocol::Runtime::RemoteObject;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js index bac0f5f7..743cc06f 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
@@ -212,6 +212,15 @@ /** * @param {*} object + * @return {boolean} + */ + _shouldPassByValue: function(object) + { + return typeof object === "object" && InjectedScriptHost.subtype(object) === "internal#location"; + }, + + /** + * @param {*} object * @param {string} groupName * @param {boolean} canAccessInspectedGlobalObject * @param {boolean} forceValueType @@ -716,6 +725,13 @@ return; } + if (injectedScript._shouldPassByValue(object)) { + this.value = object; + this.subtype = injectedScript._subtype(object); + this.description = injectedScript._describeIncludingPrimitives(object); + return; + } + object = /** @type {!Object} */ (object); if (!doNotBind)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp index 921dcbff..7cf80d6 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp
@@ -265,13 +265,13 @@ { v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate(), name); v8::Local<v8::Function> func; - if (!v8::Function::New(context, callback, console).ToLocal(&func)) + if (!v8::Function::New(context, callback, console, 0, v8::ConstructorBehavior::kThrow).ToLocal(&func)) return; func->SetName(funcName); if (description) { v8::Local<v8::String> returnValue = toV8String(context->GetIsolate(), description); v8::Local<v8::Function> toStringFunction; - if (v8::Function::New(context, returnDataCallback, returnValue).ToLocal(&toStringFunction)) + if (v8::Function::New(context, returnDataCallback, returnValue, 0, v8::ConstructorBehavior::kThrow).ToLocal(&toStringFunction)) func->Set(toV8StringInternalized(context->GetIsolate(), "toString"), toStringFunction); } if (!console->Set(context, funcName, func).FromMaybe(false)) @@ -676,7 +676,7 @@ DCHECK(success); if (hasMemoryAttribute) - console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Function::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT); + console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(context, V8Console::memoryGetterCallback, console, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(), v8::Function::New(context, V8Console::memorySetterCallback, v8::Local<v8::Value>(), 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(), static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT); console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::External::New(isolate, inspectedContext)); return console;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp index e1dbb81..53ccca1 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -27,7 +27,6 @@ using blink::protocol::Debugger::CallFrame; using blink::protocol::Runtime::ExceptionDetails; using blink::protocol::Debugger::FunctionDetails; -using blink::protocol::Debugger::GeneratorObjectDetails; using blink::protocol::Runtime::ScriptId; using blink::protocol::Runtime::StackTrace; using blink::protocol::Runtime::RemoteObject; @@ -633,34 +632,6 @@ *details = std::move(functionDetails); } -void V8DebuggerAgentImpl::getGeneratorObjectDetails(ErrorString* errorString, const String16& objectId, std::unique_ptr<GeneratorObjectDetails>* outDetails) -{ - if (!checkEnabled(errorString)) - return; - InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), objectId); - if (!scope.initialize()) - return; - if (!scope.object()->IsObject()) { - *errorString = "Value with given id is not an Object"; - return; - } - v8::Local<v8::Object> object = scope.object().As<v8::Object>(); - - v8::Local<v8::Object> detailsObject; - v8::Local<v8::Value> detailsValue = debugger().generatorObjectDetails(object); - if (hasInternalError(errorString, !detailsValue->IsObject() || !detailsValue->ToObject(scope.context()).ToLocal(&detailsObject))) - return; - - if (!scope.injectedScript()->wrapObjectProperty(errorString, detailsObject, toV8StringInternalized(m_isolate, "function"), scope.objectGroupName())) - return; - - protocol::ErrorSupport errors; - std::unique_ptr<GeneratorObjectDetails> protocolDetails = GeneratorObjectDetails::parse(toProtocolValue(scope.context(), detailsObject).get(), &errors); - if (hasInternalError(errorString, !protocolDetails)) - return; - *outDetails = std::move(protocolDetails); -} - void V8DebuggerAgentImpl::schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) { if (!enabled() || m_scheduledDebuggerStep == StepInto || m_javaScriptPauseScheduled || debugger().isPaused() || !debugger().breakpointsActivated())
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h index 65f2c84..fdae2de 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h
@@ -95,9 +95,6 @@ void getFunctionDetails(ErrorString*, const String16& functionId, std::unique_ptr<protocol::Debugger::FunctionDetails>*) override; - void getGeneratorObjectDetails(ErrorString*, - const String16& objectId, - std::unique_ptr<protocol::Debugger::GeneratorObjectDetails>*) override; void pause(ErrorString*) override; void resume(ErrorString*) override; void stepOver(ErrorString*) override;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp index 8091b318..e945af4 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
@@ -314,7 +314,7 @@ v8::HandleScope scope(m_isolate); v8::Local<v8::Function> breakFunction; - if (!v8::Function::New(m_isolate->GetCurrentContext(), &V8DebuggerImpl::breakProgramCallback, v8::External::New(m_isolate, this)).ToLocal(&breakFunction)) + if (!v8::Function::New(m_isolate->GetCurrentContext(), &V8DebuggerImpl::breakProgramCallback, v8::External::New(m_isolate, this), 0, v8::ConstructorBehavior::kThrow).ToLocal(&breakFunction)) return; v8::Debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); } @@ -668,17 +668,14 @@ properties->Set(properties->Length(), entries); } } - return properties; -} - -v8::Local<v8::Value> V8DebuggerImpl::generatorObjectDetails(v8::Local<v8::Object>& object) -{ - if (!enabled()) { - NOTREACHED(); - return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); + if (value->IsGeneratorObject()) { + v8::Local<v8::Value> location = generatorObjectLocation(v8::Local<v8::Object>::Cast(value)); + if (location->IsObject()) { + properties->Set(properties->Length(), v8InternalizedString("[[GeneratorLocation]]")); + properties->Set(properties->Length(), location); + } } - v8::Local<v8::Value> argv[] = { object }; - return callDebuggerMethod("getGeneratorObjectDetails", 1, argv).ToLocalChecked(); + return properties; } v8::Local<v8::Value> V8DebuggerImpl::collectionEntries(v8::Local<v8::Context> context, v8::Local<v8::Object> object) @@ -704,6 +701,22 @@ return entries; } +v8::Local<v8::Value> V8DebuggerImpl::generatorObjectLocation(v8::Local<v8::Object> object) +{ + if (!enabled()) { + NOTREACHED(); + return v8::Null(m_isolate); + } + v8::Local<v8::Value> argv[] = { object }; + v8::Local<v8::Value> location = callDebuggerMethod("getGeneratorObjectLocation", 1, argv).ToLocalChecked(); + if (!location->IsObject()) + return v8::Null(m_isolate); + v8::Local<v8::Context> context = m_debuggerContext.Get(m_isolate); + if (!location.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalLocationPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false)) + return v8::Null(m_isolate); + return location; +} + bool V8DebuggerImpl::isPaused() { return !m_pausedContext.IsEmpty();
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h index e4da436..1ce6d5b 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
@@ -106,7 +106,6 @@ v8::MaybeLocal<v8::Value> functionScopes(v8::Local<v8::Function>); v8::MaybeLocal<v8::Array> internalProperties(v8::Local<v8::Context>, v8::Local<v8::Value>); - v8::Local<v8::Value> generatorObjectDetails(v8::Local<v8::Object>&); v8::Isolate* isolate() const { return m_isolate; } V8DebuggerClient* client() { return m_client; } @@ -176,6 +175,7 @@ using ContextsByGroupMap = protocol::HashMap<int, std::unique_ptr<ContextByIdMap>>; v8::Local<v8::Value> collectionEntries(v8::Local<v8::Context>, v8::Local<v8::Object>); + v8::Local<v8::Value> generatorObjectLocation(v8::Local<v8::Object>); v8::Isolate* m_isolate; V8DebuggerClient* m_client;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp index 85800be..1ef3bbba 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
@@ -19,7 +19,7 @@ { v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate(), name); v8::Local<v8::Function> func; - if (!v8::Function::New(context, callback, external).ToLocal(&func)) + if (!v8::Function::New(context, callback, external, 0, v8::ConstructorBehavior::kThrow).ToLocal(&func)) return; func->SetName(funcName); if (!obj->Set(context, funcName, func).FromMaybe(false)) @@ -59,6 +59,11 @@ return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InjectedScriptHost#internalEntry")); } +v8::Local<v8::Private> V8InjectedScriptHost::internalLocationPrivate(v8::Isolate* isolate) +{ + return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InjectedScriptHost#internalLocation")); +} + void V8InjectedScriptHost::internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { if (info.Length() < 1 || !info[0]->IsObject()) @@ -137,6 +142,10 @@ info.GetReturnValue().Set(toV8StringInternalized(isolate, "internal#entry")); return; } + if (obj->HasPrivate(isolate->GetCurrentContext(), internalLocationPrivate(isolate)).FromMaybe(false)) { + info.GetReturnValue().Set(toV8StringInternalized(isolate, "internal#location")); + return; + } } String16 subtype = unwrapDebugger(info)->client()->valueSubtype(value); if (!subtype.isEmpty()) {
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h index 151ce90..9a25824 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h
@@ -23,6 +23,7 @@ static v8::Local<v8::Object> create(v8::Local<v8::Context>, V8DebuggerImpl*); static v8::Local<v8::Private> internalEntryPrivate(v8::Isolate*); + static v8::Local<v8::Private> internalLocationPrivate(v8::Isolate*); private: static void internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/debugger_script_externs.js b/third_party/WebKit/Source/platform/v8_inspector/debugger_script_externs.js index 25d0754..cf2a045 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/debugger_script_externs.js +++ b/third_party/WebKit/Source/platform/v8_inspector/debugger_script_externs.js
@@ -19,14 +19,6 @@ var RawLocation; /** @typedef {{ - function: function(), - functionName: string, - status: string, - location: (!RawLocation|undefined) - }} */ -var GeneratorObjectDetails; - -/** @typedef {{ id: number, name: string, sourceURL: (string|undefined),
diff --git a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json index 6ab35586..9cbc9361 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json +++ b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json
@@ -365,18 +365,6 @@ "description": "Information about the function." }, { - "id": "GeneratorObjectDetails", - "hidden": true, - "type": "object", - "properties": [ - { "name": "function", "$ref": "Runtime.RemoteObject", "description": "Generator function." }, - { "name": "functionName", "type": "string", "description": "Name of the generator function." }, - { "name": "status", "type": "string", "enum": ["running", "suspended", "closed"], "description": "Current generator object status." }, - { "name": "location", "$ref": "Location", "optional": true, "description": "If suspended, location where generator function was suspended (e.g. location of the last 'yield'). Otherwise, location of the generator function." } - ], - "description": "Information about the generator object." - }, - { "id": "CallFrame", "type": "object", "properties": [ @@ -579,17 +567,6 @@ "description": "Returns detailed information on given function." }, { - "name": "getGeneratorObjectDetails", - "hidden": true, - "parameters": [ - { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the generator object to get details for." } - ], - "returns": [ - { "name": "details", "$ref": "GeneratorObjectDetails", "description": "Information about the generator object." } - ], - "description": "Returns detailed information on given generator object." - }, - { "name": "setPauseOnExceptions", "parameters": [ { "name": "state", "type": "string", "enum": ["none", "uncaught", "all"], "description": "Pause on exceptions mode." }
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp b/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp index e29d874..f1a6a401 100644 --- a/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp +++ b/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp
@@ -77,7 +77,6 @@ KURL RegisterMockedUrl(const std::string& urlRoot, const WTF::String& filename) { WebURLResponse response; - response.initialize(); response.setMIMEType("text/html"); WTF::String localPath = m_baseFilePath; localPath.append(filename); @@ -241,7 +240,6 @@ WebString headerNameString(WebString::fromUTF8(headerName)); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*"); @@ -294,7 +292,6 @@ request.setURL(url); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedResponse, m_frameFilePath); @@ -332,7 +329,6 @@ request.setRequestContext(WebURLRequest::RequestContextScript); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedResponse, m_frameFilePath); @@ -358,7 +354,6 @@ request.setURL(url); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); @@ -385,7 +380,6 @@ request.setURL(url); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); @@ -418,7 +412,6 @@ request.setURL(url); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(0); m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); @@ -450,7 +443,6 @@ request.setURL(url); m_expectedRedirectResponse = WebURLResponse(); - m_expectedRedirectResponse.initialize(); m_expectedRedirectResponse.setMIMEType("text/html"); m_expectedRedirectResponse.setHTTPStatusCode(301); m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); @@ -461,7 +453,6 @@ m_expectedNewRequest.setURL(redirectURL); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); Platform::current()->getURLLoaderMockFactory()->registerURL(redirectURL, m_expectedResponse, m_frameFilePath); @@ -488,7 +479,6 @@ request.setURL(url); m_expectedRedirectResponse = WebURLResponse(); - m_expectedRedirectResponse.initialize(); m_expectedRedirectResponse.setMIMEType("text/html"); m_expectedRedirectResponse.setHTTPStatusCode(301); m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); @@ -499,7 +489,6 @@ m_expectedNewRequest.setURL(redirectURL); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); Platform::current()->getURLLoaderMockFactory()->registerURL(redirectURL, m_expectedResponse, m_frameFilePath); @@ -527,7 +516,6 @@ request.setURL(url); m_expectedRedirectResponse = WebURLResponse(); - m_expectedRedirectResponse.initialize(); m_expectedRedirectResponse.setMIMEType("text/html"); m_expectedRedirectResponse.setHTTPStatusCode(301); m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); @@ -538,7 +526,6 @@ m_expectedNewRequest.setURL(redirectURL); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); Platform::current()->getURLLoaderMockFactory()->registerURL(redirectURL, m_expectedResponse, m_frameFilePath); @@ -572,7 +559,6 @@ // Create a redirect response that allows the redirect to pass the access control checks. m_expectedRedirectResponse = WebURLResponse(); - m_expectedRedirectResponse.initialize(); m_expectedRedirectResponse.setMIMEType("text/html"); m_expectedRedirectResponse.setHTTPStatusCode(301); m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect); @@ -585,7 +571,6 @@ m_expectedNewRequest.setHTTPHeaderField("accept", "application/json"); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); m_expectedResponse.addHTTPHeaderField("access-control-allow-origin", "*"); @@ -699,7 +684,6 @@ WebString headerNameString(WebString::fromUTF8("non-whitelisted")); m_expectedResponse = WebURLResponse(); - m_expectedResponse.initialize(); m_expectedResponse.setMIMEType("text/html"); m_expectedResponse.setHTTPStatusCode(200); m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.cpp b/third_party/WebKit/Source/web/InspectorOverlay.cpp index 795309b6..25e495b5 100644 --- a/third_party/WebKit/Source/web/InspectorOverlay.cpp +++ b/third_party/WebKit/Source/web/InspectorOverlay.cpp
@@ -389,8 +389,7 @@ LocalFrame* frame = toLocalFrame(overlayPage()->mainFrame()); frame->view()->resize(viewportSize); overlayPage()->frameHost().visualViewport().setSize(viewportSize); - float windowToViewportScale = m_webViewImpl->chromeClient().windowToViewportScalar(1.0f); - frame->setPageZoomFactor(windowToViewportScale); + frame->setPageZoomFactor(windowToViewportScale()); reset(viewportSize, visibleRectInDocument.location()); @@ -446,7 +445,7 @@ if (!m_highlightQuad) return; - InspectorHighlight highlight; + InspectorHighlight highlight(windowToViewportScale()); highlight.appendQuad(*m_highlightQuad, m_quadHighlightConfig.content, m_quadHighlightConfig.contentOutline); evaluateInOverlay("drawHighlight", highlight.asProtocolValue()); } @@ -463,6 +462,11 @@ evaluateInOverlay("drawViewSize", ""); } +float InspectorOverlay::windowToViewportScale() const +{ + return m_webViewImpl->chromeClient().windowToViewportScalar(1.0f); +} + Page* InspectorOverlay::overlayPage() { if (m_overlayPage) @@ -544,8 +548,7 @@ // The zoom factor in the overlay frame already has been multiplied by the window to viewport scale // (aka device scale factor), so cancel it. - float windowToViewportScale = m_webViewImpl->chromeClient().windowToViewportScalar(1.0f); - resetData->setNumber("pageZoomFactor", m_webViewImpl->mainFrameImpl()->frame()->pageZoomFactor() / windowToViewportScale); + resetData->setNumber("pageZoomFactor", m_webViewImpl->mainFrameImpl()->frame()->pageZoomFactor() / windowToViewportScale()); resetData->setNumber("scrollX", documentScrollOffset.x()); resetData->setNumber("scrollY", documentScrollOffset.y());
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.h b/third_party/WebKit/Source/web/InspectorOverlay.h index c9daa2b..30f1d91 100644 --- a/third_party/WebKit/Source/web/InspectorOverlay.h +++ b/third_party/WebKit/Source/web/InspectorOverlay.h
@@ -120,6 +120,8 @@ void drawPausedInDebuggerMessage(); void drawViewSize(); + float windowToViewportScale() const; + Page* overlayPage(); LocalFrame* overlayMainFrame(); void reset(const IntSize& viewportSize, const IntPoint& documentScrollOffset);
diff --git a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp index 1cf7e7b4..6a086e9a 100644 --- a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp +++ b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
@@ -59,7 +59,6 @@ const WebURLResponse& WebDataSourceImpl::response() const { - m_responseWrapper.bind(DocumentLoader::response()); return m_responseWrapper; } @@ -135,6 +134,7 @@ WebDataSourceImpl::WebDataSourceImpl(LocalFrame* frame, const ResourceRequest& request, const SubstituteData& data) : DocumentLoader(frame, request, data) + , m_responseWrapper(DocumentLoader::response()) { }
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp index bb6f205f..5373f46 100644 --- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp +++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImplTest.cpp
@@ -67,7 +67,6 @@ WebURL scriptURL = URLTestHelpers::toKURL("https://www.example.com/sw.js"); WebURLResponse response; - response.initialize(); response.setMIMEType("text/javascript"); response.setHTTPStatusCode(200); Platform::current()->getURLLoaderMockFactory()->registerURL(scriptURL, response, ""); @@ -167,7 +166,6 @@ { WebURL scriptURL = URLTestHelpers::toKURL("https://www.example.com/sw-404.js"); WebURLResponse response; - response.initialize(); response.setMIMEType("text/javascript"); response.setHTTPStatusCode(404); WebURLError error;
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index 063029b..1ce4ec7 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -838,7 +838,7 @@ #endif bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS; - bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10; + bool isShiftF10 = (event.modifiers & WebInputEvent::InputModifiers) == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10; if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) { view()->sendContextMenuEvent(event); return WebInputEventResult::HandledSystem;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index 73a6abc..c8a165a 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1488,8 +1488,6 @@ PermissionController::provideTo(*m_frame, m_client ? m_client->permissionClient() : nullptr); if (RuntimeEnabledFeatures::webVREnabled()) VRController::provideTo(*m_frame, m_client ? m_client->serviceRegistry() : nullptr); - if (RuntimeEnabledFeatures::wakeLockEnabled()) - ScreenWakeLock::provideTo(*m_frame, m_client ? m_client->serviceRegistry(): nullptr); if (RuntimeEnabledFeatures::audioOutputDevicesEnabled()) provideAudioOutputDeviceClientTo(*m_frame, AudioOutputDeviceClientImpl::create()); if (RuntimeEnabledFeatures::installedAppEnabled())
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 3e92e32a..62a586d0d 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -1134,7 +1134,7 @@ #endif bool isUnmodifiedMenuKey = !(event.modifiers & WebInputEvent::InputModifiers) && event.windowsKeyCode == VKEY_APPS; - bool isShiftF10 = event.modifiers == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10; + bool isShiftF10 = (event.modifiers & WebInputEvent::InputModifiers) == WebInputEvent::ShiftKey && event.windowsKeyCode == VKEY_F10; if ((isUnmodifiedMenuKey || isShiftF10) && event.type == contextMenuTriggeringEventType) { sendContextMenuEvent(event); return WebInputEventResult::HandledSystem;
diff --git a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp index 50e3a2c..5ad77bd 100644 --- a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp +++ b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
@@ -105,7 +105,6 @@ error.domain = "FrameSerializerTest"; WebURLResponse response; - response.initialize(); response.setMIMEType("text/html"); response.setHTTPStatusCode(statusCode);
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp index 750fc500..7cc4987 100644 --- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp +++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
@@ -35,6 +35,7 @@ #include "platform/testing/WebLayerTreeViewImplForTesting.h" #include "public/platform/Platform.h" #include "public/platform/WebData.h" +#include "public/platform/WebSecurityOrigin.h" #include "public/platform/WebString.h" #include "public/platform/WebThread.h" #include "public/platform/WebURLLoaderMockFactory.h" @@ -124,6 +125,7 @@ WebURLRequest urlRequest; urlRequest.initialize(); urlRequest.setURL(URLTestHelpers::toKURL(url)); + urlRequest.setRequestorOrigin(WebSecurityOrigin::createUnique()); frame->loadRequest(urlRequest); pumpPendingRequestsForFrameToLoad(frame); }
diff --git a/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp b/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp index 667b098..13d13fe 100644 --- a/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp +++ b/third_party/WebKit/Source/web/tests/FrameThrottlingTest.cpp
@@ -633,8 +633,8 @@ mainResource.complete("<iframe id=frame sandbox=allow-scripts src=iframe.html></iframe>"); frameResource.complete( "<script>" - "window.addEventListener('touchstart', function(){});" - "document.addEventListener('touchstart', function(){});" + "window.addEventListener('touchstart', function(){}, {passive: false});" + "document.addEventListener('touchstart', function(){}, {passive: false});" "</script>"); auto* frameElement = toHTMLIFrameElement(document().getElementById("frame")); frameElement->setAttribute(styleAttr, "transform: translateY(480px)");
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index 2c5d98d..0b2963d 100644 --- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -208,7 +208,6 @@ void registerMockedHttpURLLoadWithCSP(const std::string& fileName, const std::string& csp, bool reportOnly = false) { WebURLResponse response; - response.initialize(); response.setMIMEType("text/html"); response.addHTTPHeaderField(reportOnly ? WebString("Content-Security-Policy-Report-Only") : WebString("Content-Security-Policy"), WebString::fromUTF8(csp)); std::string fullString = m_baseURL + fileName; @@ -3323,6 +3322,7 @@ WebURLRequest request; request.initialize(); request.setURL(toKURL(m_baseURL + "fixed_layout.html")); + request.setRequestorOrigin(WebSecurityOrigin::createUnique()); webViewHelper.webView()->mainFrame()->loadRequest(request); // start reload before first request is delivered. FrameTestHelpers::reloadFrameIgnoringCache(webViewHelper.webView()->mainFrame()); @@ -5074,7 +5074,6 @@ error.domain = "WebFrameTest"; std::string errorURL = "http://0.0.0.0"; WebURLResponse response; - response.initialize(); response.setURL(URLTestHelpers::toKURL(errorURL)); response.setMIMEType("text/html"); response.setHTTPStatusCode(500); @@ -5720,14 +5719,12 @@ char redirect[] = "http://internal.test/first_party.html"; WebURL redirectURL(toKURL(redirect)); WebURLResponse redirectResponse; - redirectResponse.initialize(); redirectResponse.setMIMEType("text/html"); redirectResponse.setHTTPStatusCode(302); redirectResponse.setHTTPHeaderField("Location", redirect); Platform::current()->getURLLoaderMockFactory()->registerURL(testURL, redirectResponse, filePath); WebURLResponse finalResponse; - finalResponse.initialize(); finalResponse.setMIMEType("text/html"); Platform::current()->getURLLoaderMockFactory()->registerURL(redirectURL, finalResponse, filePath); @@ -6293,6 +6290,7 @@ WebURLRequest request; request.initialize(); request.setURL(toKURL(url)); + request.setRequestorOrigin(WebSecurityOrigin::createUnique()); frame->loadRequest(request); // Before commit, there is no history item. @@ -8812,6 +8810,7 @@ URLTestHelpers::registerMockedURLLoad(toKURL(redirectURL), "foo.html"); request.initialize(); request.setURL(toKURL("javascript:location='" + redirectURL + "'")); + request.setRequestorOrigin(WebSecurityOrigin::createUnique()); helper.webViewImpl()->mainFrame()->toWebLocalFrame()->loadRequest(request); // Normally, the result of the JS url replaces the existing contents on the
diff --git a/third_party/WebKit/Source/web/tests/WebURLResponseTest.cpp b/third_party/WebKit/Source/web/tests/WebURLResponseTest.cpp index 4ffd6a86..8f1d8e4 100644 --- a/third_party/WebKit/Source/web/tests/WebURLResponseTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebURLResponseTest.cpp
@@ -30,6 +30,8 @@ #include "public/platform/WebURLResponse.h" +#include "platform/weborigin/KURL.h" +#include "public/platform/WebURL.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink { @@ -60,7 +62,6 @@ TestExtraData* extraData = new TestExtraData(&alive); EXPECT_TRUE(alive); - urlResponse.initialize(); urlResponse.setExtraData(extraData); EXPECT_EQ(extraData, urlResponse.getExtraData()); { @@ -75,4 +76,17 @@ EXPECT_FALSE(alive); } +TEST(WebURLResponseTest, NewInstanceIsNull) +{ + WebURLResponse instance; + EXPECT_TRUE(instance.isNull()); +} + +TEST(WebURLResponseTest, NotNullAfterSetURL) +{ + WebURLResponse instance; + instance.setURL(KURL(ParsedURLString, "http://localhost/")); + EXPECT_FALSE(instance.isNull()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/data/touch-event-handler.html b/third_party/WebKit/Source/web/tests/data/touch-event-handler.html index 208be23..4d4b8c1 100644 --- a/third_party/WebKit/Source/web/tests/data/touch-event-handler.html +++ b/third_party/WebKit/Source/web/tests/data/touch-event-handler.html
@@ -3,8 +3,7 @@ <head> <script type="text/javascript"> window.addEventListener('touchstart', function(event) { - }); + }, {passive: false}); </script> </head> - </html>
diff --git a/third_party/WebKit/Source/web/tests/sim/SimTest.cpp b/third_party/WebKit/Source/web/tests/sim/SimTest.cpp index 95c4bdfd..984f7a1 100644 --- a/third_party/WebKit/Source/web/tests/sim/SimTest.cpp +++ b/third_party/WebKit/Source/web/tests/sim/SimTest.cpp
@@ -7,6 +7,7 @@ #include "core/dom/Document.h" #include "platform/LayoutTestSupport.h" #include "platform/scroll/ScrollbarTheme.h" +#include "public/platform/WebSecurityOrigin.h" #include "public/web/WebCache.h" #include "web/WebLocalFrameImpl.h" #include "web/WebViewImpl.h" @@ -42,6 +43,7 @@ WebURLRequest request; request.initialize(); request.setURL(KURL(ParsedURLString, url)); + request.setRequestorOrigin(WebSecurityOrigin::createUnique()); webView().mainFrameImpl()->loadRequest(request); }
diff --git a/third_party/WebKit/Source/wtf/VectorTest.cpp b/third_party/WebKit/Source/wtf/VectorTest.cpp index 74b08ca..aa7509b1 100644 --- a/third_party/WebKit/Source/wtf/VectorTest.cpp +++ b/third_party/WebKit/Source/wtf/VectorTest.cpp
@@ -27,6 +27,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "wtf/HashSet.h" +#include "wtf/Optional.h" #include "wtf/PtrUtil.h" #include "wtf/text/WTFString.h" #include <memory> @@ -688,6 +689,15 @@ EXPECT_EQ(3, vector3[2]); } +TEST(VectorTest, Optional) +{ + Optional<Vector<int>> vector; + EXPECT_FALSE(vector); + vector.emplace(3); + EXPECT_TRUE(vector); + EXPECT_EQ(3u, vector->size()); +} + static_assert(VectorTraits<int>::canCopyWithMemcpy, "int should be copied with memcopy."); static_assert(VectorTraits<char>::canCopyWithMemcpy, "char should be copied with memcpy."); static_assert(VectorTraits<LChar>::canCopyWithMemcpy, "LChar should be copied with memcpy.");
diff --git a/third_party/WebKit/Source/wtf/allocator/PartitionAllocator.h b/third_party/WebKit/Source/wtf/allocator/PartitionAllocator.h index e10e16f..470ed96d 100644 --- a/third_party/WebKit/Source/wtf/allocator/PartitionAllocator.h +++ b/third_party/WebKit/Source/wtf/allocator/PartitionAllocator.h
@@ -155,6 +155,7 @@ ASSERT(location); \ return location; \ } \ + void* operator new(size_t, void* location) { return location; } \ private: \ typedef int __thisIsHereToForceASemicolonAfterThisMacro
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py index 8f56c40..947cf91 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py
@@ -330,3 +330,6 @@ self._discard_working_directory_changes() self._run_git(['checkout', '-q', self._branch_tracking_remote_master()]) self._discard_local_commits() + + def get_issue_number(self): + return str(self._run_git(['cl', 'issue']).split()[2])
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py index 9f662cd..77632028 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
@@ -31,7 +31,7 @@ import unittest from webkitpy.common.system.executive import Executive, ScriptError -from webkitpy.common.system.executive_mock import MockExecutive +from webkitpy.common.system.executive_mock import MockExecutive, MockExecutive2 from webkitpy.common.system.filesystem import FileSystem from webkitpy.common.system.filesystem_mock import MockFileSystem from webkitpy.common.checkout.scm.detection import detect_scm_system @@ -254,3 +254,11 @@ scm._run_git = lambda args: 'Date: 2013-02-08 01:55:21 -0800' self.assertEqual(scm.timestamp_of_revision('some-path', '12345'), '2013-02-08T09:55:21Z') + + def test_get_issue_number(self): + scm = Git(cwd='.', executive=MockExecutive2(output='Issue number: 12345 (http://crrev.com/12345)')) + issue_number = scm.get_issue_number() + self.assertEqual(issue_number, '12345') + scm2 = Git(cwd='.', executive=MockExecutive2(output='Issue number: None (None)')) + issue_number = scm2.get_issue_number() + self.assertEqual(issue_number, 'None')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py index ccd37df..6697e3d 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py
@@ -431,6 +431,24 @@ if self._operating_system == 'linux' and self._version != 'linux32': self._architecture = 'x86_64' + self.all_systems = (('mac10.10', 'x86'), + ('mac10.11', 'x86'), + ('win7', 'x86'), + ('win10', 'x86'), + ('linux32', 'x86'), + ('precise', 'x86_64'), + ('trusty', 'x86_64')) + + self.all_build_types = ('debug', 'release') + + # To avoid surprises when introducing new macros, these are + # intentionally fixed in time. + self.configuration_specifier_macros_dict = { + 'mac': ['mac10.10', 'mac10.11'], + 'win': ['win7', 'win10'], + 'linux': ['linux32', 'precise', 'trusty'] + } + def buildbot_archives_baselines(self): return self._name != 'test-win-win7' @@ -528,33 +546,16 @@ # By default, we assume we want to test every graphics type in # every configuration on every system. test_configurations = [] - for version, architecture in self._all_systems(): - for build_type in self._all_build_types(): + for version, architecture in self.all_systems: + for build_type in self.all_build_types: test_configurations.append(TestConfiguration( version=version, architecture=architecture, build_type=build_type)) return test_configurations - def _all_systems(self): - return (('mac10.10', 'x86'), - ('mac10.11', 'x86'), - ('win7', 'x86'), - ('win10', 'x86'), - ('linux32', 'x86'), - ('precise', 'x86_64'), - ('trusty', 'x86_64')) - - def _all_build_types(self): - return ('debug', 'release') - def configuration_specifier_macros(self): - """To avoid surprises when introducing new macros, these are intentionally fixed in time.""" - return { - 'mac': ['mac10.10', 'mac10.11'], - 'win': ['win7', 'win10'], - 'linux': ['linux32', 'precise', 'trusty'] - } + return self.configuration_specifier_macros_dict def virtual_test_suites(self): return [
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py index d56f1682..b65acb6 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -5,6 +5,7 @@ """Pull latest revisions of a W3C test repo and make a local commit.""" import argparse +import time from webkitpy.common.webkit_finder import WebKitFinder @@ -12,6 +13,8 @@ WPT_DEST_NAME = 'wpt' CSS_DEST_NAME = 'csswg-test' +POLL_DELAY_SECONDS = 300 + class DepsUpdater(object): @@ -24,6 +27,7 @@ self.allow_local_commits = False self.keep_w3c_repos_around = False self.target = None + self.auto_update = False def main(self, argv=None): self.parse_args(argv) @@ -60,6 +64,19 @@ self.commit_changes_if_needed(chromium_commitish, import_commitish) + if self.auto_update: + self.check_run(['git', 'cl', 'upload', '-f']) + self.run(['git', 'cl', 'set-commit', '--dry-run']) + while True: + time.sleep(POLL_DELAY_SECONDS) + _, out = self.run(['git', 'cl', 'try-results']) + results = self.parse_try_job_results(out) + if results['Started'] or results['Scheduled']: + continue + if results['Failures']: + return 1 + break + self.run(['git', 'cl', 'land', '-f']) return 0 def parse_args(self, argv): @@ -73,12 +90,15 @@ help='leave the w3c repos around that were imported previously.') parser.add_argument('target', choices=['css', 'wpt'], help='Target repository. "css" for csswg-test, "wpt" for web-platform-tests.') + parser.add_argument('--auto-update', action='store_true', + help='uploads CL and initiates commit queue.') args = parser.parse_args(argv) self.allow_local_commits = args.allow_local_commits self.keep_w3c_repos_around = args.keep_w3c_repos_around self.verbose = args.verbose self.target = args.target + self.auto_update = args.auto_update def checkout_is_okay(self): git_diff_retcode, _ = self.run(['git', 'diff', '--quiet', 'HEAD'], exit_on_failure=False) @@ -222,3 +242,42 @@ def print_(self, msg): self.host.print_(msg) + + def parse_try_job_results(self, results): + """Parses try job results from Rietveld. + + Turns the output from git cl try-results into a usable format. + + Args: + results: The stdout obtained by running git cl try-results. + + Returns: + A dict mapping result type (e.g. Success, Failure) + to list of bots with that result type. The list of builders + is represented as a set and any bots with both success and + failure results are not included in failures. + + Raises: + AttributeError: An unexpected result was found. + """ + sets = {} + for line in results.splitlines(): + line = line.strip() + if line[-1] == ':': + result_type = line[:-1] + sets[result_type] = set() + elif line.split()[0] == 'Total:': + break + else: + sets[result_type].add(line.split()[0]) + print sets + sets['Failures'] -= sets['Successes'] + sets['Started'] -= sets['Successes'] + sets['Started'] -= sets['Failures'] + return sets + + def check_run(self, command): + return_code, out = self.run(command) + if return_code: + raise Exception('%s failed with exit code %d.' % ' '.join(command), return_code) + return out
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py new file mode 100644 index 0000000..50da6a5b --- /dev/null +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
@@ -0,0 +1,43 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import unittest + +from webkitpy.w3c.deps_updater import DepsUpdater +from webkitpy.common.host_mock import MockHost + + +class DepsUpdaterTest(unittest.TestCase): + + def test_parse_try_job_results(self): + output = """Successes: +linux_builder http://example.com/linux_builder/builds/222 +mac_builder http://example.com/mac_builder/builds/222 +win_builder http://example.com/win_builder/builds/222 +Failures: +android_builder http://example.com/android_builder/builds/111 +chromeos_builder http://example.com/chromeos_builder/builds/111 +win_builder http://example.com/win_builder/builds/111 +Started: +chromeos_generic http://example.com/chromeos_generic/builds/111 +chromeos_daisy http://example.com/chromeos_daisy/builds/111 +Total: 8 tryjobs +""" + host = MockHost() + updater = DepsUpdater(host) + self.assertEqual(updater.parse_try_job_results(output), { + 'Successes': set([ + 'mac_builder', + 'win_builder', + 'linux_builder' + ]), + 'Failures': set([ + 'android_builder', + 'chromeos_builder' + ]), + 'Started': set([ + 'chromeos_generic', + 'chromeos_daisy' + ]) + })
diff --git a/third_party/WebKit/public/blink_headers.gypi b/third_party/WebKit/public/blink_headers.gypi index 1c38838..b7e9a2b 100644 --- a/third_party/WebKit/public/blink_headers.gypi +++ b/third_party/WebKit/public/blink_headers.gypi
@@ -252,6 +252,7 @@ "platform/modules/indexeddb/WebIDBKeyPath.h", "platform/modules/indexeddb/WebIDBKeyRange.h", "platform/modules/indexeddb/WebIDBMetadata.h", + "platform/modules/indexeddb/WebIDBObserver.h", "platform/modules/indexeddb/WebIDBTypes.h", "platform/modules/indexeddb/WebIDBValue.h", "platform/modules/installedapp/WebInstalledAppClient.h",
diff --git a/third_party/WebKit/public/platform/WebFrameScheduler.h b/third_party/WebKit/public/platform/WebFrameScheduler.h index 6d11c0f..558cecd 100644 --- a/third_party/WebKit/public/platform/WebFrameScheduler.h +++ b/third_party/WebKit/public/platform/WebFrameScheduler.h
@@ -47,11 +47,11 @@ // Tells the scheduler a resource load has started. The scheduler may make // policy decisions based on this. - virtual void incrementPendingResourceLoadCount() { } + virtual void didStartLoading(unsigned long identifier) { } - // Tells the scheduler a resource load has started. The scheduler may make + // Tells the scheduler a resource load has stopped. The scheduler may make // policy decisions based on this. - virtual void decrementPendingResourceLoadCount() { } + virtual void didStopLoading(unsigned long identifier) { } }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebURLResponse.h b/third_party/WebKit/public/platform/WebURLResponse.h index 7ab714f..243be1e 100644 --- a/third_party/WebKit/public/platform/WebURLResponse.h +++ b/third_party/WebKit/public/platform/WebURLResponse.h
@@ -37,6 +37,7 @@ #include "public/platform/WebString.h" #include "public/platform/WebVector.h" #include "public/platform/modules/serviceworker/WebServiceWorkerResponseType.h" +#include <memory> namespace blink { @@ -135,25 +136,12 @@ virtual ~ExtraData() { } }; - ~WebURLResponse() { reset(); } + BLINK_PLATFORM_EXPORT ~WebURLResponse(); - WebURLResponse() : m_private(0) { } - WebURLResponse(const WebURLResponse& r) : m_private(0) { assign(r); } - WebURLResponse& operator=(const WebURLResponse& r) - { - assign(r); - return *this; - } - - explicit WebURLResponse(const WebURL& url) : m_private(0) - { - initialize(); - setURL(url); - } - - BLINK_PLATFORM_EXPORT void initialize(); - BLINK_PLATFORM_EXPORT void reset(); - BLINK_PLATFORM_EXPORT void assign(const WebURLResponse&); + BLINK_PLATFORM_EXPORT WebURLResponse(); + BLINK_PLATFORM_EXPORT WebURLResponse(const WebURLResponse&); + BLINK_PLATFORM_EXPORT explicit WebURLResponse(const WebURL&); + BLINK_PLATFORM_EXPORT WebURLResponse& operator=(const WebURLResponse&); BLINK_PLATFORM_EXPORT bool isNull() const; @@ -305,9 +293,17 @@ BLINK_PLATFORM_EXPORT void setExtraData(ExtraData*); protected: - BLINK_PLATFORM_EXPORT void assign(WebURLResponsePrivate*); + // Permit subclasses to set arbitrary WebURLResponsePrivate pointer as + // |m_private|. Parameter must be non-null. |m_owningPrivate| is not set + // in this case. + BLINK_PLATFORM_EXPORT explicit WebURLResponse(WebURLResponsePrivate*); private: + // If this instance owns WebURLResponsePrivate |m_owningPrivate| is + // non-null and is pointed by |m_private|. + std::unique_ptr<WebURLResponsePrivate> m_owningPrivate; + + // Should never be null. WebURLResponsePrivate* m_private; };
diff --git a/third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabase.h b/third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabase.h index 4752309..d4e80d2 100644 --- a/third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabase.h +++ b/third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabase.h
@@ -30,7 +30,10 @@ #include "public/platform/WebCommon.h" #include "public/platform/modules/indexeddb/WebIDBCursor.h" #include "public/platform/modules/indexeddb/WebIDBMetadata.h" +#include "public/platform/modules/indexeddb/WebIDBObserver.h" #include "public/platform/modules/indexeddb/WebIDBTypes.h" +#include <set> +#include <vector> namespace blink { @@ -40,6 +43,7 @@ class WebIDBKey; class WebIDBKeyPath; class WebIDBKeyRange; +class WebIDBObserver; class WebIDBDatabase { public: @@ -61,6 +65,9 @@ typedef WebVector<WebIDBKey> WebIndexKeys; + virtual int32_t addObserver(std::unique_ptr<WebIDBObserver>, long long transactionId) = 0; + virtual bool containsObserverId(int32_t id) const = 0; + virtual void removeObservers(const std::vector<int32_t>& observerIdsToRemove) = 0; virtual void get(long long transactionId, long long objectStoreId, long long indexId, const WebIDBKeyRange&, bool keyOnly, WebIDBCallbacks*) = 0; virtual void getAll(long long transactionId, long long objectStoreId, long long indexId, const WebIDBKeyRange&, long long maxCount, bool keyOnly, WebIDBCallbacks*) = 0; virtual void put(long long transactionId, long long objectStoreId, const WebData& value, const WebVector<WebBlobInfo>&, const WebIDBKey&, WebIDBPutMode, WebIDBCallbacks*, const WebVector<long long>& indexIds, const WebVector<WebIndexKeys>&) = 0;
diff --git a/third_party/WebKit/public/platform/modules/indexeddb/WebIDBObserver.h b/third_party/WebKit/public/platform/modules/indexeddb/WebIDBObserver.h new file mode 100644 index 0000000..0f93212 --- /dev/null +++ b/third_party/WebKit/public/platform/modules/indexeddb/WebIDBObserver.h
@@ -0,0 +1,19 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This class makes the blink::IDBObserver visible to the content layer by holding a reference to it. + +#ifndef WebIDBObserver_h +#define WebIDBObserver_h + +namespace blink { + +class WebIDBObserver { +public: + virtual ~WebIDBObserver() {} +}; + +} // namespace blink + +#endif // WebIDBObserver_h
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h index 21582b6..a5963c9 100644 --- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h +++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h
@@ -44,6 +44,7 @@ ErrorTypeNavigation, ErrorTypeNetwork, ErrorTypeNotFound, + ErrorTypeScriptEvaluateFailed, ErrorTypeSecurity, ErrorTypeState, ErrorTypeTimeout,
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni index cdbe0c9..5d1aa79 100644 --- a/third_party/boringssl/BUILD.generated.gni +++ b/third_party/boringssl/BUILD.generated.gni
@@ -288,7 +288,6 @@ "src/ssl/dtls_record.c", "src/ssl/handshake_client.c", "src/ssl/handshake_server.c", - "src/ssl/pqueue/pqueue.c", "src/ssl/s3_both.c", "src/ssl/s3_enc.c", "src/ssl/s3_lib.c",
diff --git a/third_party/boringssl/BUILD.generated_tests.gni b/third_party/boringssl/BUILD.generated_tests.gni index 8b7ea3cc..16bddff0 100644 --- a/third_party/boringssl/BUILD.generated_tests.gni +++ b/third_party/boringssl/BUILD.generated_tests.gni
@@ -522,18 +522,6 @@ deps = invoker.deps } - executable("boringssl_pqueue_test") { - sources = [ - "src/ssl/pqueue/pqueue_test.c", - ] - sources += _test_support_sources - if (defined(invoker.configs_exclude)) { - configs -= invoker.configs_exclude - } - configs += invoker.configs - deps = invoker.deps - } - executable("boringssl_ssl_test") { sources = [ "src/ssl/ssl_test.cc", @@ -582,7 +570,6 @@ ":boringssl_pkcs7_test", ":boringssl_pkcs8_test", ":boringssl_poly1305_test", - ":boringssl_pqueue_test", ":boringssl_refcount_test", ":boringssl_rsa_test", ":boringssl_spake25519_test",
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index 65a483e..399fb58 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi
@@ -16,7 +16,6 @@ 'src/ssl/dtls_record.c', 'src/ssl/handshake_client.c', 'src/ssl/handshake_server.c', - 'src/ssl/pqueue/pqueue.c', 'src/ssl/s3_both.c', 'src/ssl/s3_enc.c', 'src/ssl/s3_lib.c',
diff --git a/third_party/boringssl/boringssl_tests.gypi b/third_party/boringssl/boringssl_tests.gypi index 8542e5c2..1076214f 100644 --- a/third_party/boringssl/boringssl_tests.gypi +++ b/third_party/boringssl/boringssl_tests.gypi
@@ -595,20 +595,6 @@ 'msvs_disabled_warnings': [ 4267, ], }, { - 'target_name': 'boringssl_pqueue_test', - 'type': 'executable', - 'dependencies': [ - 'boringssl.gyp:boringssl', - ], - 'sources': [ - 'src/ssl/pqueue/pqueue_test.c', - '<@(boringssl_test_support_sources)', - ], - # TODO(davidben): Fix size_t truncations in BoringSSL. - # https://crbug.com/429039 - 'msvs_disabled_warnings': [ 4267, ], - }, - { 'target_name': 'boringssl_ssl_test', 'type': 'executable', 'dependencies': [ @@ -671,7 +657,6 @@ 'boringssl_pkcs7_test', 'boringssl_pkcs8_test', 'boringssl_poly1305_test', - 'boringssl_pqueue_test', 'boringssl_refcount_test', 'boringssl_rsa_test', 'boringssl_spake25519_test',
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c index 32976ad..14f2dc1 100644 --- a/third_party/boringssl/err_data.c +++ b/third_party/boringssl/err_data.c
@@ -74,51 +74,51 @@ 0xc3a8845, 0xc3b00ea, 0x10320845, - 0x1032939a, - 0x103313a6, - 0x103393bf, - 0x103413d2, - 0x10348e7a, + 0x103293ab, + 0x103313b7, + 0x103393d0, + 0x103413e3, + 0x10348e8b, 0x10350c19, - 0x103593e5, - 0x103613fa, - 0x1036940d, - 0x1037142c, - 0x10379445, - 0x1038145a, - 0x10389478, - 0x10391487, - 0x103994a3, - 0x103a14be, - 0x103a94cd, - 0x103b14e9, - 0x103b9504, - 0x103c151b, + 0x103593f6, + 0x1036140b, + 0x1036941e, + 0x1037143d, + 0x10379456, + 0x1038146b, + 0x10389489, + 0x10391498, + 0x103994b4, + 0x103a14cf, + 0x103a94de, + 0x103b14fa, + 0x103b9515, + 0x103c152c, 0x103c80ea, - 0x103d152c, - 0x103d9540, - 0x103e155f, - 0x103e956e, - 0x103f1585, - 0x103f9598, + 0x103d153d, + 0x103d9551, + 0x103e1570, + 0x103e957f, + 0x103f1596, + 0x103f95a9, 0x10400bea, - 0x104095ab, - 0x104115c9, - 0x104195dc, - 0x104215f6, - 0x10429606, - 0x1043161a, - 0x10439630, - 0x10441648, - 0x1044965d, - 0x10451671, - 0x10459683, + 0x104095bc, + 0x104115da, + 0x104195ed, + 0x10421607, + 0x10429617, + 0x1043162b, + 0x10439641, + 0x10441659, + 0x1044966e, + 0x10451682, + 0x10459694, 0x104605fb, 0x1046893f, - 0x10471698, - 0x104796af, - 0x104816c4, - 0x104896d2, + 0x104716a9, + 0x104796c0, + 0x104816d5, + 0x104896e3, 0x14320bcd, 0x14328bdb, 0x14330bea, @@ -126,51 +126,51 @@ 0x143400ac, 0x143480ea, 0x18320083, - 0x18328ed0, + 0x18328ee1, 0x183300ac, - 0x18338ee6, - 0x18340efa, + 0x18338ef7, + 0x18340f0b, 0x183480ea, - 0x18350f0f, - 0x18358f27, - 0x18360f3c, - 0x18368f50, - 0x18370f74, - 0x18378f8a, - 0x18380f9e, - 0x18388fae, + 0x18350f20, + 0x18358f38, + 0x18360f4d, + 0x18368f61, + 0x18370f85, + 0x18378f9b, + 0x18380faf, + 0x18388fbf, 0x18390a57, - 0x18398fbe, - 0x183a0fd3, - 0x183a8fe7, + 0x18398fcf, + 0x183a0fe4, + 0x183a8ff8, 0x183b0c25, - 0x183b8ff4, - 0x183c1006, - 0x183c9011, - 0x183d1021, - 0x183d9032, - 0x183e1043, - 0x183e9055, - 0x183f107e, - 0x183f9097, - 0x184010af, + 0x183b9005, + 0x183c1017, + 0x183c9022, + 0x183d1032, + 0x183d9043, + 0x183e1054, + 0x183e9066, + 0x183f108f, + 0x183f90a8, + 0x184010c0, 0x184086d3, - 0x203210d6, - 0x243210e2, + 0x203210e7, + 0x243210f3, 0x24328985, - 0x243310f4, - 0x24339101, - 0x2434110e, - 0x24349120, - 0x2435112f, - 0x2435914c, - 0x24361159, - 0x24369167, - 0x24371175, - 0x24379183, - 0x2438118c, - 0x24389199, - 0x243911ac, + 0x24331105, + 0x24339112, + 0x2434111f, + 0x24349131, + 0x24351140, + 0x2435915d, + 0x2436116a, + 0x24369178, + 0x24371186, + 0x24379194, + 0x2438119d, + 0x243891aa, + 0x243911bd, 0x28320c0d, 0x28328c25, 0x28330bea, @@ -178,42 +178,42 @@ 0x28340c19, 0x283480ac, 0x283500ea, - 0x2c32274a, - 0x2c32a758, - 0x2c33276a, - 0x2c33a77c, - 0x2c342790, - 0x2c34a7a2, - 0x2c3527bd, - 0x2c35a7cf, - 0x2c3627e2, + 0x2c322799, + 0x2c32a7a7, + 0x2c3327b9, + 0x2c33a7cb, + 0x2c3427df, + 0x2c34a7f1, + 0x2c35280c, + 0x2c35a81e, + 0x2c362831, 0x2c36832d, - 0x2c3727ef, - 0x2c37a801, - 0x2c382814, - 0x2c38a82b, - 0x2c392839, - 0x2c39a849, - 0x2c3a285b, - 0x2c3aa86f, - 0x2c3b2880, - 0x2c3ba89f, - 0x2c3c28b3, - 0x2c3ca8c9, - 0x2c3d28e2, - 0x2c3da8ff, - 0x2c3e2910, - 0x2c3ea91e, - 0x2c3f2936, - 0x2c3fa94e, - 0x2c40295b, - 0x2c4090d6, - 0x2c41296c, - 0x2c41a97f, - 0x2c4210af, - 0x2c42a990, + 0x2c37283e, + 0x2c37a850, + 0x2c382863, + 0x2c38a87a, + 0x2c392888, + 0x2c39a898, + 0x2c3a28aa, + 0x2c3aa8be, + 0x2c3b28cf, + 0x2c3ba8ee, + 0x2c3c2902, + 0x2c3ca918, + 0x2c3d2931, + 0x2c3da94e, + 0x2c3e295f, + 0x2c3ea96d, + 0x2c3f2985, + 0x2c3fa99d, + 0x2c4029aa, + 0x2c4090e7, + 0x2c4129bb, + 0x2c41a9ce, + 0x2c4210c0, + 0x2c42a9df, 0x2c430720, - 0x2c43a891, + 0x2c43a8e0, 0x30320000, 0x30328015, 0x3033001f, @@ -319,211 +319,214 @@ 0x3c340cb3, 0x3c348cdd, 0x3c350cf8, - 0x3c358d0d, - 0x3c360d26, - 0x3c368d3e, - 0x3c370d4f, - 0x3c378d5d, - 0x3c380d6a, - 0x3c388d7e, + 0x3c358d1e, + 0x3c360d37, + 0x3c368d4f, + 0x3c370d60, + 0x3c378d6e, + 0x3c380d7b, + 0x3c388d8f, 0x3c390c25, - 0x3c398d92, - 0x3c3a0da6, + 0x3c398da3, + 0x3c3a0db7, 0x3c3a88ff, - 0x3c3b0db6, - 0x3c3b8dd1, - 0x3c3c0de3, - 0x3c3c8df9, - 0x3c3d0e03, - 0x3c3d8e17, - 0x3c3e0e25, - 0x3c3e8e4a, + 0x3c3b0dc7, + 0x3c3b8de2, + 0x3c3c0df4, + 0x3c3c8e0a, + 0x3c3d0e14, + 0x3c3d8e28, + 0x3c3e0e36, + 0x3c3e8e5b, 0x3c3f0c4e, - 0x3c3f8e33, + 0x3c3f8e44, 0x3c4000ac, 0x3c4080ea, 0x3c410cce, - 0x403216e9, - 0x403296ff, - 0x4033172d, - 0x40339737, - 0x4034174e, - 0x4034976c, - 0x4035177c, - 0x4035978e, - 0x4036179b, - 0x403697a7, - 0x403717bc, - 0x403797ce, - 0x403817d9, - 0x403897eb, - 0x40390e7a, - 0x403997fb, - 0x403a180e, - 0x403a982f, - 0x403b1840, - 0x403b9850, + 0x3c418d0d, + 0x403216fa, + 0x40329710, + 0x4033173e, + 0x40339748, + 0x4034175f, + 0x4034977d, + 0x4035178d, + 0x4035979f, + 0x403617ac, + 0x403697b8, + 0x403717cd, + 0x403797df, + 0x403817ea, + 0x403897fc, + 0x40390e8b, + 0x4039980c, + 0x403a181f, + 0x403a9840, + 0x403b1851, + 0x403b9861, 0x403c0064, 0x403c8083, - 0x403d185c, - 0x403d9872, - 0x403e1881, - 0x403e9894, - 0x403f18ae, - 0x403f98bc, - 0x404018d1, - 0x404098e5, - 0x40411902, - 0x4041991d, - 0x40421936, - 0x40429949, - 0x4043195d, - 0x40439975, - 0x4044198c, + 0x403d186d, + 0x403d9883, + 0x403e1892, + 0x403e98a5, + 0x403f18bf, + 0x403f98cd, + 0x404018e2, + 0x404098f6, + 0x40411913, + 0x4041992e, + 0x40421947, + 0x4042995a, + 0x4043196e, + 0x40439986, + 0x4044199d, 0x404480ac, - 0x404519a1, - 0x404599b3, - 0x404619d7, - 0x404699f7, - 0x40471a05, - 0x40479a19, - 0x40481a2e, - 0x40489a47, - 0x40491a5e, - 0x40499a78, - 0x404a1a8f, - 0x404a9aad, - 0x404b1ac5, - 0x404b9adc, - 0x404c1af2, - 0x404c9b04, - 0x404d1b25, - 0x404d9b47, - 0x404e1b5b, - 0x404e9b68, - 0x404f1b7f, - 0x404f9b8f, - 0x40501b9f, - 0x40509bb3, - 0x40511bce, - 0x40519bde, - 0x40521bf5, - 0x40529c07, - 0x40531c1f, - 0x40539c32, - 0x40541c47, - 0x40549c6a, - 0x40551c78, - 0x40559c95, - 0x40561ca2, - 0x40569cbb, - 0x40571cd3, - 0x40579ce6, - 0x40581cfb, - 0x40589d0d, - 0x40591d1d, - 0x40599d36, - 0x405a1d4a, - 0x405a9d5a, - 0x405b1d72, - 0x405b9d83, - 0x405c1d96, - 0x405c9da7, - 0x405d1db4, - 0x405d9dcb, - 0x405e1deb, + 0x404519b2, + 0x404599c4, + 0x404619e8, + 0x40469a08, + 0x40471a16, + 0x40479a2a, + 0x40481a3f, + 0x40489a58, + 0x40491a6f, + 0x40499a89, + 0x404a1aa0, + 0x404a9abe, + 0x404b1ad6, + 0x404b9aed, + 0x404c1b03, + 0x404c9b15, + 0x404d1b36, + 0x404d9b58, + 0x404e1b6c, + 0x404e9b79, + 0x404f1b90, + 0x404f9ba0, + 0x40501bca, + 0x40509bde, + 0x40511bf9, + 0x40519c09, + 0x40521c20, + 0x40529c32, + 0x40531c4a, + 0x40539c5d, + 0x40541c72, + 0x40549c95, + 0x40551ca3, + 0x40559cc0, + 0x40561ccd, + 0x40569ce6, + 0x40571cfe, + 0x40579d11, + 0x40581d26, + 0x40589d38, + 0x40591d48, + 0x40599d61, + 0x405a1d75, + 0x405a9d85, + 0x405b1d9d, + 0x405b9dae, + 0x405c1dc1, + 0x405c9dd2, + 0x405d1ddf, + 0x405d9df6, + 0x405e1e16, 0x405e8a95, - 0x405f1e0c, - 0x405f9e19, - 0x40601e27, - 0x40609e49, - 0x40611e71, - 0x40619e86, - 0x40621e9d, - 0x40629eae, - 0x40631ebf, - 0x40639ed4, - 0x40641eeb, - 0x40649efc, - 0x40651f17, - 0x40659f2e, - 0x40661f46, - 0x40669f70, - 0x40671f9b, - 0x40679fbc, - 0x40681fcf, - 0x40689ff0, - 0x40692022, - 0x4069a050, - 0x406a2071, - 0x406aa091, - 0x406b2219, - 0x406ba23c, - 0x406c2252, - 0x406ca47e, - 0x406d24ad, - 0x406da4d5, - 0x406e24ee, - 0x406ea506, - 0x406f2525, - 0x406fa53a, - 0x4070254d, - 0x4070a56a, + 0x405f1e37, + 0x405f9e44, + 0x40601e52, + 0x40609e74, + 0x40611e9c, + 0x40619eb1, + 0x40621ec8, + 0x40629ed9, + 0x40631eea, + 0x40639eff, + 0x40641f16, + 0x40649f27, + 0x40651f42, + 0x40659f59, + 0x40661f71, + 0x40669f9b, + 0x40671fc6, + 0x40679fe7, + 0x40681ffa, + 0x4068a01b, + 0x4069204d, + 0x4069a07b, + 0x406a209c, + 0x406aa0bc, + 0x406b2244, + 0x406ba267, + 0x406c227d, + 0x406ca4a9, + 0x406d24d8, + 0x406da500, + 0x406e2519, + 0x406ea531, + 0x406f2550, + 0x406fa565, + 0x40702578, + 0x4070a595, 0x40710800, - 0x4071a57c, - 0x4072258f, - 0x4072a5a8, - 0x407325c0, - 0x4073935c, - 0x407425d4, - 0x4074a5ee, - 0x407525ff, - 0x4075a613, - 0x40762621, - 0x40769199, - 0x40772646, - 0x4077a668, - 0x40782683, - 0x4078a698, - 0x407926af, - 0x4079a6c5, - 0x407a26d1, - 0x407aa6e4, - 0x407b26f9, - 0x407ba70b, - 0x407c2720, - 0x407ca729, - 0x407d200b, - 0x41f42144, - 0x41f921d6, - 0x41fe20c9, - 0x41fea2a5, - 0x41ff2396, - 0x4203215d, - 0x4208217f, - 0x4208a1bb, - 0x420920ad, - 0x4209a1f5, - 0x420a2104, - 0x420aa0e4, - 0x420b2124, - 0x420ba19d, - 0x420c23b2, - 0x420ca272, - 0x420d228c, - 0x420da2c3, - 0x421222dd, - 0x42172379, - 0x4217a31f, - 0x421c2341, - 0x421f22fc, - 0x422123c9, - 0x4226235c, - 0x422b2462, - 0x422ba42b, - 0x422c244a, - 0x422ca405, - 0x422d23e4, + 0x4071a5a7, + 0x407225ba, + 0x4072a5d3, + 0x407325eb, + 0x4073936d, + 0x407425ff, + 0x4074a619, + 0x4075262a, + 0x4075a63e, + 0x4076264c, + 0x407691aa, + 0x40772671, + 0x4077a693, + 0x407826ae, + 0x4078a6e7, + 0x407926fe, + 0x4079a714, + 0x407a2720, + 0x407aa733, + 0x407b2748, + 0x407ba75a, + 0x407c276f, + 0x407ca778, + 0x407d2036, + 0x407d9bb0, + 0x407e26c3, + 0x41f4216f, + 0x41f92201, + 0x41fe20f4, + 0x41fea2d0, + 0x41ff23c1, + 0x42032188, + 0x420821aa, + 0x4208a1e6, + 0x420920d8, + 0x4209a220, + 0x420a212f, + 0x420aa10f, + 0x420b214f, + 0x420ba1c8, + 0x420c23dd, + 0x420ca29d, + 0x420d22b7, + 0x420da2ee, + 0x42122308, + 0x421723a4, + 0x4217a34a, + 0x421c236c, + 0x421f2327, + 0x422123f4, + 0x42262387, + 0x422b248d, + 0x422ba456, + 0x422c2475, + 0x422ca430, + 0x422d240f, 0x4432072b, 0x4432873a, 0x44330746, @@ -541,104 +544,104 @@ 0x44390800, 0x4439880e, 0x443a0821, - 0x4c3211c3, - 0x4c3291d3, - 0x4c3311e6, - 0x4c339206, + 0x4c3211d4, + 0x4c3291e4, + 0x4c3311f7, + 0x4c339217, 0x4c3400ac, 0x4c3480ea, - 0x4c351212, - 0x4c359220, - 0x4c36123c, - 0x4c36924f, - 0x4c37125e, - 0x4c37926c, - 0x4c381281, - 0x4c38928d, - 0x4c3912ad, - 0x4c3992d7, - 0x4c3a12f0, - 0x4c3a9309, + 0x4c351223, + 0x4c359231, + 0x4c36124d, + 0x4c369260, + 0x4c37126f, + 0x4c37927d, + 0x4c381292, + 0x4c38929e, + 0x4c3912be, + 0x4c3992e8, + 0x4c3a1301, + 0x4c3a931a, 0x4c3b05fb, - 0x4c3b9322, - 0x4c3c1334, - 0x4c3c9343, - 0x4c3d135c, - 0x4c3d936b, - 0x4c3e1378, - 0x503229a2, - 0x5032a9b1, - 0x503329bc, - 0x5033a9cc, - 0x503429e5, - 0x5034a9ff, - 0x50352a0d, - 0x5035aa23, - 0x50362a35, - 0x5036aa4b, - 0x50372a64, - 0x5037aa77, - 0x50382a8f, - 0x5038aaa0, - 0x50392ab5, - 0x5039aac9, - 0x503a2ae9, - 0x503aaaff, - 0x503b2b17, - 0x503bab29, - 0x503c2b45, - 0x503cab5c, - 0x503d2b75, - 0x503dab8b, - 0x503e2b98, - 0x503eabae, - 0x503f2bc0, + 0x4c3b9333, + 0x4c3c1345, + 0x4c3c9354, + 0x4c3d136d, + 0x4c3d937c, + 0x4c3e1389, + 0x503229f1, + 0x5032aa00, + 0x50332a0b, + 0x5033aa1b, + 0x50342a34, + 0x5034aa4e, + 0x50352a5c, + 0x5035aa72, + 0x50362a84, + 0x5036aa9a, + 0x50372ab3, + 0x5037aac6, + 0x50382ade, + 0x5038aaef, + 0x50392b04, + 0x5039ab18, + 0x503a2b38, + 0x503aab4e, + 0x503b2b66, + 0x503bab78, + 0x503c2b94, + 0x503cabab, + 0x503d2bc4, + 0x503dabda, + 0x503e2be7, + 0x503eabfd, + 0x503f2c0f, 0x503f8382, - 0x50402bd3, - 0x5040abe3, - 0x50412bfd, - 0x5041ac0c, - 0x50422c26, - 0x5042ac43, - 0x50432c53, - 0x5043ac63, - 0x50442c72, + 0x50402c22, + 0x5040ac32, + 0x50412c4c, + 0x5041ac5b, + 0x50422c75, + 0x5042ac92, + 0x50432ca2, + 0x5043acb2, + 0x50442cc1, 0x5044843f, - 0x50452c86, - 0x5045aca4, - 0x50462cb7, - 0x5046accd, - 0x50472cdf, - 0x5047acf4, - 0x50482d1a, - 0x5048ad28, - 0x50492d3b, - 0x5049ad50, - 0x504a2d66, - 0x504aad76, - 0x504b2d96, - 0x504bada9, - 0x504c2dcc, - 0x504cadfa, - 0x504d2e0c, - 0x504dae29, - 0x504e2e44, - 0x504eae60, - 0x504f2e72, - 0x504fae89, - 0x50502e98, + 0x50452cd5, + 0x5045acf3, + 0x50462d06, + 0x5046ad1c, + 0x50472d2e, + 0x5047ad43, + 0x50482d69, + 0x5048ad77, + 0x50492d8a, + 0x5049ad9f, + 0x504a2db5, + 0x504aadc5, + 0x504b2de5, + 0x504badf8, + 0x504c2e1b, + 0x504cae49, + 0x504d2e5b, + 0x504dae78, + 0x504e2e93, + 0x504eaeaf, + 0x504f2ec1, + 0x504faed8, + 0x50502ee7, 0x505086ef, - 0x50512eab, - 0x58320eb8, - 0x68320e7a, + 0x50512efa, + 0x58320ec9, + 0x68320e8b, 0x68328c25, 0x68330c38, - 0x68338e88, - 0x68340e98, + 0x68338e99, + 0x68340ea9, 0x683480ea, - 0x6c320e56, + 0x6c320e67, 0x6c328bfc, - 0x6c330e61, + 0x6c330e72, 0x74320a0b, 0x78320970, 0x78328985, @@ -665,7 +668,7 @@ 0x783d0b19, 0x783d8b2e, 0x783e0a84, - 0x7c3210c5, + 0x7c3210d6, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); @@ -844,6 +847,7 @@ "GROUP_MISMATCH\0" "I2D_ECPKPARAMETERS_FAILURE\0" "INCOMPATIBLE_OBJECTS\0" + "INVALID_COFACTOR\0" "INVALID_COMPRESSED_POINT\0" "INVALID_COMPRESSION_BIT\0" "INVALID_ENCODING\0" @@ -1025,6 +1029,7 @@ "INAPPROPRIATE_FALLBACK\0" "INVALID_COMMAND\0" "INVALID_MESSAGE\0" + "INVALID_OUTER_RECORD_TYPE\0" "INVALID_SSL_SESSION\0" "INVALID_TICKET_KEYS_LENGTH\0" "LENGTH_MISMATCH\0" @@ -1133,6 +1138,7 @@ "UNSUPPORTED_COMPRESSION_ALGORITHM\0" "UNSUPPORTED_ELLIPTIC_CURVE\0" "UNSUPPORTED_PROTOCOL\0" + "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\0" "WRONG_CERTIFICATE_TYPE\0" "WRONG_CIPHER_RETURNED\0" "WRONG_CURVE\0"
diff --git a/third_party/boringssl/win-x86_64/crypto/chacha/chacha-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/chacha/chacha-x86_64.asm index 0ecbe95..afebd2e 100644 --- a/third_party/boringssl/win-x86_64/crypto/chacha/chacha-x86_64.asm +++ b/third_party/boringssl/win-x86_64/crypto/chacha/chacha-x86_64.asm
@@ -1091,10 +1091,10 @@ - vbroadcasti128 ymm11,YMMWORD[$L$sigma] - vbroadcasti128 ymm3,YMMWORD[rcx] - vbroadcasti128 ymm15,YMMWORD[16+rcx] - vbroadcasti128 ymm7,YMMWORD[r8] + vbroadcasti128 ymm11,XMMWORD[$L$sigma] + vbroadcasti128 ymm3,XMMWORD[rcx] + vbroadcasti128 ymm15,XMMWORD[16+rcx] + vbroadcasti128 ymm7,XMMWORD[r8] lea rcx,[256+rsp] lea rax,[512+rsp] lea r10,[$L$rot16] @@ -1161,7 +1161,7 @@ $L$oop_enter8x: vmovdqa YMMWORD[64+rsp],ymm14 vmovdqa YMMWORD[96+rsp],ymm15 - vbroadcasti128 ymm15,YMMWORD[r10] + vbroadcasti128 ymm15,XMMWORD[r10] vmovdqa YMMWORD[(512-512)+rax],ymm4 mov eax,10 jmp NEAR $L$oop8x @@ -1179,7 +1179,7 @@ vpslld ymm14,ymm0,12 vpsrld ymm0,ymm0,20 vpor ymm0,ymm14,ymm0 - vbroadcasti128 ymm14,YMMWORD[r11] + vbroadcasti128 ymm14,XMMWORD[r11] vpaddd ymm13,ymm13,ymm5 vpxor ymm1,ymm13,ymm1 vpslld ymm15,ymm1,12 @@ -1196,7 +1196,7 @@ vpslld ymm15,ymm0,7 vpsrld ymm0,ymm0,25 vpor ymm0,ymm15,ymm0 - vbroadcasti128 ymm15,YMMWORD[r10] + vbroadcasti128 ymm15,XMMWORD[r10] vpaddd ymm13,ymm13,ymm5 vpxor ymm1,ymm13,ymm1 vpslld ymm14,ymm1,7 @@ -1217,7 +1217,7 @@ vpslld ymm14,ymm2,12 vpsrld ymm2,ymm2,20 vpor ymm2,ymm14,ymm2 - vbroadcasti128 ymm14,YMMWORD[r11] + vbroadcasti128 ymm14,XMMWORD[r11] vpaddd ymm13,ymm13,ymm7 vpxor ymm3,ymm13,ymm3 vpslld ymm15,ymm3,12 @@ -1234,7 +1234,7 @@ vpslld ymm15,ymm2,7 vpsrld ymm2,ymm2,25 vpor ymm2,ymm15,ymm2 - vbroadcasti128 ymm15,YMMWORD[r10] + vbroadcasti128 ymm15,XMMWORD[r10] vpaddd ymm13,ymm13,ymm7 vpxor ymm3,ymm13,ymm3 vpslld ymm14,ymm3,7 @@ -1251,7 +1251,7 @@ vpslld ymm14,ymm1,12 vpsrld ymm1,ymm1,20 vpor ymm1,ymm14,ymm1 - vbroadcasti128 ymm14,YMMWORD[r11] + vbroadcasti128 ymm14,XMMWORD[r11] vpaddd ymm13,ymm13,ymm4 vpxor ymm2,ymm13,ymm2 vpslld ymm15,ymm2,12 @@ -1268,7 +1268,7 @@ vpslld ymm15,ymm1,7 vpsrld ymm1,ymm1,25 vpor ymm1,ymm15,ymm1 - vbroadcasti128 ymm15,YMMWORD[r10] + vbroadcasti128 ymm15,XMMWORD[r10] vpaddd ymm13,ymm13,ymm4 vpxor ymm2,ymm13,ymm2 vpslld ymm14,ymm2,7 @@ -1289,7 +1289,7 @@ vpslld ymm14,ymm3,12 vpsrld ymm3,ymm3,20 vpor ymm3,ymm14,ymm3 - vbroadcasti128 ymm14,YMMWORD[r11] + vbroadcasti128 ymm14,XMMWORD[r11] vpaddd ymm13,ymm13,ymm6 vpxor ymm0,ymm13,ymm0 vpslld ymm15,ymm0,12 @@ -1306,7 +1306,7 @@ vpslld ymm15,ymm3,7 vpsrld ymm3,ymm3,25 vpor ymm3,ymm15,ymm3 - vbroadcasti128 ymm15,YMMWORD[r10] + vbroadcasti128 ymm15,XMMWORD[r10] vpaddd ymm13,ymm13,ymm6 vpxor ymm0,ymm13,ymm0 vpslld ymm14,ymm0,7
diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn index 0d6fcbc..4b88d7c 100644 --- a/third_party/harfbuzz-ng/BUILD.gn +++ b/third_party/harfbuzz-ng/BUILD.gn
@@ -181,6 +181,11 @@ "src/hb-coretext.h", ] defines += [ "HAVE_CORETEXT" ] + libs = [ + "CoreFoundation.framework", + "CoreGraphics.framework", + "CoreText.framework", + ] } # When without -fvisibility=hidden for pango to use the harfbuzz
diff --git a/tools/android/loading/sandwich.py b/tools/android/loading/sandwich.py index 7cb0834..40419431 100755 --- a/tools/android/loading/sandwich.py +++ b/tools/android/loading/sandwich.py
@@ -218,6 +218,7 @@ setup_path = os.path.join(args.output, _SANDWICH_SETUP_FILENAME) with open(setup_path) as file_input: setup = yaml.load(file_input) + android_device = None if setup['sandwich_runner']['android_device_serial']: android_device = device_setup.GetDeviceFromSerial( setup['sandwich_runner']['android_device_serial'])
diff --git a/tools/android/loading/task_manager.py b/tools/android/loading/task_manager.py index 0ae1f7a5..f132eb1 100644 --- a/tools/android/loading/task_manager.py +++ b/tools/android/loading/task_manager.py
@@ -64,6 +64,7 @@ import common_util +_TASK_LOGS_DIR_NAME = 'logs' _TASK_GRAPH_DOTFILE_NAME = 'tasks_graph.dot' _TASK_GRAPH_PNG_NAME = 'tasks_graph.png' _TASK_RESUME_ARGUMENTS_FILE = 'resume.txt' @@ -467,9 +468,11 @@ log_filename = datetime.datetime.now().strftime( _TASK_EXECUTION_LOG_NAME_FORMAT) + log_path = os.path.join(args.output, _TASK_LOGS_DIR_NAME, log_filename) + if not os.path.isdir(os.path.dirname(log_path)): + os.makedirs(os.path.dirname(log_path)) formatter = logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s') - handler = logging.FileHandler( - os.path.join(args.output, log_filename), mode='a') + handler = logging.FileHandler(log_path, mode='a') handler.setFormatter(formatter) logging.getLogger().addHandler(handler) logging.info(
diff --git a/tools/clang/blink_gc_plugin/tests/base_class_must_define_virtual_trace.h b/tools/clang/blink_gc_plugin/tests/base_class_must_define_virtual_trace.h index 16558bb8..fbd26d73 100644 --- a/tools/clang/blink_gc_plugin/tests/base_class_must_define_virtual_trace.h +++ b/tools/clang/blink_gc_plugin/tests/base_class_must_define_virtual_trace.h
@@ -10,12 +10,12 @@ namespace blink { class PartBase { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); // Missing virtual trace. }; class PartDerived : public PartBase { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); public: virtual void trace(Visitor*); };
diff --git a/tools/clang/blink_gc_plugin/tests/class_requires_trace_method.h b/tools/clang/blink_gc_plugin/tests/class_requires_trace_method.h index 782d80e1..4a442b72 100644 --- a/tools/clang/blink_gc_plugin/tests/class_requires_trace_method.h +++ b/tools/clang/blink_gc_plugin/tests/class_requires_trace_method.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: Member<HeapObject> m_obj; };
diff --git a/tools/clang/blink_gc_plugin/tests/class_requires_trace_method_tmpl.h b/tools/clang/blink_gc_plugin/tests/class_requires_trace_method_tmpl.h index b24b1dd..70cab61 100644 --- a/tools/clang/blink_gc_plugin/tests/class_requires_trace_method_tmpl.h +++ b/tools/clang/blink_gc_plugin/tests/class_requires_trace_method_tmpl.h
@@ -12,11 +12,11 @@ class HeapObject : public GarbageCollected<HeapObject> { }; class PartObjectA { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); }; class PartObjectB { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); public: void trace(Visitor* visitor) { visitor->trace(m_obj); } private:
diff --git a/tools/clang/blink_gc_plugin/tests/fields_illegal_tracing.h b/tools/clang/blink_gc_plugin/tests/fields_illegal_tracing.h index 4d9e692a..7700b82 100644 --- a/tools/clang/blink_gc_plugin/tests/fields_illegal_tracing.h +++ b/tools/clang/blink_gc_plugin/tests/fields_illegal_tracing.h
@@ -30,7 +30,7 @@ class PartObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); public: void trace(Visitor*); private:
diff --git a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h index 60caa68..1819411 100644 --- a/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h +++ b/tools/clang/blink_gc_plugin/tests/fields_require_tracing.h
@@ -13,7 +13,7 @@ class PartObject; class PartBObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); public: void trace(Visitor*); private: @@ -22,7 +22,7 @@ }; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); public: void trace(Visitor*); private:
diff --git a/tools/clang/blink_gc_plugin/tests/heap/stubs.h b/tools/clang/blink_gc_plugin/tests/heap/stubs.h index fff4a78..813ab127 100644 --- a/tools/clang/blink_gc_plugin/tests/heap/stubs.h +++ b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
@@ -139,7 +139,7 @@ using namespace WTF; -#define DISALLOW_ALLOCATION() \ +#define DISALLOW_NEW() \ private: \ void* operator new(size_t) = delete; \ void* operator new(size_t, void*) = delete;
diff --git a/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h index 5a59c7e..2a7c868 100644 --- a/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h +++ b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h
@@ -28,7 +28,7 @@ }; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); public: void trace(Visitor*); private:
diff --git a/tools/clang/blink_gc_plugin/tests/own_ptr_to_gc_managed_class.h b/tools/clang/blink_gc_plugin/tests/own_ptr_to_gc_managed_class.h index b412561..6f47bafe 100644 --- a/tools/clang/blink_gc_plugin/tests/own_ptr_to_gc_managed_class.h +++ b/tools/clang/blink_gc_plugin/tests/own_ptr_to_gc_managed_class.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: OwnPtr<HeapObject> m_obj; };
diff --git a/tools/clang/blink_gc_plugin/tests/persistent_field_in_gc_managed_class.h b/tools/clang/blink_gc_plugin/tests/persistent_field_in_gc_managed_class.h index 0ae2b27..a90f63c 100644 --- a/tools/clang/blink_gc_plugin/tests/persistent_field_in_gc_managed_class.h +++ b/tools/clang/blink_gc_plugin/tests/persistent_field_in_gc_managed_class.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: Persistent<HeapObject> m_obj; };
diff --git a/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class.h b/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class.h index 987001d..18fa9fa4 100644 --- a/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class.h +++ b/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: PartObject();
diff --git a/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class_error.h b/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class_error.h index 2fa73a2..f4921c4 100644 --- a/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class_error.h +++ b/tools/clang/blink_gc_plugin/tests/raw_ptr_to_gc_managed_class_error.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: PartObject();
diff --git a/tools/clang/blink_gc_plugin/tests/ref_ptr_to_gc_managed_class.h b/tools/clang/blink_gc_plugin/tests/ref_ptr_to_gc_managed_class.h index 0dba311..c3df7f8 100644 --- a/tools/clang/blink_gc_plugin/tests/ref_ptr_to_gc_managed_class.h +++ b/tools/clang/blink_gc_plugin/tests/ref_ptr_to_gc_managed_class.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: RefPtr<HeapObject> m_obj; };
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated.h b/tools/clang/blink_gc_plugin/tests/stack_allocated.h index ed773266..88c01ab1 100644 --- a/tools/clang/blink_gc_plugin/tests/stack_allocated.h +++ b/tools/clang/blink_gc_plugin/tests/stack_allocated.h
@@ -12,7 +12,7 @@ class HeapObject; class PartObject { - DISALLOW_ALLOCATION(); + DISALLOW_NEW(); private: Member<HeapObject> m_obj; // Needs tracing. };
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc index 5796ada2..eceb4f03 100644 --- a/tools/gn/setup.cc +++ b/tools/gn/setup.cc
@@ -514,7 +514,7 @@ if (dotfile_name_.empty()) { Err(Location(), "Could not load dotfile.", "The file \"" + FilePathToUTF8(dot_file_path) + - "\" cound't be loaded.").PrintToStdout(); + "\" couldn't be loaded.").PrintToStdout(); return false; } } @@ -624,7 +624,7 @@ dotfile_input_file_.reset(new InputFile(SourceFile("//.gn"))); if (!dotfile_input_file_->Load(dotfile_name_)) { Err(Location(), "Could not load dotfile.", - "The file \"" + FilePathToUTF8(dotfile_name_) + "\" cound't be loaded") + "The file \"" + FilePathToUTF8(dotfile_name_) + "\" couldn't be loaded") .PrintToStdout(); return false; }
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index fab8491..34d789c3 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -616,6 +616,19 @@ </summary> </histogram> +<histogram name="AppBanners.BeforeInstallEvent" + enum="AppBannersBeforeInstallEvent"> + <owner>dominickn@chromium.org</owner> + <summary> + App banners promote an application related to the current website, and are + requested specifically through the current page's HTML. This stat tracks + usage of the BeforeInstallPromptEvent, which allows developers to control + when an app banner appears. The events in this histogram are not mutually + exclusive - for example, preventDefault() must be called if prompt() is + called. + </summary> +</histogram> + <histogram name="AppBanners.DismissEvent" enum="AppBannersDismissEvent"> <owner>dfalcantara@chromium.org</owner> <summary> @@ -8984,6 +8997,36 @@ </summary> </histogram> +<histogram name="DirectWrite.Fonts.Proxy.FamilyCount" units="families"> + <owner>kulshin@chromium.org</owner> + <summary> + The number of font families as seen by the font proxy in the renderer. + </summary> +</histogram> + +<histogram name="DirectWrite.Fonts.Proxy.FontProxyError" + enum="DirectWriteFontProxyError"> + <owner>kulshin@chromium.org</owner> + <summary> + The errors encountered by the DirectWrite font proxy while loading fonts. + </summary> +</histogram> + +<histogram name="DirectWrite.Fonts.Proxy.LastResortFontCount" units="fonts"> + <owner>kulshin@chromium.org</owner> + <summary> + The number of last resort fallback fonts found on the system as seen by the + browser. + </summary> +</histogram> + +<histogram name="DirectWrite.Fonts.Proxy.LastResortFontFileCount" units="files"> + <owner>kulshin@chromium.org</owner> + <summary> + The number of font files found for a last resort fallback font. + </summary> +</histogram> + <histogram name="DirectWrite.Fonts.Proxy.LoaderType" enum="DirectWriteFontLoaderType"> <owner>kulshin@chromium.org</owner> @@ -9012,6 +9055,14 @@ </summary> </histogram> +<histogram name="DirectWrite.Fonts.Proxy.MessageFilterError" + enum="DirectWriteMessageFilterError"> + <owner>kulshin@chromium.org</owner> + <summary> + Errors, if any, encountered by the DirectWrite font proxy message filter. + </summary> +</histogram> + <histogram name="DisabledExtension.ExtensionWipedStatus" enum="BooleanWiped"> <obsolete> Deprecated 04/2016 as doesn't have data nor owner. @@ -31367,6 +31418,9 @@ </histogram> <histogram name="Net.SSLServerKeyExchangeHash" enum="SSLHashAlgorithm"> + <obsolete> + Replaced by Net.SSLSignatureAlgorithm. + </obsolete> <owner>davidben@chromium.org</owner> <summary> For each SSL connection with a full handshake using a DHE- or ECDHE-based @@ -31386,6 +31440,15 @@ </summary> </histogram> +<histogram name="Net.SSLSignatureAlgorithm" enum="SSLSignatureAlgorithm"> + <summary> + For each SSL connection with a full handshake using a DHE- or ECDHE-based + key exchange, the signature algorithm used to authenticate the peer. In TLS + 1.2, this is the signature on the ServerKeyExchange message. (Note: Although + the ECDSA values specify a curve, the curve is only enforced in TLS 1.3.) + </summary> +</histogram> + <histogram name="Net.SSLv3FallbackToRenegoPatchedServer" enum="TLSRenegotiationPatched"> <obsolete> @@ -33853,6 +33916,48 @@ </summary> </histogram> +<histogram name="Network.Shill.WiFi.SuspendDurationWoWOffConnected" + units="seconds"> + <owner>semenzato@chromium.org</owner> + <owner>kirtika@chromium.org</owner> + <summary> + Time spent in suspended state, on a resume, for the case when wake on wifi + is disabled (WoWOff), and after resume, the NIC is found to be already + connected. + </summary> +</histogram> + +<histogram name="Network.Shill.WiFi.SuspendDurationWoWOffDisconnected" + units="seconds"> + <owner>semenzato@chromium.org</owner> + <owner>kirtika@chromium.org</owner> + <summary> + Time spent in suspended state, on a resume, for the case when wake on wifi + is enabled (WoWOff), and after resume, the NIC is found to be disconnected. + </summary> +</histogram> + +<histogram name="Network.Shill.WiFi.SuspendDurationWoWOnConnected" + units="seconds"> + <owner>semenzato@chromium.org</owner> + <owner>kirtika@chromium.org</owner> + <summary> + Time spent in suspended state, on a resume, for the case when wake on wifi + is enabled (WoWOn), and after resume, the NIC is found to be already + connected. + </summary> +</histogram> + +<histogram name="Network.Shill.WiFi.SuspendDurationWoWOnDisconnected" + units="seconds"> + <owner>semenzato@chromium.org</owner> + <owner>kirtika@chromium.org</owner> + <summary> + Time spent in suspended state, on a resume, for the case when wake on wifi + is enabled (WoWOn), and after resume, the NIC is found to be disconnected. + </summary> +</histogram> + <histogram name="Network.Shill.Wifi.TimeOnline" units="seconds"> <owner>quiche@chromium.org</owner> <summary> @@ -45782,6 +45887,15 @@ </summary> </histogram> +<histogram name="RendererScheduler.ExpectedTaskQueueingDuration" units="ms"> + <owner>tdresser@chromium.org</owner> + <summary> + The estimated queueing duration which would be observed for additional high + priority tasks posted to the RendererScheduler. Recorded for each 1000 ms + window. + </summary> +</histogram> + <histogram name="RendererScheduler.TaskQueueManager.DelayedTaskLateness" units="ms"> <owner>alexclarke@chromium.org</owner> @@ -55610,6 +55724,16 @@ </summary> </histogram> +<histogram name="Storage.BlacklistedImportantSites.Reason" + enum="ClearDataSiteBlacklistReason"> + <owner>dmurph@chromium.org</owner> + <summary> + This is recorded for every site that the user blacklists when they when they + clear browsing data. It indicates which signals were used to show the given + site to the user that the user then chose to exclude from clearing. + </summary> +</histogram> + <histogram name="Storage.Blob.Broken" enum="BooleanBroken"> <owner>dmurph@chromium.org</owner> <summary> @@ -65543,6 +65667,15 @@ <int value="15" label="RESULT_WSC_NOT_AVAILABLE"/> </enum> +<enum name="AppBannersBeforeInstallEvent" type="int"> + <int value="1" label="Event created and dispatched"/> + <int value="2" label="Showing the banner"/> + <int value="3" label="preventDefault() not called"/> + <int value="4" label="preventDefault() called"/> + <int value="5" label="prompt() called after preventDefault()"/> + <int value="6" label="prompt() not called after preventDefault()"/> +</enum> + <enum name="AppBannersDismissEvent" type="int"> <int value="41" label="Error/unknown reason for dismissal"/> <int value="42" label="User opened the application after installing it"/> @@ -68526,6 +68659,17 @@ <int value="613" label="X_Takri"/> </enum> +<enum name="ClearDataSiteBlacklistReason" type="int"> + <int value="0" label="Durable"/> + <int value="1" label="Notifications"/> + <int value="2" label="Engagement"/> + <int value="3" label="Notifications and Engagement"/> + <int value="4" label="Durable and Engagement"/> + <int value="5" label="Notifications and Durable"/> + <int value="6" label="Notifications, Durable, and Engagement"/> + <int value="7" label="Unknown"/> +</enum> + <enum name="ClientAppId" type="int"> <int value="0" label="Other"/> <int value="1" label="Gmail"/> @@ -70606,12 +70750,29 @@ <int value="2" label="Non-file loader"/> </enum> +<enum name="DirectWriteFontProxyError" type="int"> + <int value="0" label="FindFamily: send failed"/> + <int value="1" label="GetFamilyCount: send failed"/> + <int value="2" label="CreateEnumeratorFromKey: invalid key"/> + <int value="3" label="CreateEnumeratorFromKey: family index out of range"/> + <int value="4" label="GetFontFiles: send failed"/> + <int value="5" label="FontfileStream: failed to created mapped file"/> +</enum> + <enum name="DirectWriteLoadFamilyResult" type="int"> <int value="0" label="Success: single family"/> <int value="1" label="Success: matched from collection"/> <int value="2" label="Error: multiple families"/> <int value="3" label="Error: no families"/> - <int value="4" label="Error: failed to create colleciton"/> + <int value="4" label="Error: failed to create collection"/> +</enum> + +<enum name="DirectWriteMessageFilterError" type="int"> + <int value="0" label="OnGetFontFiles: GetFont failed"/> + <int value="1" label="OnGetFontFiles: AddFilesForFont failed"/> + <int value="2" label="OnGetFontFiles: GetFontFamily failed"/> + <int value="3" label="InitializeDirectWrite: GetSystemFontCollection failed"/> + <int value="4" label="MapCharacters: could not find family"/> </enum> <enum name="DistillableType" type="int"> @@ -91111,6 +91272,9 @@ </enum> <enum name="SSLHashAlgorithm" type="int"> + <obsolete> + Removed June 2016. + </obsolete> <int value="0" label="None (unused)"/> <int value="1" label="MD5"/> <int value="2" label="SHA-1"/> @@ -91216,6 +91380,17 @@ label="Displayed clock interstitial. (DISPLAYED_CLOCK_INTERSTITIAL)"/> </enum> +<enum name="SSLSignatureAlgorithm" type="int"> + <int value="513" label="rsa_pkcs1_sha1"/> + <int value="515" label="ecdsa_sha1"/> + <int value="1025" label="rsa_pkcs1_sha256"/> + <int value="1027" label="ecdsa_secp256r1_sha256"/> + <int value="1281" label="rsa_pkcs1_sha384"/> + <int value="1283" label="ecdsa_secp384r1_sha384"/> + <int value="1537" label="rsa_pkcs1_sha512"/> + <int value="1539" label="ecdsa_secp521r1_sha512"/> +</enum> + <enum name="StarsLaunchLocation" type="int"> <int value="0" label="All Items"/> <int value="1" label="Uncategorized"/> @@ -98264,9 +98439,6 @@ <histogram_suffixes name="PageLoadMetricsClients.Reload" separator="." ordering="prefix"> - <obsolete> - Deprecated in favor of LoadType.Reload. - </obsolete> <suffix name="Clients.Reload" label="PageLoadMetrics from a page that is reloaded"/> <affected-histogram
diff --git a/tools/perf/benchmarks/battor.py b/tools/perf/benchmarks/battor.py index d5fb768..a69b125c 100644 --- a/tools/perf/benchmarks/battor.py +++ b/tools/perf/benchmarks/battor.py
@@ -17,7 +17,7 @@ options.config.enable_battor_trace = True options.config.enable_chrome_trace = True options.config.chrome_trace_config.SetDefaultOverheadFilter() - options.SetTimelineBasedMetric('powerMetric') + options.SetTimelineBasedMetrics(['powerMetric']) return options @classmethod @@ -105,7 +105,7 @@ options.config.enable_battor_trace = True options.config.enable_chrome_trace = False options.config.chrome_trace_config.SetDefaultOverheadFilter() - options.SetTimelineBasedMetric('powerMetric') + options.SetTimelineBasedMetrics(['powerMetric']) return options @classmethod
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py index 25ddfbe..249ef6b 100644 --- a/tools/perf/benchmarks/benchmark_smoke_unittest.py +++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -19,10 +19,10 @@ from telemetry.testing import options_for_unittests from telemetry.testing import progress_reporter - from benchmarks import image_decoding from benchmarks import indexeddb_perf from benchmarks import jetstream +from benchmarks import kraken from benchmarks import memory from benchmarks import octane from benchmarks import rasterize_and_record_micro @@ -90,7 +90,8 @@ speedometer, # Takes 101 seconds. jetstream, # Take 206 seconds. text_selection, # Always fails on cq bot. - memory # Flaky on bots, crbug.com/513767. + memory, # Flaky on bots, crbug.com/513767. + kraken, # Flaky on Android, crbug.com/626174. }
diff --git a/tools/perf/benchmarks/memory_infra.py b/tools/perf/benchmarks/memory_infra.py index c72a7083..f371f44 100644 --- a/tools/perf/benchmarks/memory_infra.py +++ b/tools/perf/benchmarks/memory_infra.py
@@ -41,7 +41,7 @@ tbm_options = timeline_based_measurement.Options( overhead_level=trace_memory) tbm_options.config.enable_android_graphics_memtrack = True - tbm_options.SetTimelineBasedMetric('memoryMetric') + tbm_options.SetTimelineBasedMetrics(['memoryMetric']) return tbm_options @@ -181,7 +181,7 @@ category_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter( ','.join(['-*'] + v8_categories + memory_categories)) options = timeline_based_measurement.Options(category_filter) - options.SetTimelineBasedMetric('v8AndMemoryMetrics') + options.SetTimelineBasedMetrics(['v8AndMemoryMetrics']) return options @classmethod
diff --git a/tools/perf/benchmarks/page_cycler_v2.py b/tools/perf/benchmarks/page_cycler_v2.py index ca998855..2e51532 100644 --- a/tools/perf/benchmarks/page_cycler_v2.py +++ b/tools/perf/benchmarks/page_cycler_v2.py
@@ -17,7 +17,11 @@ from telemetry.web_perf import timeline_based_measurement +# crbug.com/619254 +@benchmark.Disabled('reference') class _PageCyclerV2(perf_benchmark.PerfBenchmark): + options = {'pageset_repeat': 2} + def CreateTimelineBasedMeasurementOptions(self): cat_filter = chrome_trace_category_filter.ChromeTraceCategoryFilter( filter_string='blink.console,navigation,blink.user_timing,loading') @@ -28,23 +32,9 @@ tbm_options = timeline_based_measurement.Options( overhead_level=cat_filter) - tbm_options.SetTimelineBasedMetric('firstPaintMetric') + tbm_options.SetTimelineBasedMetrics(['firstPaintMetric']) return tbm_options -# crbug.com/619254 -@benchmark.Disabled('reference') -class PageCyclerV2Typical25(_PageCyclerV2): - """Page load time benchmark for a 25 typical web pages. - - Designed to represent typical, not highly optimized or highly popular web - sites. Runs against pages recorded in June, 2014. - """ - options = {'pageset_repeat': 2} - - @classmethod - def Name(cls): - return 'page_cycler_v2.typical_25' - @classmethod def ShouldDisable(cls, possible_browser): # crbug.com/616781 @@ -54,7 +44,50 @@ return True return False + +class PageCyclerV2Typical25(_PageCyclerV2): + """Page load time benchmark for a 25 typical web pages. + + Designed to represent typical, not highly optimized or highly popular web + sites. Runs against pages recorded in June, 2014. + """ + + @classmethod + def Name(cls): + return 'page_cycler_v2.typical_25' + def CreateStorySet(self, options): return page_sets.Typical25PageSet(run_no_page_interactions=True, cache_temperatures=[ cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM]) + + +class PageCyclerV2IntlArFaHe(_PageCyclerV2): + """Page load time for a variety of pages in Arabic, Farsi and Hebrew. + + Runs against pages recorded in April, 2013. + """ + page_set = page_sets.IntlArFaHePageSet + + @classmethod + def Name(cls): + return 'page_cycler_v2.intl_ar_fa_he' + + def CreateStorySet(self, options): + return page_sets.IntlArFaHePageSet(cache_temperatures=[ + cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM]) + + +class PageCyclerV2IntlJaZh(_PageCyclerV2): + """Page load time benchmark for a variety of pages in Japanese and Chinese. + + Runs against pages recorded in April, 2013. + """ + + @classmethod + def Name(cls): + return 'page_cycler_v2.intl_ja_zh' + + def CreateStorySet(self, options): + return page_sets.IntlJaZhPageSet(cache_temperatures=[ + cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
diff --git a/tools/perf/benchmarks/system_health.py b/tools/perf/benchmarks/system_health.py index 25d43106..c53960f 100644 --- a/tools/perf/benchmarks/system_health.py +++ b/tools/perf/benchmarks/system_health.py
@@ -28,7 +28,7 @@ options.config.chrome_trace_config.SetCategoryFilter( chrome_trace_category_filter.ChromeTraceCategoryFilter(','.join( self.TRACING_CATEGORIES))) - options.SetTimelineBasedMetric('systemHealthMetrics') + options.SetTimelineBasedMetrics(['systemHealthMetrics']) return options @classmethod @@ -64,9 +64,6 @@ """ def SetExtraBrowserOptions(self, options): - # TODO(petrcermak): Remove this and switch to log-on-retry - # (http://crbug.com/623058). - options.logging_verbosity = options.NON_VERBOSE_LOGGING options.AppendExtraBrowserArgs([ # TODO(perezju): Temporary workaround to disable periodic memory dumps. # See: http://crbug.com/513692 @@ -78,7 +75,7 @@ chrome_trace_category_filter.ChromeTraceCategoryFilter( '-*,disabled-by-default-memory-infra')) options.config.enable_android_graphics_memtrack = True - options.SetTimelineBasedMetric('memoryMetric') + options.SetTimelineBasedMetrics(['memoryMetric']) return options @classmethod @@ -114,7 +111,6 @@ possible_browser.browser_type == 'reference' and possible_browser.platform.GetDeviceTypeName() == 'Nexus 5X') - @benchmark.Enabled('android-webview') class WebviewStartupSystemHealthBenchmark(perf_benchmark.PerfBenchmark): """Webview startup time benchmark @@ -128,7 +124,7 @@ def CreateTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options() - options.SetTimelineBasedMetric('webviewStartupMetric') + options.SetTimelineBasedMetrics(['webviewStartupMetric']) options.config.enable_atrace_trace = True options.config.enable_chrome_trace = False options.config.atrace_config.app_name = 'org.chromium.webview_shell'
diff --git a/tools/perf/benchmarks/tracing.py b/tools/perf/benchmarks/tracing.py index e09c324..71adb584 100644 --- a/tools/perf/benchmarks/tracing.py +++ b/tools/perf/benchmarks/tracing.py
@@ -19,7 +19,7 @@ def CreateTimelineBasedMeasurementOptions(self): options = timeline_based_measurement.Options( timeline_based_measurement.DEBUG_OVERHEAD_LEVEL) - options.SetTimelineBasedMetric('tracingMetric') + options.SetTimelineBasedMetrics(['tracingMetric']) return options @classmethod @@ -43,7 +43,7 @@ memory_dump_config = chrome_trace_config.MemoryDumpConfig() memory_dump_config.AddTrigger('background', 200) options.config.chrome_trace_config.SetMemoryDumpConfig(memory_dump_config) - options.SetTimelineBasedMetric('tracingMetric') + options.SetTimelineBasedMetrics(['tracingMetric']) return options @classmethod
diff --git a/tools/perf/benchmarks/v8.py b/tools/perf/benchmarks/v8.py index 9ff18a3..6d7eb7ac 100644 --- a/tools/perf/benchmarks/v8.py +++ b/tools/perf/benchmarks/v8.py
@@ -26,7 +26,7 @@ category_filter.AddIncludedCategory('blink.console') category_filter.AddDisabledByDefault('disabled-by-default-v8.compile') options = timeline_based_measurement.Options(category_filter) - options.SetTimelineBasedMetric('executionMetric') + options.SetTimelineBasedMetrics(['executionMetric']) return options @@ -105,7 +105,7 @@ options = timeline_based_measurement.Options(category_filter) # TODO(ulan): Add frame time discrepancy once it is ported to TBMv2, # see crbug.com/606841. - options.SetTimelineBasedMetric('v8AndMemoryMetrics') + options.SetTimelineBasedMetrics(['v8AndMemoryMetrics']) return options @classmethod @@ -214,7 +214,7 @@ memory_dump_config = chrome_trace_config.MemoryDumpConfig() memory_dump_config.AddTrigger('light', 20) options.config.chrome_trace_config.SetMemoryDumpConfig(memory_dump_config) - options.SetTimelineBasedMetric('memoryMetric') + options.SetTimelineBasedMetrics(['memoryMetric']) return options page_set = page_sets.Top10MobileMemoryPageSet
diff --git a/tools/perf/page_sets/intl_ar_fa_he.py b/tools/perf/page_sets/intl_ar_fa_he.py index 9299745e..cc8f597 100644 --- a/tools/perf/page_sets/intl_ar_fa_he.py +++ b/tools/perf/page_sets/intl_ar_fa_he.py
@@ -1,6 +1,7 @@ # Copyright 2014 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. +from telemetry.page import cache_temperature as cache_temperature_module from telemetry.page import page as page_module from telemetry.page import shared_page_state from telemetry import story @@ -8,10 +9,11 @@ class IntlArFaHePage(page_module.Page): - def __init__(self, url, page_set): + def __init__(self, url, page_set, cache_temperature=None): super(IntlArFaHePage, self).__init__( url=url, page_set=page_set, - shared_page_state_class=shared_page_state.SharedDesktopPageState) + shared_page_state_class=shared_page_state.SharedDesktopPageState, + cache_temperature=cache_temperature) self.archive_data_file = 'data/intl_ar_fa_he.json' @@ -19,10 +21,12 @@ """ Popular pages in right-to-left languages Arabic, Farsi and Hebrew. """ - def __init__(self): + def __init__(self, cache_temperatures=None): super(IntlArFaHePageSet, self).__init__( archive_data_file='data/intl_ar_fa_he.json', cloud_storage_bucket=story.PARTNER_BUCKET) + if cache_temperatures is None: + cache_temperatures = [cache_temperature_module.ANY] urls_list = [ 'http://msn.co.il/', @@ -36,4 +40,5 @@ ] for url in urls_list: - self.AddStory(IntlArFaHePage(url, self)) + for temp in cache_temperatures: + self.AddStory(IntlArFaHePage(url, self, cache_temperature=temp))
diff --git a/tools/perf/page_sets/intl_ja_zh.py b/tools/perf/page_sets/intl_ja_zh.py index 984f8b8..10c7ccc3 100644 --- a/tools/perf/page_sets/intl_ja_zh.py +++ b/tools/perf/page_sets/intl_ja_zh.py
@@ -1,6 +1,7 @@ # Copyright 2014 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. +from telemetry.page import cache_temperature as cache_temperature_module from telemetry.page import page as page_module from telemetry.page import shared_page_state from telemetry import story @@ -8,20 +9,23 @@ class IntlJaZhPage(page_module.Page): - def __init__(self, url, page_set): + def __init__(self, url, page_set, cache_temperature=None): super(IntlJaZhPage, self).__init__( url=url, page_set=page_set, - shared_page_state_class=shared_page_state.SharedDesktopPageState) + shared_page_state_class=shared_page_state.SharedDesktopPageState, + cache_temperature=cache_temperature) class IntlJaZhPageSet(story.StorySet): """ Popular pages in Japanese and Chinese. """ - def __init__(self): + def __init__(self, cache_temperatures=None): super(IntlJaZhPageSet, self).__init__( archive_data_file='data/intl_ja_zh.json', cloud_storage_bucket=story.PARTNER_BUCKET) + if cache_temperatures is None: + cache_temperatures = [cache_temperature_module.ANY] urls_list = [ # Why: #5 Japanese site @@ -55,4 +59,5 @@ ] for url in urls_list: - self.AddStory(IntlJaZhPage(url, self)) + for temp in cache_temperatures: + self.AddStory(IntlJaZhPage(url, self, cache_temperature=temp))
diff --git a/tools/roll_webrtc.py b/tools/roll_webrtc.py index 4291c38..fde94f7 100755 --- a/tools/roll_webrtc.py +++ b/tools/roll_webrtc.py
@@ -166,7 +166,7 @@ description = [ '-m', 'Roll ' + webrtc_str ] description.extend(['-m', 'Changes: %s' % webrtc_changelog_url]) description.extend(['-m', 'TBR=']) - description.extend(['-m', 'CQ_EXTRA_TRYBOTS=%s' % EXTRA_TRYBOTS]) + description.extend(['-m', 'CQ_INCLUDE_TRYBOTS=%s' % EXTRA_TRYBOTS]) return description
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn index 2fc2728..d4433b5 100644 --- a/ui/app_list/BUILD.gn +++ b/ui/app_list/BUILD.gn
@@ -178,39 +178,6 @@ "//ui/views", ] } - - if (is_mac) { - sources += [ - "cocoa/app_list_pager_view.h", - "cocoa/app_list_pager_view.mm", - "cocoa/app_list_view_controller.h", - "cocoa/app_list_view_controller.mm", - "cocoa/app_list_window_controller.h", - "cocoa/app_list_window_controller.mm", - "cocoa/apps_collection_view_drag_manager.h", - "cocoa/apps_collection_view_drag_manager.mm", - "cocoa/apps_grid_controller.h", - "cocoa/apps_grid_controller.mm", - "cocoa/apps_grid_view_item.h", - "cocoa/apps_grid_view_item.mm", - "cocoa/apps_pagination_model_observer.h", - "cocoa/apps_search_box_controller.h", - "cocoa/apps_search_box_controller.mm", - "cocoa/apps_search_results_controller.h", - "cocoa/apps_search_results_controller.mm", - "cocoa/apps_search_results_model_bridge.h", - "cocoa/apps_search_results_model_bridge.mm", - "cocoa/item_drag_controller.h", - "cocoa/item_drag_controller.mm", - "cocoa/scroll_view_with_no_scrollbars.h", - "cocoa/scroll_view_with_no_scrollbars.mm", - ] - deps += [ "//third_party/google_toolbox_for_mac" ] - libs = [ - "AppKit.framework", - "QuartzCore.framework", - ] - } } static_library("test_support") { @@ -325,16 +292,4 @@ "//ui/views:test_support", ] } - - if (is_mac) { - sources += [ - "cocoa/app_list_view_controller_unittest.mm", - "cocoa/app_list_window_controller_unittest.mm", - "cocoa/apps_grid_controller_unittest.mm", - "cocoa/apps_search_box_controller_unittest.mm", - "cocoa/apps_search_results_controller_unittest.mm", - "cocoa/test/apps_grid_controller_test_helper.h", - "cocoa/test/apps_grid_controller_test_helper.mm", - ] - } }
diff --git a/ui/app_list/PRESUBMIT.py b/ui/app_list/PRESUBMIT.py index 73df615..e788678 100644 --- a/ui/app_list/PRESUBMIT.py +++ b/ui/app_list/PRESUBMIT.py
@@ -12,14 +12,9 @@ r'.*\.(cc|h)$', ) -EXCLUDE = ( - # Objective C confuses everything. - r'.*/cocoa/.*', -) - def CheckChangeLintsClean(input_api, output_api): """Makes sure that the ui/app_list/ code is cpplint clean.""" - black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDE + black_list = input_api.DEFAULT_BLACK_LIST sources = lambda x: input_api.FilterSourceFile( x, white_list = INCLUDE_CPP_FILES_ONLY, black_list = black_list) return input_api.canned_checks.CheckChangeLintsClean(
diff --git a/ui/app_list/app_list.gyp b/ui/app_list/app_list.gyp index 392303a3..59c0532 100644 --- a/ui/app_list/app_list.gyp +++ b/ui/app_list/app_list.gyp
@@ -55,29 +55,6 @@ 'app_list_switches.h', 'app_list_view_delegate.cc', 'app_list_view_delegate.h', - 'cocoa/app_list_pager_view.h', - 'cocoa/app_list_pager_view.mm', - 'cocoa/app_list_view_controller.h', - 'cocoa/app_list_view_controller.mm', - 'cocoa/app_list_window_controller.h', - 'cocoa/app_list_window_controller.mm', - 'cocoa/apps_collection_view_drag_manager.h', - 'cocoa/apps_collection_view_drag_manager.mm', - 'cocoa/apps_grid_controller.h', - 'cocoa/apps_grid_controller.mm', - 'cocoa/apps_grid_view_item.h', - 'cocoa/apps_grid_view_item.mm', - 'cocoa/apps_pagination_model_observer.h', - 'cocoa/apps_search_box_controller.h', - 'cocoa/apps_search_box_controller.mm', - 'cocoa/apps_search_results_controller.h', - 'cocoa/apps_search_results_controller.mm', - 'cocoa/apps_search_results_model_bridge.h', - 'cocoa/apps_search_results_model_bridge.mm', - 'cocoa/item_drag_controller.h', - 'cocoa/item_drag_controller.mm', - 'cocoa/scroll_view_with_no_scrollbars.h', - 'cocoa/scroll_view_with_no_scrollbars.mm', 'folder_image.cc', 'folder_image.h', 'pagination_controller.cc', @@ -206,20 +183,6 @@ ['exclude', 'views/'], ], }], - ['OS=="mac"', { - 'dependencies': [ - '../../third_party/google_toolbox_for_mac/google_toolbox_for_mac.gyp:google_toolbox_for_mac', - ], - 'link_settings': { - 'libraries': [ - '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', - ], - }, - }, { # OS!="mac" - 'sources/': [ - ['exclude', 'cocoa/'], - ], - }], ], # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. 'msvs_disabled_warnings': [ 4267, ], @@ -265,13 +228,6 @@ # Note: sources list duplicated in GN build. 'app_list_item_list_unittest.cc', 'app_list_model_unittest.cc', - 'cocoa/app_list_view_controller_unittest.mm', - 'cocoa/app_list_window_controller_unittest.mm', - 'cocoa/apps_grid_controller_unittest.mm', - 'cocoa/apps_search_box_controller_unittest.mm', - 'cocoa/apps_search_results_controller_unittest.mm', - 'cocoa/test/apps_grid_controller_test_helper.h', - 'cocoa/test/apps_grid_controller_test_helper.mm', 'folder_image_unittest.cc', 'pagination_model_unittest.cc', 'search/history_data_store_unittest.cc', @@ -304,22 +260,6 @@ ['exclude', 'views/'], ] }], - ['OS=="mac"', { - 'dependencies': [ - '../events/events.gyp:events_test_support', - '../gfx/gfx.gyp:gfx_test_support', - ], - 'conditions': [ - ['component=="static_library"', { - # Needed to link to Obj-C static libraries. - 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']}, - }], - ], - }, { # OS!="mac" - 'sources/': [ - ['exclude', 'cocoa/'], - ], - }], ], # Disable c4267 warnings until we fix size_t to int truncations. 'msvs_disabled_warnings': [ 4267, ],
diff --git a/ui/app_list/cocoa/app_list_pager_view.h b/ui/app_list/cocoa/app_list_pager_view.h deleted file mode 100644 index 0dcc44d..0000000 --- a/ui/app_list/cocoa/app_list_pager_view.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APP_LIST_PAGER_VIEW_H_ -#define UI_APP_LIST_COCOA_APP_LIST_PAGER_VIEW_H_ - -#import <Cocoa/Cocoa.h> - -#import "ui/base/cocoa/tracking_area.h" - -@class AppListPagerView; - -// Delegate to obtain the visible portion of a page and respond to clicks. -@protocol AppListPagerDelegate<NSObject> - -// Returns the portion of a page that is visible, in the range (-1.0, 1.0]. -// Positive indicates the left side is visible, negative indicates the right. -- (CGFloat)visiblePortionOfPage:(int)page; - -// Invoked when the pager is clicked. -- (void)onPagerClicked:(AppListPagerView*)sender; - -@end - -// AppListPagerView draws a button strip with buttons representing pages, and a -// highlight that mirrors the visible portion of the page. -@interface AppListPagerView : NSSegmentedControl { - @private - // Used to auto-select a segment on hover. - ui::ScopedCrTrackingArea trackingArea_; - - // The segment currently highlighted with a mouse hover, or -1 for none. - NSInteger hoveredSegment_; -} - -// Returns -1 if |locationInWindow| is not over a segment. Otherwise returns the -// segment index and highlights it. -- (NSInteger)findAndHighlightSegmentAtLocation:(NSPoint)locationInWindow; - -@end - -#endif // UI_APP_LIST_COCOA_APP_LIST_PAGER_VIEW_H_
diff --git a/ui/app_list/cocoa/app_list_pager_view.mm b/ui/app_list/cocoa/app_list_pager_view.mm deleted file mode 100644 index 82e33f6..0000000 --- a/ui/app_list/cocoa/app_list_pager_view.mm +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/app_list_pager_view.h" - -#include "base/mac/foundation_util.h" -#include "skia/ext/skia_utils_mac.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" - -namespace { - -const CGFloat kButtonHeight = 6; -const CGFloat kButtonCornerRadius = 2; -const CGFloat kButtonStripPadding = 20; - -} // namespace - -@interface AppListPagerView () - -@property(assign, nonatomic) NSInteger hoveredSegment; - -- (NSInteger)segmentUnderLocation:(NSPoint)locationInWindow; - -@end - -@interface AppListPagerCell : NSSegmentedCell; -@end - -@implementation AppListPagerView - -@synthesize hoveredSegment = hoveredSegment_; - -+ (Class)cellClass { - return [AppListPagerCell class]; -} - -- (id)init { - if ((self = [super initWithFrame:NSZeroRect])) { - trackingArea_.reset( - [[CrTrackingArea alloc] initWithRect:NSZeroRect - options:NSTrackingInVisibleRect | - NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveInKeyWindow - owner:self - userInfo:nil]); - [self addTrackingArea:trackingArea_.get()]; - hoveredSegment_ = -1; - } - return self; -} - -- (NSInteger)findAndHighlightSegmentAtLocation:(NSPoint)locationInWindow { - NSInteger segment = [self segmentUnderLocation:locationInWindow]; - [self setHoveredSegment:segment]; - return segment; -} - -- (void)setHoveredSegment:(NSInteger)segment { - if (segment == hoveredSegment_) - return; - - hoveredSegment_ = segment; - [self setNeedsDisplay:YES]; - return; -} - -- (NSInteger)segmentUnderLocation:(NSPoint)locationInWindow { - if ([self segmentCount] == 0) - return -1; - - NSPoint pointInView = [self convertPoint:locationInWindow - fromView:nil]; - if (![self mouse:pointInView inRect:[self bounds]]) - return -1; - - CGFloat segmentWidth = [self bounds].size.width / [self segmentCount]; - return pointInView.x / segmentWidth; -} - -- (BOOL)isHoveredForSegment:(NSInteger)segment { - return segment == hoveredSegment_; -} - -- (void)mouseExited:(NSEvent*)theEvent { - [self setHoveredSegment:-1]; -} - -- (void)mouseMoved:(NSEvent*)theEvent { - [self findAndHighlightSegmentAtLocation:[theEvent locationInWindow]]; -} - -- (void)mouseDown:(NSEvent*)theEvent { - // Temporarily clear the highlight to give feedback. - [self setHoveredSegment:-1]; -} - -// The stock NSSegmentedControl ignores any clicks outside the non-default -// control height, so process all clicks here. -- (void)mouseUp:(NSEvent*)theEvent { - [self findAndHighlightSegmentAtLocation:[theEvent locationInWindow]]; - if (hoveredSegment_ < 0) - return; - - [self setSelectedSegment:hoveredSegment_]; - [[self target] performSelector:[self action] - withObject:self]; -} - -@end - -@implementation AppListPagerCell - -- (void)drawWithFrame:(NSRect)cellFrame - inView:(NSView*)controlView { - // Draw nothing if there are less than two segments. - if ([self segmentCount] < 2) - return; - - cellFrame.size.width /= [self segmentCount]; - for (NSInteger i = 0; i < [self segmentCount]; ++i) { - [self drawSegment:i - inFrame:cellFrame - withView:controlView]; - cellFrame.origin.x += cellFrame.size.width; - } -} - -- (void)drawSegment:(NSInteger)segment - inFrame:(NSRect)frame - withView:(NSView*)controlView { - gfx::ScopedNSGraphicsContextSaveGState context; - NSRect clipRect = NSMakeRect( - frame.origin.x + kButtonStripPadding / 2, - floor(frame.origin.y + (frame.size.height - kButtonHeight) / 2), - frame.size.width - kButtonStripPadding, - kButtonHeight); - [[NSBezierPath bezierPathWithRoundedRect:clipRect - xRadius:kButtonCornerRadius - yRadius:kButtonCornerRadius] addClip]; - - AppListPagerView* pagerControl = - base::mac::ObjCCastStrict<AppListPagerView>(controlView); - SkColor backgroundColor = [pagerControl hoveredSegment] == segment ? - app_list::kPagerHoverColor : - app_list::kPagerNormalColor; - - [skia::SkColorToSRGBNSColor(backgroundColor) set]; - NSRectFill(frame); - - if (![[self target] conformsToProtocol:@protocol(AppListPagerDelegate)]) - return; - - CGFloat selectedRatio = [[self target] visiblePortionOfPage:segment]; - if (selectedRatio == 0.0) - return; - - [skia::SkColorToSRGBNSColor(app_list::kPagerSelectedColor) set]; - if (selectedRatio < 0) - frame.origin.x += frame.size.width + frame.size.width * selectedRatio; - frame.size.width *= fabs(selectedRatio); - NSRectFill(frame); -} - -@end
diff --git a/ui/app_list/cocoa/app_list_view_controller.h b/ui/app_list/cocoa/app_list_view_controller.h deleted file mode 100644 index 664f6a5..0000000 --- a/ui/app_list/cocoa/app_list_view_controller.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APP_LIST_VIEW_CONTROLLER_H_ -#define UI_APP_LIST_COCOA_APP_LIST_VIEW_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include <memory> - -#include "base/mac/scoped_nsobject.h" -#include "ui/app_list/app_list_export.h" -#import "ui/app_list/cocoa/apps_pagination_model_observer.h" -#import "ui/app_list/cocoa/apps_search_box_controller.h" -#import "ui/app_list/cocoa/apps_search_results_controller.h" - -namespace app_list { -class AppListViewDelegate; -class AppListModel; -class AppListModelObserverBridge; -} - -@class AppListPagerView; -@class AppsGridController; - -// Controller for the top-level view of the app list UI. It creates and hosts an -// AppsGridController (displaying an AppListModel), pager control to navigate -// between pages in the grid, and search entry box with a pop up menu. -APP_LIST_EXPORT -@interface AppListViewController : NSViewController<AppsPaginationModelObserver, - AppsSearchBoxDelegate, - AppsSearchResultsDelegate, - NSTextViewDelegate> { - @private - base::scoped_nsobject<AppsGridController> appsGridController_; - base::scoped_nsobject<AppListPagerView> pagerControl_; - base::scoped_nsobject<AppsSearchBoxController> appsSearchBoxController_; - base::scoped_nsobject<AppsSearchResultsController> - appsSearchResultsController_; - - // If set, a message displayed above the app list grid. - base::scoped_nsobject<NSTextView> messageText_; - base::scoped_nsobject<NSScrollView> messageScrollView_; - - // Subview for drawing the background. - base::scoped_nsobject<NSView> backgroundView_; - - // Subview of |backgroundView_| that slides out when search results are shown. - base::scoped_nsobject<NSView> contentsView_; - - // Progress indicator that is visible while the delegate is NULL. - base::scoped_nsobject<NSProgressIndicator> loadingIndicator_; - - app_list::AppListViewDelegate* delegate_; // Weak. Owned by AppListService. - - std::unique_ptr<app_list::AppListModelObserverBridge> - app_list_model_observer_bridge_; - BOOL showingSearchResults_; -} - -@property(readonly, nonatomic) AppsSearchBoxController* - searchBoxController; - -- (app_list::AppListViewDelegate*)delegate; -- (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate; -- (void)onProfilesChanged; - -@end - -@interface AppListViewController (TestingAPI) - -@property(nonatomic, readonly) BOOL showingSearchResults; - -- (AppsGridController*)appsGridController; -- (NSSegmentedControl*)pagerControl; -- (NSView*)backgroundView; - -@end - -#endif // UI_APP_LIST_COCOA_APP_LIST_VIEW_CONTROLLER_H_
diff --git a/ui/app_list/cocoa/app_list_view_controller.mm b/ui/app_list/cocoa/app_list_view_controller.mm deleted file mode 100644 index a05c6c0..0000000 --- a/ui/app_list/cocoa/app_list_view_controller.mm +++ /dev/null
@@ -1,608 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/app_list_view_controller.h" - -#include <stddef.h> - -#include "base/mac/foundation_util.h" -#include "base/mac/mac_util.h" -#include "base/macros.h" -#include "base/strings/string_util.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "skia/ext/skia_utils_mac.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/app_list_view_delegate.h" -#include "ui/app_list/app_list_view_delegate_observer.h" -#import "ui/app_list/cocoa/app_list_pager_view.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#include "ui/app_list/search_box_model.h" -#import "ui/base/cocoa/flipped_view.h" -#import "ui/gfx/image/image_skia_util_mac.h" -#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" - -namespace { - -// The roundedness of the corners of the bubble. -const CGFloat kBubbleCornerRadius = 3; - -// Height of the pager. -const CGFloat kPagerPreferredHeight = 57; - -// Height of separator line drawn between the searchbox and grid view. -const CGFloat kTopSeparatorSize = 1; - -// Height of the search input. -const CGFloat kSearchInputHeight = 48; - -// Minimum margin on either side of the pager. If the pager grows beyond this, -// the segment size is reduced. -const CGFloat kMinPagerMargin = 40; -// Maximum width of a single segment. -const CGFloat kMaxSegmentWidth = 80; - -// Duration of the animation for sliding in and out search results. -const NSTimeInterval kResultsAnimationDuration = 0.2; - -// Properties of the message rectangle, if it is shown. -const NSRect kMessageRect = {{12, 12}, {370, 91}}; -const CGFloat kMessageCornerRadius = 2; -const CGFloat kSpacingBelowMessageTitle = 6; -const SkColor kMessageBackgroundColor = SkColorSetRGB(0xFF, 0xFD, 0xE7); -const SkColor kMessageStrokeColor = SkColorSetARGB(0x3d, 0x00, 0x00, 0x00); -// The inset should be 16px, but NSTextView has its own inset of 3. -const CGFloat kMessageTextInset = 13; - -} // namespace - -@interface BackgroundView : FlippedView; -@end - -@implementation BackgroundView - -- (void)drawRect:(NSRect)dirtyRect { - gfx::ScopedNSGraphicsContextSaveGState context; - NSRect boundsRect = [self bounds]; - NSRect searchAreaRect = NSMakeRect(0, 0, - NSWidth(boundsRect), kSearchInputHeight); - NSRect separatorRect = NSMakeRect(0, NSMaxY(searchAreaRect), - NSWidth(boundsRect), kTopSeparatorSize); - - [[NSBezierPath bezierPathWithRoundedRect:boundsRect - xRadius:kBubbleCornerRadius - yRadius:kBubbleCornerRadius] addClip]; - - [skia::SkColorToSRGBNSColor(app_list::kContentsBackgroundColor) set]; - NSRectFill(boundsRect); - [skia::SkColorToSRGBNSColor(app_list::kSearchBoxBackground) set]; - NSRectFill(searchAreaRect); - [skia::SkColorToSRGBNSColor(app_list::kTopSeparatorColor) set]; - NSRectFill(separatorRect); -} - -@end - -@interface MessageBackgroundView : FlippedView -@end - -@implementation MessageBackgroundView - -- (void)drawRect:(NSRect)dirtyRect { - NSRect boundsRect = [self bounds]; - gfx::ScopedNSGraphicsContextSaveGState context; - [[NSBezierPath bezierPathWithRoundedRect:boundsRect - xRadius:kMessageCornerRadius - yRadius:kMessageCornerRadius] addClip]; - - [skia::SkColorToSRGBNSColor(kMessageStrokeColor) set]; - NSRectFill(boundsRect); - - [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(boundsRect, 1, 1) - xRadius:kMessageCornerRadius - yRadius:kMessageCornerRadius] addClip]; - [skia::SkColorToSRGBNSColor(kMessageBackgroundColor) set]; - NSRectFill(boundsRect); -} - -@end - -@interface AppListViewController () - -- (void)updateMessage; -- (void)loadAndSetView; -- (void)revealSearchResults:(BOOL)show; - -@end - -namespace app_list { - -class AppListModelObserverBridge : public AppListViewDelegateObserver { - public: - AppListModelObserverBridge(AppListViewController* parent); - ~AppListModelObserverBridge() override; - - private: - // Overridden from app_list::AppListViewDelegateObserver: - void OnProfilesChanged() override; - void OnShutdown() override; - - AppListViewController* parent_; // Weak. Owns us. - - DISALLOW_COPY_AND_ASSIGN(AppListModelObserverBridge); -}; - -AppListModelObserverBridge::AppListModelObserverBridge( - AppListViewController* parent) - : parent_(parent) { - [parent_ delegate]->AddObserver(this); -} - -AppListModelObserverBridge::~AppListModelObserverBridge() { - [parent_ delegate]->RemoveObserver(this); -} - -void AppListModelObserverBridge::OnProfilesChanged() { - [parent_ onProfilesChanged]; -} - -void AppListModelObserverBridge::OnShutdown() { - [parent_ setDelegate:nil]; -} - -} // namespace app_list - -@implementation AppListViewController - -- (id)init { - if ((self = [super init])) { - appsGridController_.reset([[AppsGridController alloc] init]); - [self loadAndSetView]; - - [self totalPagesChanged]; - [self selectedPageChanged:0]; - [appsGridController_ setPaginationObserver:self]; - } - return self; -} - -- (void)dealloc { - // Ensure that setDelegate(NULL) has been called before destruction, because - // dealloc can be called at odd times, and Objective C destruction order does - // not properly tear down these dependencies. - DCHECK(delegate_ == NULL); - [appsGridController_ setPaginationObserver:nil]; - [super dealloc]; -} - -- (AppsSearchBoxController*)searchBoxController { - return appsSearchBoxController_; -} - -- (BOOL)showingSearchResults { - return showingSearchResults_; -} - -- (AppsGridController*)appsGridController { - return appsGridController_; -} - -- (NSSegmentedControl*)pagerControl { - return pagerControl_; -} - -- (NSView*)backgroundView { - return backgroundView_; -} - -- (app_list::AppListViewDelegate*)delegate { - return delegate_; -} - -- (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate { - if (delegate_) { - // Ensure the search box is cleared when switching profiles. - if ([self searchBoxModel]) - [self searchBoxModel]->SetText(base::string16()); - - // First clean up, in reverse order. - app_list_model_observer_bridge_.reset(); - [appsSearchResultsController_ setDelegate:nil]; - [appsSearchBoxController_ setDelegate:nil]; - [appsGridController_ setDelegate:nil]; - [messageText_ setDelegate:nil]; - } - delegate_ = newDelegate; - if (delegate_) { - [loadingIndicator_ stopAnimation:self]; - } else { - [loadingIndicator_ startAnimation:self]; - return; - } - - [appsGridController_ setDelegate:delegate_]; - [appsSearchBoxController_ setDelegate:self]; - [appsSearchResultsController_ setDelegate:self]; - app_list_model_observer_bridge_.reset( - new app_list::AppListModelObserverBridge(self)); - [self onProfilesChanged]; - [self updateMessage]; -} - -- (void)updateMessage { - if (![AppsGridController hasFewerRows]) - return; - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - NSFont* messageFont = rb.GetFontWithDelta(0).GetNativeFont(); - NSFont* titleFont = rb.GetFontWithDelta(2).GetNativeFont(); - - base::string16 title = delegate_->GetMessageTitle(); - size_t messageBreak; - base::string16 messageFull = delegate_->GetMessageText(&messageBreak); - base::string16 shortcutName = delegate_->GetAppsShortcutName(); - base::string16 learnMore = delegate_->GetLearnMoreText(); - base::string16 learnMoreUrl = delegate_->GetLearnMoreLink(); - - base::string16 messagePre = messageFull.substr(0, messageBreak); - base::string16 messagePost = messageFull.substr(messageBreak); - - NSURL* linkURL = [NSURL URLWithString:base::SysUTF16ToNSString(learnMoreUrl)]; - gfx::ImageSkia* icon = delegate_->GetAppsIcon(); - - // Shift the baseline up so that the graphics align centered. 4 looks nice. It - // happens to be the image size minus the font size, but that's a coincidence. - const CGFloat kBaselineShift = 4; - base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( - [[NSMutableParagraphStyle alloc] init]); - [paragraphStyle setLineSpacing:kSpacingBelowMessageTitle + kBaselineShift]; - - NSNumber* baselineOffset = [NSNumber numberWithFloat:kBaselineShift]; - base::scoped_nsobject<NSMutableAttributedString> text( - [[NSMutableAttributedString alloc] - initWithString:base::SysUTF16ToNSString(title) - attributes:@{ - NSParagraphStyleAttributeName : paragraphStyle, - NSFontAttributeName : titleFont - }]); - - NSDictionary* defaultAttributes = @{ - NSFontAttributeName : messageFont, - NSBaselineOffsetAttributeName : baselineOffset - }; - - base::scoped_nsobject<NSAttributedString> lineBreak( - [[NSAttributedString alloc] initWithString:@"\n" - attributes:defaultAttributes]); - base::scoped_nsobject<NSAttributedString> space([[NSAttributedString alloc] - initWithString:@" " - attributes:defaultAttributes]); - base::scoped_nsobject<NSAttributedString> messagePreString( - [[NSAttributedString alloc] - initWithString:base::SysUTF16ToNSString(messagePre) - attributes:defaultAttributes]); - base::scoped_nsobject<NSAttributedString> messagePostString( - [[NSAttributedString alloc] - initWithString:base::SysUTF16ToNSString(messagePost) - attributes:defaultAttributes]); - - // NSUnderlineStyleNone is broken. - base::scoped_nsobject<NSAttributedString> learnMoreString( - [[NSAttributedString alloc] - initWithString:base::SysUTF16ToNSString(learnMore) - attributes:@{ - NSParagraphStyleAttributeName : paragraphStyle, - NSFontAttributeName : messageFont, - NSLinkAttributeName : linkURL, - NSBaselineOffsetAttributeName : baselineOffset, - NSUnderlineStyleAttributeName : - [NSNumber numberWithInt:NSUnderlineStyleNone] - }]); - base::scoped_nsobject<NSAttributedString> shortcutStringText( - [[NSAttributedString alloc] - initWithString:base::SysUTF16ToNSString(shortcutName) - attributes:defaultAttributes]); - base::scoped_nsobject<NSMutableAttributedString> shortcutString( - [[NSMutableAttributedString alloc] init]); - if (icon) { - NSImage* image = gfx::NSImageFromImageSkia(*icon); - // The image has a bunch of representations. Ensure the smallest is used. - // (Going smaller would make pixels all manky, so don't do that). - [image setSize:NSMakeSize(16, 16)]; - - base::scoped_nsobject<NSTextAttachmentCell> attachmentCell( - [[NSTextAttachmentCell alloc] initImageCell:image]); - base::scoped_nsobject<NSTextAttachment> attachment( - [[NSTextAttachment alloc] init]); - [attachment setAttachmentCell:attachmentCell]; - [shortcutString - appendAttributedString:[NSAttributedString - attributedStringWithAttachment:attachment]]; - [shortcutString appendAttributedString:space]; - } - [shortcutString appendAttributedString:shortcutStringText]; - - [text appendAttributedString:lineBreak]; - [text appendAttributedString:messagePreString]; - [text appendAttributedString:shortcutString]; - [text appendAttributedString:messagePostString]; - [text appendAttributedString:space]; - [text appendAttributedString:learnMoreString]; - - [[messageText_ textStorage] setAttributedString:text]; - [messageText_ sizeToFit]; - - // If the user scroller preference is to always show scrollbars, and the - // translated message is long, the scroll track may be present. This means - // text will be under the scroller. We only want vertical scrolling, but - // reducing the width puts the scroll track in a weird spot. So, increase the - // width of the scroll view to move the track into the padding towards the - // message background border, then reduce the width of the text view. The - // non-overlay scroller still looks kinda weird but hopefully not many will - // actually see it. - CGFloat overlap = - NSWidth([messageText_ bounds]) - [messageScrollView_ contentSize].width; - if (overlap > 0) { - NSRect rect = [messageScrollView_ frame]; - rect.size.width += kMessageTextInset - 2; - [messageScrollView_ setFrame:rect]; - overlap -= kMessageTextInset - 2; - DCHECK_GT(overlap, 0); - rect = [messageText_ frame]; - rect.size.width -= overlap; - [messageText_ setFrame:rect]; - [messageText_ sizeToFit]; - - // And after doing all that for some reason Cocoa scrolls to the bottom. So - // fix that. - [[messageScrollView_ documentView] scrollPoint:NSMakePoint(0, 0)]; - } - - [messageText_ setDelegate:self]; -} - -- (void)loadAndSetView { - pagerControl_.reset([[AppListPagerView alloc] init]); - [pagerControl_ setTarget:appsGridController_]; - [pagerControl_ setAction:@selector(onPagerClicked:)]; - - NSRect gridFrame = [[appsGridController_ view] frame]; - - base::scoped_nsobject<NSView> messageTextBackground; - if ([AppsGridController hasFewerRows]) { - messageTextBackground.reset( - [[MessageBackgroundView alloc] initWithFrame:kMessageRect]); - NSRect frameRect = - NSInsetRect(kMessageRect, kMessageTextInset, kMessageTextInset); - messageText_.reset([[NSTextView alloc] initWithFrame:frameRect]); - // Provide a solid background here (as well as the background) so that - // subpixel AA works. - [messageText_ - setBackgroundColor:skia::SkColorToSRGBNSColor(kMessageBackgroundColor)]; - [messageText_ setDrawsBackground:YES]; - [messageText_ setEditable:NO]; - // Ideally setSelectable:NO would also be set here, but that disables mouse - // events completely, breaking the "Learn more" link. Instead, selection is - // "disabled" via a delegate method which Apple's documentation suggests. In - // reality, selection still happens, it just disappears once the mouse is - // released. To avoid the selection appearing, also set selected text to - // have no special attributes. Sadly, the mouse cursor still displays an - // I-beam, but hacking cursor rectangles on the view so that the "Learn - // More" link is still correctly handled is too hard. - [messageText_ setSelectedTextAttributes:@{}]; - gridFrame.origin.y += NSMaxY([messageTextBackground frame]); - } - - [[appsGridController_ view] setFrame:gridFrame]; - - NSRect contentsRect = - NSMakeRect(0, kSearchInputHeight + kTopSeparatorSize, NSWidth(gridFrame), - NSMaxY(gridFrame) + kPagerPreferredHeight - - [AppsGridController scrollerPadding]); - - contentsView_.reset([[FlippedView alloc] initWithFrame:contentsRect]); - - // The contents view contains animations both from an NSCollectionView and the - // app list's own transitive drag layers. On Mavericks, the subviews need to - // have access to a compositing layer they can share. Otherwise the compositor - // makes tearing artifacts. However, doing this on Mountain Lion or earler - // results in flickering whilst an item is installing. - if (base::mac::IsOSMavericksOrLater()) - [contentsView_ setWantsLayer:YES]; - - backgroundView_.reset( - [[BackgroundView alloc] initWithFrame: - NSMakeRect(0, 0, NSMaxX(contentsRect), NSMaxY(contentsRect))]); - appsSearchBoxController_.reset( - [[AppsSearchBoxController alloc] initWithFrame: - NSMakeRect(0, 0, NSWidth(contentsRect), kSearchInputHeight)]); - appsSearchResultsController_.reset( - [[AppsSearchResultsController alloc] initWithAppsSearchResultsFrameSize: - [contentsView_ bounds].size]); - base::scoped_nsobject<NSView> containerView( - [[NSView alloc] initWithFrame:[backgroundView_ frame]]); - - loadingIndicator_.reset( - [[NSProgressIndicator alloc] initWithFrame:NSZeroRect]); - [loadingIndicator_ setStyle:NSProgressIndicatorSpinningStyle]; - [loadingIndicator_ sizeToFit]; - NSRect indicatorRect = [loadingIndicator_ frame]; - indicatorRect.origin.x = NSWidth(contentsRect) / 2 - NSMidX(indicatorRect); - indicatorRect.origin.y = NSHeight(contentsRect) / 2 - NSMidY(indicatorRect); - [loadingIndicator_ setFrame:indicatorRect]; - [loadingIndicator_ setDisplayedWhenStopped:NO]; - [loadingIndicator_ startAnimation:self]; - - if (messageText_) { - [contentsView_ addSubview:messageTextBackground]; - - // Add a scroll view in case the translation is long and doesn't fit. Mac - // likes to hide scrollbars, so add to the height so the user can see part - // of the next line of text: just extend out into the padding towards the - // text background's border. Subtract at least 2: one for the border stroke - // and one for a bit of padding. - NSRect frameRect = [messageText_ frame]; - frameRect.size.height += kMessageTextInset - 2; - messageScrollView_.reset([[NSScrollView alloc] initWithFrame:frameRect]); - [messageScrollView_ setHasVerticalScroller:YES]; - [messageScrollView_ setAutohidesScrollers:YES]; - - // Now the message is going into an NSScrollView, origin should be 0, 0. - frameRect = [messageText_ frame]; - frameRect.origin = NSMakePoint(0, 0); - [messageText_ setFrame:frameRect]; - - [messageScrollView_ setDocumentView:messageText_]; - [contentsView_ addSubview:messageScrollView_]; - } - [contentsView_ addSubview:[appsGridController_ view]]; - [contentsView_ addSubview:pagerControl_]; - [contentsView_ addSubview:loadingIndicator_]; - [backgroundView_ addSubview:contentsView_]; - [backgroundView_ addSubview:[appsSearchResultsController_ view]]; - [backgroundView_ addSubview:[appsSearchBoxController_ view]]; - [containerView addSubview:backgroundView_]; - [self setView:containerView]; -} - -- (void)revealSearchResults:(BOOL)show { - if (show == showingSearchResults_) - return; - - showingSearchResults_ = show; - NSSize contentsSize = [contentsView_ frame].size; - NSRect resultsTargetRect = NSMakeRect( - 0, kSearchInputHeight + kTopSeparatorSize, - contentsSize.width, contentsSize.height); - NSRect contentsTargetRect = resultsTargetRect; - - // Shows results by sliding the grid and pager down to the bottom of the view. - // Hides results by collapsing the search results container to a height of 0. - if (show) - contentsTargetRect.origin.y += NSHeight(contentsTargetRect); - else - resultsTargetRect.size.height = 0; - - [[NSAnimationContext currentContext] setDuration:kResultsAnimationDuration]; - [[contentsView_ animator] setFrame:contentsTargetRect]; - [[[appsSearchResultsController_ view] animator] setFrame:resultsTargetRect]; -} - -- (void)totalPagesChanged { - size_t pageCount = [appsGridController_ pageCount]; - [pagerControl_ setSegmentCount:pageCount]; - - NSRect viewFrame = [[pagerControl_ superview] bounds]; - CGFloat segmentWidth = std::min( - kMaxSegmentWidth, - (viewFrame.size.width - 2 * kMinPagerMargin) / pageCount); - - for (size_t i = 0; i < pageCount; ++i) { - [pagerControl_ setWidth:segmentWidth - forSegment:i]; - [[pagerControl_ cell] setTag:i - forSegment:i]; - } - - // Center in view. - [pagerControl_ sizeToFit]; - [pagerControl_ setFrame: - NSMakeRect(NSMidX(viewFrame) - NSMidX([pagerControl_ bounds]), - viewFrame.size.height - kPagerPreferredHeight, - [pagerControl_ bounds].size.width, - kPagerPreferredHeight)]; -} - -- (void)selectedPageChanged:(int)newSelected { - [pagerControl_ selectSegmentWithTag:newSelected]; -} - -- (void)pageVisibilityChanged { - [pagerControl_ setNeedsDisplay:YES]; -} - -- (NSInteger)pagerSegmentAtLocation:(NSPoint)locationInWindow { - return [pagerControl_ findAndHighlightSegmentAtLocation:locationInWindow]; -} - -- (app_list::SearchBoxModel*)searchBoxModel { - app_list::AppListModel* appListModel = [appsGridController_ model]; - return appListModel ? appListModel->search_box() : NULL; -} - -- (app_list::AppListViewDelegate*)appListDelegate { - return [self delegate]; -} - -- (BOOL)control:(NSControl*)control - textView:(NSTextView*)textView - doCommandBySelector:(SEL)command { - if (showingSearchResults_) - return [appsSearchResultsController_ handleCommandBySelector:command]; - - // If anything has been written, let the search view handle it. - if ([[control stringValue] length] > 0) - return NO; - - // Handle escape. - if (command == @selector(complete:) || - command == @selector(cancel:) || - command == @selector(cancelOperation:)) { - if (delegate_) - delegate_->Dismiss(); - return YES; - } - - // Possibly handle grid navigation. - return [appsGridController_ handleCommandBySelector:command]; -} - -- (void)modelTextDidChange { - app_list::SearchBoxModel* searchBoxModel = [self searchBoxModel]; - if (!searchBoxModel || !delegate_) - return; - - base::string16 query; - base::TrimWhitespace(searchBoxModel->text(), base::TRIM_ALL, &query); - BOOL shouldShowSearch = !query.empty(); - [self revealSearchResults:shouldShowSearch]; - if (shouldShowSearch) - delegate_->StartSearch(); - else - delegate_->StopSearch(); -} - -- (app_list::AppListModel*)appListModel { - return [appsGridController_ model]; -} - -- (void)openResult:(app_list::SearchResult*)result { - if (delegate_) { - delegate_->OpenSearchResult( - result, false /* auto_launch */, 0 /* event flags */); - } -} - -- (void)onProfilesChanged { - [appsSearchBoxController_ rebuildMenu]; -} - -// NSTextViewDelegate implementation. - -- (BOOL)textView:(NSTextView*)textView - clickedOnLink:(id)link - atIndex:(NSUInteger)charIndex { - DCHECK(delegate_); - delegate_->OpenLearnMoreLink(); - return YES; -} - -- (NSArray*)textView:(NSTextView*)aTextView - willChangeSelectionFromCharacterRanges:(NSArray*)oldSelectedCharRanges - toCharacterRanges:(NSArray*)newSelectedCharRanges { - return oldSelectedCharRanges; -} - -@end
diff --git a/ui/app_list/cocoa/app_list_view_controller_unittest.mm b/ui/app_list/cocoa/app_list_view_controller_unittest.mm deleted file mode 100644 index 2c23574..0000000 --- a/ui/app_list/cocoa/app_list_view_controller_unittest.mm +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#import "testing/gtest_mac.h" -#import "ui/app_list/cocoa/app_list_view_controller.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#import "ui/app_list/cocoa/test/apps_grid_controller_test_helper.h" -#include "ui/app_list/test/app_list_test_model.h" -#include "ui/app_list/test/app_list_test_view_delegate.h" - -namespace app_list { -namespace test { - -class AppListViewControllerTest : public AppsGridControllerTestHelper { - public: - AppListViewControllerTest() {} - - void SetUp() override { - app_list_view_controller_.reset([[AppListViewController alloc] init]); - delegate_.reset(new AppListTestViewDelegate); - [app_list_view_controller_ setDelegate:delegate_.get()]; - SetUpWithGridController([app_list_view_controller_ appsGridController]); - [[test_window() contentView] addSubview:[app_list_view_controller_ view]]; - } - - void TearDown() override { - [app_list_view_controller_ setDelegate:NULL]; - app_list_view_controller_.reset(); - AppsGridControllerTestHelper::TearDown(); - } - - void ReplaceTestModel(int item_count) { - [app_list_view_controller_ setDelegate:NULL]; - delegate_.reset(new AppListTestViewDelegate); - delegate_->ReplaceTestModel(item_count); - [app_list_view_controller_ setDelegate:delegate_.get()]; - } - - AppListTestModel* model() { return delegate_->GetTestModel(); } - - protected: - std::unique_ptr<AppListTestViewDelegate> delegate_; - base::scoped_nsobject<AppListViewController> app_list_view_controller_; - - private: - DISALLOW_COPY_AND_ASSIGN(AppListViewControllerTest); -}; - -TEST_VIEW(AppListViewControllerTest, [app_list_view_controller_ view]); - -// Test that adding and removing pages updates the pager. -TEST_F(AppListViewControllerTest, PagerSegmentCounts) { - NSSegmentedControl* pager = [app_list_view_controller_ pagerControl]; - EXPECT_EQ(1, [pager segmentCount]); - - ReplaceTestModel(kItemsPerPage * 2); - EXPECT_EQ(2, [pager segmentCount]); - model()->PopulateApps(1); - EXPECT_EQ(3, [pager segmentCount]); - - ReplaceTestModel(1); - EXPECT_EQ(1, [pager segmentCount]); -} - -// Test that clicking the pager changes pages. -TEST_F(AppListViewControllerTest, PagerChangingPage) { - NSSegmentedControl* pager = [app_list_view_controller_ pagerControl]; - ReplaceTestModel(kItemsPerPage * 3); - EXPECT_EQ(3, [pager segmentCount]); - - EXPECT_EQ(0, [pager selectedSegment]); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(1.0, [apps_grid_controller_ visiblePortionOfPage:0]); - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:1]); - - // Emulate a click on the second segment to navigate to the second page. - [pager setSelectedSegment:1]; - [[pager target] performSelector:[pager action] - withObject:pager]; - - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(1, [pager selectedSegment]); - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:0]); - EXPECT_EQ(1.0, [apps_grid_controller_ visiblePortionOfPage:1]); - - // Replace with a single page model, and ensure we go back to the first page. - ReplaceTestModel(1); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(0, [pager selectedSegment]); - EXPECT_EQ(1, [pager segmentCount]); - EXPECT_EQ(1.0, [apps_grid_controller_ visiblePortionOfPage:0]); -} - -} // namespace test -} // namespace app_list
diff --git a/ui/app_list/cocoa/app_list_window_controller.h b/ui/app_list/cocoa/app_list_window_controller.h deleted file mode 100644 index 052682ff..0000000 --- a/ui/app_list/cocoa/app_list_window_controller.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APP_LIST_WINDOW_CONTROLLER_H_ -#define UI_APP_LIST_COCOA_APP_LIST_WINDOW_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include "base/mac/scoped_nsobject.h" -#include "ui/app_list/app_list_export.h" - -@class AppListViewController; - -// Controller for the app list NSWindow. -APP_LIST_EXPORT -@interface AppListWindowController : NSWindowController<NSWindowDelegate> { - @private - base::scoped_nsobject<AppListViewController> appListViewController_; -} - -- (AppListViewController*)appListViewController; - -@end - -#endif // UI_APP_LIST_COCOA_APP_LIST_WINDOW_CONTROLLER_H_
diff --git a/ui/app_list/cocoa/app_list_window_controller.mm b/ui/app_list/cocoa/app_list_window_controller.mm deleted file mode 100644 index 5eae08d7..0000000 --- a/ui/app_list/cocoa/app_list_window_controller.mm +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/app_list_window_controller.h" - -#include "ui/app_list/app_list_view_delegate.h" -#import "ui/app_list/cocoa/app_list_view_controller.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#import "ui/app_list/cocoa/apps_search_box_controller.h" -#include "ui/base/cocoa/window_size_constants.h" - -@interface AppListWindow : NSWindow; -@end - -@implementation AppListWindow - -// If we initialize a window with NSBorderlessWindowMask, it will not accept key -// events (among other things) unless canBecomeKeyWindow is overridden. -- (BOOL)canBecomeKeyWindow { - return YES; -} - -- (BOOL)canBecomeMainWindow { - return YES; -} - -// On Mavericks with the "Displays have separate Spaces" option, OSX has stopped -// switching out of the fullscreen space when activating a window in the non- -// active application, other than by clicking its Dock icon. Since the app -// launcher Dock icon is not Chrome, this can leave a user in fullscreen with -// the app launcher window obscured. Overriding this private method allows the -// app launcher to appear on top of other applications in fullscreen. Then, -// since clicking that window will make Chrome active, subsequent window -// activations will successfully switch the user out of the fullscreen space. -- (BOOL)_allowedInOtherAppsFullScreenSpaceWithCollectionBehavior: - (NSUInteger)collectionBehavior { - return YES; -} - -@end - -@implementation AppListWindowController; - -- (id)init { - base::scoped_nsobject<NSWindow> controlledWindow( - [[AppListWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]); - [controlledWindow setReleasedWhenClosed:NO]; - [controlledWindow setBackgroundColor:[NSColor clearColor]]; - [controlledWindow setOpaque:NO]; - [controlledWindow setHasShadow:YES]; - [controlledWindow setLevel:NSDockWindowLevel]; - [controlledWindow - setCollectionBehavior:NSWindowCollectionBehaviorMoveToActiveSpace]; - - if ((self = [super initWithWindow:controlledWindow])) { - appListViewController_.reset([[AppListViewController alloc] init]); - [[self window] setFrame:[[appListViewController_ view] bounds] - display:NO]; - [[self window] setContentView:[appListViewController_ view]]; - [[self window] setDelegate:self]; - } - return self; -} - -- (AppListViewController*)appListViewController { - return appListViewController_; -} - -- (void)windowDidResignMain:(NSNotification*)notification { - if ([appListViewController_ delegate]) - [appListViewController_ delegate]->Dismiss(); -} - -- (void)windowWillClose:(NSNotification*)notification { - [[appListViewController_ searchBoxController] clearSearch]; -} - -@end
diff --git a/ui/app_list/cocoa/app_list_window_controller_unittest.mm b/ui/app_list/cocoa/app_list_window_controller_unittest.mm deleted file mode 100644 index 2f857da..0000000 --- a/ui/app_list/cocoa/app_list_window_controller_unittest.mm +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "base/strings/utf_string_conversions.h" -#import "testing/gtest_mac.h" -#include "ui/app_list/app_list_view_delegate.h" -#import "ui/app_list/cocoa/app_list_view_controller.h" -#import "ui/app_list/cocoa/app_list_window_controller.h" -#include "ui/app_list/search_box_model.h" -#include "ui/app_list/test/app_list_test_view_delegate.h" -#import "ui/gfx/test/ui_cocoa_test_helper.h" - -namespace { - -class AppListWindowControllerTest : public ui::CocoaTest { - public: - AppListWindowControllerTest(); - - protected: - void TearDown() override; - - base::scoped_nsobject<AppListWindowController> controller_; - - app_list::test::AppListTestViewDelegate* delegate() { - return delegate_.get(); - } - - private: - std::unique_ptr<app_list::test::AppListTestViewDelegate> delegate_; - - DISALLOW_COPY_AND_ASSIGN(AppListWindowControllerTest); -}; - -AppListWindowControllerTest::AppListWindowControllerTest() - : delegate_(new app_list::test::AppListTestViewDelegate) { - Init(); - controller_.reset([[AppListWindowController alloc] init]); - [[controller_ appListViewController] setDelegate:delegate()]; -} - -void AppListWindowControllerTest::TearDown() { - EXPECT_TRUE(controller_.get()); - [[controller_ window] close]; - [[controller_ appListViewController] setDelegate:NULL]; - controller_.reset(); - ui::CocoaTest::TearDown(); -} - -} // namespace - -// Test showing, hiding and closing the app list window. -TEST_F(AppListWindowControllerTest, ShowHideCloseRelease) { - EXPECT_TRUE([controller_ window]); - [[controller_ window] makeKeyAndOrderFront:nil]; - EXPECT_TRUE([[controller_ window] isVisible]); - EXPECT_TRUE([[[controller_ window] contentView] superview]); - [[controller_ window] close]; // Hide. - EXPECT_FALSE([[controller_ window] isVisible]); - [[controller_ window] makeKeyAndOrderFront:nil]; -} - -// Test that the key bound to cancel (usually Escape) asks the controller to -// dismiss the window. -TEST_F(AppListWindowControllerTest, DismissWithEscape) { - [[controller_ window] makeKeyAndOrderFront:nil]; - EXPECT_EQ(0, delegate()->dismiss_count()); - [[controller_ window] cancelOperation:controller_]; - EXPECT_EQ(1, delegate()->dismiss_count()); -} - -// Test that search results are cleared when the window closes, not when a -// search result is selected. If cleared upon selection, the animation showing -// the results sliding away is seen as the window closes, which looks weird. -TEST_F(AppListWindowControllerTest, CloseClearsSearch) { - [[controller_ window] makeKeyAndOrderFront:nil]; - app_list::SearchBoxModel* model = delegate()->GetModel()->search_box(); - AppListViewController* view_controller = [controller_ appListViewController]; - - EXPECT_FALSE([view_controller showingSearchResults]); - - const base::string16 search_text(base::ASCIIToUTF16("test")); - model->SetText(search_text); - EXPECT_TRUE([view_controller showingSearchResults]); - - EXPECT_EQ(0, delegate()->open_search_result_count()); - [view_controller openResult:nil]; - EXPECT_EQ(1, delegate()->open_search_result_count()); - - EXPECT_TRUE([view_controller showingSearchResults]); - [[controller_ window] close]; // Hide. - EXPECT_FALSE([view_controller showingSearchResults]); -}
diff --git a/ui/app_list/cocoa/apps_collection_view_drag_manager.h b/ui/app_list/cocoa/apps_collection_view_drag_manager.h deleted file mode 100644 index 94e74791..0000000 --- a/ui/app_list/cocoa/apps_collection_view_drag_manager.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_COLLECTION_VIEW_DRAG_MANAGER_H_ -#define UI_APP_LIST_COCOA_APPS_COLLECTION_VIEW_DRAG_MANAGER_H_ - -#import <Cocoa/Cocoa.h> -#include <stddef.h> - -#include "base/mac/scoped_nsobject.h" -#include "ui/app_list/app_list_export.h" - -@class AppsGridController; -@class ItemDragController; - -// Manager for the state associated with dragging an NSCollectionViewItem in the -// AppsGridController. It is also a factory for the NSCollectionView pages in -// the grid, allowing items to be dragged between pages. -APP_LIST_EXPORT -@interface AppsCollectionViewDragManager : NSObject { - @private - base::scoped_nsobject<ItemDragController> itemDragController_; - AppsGridController* gridController_; // Weak. Owns us. - - NSSize cellSize_; - size_t rows_; - size_t columns_; - - // Index of the last known position of the item currently being dragged. - size_t itemDragIndex_; - - // Model index of the item being dragged, or NSNotFound if nothing was hit on - // the last mouseDown. - size_t itemHitIndex_; - - // Location in the window of the last mouseDown event. - NSPoint mouseDownLocation_; - - // Whether the current mouse action has converted into an item drag. - BOOL dragging_; -} - -- (id)initWithCellSize:(NSSize)cellSize - rows:(size_t)rows - columns:(size_t)columns - gridController:(AppsGridController*)gridController; - -// Make an empty NSCollectionView with draggable items in the given |pageFrame|. -- (NSCollectionView*)makePageWithFrame:(NSRect)pageFrame; - -- (void)cancelDrag; - -@end - -@interface AppsCollectionViewDragManager (TestingAPI) - -- (void)onMouseDownInPage:(NSCollectionView*)page - withEvent:(NSEvent*)theEvent; -- (void)onMouseDragged:(NSEvent*)theEvent; -- (void)onMouseUp:(NSEvent*)theEvent; - -@end - -#endif // UI_APP_LIST_COCOA_APPS_COLLECTION_VIEW_DRAG_MANAGER_H_
diff --git a/ui/app_list/cocoa/apps_collection_view_drag_manager.mm b/ui/app_list/cocoa/apps_collection_view_drag_manager.mm deleted file mode 100644 index 74e23c4..0000000 --- a/ui/app_list/cocoa/apps_collection_view_drag_manager.mm +++ /dev/null
@@ -1,263 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_collection_view_drag_manager.h" - -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#import "ui/app_list/cocoa/apps_grid_view_item.h" -#import "ui/app_list/cocoa/item_drag_controller.h" - -namespace { - -// Distance cursor must travel in either x or y direction to start a drag. -const CGFloat kDragThreshold = 5; - -} // namespace - -@interface AppsCollectionViewDragManager () - -// Returns the item index that |theEvent| would hit in the page at |pageIndex| -// or NSNotFound if no item is hit. -- (size_t)itemIndexForPage:(size_t)pageIndex - hitWithEvent:(NSEvent*)theEvent; - -- (void)initiateDrag:(NSEvent*)theEvent; -- (void)updateDrag:(NSEvent*)theEvent; -- (void)completeDrag; - -- (NSMenu*)menuForEvent:(NSEvent*)theEvent - inPage:(NSCollectionView*)page; - -@end - -// An NSCollectionView that forwards mouse events to the factory they share. -@interface GridCollectionView : NSCollectionView { - @private - AppsCollectionViewDragManager* factory_; -} - -@property(assign, nonatomic) AppsCollectionViewDragManager* factory; - -@end - -@implementation AppsCollectionViewDragManager - -- (id)initWithCellSize:(NSSize)cellSize - rows:(size_t)rows - columns:(size_t)columns - gridController:(AppsGridController*)gridController { - if ((self = [super init])) { - cellSize_ = cellSize; - rows_ = rows; - columns_ = columns; - gridController_ = gridController; - } - return self; -} - -- (NSCollectionView*)makePageWithFrame:(NSRect)pageFrame { - base::scoped_nsobject<GridCollectionView> itemCollectionView( - [[GridCollectionView alloc] initWithFrame:pageFrame]); - [itemCollectionView setFactory:self]; - [itemCollectionView setMaxNumberOfRows:rows_]; - [itemCollectionView setMinItemSize:cellSize_]; - [itemCollectionView setMaxItemSize:cellSize_]; - [itemCollectionView setSelectable:YES]; - [itemCollectionView setFocusRingType:NSFocusRingTypeNone]; - [itemCollectionView setBackgroundColors: - [NSArray arrayWithObject:[NSColor clearColor]]]; - [itemCollectionView setDelegate:gridController_]; - - base::scoped_nsobject<AppsGridViewItem> itemPrototype( - [[AppsGridViewItem alloc] initWithSize:cellSize_]); - [[itemPrototype button] setTarget:gridController_]; - [[itemPrototype button] setAction:@selector(onItemClicked:)]; - - [itemCollectionView setItemPrototype:itemPrototype]; - return itemCollectionView.autorelease(); -} - -- (void)onMouseDownInPage:(NSCollectionView*)page - withEvent:(NSEvent*)theEvent { - size_t pageIndex = [gridController_ pageIndexForCollectionView:page]; - itemHitIndex_ = [self itemIndexForPage:pageIndex - hitWithEvent:theEvent]; - if (itemHitIndex_ == NSNotFound) - return; - - mouseDownLocation_ = [theEvent locationInWindow]; - [[[gridController_ itemAtIndex:itemHitIndex_] view] mouseDown:theEvent]; -} - -- (void)onMouseDragged:(NSEvent*)theEvent { - if (itemHitIndex_ == NSNotFound) - return; - - if (dragging_) { - [self updateDrag:theEvent]; - return; - } - - NSPoint mouseLocation = [theEvent locationInWindow]; - CGFloat deltaX = mouseLocation.x - mouseDownLocation_.x; - CGFloat deltaY = mouseLocation.y - mouseDownLocation_.y; - if (deltaX * deltaX + deltaY * deltaY > kDragThreshold * kDragThreshold) { - [self initiateDrag:theEvent]; - return; - } - - [[[gridController_ itemAtIndex:itemHitIndex_] view] mouseDragged:theEvent]; -} - -- (void)onMouseUp:(NSEvent*)theEvent { - if (itemHitIndex_ == NSNotFound) - return; - - if (dragging_) { - [self completeDrag]; - return; - } - - [[[gridController_ itemAtIndex:itemHitIndex_] view] mouseUp:theEvent]; -} - -- (size_t)itemIndexForPage:(size_t)pageIndex - hitWithEvent:(NSEvent*)theEvent { - NSCollectionView* page = - [gridController_ collectionViewAtPageIndex:pageIndex]; - NSPoint pointInView = [page convertPoint:[theEvent locationInWindow] - fromView:nil]; - - const size_t itemsInPage = [[page content] count]; - for (size_t indexInPage = 0; indexInPage < itemsInPage; ++indexInPage) { - if ([page mouse:pointInView - inRect:[page frameForItemAtIndex:indexInPage]]) { - return indexInPage + pageIndex * rows_ * columns_; - } - } - - return NSNotFound; -} - -- (void)initiateDrag:(NSEvent*)theEvent { - DCHECK_LT(itemHitIndex_, [gridController_ itemCount]); - dragging_ = YES; - - if (!itemDragController_) { - itemDragController_.reset( - [[ItemDragController alloc] initWithGridCellSize:cellSize_]); - [[[gridController_ view] superview] addSubview:[itemDragController_ view]]; - } - - [itemDragController_ initiate:[gridController_ itemAtIndex:itemHitIndex_] - mouseDownLocation:mouseDownLocation_ - currentLocation:[theEvent locationInWindow] - timestamp:[theEvent timestamp]]; - - itemDragIndex_ = itemHitIndex_; - [self updateDrag:theEvent]; -} - -- (void)updateDrag:(NSEvent*)theEvent { - [itemDragController_ update:[theEvent locationInWindow] - timestamp:[theEvent timestamp]]; - [gridController_ maybeChangePageForPoint:[theEvent locationInWindow]]; - - size_t visiblePage = [gridController_ visiblePage]; - size_t itemIndexOver = [self itemIndexForPage:visiblePage - hitWithEvent:theEvent]; - DCHECK_NE(0u, [gridController_ itemCount]); - if (itemIndexOver == NSNotFound) { - if (visiblePage != [gridController_ pageCount] - 1) - return; - - // If nothing was hit, but the last page is shown, move to the end. - itemIndexOver = [gridController_ itemCount] - 1; - } - - if (itemDragIndex_ == itemIndexOver) - return; - - [gridController_ moveItemInView:itemDragIndex_ - toItemIndex:itemIndexOver]; - // A new item may be created when moving between pages. Ensure it is hidden. - [[[gridController_ itemAtIndex:itemIndexOver] button] setHidden:YES]; - itemDragIndex_ = itemIndexOver; -} - -- (void)cancelDrag { - if (!dragging_) - return; - - [gridController_ moveItemInView:itemDragIndex_ - toItemIndex:itemHitIndex_]; - itemDragIndex_ = itemHitIndex_; - [self completeDrag]; - itemHitIndex_ = NSNotFound; // Ignore future mouse events for this drag. -} - -- (void)completeDrag { - DCHECK_GE(itemDragIndex_, 0u); - [gridController_ cancelScrollTimer]; - AppsGridViewItem* item = [gridController_ itemAtIndex:itemDragIndex_]; - - // The item could still be animating in the NSCollectionView, so ask it where - // it would place the item. - NSCollectionView* pageView = base::mac::ObjCCastStrict<NSCollectionView>( - [[item view] superview]); - size_t indexInPage = itemDragIndex_ % (rows_ * columns_); - NSPoint targetOrigin = [[[itemDragController_ view] superview] - convertPoint:[pageView frameForItemAtIndex:indexInPage].origin - fromView:pageView]; - - [itemDragController_ complete:item - targetOrigin:targetOrigin]; - [gridController_ moveItemWithIndex:itemHitIndex_ - toModelIndex:itemDragIndex_]; - - dragging_ = NO; -} - -- (NSMenu*)menuForEvent:(NSEvent*)theEvent - inPage:(NSCollectionView*)page { - size_t pageIndex = [gridController_ pageIndexForCollectionView:page]; - size_t itemIndex = [self itemIndexForPage:pageIndex - hitWithEvent:theEvent]; - if (itemIndex == NSNotFound) - return nil; - - return [[gridController_ itemAtIndex:itemIndex] contextMenu]; -} - -@end - -@implementation GridCollectionView - -@synthesize factory = factory_; - -- (NSMenu*)menuForEvent:(NSEvent*)theEvent { - return [factory_ menuForEvent:theEvent - inPage:self]; -} - -- (void)mouseDown:(NSEvent*)theEvent { - [factory_ onMouseDownInPage:self - withEvent:theEvent]; -} - -- (void)mouseDragged:(NSEvent*)theEvent { - [factory_ onMouseDragged:theEvent]; -} - -- (void)mouseUp:(NSEvent*)theEvent { - [factory_ onMouseUp:theEvent]; -} - -- (BOOL)acceptsFirstResponder { - return NO; -} - -@end
diff --git a/ui/app_list/cocoa/apps_grid_controller.h b/ui/app_list/cocoa/apps_grid_controller.h deleted file mode 100644 index f1a1b83..0000000 --- a/ui/app_list/cocoa/apps_grid_controller.h +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_GRID_CONTROLLER_H_ -#define UI_APP_LIST_COCOA_APPS_GRID_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> -#include <stddef.h> - -#include <memory> - -#include "base/mac/scoped_nsobject.h" -#include "ui/app_list/app_list_export.h" -#import "ui/app_list/cocoa/app_list_pager_view.h" -#import "ui/app_list/cocoa/scroll_view_with_no_scrollbars.h" - -namespace app_list { -class AppListModel; -class AppListViewDelegate; -class AppsGridDelegateBridge; -} - -@class AppsGridViewItem; -@protocol AppsPaginationModelObserver; -@class AppsCollectionViewDragManager; - -// Controls a grid of views, representing AppListItemList sub models. -APP_LIST_EXPORT -@interface AppsGridController : NSViewController<GestureScrollDelegate, - AppListPagerDelegate, - NSCollectionViewDelegate> { - @private - app_list::AppListViewDelegate* delegate_; // Weak. Owned by view controller. - std::unique_ptr<app_list::AppsGridDelegateBridge> bridge_; - - base::scoped_nsobject<AppsCollectionViewDragManager> dragManager_; - base::scoped_nsobject<NSMutableArray> pages_; - base::scoped_nsobject<NSMutableArray> items_; - base::scoped_nsobject<NSTimer> scrollWhileDraggingTimer_; - - id<AppsPaginationModelObserver> paginationObserver_; - - // Index of the currently visible page. - size_t visiblePage_; - // The page to which the view is currently animating a scroll. - size_t targetScrollPage_; - // The page to start scrolling to when the timer expires. - size_t scheduledScrollPage_; - - // Whether we are currently animating a scroll to the nearest page. - BOOL animatingScroll_; -} - -@property(assign, nonatomic) id<AppsPaginationModelObserver> paginationObserver; - -+ (void)setScrollAnimationDuration:(NSTimeInterval)duration; - -// The amount the grid view has been extended to hold the sometimes present -// invisible scroller that allows for gesture scrolling. -+ (CGFloat)scrollerPadding; - -// Whether the grid is configured with fewer rows than normal. -+ (BOOL)hasFewerRows; - -- (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex; -- (size_t)pageIndexForCollectionView:(NSCollectionView*)page; - -- (AppsGridViewItem*)itemAtIndex:(size_t)itemIndex; - -- (app_list::AppListModel*)model; - -- (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate; - -- (size_t)visiblePage; - -// Calls item->Activate for the currently selected item by simulating a click. -- (void)activateSelection; - -// Return the number of pages of icons in the grid. -- (size_t)pageCount; - -// Return the number of items over all pages in the grid. -- (size_t)itemCount; - -// Scroll to a page in the grid view with an animation. -- (void)scrollToPage:(size_t)pageIndex; - -// Start a timer to scroll to a new page, if |locationInWindow| is to the left -// or the right of the view, or if it is over a pager segment. Cancels any -// existing timer if the target page changes. -- (void)maybeChangePageForPoint:(NSPoint)locationInWindow; - -// Cancel a timer that may have been set by maybeChangePageForPoint(). -- (void)cancelScrollTimer; - -// Moves an item within the view only, for dragging or in response to model -// changes. -- (void)moveItemInView:(size_t)fromIndex - toItemIndex:(size_t)toIndex; - -// Moves an item in the item model. Does not adjust the view. -- (void)moveItemWithIndex:(size_t)itemIndex - toModelIndex:(size_t)modelIndex; - -// Return the index of the selected item. -- (NSUInteger)selectedItemIndex; - -// Moves the selection to the given index. -- (void)selectItemAtIndex:(NSUInteger)index; - -// Handle key actions. Similar to doCommandBySelector from NSResponder but that -// requires this class to be in the responder chain. Instead this method is -// invoked by the AppListViewController. -// Returns YES if this handled navigation or launched an app. -- (BOOL)handleCommandBySelector:(SEL)command; - -@end - -@interface AppsGridController(TestingAPI) - -- (AppsCollectionViewDragManager*)dragManager; -- (size_t)scheduledScrollPage; - -@end - -#endif // UI_APP_LIST_COCOA_APPS_GRID_CONTROLLER_H_
diff --git a/ui/app_list/cocoa/apps_grid_controller.mm b/ui/app_list/cocoa/apps_grid_controller.mm deleted file mode 100644 index 455c441..0000000 --- a/ui/app_list/cocoa/apps_grid_controller.mm +++ /dev/null
@@ -1,709 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_grid_controller.h" - -#include "base/command_line.h" -#include "base/mac/foundation_util.h" -#include "base/macros.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/app_list_model_observer.h" -#include "ui/app_list/app_list_view_delegate.h" -#import "ui/app_list/cocoa/apps_collection_view_drag_manager.h" -#import "ui/app_list/cocoa/apps_grid_view_item.h" -#import "ui/app_list/cocoa/apps_pagination_model_observer.h" -#include "ui/base/models/list_model_observer.h" - -namespace { - -// OSX app list has hardcoded columns for now. -const int kFixedColumns = 4; - -// Padding space in pixels for fixed layout. -const CGFloat kGridTopPadding = 1; -const CGFloat kLeftRightPadding = 21; -const CGFloat kScrollerPadding = 16; - -// Preferred tile size when showing in fixed layout. These should be even -// numbers to ensure that if they are grown 50% they remain integers. -const CGFloat kPreferredTileWidth = 88; -const CGFloat kPreferredTileHeight = 98; - -const CGFloat kViewWidth = - kFixedColumns * kPreferredTileWidth + 2 * kLeftRightPadding; - -const NSTimeInterval kScrollWhileDraggingDelay = 1.0; -NSTimeInterval g_scroll_duration = 0.18; - -const char kTestType[] = "test-type"; - -int DetermineFixedRowCount() { - // This needs to be called before a delegate exists, since it is needed to - // determine the height of the view. - return [AppsGridController hasFewerRows] ? 3 : 4; -} - -int RowCount() { - static const int row_count = DetermineFixedRowCount(); - return row_count; -} - -int ItemsPerPage() { - return RowCount() * kFixedColumns; -} - -CGFloat ViewHeight() { - return RowCount() * kPreferredTileHeight; -} - -} // namespace - -@interface AppsGridController () - -- (void)scrollToPageWithTimer:(size_t)targetPage; -- (void)onTimer:(NSTimer*)theTimer; - -// Cancel a currently running scroll animation. -- (void)cancelScrollAnimation; - -// Index of the page with the most content currently visible. -- (size_t)nearestPageIndex; - -// Bootstrap the views this class controls. -- (void)loadAndSetView; - -- (void)boundsDidChange:(NSNotification*)notification; - -// Action for buttons in the grid. -- (void)onItemClicked:(id)sender; - -- (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex - indexInPage:(size_t)indexInPage; - -// Return the button of the selected item. -- (NSButton*)selectedButton; - -// The scroll view holding the grid pages. -- (NSScrollView*)gridScrollView; - -- (NSView*)pagesContainerView; - -// Create any new pages after updating |items_|. -- (void)updatePages:(size_t)startItemIndex; - -- (void)updatePageContent:(size_t)pageIndex - resetModel:(BOOL)resetModel; - -// Bridged methods for AppListItemListObserver. -- (void)listItemAdded:(size_t)index - item:(app_list::AppListItem*)item; - -- (void)listItemRemoved:(size_t)index; - -- (void)listItemMovedFromIndex:(size_t)fromIndex - toModelIndex:(size_t)toIndex; - -// Moves the selection by |indexDelta| items. -- (BOOL)moveSelectionByDelta:(int)indexDelta; - -@end - -namespace app_list { - -class AppsGridDelegateBridge : public AppListItemListObserver { - public: - AppsGridDelegateBridge(AppsGridController* parent) : parent_(parent) {} - - private: - // Overridden from AppListItemListObserver: - void OnListItemAdded(size_t index, AppListItem* item) override { - [parent_ listItemAdded:index - item:item]; - } - void OnListItemRemoved(size_t index, AppListItem* item) override { - [parent_ listItemRemoved:index]; - } - void OnListItemMoved(size_t from_index, - size_t to_index, - AppListItem* item) override { - [parent_ listItemMovedFromIndex:from_index - toModelIndex:to_index]; - } - void OnAppListItemHighlight(size_t index, bool highlight) override { - // NSCollectionView (or -[AppsGridController scrollToPage]) ensures only one - // item is highlighted, so clearing a highlight isn't necessary. - if (!highlight) - return; - - [parent_ selectItemAtIndex:index]; - [parent_ scrollToPage:index / ItemsPerPage()]; - } - - AppsGridController* parent_; // Weak, owns us. - - DISALLOW_COPY_AND_ASSIGN(AppsGridDelegateBridge); -}; - -} // namespace app_list - -@interface PageContainerView : NSView; -@end - -// The container view needs to flip coordinates so that it is laid out -// correctly whether or not there is a horizontal scrollbar. -@implementation PageContainerView - -- (BOOL)isFlipped { - return YES; -} - -@end - -@implementation AppsGridController - -+ (void)setScrollAnimationDuration:(NSTimeInterval)duration { - g_scroll_duration = duration; -} - -+ (CGFloat)scrollerPadding { - return kScrollerPadding; -} - -+ (BOOL)hasFewerRows { - return !base::CommandLine::ForCurrentProcess()->HasSwitch(kTestType); -} - -@synthesize paginationObserver = paginationObserver_; - -- (id)init { - if ((self = [super init])) { - bridge_.reset(new app_list::AppsGridDelegateBridge(self)); - NSSize cellSize = NSMakeSize(kPreferredTileWidth, kPreferredTileHeight); - dragManager_.reset([[AppsCollectionViewDragManager alloc] - initWithCellSize:cellSize - rows:RowCount() - columns:kFixedColumns - gridController:self]); - pages_.reset([[NSMutableArray alloc] init]); - items_.reset([[NSMutableArray alloc] init]); - [self loadAndSetView]; - [self updatePages:0]; - } - return self; -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; -} - -- (NSCollectionView*)collectionViewAtPageIndex:(size_t)pageIndex { - return [pages_ objectAtIndex:pageIndex]; -} - -- (size_t)pageIndexForCollectionView:(NSCollectionView*)page { - for (size_t pageIndex = 0; pageIndex < [pages_ count]; ++pageIndex) { - if (page == [self collectionViewAtPageIndex:pageIndex]) - return pageIndex; - } - return NSNotFound; -} - -- (app_list::AppListModel*)model { - return delegate_ ? delegate_->GetModel() : NULL; -} - -- (void)setDelegate:(app_list::AppListViewDelegate*)newDelegate { - if (delegate_) { - app_list::AppListModel* oldModel = delegate_->GetModel(); - if (oldModel) - oldModel->top_level_item_list()->RemoveObserver(bridge_.get()); - } - - // Since the old model may be getting deleted, and the AppKit objects might - // be sitting in an NSAutoreleasePool, ensure there are no references to - // the model. - for (size_t i = 0; i < [items_ count]; ++i) - [[self itemAtIndex:i] setModel:NULL]; - - [items_ removeAllObjects]; - [self updatePages:0]; - [self scrollToPage:0]; - - delegate_ = newDelegate; - if (!delegate_) - return; - - app_list::AppListModel* newModel = delegate_->GetModel(); - if (!newModel) - return; - - newModel->top_level_item_list()->AddObserver(bridge_.get()); - for (size_t i = 0; i < newModel->top_level_item_list()->item_count(); ++i) { - app_list::AppListItem* itemModel = - newModel->top_level_item_list()->item_at(i); - [items_ insertObject:[NSValue valueWithPointer:itemModel] - atIndex:i]; - } - [self updatePages:0]; -} - -- (size_t)visiblePage { - return visiblePage_; -} - -- (void)activateSelection { - [[self selectedButton] performClick:self]; -} - -- (size_t)pageCount { - return [pages_ count]; -} - -- (size_t)itemCount { - return [items_ count]; -} - -- (void)scrollToPage:(size_t)pageIndex { - NSClipView* clipView = [[self gridScrollView] contentView]; - NSPoint newOrigin = [clipView bounds].origin; - - // Scrolling outside of this range is edge elasticity, which animates - // automatically. - if ((pageIndex == 0 && (newOrigin.x <= 0)) || - (pageIndex + 1 == [self pageCount] && - newOrigin.x >= pageIndex * kViewWidth)) { - return; - } - - // Clear any selection on the current page (unless it has been removed). - if (visiblePage_ < [pages_ count]) { - [[self collectionViewAtPageIndex:visiblePage_] - setSelectionIndexes:[NSIndexSet indexSet]]; - } - - newOrigin.x = pageIndex * kViewWidth; - [NSAnimationContext beginGrouping]; - [[NSAnimationContext currentContext] setDuration:g_scroll_duration]; - [[clipView animator] setBoundsOrigin:newOrigin]; - [NSAnimationContext endGrouping]; - animatingScroll_ = YES; - targetScrollPage_ = pageIndex; - [self cancelScrollTimer]; -} - -- (void)maybeChangePageForPoint:(NSPoint)locationInWindow { - NSPoint pointInView = [[self view] convertPoint:locationInWindow - fromView:nil]; - // Check if the point is outside the view on the left or right. - if (pointInView.x <= 0 || pointInView.x >= NSWidth([[self view] bounds])) { - size_t targetPage = visiblePage_; - if (pointInView.x <= 0) - targetPage -= targetPage != 0 ? 1 : 0; - else - targetPage += targetPage < [pages_ count] - 1 ? 1 : 0; - [self scrollToPageWithTimer:targetPage]; - return; - } - - if (paginationObserver_) { - NSInteger segment = - [paginationObserver_ pagerSegmentAtLocation:locationInWindow]; - if (segment >= 0 && static_cast<size_t>(segment) != targetScrollPage_) { - [self scrollToPageWithTimer:segment]; - return; - } - } - - // Otherwise the point may have moved back into the view. - [self cancelScrollTimer]; -} - -- (void)cancelScrollTimer { - scheduledScrollPage_ = targetScrollPage_; - [scrollWhileDraggingTimer_ invalidate]; -} - -- (void)scrollToPageWithTimer:(size_t)targetPage { - if (targetPage == targetScrollPage_) { - [self cancelScrollTimer]; - return; - } - - if (targetPage == scheduledScrollPage_) - return; - - scheduledScrollPage_ = targetPage; - [scrollWhileDraggingTimer_ invalidate]; - scrollWhileDraggingTimer_.reset( - [[NSTimer scheduledTimerWithTimeInterval:kScrollWhileDraggingDelay - target:self - selector:@selector(onTimer:) - userInfo:nil - repeats:NO] retain]); -} - -- (void)onTimer:(NSTimer*)theTimer { - if (scheduledScrollPage_ == targetScrollPage_) - return; // Already animating scroll. - - [self scrollToPage:scheduledScrollPage_]; -} - -- (void)cancelScrollAnimation { - NSClipView* clipView = [[self gridScrollView] contentView]; - [NSAnimationContext beginGrouping]; - [[NSAnimationContext currentContext] setDuration:0]; - [[clipView animator] setBoundsOrigin:[clipView bounds].origin]; - [NSAnimationContext endGrouping]; - animatingScroll_ = NO; -} - -- (size_t)nearestPageIndex { - return lround( - NSMinX([[[self gridScrollView] contentView] bounds]) / kViewWidth); -} - -- (void)userScrolling:(BOOL)isScrolling { - if (isScrolling) { - if (animatingScroll_) - [self cancelScrollAnimation]; - } else { - [self scrollToPage:[self nearestPageIndex]]; - } -} - -- (void)loadAndSetView { - base::scoped_nsobject<PageContainerView> pagesContainer( - [[PageContainerView alloc] initWithFrame:NSZeroRect]); - - NSRect scrollFrame = NSMakeRect(0, kGridTopPadding, kViewWidth, - ViewHeight() + kScrollerPadding); - base::scoped_nsobject<ScrollViewWithNoScrollbars> scrollView( - [[ScrollViewWithNoScrollbars alloc] initWithFrame:scrollFrame]); - [scrollView setBorderType:NSNoBorder]; - [scrollView setLineScroll:kViewWidth]; - [scrollView setPageScroll:kViewWidth]; - [scrollView setDelegate:self]; - [scrollView setDocumentView:pagesContainer]; - [scrollView setDrawsBackground:NO]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(boundsDidChange:) - name:NSViewBoundsDidChangeNotification - object:[scrollView contentView]]; - - [self setView:scrollView]; -} - -- (void)boundsDidChange:(NSNotification*)notification { - size_t newPage = [self nearestPageIndex]; - if (newPage == visiblePage_) { - [paginationObserver_ pageVisibilityChanged]; - return; - } - - visiblePage_ = newPage; - [paginationObserver_ selectedPageChanged:newPage]; - [paginationObserver_ pageVisibilityChanged]; -} - -- (void)onItemClicked:(id)sender { - for (size_t i = 0; i < [items_ count]; ++i) { - AppsGridViewItem* gridItem = [self itemAtIndex:i]; - if ([[gridItem button] isEqual:sender]) - [gridItem model]->Activate(0); - } -} - -- (AppsGridViewItem*)itemAtPageIndex:(size_t)pageIndex - indexInPage:(size_t)indexInPage { - return base::mac::ObjCCastStrict<AppsGridViewItem>( - [[self collectionViewAtPageIndex:pageIndex] itemAtIndex:indexInPage]); -} - -- (AppsGridViewItem*)itemAtIndex:(size_t)itemIndex { - const size_t pageIndex = itemIndex / ItemsPerPage(); - return [self itemAtPageIndex:pageIndex - indexInPage:itemIndex - pageIndex * ItemsPerPage()]; -} - -- (NSUInteger)selectedItemIndex { - NSCollectionView* page = [self collectionViewAtPageIndex:visiblePage_]; - NSUInteger indexOnPage = [[page selectionIndexes] firstIndex]; - if (indexOnPage == NSNotFound) - return NSNotFound; - - return indexOnPage + visiblePage_ * ItemsPerPage(); -} - -- (NSButton*)selectedButton { - NSUInteger index = [self selectedItemIndex]; - if (index == NSNotFound) - return nil; - - return [[self itemAtIndex:index] button]; -} - -- (NSScrollView*)gridScrollView { - return base::mac::ObjCCastStrict<NSScrollView>([self view]); -} - -- (NSView*)pagesContainerView { - return [[self gridScrollView] documentView]; -} - -- (void)updatePages:(size_t)startItemIndex { - // Note there is always at least one page. - size_t targetPages = 1; - if ([items_ count] != 0) - targetPages = ([items_ count] - 1) / ItemsPerPage() + 1; - - const size_t currentPages = [self pageCount]; - // First see if the number of pages have changed. - if (targetPages != currentPages) { - if (targetPages < currentPages) { - // Pages need to be removed. - [pages_ removeObjectsInRange:NSMakeRange(targetPages, - currentPages - targetPages)]; - } else { - // Pages need to be added. - for (size_t i = currentPages; i < targetPages; ++i) { - NSRect pageFrame = NSMakeRect(kLeftRightPadding + kViewWidth * i, 0, - kViewWidth, ViewHeight()); - [pages_ addObject:[dragManager_ makePageWithFrame:pageFrame]]; - } - } - - [[self pagesContainerView] setSubviews:pages_]; - NSSize pagesSize = NSMakeSize(kViewWidth * targetPages, ViewHeight()); - [[self pagesContainerView] setFrameSize:pagesSize]; - [paginationObserver_ totalPagesChanged]; - } - - const size_t startPage = startItemIndex / ItemsPerPage(); - // All pages on or after |startPage| may need items added or removed. - for (size_t pageIndex = startPage; pageIndex < targetPages; ++pageIndex) { - [self updatePageContent:pageIndex - resetModel:YES]; - } -} - -- (void)updatePageContent:(size_t)pageIndex - resetModel:(BOOL)resetModel { - NSCollectionView* pageView = [self collectionViewAtPageIndex:pageIndex]; - if (resetModel) { - // Clear the models first, otherwise removed items could be autoreleased at - // an unknown point in the future, when the model owner may have gone away. - for (size_t i = 0; i < [[pageView content] count]; ++i) { - AppsGridViewItem* gridItem = base::mac::ObjCCastStrict<AppsGridViewItem>( - [pageView itemAtIndex:i]); - [gridItem setModel:NULL]; - } - } - - NSRange inPageRange = NSIntersectionRange( - NSMakeRange(pageIndex * ItemsPerPage(), ItemsPerPage()), - NSMakeRange(0, [items_ count])); - NSArray* pageContent = [items_ subarrayWithRange:inPageRange]; - [pageView setContent:pageContent]; - if (!resetModel) - return; - - for (size_t i = 0; i < [pageContent count]; ++i) { - AppsGridViewItem* gridItem = base::mac::ObjCCastStrict<AppsGridViewItem>( - [pageView itemAtIndex:i]); - [gridItem setModel:static_cast<app_list::AppListItem*>( - [[pageContent objectAtIndex:i] pointerValue])]; - } -} - -- (void)moveItemInView:(size_t)fromIndex - toItemIndex:(size_t)toIndex { - base::scoped_nsobject<NSValue> item( - [[items_ objectAtIndex:fromIndex] retain]); - [items_ removeObjectAtIndex:fromIndex]; - [items_ insertObject:item - atIndex:toIndex]; - - size_t fromPageIndex = fromIndex / ItemsPerPage(); - size_t toPageIndex = toIndex / ItemsPerPage(); - if (fromPageIndex == toPageIndex) { - [self updatePageContent:fromPageIndex - resetModel:NO]; // Just reorder items. - return; - } - - if (fromPageIndex > toPageIndex) - std::swap(fromPageIndex, toPageIndex); - - for (size_t i = fromPageIndex; i <= toPageIndex; ++i) { - [self updatePageContent:i - resetModel:YES]; - } -} - -// Compare with views implementation in AppsGridView::MoveItemInModel(). -- (void)moveItemWithIndex:(size_t)itemIndex - toModelIndex:(size_t)modelIndex { - // Ingore no-op moves. Note that this is always the case when canceled. - if (itemIndex == modelIndex) - return; - - app_list::AppListItemList* itemList = [self model]->top_level_item_list(); - itemList->RemoveObserver(bridge_.get()); - itemList->MoveItem(itemIndex, modelIndex); - itemList->AddObserver(bridge_.get()); -} - -- (AppsCollectionViewDragManager*)dragManager { - return dragManager_; -} - -- (size_t)scheduledScrollPage { - return scheduledScrollPage_; -} - -- (void)listItemAdded:(size_t)index - item:(app_list::AppListItem*)itemModel { - // Cancel any drag, to ensure the model stays consistent. - [dragManager_ cancelDrag]; - - [items_ insertObject:[NSValue valueWithPointer:itemModel] - atIndex:index]; - - [self updatePages:index]; -} - -- (void)listItemRemoved:(size_t)index { - [dragManager_ cancelDrag]; - - // Clear the models explicitly to avoid surprises from autorelease. - [[self itemAtIndex:index] setModel:NULL]; - - [items_ removeObjectsInRange:NSMakeRange(index, 1)]; - [self updatePages:index]; -} - -- (void)listItemMovedFromIndex:(size_t)fromIndex - toModelIndex:(size_t)toIndex { - [dragManager_ cancelDrag]; - [self moveItemInView:fromIndex - toItemIndex:toIndex]; -} - -- (CGFloat)visiblePortionOfPage:(int)page { - CGFloat scrollOffsetOfPage = - NSMinX([[[self gridScrollView] contentView] bounds]) / kViewWidth - page; - if (scrollOffsetOfPage <= -1.0 || scrollOffsetOfPage >= 1.0) - return 0.0; - - if (scrollOffsetOfPage <= 0.0) - return scrollOffsetOfPage + 1.0; - - return -1.0 + scrollOffsetOfPage; -} - -- (void)onPagerClicked:(AppListPagerView*)sender { - int selectedSegment = [sender selectedSegment]; - if (selectedSegment < 0) - return; // No selection. - - int pageIndex = [[sender cell] tagForSegment:selectedSegment]; - if (pageIndex >= 0) - [self scrollToPage:pageIndex]; -} - -- (BOOL)moveSelectionByDelta:(int)indexDelta { - if (indexDelta == 0) - return NO; - - NSUInteger oldIndex = [self selectedItemIndex]; - - // If nothing is currently selected, select the first item on the page. - if (oldIndex == NSNotFound) { - [self selectItemAtIndex:visiblePage_ * ItemsPerPage()]; - return YES; - } - - // Can't select a negative index. - if (indexDelta < 0 && static_cast<NSUInteger>(-indexDelta) > oldIndex) - return NO; - - // Can't select an index greater or equal to the number of items. - if (oldIndex + indexDelta >= [items_ count]) { - if (visiblePage_ == [pages_ count] - 1) - return NO; - - // If we're not on the last page, then select the last item. - [self selectItemAtIndex:[items_ count] - 1]; - return YES; - } - - [self selectItemAtIndex:oldIndex + indexDelta]; - return YES; -} - -- (void)selectItemAtIndex:(NSUInteger)index { - if (index >= [items_ count]) - return; - - if (index / ItemsPerPage() != visiblePage_) - [self scrollToPage:index / ItemsPerPage()]; - - [[self itemAtIndex:index] setSelected:YES]; -} - -- (BOOL)handleCommandBySelector:(SEL)command { - if (command == @selector(insertNewline:) || - command == @selector(insertLineBreak:)) { - [self activateSelection]; - return YES; - } - - NSUInteger oldIndex = [self selectedItemIndex]; - // If nothing is currently selected, select the first item on the page. - if (oldIndex == NSNotFound) { - [self selectItemAtIndex:visiblePage_ * ItemsPerPage()]; - return YES; - } - - if (command == @selector(moveLeft:)) { - return oldIndex % kFixedColumns == 0 - ? [self moveSelectionByDelta:-ItemsPerPage() + kFixedColumns - 1] - : [self moveSelectionByDelta:-1]; - } - - if (command == @selector(moveRight:)) { - return oldIndex % kFixedColumns == kFixedColumns - 1 - ? [self moveSelectionByDelta:+ItemsPerPage() - kFixedColumns + 1] - : [self moveSelectionByDelta:1]; - } - - if (command == @selector(moveUp:)) { - return oldIndex / kFixedColumns % RowCount() == 0 - ? NO - : [self moveSelectionByDelta:-kFixedColumns]; - } - - if (command == @selector(moveDown:)) { - return oldIndex / kFixedColumns % RowCount() == RowCount() - 1 - ? NO - : [self moveSelectionByDelta:kFixedColumns]; - } - - if (command == @selector(pageUp:) || - command == @selector(scrollPageUp:)) - return [self moveSelectionByDelta:-ItemsPerPage()]; - - if (command == @selector(pageDown:) || - command == @selector(scrollPageDown:)) - return [self moveSelectionByDelta:ItemsPerPage()]; - - return NO; -} - -@end
diff --git a/ui/app_list/cocoa/apps_grid_controller_unittest.mm b/ui/app_list/cocoa/apps_grid_controller_unittest.mm deleted file mode 100644 index 357eb465..0000000 --- a/ui/app_list/cocoa/apps_grid_controller_unittest.mm +++ /dev/null
@@ -1,979 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "base/strings/utf_string_conversions.h" -#include "skia/ext/skia_utils_mac.h" -#import "testing/gtest_mac.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_item.h" -#import "ui/app_list/cocoa/apps_collection_view_drag_manager.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#import "ui/app_list/cocoa/apps_grid_view_item.h" -#import "ui/app_list/cocoa/apps_pagination_model_observer.h" -#import "ui/app_list/cocoa/test/apps_grid_controller_test_helper.h" -#include "ui/app_list/test/app_list_test_model.h" -#include "ui/app_list/test/app_list_test_view_delegate.h" -#include "ui/base/models/simple_menu_model.h" -#import "ui/events/test/cocoa_test_event_utils.h" - -@interface TestPaginationObserver : NSObject<AppsPaginationModelObserver> { - @private - NSInteger hoveredSegmentForTest_; - int totalPagesChangedCount_; - int selectedPageChangedCount_; - int lastNewSelectedPage_; - bool visibilityDidChange_; -} - -@property(assign, nonatomic) NSInteger hoveredSegmentForTest; -@property(assign, nonatomic) int totalPagesChangedCount; -@property(assign, nonatomic) int selectedPageChangedCount; -@property(assign, nonatomic) int lastNewSelectedPage; - -- (bool)readVisibilityDidChange; - -@end - -@implementation TestPaginationObserver - -@synthesize hoveredSegmentForTest = hoveredSegmentForTest_; -@synthesize totalPagesChangedCount = totalPagesChangedCount_; -@synthesize selectedPageChangedCount = selectedPageChangedCount_; -@synthesize lastNewSelectedPage = lastNewSelectedPage_; - -- (id)init { - if ((self = [super init])) - hoveredSegmentForTest_ = -1; - - return self; -} - -- (bool)readVisibilityDidChange { - bool truth = visibilityDidChange_; - visibilityDidChange_ = false; - return truth; -} - -- (void)totalPagesChanged { - ++totalPagesChangedCount_; -} - -- (void)selectedPageChanged:(int)newSelected { - ++selectedPageChangedCount_; - lastNewSelectedPage_ = newSelected; -} - -- (void)pageVisibilityChanged { - visibilityDidChange_ = true; -} - -- (NSInteger)pagerSegmentAtLocation:(NSPoint)locationInWindow { - return hoveredSegmentForTest_; -} - -@end - -namespace app_list { -namespace test { - -namespace { - -class AppsGridControllerTest : public AppsGridControllerTestHelper { - public: - AppsGridControllerTest() {} - - AppListTestViewDelegate* delegate() { - return owned_delegate_.get(); - } - - NSColor* ButtonTitleColorAt(size_t index) { - NSDictionary* attributes = - [[[GetItemViewAt(index) cell] attributedTitle] attributesAtIndex:0 - effectiveRange:NULL]; - return [attributes objectForKey:NSForegroundColorAttributeName]; - } - - void SetUp() override { - owned_apps_grid_controller_.reset([[AppsGridController alloc] init]); - owned_delegate_.reset(new AppListTestViewDelegate); - [owned_apps_grid_controller_ setDelegate:owned_delegate_.get()]; - AppsGridControllerTestHelper::SetUpWithGridController( - owned_apps_grid_controller_.get()); - - [[test_window() contentView] addSubview:[apps_grid_controller_ view]]; - [test_window() makePretendKeyWindowAndSetFirstResponder: - [apps_grid_controller_ collectionViewAtPageIndex:0]]; - } - - void TearDown() override { - [owned_apps_grid_controller_ setDelegate:NULL]; - owned_apps_grid_controller_.reset(); - AppsGridControllerTestHelper::TearDown(); - } - - void ReplaceTestModel(int item_count) { - // Clear the delegate before reseting and destroying the model. - [owned_apps_grid_controller_ setDelegate:NULL]; - - owned_delegate_->ReplaceTestModel(item_count); - [owned_apps_grid_controller_ setDelegate:owned_delegate_.get()]; - } - - AppListTestModel* model() { return owned_delegate_->GetTestModel(); } - - private: - base::scoped_nsobject<AppsGridController> owned_apps_grid_controller_; - std::unique_ptr<AppListTestViewDelegate> owned_delegate_; - - DISALLOW_COPY_AND_ASSIGN(AppsGridControllerTest); -}; - -class AppListItemWithMenu : public AppListItem { - public: - explicit AppListItemWithMenu(const std::string& id) - : AppListItem(id), - menu_model_(NULL), - menu_ready_(true) { - SetName(id); - menu_model_.AddItem(0, base::UTF8ToUTF16("Menu For: " + id)); - } - - void SetMenuReadyForTesting(bool ready) { - menu_ready_ = ready; - } - - ui::MenuModel* GetContextMenuModel() override { - if (!menu_ready_) - return NULL; - - return &menu_model_; - } - - private: - ui::SimpleMenuModel menu_model_; - bool menu_ready_; - - DISALLOW_COPY_AND_ASSIGN(AppListItemWithMenu); -}; - -// Generate a mouse event at the centre of the view in |page| with the given -// |index_in_page| that can be used to initiate, update and complete drag -// operations. -NSEvent* MouseEventInCell(NSCollectionView* page, size_t index_in_page) { - NSRect cell_rect = [page frameForItemAtIndex:index_in_page]; - NSPoint point_in_view = NSMakePoint(NSMidX(cell_rect), NSMidY(cell_rect)); - NSPoint point_in_window = [page convertPoint:point_in_view - toView:nil]; - return cocoa_test_event_utils::LeftMouseDownAtPoint(point_in_window); -} - -NSEvent* MouseEventForScroll(NSView* view, CGFloat relative_x) { - NSRect view_rect = [view frame]; - NSPoint point_in_view = NSMakePoint(NSMidX(view_rect), NSMidY(view_rect)); - point_in_view.x += point_in_view.x * relative_x; - NSPoint point_in_window = [view convertPoint:point_in_view - toView:nil]; - return cocoa_test_event_utils::LeftMouseDownAtPoint(point_in_window); -} - -} // namespace - -TEST_VIEW(AppsGridControllerTest, [apps_grid_controller_ view]); - -// Test showing with an empty model. -TEST_F(AppsGridControllerTest, EmptyModelAndShow) { - EXPECT_TRUE([[apps_grid_controller_ view] superview]); - - // First page should always exist, even if empty. - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(0u, [[GetPageAt(0) content] count]); - EXPECT_TRUE([GetPageAt(0) superview]); // The pages container. - EXPECT_TRUE([[GetPageAt(0) superview] superview]); -} - -// Test with a single item. -// This test is disabled in builders until the delay to wait for the collection -// view to load subviews can be removed, or some other solution is found. -TEST_F(AppsGridControllerTest, DISABLED_SingleEntryModel) { - // We need to "wake up" the NSCollectionView, otherwise it does not - // immediately update its subviews later in this function. - // When this test is run by itself, it's enough just to send a keypress (and - // this delay is not needed). - DelayForCollectionView(); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(0u, [[GetPageAt(0) content] count]); - - model()->PopulateApps(1); - SinkEvents(); - EXPECT_FALSE([GetPageAt(0) animations]); - - EXPECT_EQ(1u, [[GetPageAt(0) content] count]); - NSArray* subviews = [GetPageAt(0) subviews]; - EXPECT_EQ(1u, [subviews count]); - - // Note that using GetItemViewAt(0) here also works, and returns non-nil even - // without the delay, but a "click" on it does not register without the delay. - NSView* subview = [subviews objectAtIndex:0]; - - // Launch the item. - SimulateClick(subview); - SinkEvents(); - EXPECT_EQ(1, model()->activate_count()); - ASSERT_TRUE(model()->last_activated()); - EXPECT_EQ(std::string("Item 0"), model()->last_activated()->name()); -} - -// Test activating an item on the second page (the 17th item). -TEST_F(AppsGridControllerTest, DISABLED_TwoPageModel) { - DelayForCollectionView(); - ReplaceTestModel(kItemsPerPage * 2); - [apps_grid_controller_ scrollToPage:1]; - - // The NSScrollView animator ignores the duration configured on the - // NSAnimationContext (set by CocoaTest::Init), so we need to delay here. - DelayForCollectionView(); - NSArray* subviews = [GetPageAt(1) subviews]; - NSView* subview = [subviews objectAtIndex:0]; - // Launch the item. - SimulateClick(subview); - SinkEvents(); - EXPECT_EQ(1, model()->activate_count()); - ASSERT_TRUE(model()->last_activated()); - EXPECT_EQ(std::string("Item 16"), model()->last_activated()->name()); -} - -// Test setModel. -TEST_F(AppsGridControllerTest, ReplaceModel) { - const size_t kOrigItems = 1; - const size_t kNewItems = 2; - - model()->PopulateApps(kOrigItems); - EXPECT_EQ(kOrigItems, [[GetPageAt(0) content] count]); - - ReplaceTestModel(kNewItems); - EXPECT_EQ(kNewItems, [[GetPageAt(0) content] count]); -} - -// Test pagination. -TEST_F(AppsGridControllerTest, Pagination) { - model()->PopulateApps(1); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(1u, [[GetPageAt(0) content] count]); - - ReplaceTestModel(kItemsPerPage); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(kItemsPerPage, [[GetPageAt(0) content] count]); - - // Test adding an item onto the next page. - model()->PopulateApps(1); // Now 17 items. - EXPECT_EQ(2u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(kItemsPerPage, [[GetPageAt(0) content] count]); - EXPECT_EQ(1u, [[GetPageAt(1) content] count]); - - // Test N pages with the last page having one empty spot. - const size_t kPagesToTest = 3; - ReplaceTestModel(kPagesToTest * kItemsPerPage - 1); - EXPECT_EQ(kPagesToTest, [apps_grid_controller_ pageCount]); - for (size_t page_index = 0; page_index < kPagesToTest - 1; ++page_index) { - EXPECT_EQ(kItemsPerPage, [[GetPageAt(page_index) content] count]); - } - EXPECT_EQ(kItemsPerPage - 1, [[GetPageAt(kPagesToTest - 1) content] count]); - - // Test removing pages. - ReplaceTestModel(1); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(1u, [[GetPageAt(0) content] count]); -} - -// Tests basic keyboard navigation on the first page. -TEST_F(AppsGridControllerTest, FirstPageKeyboardNavigation) { - model()->PopulateApps(kItemsPerPage - 2); - EXPECT_EQ(kItemsPerPage - 2, [[GetPageAt(0) content] count]); - - SimulateKeyAction(@selector(moveRight:)); - EXPECT_EQ(0u, [apps_grid_controller_ selectedItemIndex]); - - SimulateKeyAction(@selector(moveRight:)); - EXPECT_EQ(1u, [apps_grid_controller_ selectedItemIndex]); - - SimulateKeyAction(@selector(moveDown:)); - EXPECT_EQ(5u, [apps_grid_controller_ selectedItemIndex]); - - SimulateKeyAction(@selector(moveLeft:)); - EXPECT_EQ(4u, [apps_grid_controller_ selectedItemIndex]); - - SimulateKeyAction(@selector(moveUp:)); - EXPECT_EQ(0u, [apps_grid_controller_ selectedItemIndex]); - - // Go to the third item, and launch it. - SimulateKeyAction(@selector(moveRight:)); - SimulateKeyAction(@selector(moveRight:)); - EXPECT_EQ(2u, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(insertNewline:)); - EXPECT_EQ(1, model()->activate_count()); - ASSERT_TRUE(model()->last_activated()); - EXPECT_EQ(std::string("Item 2"), model()->last_activated()->name()); -} - -// Tests keyboard navigation across pages. -TEST_F(AppsGridControllerTest, CrossPageKeyboardNavigation) { - model()->PopulateApps(kItemsPerPage + 10); - EXPECT_EQ(kItemsPerPage, [[GetPageAt(0) content] count]); - EXPECT_EQ(10u, [[GetPageAt(1) content] count]); - - // Moving Left, Up, or PageUp from the top-left corner of the first page does - // nothing. - [apps_grid_controller_ selectItemAtIndex:0]; - SimulateKeyAction(@selector(moveLeft:)); - EXPECT_EQ(0u, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(moveUp:)); - EXPECT_EQ(0u, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(scrollPageUp:)); - EXPECT_EQ(0u, [apps_grid_controller_ selectedItemIndex]); - - // Moving Right from the right side goes to the next page. Moving Left goes - // back to the first page. - [apps_grid_controller_ selectItemAtIndex:3]; - SimulateKeyAction(@selector(moveRight:)); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(kItemsPerPage, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(moveLeft:)); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(3u, [apps_grid_controller_ selectedItemIndex]); - - // Moving Down from the bottom does nothing. - [apps_grid_controller_ selectItemAtIndex:13]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - SimulateKeyAction(@selector(moveDown:)); - EXPECT_EQ(13u, [apps_grid_controller_ selectedItemIndex]); - - // Moving Right into a non-existent square on the next page will select the - // last item. - [apps_grid_controller_ selectItemAtIndex:15]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - SimulateKeyAction(@selector(moveRight:)); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(kItemsPerPage + 9, [apps_grid_controller_ selectedItemIndex]); - - // PageDown and PageUp switches pages while maintaining the same selection - // position. - [apps_grid_controller_ selectItemAtIndex:6]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - SimulateKeyAction(@selector(scrollPageDown:)); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(kItemsPerPage + 6, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(scrollPageUp:)); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(6u, [apps_grid_controller_ selectedItemIndex]); - - // PageDown into a non-existent square on the next page will select the last - // item. - [apps_grid_controller_ selectItemAtIndex:11]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - SimulateKeyAction(@selector(scrollPageDown:)); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(kItemsPerPage + 9, [apps_grid_controller_ selectedItemIndex]); - - // Moving Right, Down, or PageDown from the bottom-right corner of the last - // page (not the last item) does nothing. - [apps_grid_controller_ selectItemAtIndex:kItemsPerPage + 9]; - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - SimulateKeyAction(@selector(moveRight:)); - EXPECT_EQ(kItemsPerPage + 9, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(moveDown:)); - EXPECT_EQ(kItemsPerPage + 9, [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(scrollPageDown:)); - EXPECT_EQ(kItemsPerPage + 9, [apps_grid_controller_ selectedItemIndex]); - - // After page switch, arrow keys select first item on current page. - [apps_grid_controller_ scrollToPage:0]; - [apps_grid_controller_ scrollToPage:1]; - EXPECT_EQ(static_cast<NSUInteger>(NSNotFound), - [apps_grid_controller_ selectedItemIndex]); - SimulateKeyAction(@selector(moveUp:)); - EXPECT_EQ(kItemsPerPage, [apps_grid_controller_ selectedItemIndex]); -} - -// Highlighting an item should cause the page it's on to be visible. -TEST_F(AppsGridControllerTest, EnsureHighlightedVisible) { - model()->PopulateApps(3 * kItemsPerPage); - EXPECT_EQ(kItemsPerPage, [[GetPageAt(2) content] count]); - - // First and last items of first page. - [apps_grid_controller_ selectItemAtIndex:0]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - [apps_grid_controller_ selectItemAtIndex:kItemsPerPage - 1]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - - // First item of second page. - [apps_grid_controller_ selectItemAtIndex:kItemsPerPage + 1]; - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - - // Last item in model. - [apps_grid_controller_ selectItemAtIndex:3 * kItemsPerPage - 1]; - EXPECT_EQ(2u, [apps_grid_controller_ visiblePage]); -} - -// Test runtime updates: adding items, removing items, and moving items (e.g. in -// response to app install, uninstall, and chrome sync changes. Also test -// changing titles and icons. -TEST_F(AppsGridControllerTest, ModelUpdate) { - model()->PopulateApps(2); - EXPECT_EQ(2u, [[GetPageAt(0) content] count]); - EXPECT_EQ(std::string("|Item 0,Item 1|"), GetViewContent()); - - // Add an item (PopulateApps will create a new "Item 2"). - model()->PopulateApps(1); - EXPECT_EQ(3u, [[GetPageAt(0) content] count]); - NSButton* button = GetItemViewAt(2); - EXPECT_NSEQ(@"Item 2", [button title]); - EXPECT_EQ(std::string("|Item 0,Item 1,Item 2|"), GetViewContent()); - - // Update the title via the ItemModelObserver. - app_list::AppListItem* item_model = - model()->top_level_item_list()->item_at(2); - model()->SetItemName(item_model, "UpdatedItem"); - EXPECT_NSEQ(@"UpdatedItem", [button title]); - - // Test icon updates through the model observer by ensuring the icon changes. - item_model->SetIcon(gfx::ImageSkia()); - NSSize icon_size = [[button image] size]; - EXPECT_EQ(0, icon_size.width); - EXPECT_EQ(0, icon_size.height); - - SkBitmap bitmap; - const int kTestImageSize = 10; - const int kTargetImageSize = 48; - bitmap.setInfo(SkImageInfo::MakeN32Premul(kTestImageSize, kTestImageSize)); - item_model->SetIcon(gfx::ImageSkia::CreateFrom1xBitmap(bitmap)); - icon_size = [[button image] size]; - // Icon should always be resized to 48x48. - EXPECT_EQ(kTargetImageSize, icon_size.width); - EXPECT_EQ(kTargetImageSize, icon_size.height); -} - -TEST_F(AppsGridControllerTest, ModelAdd) { - model()->PopulateApps(2); - EXPECT_EQ(2u, [[GetPageAt(0) content] count]); - EXPECT_EQ(std::string("|Item 0,Item 1|"), GetViewContent()); - - app_list::AppListItemList* item_list = model()->top_level_item_list(); - - model()->CreateAndAddItem("Item 2"); - ASSERT_EQ(3u, item_list->item_count()); - EXPECT_EQ(3u, [apps_grid_controller_ itemCount]); - EXPECT_EQ(std::string("|Item 0,Item 1,Item 2|"), GetViewContent()); - - // Test adding an item whose position is in the middle. - app_list::AppListItem* item0 = item_list->item_at(0); - app_list::AppListItem* item1 = item_list->item_at(1); - app_list::AppListItem* item3 = model()->CreateItem("Item Three"); - model()->AddItem(item3); - item_list->SetItemPosition( - item3, item0->position().CreateBetween(item1->position())); - EXPECT_EQ(4u, [apps_grid_controller_ itemCount]); - EXPECT_EQ(std::string("|Item 0,Item Three,Item 1,Item 2|"), GetViewContent()); -} - -TEST_F(AppsGridControllerTest, ModelMove) { - model()->PopulateApps(3); - EXPECT_EQ(3u, [[GetPageAt(0) content] count]); - EXPECT_EQ(std::string("|Item 0,Item 1,Item 2|"), GetViewContent()); - - // Test swapping items (e.g. rearranging via sync). - model()->top_level_item_list()->MoveItem(1, 2); - EXPECT_EQ(std::string("|Item 0,Item 2,Item 1|"), GetViewContent()); -} - -TEST_F(AppsGridControllerTest, ModelRemove) { - model()->PopulateApps(3); - EXPECT_EQ(3u, [[GetPageAt(0) content] count]); - EXPECT_EQ(std::string("|Item 0,Item 1,Item 2|"), GetViewContent()); - - // Test removing an item at the end. - model()->DeleteItem("Item 2"); - EXPECT_EQ(2u, [apps_grid_controller_ itemCount]); - EXPECT_EQ(std::string("|Item 0,Item 1|"), GetViewContent()); - - // Test removing in the middle. - model()->CreateAndAddItem("Item 2"); - EXPECT_EQ(3u, [apps_grid_controller_ itemCount]); - EXPECT_EQ(std::string("|Item 0,Item 1,Item 2|"), GetViewContent()); - model()->DeleteItem("Item 1"); - EXPECT_EQ(2u, [apps_grid_controller_ itemCount]); - EXPECT_EQ(std::string("|Item 0,Item 2|"), GetViewContent()); -} - -TEST_F(AppsGridControllerTest, ModelRemoveSeveral) { - model()->PopulateApps(3); - EXPECT_EQ(3u, [[GetPageAt(0) content] count]); - EXPECT_EQ(std::string("|Item 0,Item 1,Item 2|"), GetViewContent()); - - // Test removing multiple items via the model. - model()->DeleteItem("Item 0"); - model()->DeleteItem("Item 1"); - model()->DeleteItem("Item 2"); - EXPECT_EQ(0u, [apps_grid_controller_ itemCount]); - EXPECT_EQ(std::string("||"), GetViewContent()); -} - -TEST_F(AppsGridControllerTest, ModelRemovePage) { - app_list::AppListItemList* item_list = model()->top_level_item_list(); - - model()->PopulateApps(kItemsPerPage + 1); - ASSERT_EQ(kItemsPerPage + 1, item_list->item_count()); - EXPECT_EQ(kItemsPerPage + 1, [apps_grid_controller_ itemCount]); - EXPECT_EQ(2u, [apps_grid_controller_ pageCount]); - - // Test removing the last item when there is one item on the second page. - app_list::AppListItem* last_item = item_list->item_at(kItemsPerPage); - model()->DeleteItem(last_item->id()); - EXPECT_EQ(kItemsPerPage, item_list->item_count()); - EXPECT_EQ(kItemsPerPage, [apps_grid_controller_ itemCount]); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); -} - -// Test install progress bars, and install flow with item highlighting. -TEST_F(AppsGridControllerTest, ItemInstallProgress) { - ReplaceTestModel(kItemsPerPage + 1); - EXPECT_EQ(2u, [apps_grid_controller_ pageCount]); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - // The single item on the second page. - int kTestItemIndex = kItemsPerPage; - app_list::AppListItem* item_model = - model()->top_level_item_list()->item_at(kTestItemIndex); - - // Highlighting an item should activate the page it is on. - model()->HighlightItemAt(kTestItemIndex); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - - // Starting install should add a progress bar, and temporarily clear the - // button title. - NSButton* button = GetItemViewAt(kTestItemIndex); - NSView* containerView = [button superview]; - EXPECT_EQ(1u, [[containerView subviews] count]); - EXPECT_NSEQ(@"Item 16", [button title]); - model()->HighlightItemAt(kTestItemIndex); - item_model->SetIsInstalling(true); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - - EXPECT_EQ(2u, [[containerView subviews] count]); - EXPECT_NSEQ(@"", [button title]); - NSProgressIndicator* progressIndicator = - [[containerView subviews] objectAtIndex:1]; - EXPECT_FALSE([progressIndicator isIndeterminate]); - EXPECT_EQ(0.0, [progressIndicator doubleValue]); - - // Updating the progress in the model should update the progress bar. - item_model->SetPercentDownloaded(50); - EXPECT_EQ(50.0, [progressIndicator doubleValue]); - - // Two things can be installing simultaneously. When one starts or completes - // the model builder will ask for the item to be highlighted. - const int kAlternateTestItemIndex = 0; - model()->HighlightItemAt(kAlternateTestItemIndex); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - - // Update the first item (page doesn't change on updates). - item_model->SetPercentDownloaded(100); - EXPECT_EQ(100.0, [progressIndicator doubleValue]); - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - - // A percent of -1 indicates the download is complete and the unpack/install - // process has started. - item_model->SetPercentDownloaded(-1); - EXPECT_TRUE([progressIndicator isIndeterminate]); - - // Completing install removes the progress bar, and restores the title. - // ExtensionAppModelBuilder will reload the ExtensionAppItem, which also - // highlights. Do the same here. - model()->HighlightItemAt(kTestItemIndex); - item_model->SetIsInstalling(false); - EXPECT_EQ(1u, [[containerView subviews] count]); - EXPECT_NSEQ(@"Item 16", [button title]); - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - - // Things should cleanup OK with |alternate_item_model| left installing. -} - -// Test mouseover selection. -TEST_F(AppsGridControllerTest, MouseoverSelects) { - model()->PopulateApps(2); - EXPECT_EQ(nil, GetSelectedView()); - - // Test entering and exiting the first item. - SimulateMouseEnterItemAt(0); - EXPECT_EQ(GetItemViewAt(0), GetSelectedView()); - SimulateMouseExitItemAt(0); - EXPECT_EQ(nil, GetSelectedView()); - - // AppKit doesn't guarantee the order, so test moving between items. - SimulateMouseEnterItemAt(0); - EXPECT_EQ(GetItemViewAt(0), GetSelectedView()); - SimulateMouseEnterItemAt(1); - EXPECT_EQ(GetItemViewAt(1), GetSelectedView()); - SimulateMouseExitItemAt(0); - EXPECT_EQ(GetItemViewAt(1), GetSelectedView()); - SimulateMouseExitItemAt(1); - EXPECT_EQ(nil, GetSelectedView()); -} - -// Test AppsGridPaginationObserver totalPagesChanged(). -TEST_F(AppsGridControllerTest, PaginationObserverPagesChanged) { - base::scoped_nsobject<TestPaginationObserver> observer( - [[TestPaginationObserver alloc] init]); - [apps_grid_controller_ setPaginationObserver:observer]; - - // Test totalPagesChanged. - model()->PopulateApps(kItemsPerPage); - EXPECT_EQ(0, [observer totalPagesChangedCount]); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - model()->PopulateApps(1); - EXPECT_EQ(1, [observer totalPagesChangedCount]); - EXPECT_EQ(2u, [apps_grid_controller_ pageCount]); - ReplaceTestModel(0); - EXPECT_EQ(2, [observer totalPagesChangedCount]); - EXPECT_EQ(1u, [apps_grid_controller_ pageCount]); - ReplaceTestModel(kItemsPerPage * 3 + 1); - EXPECT_EQ(3, [observer totalPagesChangedCount]); - EXPECT_EQ(4u, [apps_grid_controller_ pageCount]); - - EXPECT_FALSE([observer readVisibilityDidChange]); - EXPECT_EQ(0, [observer selectedPageChangedCount]); - - [apps_grid_controller_ setPaginationObserver:nil]; -} - -// Test AppsGridPaginationObserver selectedPageChanged(). -TEST_F(AppsGridControllerTest, PaginationObserverSelectedPageChanged) { - base::scoped_nsobject<TestPaginationObserver> observer( - [[TestPaginationObserver alloc] init]); - [apps_grid_controller_ setPaginationObserver:observer]; - EXPECT_EQ(0, [[NSAnimationContext currentContext] duration]); - - ReplaceTestModel(kItemsPerPage * 3 + 1); - EXPECT_EQ(1, [observer totalPagesChangedCount]); - EXPECT_EQ(4u, [apps_grid_controller_ pageCount]); - - EXPECT_FALSE([observer readVisibilityDidChange]); - EXPECT_EQ(0, [observer selectedPageChangedCount]); - - [apps_grid_controller_ scrollToPage:1]; - EXPECT_EQ(1, [observer selectedPageChangedCount]); - EXPECT_EQ(1, [observer lastNewSelectedPage]); - EXPECT_TRUE([observer readVisibilityDidChange]); - EXPECT_FALSE([observer readVisibilityDidChange]); // Testing test behaviour. - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:0]); - EXPECT_EQ(1.0, [apps_grid_controller_ visiblePortionOfPage:1]); - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:2]); - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:3]); - - [apps_grid_controller_ scrollToPage:0]; - EXPECT_EQ(2, [observer selectedPageChangedCount]); - EXPECT_EQ(0, [observer lastNewSelectedPage]); - EXPECT_TRUE([observer readVisibilityDidChange]); - EXPECT_EQ(1.0, [apps_grid_controller_ visiblePortionOfPage:0]); - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:1]); - - [apps_grid_controller_ scrollToPage:3]; - // Note: with no animations, there is only a single page change. However, with - // animations we expect multiple updates depending on the rate that the scroll - // view updates and sends out NSViewBoundsDidChangeNotification. - EXPECT_EQ(3, [observer selectedPageChangedCount]); - EXPECT_EQ(3, [observer lastNewSelectedPage]); - EXPECT_TRUE([observer readVisibilityDidChange]); - EXPECT_EQ(0.0, [apps_grid_controller_ visiblePortionOfPage:0]); - EXPECT_EQ(1.0, [apps_grid_controller_ visiblePortionOfPage:3]); - - [apps_grid_controller_ setPaginationObserver:nil]; -} - -// Test basic item moves with two items; swapping them around, dragging outside -// of the view bounds, and dragging on the background. -TEST_F(AppsGridControllerTest, DragAndDropSimple) { - model()->PopulateApps(2); - NSCollectionView* page = [apps_grid_controller_ collectionViewAtPageIndex:0]; - NSEvent* mouse_at_cell_0 = MouseEventInCell(page, 0); - NSEvent* mouse_at_cell_1 = MouseEventInCell(page, 1); - NSEvent* mouse_at_page_centre = MouseEventInCell(page, 6); - NSEvent* mouse_off_page = MouseEventInCell(page, kItemsPerPage * 2); - - const std::string kOrdered = "Item 0,Item 1"; - const std::string kSwapped = "Item 1,Item 0"; - const std::string kOrderedView = "|Item 0,Item 1|"; - const std::string kSwappedView = "|Item 1,Item 0|"; - - EXPECT_EQ(kOrdered, model()->GetModelContent()); - EXPECT_EQ(kOrderedView, GetViewContent()); - AppsCollectionViewDragManager* drag_manager = - [apps_grid_controller_ dragManager]; - - // Drag first item over the second item and release. - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_0]; - [drag_manager onMouseDragged:mouse_at_cell_1]; - EXPECT_EQ(kOrdered, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); // View swaps first. - [drag_manager onMouseUp:mouse_at_cell_1]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - - // Drag item back. - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_1]; - [drag_manager onMouseDragged:mouse_at_cell_0]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kOrderedView, GetViewContent()); - [drag_manager onMouseUp:mouse_at_cell_0]; - EXPECT_EQ(kOrdered, model()->GetModelContent()); - EXPECT_EQ(kOrderedView, GetViewContent()); - - // Drag first item to centre of view (should put in last place). - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_0]; - [drag_manager onMouseDragged:mouse_at_page_centre]; - EXPECT_EQ(kOrdered, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - [drag_manager onMouseUp:mouse_at_page_centre]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - - // Drag item to centre again (should leave it in the last place). - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_1]; - [drag_manager onMouseDragged:mouse_at_page_centre]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - [drag_manager onMouseUp:mouse_at_page_centre]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - - // Drag starting in the centre of the view, should do nothing. - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_page_centre]; - [drag_manager onMouseDragged:mouse_at_cell_0]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - [drag_manager onMouseUp:mouse_at_cell_0]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - - // Click off page. - [drag_manager onMouseDownInPage:page - withEvent:mouse_off_page]; - [drag_manager onMouseDragged:mouse_at_cell_0]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - [drag_manager onMouseUp:mouse_at_cell_0]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kSwappedView, GetViewContent()); - - // Drag to first over second item, then off page. - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_0]; - [drag_manager onMouseDragged:mouse_at_cell_1]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kOrderedView, GetViewContent()); - [drag_manager onMouseDragged:mouse_off_page]; - EXPECT_EQ(kSwapped, model()->GetModelContent()); - EXPECT_EQ(kOrderedView, GetViewContent()); - [drag_manager onMouseUp:mouse_off_page]; - EXPECT_EQ(kOrdered, model()->GetModelContent()); - EXPECT_EQ(kOrderedView, GetViewContent()); - - // Replace with an empty model, and ensure we do not break. - ReplaceTestModel(0); - EXPECT_EQ(std::string(), model()->GetModelContent()); - EXPECT_EQ(std::string("||"), GetViewContent()); - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_0]; - [drag_manager onMouseDragged:mouse_at_cell_1]; - [drag_manager onMouseUp:mouse_at_cell_1]; - EXPECT_EQ(std::string(), model()->GetModelContent()); - EXPECT_EQ(std::string("||"), GetViewContent()); -} - -// Test item moves between pages. -TEST_F(AppsGridControllerTest, DragAndDropMultiPage) { - const size_t kPagesToTest = 3; - // Put one item on the last page to hit more edge cases. - ReplaceTestModel(kItemsPerPage * (kPagesToTest - 1) + 1); - NSCollectionView* page[kPagesToTest]; - for (size_t i = 0; i < kPagesToTest; ++i) - page[i] = [apps_grid_controller_ collectionViewAtPageIndex:i]; - - const std::string kSecondItemMovedToSecondPage = - "|Item 0,Item 2,Item 3,Item 4,Item 5,Item 6,Item 7,Item 8," - "Item 9,Item 10,Item 11,Item 12,Item 13,Item 14,Item 15,Item 16|" - "|Item 17,Item 1,Item 18,Item 19,Item 20,Item 21,Item 22,Item 23," - "Item 24,Item 25,Item 26,Item 27,Item 28,Item 29,Item 30,Item 31|" - "|Item 32|"; - - NSEvent* mouse_at_cell_0 = MouseEventInCell(page[0], 0); - NSEvent* mouse_at_cell_1 = MouseEventInCell(page[0], 1); - AppsCollectionViewDragManager* drag_manager = - [apps_grid_controller_ dragManager]; - [drag_manager onMouseDownInPage:page[0] - withEvent:mouse_at_cell_1]; - - // Initiate dragging before changing pages. - [drag_manager onMouseDragged:mouse_at_cell_0]; - - // Scroll to the second page. - [apps_grid_controller_ scrollToPage:1]; - [drag_manager onMouseDragged:mouse_at_cell_1]; - - // Do one exhaustive check, and then spot-check corner cases. - EXPECT_EQ(kSecondItemMovedToSecondPage, GetViewContent()); - EXPECT_EQ(0u, GetPageIndexForItem(0)); - EXPECT_EQ(1u, GetPageIndexForItem(1)); - EXPECT_EQ(0u, GetPageIndexForItem(2)); - EXPECT_EQ(0u, GetPageIndexForItem(16)); - EXPECT_EQ(1u, GetPageIndexForItem(17)); - EXPECT_EQ(1u, GetPageIndexForItem(31)); - EXPECT_EQ(2u, GetPageIndexForItem(32)); - - // Scroll to the third page and drag some more. - [apps_grid_controller_ scrollToPage:2]; - [drag_manager onMouseDragged:mouse_at_cell_1]; - EXPECT_EQ(2u, GetPageIndexForItem(1)); - EXPECT_EQ(1u, GetPageIndexForItem(31)); - EXPECT_EQ(1u, GetPageIndexForItem(32)); - - // Scroll backwards. - [apps_grid_controller_ scrollToPage:1]; - [drag_manager onMouseDragged:mouse_at_cell_1]; - EXPECT_EQ(kSecondItemMovedToSecondPage, GetViewContent()); - EXPECT_EQ(1u, GetPageIndexForItem(1)); - EXPECT_EQ(1u, GetPageIndexForItem(31)); - EXPECT_EQ(2u, GetPageIndexForItem(32)); - - // Simulate installing an item while dragging (or have it appear during sync). - model()->PopulateAppWithId(33); - // Item should go back to its position before the drag. - EXPECT_EQ(0u, GetPageIndexForItem(1)); - EXPECT_EQ(1u, GetPageIndexForItem(31)); - EXPECT_EQ(2u, GetPageIndexForItem(32)); - // New item should appear at end. - EXPECT_EQ(2u, GetPageIndexForItem(33)); - - // Scroll to end again, and keep dragging (should be ignored). - [apps_grid_controller_ scrollToPage:2]; - [drag_manager onMouseDragged:mouse_at_cell_0]; - EXPECT_EQ(0u, GetPageIndexForItem(1)); - [drag_manager onMouseUp:mouse_at_cell_0]; - EXPECT_EQ(0u, GetPageIndexForItem(1)); -} - -// Test scrolling when dragging past edge or over the pager. -TEST_F(AppsGridControllerTest, ScrollingWhileDragging) { - base::scoped_nsobject<TestPaginationObserver> observer( - [[TestPaginationObserver alloc] init]); - [apps_grid_controller_ setPaginationObserver:observer]; - - ReplaceTestModel(kItemsPerPage * 3); - // Start on the middle page. - [apps_grid_controller_ scrollToPage:1]; - NSCollectionView* page = [apps_grid_controller_ collectionViewAtPageIndex:1]; - NSEvent* mouse_at_cell_0 = MouseEventInCell(page, 0); - - NSEvent* at_center = MouseEventForScroll([apps_grid_controller_ view], 0.0); - NSEvent* at_left = MouseEventForScroll([apps_grid_controller_ view], -1.1); - NSEvent* at_right = MouseEventForScroll([apps_grid_controller_ view], 1.1); - - AppsCollectionViewDragManager* drag_manager = - [apps_grid_controller_ dragManager]; - [drag_manager onMouseDownInPage:page - withEvent:mouse_at_cell_0]; - [drag_manager onMouseDragged:at_center]; - - // Nothing should be scheduled: target page is visible page. - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(1u, [apps_grid_controller_ scheduledScrollPage]); - - // Drag to the left, should go to first page and no further. - [drag_manager onMouseDragged:at_left]; - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(0u, [apps_grid_controller_ scheduledScrollPage]); - [apps_grid_controller_ scrollToPage:0]; // Commit without timer for testing. - [drag_manager onMouseDragged:at_left]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(0u, [apps_grid_controller_ scheduledScrollPage]); - - // Drag to the right, should go to last page and no futher. - [drag_manager onMouseDragged:at_right]; - EXPECT_EQ(0u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(1u, [apps_grid_controller_ scheduledScrollPage]); - [apps_grid_controller_ scrollToPage:1]; - [drag_manager onMouseDragged:at_right]; - EXPECT_EQ(1u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(2u, [apps_grid_controller_ scheduledScrollPage]); - [apps_grid_controller_ scrollToPage:2]; - [drag_manager onMouseDragged:at_right]; - EXPECT_EQ(2u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(2u, [apps_grid_controller_ scheduledScrollPage]); - - // Simulate a hover over the first pager segment. - [observer setHoveredSegmentForTest:0]; - [drag_manager onMouseDragged:at_center]; - EXPECT_EQ(2u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(0u, [apps_grid_controller_ scheduledScrollPage]); - - // Drag it back, should cancel schedule. - [observer setHoveredSegmentForTest:-1]; - [drag_manager onMouseDragged:at_center]; - EXPECT_EQ(2u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(2u, [apps_grid_controller_ scheduledScrollPage]); - - // Hover again, now over middle segment, and ensure a release also cancels. - [observer setHoveredSegmentForTest:1]; - [drag_manager onMouseDragged:at_center]; - EXPECT_EQ(2u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(1u, [apps_grid_controller_ scheduledScrollPage]); - [drag_manager onMouseUp:at_center]; - EXPECT_EQ(2u, [apps_grid_controller_ visiblePage]); - EXPECT_EQ(2u, [apps_grid_controller_ scheduledScrollPage]); - - [apps_grid_controller_ setPaginationObserver:nil]; -} - -TEST_F(AppsGridControllerTest, ContextMenus) { - AppListItemWithMenu* item_two_model = new AppListItemWithMenu("Item Two"); - model()->AddItem(new AppListItemWithMenu("Item One")); - model()->AddItem(item_two_model); - EXPECT_EQ(2u, [apps_grid_controller_ itemCount]); - - NSCollectionView* page = [apps_grid_controller_ collectionViewAtPageIndex:0]; - NSEvent* mouse_at_cell_0 = MouseEventInCell(page, 0); - NSEvent* mouse_at_cell_1 = MouseEventInCell(page, 1); - - NSMenu* menu = [page menuForEvent:mouse_at_cell_0]; - EXPECT_EQ(1, [menu numberOfItems]); - EXPECT_NSEQ(@"Menu For: Item One", [[menu itemAtIndex:0] title]); - - // Test a context menu request while the item is still installing. - item_two_model->SetMenuReadyForTesting(false); - menu = [page menuForEvent:mouse_at_cell_1]; - EXPECT_EQ(nil, menu); - - item_two_model->SetMenuReadyForTesting(true); - menu = [page menuForEvent:mouse_at_cell_1]; - EXPECT_EQ(1, [menu numberOfItems]); - EXPECT_NSEQ(@"Menu For: Item Two", [[menu itemAtIndex:0] title]); - - // Test that a button being held down with the left button does not also show - // a context menu. - [GetItemViewAt(0) highlight:YES]; - EXPECT_FALSE([page menuForEvent:mouse_at_cell_0]); - [GetItemViewAt(0) highlight:NO]; - EXPECT_TRUE([page menuForEvent:mouse_at_cell_0]); -} - -} // namespace test -} // namespace app_list
diff --git a/ui/app_list/cocoa/apps_grid_view_item.h b/ui/app_list/cocoa/apps_grid_view_item.h deleted file mode 100644 index 8eae04b..0000000 --- a/ui/app_list/cocoa/apps_grid_view_item.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_GRID_VIEW_ITEM_H_ -#define UI_APP_LIST_COCOA_APPS_GRID_VIEW_ITEM_H_ - -#import <Cocoa/Cocoa.h> - -#include <memory> - -#include "ui/app_list/app_list_export.h" -#import "ui/base/cocoa/tracking_area.h" - -namespace app_list { -class AppListItem; -class ItemModelObserverBridge; -} - -// AppsGridViewItem is the controller for an NSButton representing an app item -// on an NSCollectionView controlled by an AppsGridController. -APP_LIST_EXPORT -@interface AppsGridViewItem : NSCollectionViewItem { - @private - std::unique_ptr<app_list::ItemModelObserverBridge> observerBridge_; - base::scoped_nsobject<NSProgressIndicator> progressIndicator_; - - // Used to highlight the background on hover. - ui::ScopedCrTrackingArea trackingArea_; -} - -@property(readonly, nonatomic) NSProgressIndicator* progressIndicator; - -// Designated initializer. |tileSize| is the size of tiles in the grid. -- (id)initWithSize:(NSSize)tileSize; - -// Set the represented model, updating views. Clears if |itemModel| is NULL. -- (void)setModel:(app_list::AppListItem*)itemModel; - -// Model accessor, via the |observerBridge_|. -- (app_list::AppListItem*)model; - -// Return the button portion of the item, showing the icon and title. -- (NSButton*)button; - -// Generate and return a context menu, populated using the represented model. -- (NSMenu*)contextMenu; - -// Take a snapshot of the grid cell with correct layout, then hide the button. -// If |isRestore| is true, the snapshot includes the label and items hidden for -// the initial snapshot are restored. -- (NSBitmapImageRep*)dragRepresentationForRestore:(BOOL)isRestore; - -@end - -#endif // UI_APP_LIST_COCOA_APPS_GRID_VIEW_ITEM_H_
diff --git a/ui/app_list/cocoa/apps_grid_view_item.mm b/ui/app_list/cocoa/apps_grid_view_item.mm deleted file mode 100644 index 9a4198a..0000000 --- a/ui/app_list/cocoa/apps_grid_view_item.mm +++ /dev/null
@@ -1,455 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_grid_view_item.h" - -#include "base/mac/foundation_util.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "base/strings/sys_string_conversions.h" -#include "skia/ext/skia_utils_mac.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_item.h" -#include "ui/app_list/app_list_item_observer.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#import "ui/base/cocoa/menu_controller.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/image/image_skia_util_mac.h" -#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" - -namespace { - -// Padding from the top of the tile to the top of the app icon. -const CGFloat kTileTopPadding = 10; - -const CGFloat kIconSize = 48; - -const CGFloat kProgressBarHorizontalPadding = 8; -const CGFloat kProgressBarVerticalPadding = 13; - -// On Mac, fonts of the same enum from ResourceBundle are larger. The smallest -// enum is already used, so it needs to be reduced further to match Windows. -const int kMacFontSizeDelta = -1; - -} // namespace - -@class AppsGridItemBackgroundView; - -@interface AppsGridViewItem () - -// Typed accessor for the root view. -- (AppsGridItemBackgroundView*)itemBackgroundView; - -// Bridged methods from app_list::AppListItemObserver: -// Update the title, correctly setting the color if the button is highlighted. -- (void)updateButtonTitle; - -// Update the button image after ensuring its dimensions are |kIconSize|. -- (void)updateButtonImage; - -// Add or remove a progress bar from the view. -- (void)setItemIsInstalling:(BOOL)isInstalling; - -// Update the progress bar to represent |percent|, or make it indeterminate if -// |percent| is -1, when unpacking begins. -- (void)setPercentDownloaded:(int)percent; - -@end - -namespace app_list { - -class ItemModelObserverBridge : public app_list::AppListItemObserver { - public: - ItemModelObserverBridge(AppsGridViewItem* parent, AppListItem* model); - ~ItemModelObserverBridge() override; - - AppListItem* model() { return model_; } - NSMenu* GetContextMenu(); - - void ItemIconChanged() override; - void ItemNameChanged() override; - void ItemIsInstallingChanged() override; - void ItemPercentDownloadedChanged() override; - - private: - AppsGridViewItem* parent_; // Weak. Owns us. - AppListItem* model_; // Weak. Owned by AppListModel. - base::scoped_nsobject<MenuController> context_menu_controller_; - - DISALLOW_COPY_AND_ASSIGN(ItemModelObserverBridge); -}; - -ItemModelObserverBridge::ItemModelObserverBridge(AppsGridViewItem* parent, - AppListItem* model) - : parent_(parent), - model_(model) { - model_->AddObserver(this); -} - -ItemModelObserverBridge::~ItemModelObserverBridge() { - model_->RemoveObserver(this); -} - -NSMenu* ItemModelObserverBridge::GetContextMenu() { - if (!context_menu_controller_) { - ui::MenuModel* menu_model = model_->GetContextMenuModel(); - if (!menu_model) - return nil; - - context_menu_controller_.reset( - [[MenuController alloc] initWithModel:menu_model - useWithPopUpButtonCell:NO]); - } - return [context_menu_controller_ menu]; -} - -void ItemModelObserverBridge::ItemIconChanged() { - [parent_ updateButtonImage]; -} - -void ItemModelObserverBridge::ItemNameChanged() { - [parent_ updateButtonTitle]; -} - -void ItemModelObserverBridge::ItemIsInstallingChanged() { - [parent_ setItemIsInstalling:model_->is_installing()]; -} - -void ItemModelObserverBridge::ItemPercentDownloadedChanged() { - [parent_ setPercentDownloaded:model_->percent_downloaded()]; -} - -} // namespace app_list - -// Container for an NSButton to allow proper alignment of the icon in the apps -// grid, and to draw with a highlight when selected. -@interface AppsGridItemBackgroundView : NSView { - @private - BOOL selected_; -} - -- (NSButton*)button; - -- (void)setSelected:(BOOL)flag; - -@end - -@interface AppsGridItemButtonCell : NSButtonCell { - @private - BOOL hasShadow_; -} - -@property(assign, nonatomic) BOOL hasShadow; - -@end - -@interface AppsGridItemButton : NSButton; -@end - -@implementation AppsGridItemBackgroundView - -- (NSButton*)button { - // These views are part of a prototype NSCollectionViewItem, copied with an - // NSCoder. Rather than encoding additional members, the following relies on - // the button always being the first item added to AppsGridItemBackgroundView. - return base::mac::ObjCCastStrict<NSButton>([[self subviews] objectAtIndex:0]); -} - -- (void)setSelected:(BOOL)flag { - DCHECK(selected_ != flag); - selected_ = flag; - [self setNeedsDisplay:YES]; -} - -// Ignore all hit tests. The grid controller needs to be the owner of any drags. -- (NSView*)hitTest:(NSPoint)aPoint { - return nil; -} - -- (void)drawRect:(NSRect)dirtyRect { - if (!selected_) - return; - - [skia::SkColorToSRGBNSColor(app_list::kSelectedColor) set]; - NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver); -} - -- (void)mouseDown:(NSEvent*)theEvent { - [[[self button] cell] setHighlighted:YES]; -} - -- (void)mouseDragged:(NSEvent*)theEvent { - NSPoint pointInView = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - BOOL isInView = [self mouse:pointInView inRect:[self bounds]]; - [[[self button] cell] setHighlighted:isInView]; -} - -- (void)mouseUp:(NSEvent*)theEvent { - NSPoint pointInView = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - if (![self mouse:pointInView inRect:[self bounds]]) - return; - - [[self button] performClick:self]; -} - -@end - -@implementation AppsGridViewItem - -- (id)initWithSize:(NSSize)tileSize { - if ((self = [super init])) { - base::scoped_nsobject<AppsGridItemButton> prototypeButton( - [[AppsGridItemButton alloc] initWithFrame:NSMakeRect( - 0, 0, tileSize.width, tileSize.height - kTileTopPadding)]); - - // This NSButton style always positions the icon at the very top of the - // button frame. AppsGridViewItem uses an enclosing view so that it is - // visually correct. - [prototypeButton setImagePosition:NSImageAbove]; - [prototypeButton setButtonType:NSMomentaryChangeButton]; - [prototypeButton setBordered:NO]; - - base::scoped_nsobject<AppsGridItemBackgroundView> prototypeButtonBackground( - [[AppsGridItemBackgroundView alloc] - initWithFrame:NSMakeRect(0, 0, tileSize.width, tileSize.height)]); - [prototypeButtonBackground addSubview:prototypeButton]; - [self setView:prototypeButtonBackground]; - } - return self; -} - -- (NSProgressIndicator*)progressIndicator { - return progressIndicator_; -} - -- (void)updateButtonTitle { - if (progressIndicator_) - return; - - base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( - [[NSMutableParagraphStyle alloc] init]); - [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; - [paragraphStyle setAlignment:NSCenterTextAlignment]; - NSDictionary* titleAttributes = @{ - NSParagraphStyleAttributeName : paragraphStyle, - NSFontAttributeName : ui::ResourceBundle::GetSharedInstance() - .GetFontList(app_list::kItemTextFontStyle) - .DeriveWithSizeDelta(kMacFontSizeDelta) - .GetPrimaryFont() - .GetNativeFont(), - NSForegroundColorAttributeName : - skia::SkColorToSRGBNSColor(app_list::kGridTitleColor) - }; - NSString* buttonTitle = - base::SysUTF8ToNSString([self model]->GetDisplayName()); - base::scoped_nsobject<NSAttributedString> attributedTitle( - [[NSAttributedString alloc] initWithString:buttonTitle - attributes:titleAttributes]); - [[self button] setAttributedTitle:attributedTitle]; - - // If the display name would be truncated in the NSButton, or if the display - // name differs from the full name, add a tooltip showing the full name. - NSRect titleRect = - [[[self button] cell] titleRectForBounds:[[self button] bounds]]; - if ([self model]->name() == [self model]->GetDisplayName() && - [attributedTitle size].width < NSWidth(titleRect)) { - [[self view] removeAllToolTips]; - } else { - [[self view] setToolTip:base::SysUTF8ToNSString([self model]->name())]; - } -} - -- (void)updateButtonImage { - const gfx::Size iconSize = gfx::Size(kIconSize, kIconSize); - gfx::ImageSkia icon = [self model]->icon(); - if (icon.size() != iconSize) { - icon = gfx::ImageSkiaOperations::CreateResizedImage( - icon, skia::ImageOperations::RESIZE_BEST, iconSize); - } - NSImage* buttonImage = gfx::NSImageFromImageSkiaWithColorSpace( - icon, base::mac::GetSRGBColorSpace()); - [[self button] setImage:buttonImage]; - [[[self button] cell] setHasShadow:true]; -} - -- (void)setModel:(app_list::AppListItem*)itemModel { - [trackingArea_.get() clearOwner]; - if (!itemModel) { - observerBridge_.reset(); - return; - } - - observerBridge_.reset(new app_list::ItemModelObserverBridge(self, itemModel)); - [self updateButtonTitle]; - [self updateButtonImage]; - - if (trackingArea_.get()) - [[self view] removeTrackingArea:trackingArea_.get()]; - - trackingArea_.reset( - [[CrTrackingArea alloc] initWithRect:NSZeroRect - options:NSTrackingInVisibleRect | - NSTrackingMouseEnteredAndExited | - NSTrackingActiveInKeyWindow - owner:self - userInfo:nil]); - [[self view] addTrackingArea:trackingArea_.get()]; -} - -- (app_list::AppListItem*)model { - return observerBridge_->model(); -} - -- (NSButton*)button { - return [[self itemBackgroundView] button]; -} - -- (NSMenu*)contextMenu { - // Don't show the menu if button is already held down, e.g. with a left-click. - if ([[[self button] cell] isHighlighted]) - return nil; - - [self setSelected:YES]; - return observerBridge_->GetContextMenu(); -} - -- (NSBitmapImageRep*)dragRepresentationForRestore:(BOOL)isRestore { - NSButton* button = [self button]; - NSView* itemView = [self view]; - - // The snapshot is never drawn as if it was selected. Also remove the cell - // highlight on the button image, added when it was clicked. - [button setHidden:NO]; - [[button cell] setHighlighted:NO]; - [self setSelected:NO]; - [progressIndicator_ setHidden:YES]; - if (isRestore) - [self updateButtonTitle]; - else - [button setTitle:@""]; - - NSBitmapImageRep* imageRep = - [itemView bitmapImageRepForCachingDisplayInRect:[itemView visibleRect]]; - [itemView cacheDisplayInRect:[itemView visibleRect] - toBitmapImageRep:imageRep]; - - if (isRestore) { - [progressIndicator_ setHidden:NO]; - [self setSelected:YES]; - } - // Button is always hidden until the drag animation completes. - [button setHidden:YES]; - return imageRep; -} - -- (void)setItemIsInstalling:(BOOL)isInstalling { - if (!isInstalling == !progressIndicator_) - return; - - if (!isInstalling) { - [progressIndicator_ removeFromSuperview]; - progressIndicator_.reset(); - [self updateButtonTitle]; - [self setSelected:YES]; - return; - } - - NSRect rect = NSMakeRect( - kProgressBarHorizontalPadding, - kProgressBarVerticalPadding, - NSWidth([[self view] bounds]) - 2 * kProgressBarHorizontalPadding, - NSProgressIndicatorPreferredAquaThickness); - [[self button] setTitle:@""]; - progressIndicator_.reset([[NSProgressIndicator alloc] initWithFrame:rect]); - [progressIndicator_ setIndeterminate:NO]; - [progressIndicator_ setControlSize:NSSmallControlSize]; - [[self view] addSubview:progressIndicator_]; -} - -- (void)setPercentDownloaded:(int)percent { - // In a corner case, items can be installing when they are first added. For - // those, the icon will start desaturated. Wait for a progress update before - // showing the progress bar. - [self setItemIsInstalling:YES]; - if (percent != -1) { - [progressIndicator_ setDoubleValue:percent]; - return; - } - - // Otherwise, fully downloaded and waiting for install to complete. - [progressIndicator_ setIndeterminate:YES]; - [progressIndicator_ startAnimation:self]; -} - -- (AppsGridItemBackgroundView*)itemBackgroundView { - return base::mac::ObjCCastStrict<AppsGridItemBackgroundView>([self view]); -} - -- (void)mouseEntered:(NSEvent*)theEvent { - [self setSelected:YES]; -} - -- (void)mouseExited:(NSEvent*)theEvent { - [self setSelected:NO]; -} - -- (void)setSelected:(BOOL)flag { - if ([self isSelected] == flag) - return; - - [[self itemBackgroundView] setSelected:flag]; - [super setSelected:flag]; - [self updateButtonTitle]; -} - -@end - -@implementation AppsGridItemButton - -+ (Class)cellClass { - return [AppsGridItemButtonCell class]; -} - -@end - -@implementation AppsGridItemButtonCell - -@synthesize hasShadow = hasShadow_; - -- (void)drawImage:(NSImage*)image - withFrame:(NSRect)frame - inView:(NSView*)controlView { - if (!hasShadow_) { - [super drawImage:image - withFrame:frame - inView:controlView]; - return; - } - - base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); - gfx::ScopedNSGraphicsContextSaveGState context; - [shadow setShadowOffset:NSMakeSize(0, -2)]; - [shadow setShadowBlurRadius:2.0]; - [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0 - alpha:0.14]]; - [shadow set]; - - [super drawImage:image - withFrame:frame - inView:controlView]; -} - -// Workaround for http://crbug.com/324365: AppKit in Mavericks tries to call -// - [NSButtonCell item] when inspecting accessibility. Without this, an -// unrecognized selector exception is thrown inside AppKit, crashing Chrome. -- (id)item { - return nil; -} - -@end
diff --git a/ui/app_list/cocoa/apps_pagination_model_observer.h b/ui/app_list/cocoa/apps_pagination_model_observer.h deleted file mode 100644 index a2f463f..0000000 --- a/ui/app_list/cocoa/apps_pagination_model_observer.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_PAGINATION_MODEL_OBSERVER_H_ -#define UI_APP_LIST_COCOA_APPS_PAGINATION_MODEL_OBSERVER_H_ - -// Observer protocol for page changes. Compare with -// app_list::PaginationModelObserver. -@protocol AppsPaginationModelObserver - -// Invoked when the total number of pages has changed. -- (void)totalPagesChanged; - -// Invoked when the selected page index is changed. -- (void)selectedPageChanged:(int)newSelected; - -// Invoked when the portion of pages that are visible have changed. -- (void)pageVisibilityChanged; - -// Return a pager segment at |locationInWindow| or -1 if there is none. -- (NSInteger)pagerSegmentAtLocation:(NSPoint)locationInWindow; - -@end - -#endif // UI_APP_LIST_COCOA_APPS_PAGINATION_MODEL_OBSERVER_H_
diff --git a/ui/app_list/cocoa/apps_search_box_controller.h b/ui/app_list/cocoa/apps_search_box_controller.h deleted file mode 100644 index 553ba98..0000000 --- a/ui/app_list/cocoa/apps_search_box_controller.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_SEARCH_BOX_CONTROLLER_H_ -#define UI_APP_LIST_COCOA_APPS_SEARCH_BOX_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include <memory> - -#include "base/mac/scoped_nsobject.h" -#include "ui/app_list/app_list_export.h" - -namespace app_list { -class AppListMenu; -class AppListModel; -class AppListViewDelegate; -class SearchBoxModel; -class SearchBoxModelObserverBridge; -} - -@class AppListMenuController; -@class HoverImageMenuButton; -@class SearchTextField; - -@protocol AppsSearchBoxDelegate<NSTextFieldDelegate> - -- (app_list::AppListViewDelegate*)appListDelegate; -- (app_list::SearchBoxModel*)searchBoxModel; -- (app_list::AppListModel*)appListModel; -- (void)modelTextDidChange; - -@end - -// Controller for the search box in the topmost portion of the app list. -APP_LIST_EXPORT -@interface AppsSearchBoxController : NSViewController<NSTextFieldDelegate> { - @private - base::scoped_nsobject<SearchTextField> searchTextField_; - base::scoped_nsobject<NSImageView> searchImageView_; - base::scoped_nsobject<HoverImageMenuButton> menuButton_; - base::scoped_nsobject<AppListMenuController> menuController_; - std::unique_ptr<app_list::SearchBoxModelObserverBridge> bridge_; - std::unique_ptr<app_list::AppListMenu> appListMenu_; - - id<AppsSearchBoxDelegate> delegate_; // Weak. Owns us. -} - -@property(assign, nonatomic) id<AppsSearchBoxDelegate> delegate; - -- (id)initWithFrame:(NSRect)frame; -- (void)clearSearch; - -// Rebuild the menu due to changes from the AppListViewDelegate. -- (void)rebuildMenu; - -@end - -@interface AppsSearchBoxController (TestingAPI) - -- (NSTextField*)searchTextField; -- (NSPopUpButton*)menuControl; -- (app_list::AppListMenu*)appListMenu; - -@end - -#endif // UI_APP_LIST_COCOA_APPS_SEARCH_BOX_CONTROLLER_H_
diff --git a/ui/app_list/cocoa/apps_search_box_controller.mm b/ui/app_list/cocoa/apps_search_box_controller.mm deleted file mode 100644 index 19ef300..0000000 --- a/ui/app_list/cocoa/apps_search_box_controller.mm +++ /dev/null
@@ -1,403 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_search_box_controller.h" - -#include "base/mac/foundation_util.h" -#include "base/mac/mac_util.h" -#include "base/macros.h" -#include "base/strings/sys_string_conversions.h" -#include "ui/app_list/app_list_menu.h" -#include "ui/app_list/app_list_model.h" -#include "ui/app_list/resources/grit/app_list_resources.h" -#include "ui/app_list/search_box_model.h" -#include "ui/app_list/search_box_model_observer.h" -#include "ui/base/cocoa/cocoa_base_utils.h" -#import "ui/base/cocoa/controls/hover_image_menu_button.h" -#import "ui/base/cocoa/controls/hover_image_menu_button_cell.h" -#import "ui/base/cocoa/menu_controller.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image_skia_util_mac.h" - -namespace { - -// Padding either side of the search icon and menu button. -const CGFloat kPadding = 14; - -// Size of the search icon. -const CGFloat kSearchIconDimension = 32; - -// Size of the menu button on the right. -const CGFloat kMenuButtonDimension = 29; - -// Menu offset relative to the bottom-right corner of the menu button. -const CGFloat kMenuYOffsetFromButton = -4; -const CGFloat kMenuXOffsetFromButton = -7; - -} - -@interface AppsSearchBoxController () - -- (NSImageView*)searchImageView; -- (void)addSubviews; - -@end - -namespace app_list { - -class SearchBoxModelObserverBridge : public SearchBoxModelObserver { - public: - SearchBoxModelObserverBridge(AppsSearchBoxController* parent); - ~SearchBoxModelObserverBridge() override; - - void SetSearchText(const base::string16& text); - - void IconChanged() override; - void SpeechRecognitionButtonPropChanged() override; - void HintTextChanged() override; - void SelectionModelChanged() override; - void TextChanged() override; - - private: - SearchBoxModel* GetModel(); - - AppsSearchBoxController* parent_; // Weak. Owns us. - - DISALLOW_COPY_AND_ASSIGN(SearchBoxModelObserverBridge); -}; - -SearchBoxModelObserverBridge::SearchBoxModelObserverBridge( - AppsSearchBoxController* parent) - : parent_(parent) { - IconChanged(); - HintTextChanged(); - GetModel()->AddObserver(this); -} - -SearchBoxModelObserverBridge::~SearchBoxModelObserverBridge() { - GetModel()->RemoveObserver(this); -} - -SearchBoxModel* SearchBoxModelObserverBridge::GetModel() { - SearchBoxModel* searchBoxModel = [[parent_ delegate] searchBoxModel]; - DCHECK(searchBoxModel); - return searchBoxModel; -} - -void SearchBoxModelObserverBridge::SetSearchText(const base::string16& text) { - SearchBoxModel* model = GetModel(); - model->RemoveObserver(this); - model->SetText(text); - // TODO(tapted): See if this should call SetSelectionModel here. - model->AddObserver(this); -} - -void SearchBoxModelObserverBridge::IconChanged() { - [[parent_ searchImageView] setImage:gfx::NSImageFromImageSkiaWithColorSpace( - GetModel()->icon(), base::mac::GetSRGBColorSpace())]; -} - -void SearchBoxModelObserverBridge::SpeechRecognitionButtonPropChanged() { - // TODO(mukai): implement. - NOTIMPLEMENTED(); -} - -void SearchBoxModelObserverBridge::HintTextChanged() { - [[[parent_ searchTextField] cell] setPlaceholderString: - base::SysUTF16ToNSString(GetModel()->hint_text())]; -} - -void SearchBoxModelObserverBridge::SelectionModelChanged() { - // TODO(tapted): See if anything needs to be done here for RTL. -} - -void SearchBoxModelObserverBridge::TextChanged() { - // Currently the model text is only changed when we are not observing it, or - // it is changed in tests to establish a particular state. - [[parent_ searchTextField] - setStringValue:base::SysUTF16ToNSString(GetModel()->text())]; - [[parent_ delegate] modelTextDidChange]; -} - -} // namespace app_list - -@interface SearchTextField : NSTextField { - @private - NSRect textFrameInset_; -} - -@property(readonly, nonatomic) NSRect textFrameInset; - -- (void)setMarginsWithLeftMargin:(CGFloat)leftMargin - rightMargin:(CGFloat)rightMargin; - -@end - -@interface AppListMenuController : MenuController { - @private - AppsSearchBoxController* searchBoxController_; // Weak. Owns us. -} - -- (id)initWithSearchBoxController:(AppsSearchBoxController*)parent; - -@end - -@implementation AppsSearchBoxController - -@synthesize delegate = delegate_; - -- (id)initWithFrame:(NSRect)frame { - if ((self = [super init])) { - base::scoped_nsobject<NSView> containerView( - [[NSView alloc] initWithFrame:frame]); - [self setView:containerView]; - [self addSubviews]; - } - return self; -} - -- (void)clearSearch { - [searchTextField_ setStringValue:@""]; - // -controlTextDidChange:'s parameter is marked nonnull in the 10.11 SDK, - // so pass a dummy object even though we know that this class's implementation - // never looks at the parameter. - [self controlTextDidChange:[NSNotification notificationWithName:@"" - object:self]]; -} - -- (void)rebuildMenu { - if (![delegate_ appListDelegate]) - return; - - menuController_.reset(); - appListMenu_.reset( - new app_list::AppListMenu([delegate_ appListDelegate])); - menuController_.reset([[AppListMenuController alloc] - initWithSearchBoxController:self]); - [menuButton_ setMenu:[menuController_ menu]]; // Menu will populate here. -} - -- (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate { - [[menuButton_ menu] removeAllItems]; - menuController_.reset(); - appListMenu_.reset(); - bridge_.reset(); // Ensure observers are cleared before updating |delegate_|. - delegate_ = delegate; - if (!delegate_) - return; - - bridge_.reset(new app_list::SearchBoxModelObserverBridge(self)); - [self rebuildMenu]; -} - -- (NSTextField*)searchTextField { - return searchTextField_; -} - -- (NSPopUpButton*)menuControl { - return menuButton_; -} - -- (app_list::AppListMenu*)appListMenu { - return appListMenu_.get(); -} - -- (NSImageView*)searchImageView { - return searchImageView_; -} - -- (void)addSubviews { - NSRect viewBounds = [[self view] bounds]; - searchImageView_.reset([[NSImageView alloc] initWithFrame:NSMakeRect( - kPadding, 0, kSearchIconDimension, NSHeight(viewBounds))]); - - searchTextField_.reset([[SearchTextField alloc] initWithFrame:viewBounds]); - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - [searchTextField_ setDelegate:self]; - [searchTextField_ setFont:rb.GetFont( - ui::ResourceBundle::MediumFont).GetNativeFont()]; - [searchTextField_ - setMarginsWithLeftMargin:NSMaxX([searchImageView_ frame]) + kPadding - rightMargin:kMenuButtonDimension + 2 * kPadding]; - - // Add the drop-down menu, with a custom button. - NSRect buttonFrame = NSMakeRect( - NSWidth(viewBounds) - kMenuButtonDimension - kPadding, - floor(NSMidY(viewBounds) - kMenuButtonDimension / 2), - kMenuButtonDimension, - kMenuButtonDimension); - menuButton_.reset([[HoverImageMenuButton alloc] initWithFrame:buttonFrame - pullsDown:YES]); - [[menuButton_ hoverImageMenuButtonCell] setDefaultImage: - rb.GetNativeImageNamed(IDR_APP_LIST_TOOLS_NORMAL).AsNSImage()]; - [[menuButton_ hoverImageMenuButtonCell] setAlternateImage: - rb.GetNativeImageNamed(IDR_APP_LIST_TOOLS_PRESSED).AsNSImage()]; - [[menuButton_ hoverImageMenuButtonCell] setHoverImage: - rb.GetNativeImageNamed(IDR_APP_LIST_TOOLS_HOVER).AsNSImage()]; - - [[self view] addSubview:searchImageView_]; - [[self view] addSubview:searchTextField_]; - [[self view] addSubview:menuButton_]; -} - -- (BOOL)control:(NSControl*)control - textView:(NSTextView*)textView - doCommandBySelector:(SEL)command { - // Forward the message first, to handle grid or search results navigation. - BOOL handled = [delegate_ control:control - textView:textView - doCommandBySelector:command]; - if (handled) - return YES; - - // If the delegate did not handle the escape key, it means the window was not - // dismissed because there were search results. Clear them. - if (command == @selector(complete:)) { - [self clearSearch]; - return YES; - } - - return NO; -} - -- (void)controlTextDidChange:(NSNotification*)notification { - if (bridge_) { - bridge_->SetSearchText( - base::SysNSStringToUTF16([searchTextField_ stringValue])); - } - - [delegate_ modelTextDidChange]; -} - -@end - -@interface SearchTextFieldCell : NSTextFieldCell; - -- (NSRect)textFrameForFrameInternal:(NSRect)cellFrame; - -@end - -@implementation SearchTextField - -@synthesize textFrameInset = textFrameInset_; - -+ (Class)cellClass { - return [SearchTextFieldCell class]; -} - -- (id)initWithFrame:(NSRect)theFrame { - if ((self = [super initWithFrame:theFrame])) { - [self setFocusRingType:NSFocusRingTypeNone]; - [self setDrawsBackground:NO]; - [self setBordered:NO]; - } - return self; -} - -- (void)setMarginsWithLeftMargin:(CGFloat)leftMargin - rightMargin:(CGFloat)rightMargin { - // Find the preferred height for the current text properties, and center. - NSRect viewBounds = [self bounds]; - [self sizeToFit]; - NSRect textBounds = [self bounds]; - textFrameInset_.origin.x = leftMargin; - textFrameInset_.origin.y = floor(NSMidY(viewBounds) - NSMidY(textBounds)); - textFrameInset_.size.width = leftMargin + rightMargin; - textFrameInset_.size.height = NSHeight(viewBounds) - NSHeight(textBounds); - [self setFrame:viewBounds]; -} - -@end - -@implementation SearchTextFieldCell - -- (NSRect)textFrameForFrameInternal:(NSRect)cellFrame { - SearchTextField* searchTextField = - base::mac::ObjCCastStrict<SearchTextField>([self controlView]); - NSRect insetRect = [searchTextField textFrameInset]; - cellFrame.origin.x += insetRect.origin.x; - cellFrame.origin.y += insetRect.origin.y; - cellFrame.size.width -= insetRect.size.width; - cellFrame.size.height -= insetRect.size.height; - return cellFrame; -} - -- (NSRect)textFrameForFrame:(NSRect)cellFrame { - return [self textFrameForFrameInternal:cellFrame]; -} - -- (NSRect)textCursorFrameForFrame:(NSRect)cellFrame { - return [self textFrameForFrameInternal:cellFrame]; -} - -- (void)resetCursorRect:(NSRect)cellFrame - inView:(NSView*)controlView { - [super resetCursorRect:[self textCursorFrameForFrame:cellFrame] - inView:controlView]; -} - -- (NSRect)drawingRectForBounds:(NSRect)theRect { - return [super drawingRectForBounds:[self textFrameForFrame:theRect]]; -} - -- (void)editWithFrame:(NSRect)cellFrame - inView:(NSView*)controlView - editor:(NSText*)editor - delegate:(id)delegate - event:(NSEvent*)event { - [super editWithFrame:[self textFrameForFrame:cellFrame] - inView:controlView - editor:editor - delegate:delegate - event:event]; -} - -- (void)selectWithFrame:(NSRect)cellFrame - inView:(NSView*)controlView - editor:(NSText*)editor - delegate:(id)delegate - start:(NSInteger)start - length:(NSInteger)length { - [super selectWithFrame:[self textFrameForFrame:cellFrame] - inView:controlView - editor:editor - delegate:delegate - start:start - length:length]; -} - -@end - -@implementation AppListMenuController - -- (id)initWithSearchBoxController:(AppsSearchBoxController*)parent { - // Need to initialze super with a NULL model, otherwise it will immediately - // try to populate, which can't be done until setting the parent. - if ((self = [super initWithModel:NULL - useWithPopUpButtonCell:YES])) { - searchBoxController_ = parent; - [super setModel:[parent appListMenu]->menu_model()]; - } - return self; -} - -- (NSRect)confinementRectForMenu:(NSMenu*)menu - onScreen:(NSScreen*)screen { - NSPopUpButton* menuButton = [searchBoxController_ menuControl]; - // Ensure the menu comes up below the menu button by trimming the window frame - // to a point anchored below the bottom right of the button. - NSRect anchorRect = [menuButton convertRect:[menuButton bounds] - toView:nil]; - NSPoint anchorPoint = ui::ConvertPointFromWindowToScreen( - [menuButton window], - NSMakePoint(NSMaxX(anchorRect) + kMenuXOffsetFromButton, - NSMinY(anchorRect) - kMenuYOffsetFromButton)); - - NSRect confinementRect = [[menuButton window] frame]; - confinementRect.size = NSMakeSize(anchorPoint.x - NSMinX(confinementRect), - anchorPoint.y - NSMinY(confinementRect)); - return confinementRect; -} - -@end
diff --git a/ui/app_list/cocoa/apps_search_box_controller_unittest.mm b/ui/app_list/cocoa/apps_search_box_controller_unittest.mm deleted file mode 100644 index 75ba7cd..0000000 --- a/ui/app_list/cocoa/apps_search_box_controller_unittest.mm +++ /dev/null
@@ -1,270 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_search_box_controller.h" - -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#import "testing/gtest_mac.h" -#include "ui/app_list/app_list_menu.h" -#include "ui/app_list/app_list_model_observer.h" -#include "ui/app_list/search_box_model.h" -#include "ui/app_list/test/app_list_test_model.h" -#include "ui/app_list/test/app_list_test_view_delegate.h" -#import "ui/base/cocoa/menu_controller.h" -#import "ui/gfx/test/ui_cocoa_test_helper.h" - -using base::ASCIIToUTF16; - -@interface TestAppsSearchBoxDelegate : NSObject<AppsSearchBoxDelegate> { - @private - app_list::SearchBoxModel searchBoxModel_; - app_list::test::AppListTestViewDelegate appListDelegate_; - app_list::test::AppListTestModel appListModel_; - int textChangeCount_; -} - -@property(assign, nonatomic) int textChangeCount; - -@end - -@implementation TestAppsSearchBoxDelegate - -@synthesize textChangeCount = textChangeCount_; - -- (id)init { - if ((self = [super init])) { - app_list::AppListViewDelegate::Users users(2); - users[0].name = ASCIIToUTF16("user1"); - users[1].name = ASCIIToUTF16("user2"); - users[1].email = ASCIIToUTF16("user2@chromium.org"); - users[1].active = true; - appListDelegate_.SetUsers(users); - } - return self; -} - -- (app_list::SearchBoxModel*)searchBoxModel { - return &searchBoxModel_; -} - -- (app_list::AppListViewDelegate*)appListDelegate { - return &appListDelegate_; -} - -- (app_list::test::AppListTestViewDelegate*)appListTestViewDelegate { - return &appListDelegate_; -} - - -- (BOOL)control:(NSControl*)control - textView:(NSTextView*)textView - doCommandBySelector:(SEL)command { - return NO; -} - -- (void)modelTextDidChange { - ++textChangeCount_; -} - -- (CGFloat)bubbleCornerRadius { - return 3; -} - -- (app_list::AppListModel*)appListModel { - return &appListModel_; -} - -@end - -namespace app_list { -namespace test { - -class AppsSearchBoxControllerTest : public ui::CocoaTest { - public: - AppsSearchBoxControllerTest() { - Init(); - } - - void SetUp() override { - apps_search_box_controller_.reset( - [[AppsSearchBoxController alloc] initWithFrame: - NSMakeRect(0, 0, 400, 100)]); - delegate_.reset([[TestAppsSearchBoxDelegate alloc] init]); - [apps_search_box_controller_ setDelegate:delegate_]; - - ui::CocoaTest::SetUp(); - [[test_window() contentView] addSubview:[apps_search_box_controller_ view]]; - } - - void TearDown() override { - [apps_search_box_controller_ setDelegate:nil]; - ui::CocoaTest::TearDown(); - } - - void SimulateKeyAction(SEL c) { - base::scoped_nsobject<NSTextView> stub_field_editor( - [[NSTextView alloc] initWithFrame:NSZeroRect]); - NSControl* control = [apps_search_box_controller_ searchTextField]; - [apps_search_box_controller_ control:control - textView:stub_field_editor.get() - doCommandBySelector:c]; - } - - protected: - base::scoped_nsobject<TestAppsSearchBoxDelegate> delegate_; - base::scoped_nsobject<AppsSearchBoxController> apps_search_box_controller_; - - private: - DISALLOW_COPY_AND_ASSIGN(AppsSearchBoxControllerTest); -}; - -TEST_VIEW(AppsSearchBoxControllerTest, [apps_search_box_controller_ view]); - -// Test the search box initialization, and search input and clearing. -TEST_F(AppsSearchBoxControllerTest, SearchBoxModel) { - app_list::SearchBoxModel* model = [delegate_ searchBoxModel]; - // Usually localized "Search". - const base::string16 hit_text(ASCIIToUTF16("hint")); - model->SetHintText(hit_text); - EXPECT_NSEQ(base::SysUTF16ToNSString(hit_text), - [[[apps_search_box_controller_ searchTextField] cell] placeholderString]); - - const base::string16 search_text(ASCIIToUTF16("test")); - model->SetText(search_text); - EXPECT_NSEQ(base::SysUTF16ToNSString(search_text), - [[apps_search_box_controller_ searchTextField] stringValue]); - // Updates coming via the model should notify the delegate. - EXPECT_EQ(1, [delegate_ textChangeCount]); - - // Updates from the view should update the model and notify the delegate. - [apps_search_box_controller_ clearSearch]; - EXPECT_EQ(base::string16(), model->text()); - EXPECT_NSEQ([NSString string], - [[apps_search_box_controller_ searchTextField] stringValue]); - EXPECT_EQ(2, [delegate_ textChangeCount]); - - // Test pressing escape clears the search. First add some text. - model->SetText(search_text); - EXPECT_EQ(3, [delegate_ textChangeCount]); - - EXPECT_NSEQ(base::SysUTF16ToNSString(search_text), - [[apps_search_box_controller_ searchTextField] stringValue]); - SimulateKeyAction(@selector(complete:)); - EXPECT_NSEQ([NSString string], - [[apps_search_box_controller_ searchTextField] stringValue]); - EXPECT_EQ(4, [delegate_ textChangeCount]); -} - -// Test the popup menu items when there is only one user.. -TEST_F(AppsSearchBoxControllerTest, SearchBoxMenuSingleUser) { - // Set a single user. We need to set the delegate again because the - // AppListModel observer isn't hooked up in these tests. - [delegate_ appListTestViewDelegate]->SetUsers( - app_list::AppListViewDelegate::Users(1)); - [apps_search_box_controller_ setDelegate:delegate_]; - - NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; - EXPECT_TRUE([apps_search_box_controller_ appListMenu]); - ui::MenuModel* menu_model - = [apps_search_box_controller_ appListMenu]->menu_model(); - // Add one to the item count to account for the blank, first item that Cocoa - // has in its popup menus. - EXPECT_EQ(menu_model->GetItemCount() + 1, - [[menu_control menu] numberOfItems]); - - // All command ids should be less than |SELECT_PROFILE| as no user menu items - // are being shown. - for (int i = 0; i < menu_model->GetItemCount(); ++i) - EXPECT_LT(menu_model->GetCommandIdAt(i), AppListMenu::SELECT_PROFILE); - - // The number of items should match the index that starts profile items. - EXPECT_EQ(AppListMenu::SELECT_PROFILE, menu_model->GetItemCount()); -} - -// Test the popup menu items for the multi-profile case. -TEST_F(AppsSearchBoxControllerTest, SearchBoxMenu) { - const app_list::AppListViewDelegate::Users& users = - [delegate_ appListDelegate]->GetUsers(); - NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; - EXPECT_TRUE([apps_search_box_controller_ appListMenu]); - ui::MenuModel* menu_model - = [apps_search_box_controller_ appListMenu]->menu_model(); - // Add one to the item count to account for the blank, first item that Cocoa - // has in its popup menus. - EXPECT_EQ(menu_model->GetItemCount() + 1, - [[menu_control menu] numberOfItems]); - - ui::MenuModel* found_menu_model = menu_model; - int index; - MenuController* controller = [[menu_control menu] delegate]; - - // The first user item is an unchecked label. - EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( - AppListMenu::SELECT_PROFILE, &menu_model, &index)); - EXPECT_EQ(found_menu_model, menu_model); - NSMenuItem* unchecked_user_item = [[menu_control menu] itemAtIndex:index + 1]; - [controller validateUserInterfaceItem:unchecked_user_item]; - // The profile name should be shown if there is no email available. - EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), - [unchecked_user_item title]); - EXPECT_EQ(NSOffState, [unchecked_user_item state]); - - // The second user item is a checked label because it is the active profile. - EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( - AppListMenu::SELECT_PROFILE + 1, &menu_model, &index)); - EXPECT_EQ(found_menu_model, menu_model); - NSMenuItem* checked_user_item = [[menu_control menu] itemAtIndex:index + 1]; - [controller validateUserInterfaceItem:checked_user_item]; - // The email is shown when available. - EXPECT_NSEQ(base::SysUTF16ToNSString(users[1].email), - [checked_user_item title]); - EXPECT_EQ(NSOnState, [checked_user_item state]); - - // A regular item should have just the label. - EXPECT_TRUE(ui::MenuModel::GetModelAndIndexForCommandId( - AppListMenu::SHOW_SETTINGS, &menu_model, &index)); - EXPECT_EQ(found_menu_model, menu_model); - NSMenuItem* settings_item = [[menu_control menu] itemAtIndex:index + 1]; - EXPECT_FALSE([settings_item view]); - EXPECT_NSEQ(base::SysUTF16ToNSString(menu_model->GetLabelAt(index)), - [settings_item title]); -} - -// Test adding another user, and changing an existing one. -TEST_F(AppsSearchBoxControllerTest, SearchBoxMenuChangingUsers) { - app_list::AppListViewDelegate::Users users = - [delegate_ appListDelegate]->GetUsers(); - EXPECT_EQ(2u, users.size()); - ui::MenuModel* menu_model - = [apps_search_box_controller_ appListMenu]->menu_model(); - // Adding one to account for the empty item at index 0 in Cocoa popup menus. - int non_user_items = menu_model->GetItemCount() - users.size() + 1; - - NSPopUpButton* menu_control = [apps_search_box_controller_ menuControl]; - EXPECT_EQ(2, [[menu_control menu] numberOfItems] - non_user_items); - EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), - [[[menu_control menu] itemAtIndex:1] title]); - - users[0].name = ASCIIToUTF16("renamed user"); - app_list::AppListViewDelegate::User new_user; - new_user.name = ASCIIToUTF16("user3"); - users.push_back(new_user); - [delegate_ appListTestViewDelegate]->SetUsers(users); - // Note: menu does not automatically get rebuilt. Force a rebuild (which - // would normally occur when the UI is closed / re-opend). - [apps_search_box_controller_ rebuildMenu]; - - // Should now be an extra item, and it should have correct titles. - EXPECT_EQ(3, [[menu_control menu] numberOfItems] - non_user_items); - EXPECT_NSEQ(base::SysUTF16ToNSString(users[0].name), - [[[menu_control menu] itemAtIndex:1] title]); - EXPECT_NSEQ(base::SysUTF16ToNSString(new_user.name), - [[[menu_control menu] itemAtIndex:3] title]); -} - -} // namespace test -} // namespace app_list
diff --git a/ui/app_list/cocoa/apps_search_results_controller.h b/ui/app_list/cocoa/apps_search_results_controller.h deleted file mode 100644 index 18684eb..0000000 --- a/ui/app_list/cocoa/apps_search_results_controller.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_CONTROLLER_H_ -#define UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include <memory> - -#include "base/mac/scoped_nsobject.h" -#include "ui/app_list/app_list_export.h" -#include "ui/app_list/app_list_model.h" -#import "ui/base/cocoa/tracking_area.h" - -namespace app_list { -class AppsSearchResultsModelBridge; -class SearchResult; -} - -@class AppsSearchResultsCell; - -@protocol AppsSearchResultsDelegate<NSObject> - -- (app_list::AppListModel*)appListModel; -- (void)openResult:(app_list::SearchResult*)result; - -@end - -// Controller for the search results displayed when a user types in the app list -// search box. Results display in an NSTableView with a single column. Each row -// has an icon on the left, and one or two lines of formatted text describing -// the result. -APP_LIST_EXPORT -@interface AppsSearchResultsController - : NSViewController<NSTableViewDelegate, NSTableViewDataSource> { - @private - base::scoped_nsobject<NSTableView> tableView_; - ui::ScopedCrTrackingArea trackingArea_; - NSPoint lastMouseDownInView_; - NSInteger hoveredRowIndex_; - std::unique_ptr<app_list::AppsSearchResultsModelBridge> bridge_; - NSObject<AppsSearchResultsDelegate>* delegate_; // Weak. Owns us. -} - -@property(assign, nonatomic) NSObject<AppsSearchResultsDelegate>* delegate; -@property(readonly, nonatomic) app_list::AppListModel::SearchResults* results; -@property(readonly, nonatomic) NSTableView* tableView; - -- (id)initWithAppsSearchResultsFrameSize:(NSSize)size; - -// Returns true when handling Enter, to activate the highlighted search result, -// or up/down to navigate results. -- (BOOL)handleCommandBySelector:(SEL)command; - -@end - -#endif // UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_CONTROLLER_H_
diff --git a/ui/app_list/cocoa/apps_search_results_controller.mm b/ui/app_list/cocoa/apps_search_results_controller.mm deleted file mode 100644 index 41155f22..0000000 --- a/ui/app_list/cocoa/apps_search_results_controller.mm +++ /dev/null
@@ -1,469 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_search_results_controller.h" - -#include "base/mac/foundation_util.h" -#include "base/mac/mac_util.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/sys_string_conversions.h" -#include "skia/ext/skia_utils_mac.h" -#include "ui/app_list/app_list_constants.h" -#include "ui/app_list/app_list_model.h" -#import "ui/app_list/cocoa/apps_search_results_model_bridge.h" -#include "ui/app_list/search_result.h" -#import "ui/base/cocoa/flipped_view.h" -#include "ui/gfx/image/image_skia_util_mac.h" - -namespace { - -const CGFloat kPreferredRowHeight = 52; -const CGFloat kIconDimension = 32; -const CGFloat kIconPadding = 14; -const CGFloat kIconViewWidth = kIconDimension + 2 * kIconPadding; -const CGFloat kTextTrailPadding = kIconPadding; - -// Map background styles to represent selection and hover in the results list. -const NSBackgroundStyle kBackgroundNormal = NSBackgroundStyleLight; -const NSBackgroundStyle kBackgroundSelected = NSBackgroundStyleDark; -const NSBackgroundStyle kBackgroundHovered = NSBackgroundStyleRaised; - -// The mouse hover colour (3% black over kContentsBackgroundColor). -const SkColor kHighlightedRowColor = SkColorSetRGB(0xEE, 0xEE, 0xEE); -// The keyboard select colour (6% black over kContentsBackgroundColor). -const SkColor kSelectedRowColor = SkColorSetRGB(0xE6, 0xE6, 0xE6); - -} // namespace - -@interface AppsSearchResultsController () - -- (void)loadAndSetViewWithResultsFrameSize:(NSSize)size; -- (void)mouseDown:(NSEvent*)theEvent; -- (void)tableViewClicked:(id)sender; -- (app_list::AppListModel::SearchResults*)searchResults; -- (void)activateSelection; -- (BOOL)moveSelectionByDelta:(NSInteger)delta; -- (NSMenu*)contextMenuForRow:(NSInteger)rowIndex; - -@end - -@interface AppsSearchResultsCell : NSTextFieldCell -@end - -// Immutable class representing a search result in the NSTableView. -@interface AppsSearchResultRep : NSObject<NSCopying> { - @private - base::scoped_nsobject<NSAttributedString> attributedStringValue_; - base::scoped_nsobject<NSImage> resultIcon_; -} - -@property(readonly, nonatomic) NSAttributedString* attributedStringValue; -@property(readonly, nonatomic) NSImage* resultIcon; - -- (id)initWithSearchResult:(app_list::SearchResult*)result; - -- (NSMutableAttributedString*)createRenderText:(const base::string16&)content - tags:(const app_list::SearchResult::Tags&)tags; - -- (NSAttributedString*)createResultsAttributedStringWithModel - :(app_list::SearchResult*)result; - -@end - -// Simple extension to NSTableView that passes mouseDown events to the -// delegate so that drag events can be detected, and forwards requests for -// context menus. -@interface AppsSearchResultsTableView : NSTableView - -- (AppsSearchResultsController*)controller; - -@end - -@implementation AppsSearchResultsController - -@synthesize delegate = delegate_; - -- (id)initWithAppsSearchResultsFrameSize:(NSSize)size { - if ((self = [super init])) { - hoveredRowIndex_ = -1; - [self loadAndSetViewWithResultsFrameSize:size]; - } - return self; -} - -- (app_list::AppListModel::SearchResults*)results { - DCHECK([delegate_ appListModel]); - return [delegate_ appListModel]->results(); -} - -- (NSTableView*)tableView { - return tableView_; -} - -- (void)setDelegate:(id<AppsSearchResultsDelegate>)newDelegate { - bridge_.reset(); - delegate_ = newDelegate; - app_list::AppListModel* appListModel = [delegate_ appListModel]; - if (!appListModel || !appListModel->results()) { - [tableView_ reloadData]; - return; - } - - bridge_.reset(new app_list::AppsSearchResultsModelBridge(self)); - [tableView_ reloadData]; -} - -- (BOOL)handleCommandBySelector:(SEL)command { - if (command == @selector(insertNewline:) || - command == @selector(insertLineBreak:)) { - [self activateSelection]; - return YES; - } - - if (command == @selector(moveUp:)) - return [self moveSelectionByDelta:-1]; - - if (command == @selector(moveDown:)) - return [self moveSelectionByDelta:1]; - - return NO; -} - -- (void)loadAndSetViewWithResultsFrameSize:(NSSize)size { - tableView_.reset( - [[AppsSearchResultsTableView alloc] initWithFrame:NSZeroRect]); - // Refuse first responder so that focus stays with the search text field. - [tableView_ setRefusesFirstResponder:YES]; - [tableView_ setRowHeight:kPreferredRowHeight]; - [tableView_ setGridStyleMask:NSTableViewSolidHorizontalGridLineMask]; - [tableView_ - setGridColor:skia::SkColorToSRGBNSColor(app_list::kResultBorderColor)]; - [tableView_ setBackgroundColor:[NSColor clearColor]]; - [tableView_ setAction:@selector(tableViewClicked:)]; - [tableView_ setDelegate:self]; - [tableView_ setDataSource:self]; - [tableView_ setTarget:self]; - - // Tracking to highlight an individual row on mouseover. - trackingArea_.reset( - [[CrTrackingArea alloc] initWithRect:NSZeroRect - options:NSTrackingInVisibleRect | - NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveInKeyWindow - owner:self - userInfo:nil]); - [tableView_ addTrackingArea:trackingArea_.get()]; - - base::scoped_nsobject<NSTableColumn> resultsColumn( - [[NSTableColumn alloc] initWithIdentifier:@""]); - base::scoped_nsobject<NSCell> resultsDataCell( - [[AppsSearchResultsCell alloc] initTextCell:@""]); - [resultsColumn setDataCell:resultsDataCell]; - [resultsColumn setWidth:size.width]; - [tableView_ addTableColumn:resultsColumn]; - - // An NSTableView is normally put in a NSScrollView, but scrolling is not - // used for the app list. Instead, place it in a container with the desired - // size; flipped so the table is anchored to the top-left. - base::scoped_nsobject<FlippedView> containerView([[FlippedView alloc] - initWithFrame:NSMakeRect(0, 0, size.width, size.height)]); - - // The container is then anchored in an un-flipped view, initially hidden, - // so that |containerView| slides in from the top when showing results. - base::scoped_nsobject<NSView> clipView( - [[NSView alloc] initWithFrame:NSMakeRect(0, 0, size.width, 0)]); - - [containerView addSubview:tableView_]; - [clipView addSubview:containerView]; - [self setView:clipView]; -} - -- (void)mouseDown:(NSEvent*)theEvent { - lastMouseDownInView_ = [tableView_ convertPoint:[theEvent locationInWindow] - fromView:nil]; -} - -- (void)tableViewClicked:(id)sender { - const CGFloat kDragThreshold = 5; - // If the user clicked and then dragged elsewhere, ignore the click. - NSEvent* event = [[tableView_ window] currentEvent]; - NSPoint pointInView = [tableView_ convertPoint:[event locationInWindow] - fromView:nil]; - CGFloat deltaX = pointInView.x - lastMouseDownInView_.x; - CGFloat deltaY = pointInView.y - lastMouseDownInView_.y; - if (deltaX * deltaX + deltaY * deltaY <= kDragThreshold * kDragThreshold) - [self activateSelection]; - - // Mouse tracking is suppressed by the NSTableView during a drag, so ensure - // any hover state is cleaned up. - [self mouseMoved:event]; -} - -- (app_list::AppListModel::SearchResults*)searchResults { - app_list::AppListModel* appListModel = [delegate_ appListModel]; - DCHECK(bridge_); - DCHECK(appListModel); - DCHECK(appListModel->results()); - return appListModel->results(); -} - -- (void)activateSelection { - NSInteger selectedRow = [tableView_ selectedRow]; - if (!bridge_ || selectedRow < 0) - return; - - [delegate_ openResult:[self searchResults]->GetItemAt(selectedRow)]; -} - -- (BOOL)moveSelectionByDelta:(NSInteger)delta { - NSInteger rowCount = [tableView_ numberOfRows]; - if (rowCount <= 0) - return NO; - - NSInteger selectedRow = [tableView_ selectedRow]; - NSInteger targetRow; - if (selectedRow == -1) { - // No selection. Select first or last, based on direction. - targetRow = delta > 0 ? 0 : rowCount - 1; - } else { - targetRow = (selectedRow + delta) % rowCount; - if (targetRow < 0) - targetRow += rowCount; - } - - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:targetRow] - byExtendingSelection:NO]; - return YES; -} - -- (NSMenu*)contextMenuForRow:(NSInteger)rowIndex { - DCHECK(bridge_); - if (rowIndex < 0) - return nil; - - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex] - byExtendingSelection:NO]; - return bridge_->MenuForItem(rowIndex); -} - -- (NSInteger)numberOfRowsInTableView:(NSTableView*)aTableView { - return bridge_ ? [self searchResults]->item_count() : 0; -} - -- (id)tableView:(NSTableView*)aTableView - objectValueForTableColumn:(NSTableColumn*)aTableColumn - row:(NSInteger)rowIndex { - // When the results were previously cleared, nothing will be selected. For - // that case, select the first row when it appears. - if (rowIndex == 0 && [tableView_ selectedRow] == -1) { - [tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:0] - byExtendingSelection:NO]; - } - - base::scoped_nsobject<AppsSearchResultRep> resultRep( - [[AppsSearchResultRep alloc] - initWithSearchResult:[self searchResults]->GetItemAt(rowIndex)]); - return resultRep.autorelease(); -} - -- (void)tableView:(NSTableView*)tableView - willDisplayCell:(id)cell - forTableColumn:(NSTableColumn*)tableColumn - row:(NSInteger)rowIndex { - if (rowIndex == [tableView selectedRow]) - [cell setBackgroundStyle:kBackgroundSelected]; - else if (rowIndex == hoveredRowIndex_) - [cell setBackgroundStyle:kBackgroundHovered]; - else - [cell setBackgroundStyle:kBackgroundNormal]; -} - -- (void)mouseExited:(NSEvent*)theEvent { - if (hoveredRowIndex_ == -1) - return; - - [tableView_ setNeedsDisplayInRect:[tableView_ rectOfRow:hoveredRowIndex_]]; - hoveredRowIndex_ = -1; -} - -- (void)mouseMoved:(NSEvent*)theEvent { - NSPoint pointInView = [tableView_ convertPoint:[theEvent locationInWindow] - fromView:nil]; - NSInteger newIndex = [tableView_ rowAtPoint:pointInView]; - if (newIndex == hoveredRowIndex_) - return; - - if (newIndex != -1) - [tableView_ setNeedsDisplayInRect:[tableView_ rectOfRow:newIndex]]; - if (hoveredRowIndex_ != -1) - [tableView_ setNeedsDisplayInRect:[tableView_ rectOfRow:hoveredRowIndex_]]; - hoveredRowIndex_ = newIndex; -} - -@end - -@implementation AppsSearchResultRep - -- (NSAttributedString*)attributedStringValue { - return attributedStringValue_; -} - -- (NSImage*)resultIcon { - return resultIcon_; -} - -- (id)initWithSearchResult:(app_list::SearchResult*)result { - if ((self = [super init])) { - attributedStringValue_.reset( - [[self createResultsAttributedStringWithModel:result] retain]); - if (!result->icon().isNull()) { - resultIcon_.reset([gfx::NSImageFromImageSkiaWithColorSpace( - result->icon(), base::mac::GetSRGBColorSpace()) retain]); - } - } - return self; -} - -- (NSMutableAttributedString*)createRenderText:(const base::string16&)content - tags:(const app_list::SearchResult::Tags&)tags { - NSFont* boldFont = nil; - base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( - [[NSMutableParagraphStyle alloc] init]); - [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; - NSDictionary* defaultAttributes = @{ - NSForegroundColorAttributeName : - skia::SkColorToSRGBNSColor(app_list::kResultDefaultTextColor), - NSParagraphStyleAttributeName : paragraphStyle - }; - - base::scoped_nsobject<NSMutableAttributedString> text( - [[NSMutableAttributedString alloc] - initWithString:base::SysUTF16ToNSString(content) - attributes:defaultAttributes]); - - for (app_list::SearchResult::Tags::const_iterator it = tags.begin(); - it != tags.end(); ++it) { - if (it->styles == app_list::SearchResult::Tag::NONE) - continue; - - if (it->styles & app_list::SearchResult::Tag::MATCH) { - if (!boldFont) { - NSFontManager* fontManager = [NSFontManager sharedFontManager]; - boldFont = [fontManager convertFont:[NSFont controlContentFontOfSize:0] - toHaveTrait:NSBoldFontMask]; - } - [text addAttribute:NSFontAttributeName - value:boldFont - range:it->range.ToNSRange()]; - } - - if (it->styles & app_list::SearchResult::Tag::DIM) { - NSColor* dimmedColor = - skia::SkColorToSRGBNSColor(app_list::kResultDimmedTextColor); - [text addAttribute:NSForegroundColorAttributeName - value:dimmedColor - range:it->range.ToNSRange()]; - } else if (it->styles & app_list::SearchResult::Tag::URL) { - NSColor* urlColor = - skia::SkColorToSRGBNSColor(app_list::kResultURLTextColor); - [text addAttribute:NSForegroundColorAttributeName - value:urlColor - range:it->range.ToNSRange()]; - } - } - - return text.autorelease(); -} - -- (NSAttributedString*)createResultsAttributedStringWithModel - :(app_list::SearchResult*)result { - NSMutableAttributedString* titleText = - [self createRenderText:result->title() - tags:result->title_tags()]; - if (!result->details().empty()) { - NSMutableAttributedString* detailText = - [self createRenderText:result->details() - tags:result->details_tags()]; - base::scoped_nsobject<NSAttributedString> lineBreak( - [[NSAttributedString alloc] initWithString:@"\n"]); - [titleText appendAttributedString:lineBreak]; - [titleText appendAttributedString:detailText]; - } - return titleText; -} - -- (id)copyWithZone:(NSZone*)zone { - return [self retain]; -} - -@end - -@implementation AppsSearchResultsTableView - -- (AppsSearchResultsController*)controller { - return base::mac::ObjCCastStrict<AppsSearchResultsController>( - [self delegate]); -} - -- (void)mouseDown:(NSEvent*)theEvent { - [[self controller] mouseDown:theEvent]; - [super mouseDown:theEvent]; -} - -- (NSMenu*)menuForEvent:(NSEvent*)theEvent { - NSPoint pointInView = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - return [[self controller] contextMenuForRow:[self rowAtPoint:pointInView]]; -} - -@end - -@implementation AppsSearchResultsCell - -- (void)drawWithFrame:(NSRect)cellFrame - inView:(NSView*)controlView { - if ([self backgroundStyle] != kBackgroundNormal) { - if ([self backgroundStyle] == kBackgroundSelected) - [skia::SkColorToSRGBNSColor(kSelectedRowColor) set]; - else - [skia::SkColorToSRGBNSColor(kHighlightedRowColor) set]; - - // Extend up by one pixel to draw over cell border. - NSRect backgroundRect = cellFrame; - backgroundRect.origin.y -= 1; - backgroundRect.size.height += 1; - NSRectFill(backgroundRect); - } - - NSAttributedString* titleText = [self attributedStringValue]; - NSRect titleRect = cellFrame; - titleRect.size.width -= kTextTrailPadding + kIconViewWidth; - titleRect.origin.x += kIconViewWidth; - titleRect.origin.y += - floor(NSHeight(cellFrame) / 2 - [titleText size].height / 2); - // Ensure no drawing occurs outside of the cell. - titleRect = NSIntersectionRect(titleRect, cellFrame); - - [titleText drawInRect:titleRect]; - - NSImage* resultIcon = [[self objectValue] resultIcon]; - if (!resultIcon) - return; - - NSSize iconSize = [resultIcon size]; - NSRect iconRect = NSMakeRect( - floor(NSMinX(cellFrame) + kIconViewWidth / 2 - iconSize.width / 2), - floor(NSMinY(cellFrame) + kPreferredRowHeight / 2 - iconSize.height / 2), - std::min(iconSize.width, kIconDimension), - std::min(iconSize.height, kIconDimension)); - [resultIcon drawInRect:iconRect - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0 - respectFlipped:YES - hints:nil]; -} - -@end
diff --git a/ui/app_list/cocoa/apps_search_results_controller_unittest.mm b/ui/app_list/cocoa/apps_search_results_controller_unittest.mm deleted file mode 100644 index 78d0730b..0000000 --- a/ui/app_list/cocoa/apps_search_results_controller_unittest.mm +++ /dev/null
@@ -1,301 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_search_results_controller.h" - -#include <stddef.h> - -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/stringprintf.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#import "testing/gtest_mac.h" -#include "ui/app_list/test/app_list_test_model.h" -#include "ui/app_list/test/test_search_result.h" -#include "ui/base/models/simple_menu_model.h" -#import "ui/events/test/cocoa_test_event_utils.h" -#include "ui/gfx/image/image_skia_util_mac.h" -#import "ui/gfx/test/ui_cocoa_test_helper.h" - -@interface TestAppsSearchResultsDelegate : NSObject<AppsSearchResultsDelegate> { - @private - app_list::test::AppListTestModel appListModel_; - app_list::SearchResult* lastOpenedResult_; -} - -@property(readonly, nonatomic) app_list::SearchResult* lastOpenedResult; - -- (void)quitMessageLoop; - -@end - -@implementation TestAppsSearchResultsDelegate - -@synthesize lastOpenedResult = lastOpenedResult_; - -- (app_list::AppListModel*)appListModel { - return &appListModel_; -} - -- (void)openResult:(app_list::SearchResult*)result { - lastOpenedResult_ = result; -} - -- (void)quitMessageLoop { - base::MessageLoop::current()->QuitNow(); -} - -@end - -namespace app_list { -namespace test { -namespace { - -const int kDefaultResultsCount = 3; - -class SearchResultWithMenu : public TestSearchResult { - public: - SearchResultWithMenu(const std::string& title, const std::string& details) - : menu_model_(NULL), - menu_ready_(true) { - set_title(base::ASCIIToUTF16(title)); - set_details(base::ASCIIToUTF16(details)); - menu_model_.AddItem(0, base::UTF8ToUTF16("Menu For: " + title)); - } - - void SetMenuReadyForTesting(bool ready) { - menu_ready_ = ready; - } - - ui::MenuModel* GetContextMenuModel() override { - if (!menu_ready_) - return NULL; - - return &menu_model_; - } - - private: - ui::SimpleMenuModel menu_model_; - bool menu_ready_; - - DISALLOW_COPY_AND_ASSIGN(SearchResultWithMenu); -}; - -class AppsSearchResultsControllerTest : public ui::CocoaTest { - public: - AppsSearchResultsControllerTest() {} - - void AddTestResultAtIndex(size_t index, - const std::string& title, - const std::string& details) { - std::unique_ptr<SearchResult> result( - new SearchResultWithMenu(title, details)); - AppListModel::SearchResults* results = [delegate_ appListModel]->results(); - results->AddAt(index, result.release()); - } - - SearchResult* ModelResultAt(size_t index) { - return [delegate_ appListModel]->results()->GetItemAt(index); - } - - NSCell* ViewResultAt(NSInteger index) { - NSTableView* table_view = [apps_search_results_controller_ tableView]; - return [table_view preparedCellAtColumn:0 - row:index]; - } - - void SetMenuReadyAt(size_t index, bool ready) { - SearchResultWithMenu* result = - static_cast<SearchResultWithMenu*>(ModelResultAt(index)); - result->SetMenuReadyForTesting(ready); - } - - BOOL SimulateKeyAction(SEL c) { - return [apps_search_results_controller_ handleCommandBySelector:c]; - } - - void ExpectConsistent(); - - // ui::CocoaTest overrides: - void SetUp() override; - void TearDown() override; - - protected: - base::scoped_nsobject<TestAppsSearchResultsDelegate> delegate_; - base::scoped_nsobject<AppsSearchResultsController> - apps_search_results_controller_; - - private: - DISALLOW_COPY_AND_ASSIGN(AppsSearchResultsControllerTest); -}; - -void AppsSearchResultsControllerTest::ExpectConsistent() { - NSInteger item_count = [delegate_ appListModel]->results()->item_count(); - ASSERT_EQ(item_count, - [[apps_search_results_controller_ tableView] numberOfRows]); - - // Compare content strings to ensure the order of items is consistent, and any - // model data that should have been reloaded has been reloaded in the view. - for (NSInteger i = 0; i < item_count; ++i) { - SearchResult* result = ModelResultAt(i); - base::string16 string_in_model = result->title(); - if (!result->details().empty()) - string_in_model += base::ASCIIToUTF16("\n") + result->details(); - EXPECT_NSEQ(base::SysUTF16ToNSString(string_in_model), - [[ViewResultAt(i) attributedStringValue] string]); - } -} - -void AppsSearchResultsControllerTest::SetUp() { - apps_search_results_controller_.reset( - [[AppsSearchResultsController alloc] initWithAppsSearchResultsFrameSize: - NSMakeSize(400, 400)]); - // The view is initially hidden. Give it a non-zero height so it draws. - [[apps_search_results_controller_ view] setFrameSize:NSMakeSize(400, 400)]; - - delegate_.reset([[TestAppsSearchResultsDelegate alloc] init]); - - // Populate with some results so that TEST_VIEW does something non-trivial. - for (int i = 0; i < kDefaultResultsCount; ++i) - AddTestResultAtIndex(i, base::StringPrintf("Result %d", i), "ItemDetail"); - - SearchResult::Tags test_tags; - // Apply markup to the substring "Result" in the first item. - test_tags.push_back(SearchResult::Tag(SearchResult::Tag::NONE, 0, 1)); - test_tags.push_back(SearchResult::Tag(SearchResult::Tag::URL, 1, 2)); - test_tags.push_back(SearchResult::Tag(SearchResult::Tag::MATCH, 2, 3)); - test_tags.push_back(SearchResult::Tag(SearchResult::Tag::DIM, 3, 4)); - test_tags.push_back(SearchResult::Tag(SearchResult::Tag::MATCH | - SearchResult::Tag::URL, 4, 5)); - test_tags.push_back(SearchResult::Tag(SearchResult::Tag::MATCH | - SearchResult::Tag::DIM, 5, 6)); - - SearchResult* result = ModelResultAt(0); - result->SetIcon(gfx::ImageSkiaFromNSImage( - [NSImage imageNamed:NSImageNameStatusAvailable])); - result->set_title_tags(test_tags); - - [apps_search_results_controller_ setDelegate:delegate_]; - - ui::CocoaTest::SetUp(); - [[test_window() contentView] addSubview: - [apps_search_results_controller_ view]]; -} - -void AppsSearchResultsControllerTest::TearDown() { - [apps_search_results_controller_ setDelegate:nil]; - ui::CocoaTest::TearDown(); -} - -NSEvent* MouseEventInRow(NSTableView* table_view, NSInteger row_index) { - NSRect row_rect = [table_view rectOfRow:row_index]; - NSPoint point_in_view = NSMakePoint(NSMidX(row_rect), NSMidY(row_rect)); - NSPoint point_in_window = [table_view convertPoint:point_in_view - toView:nil]; - return cocoa_test_event_utils::LeftMouseDownAtPoint(point_in_window); -} - -} // namespace - -TEST_VIEW(AppsSearchResultsControllerTest, - [apps_search_results_controller_ view]); - -TEST_F(AppsSearchResultsControllerTest, ModelObservers) { - NSTableView* table_view = [apps_search_results_controller_ tableView]; - ExpectConsistent(); - - EXPECT_EQ(1, [table_view numberOfColumns]); - EXPECT_EQ(kDefaultResultsCount, [table_view numberOfRows]); - - // Insert at start. - AddTestResultAtIndex(0, "One", std::string()); - EXPECT_EQ(kDefaultResultsCount + 1, [table_view numberOfRows]); - ExpectConsistent(); - - // Remove from end. - [delegate_ appListModel]->results()->DeleteAt(kDefaultResultsCount); - EXPECT_EQ(kDefaultResultsCount, [table_view numberOfRows]); - ExpectConsistent(); - - // Insert at end. - AddTestResultAtIndex(kDefaultResultsCount, "Four", std::string()); - EXPECT_EQ(kDefaultResultsCount + 1, [table_view numberOfRows]); - ExpectConsistent(); - - // Delete from start. - [delegate_ appListModel]->results()->DeleteAt(0); - EXPECT_EQ(kDefaultResultsCount, [table_view numberOfRows]); - ExpectConsistent(); - - // Test clearing results. - [delegate_ appListModel]->results()->DeleteAll(); - EXPECT_EQ(0, [table_view numberOfRows]); - ExpectConsistent(); -} - -TEST_F(AppsSearchResultsControllerTest, KeyboardSelectAndActivate) { - NSTableView* table_view = [apps_search_results_controller_ tableView]; - EXPECT_EQ(-1, [table_view selectedRow]); - - // Pressing up when nothing is selected should select the last item. - EXPECT_TRUE(SimulateKeyAction(@selector(moveUp:))); - EXPECT_EQ(kDefaultResultsCount - 1, [table_view selectedRow]); - [table_view deselectAll:nil]; - EXPECT_EQ(-1, [table_view selectedRow]); - - // Pressing down when nothing is selected should select the first item. - EXPECT_TRUE(SimulateKeyAction(@selector(moveDown:))); - EXPECT_EQ(0, [table_view selectedRow]); - - // Pressing up should wrap around. - EXPECT_TRUE(SimulateKeyAction(@selector(moveUp:))); - EXPECT_EQ(kDefaultResultsCount - 1, [table_view selectedRow]); - - // Down should now also wrap, since the selection is at the end. - EXPECT_TRUE(SimulateKeyAction(@selector(moveDown:))); - EXPECT_EQ(0, [table_view selectedRow]); - - // Regular down and up movement, ensuring the cells have correct backgrounds. - EXPECT_TRUE(SimulateKeyAction(@selector(moveDown:))); - EXPECT_EQ(1, [table_view selectedRow]); - EXPECT_EQ(NSBackgroundStyleDark, [ViewResultAt(1) backgroundStyle]); - EXPECT_EQ(NSBackgroundStyleLight, [ViewResultAt(0) backgroundStyle]); - - EXPECT_TRUE(SimulateKeyAction(@selector(moveUp:))); - EXPECT_EQ(0, [table_view selectedRow]); - EXPECT_EQ(NSBackgroundStyleDark, [ViewResultAt(0) backgroundStyle]); - EXPECT_EQ(NSBackgroundStyleLight, [ViewResultAt(1) backgroundStyle]); - - // Test activating items. - EXPECT_TRUE(SimulateKeyAction(@selector(insertNewline:))); - EXPECT_EQ(ModelResultAt(0), [delegate_ lastOpenedResult]); - EXPECT_TRUE(SimulateKeyAction(@selector(moveDown:))); - EXPECT_TRUE(SimulateKeyAction(@selector(insertNewline:))); - EXPECT_EQ(ModelResultAt(1), [delegate_ lastOpenedResult]); -} - -TEST_F(AppsSearchResultsControllerTest, ContextMenus) { - NSTableView* table_view = [apps_search_results_controller_ tableView]; - NSEvent* mouse_in_row_0 = MouseEventInRow(table_view, 0); - NSEvent* mouse_in_row_1 = MouseEventInRow(table_view, 1); - - NSMenu* menu = [table_view menuForEvent:mouse_in_row_0]; - EXPECT_EQ(1, [menu numberOfItems]); - EXPECT_NSEQ(@"Menu For: Result 0", [[menu itemAtIndex:0] title]); - - // Test a context menu request while the item is still installing. - SetMenuReadyAt(1, false); - menu = [table_view menuForEvent:mouse_in_row_1]; - EXPECT_EQ(nil, menu); - - SetMenuReadyAt(1, true); - menu = [table_view menuForEvent:mouse_in_row_1]; - EXPECT_EQ(1, [menu numberOfItems]); - EXPECT_NSEQ(@"Menu For: Result 1", [[menu itemAtIndex:0] title]); -} - -} // namespace test -} // namespace app_list
diff --git a/ui/app_list/cocoa/apps_search_results_model_bridge.h b/ui/app_list/cocoa/apps_search_results_model_bridge.h deleted file mode 100644 index c29487b..0000000 --- a/ui/app_list/cocoa/apps_search_results_model_bridge.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_MODEL_BRIDGE_H_ -#define UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_MODEL_BRIDGE_H_ - -#include <stddef.h> - -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "base/memory/scoped_vector.h" -#include "ui/base/models/list_model_observer.h" - -@class NSMenu; -@class AppsSearchResultsController; - -namespace app_list { - -// Bridge observing the ListModel representing search results in the app list, -// and updating the NSTableView where they are displayed. -class AppsSearchResultsModelBridge : public ui::ListModelObserver { - public: - explicit AppsSearchResultsModelBridge( - AppsSearchResultsController* results_controller); - ~AppsSearchResultsModelBridge() override; - - // Returns the context menu for the item at |index| in the search results - // model. A menu will be generated if it hasn't been previously requested. - NSMenu* MenuForItem(size_t index); - - private: - // Lightweight observer to react to icon updates on individual results. - class ItemObserver; - - void UpdateItemObservers(); - void ReloadDataForItems(size_t start, size_t count) const; - - // Overridden from ui::ListModelObserver: - void ListItemsAdded(size_t start, size_t count) override; - void ListItemsRemoved(size_t start, size_t count) override; - void ListItemMoved(size_t index, size_t target_index) override; - void ListItemsChanged(size_t start, size_t count) override; - - AppsSearchResultsController* parent_; // Weak. Owns us. - ScopedVector<ItemObserver> item_observers_; - - DISALLOW_COPY_AND_ASSIGN(AppsSearchResultsModelBridge); -}; - -} // namespace app_list - -#endif // UI_APP_LIST_COCOA_APPS_SEARCH_RESULTS_MODEL_BRIDGE_H_
diff --git a/ui/app_list/cocoa/apps_search_results_model_bridge.mm b/ui/app_list/cocoa/apps_search_results_model_bridge.mm deleted file mode 100644 index bbe09ae..0000000 --- a/ui/app_list/cocoa/apps_search_results_model_bridge.mm +++ /dev/null
@@ -1,126 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/apps_search_results_model_bridge.h" - -#import <Cocoa/Cocoa.h> - -#include "base/macros.h" -#include "base/strings/sys_string_conversions.h" -#include "ui/app_list/app_list_model.h" -#import "ui/app_list/cocoa/apps_search_results_controller.h" -#include "ui/app_list/search_result.h" -#include "ui/app_list/search_result_observer.h" -#import "ui/base/cocoa/menu_controller.h" - -namespace app_list { - -class AppsSearchResultsModelBridge::ItemObserver : public SearchResultObserver { - public: - ItemObserver(AppsSearchResultsModelBridge* bridge, size_t index) - : bridge_(bridge), row_in_view_(index) { - // Cache the result, because the results array is updated before notifying - // observers (which happens before deleting the SearchResult). - result_ = [bridge_->parent_ results]->GetItemAt(index); - result_->AddObserver(this); - } - - ~ItemObserver() override { result_->RemoveObserver(this); } - - NSMenu* GetContextMenu() { - if (!context_menu_controller_) { - ui::MenuModel* menu_model = result_->GetContextMenuModel(); - if (!menu_model) - return nil; - - context_menu_controller_.reset( - [[MenuController alloc] initWithModel:menu_model - useWithPopUpButtonCell:NO]); - } - return [context_menu_controller_ menu]; - } - - // SearchResultObserver overrides: - void OnIconChanged() override { - bridge_->ReloadDataForItems(row_in_view_, 1); - } - void OnActionsChanged() override {} - void OnIsInstallingChanged() override {} - void OnPercentDownloadedChanged() override {} - void OnItemInstalled() override {} - - private: - AppsSearchResultsModelBridge* bridge_; // Weak. Owns us. - SearchResult* result_; // Weak. Owned by AppListModel::SearchResults. - size_t row_in_view_; - base::scoped_nsobject<MenuController> context_menu_controller_; - - DISALLOW_COPY_AND_ASSIGN(ItemObserver); -}; - -AppsSearchResultsModelBridge::AppsSearchResultsModelBridge( - AppsSearchResultsController* results_controller) - : parent_(results_controller) { - UpdateItemObservers(); - [parent_ results]->AddObserver(this); -} - -AppsSearchResultsModelBridge::~AppsSearchResultsModelBridge() { - [parent_ results]->RemoveObserver(this); -} - -NSMenu* AppsSearchResultsModelBridge::MenuForItem(size_t index) { - DCHECK_LT(index, item_observers_.size()); - return item_observers_[index]->GetContextMenu(); -} - -void AppsSearchResultsModelBridge::UpdateItemObservers() { - DCHECK(item_observers_.empty()); - const size_t itemCount = [parent_ results]->item_count(); - for (size_t i = 0 ; i < itemCount; ++i) - item_observers_.push_back(new ItemObserver(this, i)); -} - -void AppsSearchResultsModelBridge::ReloadDataForItems( - size_t start, size_t count) const { - NSIndexSet* column = [NSIndexSet indexSetWithIndex:0]; - NSIndexSet* rows = - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(start, count)]; - [[parent_ tableView] reloadDataForRowIndexes:rows - columnIndexes:column]; -} - -void AppsSearchResultsModelBridge::ListItemsAdded( - size_t start, size_t count) { - item_observers_.clear(); - if (start == static_cast<size_t>([[parent_ tableView] numberOfRows])) - [[parent_ tableView] noteNumberOfRowsChanged]; - else - [[parent_ tableView] reloadData]; - UpdateItemObservers(); -} - -void AppsSearchResultsModelBridge::ListItemsRemoved( - size_t start, size_t count) { - item_observers_.clear(); - if (start == [parent_ results]->item_count()) - [[parent_ tableView] noteNumberOfRowsChanged]; - else - [[parent_ tableView] reloadData]; - UpdateItemObservers(); -} - -void AppsSearchResultsModelBridge::ListItemMoved( - size_t index, size_t target_index) { - NOTREACHED(); -} - -void AppsSearchResultsModelBridge::ListItemsChanged( - size_t start, size_t count) { - item_observers_.clear(); - ReloadDataForItems(start, count); - UpdateItemObservers(); -} - -} // namespace app_list
diff --git a/ui/app_list/cocoa/item_drag_controller.h b/ui/app_list/cocoa/item_drag_controller.h deleted file mode 100644 index 3e5b045b..0000000 --- a/ui/app_list/cocoa/item_drag_controller.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_ITEM_DRAG_CONTROLLER_H_ -#define UI_APP_LIST_COCOA_ITEM_DRAG_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> -#import <QuartzCore/QuartzCore.h> - -#include "base/mac/scoped_nsobject.h" - -@class AppsGridViewItem; - -// Controller to manage the animations and transient views that are used when -// dragging an app list item around the app list grid. When initiated, the item -// image (only) is grown in an animation, and sticks to the mouse cursor. When -// released, the label is added to the image and it shrinks and moves to the -// item location in the grid. -@interface ItemDragController : NSViewController { - @private - base::scoped_nsobject<CALayer> dragLayer_; - base::scoped_nsobject<NSButton> buttonToRestore_; - NSPoint mouseOffset_; - NSTimeInterval growStart_; - BOOL shrinking_; -} - -- (id)initWithGridCellSize:(NSSize)size; - -- (void)initiate:(AppsGridViewItem*)item - mouseDownLocation:(NSPoint)mouseDownLocation - currentLocation:(NSPoint)currentLocation - timestamp:(NSTimeInterval)eventTimestamp; - -- (void)update:(NSPoint)currentLocation - timestamp:(NSTimeInterval)eventTimestamp; - -- (void)complete:(AppsGridViewItem*)item - targetOrigin:(NSPoint)targetOrigin; - -@end - -#endif // UI_APP_LIST_COCOA_ITEM_DRAG_CONTROLLER_H_
diff --git a/ui/app_list/cocoa/item_drag_controller.mm b/ui/app_list/cocoa/item_drag_controller.mm deleted file mode 100644 index 1de425b..0000000 --- a/ui/app_list/cocoa/item_drag_controller.mm +++ /dev/null
@@ -1,184 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/item_drag_controller.h" - -#include "base/logging.h" -#import "ui/app_list/cocoa/apps_grid_view_item.h" -#include "ui/base/cocoa/window_size_constants.h" - -// Scale to transform the grid cell when a drag starts. Note that 1.5 ensures -// that integers are used for the layer bounds when the grid cell dimensions -// are even. -const CGFloat kDraggingIconScale = 1.5; - -const NSTimeInterval kAnimationDuration = 0.2; - - -@interface ItemDragController () - -- (void)animateTransformFrom:(CATransform3D)fromValue - useDelegate:(BOOL)useDelegate; - -- (void)clearAnimations; - -@end - -@implementation ItemDragController - -- (id)initWithGridCellSize:(NSSize)size { - if ((self = [super init])) { - NSRect frameRect = NSMakeRect(0, - 0, - size.width * kDraggingIconScale, - size.height * kDraggingIconScale); - base::scoped_nsobject<NSView> dragView( - [[NSView alloc] initWithFrame:frameRect]); - [dragView setWantsLayer:YES]; - [dragView setHidden:YES]; - - dragLayer_.reset([[CALayer layer] retain]); - [dragLayer_ setFrame:NSRectToCGRect(frameRect)]; - [[dragView layer] addSublayer:dragLayer_]; - - [self setView:dragView]; - } - return self; -} - -- (void)initiate:(AppsGridViewItem*)item - mouseDownLocation:(NSPoint)mouseDownLocation - currentLocation:(NSPoint)currentLocation - timestamp:(NSTimeInterval)eventTimestamp { - [self clearAnimations]; - NSView* itemView = [item view]; - NSPoint pointInGridCell = [itemView convertPoint:mouseDownLocation - fromView:nil]; - mouseOffset_ = NSMakePoint(pointInGridCell.x - NSMidX([itemView bounds]), - NSMidY([itemView bounds]) - pointInGridCell.y); - - NSBitmapImageRep* imageRep = [item dragRepresentationForRestore:NO]; - [dragLayer_ setContents:reinterpret_cast<id>([imageRep CGImage])]; - [dragLayer_ setTransform:CATransform3DIdentity]; - - // Add a grow animation to the layer. - CATransform3D growFrom = CATransform3DScale(CATransform3DIdentity, - 1.0 / kDraggingIconScale, - 1.0 / kDraggingIconScale, - 1.0); - [self animateTransformFrom:growFrom - useDelegate:NO]; - - growStart_ = eventTimestamp; - [[self view] setHidden:NO]; -} - -- (void)update:(NSPoint)currentLocation - timestamp:(NSTimeInterval)eventTimestamp { - NSPoint pointInSuperview = [[[self view] superview] - convertPoint:currentLocation - fromView:nil]; - NSRect rect = [[self view] bounds]; - NSPoint anchor = NSMakePoint(NSMidX(rect), NSMidY(rect)); - - // If the grow animation is still in progress, make the point of the image - // that was clicked appear stuck to the mouse cursor. - CGFloat progress = (eventTimestamp - growStart_) / kAnimationDuration; - CGFloat currentIconScale = progress < 1.0 ? - 1.0 + (kDraggingIconScale - 1.0) * progress : - kDraggingIconScale; - - pointInSuperview.x -= (mouseOffset_.x * currentIconScale + anchor.x); - pointInSuperview.y -= (mouseOffset_.y * currentIconScale + anchor.y); - [[self view] setFrameOrigin:pointInSuperview]; -} - -- (void)complete:(AppsGridViewItem*)item - targetOrigin:(NSPoint)targetOrigin { - [self clearAnimations]; - - NSView* itemView = [item view]; - NSBitmapImageRep* imageRep = [item dragRepresentationForRestore:YES]; - - [dragLayer_ setContents:reinterpret_cast<id>([imageRep CGImage])]; - [dragLayer_ setTransform:CATransform3DScale(CATransform3DIdentity, - 1.0 / kDraggingIconScale, - 1.0 / kDraggingIconScale, - 1.0)]; - - // Retain the button so it can be unhidden when the animation completes. Note - // that the |item| and corresponding button can differ from the |item| passed - // to initiate(), if it moved to a new page during the drag. At this point the - // destination page is known, so retain the button. - buttonToRestore_.reset([[item button] retain]); - - // Add the shrink animation for the layer. - [self animateTransformFrom:CATransform3DIdentity - useDelegate:YES]; - shrinking_ = YES; - - // Also animate the translation, on the view. - // TODO(tapted): This should be merged into the scale transform, instead of - // using a separate NSViewAnimation. - NSRect startRect = [[self view] frame]; - - // The final position needs to be adjusted since it shrinks from each side. - NSRect targetRect = NSMakeRect( - targetOrigin.x - NSMidX([itemView bounds]) * (kDraggingIconScale - 1), - targetOrigin.y - NSMidY([itemView bounds]) * (kDraggingIconScale - 1), - startRect.size.width, - startRect.size.height); - - NSDictionary* animationDict = @{ - NSViewAnimationTargetKey: [self view], - NSViewAnimationStartFrameKey: [NSValue valueWithRect:startRect], - NSViewAnimationEndFrameKey: [NSValue valueWithRect:targetRect] - }; - - base::scoped_nsobject<NSViewAnimation> translate([[NSViewAnimation alloc] - initWithViewAnimations:[NSArray arrayWithObject:animationDict]]); - [translate setDuration:kAnimationDuration]; - [translate startAnimation]; -} - -- (void)animateTransformFrom:(CATransform3D)fromValue - useDelegate:(BOOL)useDelegate { - CABasicAnimation* animation = - [CABasicAnimation animationWithKeyPath:@"transform"]; - [animation setFromValue:[NSValue valueWithCATransform3D:fromValue]]; - if (useDelegate) - [animation setDelegate:self]; - - [animation setDuration:kAnimationDuration]; - [CATransaction begin]; - [CATransaction setValue:[NSNumber numberWithFloat:kAnimationDuration] - forKey:kCATransactionAnimationDuration]; - [dragLayer_ addAnimation:animation - forKey:@"transform"]; - [CATransaction commit]; -} - -- (void)clearAnimations { - [dragLayer_ removeAllAnimations]; - if (!shrinking_) - return; - - DCHECK(buttonToRestore_); - [buttonToRestore_ setHidden:NO]; - buttonToRestore_.reset(); - shrinking_ = NO; -} - -- (void)animationDidStop:(CAAnimation*)anim - finished:(BOOL)finished { - if (!finished) - return; - - DCHECK(shrinking_); - [self clearAnimations]; - [dragLayer_ setContents:nil]; - [[self view] setHidden:YES]; -} - -@end
diff --git a/ui/app_list/cocoa/scroll_view_with_no_scrollbars.h b/ui/app_list/cocoa/scroll_view_with_no_scrollbars.h deleted file mode 100644 index 0697e240..0000000 --- a/ui/app_list/cocoa/scroll_view_with_no_scrollbars.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_SCROLL_VIEW_WITH_NO_SCROLLBARS_H_ -#define UI_APP_LIST_COCOA_SCROLL_VIEW_WITH_NO_SCROLLBARS_H_ - -#include <Cocoa/Cocoa.h> - -// Delegate to notify when a user interaction to scroll completes. -@protocol GestureScrollDelegate - -// Called when a scroll gesture is observed, or when it completes. -- (void)userScrolling:(BOOL)isScrolling; - -@end - -// NSScrollView has a quirk when created programatically that causes gesture -// scrolling to fail if it does not have a scroll bar. This provides a scroll -// view using custom scrollers that are not visible. -@interface ScrollViewWithNoScrollbars : NSScrollView { - @private - id<GestureScrollDelegate> delegate_; -} - -@property(assign, nonatomic) id<GestureScrollDelegate> delegate; - -@end - -#endif // UI_APP_LIST_COCOA_SCROLL_VIEW_WITH_NO_SCROLLBARS_H_
diff --git a/ui/app_list/cocoa/scroll_view_with_no_scrollbars.mm b/ui/app_list/cocoa/scroll_view_with_no_scrollbars.mm deleted file mode 100644 index d4cff30..0000000 --- a/ui/app_list/cocoa/scroll_view_with_no_scrollbars.mm +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/app_list/cocoa/scroll_view_with_no_scrollbars.h" - -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_nsobject.h" -#include "base/mac/sdk_forward_declarations.h" - -@interface InvisibleScroller : NSScroller; -@end - -@implementation InvisibleScroller - -// Makes it non-interactive (and invisible) on Lion with both 10.6 and 10.7 -// SDKs. TODO(tapted): Find a way to make it non-interactive on Snow Leopard. -// TODO(tapted): Find a way to make it take up no space on Lion with a 10.6 SDK. -- (NSRect)rectForPart:(NSScrollerPart)aPart { - return NSZeroRect; -} - -@end - -@implementation ScrollViewWithNoScrollbars - -@synthesize delegate = delegate_; - -- (id)initWithFrame:(NSRect)frame { - if ((self = [super initWithFrame:frame])) { - [self setHasHorizontalScroller:YES]; - NSRect horizontalScrollerRect = [self bounds]; - horizontalScrollerRect.size.height = 0; - base::scoped_nsobject<InvisibleScroller> horizontalScroller( - [[InvisibleScroller alloc] initWithFrame:horizontalScrollerRect]); - [self setHorizontalScroller:horizontalScroller]; - } - return self; -} - -- (void)scrollWheel:(NSEvent*)event { - if ([event subtype] == NSMouseEventSubtype) { - // Since the scroll view has no vertical scroller, regular up and down mouse - // wheel events would be ignored. This maps mouse wheel events to a - // horizontal scroll event of one line, to turn pages. - BOOL downOrRight; - if ([event deltaX] != 0) - downOrRight = [event deltaX] > 0; - else if ([event deltaY] != 0) - downOrRight = [event deltaY] > 0; - else - return; - - base::ScopedCFTypeRef<CGEventRef> cgEvent(CGEventCreateScrollWheelEvent( - NULL, kCGScrollEventUnitLine, 2, 0, downOrRight ? 1 : -1)); - [super scrollWheel:[NSEvent eventWithCGEvent:cgEvent]]; - return; - } - - [super scrollWheel:event]; - if (![event respondsToSelector:@selector(momentumPhase)]) - return; - - BOOL scrollComplete = [event momentumPhase] == NSEventPhaseEnded || - ([event momentumPhase] == NSEventPhaseNone && - [event phase] == NSEventPhaseEnded); - - [delegate_ userScrolling:!scrollComplete]; -} - -@end
diff --git a/ui/app_list/cocoa/test/apps_grid_controller_test_helper.h b/ui/app_list/cocoa/test/apps_grid_controller_test_helper.h deleted file mode 100644 index 3411638..0000000 --- a/ui/app_list/cocoa/test/apps_grid_controller_test_helper.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_APP_LIST_COCOA_TEST_APPS_GRID_CONTROLLER_TEST_HELPER_H_ -#define UI_APP_LIST_COCOA_TEST_APPS_GRID_CONTROLLER_TEST_HELPER_H_ - -#include <stddef.h> - -#include <memory> -#include <string> - -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#import "ui/gfx/test/ui_cocoa_test_helper.h" - -@class AppsGridController; - -namespace app_list { - -namespace test { - -class AppsGridControllerTestHelper : public ui::CocoaTest { - public: - static const size_t kItemsPerPage; - - AppsGridControllerTestHelper(); - ~AppsGridControllerTestHelper() override; - - void SetUpWithGridController(AppsGridController* grid_controller); - - protected: - // Send a click to the test window in the centre of |view|. - void SimulateClick(NSView* view); - - // Send a key action using handleCommandBySelector. - void SimulateKeyAction(SEL c); - - void SimulateMouseEnterItemAt(size_t index); - void SimulateMouseExitItemAt(size_t index); - - // Get a string representation of the items as they are currently ordered in - // the view. Each page will start and end with a | character. - std::string GetViewContent() const; - - // Find the page containing |item_id|, and return the index of that page. - // Return NSNotFound if the item is not found, or if the item appears more - // than once. - size_t GetPageIndexForItem(int item_id) const; - - void DelayForCollectionView(); - void SinkEvents(); - - NSButton* GetItemViewAt(size_t index); - NSCollectionView* GetPageAt(size_t index); - NSView* GetSelectedView(); - - AppsGridController* apps_grid_controller_; - - private: - base::MessageLoopForUI message_loop_; - - DISALLOW_COPY_AND_ASSIGN(AppsGridControllerTestHelper); -}; - -} // namespace test -} // namespace app_list - -#endif // UI_APP_LIST_COCOA_TEST_APPS_GRID_CONTROLLER_TEST_HELPER_H_
diff --git a/ui/app_list/cocoa/test/apps_grid_controller_test_helper.mm b/ui/app_list/cocoa/test/apps_grid_controller_test_helper.mm deleted file mode 100644 index df6a139e..0000000 --- a/ui/app_list/cocoa/test/apps_grid_controller_test_helper.mm +++ /dev/null
@@ -1,120 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ui/app_list/cocoa/test/apps_grid_controller_test_helper.h" - -#include "base/mac/foundation_util.h" -#include "base/strings/stringprintf.h" -#include "ui/app_list/app_list_item.h" -#import "ui/app_list/cocoa/apps_grid_controller.h" -#import "ui/app_list/cocoa/apps_grid_view_item.h" -#import "ui/events/test/cocoa_test_event_utils.h" - -namespace app_list { -namespace test { - -const size_t AppsGridControllerTestHelper::kItemsPerPage = 16; - -AppsGridControllerTestHelper::AppsGridControllerTestHelper() { - Init(); - [AppsGridController setScrollAnimationDuration:0.0]; -} - -AppsGridControllerTestHelper::~AppsGridControllerTestHelper() {} - -void AppsGridControllerTestHelper::SetUpWithGridController( - AppsGridController* grid_controller) { - ui::CocoaTest::SetUp(); - apps_grid_controller_ = grid_controller; -} - -void AppsGridControllerTestHelper::SimulateClick(NSView* view) { - std::pair<NSEvent*, NSEvent*> events( - cocoa_test_event_utils::MouseClickInView(view, 1)); - [NSApp postEvent:events.first atStart:NO]; - [NSApp postEvent:events.second atStart:NO]; -} - -void AppsGridControllerTestHelper::SimulateKeyAction(SEL c) { - [apps_grid_controller_ handleCommandBySelector:c]; -} - -void AppsGridControllerTestHelper::SimulateMouseEnterItemAt(size_t index) { - [[apps_grid_controller_ itemAtIndex:index] - mouseEntered:cocoa_test_event_utils::EnterEvent()]; -} - -void AppsGridControllerTestHelper::SimulateMouseExitItemAt(size_t index) { - [[apps_grid_controller_ itemAtIndex:index] - mouseExited:cocoa_test_event_utils::ExitEvent()]; -} - -std::string AppsGridControllerTestHelper::GetViewContent() const { - std::string s; - for (size_t page_index = 0; page_index < [apps_grid_controller_ pageCount]; - ++page_index) { - s += '|'; - NSCollectionView* page_view = - [apps_grid_controller_ collectionViewAtPageIndex:page_index]; - for (size_t i = 0; i < [[page_view content] count]; ++i) { - AppsGridViewItem* item = base::mac::ObjCCastStrict<AppsGridViewItem>( - [page_view itemAtIndex:i]); - if (i != 0) - s += ','; - s += [item model]->id(); - } - s += '|'; - } - return s; -} - -size_t AppsGridControllerTestHelper::GetPageIndexForItem(int item_id) const { - const std::string search = base::StringPrintf("Item %d", item_id); - size_t page_index = 0; - NSUInteger found_at_page_index = NSNotFound; - for (; page_index < [apps_grid_controller_ pageCount]; ++page_index) { - NSCollectionView* page_view = - [apps_grid_controller_ collectionViewAtPageIndex:page_index]; - for (NSUInteger i = 0; i < [[page_view content] count]; ++i) { - AppsGridViewItem* item = base::mac::ObjCCastStrict<AppsGridViewItem>( - [page_view itemAtIndex:i]); - if ([item model]->id() == search) { - if (found_at_page_index != NSNotFound) - return NSNotFound; // Duplicate. - found_at_page_index = page_index; - } - } - } - return found_at_page_index; -} - -void AppsGridControllerTestHelper::DelayForCollectionView() { - message_loop_.PostDelayedTask(FROM_HERE, - base::MessageLoop::QuitWhenIdleClosure(), - base::TimeDelta::FromMilliseconds(100)); - message_loop_.Run(); -} - -void AppsGridControllerTestHelper::SinkEvents() { - message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); - message_loop_.Run(); -} - -NSButton* AppsGridControllerTestHelper::GetItemViewAt(size_t index) { - if (index == NSNotFound) - return nil; - - return [[apps_grid_controller_ itemAtIndex:index] button]; -} - -NSCollectionView* AppsGridControllerTestHelper::GetPageAt(size_t index) { - return [apps_grid_controller_ collectionViewAtPageIndex:index]; -} - -NSView* AppsGridControllerTestHelper::GetSelectedView() { - return GetItemViewAt([apps_grid_controller_ selectedItemIndex]); -} - -} // namespace test -} // namespace app_list
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc index 80e855a..c2d4ea0d 100644 --- a/ui/gfx/mac/io_surface.cc +++ b/ui/gfx/mac/io_surface.cc
@@ -21,7 +21,7 @@ namespace { const base::Feature kIOSurfaceClearYosemite{"IOSurfaceClearYosemite", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key,
diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h index c7a4684..b580a671 100644 --- a/ui/gfx/transform.h +++ b/ui/gfx/transform.h
@@ -68,7 +68,6 @@ SkMScalar col2row2, SkMScalar x_translation, SkMScalar y_translation); - ~Transform() {} bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; } bool operator!=(const Transform& rhs) const { return matrix_ != rhs.matrix_; }
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h index f8122dc5..3cf1178 100644 --- a/ui/gl/test/gl_image_test_template.h +++ b/ui/gl/test/gl_image_test_template.h
@@ -211,6 +211,11 @@ // rendering. https://crbug.com/594343. if (base::mac::IsOSMavericks()) return; + + // This functionality is disabled on Yosemite because it is suspected of + // causing performance regressions on old hardware. https://crbug.com/606850. + if (base::mac::IsOSYosemite()) + return; #endif const gfx::Size image_size(256, 256);
diff --git a/ui/login/account_picker/user_pod_row.css b/ui/login/account_picker/user_pod_row.css index fd9b1ff..6f29c15 100644 --- a/ui/login/account_picker/user_pod_row.css +++ b/ui/login/account_picker/user_pod_row.css
@@ -185,8 +185,7 @@ .auth-container.pin-disabled { opacity: 1; - transition: opacity 200ms ease-in-out 180ms, - visibility 200ms ease-in-out 180ms; + transition: opacity 200ms ease-in-out 180ms; visibility: visible; }
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js index c258be18..ab4f576 100644 --- a/ui/login/account_picker/user_pod_row.js +++ b/ui/login/account_picker/user_pod_row.js
@@ -1137,6 +1137,12 @@ currentElement.classList.toggle('pin-enabled', visible); currentElement.classList.toggle('pin-disabled', !visible); } + + // Set the focus to the input element after showing/hiding pin keyboard. + if (visible) + this.pinKeyboard.focus(); + else + this.mainInput.focus(); }, setUserPodIconType: function(userTypeClass) {
diff --git a/ui/login/screen_container.css b/ui/login/screen_container.css index 9b3e13d..3825817 100644 --- a/ui/login/screen_container.css +++ b/ui/login/screen_container.css
@@ -23,8 +23,7 @@ .pin-container.pin-enabled { opacity: 1; - transition: opacity 200ms ease-in-out 180ms, - visibility 200ms ease-in-out 180ms; + transition: opacity 200ms ease-in-out 180ms; visibility: visible; }
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc index 69954dd..b683cdf 100644 --- a/ui/native_theme/native_theme_win.cc +++ b/ui/native_theme/native_theme_win.cc
@@ -21,8 +21,6 @@ #include "skia/ext/skia_utils_win.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkColorPriv.h" -#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkShader.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/display/win/dpi.h" @@ -251,43 +249,77 @@ CommonThemePaintMenuItemBackground(this, canvas, state, rect, extra.menu_item); return; + case kScrollbarCorner: + canvas->drawColor(SK_ColorWHITE, SkXfermode::kSrc_Mode); + return; default: break; } - bool needs_paint_indirect = false; - if (!skia::SupportsPlatformPaint(canvas)) { - // This block will only get hit with --enable-accelerated-drawing flag. - needs_paint_indirect = true; - } else { - // Scrollbar components on Windows Classic theme (on all Windows versions) - // have particularly problematic alpha values, so always draw them - // indirectly. In addition, scrollbar thumbs and grippers for the Windows XP - // theme (available only on Windows XP) also need their alpha values - // fixed. - switch (part) { - case kScrollbarDownArrow: - case kScrollbarUpArrow: - case kScrollbarLeftArrow: - case kScrollbarRightArrow: - needs_paint_indirect = !GetThemeHandle(SCROLLBAR); - break; - case kScrollbarHorizontalThumb: - case kScrollbarVerticalThumb: - case kScrollbarHorizontalGripper: - case kScrollbarVerticalGripper: - needs_paint_indirect = !GetThemeHandle(SCROLLBAR) || - base::win::GetVersion() == base::win::VERSION_XP; - break; - default: - break; - } - } + skia::ScopedPlatformPaint scoped_platform_paint(canvas); + HDC hdc = scoped_platform_paint.GetPlatformSurface(); - if (needs_paint_indirect) - PaintIndirect(canvas, part, state, rect, extra); - else - PaintDirect(canvas, part, state, rect, extra); + switch (part) { + case kCheckbox: + PaintCheckbox(hdc, part, state, rect, extra.button); + return; + case kInnerSpinButton: + PaintSpinButton(hdc, part, state, rect, extra.inner_spin); + return; + case kMenuList: + PaintMenuList(hdc, state, rect, extra.menu_list); + return; + case kMenuCheck: + PaintMenuCheck(hdc, state, rect, extra.menu_check); + return; + case kMenuCheckBackground: + PaintMenuCheckBackground(hdc, state, rect); + return; + case kMenuPopupArrow: + PaintMenuArrow(hdc, state, rect, extra.menu_arrow); + return; + case kProgressBar: + PaintProgressBar(hdc, rect, extra.progress_bar); + return; + case kPushButton: + PaintPushButton(hdc, part, state, rect, extra.button); + return; + case kRadio: + PaintRadioButton(hdc, part, state, rect, extra.button); + return; + case kScrollbarDownArrow: + case kScrollbarUpArrow: + case kScrollbarLeftArrow: + case kScrollbarRightArrow: + PaintScrollbarArrow(hdc, part, state, rect, extra.scrollbar_arrow); + return; + case kScrollbarHorizontalThumb: + case kScrollbarVerticalThumb: + case kScrollbarHorizontalGripper: + case kScrollbarVerticalGripper: + PaintScrollbarThumb(hdc, part, state, rect, extra.scrollbar_thumb); + return; + case kScrollbarHorizontalTrack: + case kScrollbarVerticalTrack: + PaintScrollbarTrack(canvas, hdc, part, state, rect, + extra.scrollbar_track); + return; + case kTabPanelBackground: + PaintTabPanelBackground(hdc, rect); + return; + case kTextField: + PaintTextField(hdc, part, state, rect, extra.text_field); + return; + case kTrackbarThumb: + case kTrackbarTrack: + PaintTrackbar(canvas, hdc, part, state, rect, extra.trackbar); + return; + case kWindowResizeGripper: + PaintWindowResizeGripper(hdc, rect); + return; + default: + NOTREACHED(); + } } NativeThemeWin::NativeThemeWin() @@ -376,94 +408,6 @@ canvas->drawRect(gfx::RectToSkRect(rect), paint); } -void NativeThemeWin::PaintDirect(SkCanvas* canvas, - Part part, - State state, - const gfx::Rect& rect, - const ExtraParams& extra) const { - skia::ScopedPlatformPaint scoped_platform_paint(canvas); - HDC hdc = scoped_platform_paint.GetPlatformSurface(); - - switch (part) { - case kCheckbox: - PaintCheckbox(hdc, part, state, rect, extra.button); - return; - case kInnerSpinButton: - PaintSpinButton(hdc, part, state, rect, extra.inner_spin); - return; - case kMenuList: - PaintMenuList(hdc, state, rect, extra.menu_list); - return; - case kMenuCheck: - PaintMenuCheck(hdc, state, rect, extra.menu_check); - return; - case kMenuCheckBackground: - PaintMenuCheckBackground(hdc, state, rect); - return; - case kMenuPopupArrow: - PaintMenuArrow(hdc, state, rect, extra.menu_arrow); - return; - case kMenuPopupBackground: - PaintMenuBackground(hdc, rect); - return; - case kMenuPopupGutter: - PaintMenuGutter(hdc, rect); - return; - case kMenuPopupSeparator: - PaintMenuSeparator(hdc, rect); - return; - case kMenuItemBackground: - PaintMenuItemBackground(hdc, state, rect, extra.menu_item); - return; - case kProgressBar: - PaintProgressBar(hdc, rect, extra.progress_bar); - return; - case kPushButton: - PaintPushButton(hdc, part, state, rect, extra.button); - return; - case kRadio: - PaintRadioButton(hdc, part, state, rect, extra.button); - return; - case kScrollbarDownArrow: - case kScrollbarUpArrow: - case kScrollbarLeftArrow: - case kScrollbarRightArrow: - PaintScrollbarArrow(hdc, part, state, rect, extra.scrollbar_arrow); - return; - case kScrollbarHorizontalThumb: - case kScrollbarVerticalThumb: - case kScrollbarHorizontalGripper: - case kScrollbarVerticalGripper: - PaintScrollbarThumb(hdc, part, state, rect, extra.scrollbar_thumb); - return; - case kScrollbarHorizontalTrack: - case kScrollbarVerticalTrack: - PaintScrollbarTrack(canvas, hdc, part, state, rect, - extra.scrollbar_track); - return; - case kScrollbarCorner: - canvas->drawColor(SK_ColorWHITE, SkXfermode::kSrc_Mode); - return; - case kTabPanelBackground: - PaintTabPanelBackground(hdc, rect); - return; - case kTextField: - PaintTextField(hdc, part, state, rect, extra.text_field); - return; - case kTrackbarThumb: - case kTrackbarTrack: - PaintTrackbar(canvas, hdc, part, state, rect, extra.trackbar); - return; - case kWindowResizeGripper: - PaintWindowResizeGripper(hdc, rect); - return; - case kSliderTrack: - case kSliderThumb: - case kMaxPart: - NOTREACHED(); - } -} - SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const { const bool md = ui::MaterialDesignController::IsModeMaterial(); if (!md) { @@ -672,76 +616,6 @@ return GetAuraColor(color_id, this); } -void NativeThemeWin::PaintIndirect(SkCanvas* canvas, - Part part, - State state, - const gfx::Rect& rect, - const ExtraParams& extra) const { - // TODO(asvitkine): This path is pretty inefficient - for each paint operation - // it creates a new offscreen bitmap Skia canvas. This can - // be sped up by doing it only once per part/state and - // keeping a cache of the resulting bitmaps. - - // Create an offscreen canvas that is backed by an HDC. - sk_sp<skia::BitmapPlatformDevice> device( - skia::BitmapPlatformDevice::Create( - rect.width(), rect.height(), false, NULL)); - DCHECK(device); - SkCanvas offscreen_canvas(device.get()); - DCHECK(skia::SupportsPlatformPaint(&offscreen_canvas)); - - // Some of the Windows theme drawing operations do not write correct alpha - // values for fully-opaque pixels; instead the pixels get alpha 0. This is - // especially a problem on Windows XP or when using the Classic theme. - // - // To work-around this, mark all pixels with a placeholder value, to detect - // which pixels get touched by the paint operation. After paint, set any - // pixels that have alpha 0 to opaque and placeholders to fully-transparent. - const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0); - offscreen_canvas.clear(placeholder); - - // Offset destination rects to have origin (0,0). - gfx::Rect adjusted_rect(rect.size()); - ExtraParams adjusted_extra(extra); - switch (part) { - case kProgressBar: - adjusted_extra.progress_bar.value_rect_x = 0; - adjusted_extra.progress_bar.value_rect_y = 0; - break; - case kScrollbarHorizontalTrack: - case kScrollbarVerticalTrack: - adjusted_extra.scrollbar_track.track_x = 0; - adjusted_extra.scrollbar_track.track_y = 0; - break; - default: - break; - } - // Draw the theme controls using existing HDC-drawing code. - PaintDirect(&offscreen_canvas, part, state, adjusted_rect, adjusted_extra); - - SkBitmap bitmap = skia::ReadPixels(&offscreen_canvas); - - // Post-process the pixels to fix up the alpha values (see big comment above). - const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder); - const int pixel_count = rect.width() * rect.height(); - SkPMColor* pixels = bitmap.getAddr32(0, 0); - for (int i = 0; i < pixel_count; i++) { - if (pixels[i] == placeholder_value) { - // Pixel wasn't touched - make it fully transparent. - pixels[i] = SkPackARGB32(0, 0, 0, 0); - } else if (SkGetPackedA32(pixels[i]) == 0) { - // Pixel was touched but has incorrect alpha of 0, make it fully opaque. - pixels[i] = SkPackARGB32(0xFF, - SkGetPackedR32(pixels[i]), - SkGetPackedG32(pixels[i]), - SkGetPackedB32(pixels[i])); - } - } - - // Draw the offscreen bitmap to the destination canvas. - canvas->drawBitmap(bitmap, rect.x(), rect.y()); -} - HRESULT NativeThemeWin::GetThemePartSize(ThemeName theme_name, HDC hdc, int part_id, @@ -843,33 +717,6 @@ return S_OK; } -HRESULT NativeThemeWin::PaintMenuSeparator( - HDC hdc, - const gfx::Rect& rect) const { - RECT rect_win = rect.ToRECT(); - - HANDLE handle = GetThemeHandle(MENU); - if (handle && draw_theme_) { - // Delta is needed for non-classic to move separator up slightly. - --rect_win.top; - --rect_win.bottom; - return draw_theme_(handle, hdc, MENU_POPUPSEPARATOR, MPI_NORMAL, &rect_win, - NULL); - } - - DrawEdge(hdc, &rect_win, EDGE_ETCHED, BF_TOP); - return S_OK; -} - -HRESULT NativeThemeWin::PaintMenuGutter(HDC hdc, - const gfx::Rect& rect) const { - RECT rect_win = rect.ToRECT(); - HANDLE handle = GetThemeHandle(MENU); - return (handle && draw_theme_) ? - draw_theme_(handle, hdc, MENU_POPUPGUTTER, MPI_NORMAL, &rect_win, NULL) : - E_NOTIMPL; -} - HRESULT NativeThemeWin::PaintMenuArrow( HDC hdc, State state, @@ -916,22 +763,6 @@ state); } -HRESULT NativeThemeWin::PaintMenuBackground(HDC hdc, - const gfx::Rect& rect) const { - HANDLE handle = GetThemeHandle(MENU); - RECT rect_win = rect.ToRECT(); - if (handle && draw_theme_) { - HRESULT result = draw_theme_(handle, hdc, MENU_POPUPBACKGROUND, 0, - &rect_win, NULL); - FrameRect(hdc, &rect_win, GetSysColorBrush(COLOR_3DSHADOW)); - return result; - } - - FillRect(hdc, &rect_win, GetSysColorBrush(COLOR_MENU)); - DrawEdge(hdc, &rect_win, EDGE_RAISED, BF_RECT); - return S_OK; -} - HRESULT NativeThemeWin::PaintMenuCheck( HDC hdc, State state, @@ -964,37 +795,6 @@ &rect_win, NULL); } -HRESULT NativeThemeWin::PaintMenuItemBackground( - HDC hdc, - State state, - const gfx::Rect& rect, - const MenuItemExtraParams& extra) const { - HANDLE handle = GetThemeHandle(MENU); - RECT rect_win = rect.ToRECT(); - int state_id = MPI_NORMAL; - switch (state) { - case kDisabled: - state_id = extra.is_selected ? MPI_DISABLEDHOT : MPI_DISABLED; - break; - case kHovered: - state_id = MPI_HOT; - break; - case kNormal: - break; - case kPressed: - case kNumStates: - NOTREACHED(); - break; - } - - if (handle && draw_theme_) - return draw_theme_(handle, hdc, MENU_POPUPITEM, state_id, &rect_win, NULL); - - if (extra.is_selected) - FillRect(hdc, &rect_win, GetSysColorBrush(COLOR_HIGHLIGHT)); - return S_OK; -} - HRESULT NativeThemeWin::PaintPushButton(HDC hdc, Part part, State state,
diff --git a/ui/native_theme/native_theme_win.h b/ui/native_theme/native_theme_win.h index 03483650..8f8597b 100644 --- a/ui/native_theme/native_theme_win.h +++ b/ui/native_theme/native_theme_win.h
@@ -130,22 +130,6 @@ void PaintMenuGutter(SkCanvas* canvas, const gfx::Rect& rect) const; void PaintMenuBackground(SkCanvas* canvas, const gfx::Rect& rect) const; - // Paint directly to canvas' HDC. - void PaintDirect(SkCanvas* canvas, - Part part, - State state, - const gfx::Rect& rect, - const ExtraParams& extra) const; - - // Create a temporary HDC, paint to that, clean up the alpha values in the - // temporary HDC, and then blit the result to canvas. This is to work around - // the fact that Windows XP and some classic themes give bogus alpha values. - void PaintIndirect(SkCanvas* canvas, - Part part, - State state, - const gfx::Rect& rect, - const ExtraParams& extra) const; - HRESULT GetThemePartSize(ThemeName themeName, HDC hdc, int part_id, @@ -161,11 +145,6 @@ int state_id, RECT* rect) const; - HRESULT PaintMenuSeparator(HDC hdc, - const gfx::Rect& rect) const; - - HRESULT PaintMenuGutter(HDC hdc, const gfx::Rect& rect) const; - // |arrow_direction| determines whether the arrow is pointing to the left or // to the right. In RTL locales, sub-menus open from right to left and // therefore the menu arrow should point to the left and not to the right. @@ -174,8 +153,6 @@ const gfx::Rect& rect, const MenuArrowExtraParams& extra) const; - HRESULT PaintMenuBackground(HDC hdc, const gfx::Rect& rect) const; - HRESULT PaintMenuCheck(HDC hdc, State state, const gfx::Rect& rect, @@ -185,11 +162,6 @@ State state, const gfx::Rect& rect) const; - HRESULT PaintMenuItemBackground(HDC hdc, - State state, - const gfx::Rect& rect, - const MenuItemExtraParams& extra) const; - HRESULT PaintPushButton(HDC hdc, Part part, State state,
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc index ab14900..b7ae651 100644 --- a/ui/views/animation/ink_drop_host_view.cc +++ b/ui/views/animation/ink_drop_host_view.cc
@@ -44,18 +44,16 @@ // TODO(bruthig): Consider getting rid of this class. class InkDropHostView::InkDropGestureHandler : public ui::EventHandler { public: - InkDropGestureHandler(InkDropHostView* host_view, InkDrop* ink_drop) + explicit InkDropGestureHandler(InkDropHostView* host_view) : target_handler_(new ui::ScopedTargetHandler(host_view, this)), - host_view_(host_view), - ink_drop_(ink_drop) {} + host_view_(host_view) {} ~InkDropGestureHandler() override {} - void SetInkDrop(InkDrop* ink_drop) { ink_drop_ = ink_drop; } - // ui::EventHandler: void OnGestureEvent(ui::GestureEvent* event) override { - InkDropState current_ink_drop_state = ink_drop_->GetTargetInkDropState(); + InkDropState current_ink_drop_state = + host_view_->ink_drop()->GetTargetInkDropState(); InkDropState ink_drop_state = InkDropState::HIDDEN; switch (event->type()) { @@ -102,9 +100,6 @@ // The host view to cache ui::Events to when animating the ink drop. InkDropHostView* host_view_; - // Animation controller for the ink drop ripple effect. - InkDrop* ink_drop_; - DISALLOW_COPY_AND_ASSIGN(InkDropGestureHandler); }; @@ -241,14 +236,10 @@ else ink_drop_.reset(new InkDropImpl(this)); - if (ink_drop_mode == InkDropMode::ON) { - if (gesture_handler_) - gesture_handler_->SetInkDrop(ink_drop_.get()); - else - gesture_handler_.reset(new InkDropGestureHandler(this, ink_drop_.get())); - } else { + if (ink_drop_mode != InkDropMode::ON) gesture_handler_.reset(); - } + else if (!gesture_handler_) + gesture_handler_.reset(new InkDropGestureHandler(this)); } } // namespace views
diff --git a/ui/views/mus/views_mus_test_suite.cc b/ui/views/mus/views_mus_test_suite.cc index 5446606e..72ed1412 100644 --- a/ui/views/mus/views_mus_test_suite.cc +++ b/ui/views/mus/views_mus_test_suite.cc
@@ -15,8 +15,7 @@ #include "services/shell/background/background_shell.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/service.h" -#include "services/shell/public/cpp/shell_connection.h" -#include "services/ui/common/gpu_service.h" +#include "services/shell/public/cpp/service_context.h" #include "services/ui/common/switches.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/views/mus/window_manager_connection.h" @@ -45,12 +44,11 @@ public: PlatformTestHelperMus(shell::Connector* connector, const shell::Identity& identity) { - ui::GpuService::Initialize(connector); // It is necessary to recreate the WindowManagerConnection for each test, // since a new MessageLoop is created for each test. connection_ = WindowManagerConnection::Create(connector, identity); } - ~PlatformTestHelperMus() override { ui::GpuService::Terminate(); } + ~PlatformTestHelperMus() override {} private: std::unique_ptr<WindowManagerConnection> connection_; @@ -119,7 +117,7 @@ background_shell_.reset(new shell::BackgroundShell); background_shell_->Init(nullptr); service_.reset(new DefaultService); - shell_connection_.reset(new shell::ShellConnection( + shell_connection_.reset(new shell::ServiceContext( service_.get(), background_shell_->CreateServiceRequest(GetTestName()))); @@ -147,7 +145,7 @@ base::Thread thread_; std::unique_ptr<shell::BackgroundShell> background_shell_; - std::unique_ptr<shell::ShellConnection> shell_connection_; + std::unique_ptr<shell::ServiceContext> shell_connection_; std::unique_ptr<DefaultService> service_; std::unique_ptr<shell::Connector> shell_connector_; shell::Identity shell_identity_;
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc index d5f3670..c9ac178 100644 --- a/ui/views/mus/window_manager_connection.cc +++ b/ui/views/mus/window_manager_connection.cc
@@ -10,6 +10,7 @@ #include "base/threading/thread_local.h" #include "services/shell/public/cpp/connection.h" #include "services/shell/public/cpp/connector.h" +#include "services/ui/common/gpu_service.h" #include "services/ui/public/cpp/property_type_converters.h" #include "services/ui/public/cpp/window.h" #include "services/ui/public/cpp/window_property.h" @@ -105,6 +106,9 @@ const shell::Identity& identity) : connector_(connector), identity_(identity) { lazy_tls_ptr.Pointer()->Set(this); + + ui::GpuService::Initialize(connector); + client_.reset(new ui::WindowTreeClient(this, nullptr, nullptr)); client_->ConnectViaWindowTreeFactory(connector_); @@ -126,6 +130,7 @@ // we are still valid. client_.reset(); ui::Clipboard::DestroyClipboardForCurrentThread(); + ui::GpuService::Terminate(); lazy_tls_ptr.Pointer()->Set(nullptr); if (ViewsDelegate::GetInstance()) {