diff --git a/.gn b/.gn index f3ea8df8..264ffac 100644 --- a/.gn +++ b/.gn
@@ -12,6 +12,32 @@ # in the source tree, e.g. for third party source trees. secondary_source = "//build/secondary/" +# These arguments override the default values for items in a declare_args +# block. "gn args" in turn can override these. +# +# In general the value for a build arg in the declare_args block should be the +# default. In some cases, a DEPS-ed in project will want different defaults for +# being built as part of Chrome vs. being built standalone. In this case, the +# Chrome defaults should go here. There should be no overrides here for +# values declared in the main Chrome repository. +default_args = { + v8_extra_library_files = [ + # Dependencies used by the extra libraries. Putting them here causes them + # to be executed first during snapshot creation. + "//third_party/WebKit/Source/core/streams/CommonStrings.js", + + # Extra libraries. + "//third_party/WebKit/Source/core/streams/ByteLengthQueuingStrategy.js", + "//third_party/WebKit/Source/core/streams/CountQueuingStrategy.js", + "//third_party/WebKit/Source/core/streams/ReadableStream.js", + ] + v8_experimental_extra_library_files = + [ "//third_party/WebKit/Source/core/streams/WritableStream.js" ] + v8_enable_inspector = true + v8_enable_gdbjit = false + v8_imminent_deprecation_warnings = false +} + # These are the targets to check headers for by default. The files in targets # matching these patterns (see "gn help label_pattern" for format) will have # their includes checked for proper dependencies when you run either
diff --git a/DEPS b/DEPS index 5ddc193..7f4a758c 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'b92234a3210bce532f103d71002f4e04d336a182', + 'skia_revision': 'd46697ac36d5cb3b58571c6129cb5b26fe9d25d7', # 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': '7595f86e695fb9ef3f80ed1ae94bbb922a290bc6', + 'v8_revision': '5ad29d77f4d1fcb589f1e332e1eb0fff13abe16c', # 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. @@ -52,7 +52,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': 'c1a5d16e964ad524487eac9d2e4b5a65d837ff27', + 'angle_revision': 'd73f852f8d3332089682b35723f8849c031acd4d', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'd198e406d13b831ffd4b1a2bfdf12522dea31205', + 'pdfium_revision': '03de88464cc818ac4353de3e7ec49b98166bcdc5', # 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. @@ -465,7 +465,7 @@ Var('chromium_git') + '/external/android_protobuf.git' + '@' + '999188d0dc72e97f7fe08bb756958a2cf090f4e7', 'src/third_party/android_tools': - Var('chromium_git') + '/android_tools.git' + '@' + 'b43a6a289a7588b1769814f04dd6c7d7176974cc', + Var('chromium_git') + '/android_tools.git' + '@' + 'e429db7f48cd615b0b408cda259ffbc17d3945bb', 'src/third_party/apache-portable-runtime/src': Var('chromium_git') + '/external/apache-portable-runtime.git' + '@' + 'c76a8c4277e09a82eaa229e35246edea1ee0a6a1',
diff --git a/ash/aura/wm_shell_aura.cc b/ash/aura/wm_shell_aura.cc index 2643fa3..86158eb 100644 --- a/ash/aura/wm_shell_aura.cc +++ b/ash/aura/wm_shell_aura.cc
@@ -20,6 +20,7 @@ #include "ash/display/window_tree_host_manager.h" #include "ash/host/ash_window_tree_host_init_params.h" #include "ash/laser/laser_pointer_controller.h" +#include "ash/magnifier/partial_magnification_controller.h" #include "ash/metrics/task_switch_metrics_recorder.h" #include "ash/shared/immersive_fullscreen_controller.h" #include "ash/shell.h" @@ -276,6 +277,10 @@ Shell::GetInstance()->laser_pointer_controller()->SetEnabled(enabled); } +void WmShellAura::SetPartialMagnifierEnabled(bool enabled) { + Shell::GetInstance()->partial_magnification_controller()->SetEnabled(enabled); +} + void WmShellAura::CreatePointerWatcherAdapter() { pointer_watcher_adapter_ = base::MakeUnique<PointerWatcherAdapter>(); }
diff --git a/ash/aura/wm_shell_aura.h b/ash/aura/wm_shell_aura.h index 347794b1..9feac7ac 100644 --- a/ash/aura/wm_shell_aura.h +++ b/ash/aura/wm_shell_aura.h
@@ -80,6 +80,7 @@ bool IsTouchDown() override; void ToggleIgnoreExternalKeyboard() override; void SetLaserPointerEnabled(bool enabled) override; + void SetPartialMagnifierEnabled(bool enabled) override; void CreatePointerWatcherAdapter() override; void CreatePrimaryHost() override; void InitHosts(const ShellInitParams& init_params) override;
diff --git a/ash/common/multi_profile_uma.cc b/ash/common/multi_profile_uma.cc index d211743..bcf294e 100644 --- a/ash/common/multi_profile_uma.cc +++ b/ash/common/multi_profile_uma.cc
@@ -4,7 +4,7 @@ #include "ash/common/multi_profile_uma.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" namespace ash {
diff --git a/ash/common/palette_delegate.h b/ash/common/palette_delegate.h index 3d6ad62..c0dbbc2 100644 --- a/ash/common/palette_delegate.h +++ b/ash/common/palette_delegate.h
@@ -36,11 +36,6 @@ // Returns true if there is a note-taking application available. virtual bool HasNoteApp() = 0; - // Enables or disables the partial magnifier. - // TODO(sammiequon): This can be removed from the delegate and put in wmshell. - // See http://crbug.com/647031. - virtual void SetPartialMagnifierState(bool enabled) = 0; - // Set callback that is run when a stylus is inserted or removed. virtual void SetStylusStateChangedCallback( const OnStylusStateChangedCallback& on_stylus_state_changed) = 0;
diff --git a/ash/common/shelf/shelf_view.cc b/ash/common/shelf/shelf_view.cc index 8463037..318a1db36 100644 --- a/ash/common/shelf/shelf_view.cc +++ b/ash/common/shelf/shelf_view.cc
@@ -27,7 +27,7 @@ #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" #include "base/auto_reset.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "grit/ash_strings.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/common/system/chromeos/palette/tools/magnifier_mode.cc b/ash/common/system/chromeos/palette/tools/magnifier_mode.cc index 746b84e..f3ff7b3 100644 --- a/ash/common/system/chromeos/palette/tools/magnifier_mode.cc +++ b/ash/common/system/chromeos/palette/tools/magnifier_mode.cc
@@ -32,13 +32,13 @@ void MagnifierMode::OnEnable() { CommonPaletteTool::OnEnable(); - WmShell::Get()->palette_delegate()->SetPartialMagnifierState(true); + WmShell::Get()->SetPartialMagnifierEnabled(true); delegate()->HidePalette(); } void MagnifierMode::OnDisable() { CommonPaletteTool::OnDisable(); - WmShell::Get()->palette_delegate()->SetPartialMagnifierState(false); + WmShell::Get()->SetPartialMagnifierEnabled(false); } views::View* MagnifierMode::CreateView() {
diff --git a/ash/common/system/tray/system_tray.cc b/ash/common/system/tray/system_tray.cc index 3dc9455..fae5c963 100644 --- a/ash/common/system/tray/system_tray.cc +++ b/ash/common/system/tray/system_tray.cc
@@ -55,7 +55,7 @@ #include "ash/root_window_controller.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/timer/timer.h" #include "grit/ash_strings.h" #include "ui/base/accelerators/accelerator.h"
diff --git a/ash/common/test/test_palette_delegate.cc b/ash/common/test/test_palette_delegate.cc index 7350d8e..d05ec4a 100644 --- a/ash/common/test/test_palette_delegate.cc +++ b/ash/common/test/test_palette_delegate.cc
@@ -25,10 +25,6 @@ return has_note_app_; } -void TestPaletteDelegate::SetPartialMagnifierState(bool enabled) { - partial_magnifier_state_ = enabled; -} - void TestPaletteDelegate::SetStylusStateChangedCallback( const PaletteDelegate::OnStylusStateChangedCallback& on_stylus_state_changed) {}
diff --git a/ash/common/test/test_palette_delegate.h b/ash/common/test/test_palette_delegate.h index fff3b2f3..837c0e042 100644 --- a/ash/common/test/test_palette_delegate.h +++ b/ash/common/test/test_palette_delegate.h
@@ -20,8 +20,6 @@ int has_note_app_count() const { return has_note_app_count_; } - bool partial_magnifier_state() const { return partial_magnifier_state_; } - int take_screenshot_count() const { return take_screenshot_count_; } int take_partial_screenshot_count() const { @@ -48,7 +46,6 @@ const EnableListener& on_state_changed) override; void CreateNote() override; bool HasNoteApp() override; - void SetPartialMagnifierState(bool enabled) override; void SetStylusStateChangedCallback( const OnStylusStateChangedCallback& on_stylus_state_changed) override; bool ShouldAutoOpenPalette() override; @@ -59,7 +56,6 @@ int create_note_count_ = 0; int has_note_app_count_ = 0; - bool partial_magnifier_state_ = false; int take_screenshot_count_ = 0; int take_partial_screenshot_count_ = 0; base::Closure partial_screenshot_done_;
diff --git a/ash/common/wm/dock/docked_window_layout_manager.cc b/ash/common/wm/dock/docked_window_layout_manager.cc index 68bba9a..5faeb48 100644 --- a/ash/common/wm/dock/docked_window_layout_manager.cc +++ b/ash/common/wm/dock/docked_window_layout_manager.cc
@@ -21,7 +21,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "base/auto_reset.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "grit/ash_resources.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPaint.h"
diff --git a/ash/common/wm/maximize_mode/maximize_mode_controller.cc b/ash/common/wm/maximize_mode/maximize_mode_controller.cc index ef07902..8879f2a5 100644 --- a/ash/common/wm/maximize_mode/maximize_mode_controller.cc +++ b/ash/common/wm/maximize_mode/maximize_mode_controller.cc
@@ -11,7 +11,7 @@ #include "ash/common/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h" #include "ash/common/wm_shell.h" #include "base/command_line.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/ash/common/wm/overview/window_selector.cc b/ash/common/wm/overview/window_selector.cc index 5c7fb451..3fae96fe 100644 --- a/ash/common/wm/overview/window_selector.cc +++ b/ash/common/wm/overview/window_selector.cc
@@ -29,7 +29,7 @@ #include "ash/root_window_controller.h" #include "base/auto_reset.h" #include "base/command_line.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/ash/common/wm/overview/window_selector_controller.cc b/ash/common/wm/overview/window_selector_controller.cc index f0a80d2..28931f2 100644 --- a/ash/common/wm/overview/window_selector_controller.cc +++ b/ash/common/wm/overview/window_selector_controller.cc
@@ -13,7 +13,7 @@ #include "ash/common/wm/window_state.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" namespace ash {
diff --git a/ash/common/wm/window_cycle_controller.cc b/ash/common/wm/window_cycle_controller.cc index 17fb0448..2b8ccc9d 100644 --- a/ash/common/wm/window_cycle_controller.cc +++ b/ash/common/wm/window_cycle_controller.cc
@@ -12,7 +12,7 @@ #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" #include "ash/public/cpp/shell_window_ids.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" namespace ash {
diff --git a/ash/common/wm_shell.h b/ash/common/wm_shell.h index d6bfae07b..5dc07cf1 100644 --- a/ash/common/wm_shell.h +++ b/ash/common/wm_shell.h
@@ -443,6 +443,9 @@ // Enable or disable the laser pointer. virtual void SetLaserPointerEnabled(bool enabled) = 0; + // Enable or disable the partial magnifier. + virtual void SetPartialMagnifierEnabled(bool enabled) = 0; + virtual void CreatePointerWatcherAdapter() = 0; protected:
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index 468973e..414ce2f 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc
@@ -20,7 +20,7 @@ #include "ash/shell.h" #include "ash/wm/window_state_aura.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "ui/aura/window.h"
diff --git a/ash/mus/bridge/wm_shell_mus.cc b/ash/mus/bridge/wm_shell_mus.cc index b45d518..f63f414 100644 --- a/ash/mus/bridge/wm_shell_mus.cc +++ b/ash/mus/bridge/wm_shell_mus.cc
@@ -407,6 +407,10 @@ NOTIMPLEMENTED(); } +void WmShellMus::SetPartialMagnifierEnabled(bool enabled) { + NOTIMPLEMENTED(); +} + void WmShellMus::CreatePointerWatcherAdapter() { // Only needed in WmShellAura, which has specific creation order. }
diff --git a/ash/mus/bridge/wm_shell_mus.h b/ash/mus/bridge/wm_shell_mus.h index 438f02b3..6894a323 100644 --- a/ash/mus/bridge/wm_shell_mus.h +++ b/ash/mus/bridge/wm_shell_mus.h
@@ -109,6 +109,7 @@ bool IsTouchDown() override; void ToggleIgnoreExternalKeyboard() override; void SetLaserPointerEnabled(bool enabled) override; + void SetPartialMagnifierEnabled(bool enabled) override; void CreatePointerWatcherAdapter() override; void CreatePrimaryHost() override; void InitHosts(const ShellInitParams& init_params) override;
diff --git a/ash/shared/immersive_fullscreen_controller.cc b/ash/shared/immersive_fullscreen_controller.cc index a118aa3..a5f1199 100644 --- a/ash/shared/immersive_fullscreen_controller.cc +++ b/ash/shared/immersive_fullscreen_controller.cc
@@ -11,7 +11,7 @@ #include "ash/shared/immersive_fullscreen_controller_delegate.h" #include "ash/shared/immersive_gesture_handler.h" #include "ash/shared/immersive_handler_factory.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/base_event_utils.h"
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index ccb54f5..277b23e6 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc
@@ -44,7 +44,6 @@ } void CreateNote() override {} bool HasNoteApp() override { return false; } - void SetPartialMagnifierState(bool enabled) override {} void SetStylusStateChangedCallback( const OnStylusStateChangedCallback& on_stylus_state_changed) override {} bool ShouldAutoOpenPalette() override { return false; }
diff --git a/ash/touch/touch_uma.cc b/ash/touch/touch_uma.cc index fe2ab8a..c2666aaf 100644 --- a/ash/touch/touch_uma.cc +++ b/ash/touch/touch_uma.cc
@@ -5,7 +5,7 @@ #include "ash/touch/touch_uma.h" #include "ash/common/wm_shell.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "ui/aura/env.h" #include "ui/aura/window.h"
diff --git a/ash/wm/overview/scoped_overview_animation_settings_aura.cc b/ash/wm/overview/scoped_overview_animation_settings_aura.cc index d785c18..56e7a19 100644 --- a/ash/wm/overview/scoped_overview_animation_settings_aura.cc +++ b/ash/wm/overview/scoped_overview_animation_settings_aura.cc
@@ -4,6 +4,8 @@ #include "ash/wm/overview/scoped_overview_animation_settings_aura.h" +#include "base/lazy_instance.h" +#include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" @@ -51,6 +53,53 @@ return base::TimeDelta(); } +class OverviewEnterMetricsReporter : public ui::AnimationMetricsReporter { + void Report(int value) override { + UMA_HISTOGRAM_PERCENTAGE("Ash.WindowSelector.AnimationSmoothness.Enter", + value); + } +}; + +class OverviewExitMetricsReporter : public ui::AnimationMetricsReporter { + void Report(int value) override { + UMA_HISTOGRAM_PERCENTAGE("Ash.WindowSelector.AnimationSmoothness.Exit", + value); + } +}; + +class OverviewCloseMetricsReporter : public ui::AnimationMetricsReporter { + void Report(int value) override { + UMA_HISTOGRAM_PERCENTAGE("Ash.WindowSelector.AnimationSmoothness.Close", + value); + } +}; + +base::LazyInstance<OverviewEnterMetricsReporter>::Leaky g_reporter_enter = + LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<OverviewExitMetricsReporter>::Leaky g_reporter_exit = + LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<OverviewCloseMetricsReporter>::Leaky g_reporter_close = + LAZY_INSTANCE_INITIALIZER; + +ui::AnimationMetricsReporter* GetMetricsReporter( + OverviewAnimationType animation_type) { + switch (animation_type) { + case OVERVIEW_ANIMATION_NONE: + return nullptr; + case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN: + case OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS: + return g_reporter_enter.Pointer(); + case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT: + case OVERVIEW_ANIMATION_RESTORE_WINDOW: + return g_reporter_exit.Pointer(); + case OVERVIEW_ANIMATION_CLOSING_SELECTOR_ITEM: + case OVERVIEW_ANIMATION_CLOSE_SELECTOR_ITEM: + return g_reporter_close.Pointer(); + } + NOTREACHED(); + return nullptr; +} + } // namespace ScopedOverviewAnimationSettingsAura::ScopedOverviewAnimationSettingsAura( @@ -91,6 +140,8 @@ } animation_settings_->SetTransitionDuration( GetAnimationDuration(animation_type)); + animation_settings_->SetAnimationMetricsReporter( + GetMetricsReporter(animation_type)); } ScopedOverviewAnimationSettingsAura::~ScopedOverviewAnimationSettingsAura() {}
diff --git a/base/files/scoped_file.cc b/base/files/scoped_file.cc index 8ce45b8..78d4ca52 100644 --- a/base/files/scoped_file.cc +++ b/base/files/scoped_file.cc
@@ -37,6 +37,14 @@ int close_errno = errno; base::debug::Alias(&close_errno); +#if defined(OS_LINUX) + // NB: Some file descriptors can return errors from close() e.g. network + // filesystems such as NFS and Linux input devices. On Linux, errors from + // close other than EBADF do not indicate failure to actually close the fd. + if (ret != 0 && errno != EBADF) + ret = 0; +#endif + PCHECK(0 == ret); }
diff --git a/base/logging.h b/base/logging.h index 7854e39..6eb796f 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -712,6 +712,10 @@ // whether DCHECKs are enabled; this is so that we don't get unused // variable warnings if the only use of a variable is in a DCHECK. // This behavior is different from DLOG_IF et al. +// +// Note that the definition of the DCHECK macros depends on whether or not +// DCHECK_IS_ON() is true. When DCHECK_IS_ON() is false, the macros use +// EAT_STREAM_PARAMETERS to avoid expressions that would create temporaries. #if defined(_PREFAST_) && defined(OS_WIN) // See comments on the previous use of __analysis_assume. @@ -728,13 +732,21 @@ #else // _PREFAST_ -#define DCHECK(condition) \ - LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \ +#if DCHECK_IS_ON() + +#define DCHECK(condition) \ + LAZY_STREAM(LOG_STREAM(DCHECK), !(condition)) \ + << "Check failed: " #condition ". " +#define DPCHECK(condition) \ + LAZY_STREAM(PLOG_STREAM(DCHECK), !(condition)) \ << "Check failed: " #condition ". " -#define DPCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \ - << "Check failed: " #condition ". " +#else // DCHECK_IS_ON() + +#define DCHECK(condition) EAT_STREAM_PARAMETERS << !(condition) +#define DPCHECK(condition) EAT_STREAM_PARAMETERS << !(condition) + +#endif // DCHECK_IS_ON() #endif // _PREFAST_ @@ -744,6 +756,8 @@ // macro is used in an 'if' clause such as: // if (a == 1) // DCHECK_EQ(2, a); +#if DCHECK_IS_ON() + #define DCHECK_OP(name, op, val1, val2) \ switch (0) case 0: default: \ if (::logging::CheckOpResult true_if_passed = \ @@ -755,6 +769,25 @@ ::logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \ true_if_passed.message()).stream() +#else // DCHECK_IS_ON() + +// When DCHECKs aren't enabled, DCHECK_OP still needs to reference operator<< +// overloads for |val1| and |val2| to avoid potential compiler warnings about +// unused functions. For the same reason, it also compares |val1| and |val2| +// using |op|. +// +// Note that the contract of DCHECK_EQ, etc is that arguments are only evaluated +// once. Even though |val1| and |val2| appear twice in this version of the macro +// expansion, this is OK, since the expression is never actually evaluated. +#define DCHECK_OP(name, op, val1, val2) \ + EAT_STREAM_PARAMETERS << (::logging::MakeCheckOpValueString( \ + ::logging::g_swallow_stream, val1), \ + ::logging::MakeCheckOpValueString( \ + ::logging::g_swallow_stream, val2), \ + (val1)op(val2)) + +#endif // DCHECK_IS_ON() + // Equality/Inequality checks - compare two values, and log a // LOG_DCHECK message including the two values when the result is not // as expected. The values must have operator<<(ostream, ...)
diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h index 8a7c3a1..fead4bea 100644 --- a/base/metrics/histogram.h +++ b/base/metrics/histogram.h
@@ -79,7 +79,7 @@ #include "base/macros.h" #include "base/metrics/bucket_ranges.h" #include "base/metrics/histogram_base.h" -#if defined(OS_CHROMEOS) || defined(OS_IOS) +#if defined(OS_IOS) // TODO(asvitkine): Migrate callers to to include this directly and remove this. // Note: Incrementally migrating platforms as they become clean. #include "base/metrics/histogram_macros.h"
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc index f32e9a3..ba0ef2a1 100644 --- a/base/metrics/persistent_memory_allocator.cc +++ b/base/metrics/persistent_memory_allocator.cc
@@ -49,6 +49,11 @@ kFlagFull = 1 << 1 }; +// Errors that are logged in "errors" histogram. +enum AllocatorError : int { + kMemoryIsCorrupt = 1, +}; + bool CheckFlag(const volatile std::atomic<uint32_t>* flags, int flag) { uint32_t loaded_flags = flags->load(std::memory_order_relaxed); return (loaded_flags & flag) != 0; @@ -300,7 +305,8 @@ readonly_(readonly), corrupt_(0), allocs_histogram_(nullptr), - used_histogram_(nullptr) { + used_histogram_(nullptr), + errors_histogram_(nullptr) { // These asserts ensure that the structures are 32/64-bit agnostic and meet // all the requirements of use within the allocator. They access private // definitions and so cannot be moved to the global scope. @@ -441,16 +447,21 @@ base::StringPiece name) { if (name.empty() || readonly_) return; - std::string name_string = name.as_string(); + + DCHECK(!allocs_histogram_); + allocs_histogram_ = Histogram::FactoryGet( + "UMA.PersistentAllocator." + name_string + ".Allocs", 1, 10000, 50, + HistogramBase::kUmaTargetedHistogramFlag); + DCHECK(!used_histogram_); used_histogram_ = LinearHistogram::FactoryGet( "UMA.PersistentAllocator." + name_string + ".UsedPct", 1, 101, 21, HistogramBase::kUmaTargetedHistogramFlag); - DCHECK(!allocs_histogram_); - allocs_histogram_ = Histogram::FactoryGet( - "UMA.PersistentAllocator." + name_string + ".Allocs", 1, 10000, 50, + DCHECK(!errors_histogram_); + errors_histogram_ = SparseHistogram::FactoryGet( + "UMA.PersistentAllocator." + name_string + ".Errors", HistogramBase::kUmaTargetedHistogramFlag); } @@ -652,7 +663,7 @@ mem_size_ - shared_meta()->freeptr.load(std::memory_order_relaxed), (uint32_t)sizeof(BlockHeader)); meminfo->total = mem_size_; - meminfo->free = IsCorrupt() ? 0 : remaining - sizeof(BlockHeader); + meminfo->free = remaining - sizeof(BlockHeader); } void PersistentMemoryAllocator::MakeIterable(Reference ref) { @@ -720,9 +731,15 @@ // case, it's safe to discard the constness and modify the local flag and // maybe even the shared flag if the underlying data isn't actually read-only. void PersistentMemoryAllocator::SetCorrupt() const { - LOG(ERROR) << "Corruption detected in shared-memory segment."; - const_cast<std::atomic<bool>*>(&corrupt_)->store(true, - std::memory_order_relaxed); + if (!corrupt_.load(std::memory_order_relaxed) && + !CheckFlag( + const_cast<volatile std::atomic<uint32_t>*>(&shared_meta()->flags), + kFlagCorrupt)) { + LOG(ERROR) << "Corruption detected in shared-memory segment."; + RecordError(kMemoryIsCorrupt); + } + + corrupt_.store(true, std::memory_order_relaxed); if (!readonly_) { SetFlag(const_cast<volatile std::atomic<uint32_t>*>(&shared_meta()->flags), kFlagCorrupt); @@ -784,6 +801,11 @@ return reinterpret_cast<const volatile BlockHeader*>(mem_base_ + ref); } +void PersistentMemoryAllocator::RecordError(int error) const { + if (errors_histogram_) + errors_histogram_->Add(error); +} + const volatile void* PersistentMemoryAllocator::GetBlockData( Reference ref, uint32_t type_id,
diff --git a/base/metrics/persistent_memory_allocator.h b/base/metrics/persistent_memory_allocator.h index fd66da235..9fdef019 100644 --- a/base/metrics/persistent_memory_allocator.h +++ b/base/metrics/persistent_memory_allocator.h
@@ -286,6 +286,7 @@ // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml // with the following histograms: // UMA.PersistentAllocator.name.Allocs + // UMA.PersistentAllocator.name.Errors // UMA.PersistentAllocator.name.UsedPct void CreateTrackingHistograms(base::StringPiece name); @@ -609,11 +610,15 @@ ref, type_id, size)); } - const bool readonly_; // Indicates access to read-only memory. - std::atomic<bool> corrupt_; // Local version of "corrupted" flag. + // Record an error in the internal histogram. + void RecordError(int error) const; + + const bool readonly_; // Indicates access to read-only memory. + mutable std::atomic<bool> corrupt_; // Local version of "corrupted" flag. HistogramBase* allocs_histogram_; // Histogram recording allocs. HistogramBase* used_histogram_; // Histogram recording used space. + HistogramBase* errors_histogram_; // Histogram recording errors. friend class PersistentMemoryAllocatorTest; FRIEND_TEST_ALL_PREFIXES(PersistentMemoryAllocatorTest, AllocateAndIterate);
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc index 14f35658..1d6cfee 100644 --- a/base/task_scheduler/scheduler_worker.cc +++ b/base/task_scheduler/scheduler_worker.cc
@@ -9,8 +9,8 @@ #include <utility> #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/task_scheduler/task_tracker.h" -#include "build/build_config.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -44,12 +44,11 @@ WaitForWork(); #if defined(OS_WIN) - // This is required as SequencedWorkerPool previously blindly CoInitialized - // all of its threads. - // TODO: Get rid of this broad COM scope and force tasks that care about a - // CoInitialized environment to request one (via an upcoming execution - // mode). - win::ScopedCOMInitializer com_initializer; + std::unique_ptr<win::ScopedCOMInitializer> com_initializer; + if (outer_->backward_compatibility_ == + SchedulerBackwardCompatibility::INIT_COM_STA) { + com_initializer = MakeUnique<win::ScopedCOMInitializer>(); + } #endif while (!outer_->task_tracker_->IsShutdownComplete() && @@ -192,9 +191,11 @@ ThreadPriority priority_hint, std::unique_ptr<Delegate> delegate, TaskTracker* task_tracker, - InitialState initial_state) { - std::unique_ptr<SchedulerWorker> worker( - new SchedulerWorker(priority_hint, std::move(delegate), task_tracker)); + InitialState initial_state, + SchedulerBackwardCompatibility backward_compatibility) { + auto worker = + WrapUnique(new SchedulerWorker(priority_hint, std::move(delegate), + task_tracker, backward_compatibility)); // Creation happens before any other thread can reference this one, so no // synchronization is necessary. if (initial_state == SchedulerWorker::InitialState::ALIVE) { @@ -252,12 +253,19 @@ return !!thread_; } -SchedulerWorker::SchedulerWorker(ThreadPriority priority_hint, - std::unique_ptr<Delegate> delegate, - TaskTracker* task_tracker) +SchedulerWorker::SchedulerWorker( + ThreadPriority priority_hint, + std::unique_ptr<Delegate> delegate, + TaskTracker* task_tracker, + SchedulerBackwardCompatibility backward_compatibility) : priority_hint_(priority_hint), delegate_(std::move(delegate)), - task_tracker_(task_tracker) { + task_tracker_(task_tracker) +#if defined(OS_WIN) + , + backward_compatibility_(backward_compatibility) +#endif +{ DCHECK(delegate_); DCHECK(task_tracker_); }
diff --git a/base/task_scheduler/scheduler_worker.h b/base/task_scheduler/scheduler_worker.h index 87fd8ed..f8174de9 100644 --- a/base/task_scheduler/scheduler_worker.h +++ b/base/task_scheduler/scheduler_worker.h
@@ -13,9 +13,11 @@ #include "base/synchronization/atomic_flag.h" #include "base/synchronization/waitable_event.h" #include "base/task_scheduler/scheduler_lock.h" +#include "base/task_scheduler/scheduler_worker_params.h" #include "base/task_scheduler/sequence.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" +#include "build/build_config.h" namespace base { namespace internal { @@ -92,12 +94,15 @@ // |task_tracker| is used to handle shutdown behavior of Tasks. If // |worker_state| is DETACHED, the thread will be created upon a WakeUp(). // Returns nullptr if creating the underlying platform thread fails during - // Create(). + // Create(). |backward_compatibility| indicates whether backward compatibility + // is enabled. static std::unique_ptr<SchedulerWorker> Create( ThreadPriority priority_hint, std::unique_ptr<Delegate> delegate, TaskTracker* task_tracker, - InitialState initial_state); + InitialState initial_state, + SchedulerBackwardCompatibility backward_compatibility = + SchedulerBackwardCompatibility::DISABLED); // Destroying a SchedulerWorker in production is not allowed; it is always // leaked. In tests, it can only be destroyed after JoinForTesting() has @@ -129,7 +134,8 @@ SchedulerWorker(ThreadPriority thread_priority, std::unique_ptr<Delegate> delegate, - TaskTracker* task_tracker); + TaskTracker* task_tracker, + SchedulerBackwardCompatibility backward_compatibility); // Returns the thread instance if the detach was successful so that it can be // freed upon termination of the thread. @@ -147,9 +153,14 @@ std::unique_ptr<Thread> thread_; const ThreadPriority priority_hint_; + const std::unique_ptr<Delegate> delegate_; TaskTracker* const task_tracker_; +#if defined(OS_WIN) + const SchedulerBackwardCompatibility backward_compatibility_; +#endif + // Set once JoinForTesting() has been called. AtomicFlag should_exit_for_testing_;
diff --git a/base/task_scheduler/scheduler_worker_params.h b/base/task_scheduler/scheduler_worker_params.h new file mode 100644 index 0000000..ea753ff --- /dev/null +++ b/base/task_scheduler/scheduler_worker_params.h
@@ -0,0 +1,24 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_PARAMS_H_ +#define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_PARAMS_H_ + +namespace base { + +enum class SchedulerBackwardCompatibility { + // No backward compatibility. + DISABLED, + + // On Windows, initialize COM STA to mimic SequencedWorkerPool and + // BrowserThreadImpl. Behaves like DISABLED on other platforms. + // TODO(fdoray): Get rid of this and force tasks that care about a + // CoInitialized environment to request one explicitly (via an upcoming + // execution mode). + INIT_COM_STA, +}; + +} // namespace base + +#endif // BASE_TASK_SCHEDULER_SCHEDULER_WORKER_PARAMS_H_
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc index 912d270..93800eb3 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -21,6 +21,7 @@ #include "base/strings/stringprintf.h" #include "base/task_runner.h" #include "base/task_scheduler/delayed_task_manager.h" +#include "base/task_scheduler/scheduler_worker_pool_params.h" #include "base/task_scheduler/task_tracker.h" #include "base/task_scheduler/task_traits.h" #include "base/threading/platform_thread.h" @@ -283,14 +284,10 @@ const ReEnqueueSequenceCallback& re_enqueue_sequence_callback, TaskTracker* task_tracker, DelayedTaskManager* delayed_task_manager) { - auto worker_pool = WrapUnique(new SchedulerWorkerPoolImpl( - params.name(), params.suggested_reclaim_time(), task_tracker, - delayed_task_manager)); - if (worker_pool->Initialize( - params.priority_hint(), params.standby_thread_policy(), - params.max_threads(), re_enqueue_sequence_callback)) { + auto worker_pool = WrapUnique( + new SchedulerWorkerPoolImpl(params, task_tracker, delayed_task_manager)); + if (worker_pool->Initialize(params, re_enqueue_sequence_callback)) return worker_pool; - } return nullptr; } @@ -624,12 +621,11 @@ } SchedulerWorkerPoolImpl::SchedulerWorkerPoolImpl( - StringPiece name, - TimeDelta suggested_reclaim_time, + const SchedulerWorkerPoolParams& params, TaskTracker* task_tracker, DelayedTaskManager* delayed_task_manager) - : name_(name.as_string()), - suggested_reclaim_time_(suggested_reclaim_time), + : name_(params.name()), + suggested_reclaim_time_(params.suggested_reclaim_time()), idle_workers_stack_lock_(shared_priority_queue_.container_lock()), idle_workers_stack_cv_for_testing_( idle_workers_stack_lock_.CreateConditionVariable()), @@ -672,31 +668,29 @@ } bool SchedulerWorkerPoolImpl::Initialize( - ThreadPriority priority_hint, - SchedulerWorkerPoolParams::StandbyThreadPolicy standby_thread_policy, - size_t max_threads, + const SchedulerWorkerPoolParams& params, const ReEnqueueSequenceCallback& re_enqueue_sequence_callback) { AutoSchedulerLock auto_lock(idle_workers_stack_lock_); DCHECK(workers_.empty()); - workers_.resize(max_threads); + workers_.resize(params.max_threads()); // Create workers and push them to the idle stack in reverse order of index. // This ensures that they are woken up in order of index and that the ALIVE // worker is on top of the stack. - for (int index = max_threads - 1; index >= 0; --index) { + for (int index = params.max_threads() - 1; index >= 0; --index) { const bool is_standby_lazy = - standby_thread_policy == + params.standby_thread_policy() == SchedulerWorkerPoolParams::StandbyThreadPolicy::LAZY; const SchedulerWorker::InitialState initial_state = (index == 0 && !is_standby_lazy) ? SchedulerWorker::InitialState::ALIVE : SchedulerWorker::InitialState::DETACHED; std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( - priority_hint, + params.priority_hint(), MakeUnique<SchedulerWorkerDelegateImpl>( this, re_enqueue_sequence_callback, &shared_priority_queue_, index), - task_tracker_, initial_state); + task_tracker_, initial_state, params.backward_compatibility()); if (!worker) break; idle_workers_stack_.Push(worker.get());
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h index 2468b52..3205dae7 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -16,23 +16,21 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/strings/string_piece.h" #include "base/synchronization/atomic_flag.h" #include "base/synchronization/condition_variable.h" #include "base/task_scheduler/priority_queue.h" #include "base/task_scheduler/scheduler_lock.h" #include "base/task_scheduler/scheduler_worker.h" #include "base/task_scheduler/scheduler_worker_pool.h" -#include "base/task_scheduler/scheduler_worker_pool_params.h" #include "base/task_scheduler/scheduler_worker_stack.h" #include "base/task_scheduler/sequence.h" #include "base/task_scheduler/task.h" -#include "base/threading/platform_thread.h" #include "base/time/time.h" namespace base { class HistogramBase; +class SchedulerWorkerPoolParams; class TaskTraits; namespace internal { @@ -111,15 +109,12 @@ class SchedulerSingleThreadTaskRunner; class SchedulerWorkerDelegateImpl; - SchedulerWorkerPoolImpl(StringPiece name, - TimeDelta suggested_reclaim_time, + SchedulerWorkerPoolImpl(const SchedulerWorkerPoolParams& params, TaskTracker* task_tracker, DelayedTaskManager* delayed_task_manager); bool Initialize( - ThreadPriority priority_hint, - SchedulerWorkerPoolParams::StandbyThreadPolicy standby_thread_policy, - size_t max_threads, + const SchedulerWorkerPoolParams& params, const ReEnqueueSequenceCallback& re_enqueue_sequence_callback); // Wakes up |worker|.
diff --git a/base/task_scheduler/scheduler_worker_pool_params.cc b/base/task_scheduler/scheduler_worker_pool_params.cc index c4def6d..0747c2e 100644 --- a/base/task_scheduler/scheduler_worker_pool_params.cc +++ b/base/task_scheduler/scheduler_worker_pool_params.cc
@@ -11,12 +11,14 @@ ThreadPriority priority_hint, StandbyThreadPolicy standby_thread_policy, int max_threads, - TimeDelta suggested_reclaim_time) + TimeDelta suggested_reclaim_time, + SchedulerBackwardCompatibility backward_compatibility) : name_(name), priority_hint_(priority_hint), standby_thread_policy_(standby_thread_policy), max_threads_(max_threads), - suggested_reclaim_time_(suggested_reclaim_time) {} + suggested_reclaim_time_(suggested_reclaim_time), + backward_compatibility_(backward_compatibility) {} SchedulerWorkerPoolParams::SchedulerWorkerPoolParams( SchedulerWorkerPoolParams&& other) = default;
diff --git a/base/task_scheduler/scheduler_worker_pool_params.h b/base/task_scheduler/scheduler_worker_pool_params.h index 1e5a6a316..5f90fd4 100644 --- a/base/task_scheduler/scheduler_worker_pool_params.h +++ b/base/task_scheduler/scheduler_worker_pool_params.h
@@ -8,6 +8,7 @@ #include <string> #include "base/macros.h" +#include "base/task_scheduler/scheduler_worker_params.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -28,14 +29,19 @@ // ("TaskScheduler." + histogram name + "." + |name| + extra suffixes). The // pool will contain up to |max_threads|. |priority_hint| is the preferred // thread priority; the actual thread priority depends on shutdown state and - // platform capabilities. |suggested_reclaim_time| sets a suggestion on when - // to reclaim idle threads. The pool is free to ignore this value for - // performance or correctness reasons. - SchedulerWorkerPoolParams(const std::string& name, - ThreadPriority priority_hint, - StandbyThreadPolicy standby_thread_policy, - int max_threads, - TimeDelta suggested_reclaim_time); + // platform capabilities. |standby_thread_policy| indicates whether an idle + // thread should be kept alive on standby. |suggested_reclaim_time| sets a + // suggestion on when to reclaim idle threads. The pool is free to ignore this + // value for performance or correctness reasons. |backward_compatibility| + // indicates whether backward compatibility is enabled. + SchedulerWorkerPoolParams( + const std::string& name, + ThreadPriority priority_hint, + StandbyThreadPolicy standby_thread_policy, + int max_threads, + TimeDelta suggested_reclaim_time, + SchedulerBackwardCompatibility backward_compatibility = + SchedulerBackwardCompatibility::DISABLED); SchedulerWorkerPoolParams(SchedulerWorkerPoolParams&& other); SchedulerWorkerPoolParams& operator=(SchedulerWorkerPoolParams&& other); @@ -46,6 +52,9 @@ } size_t max_threads() const { return max_threads_; } TimeDelta suggested_reclaim_time() const { return suggested_reclaim_time_; } + SchedulerBackwardCompatibility backward_compatibility() const { + return backward_compatibility_; + } private: std::string name_; @@ -53,6 +62,7 @@ StandbyThreadPolicy standby_thread_policy_; size_t max_threads_; TimeDelta suggested_reclaim_time_; + SchedulerBackwardCompatibility backward_compatibility_; DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerPoolParams); };
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc index 948cf1dd..b65d50c 100644 --- a/base/task_scheduler/scheduler_worker_unittest.cc +++ b/base/task_scheduler/scheduler_worker_unittest.cc
@@ -25,6 +25,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_WIN) +#include <objbase.h> +#endif + using testing::_; using testing::Mock; using testing::Ne; @@ -277,6 +281,8 @@ DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerTest); }; +} // namespace + // Verify that when GetWork() continuously returns Sequences, all Tasks in these // Sequences run successfully. The test wakes up the SchedulerWorker once. TEST_P(TaskSchedulerWorkerTest, ContinuousWork) { @@ -596,6 +602,84 @@ worker->JoinForTesting(); } +#if defined(OS_WIN) + +namespace { + +class CoInitializeDelegate : public SchedulerWorkerDefaultDelegate { + public: + CoInitializeDelegate() + : get_work_returned_(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED) {} + + scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { + EXPECT_FALSE(get_work_returned_.IsSignaled()); + EXPECT_EQ(E_UNEXPECTED, coinitialize_hresult_); + + coinitialize_hresult_ = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(coinitialize_hresult_)) + CoUninitialize(); + + get_work_returned_.Signal(); + return nullptr; + } + + void WaitUntilGetWorkReturned() { get_work_returned_.Wait(); } + + HRESULT coinitialize_hresult() const { return coinitialize_hresult_; } + + private: + WaitableEvent get_work_returned_; + HRESULT coinitialize_hresult_ = E_UNEXPECTED; + + DISALLOW_COPY_AND_ASSIGN(CoInitializeDelegate); +}; + } // namespace + +TEST(TaskSchedulerWorkerTest, BackwardCompatibilityEnabled) { + TaskTracker task_tracker; + auto delegate = MakeUnique<CoInitializeDelegate>(); + CoInitializeDelegate* const delegate_raw = delegate.get(); + + // Create a worker with backward compatibility ENABLED. Wake it up and wait + // until GetWork() returns. + auto worker = SchedulerWorker::Create( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker, + SchedulerWorker::InitialState::ALIVE, + SchedulerBackwardCompatibility::INIT_COM_STA); + worker->WakeUp(); + delegate_raw->WaitUntilGetWorkReturned(); + + // The call to CoInitializeEx() should have returned S_FALSE to indicate that + // the COM library was already initialized on the thread. + EXPECT_EQ(S_FALSE, delegate_raw->coinitialize_hresult()); + + worker->JoinForTesting(); +} + +TEST(TaskSchedulerWorkerTest, BackwardCompatibilityDisabled) { + TaskTracker task_tracker; + auto delegate = MakeUnique<CoInitializeDelegate>(); + CoInitializeDelegate* const delegate_raw = delegate.get(); + + // Create a worker with backward compatibility DISABLED. Wake it up and wait + // until GetWork() returns. + auto worker = SchedulerWorker::Create( + ThreadPriority::NORMAL, std::move(delegate), &task_tracker, + SchedulerWorker::InitialState::ALIVE, + SchedulerBackwardCompatibility::DISABLED); + worker->WakeUp(); + delegate_raw->WaitUntilGetWorkReturned(); + + // The call to CoInitializeEx() should have returned S_OK to indicate that the + // COM library wasn't already initialized on the thread. + EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult()); + + worker->JoinForTesting(); +} + +#endif // defined(OS_WIN) + } // namespace internal } // namespace base
diff --git a/base/threading/thread.h b/base/threading/thread.h index 69dfcbf..01f7d8e 100644 --- a/base/threading/thread.h +++ b/base/threading/thread.h
@@ -175,9 +175,8 @@ // deadlock on Windows with printer worker thread. In any other case, Stop() // should be used. // - // StopSoon should not be called multiple times as it is risky to do so. It - // could cause a timing issue in message_loop() access. Call Stop() to reset - // the thread object once it is known that the thread has quit. + // Call Stop() to reset the thread object once it is known that the thread has + // quit. void StopSoon(); // Detaches the owning sequence, indicating that the next call to this API
diff --git a/base/win/scoped_handle_unittest.cc b/base/win/scoped_handle_unittest.cc index 2d90f9f..ca6fb451 100644 --- a/base/win/scoped_handle_unittest.cc +++ b/base/win/scoped_handle_unittest.cc
@@ -99,7 +99,15 @@ ASSERT_TRUE(::CloseHandle(handle)); } -TEST(ScopedHandleTest, MultiProcess) { +// Under ASan, the multi-process test crashes during process shutdown for +// unknown reasons. Disable it for now. http://crbug.com/685262 +#if defined(ADDRESS_SANITIZER) +#define MAYBE_MultiProcess DISABLED_MultiProcess +#else +#define MAYBE_MultiProcess MultiProcess +#endif + +TEST(ScopedHandleTest, MAYBE_MultiProcess) { // Initializing ICU in the child process causes a scoped handle to be created // before the test gets a chance to test the race condition, so disable ICU // for the child process here.
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni index 7fed8b3..80228e82 100644 --- a/build/config/sysroot.gni +++ b/build/config/sysroot.gni
@@ -57,6 +57,16 @@ } else { if (current_cpu == "x64") { sysroot = "//build/linux/debian_wheezy_amd64-sysroot" + + # TODO(tonikitoo): Remove the whole if clause below when debian/wheezy + # sysroots are switched to debian/jessie, crbug.com/564904. + import("//build_overrides/build.gni") + if (build_with_chromium) { + import("//ui/ozone/ozone.gni") + if (use_ozone && !is_chromecast) { + sysroot = "//build/linux/debian_jessie_amd64-sysroot" + } + } } else if (current_cpu == "x86") { sysroot = "//build/linux/debian_wheezy_i386-sysroot" } else if (current_cpu == "mipsel") {
diff --git a/build/docs/mac_hermetic_toolchain.md b/build/docs/mac_hermetic_toolchain.md new file mode 100644 index 0000000..97caee9 --- /dev/null +++ b/build/docs/mac_hermetic_toolchain.md
@@ -0,0 +1,44 @@ +# Mac and iOS hermetic toolchain instructions + +The following is a short explanation of why we use a the hermetic toolchain +and instructions on how to roll a new toolchain. + +## How to roll a new hermetic toolchain. + +1. Download a new version of Xcode, and confirm either mac or ios builds + properly with this new version. + +2. Run the following command: + + ``` + src/build/package_mac_toolchain.py /path/to/Xcode.app/ [ios|mac] + ``` + + The script will create a subset of the toolchain necessary for a build, and + upload them to be used by hermetic builds. + + If for some reason this toolchain version has already been uploaded, the + script will ask if we should create sub revision. This can be necessary when + the package script has been updated to compress additional files. + +2. Create a CL with updated [MAC|IOS]_TOOLCHAIN_VERSION and _SUB_REVISION in + src/build/mac_toolchain.py with the version created by the previous command. + +3. Run the CL thru the trybots to confirm the roll works. + +## Why we use a hermetic toolchain. + +Building Chrome Mac currently requires many binaries that come bundled with +Xcode, as well the macOS and iphoneOS SDK [also bundled with Xcode]. Note that +Chrome ships its own version of clang [compiler], but is dependent on Xcode +for these other binaries. + +Chrome should be built against the latest SDK available, but historically, +updating the SDK has been nontrivially difficult. Additionally, bot system +installs can range from Xcode 5 on some bots, to the latest and +greatest. Using a hermetic toolchain has two main benefits: + +1. Build Chrome with a well-defined toolchain [rather than whatever happens to +be installed on the machine]. + +2. Easily roll/update the toolchain.
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn index a28fad5d..7612541 100644 --- a/build/secondary/third_party/android_tools/BUILD.gn +++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -30,7 +30,7 @@ ] } -lib_version = "25.0.1" +lib_version = "25.1.0" lib_path = "$android_sdk_root/extras/android/m2repository/com/android/support" android_java_prebuilt("android_gcm_java") {
diff --git a/build_overrides/v8.gni b/build_overrides/v8.gni index a6370713..d67fd16 100644 --- a/build_overrides/v8.gni +++ b/build_overrides/v8.gni
@@ -2,26 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# V8 extras -# Adding V8 extras files requires API owners review +# This file should be empty. -# This list is for files that export symbols that are used in other extras -# files. Putting them here causes them to be executed first during snapshot -# creation. -_v8_extras_dependencies = - [ "//third_party/WebKit/Source/core/streams/CommonStrings.js" ] - -_v8_extras = [ - "//third_party/WebKit/Source/core/streams/ByteLengthQueuingStrategy.js", - "//third_party/WebKit/Source/core/streams/CountQueuingStrategy.js", - "//third_party/WebKit/Source/core/streams/ReadableStream.js", -] - -v8_extra_library_files = _v8_extras_dependencies + _v8_extras - -v8_experimental_extra_library_files = - [ "//third_party/WebKit/Source/core/streams/WritableStream.js" ] - -v8_enable_inspector_override = true -v8_enable_gdbjit_default = false -v8_imminent_deprecation_warnings_default = false +# TODO(brettw) http://crbug.com/684096 Remove this when all callers are updated +# to use the new build overrides system.
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index 6deff8b..03000b1 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc
@@ -502,11 +502,16 @@ SurfaceFactory::DrawCallback()); EXPECT_EQ(last_created_surface_id().local_frame_id(), id); + manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId); + SurfaceId surface_id(kArbitraryFrameSinkId, id); - manager_.AddSurfaceReference(manager_.GetRootSurfaceId(), surface_id); + Surface* surface = manager_.GetSurfaceForId(surface_id); + surface->AddDestructionDependency( + SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); factory_->Reset(); EXPECT_TRUE(client_.returned_resources().empty()); - manager_.RemoveSurfaceReference(manager_.GetRootSurfaceId(), surface_id); + + manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4)); EXPECT_TRUE(client_.returned_resources().empty()); local_frame_id_ = LocalFrameId(); }
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index 94bdac6..b290726 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc
@@ -92,8 +92,7 @@ SurfaceMap::iterator it = surface_map_.find(surface_id); DCHECK(it != surface_map_.end()); surface_map_.erase(it); - child_to_parent_refs_.erase(surface_id); - parent_to_child_refs_.erase(surface_id); + RemoveAllSurfaceReferences(surface_id); } void SurfaceManager::Destroy(std::unique_ptr<Surface> surface) { @@ -137,17 +136,18 @@ void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, const SurfaceId& child_id) { DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES); // Check some conditions that should never happen. We don't want to crash on // bad input from a compromised client so just return early. - if (parent_id == child_id) { - DLOG(ERROR) << "Cannot add self reference for " << parent_id.ToString(); + if (parent_id.frame_sink_id() == child_id.frame_sink_id()) { + DLOG(ERROR) << "Cannot add self reference from " << parent_id << " to " + << child_id; return; } - if (parent_id != root_surface_id_ && surface_map_.count(parent_id) == 0) { - DLOG(ERROR) << "No surface in map for " << parent_id.ToString(); - return; - } + + // We trust that |parent_id| either exists or is about to exist, since is not + // sent over IPC. We don't trust |child_id|, since it is sent over IPC. if (surface_map_.count(child_id) == 0) { DLOG(ERROR) << "No surface in map for " << child_id.ToString(); return; @@ -201,15 +201,10 @@ refs.erase(refs.begin(), temp_ref_iter); } -void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id, - const SurfaceId& child_id) { - parent_to_child_refs_[parent_id].insert(child_id); - child_to_parent_refs_[child_id].insert(parent_id); -} - void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id, const SurfaceId& child_id) { DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES); // Check if we have the reference that is requested to be removed. We don't // want to crash on bad input from a compromised client so just return early. @@ -240,29 +235,13 @@ return iter->second.size(); } -void SurfaceManager::GarbageCollectSurfacesFromRoot() { - DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES); - +void SurfaceManager::GarbageCollectSurfaces() { if (surfaces_to_destroy_.empty()) return; - SurfaceIdSet reachable_surfaces; - - // Walk down from the root and mark each SurfaceId we encounter as reachable. - std::queue<SurfaceId> surface_queue; - surface_queue.push(root_surface_id_); - while (!surface_queue.empty()) { - const SurfaceId& surface_id = surface_queue.front(); - auto iter = parent_to_child_refs_.find(surface_id); - if (iter != parent_to_child_refs_.end()) { - for (const SurfaceId& child_id : iter->second) { - // Check for cycles when inserting into |reachable_surfaces|. - if (reachable_surfaces.insert(child_id).second) - surface_queue.push(child_id); - } - } - surface_queue.pop(); - } + SurfaceIdSet reachable_surfaces = lifetime_type_ == LifetimeType::REFERENCES + ? GetLiveSurfacesForReferences() + : GetLiveSurfacesForSequences(); std::vector<std::unique_ptr<Surface>> surfaces_to_delete; @@ -283,12 +262,33 @@ surfaces_to_delete.clear(); } -void SurfaceManager::GarbageCollectSurfaces() { - if (lifetime_type_ == LifetimeType::REFERENCES) { - GarbageCollectSurfacesFromRoot(); - return; +SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() { + DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES); + + SurfaceIdSet reachable_surfaces; + + // Walk down from the root and mark each SurfaceId we encounter as reachable. + std::queue<SurfaceId> surface_queue; + surface_queue.push(root_surface_id_); + while (!surface_queue.empty()) { + const SurfaceId& surface_id = surface_queue.front(); + auto iter = parent_to_child_refs_.find(surface_id); + if (iter != parent_to_child_refs_.end()) { + for (const SurfaceId& child_id : iter->second) { + // Check for cycles when inserting into |reachable_surfaces|. + if (reachable_surfaces.insert(child_id).second) + surface_queue.push(child_id); + } + } + surface_queue.pop(); } + return reachable_surfaces; +} + +SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForSequences() { + DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES); + // Simple mark and sweep GC. // TODO(jbauman): Reduce the amount of work when nothing needs to be // destroyed. @@ -303,12 +303,7 @@ surface->SatisfyDestructionDependencies(&satisfied_sequences_, &valid_frame_sink_ids_); - // Never use both sequences and references for the same Surface. - DCHECK(surface->GetDestructionDependencyCount() == 0 || - GetSurfaceReferenceCount(surface_id) == 0); - - if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0 || - GetSurfaceReferenceCount(surface_id) > 0) { + if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { live_surfaces_set.insert(surface_id); live_surfaces.push_back(surface_id); } @@ -332,46 +327,37 @@ } } - std::vector<std::unique_ptr<Surface>> to_destroy; + return live_surfaces_set; +} - // Destroy all remaining unreachable surfaces. - for (auto iter = surfaces_to_destroy_.begin(); - iter != surfaces_to_destroy_.end();) { - SurfaceId surface_id = (*iter)->surface_id(); - if (!live_surfaces_set.count(surface_id)) { - DeregisterSurface(surface_id); - to_destroy.push_back(std::move(*iter)); - iter = surfaces_to_destroy_.erase(iter); - } else { - ++iter; - } - } - - to_destroy.clear(); +void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id, + const SurfaceId& child_id) { + parent_to_child_refs_[parent_id].insert(child_id); + child_to_parent_refs_[child_id].insert(parent_id); } void SurfaceManager::RemoveSurfaceReferenceImpl(const SurfaceId& parent_id, const SurfaceId& child_id) { - // Remove the reference from parent to child. This doesn't change anything - // about the validity of the parent. parent_to_child_refs_[parent_id].erase(child_id); + child_to_parent_refs_[child_id].erase(parent_id); +} - // Remove the reference from child to parent. This might drop the number of - // references to the child to zero. - DCHECK_EQ(child_to_parent_refs_.count(child_id), 1u); - SurfaceIdSet& child_refs = child_to_parent_refs_[child_id]; - DCHECK_EQ(child_refs.count(parent_id), 1u); - child_refs.erase(parent_id); +void SurfaceManager::RemoveAllSurfaceReferences(const SurfaceId& surface_id) { + // Remove all references from |surface_id| to a child surface. + auto iter = parent_to_child_refs_.find(surface_id); + if (iter != parent_to_child_refs_.end()) { + for (const SurfaceId& child_id : iter->second) + child_to_parent_refs_[child_id].erase(surface_id); + parent_to_child_refs_.erase(iter); + } - if (!child_refs.empty()) - return; - - // Remove any references the child holds before it gets garbage collected. - // Copy SurfaceIdSet to avoid iterator invalidation problems. - SurfaceIdSet child_child_refs = parent_to_child_refs_[child_id]; - for (auto& child_child_id : child_child_refs) - RemoveSurfaceReferenceImpl(child_id, child_child_id); - DCHECK_EQ(GetReferencedSurfaceCount(child_id), 0u); + // Remove all reference from parent surface to |surface_id|. + iter = child_to_parent_refs_.find(surface_id); + if (iter != child_to_parent_refs_.end()) { + for (const SurfaceId& parent_id : iter->second) + parent_to_child_refs_[parent_id].erase(surface_id); + child_to_parent_refs_.erase(iter); + } } void SurfaceManager::RegisterSurfaceFactoryClient(
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h index ef6a735..3ca1da7 100644 --- a/cc/surfaces/surface_manager.h +++ b/cc/surfaces/surface_manager.h
@@ -145,25 +145,33 @@ BeginFrameSource* source); void RecursivelyDetachBeginFrameSource(const FrameSinkId& frame_sink_id, BeginFrameSource* source); + // Returns true if |child namespace| is or has |search_frame_sink_id| as a // child. bool ChildContains(const FrameSinkId& child_frame_sink_id, const FrameSinkId& search_frame_sink_id) const; - // Garbage collects all destroyed surfaces not reachable from the root. Used - // when |use_references_| is true. - void GarbageCollectSurfacesFromRoot(); + // Garbage collects all destroyed surfaces that aren't live. void GarbageCollectSurfaces(); - // Removes reference from a parent surface to a child surface. Used to remove - // references without triggered GC. + // Returns set of live surfaces for |lifetime_manager_| is REFERENCES. + SurfaceIdSet GetLiveSurfacesForReferences(); + + // Returns set of live surfaces for |lifetime_manager_| is SEQUENCES. + SurfaceIdSet GetLiveSurfacesForSequences(); + + // Adds a reference from |parent_id| to |child_id| without dealing with + // temporary references. + void AddSurfaceReferenceImpl(const SurfaceId& parent_id, + const SurfaceId& child_id); + + // Removes a reference from a |parent_id| to |child_id|. void RemoveSurfaceReferenceImpl(const SurfaceId& parent_id, const SurfaceId& child_id); - // Adds a reference from parent id to child id without dealing with temporary - // references. - void AddSurfaceReferenceImpl(const SurfaceId& parent_id, - const SurfaceId& child_id); + // Removes all surface references to or from |surface_id|. Used when the + // surface is about to be deleted. + void RemoveAllSurfaceReferences(const SurfaceId& surface_id); #if DCHECK_IS_ON() // Recursively prints surface references starting at |surface_id| to |str|.
diff --git a/cc/surfaces/surface_manager_ref_unittest.cc b/cc/surfaces/surface_manager_ref_unittest.cc index b1dc27a..348ee8d 100644 --- a/cc/surfaces/surface_manager_ref_unittest.cc +++ b/cc/surfaces/surface_manager_ref_unittest.cc
@@ -13,11 +13,12 @@ #include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_manager.h" -#include "cc/surfaces/surface_sequence_generator.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using testing::ElementsAre; +using testing::IsEmpty; +using testing::SizeIs; using testing::UnorderedElementsAre; namespace cc { @@ -27,8 +28,6 @@ constexpr FrameSinkId kFrameSink1(1, 0); constexpr FrameSinkId kFrameSink2(2, 0); constexpr FrameSinkId kFrameSink3(3, 0); -const LocalFrameId kLocalFrame1(1, base::UnguessableToken::Create()); -const LocalFrameId kLocalFrame2(2, base::UnguessableToken::Create()); class StubSurfaceFactoryClient : public SurfaceFactoryClient { public: @@ -43,24 +42,17 @@ public: SurfaceManager& manager() { return *manager_; } - // Creates a new Surface with the provided SurfaceId. Will first create the - // SurfaceFactory for |frame_sink_id| if necessary. - SurfaceId CreateSurface(const FrameSinkId& frame_sink_id, - const LocalFrameId& local_frame_id) { + // Creates a new Surface with the provided |frame_sink_id| and |local_id|. + // Will first create a SurfaceFactory for |frame_sink_id| if necessary. + SurfaceId CreateSurface(const FrameSinkId& frame_sink_id, uint32_t local_id) { + LocalFrameId local_frame_id(local_id, + base::UnguessableToken::Deserialize(0, 1u)); GetFactory(frame_sink_id) .SubmitCompositorFrame(local_frame_id, CompositorFrame(), SurfaceFactory::DrawCallback()); return SurfaceId(frame_sink_id, local_frame_id); } - SurfaceId CreateSurface(uint32_t client_id, - uint32_t sink_id, - uint32_t local_id) { - return CreateSurface( - FrameSinkId(client_id, sink_id), - LocalFrameId(local_id, base::UnguessableToken::Deserialize(0, 1u))); - } - // Destroy Surface with |surface_id|. void DestroySurface(const SurfaceId& surface_id) { GetFactory(surface_id.frame_sink_id()).EvictSurface(); @@ -88,12 +80,19 @@ manager_.reset(); } - // Returns all the references from the given surface id. - SurfaceManager::SurfaceIdSet GetReferencesFrom(const SurfaceId& surface_id) { + // Returns all the references where |surface_id| is the parent. + const SurfaceManager::SurfaceIdSet& GetReferencesFrom( + const SurfaceId& surface_id) { return manager().parent_to_child_refs_[surface_id]; } - SurfaceManager::SurfaceIdSet GetReferencesFromRoot() { + // Returns all the references where |surface_id| is the child. + const SurfaceManager::SurfaceIdSet& GetReferencesFor( + const SurfaceId& surface_id) { + return manager().child_to_parent_refs_[surface_id]; + } + + const SurfaceManager::SurfaceIdSet& GetReferencesFromRoot() { return GetReferencesFrom(manager().GetRootSurfaceId()); } @@ -123,61 +122,37 @@ }; TEST_F(SurfaceManagerRefTest, AddReference) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 0u); + EXPECT_THAT(GetReferencesFor(id1), + UnorderedElementsAre(manager().GetRootSurfaceId())); + EXPECT_THAT(GetReferencesFrom(id1), IsEmpty()); } TEST_F(SurfaceManagerRefTest, AddRemoveReference) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); manager().AddSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id2), 0u); + EXPECT_THAT(GetReferencesFor(id1), + UnorderedElementsAre(manager().GetRootSurfaceId())); + EXPECT_THAT(GetReferencesFor(id2), UnorderedElementsAre(id1)); + EXPECT_THAT(GetReferencesFrom(id1), UnorderedElementsAre(id2)); + EXPECT_THAT(GetReferencesFrom(id2), IsEmpty()); manager().RemoveSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 0u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 0u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id2), 0u); -} - -TEST_F(SurfaceManagerRefTest, AddRemoveReferenceRecursive) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); - SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1); - - manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); - manager().AddSurfaceReference(id1, id2); - manager().AddSurfaceReference(id2, id3); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id2), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id3), 0u); - - // Should remove reference from id1 -> id2 and then since id2 has zero - // references all references it holds should be removed. - manager().RemoveSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 0u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 0u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 0u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id2), 0u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id3), 0u); + EXPECT_THAT(GetReferencesFor(id1), SizeIs(1)); + EXPECT_THAT(GetReferencesFor(id2), IsEmpty()); + EXPECT_THAT(GetReferencesFrom(id1), IsEmpty()); + EXPECT_THAT(GetReferencesFrom(id2), IsEmpty()); } TEST_F(SurfaceManagerRefTest, NewSurfaceFromFrameSink) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); - SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); + SurfaceId id3 = CreateSurface(kFrameSink3, 1); manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); manager().AddSurfaceReference(id1, id2); @@ -185,59 +160,83 @@ // |kFramesink2| received a CompositorFrame with a new size, so it destroys // |id2| and creates |id2_next|. No reference have been removed yet. - DestroySurface(id2); - SurfaceId id2_next = CreateSurface(kFrameSink2, kLocalFrame2); - EXPECT_NE(manager().GetSurfaceForId(id2), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id2_next), nullptr); + SurfaceId id2_next = CreateSurface(kFrameSink2, 2); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id2_next)); // Add references to and from |id2_next|. manager().AddSurfaceReference(id1, id2_next); manager().AddSurfaceReference(id2_next, id3); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2_next), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 2u); + EXPECT_THAT(GetReferencesFor(id2), UnorderedElementsAre(id1)); + EXPECT_THAT(GetReferencesFor(id2_next), UnorderedElementsAre(id1)); + EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2, id2_next)); manager().RemoveSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 0u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2_next), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 1u); + EXPECT_THAT(GetReferencesFor(id2), IsEmpty()); + EXPECT_THAT(GetReferencesFor(id2_next), UnorderedElementsAre(id1)); + EXPECT_THAT(GetReferencesFor(id3), UnorderedElementsAre(id2_next)); // |id2| should be deleted during GC but other surfaces shouldn't. - EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id2_next), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id3), nullptr); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id2_next)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id3)); +} + +TEST_F(SurfaceManagerRefTest, ReferenceCycleGetsDeleted) { + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); + SurfaceId id3 = CreateSurface(kFrameSink3, 1); + + manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); + manager().AddSurfaceReference(id1, id2); + manager().AddSurfaceReference(id2, id3); + + // This reference forms a cycle between id2 and id3. + manager().AddSurfaceReference(id3, id2); + + DestroySurface(id3); + DestroySurface(id2); + DestroySurface(id1); + + manager().RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); + + // Removing the reference from the root to id1 should allow all three surfaces + // to be deleted during GC even with a cycle between 2 and 3. + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id3)); } TEST_F(SurfaceManagerRefTest, CheckGC) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); manager().AddSurfaceReference(id1, id2); - EXPECT_NE(manager().GetSurfaceForId(id1), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id2), nullptr); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id1)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); // Destroying the surfaces shouldn't delete them yet, since there is still an // active reference on all surfaces. DestroySurface(id1); DestroySurface(id2); - EXPECT_NE(manager().GetSurfaceForId(id1), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id2), nullptr); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id1)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); // Should delete |id2| when the only reference to it is removed. manager().RemoveSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); // Should delete |id1| when the only reference to it is removed. manager().RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); - EXPECT_EQ(manager().GetSurfaceForId(id1), nullptr); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); } TEST_F(SurfaceManagerRefTest, CheckGCRecusiveFull) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); - SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); + SurfaceId id3 = CreateSurface(kFrameSink3, 1); manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); manager().AddSurfaceReference(id1, id2); @@ -249,17 +248,17 @@ // Destroying the surfaces shouldn't delete them yet, since there is still an // active reference on all surfaces. - EXPECT_NE(manager().GetSurfaceForId(id3), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id2), nullptr); - EXPECT_NE(manager().GetSurfaceForId(id1), nullptr); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id3)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_NE(nullptr, manager().GetSurfaceForId(id1)); manager().RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); // Removing the reference from the root to id1 should allow all three surfaces // to be deleted during GC. - EXPECT_EQ(manager().GetSurfaceForId(id1), nullptr); - EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr); - EXPECT_EQ(manager().GetSurfaceForId(id3), nullptr); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id1)); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id2)); + EXPECT_EQ(nullptr, manager().GetSurfaceForId(id3)); } TEST_F(SurfaceManagerRefTest, TryAddReferenceToBadSurface) { @@ -270,61 +269,61 @@ // Adding reference from root to the Surface should do nothing because // SurfaceManager doesn't know Surface for |id| exists. manager().AddSurfaceReference(manager().GetRootSurfaceId(), id); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id), 0u); + EXPECT_THAT(GetReferencesFor(id), IsEmpty()); } TEST_F(SurfaceManagerRefTest, TryDoubleAddReference) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); manager().AddSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u); + EXPECT_THAT(GetReferencesFor(id2), SizeIs(1)); + EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1)); // The second request should be ignored without crashing. manager().AddSurfaceReference(id1, id2); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u); + EXPECT_THAT(GetReferencesFor(id2), SizeIs(1)); + EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1)); } TEST_F(SurfaceManagerRefTest, TryAddSelfReference) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); // A temporary reference must exist to |id1|. - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); + EXPECT_THAT(GetReferencesFor(id1), SizeIs(1)); // Try to add a self reference. This should fail. manager().AddSurfaceReference(id1, id1); // Adding a self reference should be ignored without crashing. - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 0u); + EXPECT_THAT(GetReferencesFrom(id1), IsEmpty()); // The temporary reference to |id1| must still exist. - EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); + EXPECT_THAT(GetReferencesFor(id1), SizeIs(1)); } TEST_F(SurfaceManagerRefTest, TryRemoveBadReference) { - SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); - SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); + SurfaceId id1 = CreateSurface(kFrameSink1, 1); + SurfaceId id2 = CreateSurface(kFrameSink2, 1); // Removing non-existent reference should be ignored. manager().AddSurfaceReference(id1, id2); manager().RemoveSurfaceReference(id2, id1); - EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u); - EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); + EXPECT_THAT(GetReferencesFrom(id1), SizeIs(1)); + EXPECT_THAT(GetReferencesFor(id2), SizeIs(1)); } TEST_F(SurfaceManagerRefTest, AddSurfaceThenReference) { // Create a new surface. - const SurfaceId surface_id = CreateSurface(2, 1, 1); + const SurfaceId surface_id = CreateSurface(kFrameSink2, 1); // A temporary reference must be added to |surface_id|. EXPECT_THAT(GetAllTempReferences(), ElementsAre(surface_id)); EXPECT_THAT(GetReferencesFromRoot(), ElementsAre(surface_id)); // Create |parent_id| and add a real reference from it to |surface_id|. - const SurfaceId parent_id = CreateSurface(1, 1, 1); + const SurfaceId parent_id = CreateSurface(kFrameSink1, 1); manager().AddSurfaceReference(parent_id, surface_id); // The temporary reference to |surface_id| should be gone. @@ -337,7 +336,7 @@ TEST_F(SurfaceManagerRefTest, AddSurfaceThenRootReference) { // Create a new surface. - const SurfaceId surface_id = CreateSurface(1, 1, 1); + const SurfaceId surface_id = CreateSurface(kFrameSink1, 1); // Temporary reference should be added to |surface_id|. EXPECT_THAT(GetAllTempReferences(), ElementsAre(surface_id)); @@ -354,8 +353,8 @@ TEST_F(SurfaceManagerRefTest, AddTwoSurfacesThenOneReference) { // Create two surfaces with different FrameSinkIds. - const SurfaceId surface_id1 = CreateSurface(2, 1, 1); - const SurfaceId surface_id2 = CreateSurface(3, 1, 1); + const SurfaceId surface_id1 = CreateSurface(kFrameSink2, 1); + const SurfaceId surface_id2 = CreateSurface(kFrameSink3, 1); // Temporary reference should be added for both surfaces. EXPECT_THAT(GetAllTempReferences(), @@ -364,7 +363,7 @@ UnorderedElementsAre(surface_id1, surface_id2)); // Create |parent_id| and add a real reference from it to |surface_id1|. - const SurfaceId parent_id = CreateSurface(1, 1, 1); + const SurfaceId parent_id = CreateSurface(kFrameSink1, 1); manager().AddSurfaceReference(parent_id, surface_id1); // Real reference must be added to |surface_id1| and the temporary reference @@ -382,8 +381,8 @@ // Add two surfaces that have the same FrameSinkId. This would happen when a // client submits two CompositorFrames before parent submits a new // CompositorFrame. - const SurfaceId surface_id1 = CreateSurface(2, 1, 2); - const SurfaceId surface_id2 = CreateSurface(2, 1, 1); + const SurfaceId surface_id1 = CreateSurface(kFrameSink2, 2); + const SurfaceId surface_id2 = CreateSurface(kFrameSink2, 1); // Temporary references should be added for both surfaces and they should be // stored in the order of creation. @@ -395,7 +394,7 @@ // Create |parent_id| and add a reference from it to |surface_id2| which was // created later. - const SurfaceId parent_id = CreateSurface(1, 1, 1); + const SurfaceId parent_id = CreateSurface(kFrameSink1, 1); manager().AddSurfaceReference(parent_id, surface_id2); // The real reference should be added for |surface_id2| and the temporary @@ -409,8 +408,8 @@ TEST_F(SurfaceManagerRefTest, RemoveFirstTempRefOnly) { // Add two surfaces that have the same FrameSinkId. This would happen when a // client submits two CFs before parent submits a new CF. - const SurfaceId surface_id1 = CreateSurface(2, 1, 1); - const SurfaceId surface_id2 = CreateSurface(2, 1, 2); + const SurfaceId surface_id1 = CreateSurface(kFrameSink2, 1); + const SurfaceId surface_id2 = CreateSurface(kFrameSink2, 2); // Temporary references should be added for both surfaces and they should be // stored in the order of creation. @@ -422,7 +421,7 @@ // Create |parent_id| and add a reference from it to |surface_id1| which was // created earlier. - const SurfaceId parent_id = CreateSurface(1, 1, 1); + const SurfaceId parent_id = CreateSurface(kFrameSink1, 1); manager().AddSurfaceReference(parent_id, surface_id1); // The real reference should be added for |surface_id1| and its temporary
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 0980a89..59da207c 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -773,6 +773,11 @@ </intent-filter> </receiver> + <!-- Android Notification job service --> + <service android:name="org.chromium.chrome.browser.notifications.NotificationJobService" + android:exported="false" + android:permission="android.permission.BIND_JOB_SERVICE"/> + <!-- GcmTaskService implementation to wake Chrome on scheduled events --> <service android:name="org.chromium.chrome.browser.ChromeBackgroundService" android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java index c1e412b..96c9c59a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
@@ -7,6 +7,7 @@ import android.app.Activity; import android.content.SharedPreferences; import android.provider.Settings; +import android.text.TextUtils; import org.chromium.base.ApplicationState; import org.chromium.base.ApplicationStatus; @@ -197,15 +198,14 @@ } private boolean hasLocaleChanged(String newLocale) { - String previousLocale = ContextUtils.getAppSharedPreferences().getString( - PREF_LOCALE, ""); - - if (!previousLocale.equals(newLocale)) { + String previousLocale = ContextUtils.getAppSharedPreferences().getString(PREF_LOCALE, null); + if (!TextUtils.equals(previousLocale, newLocale)) { SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); SharedPreferences.Editor editor = prefs.edit(); editor.putString(PREF_LOCALE, newLocale); editor.apply(); - return true; + // Consider writing the initial value to prefs as _not_ changing the locale. + return previousLocale != null; } return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java index 4e3837ab..7588b4d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java
@@ -120,6 +120,9 @@ return mPercentCompleted; } + /** + * @return Remaining download time in milliseconds or -1 if it is unknown. + */ public long getTimeRemainingInMillis() { return mTimeRemainingInMillis; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index 737dd84..fc9ed5b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -270,7 +270,7 @@ * @param percentage Percentage completed. Value should be between 0 to 100 if * the percentage can be determined, or -1 if it is unknown. * @param bytesReceived Total number of bytes received. - * @param timeRemainingInMillis Remaining download time in milliseconds. + * @param timeRemainingInMillis Remaining download time in milliseconds or -1 if it is unknown. * @param startTime Time when download started. * @param isOffTheRecord Whether the download is off the record. * @param canDownloadWhileMetered Whether the download can happen in metered network. @@ -292,7 +292,9 @@ contentText = DownloadUtils.getStringForBytes( mContext, DownloadUtils.BYTES_DOWNLOADED_STRINGS, bytesReceived); } else { - contentText = formatRemainingTime(mContext, timeRemainingInMillis); + contentText = timeRemainingInMillis < 0 + ? mContext.getResources().getString(R.string.download_started) + : formatRemainingTime(mContext, timeRemainingInMillis); } int resId = isDownloadPending ? R.drawable.ic_download_pending : android.R.drawable.stat_sys_download;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java index de32ce9f5..5be9878 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -589,7 +589,7 @@ } if (info.getBytesReceived() == 0 - || (!item.isIndeterminate() && info.getTimeRemainingInMillis() == 0)) { + || (!item.isIndeterminate() && info.getTimeRemainingInMillis() < 0)) { // We lack enough information about the download to display a useful string. return context.getString(R.string.download_started); } else if (item.isIndeterminate()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java index cdd6a64..366cb54 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.notifications; +import android.content.Intent; + /** * Constants used in more than a single Notification class, e.g. intents and extra names. */ @@ -23,6 +25,9 @@ /** * Names of the Intent extras used for Intents related to notifications. These intents are set * and owned by Chromium. + * + * When adding a new extra, as well as setting it on the intent in NotificationPlatformBridge, + * it *must* also be set in {@link NotificationJobService#getJobExtrasFromIntent(Intent)} */ static final String EXTRA_NOTIFICATION_ID = "notification_id"; static final String EXTRA_NOTIFICATION_INFO_ORIGIN = "notification_info_origin"; @@ -32,6 +37,8 @@ static final String EXTRA_NOTIFICATION_INFO_TAG = "notification_info_tag"; static final String EXTRA_NOTIFICATION_INFO_ACTION_INDEX = "notification_info_action_index"; static final String EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE = "notification_info_webapk_package"; + static final String EXTRA_NOTIFICATION_REPLY = "notification_reply"; + static final String EXTRA_NOTIFICATION_ACTION = "notification_action"; /** * Unique identifier for a single sync notification. Since the notification ID is reused,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java new file mode 100644 index 0000000..10bb8872 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java
@@ -0,0 +1,91 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.notifications; + +import android.annotation.TargetApi; +import android.app.job.JobParameters; +import android.app.job.JobService; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.os.PersistableBundle; + +import org.chromium.base.ThreadUtils; + +/** + * Processes jobs scheduled when user actions are issued on web notifications. + * We use this instead of starting the NotificationService on N+. + */ +@TargetApi(Build.VERSION_CODES.N) +public class NotificationJobService extends JobService { + // We don't need to distinguish between jobs sent to this service, so we can reuse one job id. + // But it ought to be distinct from job ids used with other JobService classes in our code. + static final int JOB_ID = 21; + + static PersistableBundle getJobExtrasFromIntent(Intent intent) { + PersistableBundle bundle = new PersistableBundle(); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_ID, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_ID)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID)); + bundle.putBoolean(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, + intent.getBooleanExtra( + NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, false)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG)); + bundle.putInt(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, + intent.getIntExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, -1)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE, + intent.getStringExtra( + NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_ACTION, intent.getAction()); + // Only primitives can be set on a persistable bundle, so extract the raw reply. + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_REPLY, + NotificationPlatformBridge.getNotificationReply(intent)); + return bundle; + } + + /** + * Called when a Notification has been interacted with by the user. If we can verify that + * the Intent has a notification Id, start Chrome (if needed) on the UI thread. + * + * We get a wakelock for our process for the duration of this method. + * + * @return True if there is more work to be done to handle the job, to signal we would like our + * wakelock extended until we call {@link #jobFinished}. False if we have finished handling the + * job. + */ + @Override + public boolean onStartJob(final JobParameters params) { + PersistableBundle extras = params.getExtras(); + if (!extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_ID) + || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN) + || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG)) { + return false; + } + + Intent intent = + new Intent(extras.getString(NotificationConstants.EXTRA_NOTIFICATION_ACTION)); + intent.putExtras(new Bundle(extras)); + + ThreadUtils.assertOnUiThread(); + NotificationService.dispatchIntentOnUIThread(this, intent); + + // TODO(crbug.com/685197): Return true here and call jobFinished to release the wake + // lock only after the event has been completely handled by the service worker. + return false; + } + + @Override + public boolean onStopJob(JobParameters params) { + // As it stands, all our job processing is done synchronously in onStartJob so there is + // nothing to do here. Even once we include further async processing in our jobs + // (crbug.com/685197) it may by infeasible to cancel this halfway through. + // TODO(crbug.com/685197): Check what we can safely do here and update comment. + return false; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java index 3399dae..5bc1221c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -215,9 +215,14 @@ } @Nullable - private static String getNotificationReply(Intent intent) { + static String getNotificationReply(Intent intent) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { // RemoteInput was added in KITKAT_WATCH. + if (intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_REPLY) != null) { + // If the notification click went through the job scheduler, we will have set + // the reply as a standard string extra. + return intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_REPLY); + } Bundle remoteInputResults = RemoteInput.getResultsFromIntent(intent); if (remoteInputResults != null) { CharSequence reply = @@ -312,6 +317,9 @@ * Returns the PendingIntent for completing |action| on the notification identified by the data * in the other parameters. * + * All parameters set here should also be set in + * {@link NotificationJobService#getJobExtrasFromIntent(Intent)}. + * * @param context An appropriate context for the intent class and broadcast. * @param action The action this pending intent will represent. * @param notificationId The id of the notification. @@ -329,7 +337,6 @@ Uri intentData = makeIntentData(notificationId, origin, actionIndex); Intent intent = new Intent(action, intentData); intent.setClass(context, NotificationService.Receiver.class); - intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_ID, notificationId); intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, origin); intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, profileId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java index 176e45f0..15f833e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java
@@ -5,9 +5,14 @@ package org.chromium.chrome.browser.notifications; import android.app.IntentService; +import android.app.job.JobInfo; +import android.app.job.JobScheduler; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.os.Build; +import android.os.PersistableBundle; import android.os.StrictMode; import android.util.Log; @@ -33,11 +38,30 @@ @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "Received a notification intent in the NotificationService's receiver."); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + // Android encourages us not to start services directly on N+, so instead we + // schedule a job to handle the notification intent. We use the Android JobScheduler + // rather than GcmNetworkManager or FirebaseJobDispatcher since the JobScheduler + // allows us to execute immediately by setting an override deadline of zero + // milliseconds. + // TODO(crbug.com/685210): UMA to check this does not introduce noticeable latency. + PersistableBundle extras = NotificationJobService.getJobExtrasFromIntent(intent); + JobInfo job = + new JobInfo + .Builder(NotificationJobService.JOB_ID, + new ComponentName(context, NotificationJobService.class)) + .setExtras(extras) + .setOverrideDeadline(0) + .build(); + JobScheduler scheduler = + (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); + scheduler.schedule(job); + } else { + // TODO(peter): Do we need to acquire a wake lock here? - // TODO(peter): Do we need to acquire a wake lock here? - - intent.setClass(context, NotificationService.class); - context.startService(intent); + intent.setClass(context, NotificationService.class); + context.startService(intent); + } } } @@ -62,7 +86,7 @@ ThreadUtils.runOnUiThread(new Runnable() { @Override public void run() { - dispatchIntentOnUIThread(intent); + dispatchIntentOnUIThread(NotificationService.this, intent); } }); } @@ -74,9 +98,9 @@ * @param intent The intent containing the notification's information. */ @SuppressFBWarnings("DM_EXIT") - private void dispatchIntentOnUIThread(Intent intent) { + static void dispatchIntentOnUIThread(Context context, Intent intent) { try { - ChromeBrowserInitializer.getInstance(this).handleSynchronousStartup(); + ChromeBrowserInitializer.getInstance(context).handleSynchronousStartup(); // Warm up the WebappRegistry, as we need to check if this notification should launch a // standalone web app. This no-ops if the registry is already initialized and warmed,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index 94afdaf..5718ad0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -786,6 +786,13 @@ protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); + // On first run, the NewTabPageView is initialized behind the First Run Experience, meaning + // the UiConfig will pickup the screen layout then. However onConfigurationChanged is not + // called on orientation changes until the FRE is completed. This means that if a user + // starts the FRE in one orientation, changes an orientation and then leaves the FRE the + // UiConfig will have the wrong orientation. https://crbug.com/683886. + mUiConfig.updateDisplayStyle(); + if (visibility == VISIBLE) { updateVoiceSearchButtonVisibility(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java index 64516b1..1db900b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/DisplayStyleObserverAdapter.java
@@ -24,7 +24,7 @@ /** * Latest value that we transmitted to the adapted observer. If we didn't transfer any yet, - * the value is not a valid {@code DisplayStyle} + * the value is null. @see UiConfig.DisplayStyle. */ @UiConfig.DisplayStyle private Integer mNotifiedDisplayStyle;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java index 0cf7408..65626274 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
@@ -13,6 +13,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Parcelable; import android.os.RemoteException; import android.util.JsonWriter; @@ -46,6 +47,8 @@ private static final String EXTRA_ORIGIN = "origin"; private static final String EXTRA_DETAILS = "details"; private static final String EXTRA_INSTRUMENT_DETAILS = "instrumentDetails"; + private static final String EXTRA_CERTIFICATE_CHAIN = "certificateChain"; + private static final String EXTRA_CERTIFICATE = "certificate"; private static final String EMPTY_JSON_DATA = "{}"; private final Handler mHandler; private final WebContents mWebContents; @@ -104,9 +107,21 @@ mIsReadyToPayIntent.setClassName(mIsReadyToPayIntent.getPackage(), className); } + private void addCertificateChain(Bundle extras, byte[][] certificateChain) { + if (certificateChain != null && certificateChain.length > 0) { + Parcelable[] certificateArray = new Parcelable[certificateChain.length]; + for (int i = 0; i < certificateChain.length; i++) { + Bundle bundle = new Bundle(); + bundle.putByteArray(EXTRA_CERTIFICATE, certificateChain[i]); + certificateArray[i] = bundle; + } + extras.putParcelableArray(EXTRA_CERTIFICATE_CHAIN, certificateArray); + } + } + @Override public void getInstruments(Map<String, PaymentMethodData> methodData, String origin, - InstrumentsCallback callback) { + byte[][] certificateChain, InstrumentsCallback callback) { mInstrumentsCallback = callback; if (mIsReadyToPayIntent.getPackage() == null) { mHandler.post(new Runnable() { @@ -122,6 +137,7 @@ extras.putString(EXTRA_ORIGIN, origin); PaymentMethodData data = methodData.get(mMethodNames.iterator().next()); extras.putString(EXTRA_DATA, data == null ? EMPTY_JSON_DATA : data.stringifiedData); + addCertificateChain(extras, certificateChain); mIsReadyToPayIntent.putExtras(extras); if (mIsReadyToPayService != null) { @@ -202,13 +218,14 @@ } @Override - public void invokePaymentApp(String merchantName, String origin, + public void invokePaymentApp(String merchantName, String origin, byte[][] certificateChain, Map<String, PaymentMethodData> methodDataMap, PaymentItem total, List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers, InstrumentDetailsCallback callback) { assert !mMethodNames.isEmpty(); Bundle extras = new Bundle(); extras.putString(EXTRA_ORIGIN, origin); + addCertificateChain(extras, certificateChain); String methodName = mMethodNames.iterator().next(); extras.putString(EXTRA_METHOD_NAME, methodName);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java index a868d46..ca17fba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFactory.java
@@ -8,8 +8,11 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; import android.net.Uri; +import android.util.Pair; +import org.chromium.base.ContextUtils; import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedCallback; import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition; import org.chromium.content_public.browser.WebContents; @@ -58,6 +61,8 @@ for (int i = 0; i < matches.size(); i++) { ResolveInfo match = matches.get(i); String packageName = match.activityInfo.packageName; + // Do not recommend disabled apps. + if (!PaymentPreferencesUtil.isAndroidPaymentAppEnabled(packageName)) continue; AndroidPaymentApp installedApp = installedApps.get(packageName); if (installedApp == null) { CharSequence label = match.loadLabel(pm); @@ -81,4 +86,40 @@ callback.onAllPaymentAppsCreated(); } + + /** + * Checks whether there are Android payment apps on device. + * + * @return True if there are Android payment apps on device. + */ + public static boolean hasAndroidPaymentApps() { + PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); + // Note that all Android payment apps must support org.chromium.intent.action.PAY action + // without additional data to be detected. + Intent payIntent = new Intent(AndroidPaymentApp.ACTION_PAY); + return !pm.queryIntentActivities(payIntent, 0).isEmpty(); + } + + /** + * Gets Android payments apps' information on device. + * + * @return Map of Android payment apps' package names to their information. Each entry of the + * map represents an app and the value stores its name and icon. + */ + public static Map<String, Pair<String, Drawable>> getAndroidPaymentAppsInfo() { + Map<String, Pair<String, Drawable>> paymentAppsInfo = new HashMap<>(); + + PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); + Intent payIntent = new Intent(AndroidPaymentApp.ACTION_PAY); + List<ResolveInfo> matches = pm.queryIntentActivities(payIntent, 0); + if (matches.isEmpty()) return paymentAppsInfo; + + for (ResolveInfo match : matches) { + Pair<String, Drawable> appInfo = + new Pair<String, Drawable>(match.loadLabel(pm).toString(), match.loadIcon(pm)); + paymentAppsInfo.put(match.activityInfo.packageName, appInfo); + } + + return paymentAppsInfo; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java index 6ed498b..3dff383 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
@@ -46,7 +46,7 @@ @Override public void getInstruments(Map<String, PaymentMethodData> methodDataMap, String unusedOrigin, - final InstrumentsCallback callback) { + byte[][] unusedCertificateChain, final InstrumentsCallback callback) { PersonalDataManager pdm = PersonalDataManager.getInstance(); List<CreditCard> cards = pdm.getCreditCardsToSuggest(); final List<PaymentInstrument> instruments = new ArrayList<>(cards.size());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java index 4a790e5..22294230 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
@@ -80,8 +80,8 @@ @Override public void invokePaymentApp(String unusedMerchantName, String unusedOrigin, - Map<String, PaymentMethodData> unusedMethodDataMap, PaymentItem unusedTotal, - List<PaymentItem> unusedDisplayItems, + byte[][] unusedCertificateChain, Map<String, PaymentMethodData> unusedMethodDataMap, + PaymentItem unusedTotal, List<PaymentItem> unusedDisplayItems, Map<String, PaymentDetailsModifier> unusedModifiers, InstrumentDetailsCallback callback) { // The billing address should never be null for a credit card at this point.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java index b7cf365..55ecc47 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java
@@ -33,14 +33,16 @@ * cards for the current profile. Can return null or empty list, e.g., if user has no locally * stored credit cards. * - * @param methodDataMap The map from methods to method specific data. The data contains such - * information as whether the app should be invoked in test or production - * mode, merchant identifier, or a public key. - * @param origin The origin of this merchant. - * @param callback The object that will receive the list of instruments. + * @param methodDataMap The map from methods to method specific data. The data contains such + * information as whether the app should be invoked in test or + * production + * mode, merchant identifier, or a public key. + * @param origin The origin of this merchant. + * @param certificateChain The site certificate chain of the merchant. + * @param callback The object that will receive the list of instruments. */ void getInstruments(Map<String, PaymentMethodData> methodDataMap, String origin, - InstrumentsCallback callback); + byte[][] certificateChain, InstrumentsCallback callback); /** * Returns a list of all payment method names that this app supports. For example, ["visa",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java index 45079f6..88ba231f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java
@@ -73,20 +73,21 @@ * * The callback will be invoked with the resulting payment details or error. * - * @param merchantName The name of the merchant. - * @param origin The origin of this merchant. - * @param methodDataMap The payment-method specific data for all applicable payment methods, - * e.g., whether the app should be invoked in test or production, a - * merchant identifier, or a public key. - * @param total The total amount. - * @param displayItems The shopping cart items. - * @param modifiers The relevant payment details modifiers. - * @param callback The object that will receive the instrument details. + * @param merchantName The name of the merchant. + * @param origin The origin of this merchant. + * @param certificateChain The site certificate chain of the merchant. + * @param methodDataMap The payment-method specific data for all applicable payment methods, + * e.g., whether the app should be invoked in test or production, a + * merchant identifier, or a public key. + * @param total The total amount. + * @param displayItems The shopping cart items. + * @param modifiers The relevant payment details modifiers. + * @param callback The object that will receive the instrument details. */ public abstract void invokePaymentApp(String merchantName, String origin, - Map<String, PaymentMethodData> methodDataMap, PaymentItem total, - List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers, - InstrumentDetailsCallback callback); + byte[][] certificateChain, Map<String, PaymentMethodData> methodDataMap, + PaymentItem total, List<PaymentItem> displayItems, + Map<String, PaymentDetailsModifier> modifiers, InstrumentDetailsCallback callback); /** * Cleans up any resources held by the payment instrument. For example, closes server
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentPreferencesUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentPreferencesUtil.java new file mode 100644 index 0000000..62e40a3 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentPreferencesUtil.java
@@ -0,0 +1,58 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.payments; + +import org.chromium.base.ContextUtils; + +/** Place to define and control payment preferences. */ +public class PaymentPreferencesUtil { + // Avoid instantiation by accident. + private PaymentPreferencesUtil() {} + + /** Preference to indicate whether payment request has been completed successfully once.*/ + private static final String PAYMENT_COMPLETE_ONCE = "payment_complete_once"; + + /** Prefix of the preferences to persist Android payment apps' status. */ + public static final String PAYMENT_ANDROID_APP_ENABLED_ = "payment_android_app_enabled_"; + + /** + * Checks whehter the payment request has been successfully completed once. + * + * @return True If payment request has been successfully completed once. + */ + public static boolean isPaymentCompleteOnce() { + return ContextUtils.getAppSharedPreferences().getBoolean(PAYMENT_COMPLETE_ONCE, false); + } + + /** Sets the payment request has been successfully completed once. */ + public static void setPaymentCompleteOnce() { + ContextUtils.getAppSharedPreferences() + .edit() + .putBoolean(PAYMENT_COMPLETE_ONCE, true) + .apply(); + } + + /** + * Checks whether the Android payment app is enabled by user from the settings. The default + * status is enabled. + * + * @param packageName The package name of the Android payment app. + * @return True If the Android payment app is enabled by user. + */ + public static boolean isAndroidPaymentAppEnabled(String packageName) { + return ContextUtils.getAppSharedPreferences().getBoolean( + getAndroidPaymentAppEnabledPreferenceKey(packageName), true); + } + + /** + * Gets preference key for status of the Android payment app. + * + * @param packageName The packageName of the Android payment app. + * @return The preference key. + */ + public static String getAndroidPaymentAppEnabledPreferenceKey(String packageName) { + return PAYMENT_ANDROID_APP_ENABLED_ + packageName; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index f282bc7..bbf43d89 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -12,7 +12,6 @@ import android.text.TextUtils; import org.chromium.base.Callback; -import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; @@ -22,6 +21,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.favicon.FaviconHelper; +import org.chromium.chrome.browser.pageinfo.CertificateChainHelper; import org.chromium.chrome.browser.payments.ui.Completable; import org.chromium.chrome.browser.payments.ui.ContactDetailsSection; import org.chromium.chrome.browser.payments.ui.LineItem; @@ -167,7 +167,6 @@ private static final String TAG = "cr_PaymentRequest"; private static final String ANDROID_PAY_METHOD_NAME = "https://android.com/pay"; - private static final String PAYMENT_COMPLETE_ONCE = "payment_complete_once"; private static final Comparator<Completable> COMPLETENESS_COMPARATOR = new Comparator<Completable>() { @Override @@ -213,6 +212,7 @@ private final WebContents mWebContents; private final String mMerchantName; private final String mOrigin; + private final byte[][] mCertificateChain; private final AddressEditor mAddressEditor; private final CardEditor mCardEditor; private final PaymentRequestJourneyLogger mJourneyLogger = new PaymentRequestJourneyLogger(); @@ -306,6 +306,7 @@ // The feature is available only in secure context, so it's OK to not show HTTPS. mOrigin = UrlFormatter.formatUrlForSecurityDisplay( webContents.getLastCommittedUrl(), false); + mCertificateChain = CertificateChainHelper.getCertificateChain(mWebContents); final FaviconHelper faviconHelper = new FaviconHelper(); faviconHelper.getLocalFaviconImageForURL(Profile.getLastUsedProfile(), @@ -409,8 +410,8 @@ mUI = new PaymentRequestUI(mContext, this, requestShipping, requestPayerName || requestPayerPhone || requestPayerEmail, - mMerchantSupportsAutofillPaymentInstruments, !isPaymentCompleteOnce(), - mMerchantName, mOrigin, + mMerchantSupportsAutofillPaymentInstruments, + !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantName, mOrigin, new ShippingStrings( options == null ? PaymentShippingType.SHIPPING : options.shippingType)); @@ -501,6 +502,7 @@ if (!mShouldSkipShowingPaymentRequestUi) mUI.show(); recordSuccessFunnelHistograms("Shown"); + mJourneyLogger.setShowCalled(); triggerPaymentAppUiSkipIfApplicable(); } @@ -571,7 +573,7 @@ // so a fast response from a non-autofill payment app at the front of the app list does not // cause NOT_SUPPORTED payment rejection. for (Map.Entry<PaymentApp, Map<String, PaymentMethodData>> q : queryApps.entrySet()) { - q.getKey().getInstruments(q.getValue(), mOrigin, this); + q.getKey().getInstruments(q.getValue(), mOrigin, mCertificateChain, this); } } @@ -1084,8 +1086,9 @@ } } - instrument.invokePaymentApp(mMerchantName, mOrigin, Collections.unmodifiableMap(methodData), - mRawTotal, mRawLineItems, Collections.unmodifiableMap(modifiers), this); + instrument.invokePaymentApp(mMerchantName, mOrigin, mCertificateChain, + Collections.unmodifiableMap(methodData), mRawTotal, mRawLineItems, + Collections.unmodifiableMap(modifiers), this); recordSuccessFunnelHistograms("PayClicked"); return !(instrument instanceof AutofillPaymentInstrument); @@ -1131,21 +1134,12 @@ public void complete(int result) { if (mClient == null) return; recordSuccessFunnelHistograms("Completed"); - if (!isPaymentCompleteOnce()) setPaymentCompleteOnce(); + if (!PaymentPreferencesUtil.isPaymentCompleteOnce()) { + PaymentPreferencesUtil.setPaymentCompleteOnce(); + } closeUI(PaymentComplete.FAIL != result); } - private static boolean isPaymentCompleteOnce() { - return ContextUtils.getAppSharedPreferences().getBoolean(PAYMENT_COMPLETE_ONCE, false); - } - - private static void setPaymentCompleteOnce() { - ContextUtils.getAppSharedPreferences() - .edit() - .putBoolean(PAYMENT_COMPLETE_ONCE, true) - .apply(); - } - @Override public void onCardAndAddressSettingsClicked() { Intent intent = PreferencesLauncher.createIntentForSettingsPage( @@ -1188,12 +1182,16 @@ } query.addObserver(this); - if (isFinishedQueryingPaymentApps()) query.setResponse(mCanMakePayment); + if (isFinishedQueryingPaymentApps()) { + query.setResponse(mCanMakePayment); + mJourneyLogger.setCanMakePaymentValue(mCanMakePayment); + } } private void respondCanMakePaymentQuery(boolean response) { mClient.onCanMakePayment(response ? CanMakePaymentQueryResult.CAN_MAKE_PAYMENT : CanMakePaymentQueryResult.CANNOT_MAKE_PAYMENT); + mJourneyLogger.setCanMakePaymentValue(mCanMakePayment); if (sObserverForTest != null) { sObserverForTest.onPaymentRequestServiceCanMakePaymentQueryResponded(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLogger.java index 9991898..05c1d5e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLogger.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLogger.java
@@ -10,11 +10,29 @@ * A class used to record journey metrics for the Payment Request feature. */ public class PaymentRequestJourneyLogger { + // The index of the different sections of a Payment Request. Used to record journey stats. public static final int SECTION_CONTACT_INFO = 0; public static final int SECTION_CREDIT_CARDS = 1; public static final int SECTION_SHIPPING_ADDRESS = 2; public static final int SECTION_MAX = 3; + // For the CanMakePayment histograms. + public static final int CAN_MAKE_PAYMENT_USED = 0; + public static final int CAN_MAKE_PAYMENT_NOT_USED = 1; + public static final int CAN_MAKE_PAYMENT_USE_MAX = 2; + + // Used to log CanMakePayment's effect on whether the transaction was completed. + public static final int CMP_EFFECT_ON_COMPLETION_COMPLETED = 0; + public static final int CMP_EFFECT_ON_COMPLETION_ABORTED = 1; + public static final int CMP_EFFECT_ON_COMPLETION_MAX = 2; + + // Used to mesure the impact of the CanMakePayment return value on whether the Payment Request + // is shown to the user. + public static final int CMP_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW = 0; + public static final int CMP_SHOW_DID_SHOW = 1 << 0; + public static final int CMP_SHOW_COULD_MAKE_PAYMENT = 1 << 1; + public static final int CMP_SHOW_MAX = 4; + // The minimum expected value of CustomCountHistograms is always set to 1. It is still possible // to log the value 0 to that type of histogram. private static final int MIN_EXPECTED_SAMPLE = 1; @@ -31,6 +49,10 @@ private SectionStats[] mSections; + private boolean mWasCanMakePaymentUsed; + private boolean mCouldMakePayment; + private boolean mWasShowCalled; + public PaymentRequestJourneyLogger() { mSections = new SectionStats[SECTION_MAX]; for (int i = 0; i < mSections.length; ++i) { @@ -38,7 +60,7 @@ } } - /* + /** * Sets the number of suggestions shown for the specified section. * * @param section The section for which to log. @@ -50,7 +72,7 @@ mSections[section].mIsRequested = true; } - /* + /** * Increments the number of selection changes for the specified section. * * @param section The section for which to log. @@ -60,7 +82,7 @@ mSections[section].mNumberSelectionChanges++; } - /* + /** * Increments the number of selection edits for the specified section. * * @param section The section for which to log. @@ -70,7 +92,7 @@ mSections[section].mNumberSelectionEdits++; } - /* + /** * Increments the number of selection adds for the specified section. * * @param section The section for which to log. @@ -80,13 +102,46 @@ mSections[section].mNumberSelectionAdds++; } + /** + * Records the fact that the merchant called CanMakePayment and records it's return value. + * + * @param value The return value of the CanMakePayment call. + */ + public void setCanMakePaymentValue(boolean value) { + mWasCanMakePaymentUsed = true; + mCouldMakePayment |= value; + } + + /** + * Records the fact that the Payment Request was shown to the user. + */ + public void setShowCalled() { + mWasShowCalled = true; + } + /* - * Records the histograms for all the sections that were requested by the merchant. This method - * should be called when the payment request has either been completed or aborted. + * Records the histograms for all the sections that were requested by the merchant and for the + * usage of the CanMakePayment method and its effect on the transaction. This method should be + * called when the payment request has either been completed or aborted. * * @param submissionType A string indicating the way the payment request was concluded. */ public void recordJourneyStatsHistograms(String submissionType) { + recordSectionSpecificStats(submissionType); + + // Record the CanMakePayment metrics based on whether the transaction was completed or + // aborted by the user (UserAborted) or otherwise (OtherAborted). + recordCanMakePaymentStats(submissionType.contains("Abort") + ? CMP_EFFECT_ON_COMPLETION_ABORTED + : CMP_EFFECT_ON_COMPLETION_COMPLETED); + } + + /** + * Records the histograms for all the sections that were requested by the merchant. + * + * @param submissionType A string indicating the way the payment request was concluded. + */ + private void recordSectionSpecificStats(String submissionType) { for (int i = 0; i < mSections.length; ++i) { String nameSuffix = ""; switch (i) { @@ -126,4 +181,56 @@ } } } + + /** + * Records the metrics related the the CanMakePayment method. + * + * @param completionStatus Whether the transaction was completed or aborted. + */ + private void recordCanMakePaymentStats(int completionStatus) { + // Record CanMakePayment usage. + RecordHistogram.recordEnumeratedHistogram("PaymentRequest.CanMakePayment.Usage", + mWasCanMakePaymentUsed ? CAN_MAKE_PAYMENT_USED : CAN_MAKE_PAYMENT_NOT_USED, + CAN_MAKE_PAYMENT_USE_MAX); + + recordCanMakePaymentEffectOnShow(); + recordCanMakePaymentEffectOnCompletion(completionStatus); + } + + /** + * Records CanMakePayment's return value effect on whether the Payment Request was shown or not. + */ + private void recordCanMakePaymentEffectOnShow() { + if (!mWasCanMakePaymentUsed) return; + + int effectOnShow = 0; + if (mWasShowCalled) effectOnShow |= CMP_SHOW_DID_SHOW; + if (mCouldMakePayment) effectOnShow |= CMP_SHOW_COULD_MAKE_PAYMENT; + + RecordHistogram.recordEnumeratedHistogram( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", effectOnShow, CMP_SHOW_MAX); + } + + /** + * Records the completion status depending on the the usage and return value of the + * CanMakePaymentMethod. + * + * @param completionStatus Whether the transaction was completed or aborted. + */ + private void recordCanMakePaymentEffectOnCompletion(int completionStatus) { + if (!mWasShowCalled) return; + + String histogramName = "PaymentRequest.CanMakePayment."; + + if (!mWasCanMakePaymentUsed) { + histogramName += "NotUsed.WithShowEffectOnCompletion"; + } else if (mCouldMakePayment) { + histogramName += "Used.TrueWithShowEffectOnCompletion"; + } else { + histogramName += "Used.FalseWithShowEffectOnCompletion"; + } + + RecordHistogram.recordEnumeratedHistogram( + histogramName, completionStatus, CMP_EFFECT_ON_COMPLETION_MAX); + } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java index a7ea1755..26c67fa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java
@@ -50,7 +50,8 @@ @Override public void getInstruments(Map<String, PaymentMethodData> unusedMethodDataMap, - String unusedOrigin, final InstrumentsCallback callback) { + String unusedOrigin, byte[][] unusedCertificateChain, + final InstrumentsCallback callback) { final List<PaymentInstrument> instruments = new ArrayList<PaymentInstrument>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java index e50339c4..3d5c877 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java
@@ -57,9 +57,9 @@ @Override public void invokePaymentApp(String merchantName, String origin, - Map<String, PaymentMethodData> methodData, PaymentItem total, - List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers, - InstrumentDetailsCallback callback) { + byte[][] unusedCertificateChain, Map<String, PaymentMethodData> methodData, + PaymentItem total, List<PaymentItem> displayItems, + Map<String, PaymentDetailsModifier> modifiers, InstrumentDetailsCallback callback) { ServiceWorkerPaymentAppBridge.invokePaymentApp(mWebContents, mAppRegistrationId, mOption.id, origin, new HashSet<>(methodData.values()), total, displayItems, new HashSet<>(modifiers.values()));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppPreference.java new file mode 100644 index 0000000..39e71a1 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppPreference.java
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.preferences.autofill; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.preferences.ChromeSwitchPreference; + +/** ChromeSwitchPreference with fixed icon size for Android payment apps. */ +public class AndroidPaymentAppPreference extends ChromeSwitchPreference { + public AndroidPaymentAppPreference(Context context) { + super(context, null); + } + + @Override + protected View onCreateView(ViewGroup parent) { + View view = super.onCreateView(parent); + + int iconSize = + getContext().getResources().getDimensionPixelSize(R.dimen.payments_favicon_size); + View iconView = view.findViewById(android.R.id.icon); + ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams(); + layoutParams.width = iconSize; + layoutParams.height = iconSize; + iconView.setLayoutParams(layoutParams); + + return view; + } +} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppsFragment.java new file mode 100644 index 0000000..d02492b --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppsFragment.java
@@ -0,0 +1,62 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.preferences.autofill; + +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.PreferenceFragment; +import android.util.Pair; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.payments.AndroidPaymentAppFactory; +import org.chromium.chrome.browser.payments.PaymentPreferencesUtil; +import org.chromium.chrome.browser.preferences.TextMessagePreference; + +import java.util.Map; + +/** + * Preference fragment to allow users to control use of the Android payment apps on device. + */ +public class AndroidPaymentAppsFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.autofill_and_payments_preference_fragment_screen); + getActivity().setTitle(R.string.payment_apps_title); + } + + @Override + public void onResume() { + super.onResume(); + rebuildPaymentAppsList(); + } + + private void rebuildPaymentAppsList() { + getPreferenceScreen().removeAll(); + getPreferenceScreen().setOrderingAsAdded(true); + + Map<String, Pair<String, Drawable>> appsInfo = + AndroidPaymentAppFactory.getAndroidPaymentAppsInfo(); + if (appsInfo.isEmpty()) return; + + AndroidPaymentAppPreference pref = null; + for (Map.Entry<String, Pair<String, Drawable>> app : appsInfo.entrySet()) { + pref = new AndroidPaymentAppPreference(getActivity()); + pref.setTitle(app.getValue().first); + pref.setIcon(app.getValue().second); + pref.setDefaultValue(true); + pref.setKey( + PaymentPreferencesUtil.getAndroidPaymentAppEnabledPreferenceKey(app.getKey())); + getPreferenceScreen().addPreference(pref); + } + // Add a divider line at the bottom of the last preference to separate it from below + // TextMessagePreference. + if (pref != null) pref.setDrawDivider(true); + + TextMessagePreference textPreference = new TextMessagePreference(getActivity(), null); + textPreference.setTitle(getActivity().getString(R.string.payment_apps_control_message)); + getPreferenceScreen().addPreference(textPreference); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillAndPaymentsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillAndPaymentsPreferences.java index 2841b29..6b98b0eb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillAndPaymentsPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillAndPaymentsPreferences.java
@@ -10,7 +10,9 @@ import android.preference.PreferenceFragment; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.autofill.PersonalDataManager; +import org.chromium.chrome.browser.payments.AndroidPaymentAppFactory; import org.chromium.chrome.browser.preferences.ChromeSwitchPreference; /** @@ -24,6 +26,7 @@ // chrome/browser/ui/webui/options/autofill_options_handler.cc public static final String SETTINGS_ORIGIN = "Chrome settings"; private static final String PREF_AUTOFILL_SWITCH = "autofill_switch"; + private static final String PREF_ANDROID_PAYMENT_APPS = "android_payment_apps"; @Override public void onCreate(Bundle savedInstanceState) { @@ -40,6 +43,15 @@ return true; } }); + + if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_PAYMENT_APPS)) { + Preference pref = new Preference(getActivity()); + pref.setTitle(getActivity().getString(R.string.payment_apps_title)); + pref.setFragment(AndroidPaymentAppsFragment.class.getCanonicalName()); + pref.setShouldDisableView(true); + pref.setKey(PREF_ANDROID_PAYMENT_APPS); + getPreferenceScreen().addPreference(pref); + } } @Override @@ -47,5 +59,19 @@ super.onResume(); ((ChromeSwitchPreference) findPreference(PREF_AUTOFILL_SWITCH)) .setChecked(PersonalDataManager.isAutofillEnabled()); + refreshPaymentAppsPref(); + } + + private void refreshPaymentAppsPref() { + Preference pref = findPreference(PREF_ANDROID_PAYMENT_APPS); + if (pref != null) { + if (AndroidPaymentAppFactory.hasAndroidPaymentApps()) { + pref.setSummary(null); + pref.setEnabled(true); + } else { + pref.setSummary(getActivity().getString(R.string.payment_no_apps_summary)); + pref.setEnabled(false); + } + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsActivity.java index a4c4f0de..70cd127e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsActivity.java
@@ -6,22 +6,11 @@ import android.content.Intent; import android.os.Bundle; -import android.view.LayoutInflater; import android.view.Menu; -import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.SynchronousInitializationActivity; -import org.chromium.chrome.browser.ntp.ContextMenuManager; -import org.chromium.chrome.browser.ntp.UiConfig; -import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; -import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; -import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; -import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; import java.lang.ref.WeakReference; @@ -31,9 +20,7 @@ public class ContentSuggestionsActivity extends SynchronousInitializationActivity { private static WeakReference<ChromeActivity> sCallerActivity; - private ContextMenuManager mContextMenuManager; - private SuggestionsUiDelegateImpl mSuggestionsManager; - private SnippetsBridge mSnippetsBridge; + private SuggestionsBottomSheetContent mBottomSheetContent; public static void launch(ChromeActivity activity) { sCallerActivity = new WeakReference<>(activity); @@ -55,41 +42,22 @@ ChromeActivity activity = sCallerActivity.get(); if (activity == null) throw new IllegalStateException(); - NewTabPageRecyclerView recyclerView = - (NewTabPageRecyclerView) LayoutInflater.from(this).inflate( - R.layout.new_tab_page_recycler_view, null, false); - - Profile profile = Profile.getLastUsedProfile(); - UiConfig uiConfig = new UiConfig(recyclerView); - - Tab currentTab = activity.getActivityTab(); - TabModelSelector tabModelSelector = activity.getTabModelSelector(); - - mSnippetsBridge = new SnippetsBridge(profile); - SuggestionsNavigationDelegate navigationDelegate = - new SuggestionsNavigationDelegateImpl(this, profile, currentTab, tabModelSelector); - - mSuggestionsManager = new SuggestionsUiDelegateImpl( - mSnippetsBridge, mSnippetsBridge, navigationDelegate, profile, currentTab); - mContextMenuManager = new ContextMenuManager(this, navigationDelegate, recyclerView); - - NewTabPageAdapter adapter = new NewTabPageAdapter(mSuggestionsManager, null, uiConfig, - OfflinePageBridge.getForProfile(profile), mContextMenuManager); - recyclerView.setAdapter(adapter); - recyclerView.setUpSwipeToDismiss(); - - setContentView(recyclerView); + // TODO(dgn): Because the passed activity here is the Chrome one and not the one showing + // the surface, some things, like closing the context menu will not work as they would + // affect the wrong one. + mBottomSheetContent = new SuggestionsBottomSheetContent( + activity, activity.getActivityTab(), activity.getTabModelSelector()); + setContentView(mBottomSheetContent.getScrollingContentView()); } @Override public void onContextMenuClosed(Menu menu) { - mContextMenuManager.onContextMenuClosed(); + mBottomSheetContent.getContextMenuManager().onContextMenuClosed(); } @Override protected void onDestroy() { - mSnippetsBridge.destroy(); - mSuggestionsManager.onDestroy(); + mBottomSheetContent.destroy(); super.onDestroy(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java new file mode 100644 index 0000000..07dfcb1 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java
@@ -0,0 +1,68 @@ +// 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. + +package org.chromium.chrome.browser.suggestions; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ntp.ContextMenuManager; +import org.chromium.chrome.browser.ntp.UiConfig; +import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; +import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; +import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; +import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; + +/** + * Provides content to be displayed inside of the Home tab of bottom sheet. + * + * TODO(dgn): If the bottom sheet view is not recreated across tab changes, it will have to be + * notified of it, at least when it is pulled up on the new tab. + */ +public class SuggestionsBottomSheetContent { + private final NewTabPageRecyclerView mRecyclerView; + private final ContextMenuManager mContextMenuManager; + private final SuggestionsUiDelegateImpl mSuggestionsManager; + private final SnippetsBridge mSnippetsBridge; + + public SuggestionsBottomSheetContent( + ChromeActivity activity, Tab tab, TabModelSelector tabModelSelector) { + mRecyclerView = (NewTabPageRecyclerView) LayoutInflater.from(activity).inflate( + R.layout.new_tab_page_recycler_view, null, false); + + Profile profile = Profile.getLastUsedProfile(); + UiConfig uiConfig = new UiConfig(mRecyclerView); + + mSnippetsBridge = new SnippetsBridge(profile); + SuggestionsNavigationDelegate navigationDelegate = + new SuggestionsNavigationDelegateImpl(activity, profile, tab, tabModelSelector); + + mSuggestionsManager = new SuggestionsUiDelegateImpl( + mSnippetsBridge, mSnippetsBridge, navigationDelegate, profile, tab); + mContextMenuManager = new ContextMenuManager(activity, navigationDelegate, mRecyclerView); + + NewTabPageAdapter adapter = new NewTabPageAdapter(mSuggestionsManager, null, uiConfig, + OfflinePageBridge.getForProfile(profile), mContextMenuManager); + mRecyclerView.setAdapter(adapter); + mRecyclerView.setUpSwipeToDismiss(); + } + + public RecyclerView getScrollingContentView() { + return mRecyclerView; + } + + public ContextMenuManager getContextMenuManager() { + return mContextMenuManager; + } + + public void destroy() { + mSnippetsBridge.destroy(); + mSuggestionsManager.onDestroy(); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java index 8f2cb6a8..b73fc416 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java
@@ -10,7 +10,6 @@ import android.os.StrictMode; import android.provider.Settings; import android.support.v7.app.AlertDialog; -import android.text.TextUtils; import org.chromium.base.ContextUtils; import org.chromium.base.Log; @@ -19,16 +18,12 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; -import org.chromium.components.variations.VariationsAssociatedData; import org.chromium.webapk.lib.client.WebApkValidator; /** * Contains functionality needed for Chrome to host WebAPKs. */ public class ChromeWebApkHost { - /** Flag to enable installing WebAPKs using Google Play. */ - private static final String PLAY_INSTALL = "play_install"; - private static final String TAG = "ChromeWebApkHost"; private static Boolean sEnabledForTesting; @@ -60,9 +55,7 @@ /** Return whether installing WebAPKs using Google Play is enabled. */ public static boolean canUseGooglePlayToInstallWebApk() { - if (!isEnabled()) return false; - return TextUtils.equals(VariationsAssociatedData.getVariationParamValue( - ChromeFeatureList.IMPROVED_A2HS, PLAY_INSTALL), "true"); + return isEnabled() && nativeCanUseGooglePlayToInstallWebApk(); } @CalledByNative @@ -95,8 +88,11 @@ // variations on other channels. if (!ChromeVersionInfo.isCanaryBuild() && !ChromeVersionInfo.isDevBuild()) return; - if (ChromeFeatureList.isEnabled(ChromeFeatureList.IMPROVED_A2HS) - && !canUseGooglePlayToInstallWebApk() + // Update cached state. {@link #isEnabled()} and {@link #canUseGooglePlayToInstallWebApk()} + // need the state to be up to date. + cacheEnabledStateForNextLaunch(); + + if (isEnabled() && !canUseGooglePlayToInstallWebApk() && !installingFromUnknownSourcesAllowed()) { showUnknownSourcesNeededDialog(context); } @@ -157,4 +153,6 @@ AlertDialog dialog = builder.create(); dialog.show(); } + + private static native boolean nativeCanUseGooglePlayToInstallWebApk(); }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 67668fb..2394fd3 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -267,7 +267,7 @@ Recently visited </message> - <!-- Autofill preferences --> + <!-- Autofill and Payments preferences --> <message name="IDS_PREFS_AUTOFILL_AND_PAYMENTS" desc="Title of Autofill and payments settings prefrences. [CHAR-LIMIT=32]"> Autofill and payments </message> @@ -276,7 +276,16 @@ </message> <message name="IDS_AUTOFILL_PROFILES_TITLE" desc="Title of the preference to list profiles (which contain the user's name, address, etc) that can be automatically filled into web page forms. [CHAR-LIMIT=32]"> Addresses - </message> + </message> + <message name="IDS_PAYMENT_APPS_TITLE" desc="Title of the preference to list the payment apps on device."> + Payment apps + </message> + <message name="IDS_PAYMENT_NO_APPS_SUMMARY" desc="Summary of the preference to list the payment apps on device when no payments apps installed."> + No supported apps installed + </message> + <message name="IDS_PAYMENT_APPS_CONTROL_MESSAGE" desc="Message to explain what the user controls by toggling the switch of the payment app preference."> + On some websites, you can pay with supported payment apps. Choose which apps to use in Chrome. + </message> <message name="IDS_AUTOFILL_CREDIT_CARDS_TITLE" desc="Title of the preference to list the user's credit cards that can be automatically filled into web page forms. [CHAR-LIMIT=32]"> Credit cards </message>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 3a985fbb..b7ccd7f 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -546,6 +546,7 @@ "java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxy.java", "java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxyImpl.java", "java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java", + "java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java", "java/src/org/chromium/chrome/browser/notifications/NotificationService.java", "java/src/org/chromium/chrome/browser/notifications/NotificationSystemStatusUtil.java", "java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java", @@ -697,6 +698,7 @@ "java/src/org/chromium/chrome/browser/payments/PaymentApp.java", "java/src/org/chromium/chrome/browser/payments/PaymentAppFactory.java", "java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java", + "java/src/org/chromium/chrome/browser/payments/PaymentPreferencesUtil.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLogger.java", @@ -797,6 +799,8 @@ "java/src/org/chromium/chrome/browser/preferences/TextMessagePreference.java", "java/src/org/chromium/chrome/browser/preferences/TextMessageWithLinkAndIconPreference.java", "java/src/org/chromium/chrome/browser/preferences/TextScalePreference.java", + "java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppPreference.java", + "java/src/org/chromium/chrome/browser/preferences/autofill/AndroidPaymentAppsFragment.java", "java/src/org/chromium/chrome/browser/preferences/autofill/AutofillAndPaymentsPreferences.java", "java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardsFragment.java", "java/src/org/chromium/chrome/browser/preferences/autofill/AutofillCreditCardEditor.java", @@ -920,6 +924,7 @@ "java/src/org/chromium/chrome/browser/ssl/SecurityStateModel.java", "java/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsActivity.java", "java/src/org/chromium/chrome/browser/suggestions/PartialUpdateId.java", + "java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegate.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegate.java", @@ -1354,6 +1359,7 @@ "javatests/src/org/chromium/chrome/browser/payments/CurrencyFormatterTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java", @@ -1379,6 +1385,7 @@ "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerUnitTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsUnitTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java new file mode 100644 index 0000000..3043369 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
@@ -0,0 +1,257 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.payments; + +import android.content.DialogInterface; +import android.support.test.filters.MediumTest; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the correct log of the CanMakePayment metrics. + */ +public class PaymentRequestCanMakePaymentMetricsTest extends PaymentRequestTestBase { + public PaymentRequestCanMakePaymentMetricsTest() { + super("payment_request_can_make_payment_metrics_test.html"); + } + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper helper = new AutofillTestHelper(); + helper.setProfile(new AutofillProfile("", "https://example.com", true, "Jon Doe", "Google", + "340 Main St", "CA", "Los Angeles", "", "90291", "", "US", "310-310-6000", + "jon.doe@gmail.com", "en-US")); + } + + /** + * Tests that the CanMakePayment metrics are correctly logged for the case of a merchant + * calling it, receiving no as a response, still showing the Payment Request and the user aborts + * the flow. + */ + @MediumTest + @Feature({"Payments"}) + public void testCannotMakePayment_Abort() + throws InterruptedException, ExecutionException, TimeoutException { + // Initiate a payment request. + triggerUIAndWait("queryShow", mReadyForInput); + + // Press the back button. + int callCount = mDismissed.getCallCount(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mUI.getDialogForTest().onBackPressed(); + } + }); + mDismissed.waitForCallback(callCount); + expectResultContains(new String[] {"Request cancelled"}); + + // CanMakePayment was queried. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being false and shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW)); + + // There should be a record for an abort when CanMakePayment is false but the PR is shown to + // the user. + assertEquals( + 1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + } + + /** + * Tests that the CanMakePayment metrics are correctly logged for the case of a merchant + * calling it, receiving no as a response, still showing the Payment Request and the user + * completes the flow. + */ + @MediumTest + @Feature({"Payments"}) + public void testCannotMakePayment_Complete() + throws InterruptedException, ExecutionException, TimeoutException { + triggerUIAndWait("queryShow", mReadyForInput); + + // Add a new credit card. + clickInPaymentMethodAndWait(R.id.payments_section, mReadyToEdit); + setSpinnerSelectionsInCardEditorAndWait( + new int[] {11, 1, 0}, mBillingAddressChangeProcessed); + setTextInCardEditorAndWait(new String[] {"4111111111111111", "Jon Doe"}, mEditorTextUpdate); + clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay); + + // Complete the transaction. + clickAndWait(R.id.button_primary, mReadyForUnmaskInput); + setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask); + clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed); + + // CanMakePayment was queried. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being false and shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW)); + + // There should be a record for a completion when CanMakePayment is false but the PR is + // shown to the user. + assertEquals( + 1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests that the CanMakePayment metrics are correctly logged for the case of a merchant + * calling it, receiving yeas as a response, showing the Payment Request and the user aborts the + * flow. + */ + @MediumTest + @Feature({"Payments"}) + public void testCanMakePayment_Abort() + throws InterruptedException, ExecutionException, TimeoutException { + // Install the app so CanMakePayment returns true. + installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); + + // Initiate a payment request. + triggerUIAndWait("queryShow", mReadyForInput); + + // Press the back button. + int callCount = mDismissed.getCallCount(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mUI.getDialogForTest().onBackPressed(); + } + }); + mDismissed.waitForCallback(callCount); + expectResultContains(new String[] {"Request cancelled"}); + + // CanMakePayment was queried. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being false and shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW + | PaymentRequestJourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT)); + + // There should be a record for an abort when CanMakePayment is false but the PR is shown to + // the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + } + + /** + * Tests that the CanMakePayment metrics are correctly logged for the case of a merchant + * calling it, receiving yeas as a response, showing the Payment Request and the user completes + * the flow. + */ + @MediumTest + @Feature({"Payments"}) + public void testCanMakePayment_Complete() + throws InterruptedException, ExecutionException, TimeoutException { + // Install the app so CanMakePayment returns true. + installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); + + // Initiate an complete a payment request. + triggerUIAndWait("queryShow", mReadyForInput); + clickAndWait(R.id.button_primary, mDismissed); + + // CanMakePayment was queried. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being false and shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW + | PaymentRequestJourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT)); + + // There should be a record for an abort when CanMakePayment is false but the PR is shown to + // the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests that the CanMakePayment metrics are correctly logged for the case of a merchant + * not calling it but still showing the Payment Request and the user aborts the flow. + */ + @MediumTest + @Feature({"Payments"}) + public void testNoQuery_Abort() + throws InterruptedException, ExecutionException, TimeoutException { + // Initiate a payment request. + triggerUIAndWait("noQueryShow", mReadyForInput); + + // Press the back button. + int callCount = mDismissed.getCallCount(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mUI.getDialogForTest().onBackPressed(); + } + }); + mDismissed.waitForCallback(callCount); + expectResultContains(new String[] {"Request cancelled"}); + + // CanMakePayment was not queried. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_NOT_USED)); + + // There should be a record for an abort when CanMakePayment is not called but the PR is + // shown to the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + } + + /** + * Tests that the CanMakePayment metrics are correctly logged for the case of a merchant + * not calling it but still showing the Payment Request and the user completes the flow. + */ + @MediumTest + @Feature({"Payments"}) + public void testNoQuery_Completes() + throws InterruptedException, ExecutionException, TimeoutException { + // Install the app so the user can complete the Payment Request. + installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE); + + // Initiate a payment request. + triggerUIAndWait("noQueryShow", mReadyForInput); + clickAndWait(R.id.button_primary, mDismissed); + + // CanMakePayment was not queried. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_NOT_USED)); + + // There should be a record for a completion when CanMakePayment is not called but the PR is + // shown to the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerUnitTest.java new file mode 100644 index 0000000..9cf6fd3 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerUnitTest.java
@@ -0,0 +1,335 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.payments; + +import android.support.test.filters.SmallTest; + +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.test.util.ApplicationData; +import org.chromium.content.browser.test.NativeLibraryTestBase; + +/** + * Tests for the PaymentRequestJourneyLogger class. + */ +public class PaymentRequestJourneyLoggerUnitTest extends NativeLibraryTestBase { + @Override + public void setUp() throws Exception { + super.setUp(); + ApplicationData.clearAppData(getInstrumentation().getTargetContext()); + loadNativeLibraryAndInitBrowserProcess(); + } + + /** + * Tests the canMakePayment stats for the case where the merchant does not use it and does not + * show the PaymentRequest to the user. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentNotCalled_NoShow() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + logger.recordJourneyStatsHistograms(""); + + // CanMakePayment was not used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_NOT_USED)); + + // There should be no completion stats since PR was not shown to the user + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant does not use it and the + * transaction is aborted. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentNotCalled_ShowAndAbort() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The merchant does not query CanMakePayment, show the PaymentRequest and the user + // aborts it. + logger.setShowCalled(); + logger.recordJourneyStatsHistograms("Aborted"); + + // CanMakePayment was not used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_NOT_USED)); + + // There should be a record for an abort when CanMakePayment is not used but the PR is shown + // to the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant does not use it and the + * transaction is completed. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentNotCalled_ShowAndComplete() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The merchant does not query CanMakePayment, show the PaymentRequest and the user + // completes it. + logger.setShowCalled(); + logger.recordJourneyStatsHistograms("Completed"); + + // CanMakePayment was not used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_NOT_USED)); + + // There should be a record for a completion when CanMakePayment is not used but the PR is + // shown to the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant uses it, returns false and + * show is not called. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentCalled_FalseAndNoShow() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The user cannot make payment and the PaymentRequest is not shown. + logger.setCanMakePaymentValue(false); + logger.recordJourneyStatsHistograms(""); + + // CanMakePayment was used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being false and not shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger + .CMP_SHOW_COULD_NOT_MAKE_PAYMENT_AND_DID_NOT_SHOW)); + + // There should be no completion stats since PR was not shown to the user. + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant uses it, returns true and + * show is not called. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentCalled_TrueAndNoShow() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The user can make a payment but the Payment Request is not shown. + logger.setCanMakePaymentValue(true); + logger.recordJourneyStatsHistograms(""); + + // CanMakePayment was used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being true and not shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT)); + + // There should be no completion stats since PR was not shown to the user. + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant uses it, returns false, show + * is called but the transaction is aborted. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentCalled_FalseShowAndAbort() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The user cannot make a payment. the payment request is shown but aborted. + logger.setShowCalled(); + logger.setCanMakePaymentValue(false); + logger.recordJourneyStatsHistograms("Aborted"); + + // CanMakePayment was used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being true and not shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW)); + + // There should be a record for an abort when CanMakePayment is false but the PR is shown to + // the user. + assertEquals( + 1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant uses it, returns false, + * show is called and the transaction is completed. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentCalled_FalseShowAndComplete() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The user cannot make a payment. the payment request is shown and completed. + logger.setShowCalled(); + logger.setCanMakePaymentValue(false); + logger.recordJourneyStatsHistograms("Completed"); + + // CanMakePayment was used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being true and not shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW)); + + // There should be a record for a completion when CanMakePayment is false and the PR is + // shown to the user. + assertEquals( + 1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant uses it, returns true, show + * is called but the transaction is aborted. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentCalled_TrueShowAndAbort() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The user cannot make a payment. the payment request is shown and completed. + logger.setShowCalled(); + logger.setCanMakePaymentValue(true); + logger.recordJourneyStatsHistograms("Aborted"); + + // CanMakePayment was used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being true and not shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW + | PaymentRequestJourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT)); + + // There should be a record for an abort when CanMakePayment is true and the PR is shown to + // the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_ABORTED)); + } + + /** + * Tests the canMakePayment stats for the case where the merchant uses it, returns true, show + * is called and the transaction is completed. + */ + @SmallTest + @Feature({"Payments"}) + public void testRecordJourneyStatsHistograms_CanMakePaymentCalled_TrueShowAndComplete() { + PaymentRequestJourneyLogger logger = new PaymentRequestJourneyLogger(); + assertNoLogForCanMakePayment(); + + // The user cannot make a payment. the payment request is shown and completed. + logger.setShowCalled(); + logger.setCanMakePaymentValue(true); + logger.recordJourneyStatsHistograms("Completed"); + + // CanMakePayment was used. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", + PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USED)); + + // The CanMakePayment effect on show should be recorded as being true and not shown. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", + PaymentRequestJourneyLogger.CMP_SHOW_DID_SHOW + | PaymentRequestJourneyLogger.CMP_SHOW_COULD_MAKE_PAYMENT)); + + // There should be a record for a completion when CanMakePayment is true and the PR is shown + // to the user. + assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion", + PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_COMPLETED)); + } + + /** + * Asserts that no histogram is logged. + */ + private void assertNoLogForCanMakePayment() { + // Use stats. + for (int i = 0; i < PaymentRequestJourneyLogger.CAN_MAKE_PAYMENT_USE_MAX; ++i) { + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Usage", i)); + } + + // Effect on show stats. + for (int i = 0; i < PaymentRequestJourneyLogger.CMP_SHOW_MAX; ++i) { + assertEquals(0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.EffetOnShow", i)); + } + + // Effect on completion stats. + for (int i = 0; i < PaymentRequestJourneyLogger.CMP_EFFECT_ON_COMPLETION_MAX; ++i) { + assertEquals(0, + RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion", i)); + assertEquals( + 0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion", + i)); + assertEquals( + 0, RecordHistogram.getHistogramValueCountForTesting( + "PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion", + i)); + } + } +} \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java index dc8a94e3..3bb2242 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
@@ -891,7 +891,7 @@ @Override public void getInstruments(Map<String, PaymentMethodData> methodData, String origin, - InstrumentsCallback instrumentsCallback) { + byte[][] certificateChain, InstrumentsCallback instrumentsCallback) { mCallback = instrumentsCallback; respond(); } @@ -951,7 +951,7 @@ } @Override - public void invokePaymentApp(String merchantName, String origin, + public void invokePaymentApp(String merchantName, String origin, byte[][] certificateChain, Map<String, PaymentMethodData> methodData, PaymentItem total, List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers, InstrumentDetailsCallback detailsCallback) {
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 06161d3..7e458366a 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -101,6 +101,7 @@ #include "chrome/browser/android/voice_search_tab_helper.h" #include "chrome/browser/android/warmup_manager.h" #include "chrome/browser/android/web_contents_factory.h" +#include "chrome/browser/android/webapk/chrome_webapk_host.h" #include "chrome/browser/android/webapk/webapk_installer.h" #include "chrome/browser/android/webapk/webapk_update_data_fetcher.h" #include "chrome/browser/android/webapk/webapk_update_manager.h" @@ -257,6 +258,7 @@ {"ChromeMediaRouterDialogController", media_router::MediaRouterDialogControllerAndroid::Register}, #endif + {"ChromeWebApkHost", ChromeWebApkHost::Register}, {"CompositorView", RegisterCompositorView}, {"ConnectionInfoPopupAndroid", ConnectionInfoPopupAndroid::RegisterConnectionInfoPopupAndroid},
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc index dac7b572b..d274f2b6 100644 --- a/chrome/browser/android/download/download_manager_service.cc +++ b/chrome/browser/android/download/download_manager_service.cc
@@ -29,6 +29,9 @@ namespace { +// The remaining time for a download item if it cannot be calculated. +long kUnknownRemainingTime = -1; + bool ShouldShowDownloadItem(content::DownloadItem* item) { return !item->IsTemporary(); } @@ -95,27 +98,22 @@ bool has_user_gesture = item->HasUserGesture() || user_initiated; base::TimeDelta time_delta; - item->TimeRemaining(&time_delta); + bool time_remaining_known = item->TimeRemaining(&time_delta); std::string original_url = item->GetOriginalUrl().SchemeIs(url::kDataScheme) ? std::string() : item->GetOriginalUrl().spec(); return Java_DownloadInfo_createDownloadInfo( - env, - ConvertUTF8ToJavaString(env, item->GetGuid()), - ConvertUTF8ToJavaString(env, - item->GetFileNameToReportUser().value()), + env, ConvertUTF8ToJavaString(env, item->GetGuid()), + ConvertUTF8ToJavaString(env, item->GetFileNameToReportUser().value()), ConvertUTF8ToJavaString(env, item->GetTargetFilePath().value()), ConvertUTF8ToJavaString(env, item->GetTabUrl().spec()), ConvertUTF8ToJavaString(env, item->GetMimeType()), - item->GetReceivedBytes(), - item->GetBrowserContext()->IsOffTheRecord(), - item->GetState(), - item->PercentComplete(), - item->IsPaused(), - has_user_gesture, - item->CanResume(), + item->GetReceivedBytes(), item->GetBrowserContext()->IsOffTheRecord(), + item->GetState(), item->PercentComplete(), item->IsPaused(), + has_user_gesture, item->CanResume(), ConvertUTF8ToJavaString(env, original_url), ConvertUTF8ToJavaString(env, item->GetReferrerUrl().spec()), - time_delta.InMilliseconds()); + time_remaining_known ? time_delta.InMilliseconds() + : kUnknownRemainingTime); } static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& jobj) {
diff --git a/chrome/browser/android/webapk/chrome_webapk_host.cc b/chrome/browser/android/webapk/chrome_webapk_host.cc index 4014e2f6..1ebfe48 100644 --- a/chrome/browser/android/webapk/chrome_webapk_host.cc +++ b/chrome/browser/android/webapk/chrome_webapk_host.cc
@@ -4,10 +4,32 @@ #include "chrome/browser/android/webapk/chrome_webapk_host.h" +#include "chrome/browser/android/chrome_feature_list.h" +#include "components/variations/variations_associated_data.h" #include "jni/ChromeWebApkHost_jni.h" +namespace { + +// Variations flag to enable installing WebAPKs using Google Play. +const char* kPlayInstall = "play_install"; + +} // anonymous namespace + +// static +bool ChromeWebApkHost::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + // static bool ChromeWebApkHost::AreWebApkEnabled() { JNIEnv* env = base::android::AttachCurrentThread(); return Java_ChromeWebApkHost_areWebApkEnabled(env); } + +// static +jboolean CanUseGooglePlayToInstallWebApk( + JNIEnv* env, + const base::android::JavaParamRef<jclass>& clazz) { + return variations::GetVariationParamValueByFeature( + chrome::android::kImprovedA2HS, kPlayInstall) == "true"; +}
diff --git a/chrome/browser/android/webapk/chrome_webapk_host.h b/chrome/browser/android/webapk/chrome_webapk_host.h index abc2bc7..dc84ea17 100644 --- a/chrome/browser/android/webapk/chrome_webapk_host.h +++ b/chrome/browser/android/webapk/chrome_webapk_host.h
@@ -5,12 +5,17 @@ #ifndef CHROME_BROWSER_ANDROID_WEBAPK_CHROME_WEBAPK_HOST_H_ #define CHROME_BROWSER_ANDROID_WEBAPK_CHROME_WEBAPK_HOST_H_ +#include <jni.h> + #include "base/macros.h" // ChromeWebApkHost is the C++ counterpart of org.chromium.chrome.browser's // ChromeWebApkHost in Java. class ChromeWebApkHost { public: + // Registers JNI hooks. + static bool Register(JNIEnv* env); + // Returns whether the "enalbe-webapk" is turned on. static bool AreWebApkEnabled();
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 8fe892cf..cbefb07 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -92,18 +92,6 @@ "<label for=\"phone\">Phone number:</label>" " <input type=\"text\" id=\"phone\"><br>" "</form>"; -static const char kTestPasswordFormString[] = - "<form>" - "<label for=\"user\">User:</label>" - " <input id=\"user\" type=\"text\" name=\"name\"" - "onfocus=\"domAutomationController.send(true)\">" - "<br>" - "<label for=\"password\">Password:</label>" - " <input id=\"password\" type=\"password\" name=\"password\"" - "onfocus=\"domAutomationController.send(true)\">" - "<br>" - "<input type=\"submit\" value=\"Submit\">" - "</form>"; // TODO(crbug.com/609861): Remove the autocomplete attribute from the textarea // field when the bug is fixed. @@ -1727,8 +1715,19 @@ IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, PastedPasswordIsSaved) { - ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), - GURL(std::string(kDataURIPrefix) + kTestPasswordFormString))); + // Serve test page from a HTTPS server so that Form Not Secure warnings do not + // interfere with the test. + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + net::SSLServerConfig ssl_config; + ssl_config.client_cert_type = + net::SSLServerConfig::ClientCertType::NO_CLIENT_CERT; + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config); + https_server.ServeFilesFromSourceDirectory("chrome/test/data"); + ASSERT_TRUE(https_server.Start()); + + GURL url = https_server.GetURL("/autofill/autofill_password_form.html"); + ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url)); + ASSERT_TRUE(content::ExecuteScript( GetRenderViewHost(), "document.getElementById('user').value = 'user';"));
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 04b027a..00f3d7c 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -156,7 +156,7 @@ #include "device/geolocation/geolocation_delegate.h" #include "device/geolocation/geolocation_provider.h" #include "extensions/features/features.h" -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" #include "media/media_features.h" #include "net/base/net_module.h" #include "net/cookies/cookie_monster.h"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 718b141..fb21b604 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -933,11 +933,9 @@ #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(USE_OZONE) main_parts->AddParts(new ChromeBrowserMainExtraPartsViewsLinux()); #else - ChromeBrowserMainExtraPartsViews* extra_parts_views = - new ChromeBrowserMainExtraPartsViews; - main_parts->AddParts(extra_parts_views); + main_parts->AddParts(new ChromeBrowserMainExtraPartsViews()); #if defined(USE_ASH) - main_parts->AddParts(new ChromeBrowserMainExtraPartsAsh(extra_parts_views)); + main_parts->AddParts(new ChromeBrowserMainExtraPartsAsh()); #endif #endif #endif
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc index 15fac5c..826b627 100644 --- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc +++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.cc
@@ -11,9 +11,36 @@ #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/notification_blocker.h" namespace chromeos { +// Blocks all notifications for ARC++ Kiosk +class ArcKioskNotificationBlocker : public message_center::NotificationBlocker { + public: + ArcKioskNotificationBlocker() + : message_center::NotificationBlocker( + message_center::MessageCenter::Get()) { + NotifyBlockingStateChanged(); + } + + ~ArcKioskNotificationBlocker() override {} + + private: + bool ShouldShowNotification( + const message_center::Notification& notification) const override { + return false; + } + + bool ShouldShowNotificationAsPopup( + const message_center::Notification& notification) const override { + return false; + } + + DISALLOW_COPY_AND_ASSIGN(ArcKioskNotificationBlocker); +}; + // static ArcKioskAppService* ArcKioskAppService::Create(Profile* profile) { return new ArcKioskAppService(profile); @@ -91,6 +118,7 @@ prefs::kArcPolicyCompliant, base::Bind(&ArcKioskAppService::PreconditionsChanged, base::Unretained(this))); + notification_blocker_.reset(new ArcKioskNotificationBlocker()); PreconditionsChanged(); }
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h index 384505b9..a531ebb 100644 --- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h +++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
@@ -21,6 +21,8 @@ namespace chromeos { +class ArcKioskNotificationBlocker; + // Keeps track of ARC session state and auto-launches kiosk app when it's ready. // App is started when the following conditions are satisfied: // 1. App id is registered in ArcAppListPrefs and set to "ready" state. @@ -74,6 +76,7 @@ std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; // Keeps track whether the app is already launched std::unique_ptr<ArcKioskAppLauncher> app_launcher_; + std::unique_ptr<ArcKioskNotificationBlocker> notification_blocker_; DISALLOW_COPY_AND_ASSIGN(ArcKioskAppService); };
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index df305cb..fe16fe3 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -296,10 +296,6 @@ } bool CanPerformEarlyRestart() { - // Desktop build is used for development only. Early restart is not supported. - if (!base::SysInfo::IsRunningOnChromeOS()) - return false; - if (!ChromeUserManager::Get() ->GetCurrentUserFlow() ->SupportsEarlyRestartToApplyFlags()) { @@ -720,6 +716,11 @@ bool UserSessionManager::RestartToApplyPerSessionFlagsIfNeed( Profile* profile, bool early_restart) { + SessionManagerClient* session_manager_client = + DBusThreadManager::Get()->GetSessionManagerClient(); + if (!session_manager_client->SupportsRestartToApplyUserFlags()) + return false; + if (ProfileHelper::IsSigninProfile(profile)) return false; @@ -756,7 +757,7 @@ // argv[0] is the program name |base::CommandLine::NO_PROGRAM|. flags.assign(user_flags.argv().begin() + 1, user_flags.argv().end()); LOG(WARNING) << "Restarting to apply per-session flags..."; - DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser( + session_manager_client->SetFlagsForUser( cryptohome::Identification( user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()), flags);
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc index 98ba44b8..de550210 100644 --- a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc +++ b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
@@ -12,6 +12,7 @@ #include "base/memory/memory_coordinator_client_registry.h" #include "base/memory/memory_pressure_monitor.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/strings/utf_string_conversions.h" #include "base/sys_info.h"
diff --git a/chrome/browser/chromeos/settings/device_settings_test_helper.cc b/chrome/browser/chromeos/settings/device_settings_test_helper.cc index ebe9407f..792004f 100644 --- a/chrome/browser/chromeos/settings/device_settings_test_helper.cc +++ b/chrome/browser/chromeos/settings/device_settings_test_helper.cc
@@ -175,6 +175,10 @@ device_local_account_policy_[account_id].store_callbacks_.push_back(callback); } +bool DeviceSettingsTestHelper::SupportsRestartToApplyUserFlags() const { + return false; +} + void DeviceSettingsTestHelper::SetFlagsForUser( const cryptohome::Identification& cryptohome_id, const std::vector<std::string>& flags) {}
diff --git a/chrome/browser/chromeos/settings/device_settings_test_helper.h b/chrome/browser/chromeos/settings/device_settings_test_helper.h index e8a8997..384f598 100644 --- a/chrome/browser/chromeos/settings/device_settings_test_helper.h +++ b/chrome/browser/chromeos/settings/device_settings_test_helper.h
@@ -117,6 +117,7 @@ const std::string& account_id, const std::string& policy_blob, const StorePolicyCallback& callback) override; + bool SupportsRestartToApplyUserFlags() const override; void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, const std::vector<std::string>& flags) override; void GetServerBackedStateKeys(const StateKeysCallback& callback) override;
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.cc b/chrome/browser/component_updater/chrome_component_updater_configurator.cc index ea83a735..2fccab7 100644 --- a/chrome/browser/component_updater/chrome_component_updater_configurator.cc +++ b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
@@ -10,9 +10,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/threading/sequenced_worker_pool.h" #include "base/version.h" -#if defined(OS_WIN) -#include "base/win/win_util.h" -#endif +#include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/component_updater/component_patcher_operation_out_of_process.h" #include "chrome/browser/component_updater/component_updater_utils.h" @@ -20,15 +18,17 @@ #include "chrome/browser/update_client/chrome_update_query_params_delegate.h" #include "chrome/common/channel_info.h" #include "chrome/common/pref_names.h" -#if defined(OS_WIN) -#include "chrome/installer/util/google_update_settings.h" -#endif // OS_WIN #include "components/component_updater/configurator_impl.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/update_client/update_query_params.h" #include "content/public/browser/browser_thread.h" +#if defined(OS_WIN) +#include "base/win/win_util.h" +#include "chrome/installer/util/google_update_settings.h" +#endif + namespace component_updater { namespace {
diff --git a/chrome/browser/component_updater/component_updater_utils.cc b/chrome/browser/component_updater/component_updater_utils.cc index efd113a..49acf65 100644 --- a/chrome/browser/component_updater/component_updater_utils.cc +++ b/chrome/browser/component_updater/component_updater_utils.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/component_updater/component_updater_utils.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "build/build_config.h" #if defined(OS_WIN) #include "chrome/installer/util/install_util.h" #endif // OS_WIN
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc index 8d28b344..c558cfd 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc
@@ -83,6 +83,10 @@ constexpr base::Feature kExperimentalEngineFeature{ "ExperimentalSwReporterEngine", base::FEATURE_DISABLED_BY_DEFAULT}; +constexpr base::Feature kExperimentalEngineAllArchsFeature{ + "ExperimentalSwReporterEngineOnAllArchitectures", + base::FEATURE_DISABLED_BY_DEFAULT +}; void SRTHasCompleted(SRTCompleted value) { UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Cleaner.HasCompleted", value, @@ -475,11 +479,15 @@ } } - // The experiment is only enabled on x86. There's no way to check this in the + // If the experiment is not explicitly enabled on all platforms, it + // should be only enabled on x86. There's no way to check this in the // variations config so we'll hard-code it. - const bool is_experimental_engine_supported = + const bool is_x86_architecture = base::win::OSInfo::GetInstance()->architecture() == base::win::OSInfo::X86_ARCHITECTURE; + const bool is_experimental_engine_supported = + base::FeatureList::IsEnabled(kExperimentalEngineAllArchsFeature) || + is_x86_architecture; // Install the component. std::unique_ptr<ComponentInstallerTraits> traits(
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc index e50ee4b..aea298f 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include "base/feature_list.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index bb1ca3f..f8dd499f 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -401,9 +401,6 @@ { key::kForceEphemeralProfiles, prefs::kForceEphemeralProfiles, base::Value::Type::BOOLEAN }, - { key::kDHEEnabled, - ssl_config::prefs::kDHEEnabled, - base::Value::Type::BOOLEAN }, { key::kNTPContentSuggestionsEnabled, ntp_snippets::prefs::kEnableSnippets, base::Value::Type::BOOLEAN },
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc index b15a2f1..66fd6b2 100644 --- a/chrome/browser/prefs/chrome_pref_service_factory.cc +++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -380,7 +380,7 @@ std::unique_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager( const base::FilePath& profile_path) { - std::string device_id; + std::string legacy_device_id; #if defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ) // This is used by // chrome/browser/extensions/api/music_manager_private/device_id_win.cc @@ -388,7 +388,7 @@ // not available synchronously. // As part of improving pref metrics on other platforms we may want to find // ways to defer preference loading until the device ID can be used. - rlz_lib::GetMachineId(&device_id); + rlz_lib::GetMachineId(&legacy_device_id); #endif std::string seed; #if defined(GOOGLE_CHROME_BUILD) @@ -397,7 +397,7 @@ #endif return base::MakeUnique<ProfilePrefStoreManager>( profile_path, GetTrackingConfiguration(), kTrackedPrefsReportingIDsCount, - seed, device_id, g_browser_process->local_state()); + seed, legacy_device_id, g_browser_process->local_state()); } void PrepareFactory(sync_preferences::PrefServiceSyncableFactory* factory,
diff --git a/chrome/browser/prefs/profile_pref_store_manager.cc b/chrome/browser/prefs/profile_pref_store_manager.cc index 80716a3..98f85db 100644 --- a/chrome/browser/prefs/profile_pref_store_manager.cc +++ b/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -63,13 +63,13 @@ tracking_configuration, size_t reporting_ids_count, const std::string& seed, - const std::string& device_id, + const std::string& legacy_device_id, PrefService* local_state) : profile_path_(profile_path), tracking_configuration_(tracking_configuration), reporting_ids_count_(reporting_ids_count), seed_(seed), - device_id_(device_id), + legacy_device_id_(legacy_device_id), local_state_(local_state) {} ProfilePrefStoreManager::~ProfilePrefStoreManager() {} @@ -210,7 +210,7 @@ DCHECK(kPlatformSupportsPreferenceTracking); return std::unique_ptr<PrefHashStore>( - new PrefHashStoreImpl(seed_, device_id_, use_super_mac)); + new PrefHashStoreImpl(seed_, legacy_device_id_, use_super_mac)); } std::pair<std::unique_ptr<PrefHashStore>, std::unique_ptr<HashStoreContents>> @@ -219,7 +219,7 @@ #if defined(OS_WIN) return std::make_pair( base::MakeUnique<PrefHashStoreImpl>( - "ChromeRegistryHashStoreValidationSeed", device_id_, + "ChromeRegistryHashStoreValidationSeed", legacy_device_id_, false /* use_super_mac */), g_preference_validation_registry_path_for_testing ? base::MakeUnique<RegistryHashStoreContentsWin>(
diff --git a/chrome/browser/prefs/profile_pref_store_manager.h b/chrome/browser/prefs/profile_pref_store_manager.h index 8ccb455..e1d0898a 100644 --- a/chrome/browser/prefs/profile_pref_store_manager.h +++ b/chrome/browser/prefs/profile_pref_store_manager.h
@@ -40,15 +40,16 @@ // |tracking_configuration| is used for preference tracking. // |reporting_ids_count| is the count of all possible tracked preference IDs // (possibly greater than |tracking_configuration.size()|). - // |seed| and |device_id| are used to track preference value changes and must - // be the same on each launch in order to verify loaded preference values. + // |seed| and |legacy_device_id| are used to track preference value changes + // and must be the same on each launch in order to verify loaded preference + // values. ProfilePrefStoreManager( const base::FilePath& profile_path, const std::vector<PrefHashFilter::TrackedPreferenceMetadata>& tracking_configuration, size_t reporting_ids_count, const std::string& seed, - const std::string& device_id, + const std::string& legacy_device_id, PrefService* local_state); ~ProfilePrefStoreManager(); @@ -117,7 +118,7 @@ tracking_configuration_; const size_t reporting_ids_count_; const std::string seed_; - const std::string device_id_; + const std::string legacy_device_id_; PrefService* local_state_; DISALLOW_COPY_AND_ASSIGN(ProfilePrefStoreManager);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js index ac9318b..4e67530a 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js
@@ -32,7 +32,19 @@ COLLAPSED: 'collapsed', FOCUSED: 'focused', FULLSCREEN_MENUS: 'menus', - FULLSCREEN_TUTORIAL: 'tutorial' + FULLSCREEN_TUTORIAL: 'tutorial', + SEARCH: 'search' +}; + +/** + * @type {!Object<string, {title: string, location: (string|undefined)}>} + */ +Panel.ModeInfo = { + collapsed: {title: 'panel_title', location: '#'}, + focused: {title: 'panel_title', location: '#focus'}, + menus: {title: 'panel_menus_title', location: '#fullscreen'}, + tutorial: {title: 'panel_tutorial_title', location: '#fullscreen'}, + search: {title: 'panel_title', location: '#focus'} }; /** @@ -95,13 +107,6 @@ this.menusEnabled_ = localStorage['useNext'] == 'true'; /** - * True if we're currently in incremental search mode. - * @type {boolean} - * @private - */ - this.searching_ = false; - - /** * @type {Tutorial} * @private */ @@ -146,7 +151,7 @@ * Update the display based on prefs. */ Panel.updateFromPrefs = function() { - if (Panel.searching_) { + if (Panel.mode_ == Panel.Mode.SEARCH) { this.speechContainer_.hidden = true; this.brailleContainer_.hidden = true; this.searchContainer_.hidden = false; @@ -258,21 +263,8 @@ this.mode_ = mode; - if (this.mode_ == Panel.Mode.FULLSCREEN_MENUS || - this.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL) { - // Change the url fragment to 'fullscreen', which signals the native - // host code to make the window fullscreen and give it focus. - window.location = '#fullscreen'; - } else if (this.mode_ == Panel.Mode.FOCUSED) { - // Change the url fragment to 'focus', which signals the native - // host code to give the window focus. - window.location = '#focus'; - } else { - // Remove the url fragment, which signals the native host code to - // collapse the panel to its normal size and cause it to lose focus. - window.location = '#'; - } - + document.title = Msgs.getMsg(Panel.ModeInfo[this.mode_].title); + window.location = Panel.ModeInfo[this.mode_].location; $('main').hidden = (this.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL); $('menus_background').hidden = (this.mode_ != Panel.Mode.FULLSCREEN_MENUS); $('tutorial').hidden = (this.mode_ != Panel.Mode.FULLSCREEN_TUTORIAL); @@ -427,11 +419,10 @@ /** Open incremental search. */ Panel.onSearch = function() { + Panel.setMode(Panel.Mode.SEARCH); Panel.clearMenus(); Panel.pendingCallback_ = null; - Panel.searching_ = true; Panel.updateFromPrefs(); - Panel.setMode(Panel.Mode.FOCUSED); ISearchUI.init(Panel.searchInput_); };
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index 9629133..b5b47be6 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -181,7 +181,7 @@ Start reading from current location </message> <message desc="The description of the showPowerKey key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_POWER_KEY"> - Open ChromeVox keyboard help + Open ChromeVox menus </message> <message desc="The description of the hidePowerKey key. Displayed in the Options page." name="IDS_CHROMEVOX_HIDE_POWER_KEY"> Hide ChromeVox help @@ -2478,6 +2478,12 @@ <message desc="Title of the ChromeVox panel, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TITLE"> ChromeVox Panel </message> + <message desc="Title of the ChromeVox panel when menus are open, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_MENUS_TITLE"> + ChromeVox Menus + </message> + <message desc="Title of the ChromeVox panel when the tutorial is open, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TUTORIAL_TITLE"> + ChromeVox Tutorial + </message> <message desc="Title of the button that opens up the ChromeVox menus." name="IDS_CHROMEVOX_MENUS_TITLE"> ChromeVox Menus </message>
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc index a19949a4..974b1e4 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
@@ -184,8 +184,8 @@ tab_strip->GetActiveWebContents(); ASSERT_TRUE(content::WaitForLoadStop(current_web_contents)); content::TestNavigationObserver navigation_observer( - current_web_contents, - number_of_navigations); + current_web_contents, number_of_navigations, + content::MessageLoopRunner::QuitMode::DEFERRED); navigation_observer.StartWatchingNewWebContents(); // Execute test. std::string script = base::StringPrintf("clickLink('%s');", element_id);
diff --git a/chrome/browser/ui/android/page_info/certificate_chain_helper.cc b/chrome/browser/ui/android/page_info/certificate_chain_helper.cc index 50e1415..6c1c1603 100644 --- a/chrome/browser/ui/android/page_info/certificate_chain_helper.cc +++ b/chrome/browser/ui/android/page_info/certificate_chain_helper.cc
@@ -30,6 +30,8 @@ scoped_refptr<net::X509Certificate> cert = web_contents->GetController().GetVisibleEntry()->GetSSL().certificate; + if (!cert) + return ScopedJavaLocalRef<jobjectArray>(); std::vector<std::string> cert_chain; net::X509Certificate::OSCertHandles cert_handles =
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.cc b/chrome/browser/ui/ash/chrome_launcher_prefs.cc index 2a854d0..18433a4 100644 --- a/chrome/browser/ui/ash/chrome_launcher_prefs.cc +++ b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
@@ -114,15 +114,27 @@ if (display_id < 0) return; + // Avoid DictionaryPrefUpdate's notifications for read but unmodified prefs. + const base::DictionaryValue* current_shelf_prefs = + prefs->GetDictionary(prefs::kShelfPreferences); + DCHECK(current_shelf_prefs); + std::string display_key = base::Int64ToString(display_id); + const base::DictionaryValue* current_display_prefs = nullptr; + std::string current_value; + if (current_shelf_prefs->GetDictionary(display_key, ¤t_display_prefs) && + current_display_prefs->GetString(pref_key, ¤t_value) && + current_value == value) { + return; + } + DictionaryPrefUpdate update(prefs, prefs::kShelfPreferences); base::DictionaryValue* shelf_prefs = update.Get(); - base::DictionaryValue* pref_dictionary = nullptr; - std::string key = base::Int64ToString(display_id); - if (!shelf_prefs->GetDictionary(key, &pref_dictionary)) { - pref_dictionary = new base::DictionaryValue(); - shelf_prefs->Set(key, pref_dictionary); + base::DictionaryValue* display_prefs = nullptr; + if (!shelf_prefs->GetDictionary(display_key, &display_prefs)) { + display_prefs = new base::DictionaryValue(); + shelf_prefs->Set(display_key, display_prefs); } - pref_dictionary->SetStringWithoutPathExpansion(pref_key, value); + display_prefs->SetStringWithoutPathExpansion(pref_key, value); } ShelfAlignment AlignmentFromPref(const std::string& value) {
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index 45e4e9da..d7f6369 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" +#include "base/auto_reset.h" #include "base/memory/ptr_util.h" #include "chrome/browser/extensions/extension_app_icon_loader.h" #include "chrome/browser/profiles/profile.h" @@ -24,6 +25,16 @@ instance_ = nullptr; } +void ChromeLauncherController::Init() { + // Start observing the shelf controller. + if (ConnectToShelfController()) { + ash::mojom::ShelfObserverAssociatedPtrInfo ptr_info; + observer_binding_.Bind(&ptr_info, shelf_controller_.associated_group()); + shelf_controller_->AddObserver(std::move(ptr_info)); + } + OnInit(); +} + void ChromeLauncherController::LaunchApp(const std::string& app_id, ash::LaunchSource source, int event_flags) { @@ -42,12 +53,6 @@ ChromeLauncherController::ChromeLauncherController() : observer_binding_(this) { DCHECK(!instance_); instance_ = this; - // Start observing the shelf controller immediately. - if (ConnectToShelfController()) { - ash::mojom::ShelfObserverAssociatedPtrInfo ptr_info; - observer_binding_.Bind(&ptr_info, shelf_controller_.associated_group()); - shelf_controller_->AddObserver(std::move(ptr_info)); - } } bool ChromeLauncherController::ConnectToShelfController() { @@ -75,7 +80,7 @@ } void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { - if (!ConnectToShelfController()) + if (!ConnectToShelfController() || updating_shelf_pref_from_observer_) return; // The pref helper functions return default values for invalid display ids. @@ -88,7 +93,7 @@ } void ChromeLauncherController::SetShelfAlignmentFromPrefs() { - if (!ConnectToShelfController()) + if (!ConnectToShelfController() || updating_shelf_pref_from_observer_) return; // The pref helper functions return default values for invalid display ids. @@ -170,8 +175,9 @@ // The locked alignment is set temporarily and not saved to preferences. if (alignment == ash::SHELF_ALIGNMENT_BOTTOM_LOCKED) return; + DCHECK(!updating_shelf_pref_from_observer_); + base::AutoReset<bool> updating(&updating_shelf_pref_from_observer_, true); // This will uselessly store a preference value for invalid display ids. - // TODO(msw): Avoid handling this pref change and forwarding the value to ash. ash::launcher::SetShelfAlignmentPref(profile_->GetPrefs(), display_id, alignment); } @@ -179,8 +185,9 @@ void ChromeLauncherController::OnAutoHideBehaviorChanged( ash::ShelfAutoHideBehavior auto_hide, int64_t display_id) { + DCHECK(!updating_shelf_pref_from_observer_); + base::AutoReset<bool> updating(&updating_shelf_pref_from_observer_, true); // This will uselessly store a preference value for invalid display ids. - // TODO(msw): Avoid handling this pref change and forwarding the value to ash. ash::launcher::SetShelfAutoHideBehaviorPref(profile_->GetPrefs(), display_id, auto_hide); }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h index 112ae2c4..8d75234 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -76,8 +76,8 @@ ~ChromeLauncherController() override; - // Initializes this ChromeLauncherController. - virtual void Init() = 0; + // Initializes this ChromeLauncherController and calls OnInit. + void Init(); // Creates a new app item on the shelf for |controller|. virtual ash::ShelfID CreateAppLauncherItem(LauncherItemController* controller, @@ -269,9 +269,12 @@ protected: ChromeLauncherController(); + // Called after Init; allows subclasses to perform additional initialization. + virtual void OnInit() = 0; + // Connects or reconnects to the mojom::ShelfController interface in ash. - // Returns true if connected and returns false in unit tests. - bool ConnectToShelfController(); + // Returns true if connected; virtual for unit tests. + virtual bool ConnectToShelfController(); // Accessor for subclasses to interact with the shelf controller. ash::mojom::ShelfControllerPtr& shelf_controller() { @@ -289,6 +292,8 @@ int64_t display_id) override; private: + friend class TestChromeLauncherControllerImpl; + // AppIconLoaderDelegate: void OnAppImageUpdated(const std::string& app_id, const gfx::ImageSkia& image) override; @@ -306,6 +311,9 @@ // The binding this instance uses to implment mojom::ShelfObserver mojo::AssociatedBinding<ash::mojom::ShelfObserver> observer_binding_; + // True when setting a shelf pref in response to an observer notification. + bool updating_shelf_pref_from_observer_ = false; + // Used to get app info for tabs. std::unique_ptr<LauncherControllerHelper> launcher_controller_helper_;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc index 8ac83987..a5def51 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -273,18 +273,6 @@ chrome::MultiUserWindowManager::DeleteInstance(); } -void ChromeLauncherControllerImpl::Init() { - CreateBrowserShortcutLauncherItem(); - UpdateAppLaunchersFromPref(); - - // TODO(sky): update unit test so that this test isn't necessary. - if (ash::Shell::HasInstance()) - SetVirtualKeyboardBehaviorFromPrefs(); - - prefs_observer_ = - ash::launcher::ChromeLauncherPrefsObserver::CreateIfNecessary(profile()); -} - ash::ShelfID ChromeLauncherControllerImpl::CreateAppLauncherItem( LauncherItemController* controller, const std::string& app_id, @@ -951,6 +939,18 @@ /////////////////////////////////////////////////////////////////////////////// // ChromeLauncherControllerImpl protected: +void ChromeLauncherControllerImpl::OnInit() { + CreateBrowserShortcutLauncherItem(); + UpdateAppLaunchersFromPref(); + + // TODO(sky): update unit test so that this test isn't necessary. + if (ash::Shell::HasInstance()) + SetVirtualKeyboardBehaviorFromPrefs(); + + prefs_observer_ = + ash::launcher::ChromeLauncherPrefsObserver::CreateIfNecessary(profile()); +} + ash::ShelfID ChromeLauncherControllerImpl::CreateAppShortcutLauncherItem( const ash::launcher::AppLauncherId& app_launcher_id, int index) {
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h index 8401011..cfb9bb13 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h
@@ -61,7 +61,6 @@ ~ChromeLauncherControllerImpl() override; // ChromeLauncherController: - void Init() override; ash::ShelfID CreateAppLauncherItem(LauncherItemController* controller, const std::string& app_id, ash::ShelfItemStatus status) override; @@ -151,6 +150,9 @@ const std::string& app_id) override; protected: + // ChromeLauncherController: + void OnInit() override; + // Creates a new app shortcut item and controller on the shelf at |index|. // Use kInsertItemAtEnd to add a shortcut as the last item. ash::ShelfID CreateAppShortcutLauncherItem( @@ -161,6 +163,7 @@ friend class ChromeLauncherControllerImplTest; friend class ShelfAppBrowserTest; friend class LauncherPlatformAppBrowserTest; + friend class TestChromeLauncherControllerImpl; FRIEND_TEST_ALL_PREFIXES(ChromeLauncherControllerImplTest, AppPanels); typedef std::map<ash::ShelfID, LauncherItemController*> IDToItemControllerMap;
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 76aa28fe..1a4ca85b 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
@@ -4143,3 +4143,153 @@ StartAppSyncService(copy_sync_list); EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus()); } + +// A test ShelfController implementation that tracks alignment and auto-hide. +class TestShelfController : public ash::mojom::ShelfController { + public: + TestShelfController() : binding_(this) {} + ~TestShelfController() override {} + + ash::ShelfAlignment alignment() const { return alignment_; } + ash::ShelfAutoHideBehavior auto_hide() const { return auto_hide_; } + + size_t alignment_change_count() const { return alignment_change_count_; } + size_t auto_hide_change_count() const { return auto_hide_change_count_; } + + ash::mojom::ShelfControllerPtr CreateInterfacePtrAndBind() { + return binding_.CreateInterfacePtrAndBind(); + } + + // ash::mojom::ShelfController: + void AddObserver( + ash::mojom::ShelfObserverAssociatedPtrInfo observer) override { + observer_.Bind(std::move(observer)); + } + void SetAlignment(ash::ShelfAlignment alignment, + int64_t display_id) override { + alignment_change_count_++; + alignment_ = alignment; + observer_->OnAlignmentChanged(alignment_, display_id); + } + void SetAutoHideBehavior(ash::ShelfAutoHideBehavior auto_hide, + int64_t display_id) override { + auto_hide_change_count_++; + auto_hide_ = auto_hide; + observer_->OnAutoHideBehaviorChanged(auto_hide_, display_id); + } + void PinItem( + ash::mojom::ShelfItemPtr item, + ash::mojom::ShelfItemDelegateAssociatedPtrInfo delegate) override {} + void UnpinItem(const std::string& app_id) override {} + void SetItemImage(const std::string& app_id, const SkBitmap& image) override { + } + + private: + ash::ShelfAlignment alignment_ = ash::SHELF_ALIGNMENT_BOTTOM_LOCKED; + ash::ShelfAutoHideBehavior auto_hide_ = ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN; + + size_t alignment_change_count_ = 0; + size_t auto_hide_change_count_ = 0; + + ash::mojom::ShelfObserverAssociatedPtr observer_; + mojo::Binding<ash::mojom::ShelfController> binding_; + + DISALLOW_COPY_AND_ASSIGN(TestShelfController); +}; + +// A test ChromeLauncherControllerImpl sublcass that uses TestShelfController. +class TestChromeLauncherControllerImpl : public ChromeLauncherControllerImpl { + public: + TestChromeLauncherControllerImpl(Profile* profile, ash::ShelfModel* model) + : ChromeLauncherControllerImpl(profile, model) {} + + // ChromeLauncherControllerImpl: + using ChromeLauncherControllerImpl::ReleaseProfile; + bool ConnectToShelfController() override { + // Set the shelf controller pointer to a test instance; this is run in init. + if (!shelf_controller_.is_bound()) + shelf_controller_ = test_shelf_controller_.CreateInterfacePtrAndBind(); + return true; + } + + TestShelfController* test_shelf_controller() { + return &test_shelf_controller_; + } + + private: + TestShelfController test_shelf_controller_; + + DISALLOW_COPY_AND_ASSIGN(TestChromeLauncherControllerImpl); +}; + +using ChromeLauncherControllerImplPrefTest = BrowserWithTestWindowTest; + +// Tests that shelf profile preferences are loaded on login. +TEST_F(ChromeLauncherControllerImplPrefTest, PrefsLoadedOnLogin) { + PrefService* prefs = profile()->GetTestingPrefService(); + prefs->SetString(prefs::kShelfAlignmentLocal, "Left"); + prefs->SetString(prefs::kShelfAlignment, "Left"); + prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, "Always"); + prefs->SetString(prefs::kShelfAutoHideBehavior, "Always"); + + ash::ShelfModel* model = ash::WmShell::Get()->shelf_controller()->model(); + TestChromeLauncherControllerImpl test_launcher_controller(profile(), model); + test_launcher_controller.Init(); + + // Simulate login for the test controller. + test_launcher_controller.ReleaseProfile(); + test_launcher_controller.AttachProfile(profile()); + base::RunLoop().RunUntilIdle(); + + TestShelfController* shelf_controller = + test_launcher_controller.test_shelf_controller(); + ASSERT_TRUE(shelf_controller); + EXPECT_EQ(ash::SHELF_ALIGNMENT_LEFT, shelf_controller->alignment()); + EXPECT_EQ(1u, shelf_controller->alignment_change_count()); + EXPECT_EQ(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + shelf_controller->auto_hide()); + EXPECT_EQ(1u, shelf_controller->auto_hide_change_count()); +} + +// Tests that the shelf controller's changes are not wastefully echoed back. +TEST_F(ChromeLauncherControllerImplPrefTest, DoNotEchoShelfControllerChanges) { + ash::ShelfModel* model = ash::WmShell::Get()->shelf_controller()->model(); + TestChromeLauncherControllerImpl test_launcher_controller(profile(), model); + test_launcher_controller.Init(); + + // Simulate login for the test controller. + test_launcher_controller.ReleaseProfile(); + test_launcher_controller.AttachProfile(profile()); + base::RunLoop().RunUntilIdle(); + + TestShelfController* shelf_controller = + test_launcher_controller.test_shelf_controller(); + ASSERT_TRUE(shelf_controller); + EXPECT_EQ(ash::SHELF_ALIGNMENT_BOTTOM, shelf_controller->alignment()); + EXPECT_EQ(1u, shelf_controller->alignment_change_count()); + EXPECT_EQ(ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf_controller->auto_hide()); + EXPECT_EQ(1u, shelf_controller->auto_hide_change_count()); + + // Changing settings via the shelf controller causes the launcher controller + // to update profile prefs. The launcher controller's prefs observation should + // not cause those same changes to be echoed back to the shelf controller. + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + shelf_controller->SetAlignment(ash::SHELF_ALIGNMENT_LEFT, display_id); + EXPECT_EQ(2u, shelf_controller->alignment_change_count()); + shelf_controller->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + display_id); + EXPECT_EQ(2u, shelf_controller->auto_hide_change_count()); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(ash::SHELF_ALIGNMENT_LEFT, shelf_controller->alignment()); + EXPECT_EQ(2u, shelf_controller->alignment_change_count()); + EXPECT_EQ(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, + shelf_controller->auto_hide()); + EXPECT_EQ(2u, shelf_controller->auto_hide_change_count()); + + PrefService* prefs = profile()->GetTestingPrefService(); + EXPECT_EQ("Left", prefs->GetString(prefs::kShelfAlignmentLocal)); + EXPECT_EQ("Left", prefs->GetString(prefs::kShelfAlignment)); + EXPECT_EQ("Always", prefs->GetString(prefs::kShelfAutoHideBehaviorLocal)); + EXPECT_EQ("Always", prefs->GetString(prefs::kShelfAutoHideBehavior)); +}
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc index 766cffd..286708b9 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc
@@ -58,10 +58,6 @@ ChromeLauncherControllerMus::~ChromeLauncherControllerMus() {} -void ChromeLauncherControllerMus::Init() { - NOTIMPLEMENTED(); -} - ash::ShelfID ChromeLauncherControllerMus::CreateAppLauncherItem( LauncherItemController* controller, const std::string& app_id, @@ -271,6 +267,8 @@ shelf_controller()->SetItemImage(app_id, *image.bitmap()); } +void ChromeLauncherControllerMus::OnInit() {} + void ChromeLauncherControllerMus::PinAppsFromPrefs() { if (!ConnectToShelfController()) return;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h index d562e62..647297c 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h
@@ -20,7 +20,6 @@ ~ChromeLauncherControllerMus() override; // ChromeLauncherController: - void Init() override; ash::ShelfID CreateAppLauncherItem(LauncherItemController* controller, const std::string& app_id, ash::ShelfItemStatus status) override; @@ -82,6 +81,10 @@ void OnAppImageUpdated(const std::string& app_id, const gfx::ImageSkia& image) override; + protected: + // ChromeLauncherController: + void OnInit() override; + private: // Pin the items set in the current profile's preferences. void PinAppsFromPrefs();
diff --git a/chrome/browser/ui/ash/palette_delegate_chromeos.cc b/chrome/browser/ui/ash/palette_delegate_chromeos.cc index 24703ac..7c923d6 100644 --- a/chrome/browser/ui/ash/palette_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/palette_delegate_chromeos.cc
@@ -6,7 +6,6 @@ #include "ash/accelerators/accelerator_controller_delegate_aura.h" #include "ash/common/system/chromeos/palette/palette_utils.h" -#include "ash/magnifier/partial_magnification_controller.h" #include "ash/screenshot_delegate.h" #include "ash/shell.h" #include "ash/utility/screenshot_controller.h" @@ -132,12 +131,6 @@ then.Run(); } -void PaletteDelegateChromeOS::SetPartialMagnifierState(bool enabled) { - ash::PartialMagnificationController* controller = - ash::Shell::GetInstance()->partial_magnification_controller(); - controller->SetEnabled(enabled); -} - void PaletteDelegateChromeOS::SetStylusStateChangedCallback( const OnStylusStateChangedCallback& on_stylus_state_changed) { on_stylus_state_changed_ = on_stylus_state_changed;
diff --git a/chrome/browser/ui/ash/palette_delegate_chromeos.h b/chrome/browser/ui/ash/palette_delegate_chromeos.h index abce09f..95acad8 100644 --- a/chrome/browser/ui/ash/palette_delegate_chromeos.h +++ b/chrome/browser/ui/ash/palette_delegate_chromeos.h
@@ -46,7 +46,6 @@ const EnableListener& on_state_changed) override; void CreateNote() override; bool HasNoteApp() override; - void SetPartialMagnifierState(bool enabled) override; void SetStylusStateChangedCallback( const OnStylusStateChangedCallback& on_stylus_state_changed) override; bool ShouldAutoOpenPalette() override;
diff --git a/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm index 406980bf5..9cf41d8 100644 --- a/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/passwords_bubble_controller_unittest.mm
@@ -8,7 +8,6 @@ #include "base/compiler_specific.h" #include "base/mac/foundation_util.h" -#include "base/metrics/field_trial.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #import "chrome/browser/ui/cocoa/info_bubble_window.h" @@ -20,17 +19,12 @@ #include "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" -#include "components/password_manager/core/browser/password_bubble_experiment.h" -#include "components/variations/variations_associated_data.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" namespace { -using password_bubble_experiment::kChromeSignInPasswordPromoExperimentName; -using password_bubble_experiment::kChromeSignInPasswordPromoThresholdParam; - class ManagePasswordsBubbleControllerTest : public ManagePasswordsControllerTest { public: @@ -94,14 +88,6 @@ } TEST_F(ManagePasswordsBubbleControllerTest, TransitionToSignInPromo) { - const char kFakeGroup[] = "FakeGroup"; - base::FieldTrialList field_trial_list(nullptr); - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - kChromeSignInPasswordPromoExperimentName, kFakeGroup)); - variations::AssociateVariationParams( - kChromeSignInPasswordPromoExperimentName, kFakeGroup, - {{kChromeSignInPasswordPromoThresholdParam, "3"}}); - SetUpSavePendingState(false); [controller() showWindow:nil]; SavePendingPasswordViewController* saveController = @@ -112,8 +98,6 @@ EXPECT_EQ([SignInPromoViewController class], [[controller() currentController] class]); EXPECT_TRUE([[controller() window] isVisible]); - - variations::testing::ClearAllVariationParams(); } } // namespace
diff --git a/chrome/browser/ui/cocoa/passwords/save_pending_password_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/save_pending_password_view_controller_unittest.mm index 621e3b11..6039edc 100644 --- a/chrome/browser/ui/cocoa/passwords/save_pending_password_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/save_pending_password_view_controller_unittest.mm
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" @@ -38,6 +39,8 @@ TEST_F(SavePendingPasswordViewControllerTest, ShouldSavePasswordAndDismissWhenSaveClicked) { + profile()->GetPrefs()->SetBoolean( + password_manager::prefs::kWasSignInPasswordPromoClicked, true); SetUpSavePendingState(false); EXPECT_CALL(*ui_controller(), SavePassword()); EXPECT_CALL(*ui_controller(), NeverSavePassword()).Times(0);
diff --git a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller_unittest.mm index 1ce68663..1fd28fa 100644 --- a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller_unittest.mm
@@ -4,21 +4,13 @@ #import "chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.h" -#include "base/metrics/field_trial.h" #import "chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" -#include "components/password_manager/core/browser/password_bubble_experiment.h" -#include "components/variations/variations_associated_data.h" namespace { -using password_bubble_experiment::kChromeSignInPasswordPromoExperimentName; -using password_bubble_experiment::kChromeSignInPasswordPromoThresholdParam; - class SignInPromoViewControllerTest : public ManagePasswordsControllerTest { public: - SignInPromoViewControllerTest() : field_trial_list_(nullptr) {} - void SetUp() override; void TearDown() override; @@ -27,7 +19,6 @@ SignInPromoViewController* controller() { return controller_.get(); } private: - base::FieldTrialList field_trial_list_; base::scoped_nsobject<SignInPromoViewController> controller_; }; @@ -38,17 +29,10 @@ void SignInPromoViewControllerTest::TearDown() { ManagePasswordsControllerTest::TearDown(); - variations::testing::ClearAllVariationParams(); } void SignInPromoViewControllerTest::SetUpSignInPromoState() { - const char kFakeGroup[] = "FakeGroup"; SetUpSavePendingState(false); - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - kChromeSignInPasswordPromoExperimentName, kFakeGroup)); - variations::AssociateVariationParams( - kChromeSignInPasswordPromoExperimentName, kFakeGroup, - {{kChromeSignInPasswordPromoThresholdParam, "3"}}); GetModelAndCreateIfNull()->OnSaveClicked(); ASSERT_TRUE(GetModelAndCreateIfNull()->ReplaceToShowPromotionIfNeeded());
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc index d73ec0f..700ed85 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -8,7 +8,6 @@ #include <vector> #include "base/memory/ptr_util.h" -#include "base/metrics/field_trial.h" #include "base/metrics/histogram_samples.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" @@ -20,7 +19,6 @@ #include "chrome/test/base/testing_profile.h" #include "components/browser_sync/profile_sync_service_mock.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/statistics_table.h" @@ -28,15 +26,12 @@ #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/password_manager/core/common/password_manager_ui.h" #include "components/prefs/pref_service.h" -#include "components/variations/variations_associated_data.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/web_contents_tester.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using password_bubble_experiment::kChromeSignInPasswordPromoExperimentName; -using password_bubble_experiment::kChromeSignInPasswordPromoThresholdParam; using ::testing::AnyNumber; using ::testing::Return; using ::testing::ReturnRef; @@ -44,7 +39,6 @@ namespace { -constexpr char kFakeGroup[] = "FakeGroup"; constexpr char kSignInPromoCountTilNoThanksMetric[] = "PasswordManager.SignInPromoCountTilNoThanks"; constexpr char kSignInPromoCountTilSignInMetric[] = @@ -104,7 +98,7 @@ class ManagePasswordsBubbleModelTest : public ::testing::Test { public: - ManagePasswordsBubbleModelTest() : field_trials_(nullptr) {} + ManagePasswordsBubbleModelTest() = default; ~ManagePasswordsBubbleModelTest() override = default; void SetUp() override { @@ -132,8 +126,6 @@ // Reset the delegate first. It can happen if the user closes the tab. mock_delegate_.reset(); model_.reset(); - variations::testing::ClearAllVariationIDs(); - variations::testing::ClearAllVariationParams(); } PrefService* prefs() { return profile_.GetPrefs(); } @@ -171,7 +163,6 @@ content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; std::unique_ptr<content::WebContents> test_web_contents_; - base::FieldTrialList field_trials_; std::unique_ptr<ManagePasswordsBubbleModel> model_; std::unique_ptr<PasswordsModelDelegateMock> mock_delegate_; }; @@ -345,6 +336,8 @@ } TEST_F(ManagePasswordsBubbleModelTest, SuppressSignInPromo) { + prefs()->SetBoolean(password_manager::prefs::kWasSignInPasswordPromoClicked, + true); base::HistogramTester histogram_tester; PretendPasswordWaiting(); EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(GURL(kSiteOrigin).GetOrigin())); @@ -360,11 +353,6 @@ } TEST_F(ManagePasswordsBubbleModelTest, SignInPromoOK) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - kChromeSignInPasswordPromoExperimentName, kFakeGroup)); - variations::AssociateVariationParams( - kChromeSignInPasswordPromoExperimentName, kFakeGroup, - {{kChromeSignInPasswordPromoThresholdParam, "3"}}); base::HistogramTester histogram_tester; PretendPasswordWaiting(); EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(GURL(kSiteOrigin).GetOrigin())); @@ -389,11 +377,6 @@ } TEST_F(ManagePasswordsBubbleModelTest, SignInPromoCancel) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - kChromeSignInPasswordPromoExperimentName, kFakeGroup)); - variations::AssociateVariationParams( - kChromeSignInPasswordPromoExperimentName, kFakeGroup, - {{kChromeSignInPasswordPromoThresholdParam, "3"}}); base::HistogramTester histogram_tester; PretendPasswordWaiting(); EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(GURL(kSiteOrigin).GetOrigin())); @@ -417,11 +400,6 @@ } TEST_F(ManagePasswordsBubbleModelTest, SignInPromoDismiss) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - kChromeSignInPasswordPromoExperimentName, kFakeGroup)); - variations::AssociateVariationParams( - kChromeSignInPasswordPromoExperimentName, kFakeGroup, - {{kChromeSignInPasswordPromoThresholdParam, "3"}}); base::HistogramTester histogram_tester; PretendPasswordWaiting(); EXPECT_CALL(*GetStore(), RemoveSiteStatsImpl(GURL(kSiteOrigin).GetOrigin()));
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc index b015a05..04862fe 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -20,19 +20,14 @@ #include "chrome/browser/ui/ash/volume_controller.h" #include "chrome/browser/ui/ash/vpn_list_forwarder.h" #include "chrome/browser/ui/views/ash/tab_scrubber.h" -#include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h" #include "chrome/browser/ui/views/frame/immersive_context_mus.h" #include "chrome/browser/ui/views/frame/immersive_handler_factory_mus.h" #include "chrome/browser/ui/views/select_file_dialog_extension.h" #include "chrome/browser/ui/views/select_file_dialog_extension_factory.h" #include "ui/keyboard/content/keyboard.h" #include "ui/keyboard/keyboard_controller.h" -#include "ui/wm/core/capture_controller.h" -#include "ui/wm/core/wm_state.h" -ChromeBrowserMainExtraPartsAsh::ChromeBrowserMainExtraPartsAsh( - ChromeBrowserMainExtraPartsViews* extra_parts_views) - : extra_parts_views_(extra_parts_views) {} +ChromeBrowserMainExtraPartsAsh::ChromeBrowserMainExtraPartsAsh() {} ChromeBrowserMainExtraPartsAsh::~ChromeBrowserMainExtraPartsAsh() {} @@ -41,8 +36,7 @@ chrome::OpenAsh(gfx::kNullAcceleratedWidget); if (chrome::IsRunningInMash()) { - immersive_context_ = base::MakeUnique<ImmersiveContextMus>( - extra_parts_views_->wm_state()->capture_controller()); + immersive_context_ = base::MakeUnique<ImmersiveContextMus>(); immersive_handler_factory_ = base::MakeUnique<ImmersiveHandlerFactoryMus>(); }
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h index 36c6bab6..a25ef3f 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
@@ -11,7 +11,6 @@ #include "chrome/browser/chrome_browser_main_extra_parts.h" class CastConfigClientMediaRouter; -class ChromeBrowserMainExtraPartsViews; class ChromeLauncherControllerMus; class ChromeNewWindowClient; class ChromeShellContentState; @@ -27,8 +26,7 @@ // TODO(jamescook): Fold this into ChromeBrowserMainPartsChromeOS. class ChromeBrowserMainExtraPartsAsh : public ChromeBrowserMainExtraParts { public: - explicit ChromeBrowserMainExtraPartsAsh( - ChromeBrowserMainExtraPartsViews* extra_parts_views); + ChromeBrowserMainExtraPartsAsh(); ~ChromeBrowserMainExtraPartsAsh() override; // Overridden from ChromeBrowserMainExtraParts: @@ -37,8 +35,6 @@ void PostMainMessageLoopRun() override; private: - ChromeBrowserMainExtraPartsViews* extra_parts_views_; - std::unique_ptr<ChromeLauncherControllerMus> chrome_launcher_controller_mus_; std::unique_ptr<ChromeShellContentState> chrome_shell_content_state_; std::unique_ptr<CastConfigClientMediaRouter> cast_config_client_media_router_;
diff --git a/chrome/browser/ui/views/frame/immersive_context_mus.cc b/chrome/browser/ui/views/frame/immersive_context_mus.cc index 4139ba81..fd4cd05 100644 --- a/chrome/browser/ui/views/frame/immersive_context_mus.cc +++ b/chrome/browser/ui/views/frame/immersive_context_mus.cc
@@ -4,14 +4,12 @@ #include "chrome/browser/ui/views/frame/immersive_context_mus.h" -#include "ui/aura/client/capture_client.h" #include "ui/views/mus/mus_client.h" #include "ui/views/mus/pointer_watcher_event_router.h" #include "ui/views/pointer_watcher.h" +#include "ui/views/widget/desktop_aura/desktop_capture_client.h" -ImmersiveContextMus::ImmersiveContextMus( - aura::client::CaptureClient* capture_client) - : capture_client_(capture_client) {} +ImmersiveContextMus::ImmersiveContextMus() {} ImmersiveContextMus::~ImmersiveContextMus() {} @@ -49,7 +47,7 @@ } bool ImmersiveContextMus::DoesAnyWindowHaveCapture() { - return capture_client_->GetGlobalCaptureWindow() != nullptr; + return views::DesktopCaptureClient::GetCaptureWindowGlobal() != nullptr; } bool ImmersiveContextMus::IsMouseEventsEnabled() {
diff --git a/chrome/browser/ui/views/frame/immersive_context_mus.h b/chrome/browser/ui/views/frame/immersive_context_mus.h index e612e208..503d1bac 100644 --- a/chrome/browser/ui/views/frame/immersive_context_mus.h +++ b/chrome/browser/ui/views/frame/immersive_context_mus.h
@@ -8,15 +8,9 @@ #include "ash/shared/immersive_context.h" #include "base/macros.h" -namespace aura { -namespace client { -class CaptureClient; -} -} - class ImmersiveContextMus : public ash::ImmersiveContext { public: - explicit ImmersiveContextMus(aura::client::CaptureClient* capture_client); + ImmersiveContextMus(); ~ImmersiveContextMus() override; // ash::ImmersiveContext: @@ -33,8 +27,6 @@ bool IsMouseEventsEnabled() override; private: - aura::client::CaptureClient* capture_client_; - DISALLOW_COPY_AND_ASSIGN(ImmersiveContextMus); };
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index 910ca3b..dd62066 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -38,6 +38,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/settings_resources.h" #include "chrome/grit/settings_resources_map.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" @@ -202,10 +203,11 @@ web_ui()->AddMessageHandler(std::move(handler)); } -void MdSettingsUI::DidStartProvisionalLoadForFrame( - content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - bool is_error_page) { +void MdSettingsUI::DidStartNavigation( + content::NavigationHandle* navigation_handle) { + if (navigation_handle->IsSamePage()) + return; + load_start_time_ = base::Time::Now(); }
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.h b/chrome/browser/ui/webui/settings/md_settings_ui.h index 3f1d929..f09d09e 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.h +++ b/chrome/browser/ui/webui/settings/md_settings_ui.h
@@ -26,10 +26,8 @@ ~MdSettingsUI() override; // content::WebContentsObserver: - void DidStartProvisionalLoadForFrame( - content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - bool is_error_page) override; + void DidStartNavigation( + content::NavigationHandle* navigation_handle) override; void DocumentLoadedInFrame( content::RenderFrameHost *render_frame_host) override; void DocumentOnLoadCompletedInMainFrame() override;
diff --git a/chrome/common/media/media_resource_provider.h b/chrome/common/media/media_resource_provider.h index b1b5e76..4f4ad9f 100644 --- a/chrome/common/media/media_resource_provider.h +++ b/chrome/common/media/media_resource_provider.h
@@ -6,7 +6,7 @@ #define CHROME_COMMON_MEDIA_MEDIA_RESOURCE_PROVIDER_H_ #include "base/strings/string16.h" -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" namespace chrome_common_media {
diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc index b4a01e1..a8a8b54 100644 --- a/chrome/renderer/chrome_render_thread_observer.cc +++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -47,7 +47,7 @@ #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_visitor.h" #include "extensions/features/features.h" -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "net/base/net_errors.h" #include "net/base/net_module.h"
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc index 316f08b..0225cfe 100644 --- a/chrome/test/base/ui_test_utils.cc +++ b/chrome/test/base/ui_test_utils.cc
@@ -180,8 +180,8 @@ tab_strip->GetActiveWebContents()) content::WaitForLoadStop(tab_strip->GetActiveWebContents()); content::TestNavigationObserver same_tab_observer( - tab_strip->GetActiveWebContents(), - number_of_navigations); + tab_strip->GetActiveWebContents(), number_of_navigations, + content::MessageLoopRunner::QuitMode::DEFERRED); std::set<Browser*> initial_browsers; for (auto* browser : *BrowserList::GetInstance()) @@ -221,8 +221,9 @@ same_tab_observer.Wait(); return; } else if (web_contents) { - content::TestNavigationObserver observer(web_contents, - number_of_navigations); + content::TestNavigationObserver observer( + web_contents, number_of_navigations, + content::MessageLoopRunner::QuitMode::DEFERRED); observer.Wait(); return; }
diff --git a/chrome/test/data/autofill/autofill_password_form.html b/chrome/test/data/autofill/autofill_password_form.html new file mode 100644 index 0000000..f164f95 --- /dev/null +++ b/chrome/test/data/autofill/autofill_password_form.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> +<!-- Autofill password test form. --> +<html> + <head> + <title>Autofill Password Test Form</title> + </head> + <body> + <h3>Autofill Password Test Form</h3> + <form> + <label for="user">User:</label> + <input id="user" type="text" name="name" onfocus="domAutomationController.send(true)"><br> + <label for="password">Password:</label> + <input id="password" type="password" name="password" onfocus="domAutomationController.send(true)"><br> + <input type="submit" value="Submit"> + </form> + </body> +</html> +
diff --git a/chrome/test/data/payments/can_make_payment_metrics.js b/chrome/test/data/payments/can_make_payment_metrics.js new file mode 100644 index 0000000..f5795313 --- /dev/null +++ b/chrome/test/data/payments/can_make_payment_metrics.js
@@ -0,0 +1,81 @@ +/* + * Copyright 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* global PaymentRequest:false */ +/* global print:false */ + +/** + * Do not query CanMakePayment before showing the Payment Request. + */ +function noQueryShow() { // eslint-disable-line no-unused-vars + try { + var request = new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'visa']}], + {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}}); + request.show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.shippingOption + '<br>' + + JSON.stringify( + toDictionary(resp.shippingAddress), undefined, 2) + + '<br>' + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { print(error); }); + }) + .catch(function(error) { print(error); }); + } catch (error) { + print(error.message); + } +} + +/** + * Queries CanMakePayment and the shows the PaymentRequest after. + */ +function queryShow() { // eslint-disable-line no-unused-vars + try { + var request = new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'visa']}], + {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}}); + request.canMakePayment() + .then(function(result) { print(result); }) + .catch(function(error) { print(error); }); + request.show() + .then(function(resp) { + resp.complete('success') + .then(function() { + print( + resp.shippingOption + '<br>' + + JSON.stringify( + toDictionary(resp.shippingAddress), undefined, 2) + + '<br>' + resp.methodName + '<br>' + + JSON.stringify(resp.details, undefined, 2)); + }) + .catch(function(error) { print(error); }); + }) + .catch(function(error) { print(error); }); + } catch (error) { + print(error.message); + } +} + +/** + * Queries CanMakePayment but does not show the PaymentRequest after. + */ +function queryNoShow() { // eslint-disable-line no-unused-vars + try { + var request = new PaymentRequest( + [{supportedMethods: ['https://bobpay.com', 'visa']}], + {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}}); + request.canMakePayment() + .then(function(result) { print(result); }) + .catch(function(error) { print(error); }); + } catch (error) { + print(error.message); + } +}
diff --git a/chrome/test/data/payments/payment_request_can_make_payment_metrics_test.html b/chrome/test/data/payments/payment_request_can_make_payment_metrics_test.html new file mode 100644 index 0000000..965bb73 --- /dev/null +++ b/chrome/test/data/payments/payment_request_can_make_payment_metrics_test.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<!-- +Copyright 2017 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html> +<head> +<title>Can Make Payment Metrics Test</title> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> +<link rel="stylesheet" type="text/css" href="style.css"> +</head> +<body> +<button onclick="noQueryShow()" id="noQueryShow">No Query Show Test</button><br> +<button onclick="queryShow()" id="queryShow">Query Show Test</button><br> +<button onclick="queryNoShow()" id="queryNoShow">Query No Show Test</button><br> +<pre id="result"></pre> +<script src="util.js"></script> +<script src="can_make_payment_metrics.js"></script> +</body> +</html>
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 2e1d91b..46150a0 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -1944,9 +1944,11 @@ }, "SSLVersionMin": { + "note": "This policy is retired, see https://crbug.com/487730." }, "SSLVersionFallbackMin": { + "note": "This policy is retired, see https://crbug.com/621780." }, "CertificateTransparencyEnforcementDisabledForUrls": { @@ -1958,16 +1960,11 @@ }, "RC4Enabled": { + "note": "This policy is retired, see https://crbug.com/375342." }, "DHEEnabled": { - "os": ["win", "linux", "mac", "chromeos"], - "test_policy": { "DHEEnabled": true }, - "pref_mappings": [ - { "pref": "ssl.dhe_enabled", - "local_state": true - } - ] + "note": "This policy is retired, see https://crbug.com/619194." }, "WelcomePageOnOSUpgradeEnabled": {
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc index 88726fd..253609d2 100644 --- a/chromeos/dbus/fake_session_manager_client.cc +++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -146,6 +146,10 @@ base::Bind(callback, true)); } +bool FakeSessionManagerClient::SupportsRestartToApplyUserFlags() const { + return false; +} + void FakeSessionManagerClient::SetFlagsForUser( const cryptohome::Identification& cryptohome_id, const std::vector<std::string>& flags) {}
diff --git a/chromeos/dbus/fake_session_manager_client.h b/chromeos/dbus/fake_session_manager_client.h index cbc8295..89bcf87 100644 --- a/chromeos/dbus/fake_session_manager_client.h +++ b/chromeos/dbus/fake_session_manager_client.h
@@ -61,6 +61,7 @@ const std::string& account_id, const std::string& policy_blob, const StorePolicyCallback& callback) override; + bool SupportsRestartToApplyUserFlags() const override; void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, const std::vector<std::string>& flags) override; void GetServerBackedStateKeys(const StateKeysCallback& callback) override;
diff --git a/chromeos/dbus/mock_session_manager_client.h b/chromeos/dbus/mock_session_manager_client.h index 50c1e91..627498c5 100644 --- a/chromeos/dbus/mock_session_manager_client.h +++ b/chromeos/dbus/mock_session_manager_client.h
@@ -59,6 +59,7 @@ void(const std::string&, const std::string&, const StorePolicyCallback&)); + MOCK_CONST_METHOD0(SupportsRestartToApplyUserFlags, bool()); MOCK_METHOD2(SetFlagsForUser, void(const cryptohome::Identification&, const std::vector<std::string>&));
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc index 966916f3..7dfbd81 100644 --- a/chromeos/dbus/session_manager_client.cc +++ b/chromeos/dbus/session_manager_client.cc
@@ -275,6 +275,8 @@ callback); } + bool SupportsRestartToApplyUserFlags() const override { return true; } + void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, const std::vector<std::string>& flags) override { dbus::MethodCall method_call(login_manager::kSessionManagerInterface, @@ -928,6 +930,9 @@ StorePolicyForUser(cryptohome::Identification::FromString(account_id), policy_blob, callback); } + + bool SupportsRestartToApplyUserFlags() const override { return false; } + void SetFlagsForUser(const cryptohome::Identification& cryptohome_id, const std::vector<std::string>& flags) override {}
diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h index c2dfc8f2..781143e 100644 --- a/chromeos/dbus/session_manager_client.h +++ b/chromeos/dbus/session_manager_client.h
@@ -198,6 +198,10 @@ const std::string& policy_blob, const StorePolicyCallback& callback) = 0; + // Returns whether session manager can be used to restart Chrome in order to + // apply per-user session flags. + virtual bool SupportsRestartToApplyUserFlags() const = 0; + // Sets the flags to be applied next time by the session manager when Chrome // is restarted inside an already started session for a particular user. virtual void SetFlagsForUser(const cryptohome::Identification& cryptohome_id,
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn index 5dd8086..2ddd7715d 100644 --- a/components/autofill/content/renderer/BUILD.gn +++ b/components/autofill/content/renderer/BUILD.gn
@@ -30,6 +30,10 @@ "//base:i18n", "//components/autofill/content/common:mojo_interfaces", "//components/autofill/core/common", + + # TODO(elawrence): remove security_state/core when the Form-Not-Secure + # feature is fully launched. https://crbug.com/677295 + "//components/security_state/core", "//components/strings", "//content/public/common", "//content/public/renderer",
diff --git a/components/autofill/content/renderer/DEPS b/components/autofill/content/renderer/DEPS index 0885896..83ce085 100644 --- a/components/autofill/content/renderer/DEPS +++ b/components/autofill/content/renderer/DEPS
@@ -3,3 +3,11 @@ "+content/public/renderer", "+third_party/re2", ] + +specific_include_rules = { + # TODO(elawrence): remove this when the Form-Not-Secure feature is fully + # launched. https://crbug.com/677295 + "password_autofill_agent\.cc" : [ + "+components/security_state/core", + ], +}
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index cfc306f..1026178 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -28,6 +28,8 @@ #include "components/autofill/core/common/autofill_util.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/password_form_fill_data.h" +#include "components/security_state/core/security_state.h" +#include "content/public/common/origin_util.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" #include "content/public/renderer/render_frame.h" @@ -843,9 +845,25 @@ blink::WebInputElement username_element; blink::WebInputElement password_element; PasswordInfo* password_info; + if (!FindPasswordInfoForElement(element, &username_element, &password_element, - &password_info)) + &password_info)) { + // If we don't have a password stored, but the form is non-secure, warn + // the user about the non-secure form. + if ((element.isPasswordField() || + HasAutocompleteAttributeValue(element, "username")) && + security_state::IsHttpWarningInFormEnabled() && + !content::IsOriginSecure(url::Origin(render_frame() + ->GetRenderView() + ->GetMainRenderFrame() + ->GetWebFrame() + ->getSecurityOrigin()) + .GetURL())) { + autofill_agent_->ShowNotSecureWarning(element); + return true; + } return false; + } // If autocomplete='off' is set on the form elements, no suggestion dialog // should be shown. However, return |true| to indicate that this is a known
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index b6e31cd..ce63053 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -94,9 +94,9 @@ bool show_all, bool generation_popup_showing); - // Shows an Autofill popup with a warning that the form is not - // secure. This is an experimental UI that is shown when a password - // field is autofilled on a non-secure page on page load. + // Shows an Autofill-style popup with a warning that the form is not secure. + // This UI is shown when a username or password field is autofilled or edited + // on a non-secure page. void ShowNotSecureWarning(const blink::WebInputElement& element); // Called when new form controls are inserted.
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 2300508..2569c41 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -550,9 +550,12 @@ // Don't send suggestions or track forms that should not be parsed. form_structure->ShouldBeParsed(); - // Logging interactions of forms that are autofillable. + bool is_filling_credit_card = false; + + // Log interactions of forms that are autofillable. if (got_autofillable_form) { if (autofill_field->Type().group() == CREDIT_CARD) { + is_filling_credit_card = true; driver_->DidInteractWithCreditCardForm(); credit_card_form_event_logger_->OnDidInteractWithAutofillableForm(); } else { @@ -561,12 +564,17 @@ } std::vector<Suggestion> suggestions; + const bool is_context_secure = + !form_structure || + (client_->IsContextSecure(form_structure->source_url()) && + (!form_structure->target_url().is_valid() || + !form_structure->target_url().SchemeIs("http"))); + const bool is_http_warning_enabled = + security_state::IsHttpWarningInFormEnabled(); if (is_autofill_possible && driver_->RendererIsAvailable() && got_autofillable_form) { - AutofillType type = autofill_field->Type(); - bool is_filling_credit_card = (type.group() == CREDIT_CARD); // On desktop, don't return non credit card related suggestions for forms or // fields that have the "autocomplete" attribute set to off. if (IsDesktopPlatform() && !is_filling_credit_card && @@ -574,16 +582,13 @@ return; } if (is_filling_credit_card) { - suggestions = GetCreditCardSuggestions(field, type); + suggestions = GetCreditCardSuggestions(field, autofill_field->Type()); } else { suggestions = GetProfileSuggestions(*form_structure, field, *autofill_field); } + if (!suggestions.empty()) { - bool is_context_secure = - client_->IsContextSecure(form_structure->source_url()) && - (!form_structure->target_url().is_valid() || - !form_structure->target_url().SchemeIs("http")); if (is_filling_credit_card) AutofillMetrics::LogIsQueriedCreditCardFormSecure(is_context_secure); @@ -591,8 +596,6 @@ // provide them for secure pages with passive mixed content (see impl. of // IsContextSecure). if (is_filling_credit_card && !is_context_secure) { - bool is_http_warning_enabled = - security_state::IsHttpWarningInFormEnabled(); // Replace the suggestion content with a warning message explaining why // Autofill is disabled for a website. The string is different if the // credit card autofill HTTP warning experiment is enabled. @@ -603,22 +606,9 @@ warning_suggestion.frontend_id = POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE; suggestions.assign(1, warning_suggestion); - - // On top of the explanation message, first show a "Payment not secure" - // message. - if (is_http_warning_enabled) { -#if !defined(OS_ANDROID) - suggestions.insert(suggestions.begin(), Suggestion()); - suggestions.front().frontend_id = POPUP_ITEM_ID_SEPARATOR; -#endif - suggestions.insert(suggestions.begin(), - CreateHttpWarningMessageSuggestionItem( - form_structure->source_url())); - } } else { - bool section_is_autofilled = - SectionIsAutofilled(*form_structure, form, - autofill_field->section()); + bool section_is_autofilled = SectionIsAutofilled( + *form_structure, form, autofill_field->section()); if (section_is_autofilled) { // If the relevant section is auto-filled and the renderer is querying // for suggestions, then the user is editing the value of a field. @@ -650,6 +640,21 @@ } } + // Show a "Payment not secure" message. + if (!is_context_secure && is_http_warning_enabled) { +#if !defined(OS_ANDROID) + if (!suggestions.empty()) { + suggestions.insert(suggestions.begin(), Suggestion()); + suggestions.front().frontend_id = POPUP_ITEM_ID_SEPARATOR; + } +#endif + + suggestions.insert( + suggestions.begin(), + CreateHttpWarningMessageSuggestionItem( + form_structure ? form_structure->source_url() : GURL::EmptyGURL())); + } + // If there are no Autofill suggestions, consider showing Autocomplete // suggestions. We will not show Autocomplete suggestions for a field that // specifies autocomplete=off (or an unrecognized type), a field for which we
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 72d6f43..d59d33268 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -695,7 +695,7 @@ EXPECT_TRUE(on_suggestions_returned_seen_); EXPECT_EQ(expected_page_id, query_id_); - ASSERT_EQ(expected_num_suggestions, suggestions_.size()); + ASSERT_LE(expected_num_suggestions, suggestions_.size()); for (size_t i = 0; i < expected_num_suggestions; ++i) { SCOPED_TRACE(base::StringPrintf("i: %" PRIuS, i)); EXPECT_EQ(expected_suggestions[i].value, suggestions_[i].value); @@ -704,6 +704,7 @@ EXPECT_EQ(expected_suggestions[i].frontend_id, suggestions_[i].frontend_id); } + ASSERT_EQ(expected_num_suggestions, suggestions_.size()); } // Wrappers around the above GetSuggestions call that take a hardcoded number @@ -1630,11 +1631,17 @@ l10n_util::GetStringUTF8(IDS_AUTOFILL_WARNING_PAYMENT_DISABLED), "", "", POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE)); - // Clear the test credit cards and try again -- we shouldn't return a warning. + // Clear the test credit cards and try again -- we should still show the + // warning. personal_data_.ClearCreditCards(); GetAutofillSuggestions(form, field); - // Autocomplete suggestions are queried, but not Autofill. - EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen()); + // Test that we sent the right values to the external delegate. + external_delegate_->CheckSuggestions( + kDefaultPageID, + Suggestion(l10n_util::GetStringUTF8( + IDS_AUTOFILL_CREDIT_CARD_HTTP_WARNING_MESSAGE), + l10n_util::GetStringUTF8(IDS_AUTOFILL_HTTP_WARNING_LEARN_MORE), + "httpWarning", POPUP_ITEM_ID_HTTP_NOT_SECURE_WARNING_MESSAGE)); } // Test that we don't show the extra "Payment not secure" warning when the page
diff --git a/components/drive/chromeos/change_list_loader.cc b/components/drive/chromeos/change_list_loader.cc index 8c47f6f2..c20f74f 100644 --- a/components/drive/chromeos/change_list_loader.cc +++ b/components/drive/chromeos/change_list_loader.cc
@@ -13,7 +13,7 @@ #include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/cancellation_flag.h" #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/drive/chromeos/change_list_processor.cc b/components/drive/chromeos/change_list_processor.cc index 833b64f..64f9c56 100644 --- a/components/drive/chromeos/change_list_processor.cc +++ b/components/drive/chromeos/change_list_processor.cc
@@ -10,7 +10,7 @@ #include <utility> #include <vector> -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/cancellation_flag.h" #include "components/drive/chromeos/resource_metadata.h"
diff --git a/components/drive/chromeos/directory_loader.cc b/components/drive/chromeos/directory_loader.cc index ce112dd..9aafb7d 100644 --- a/components/drive/chromeos/directory_loader.cc +++ b/components/drive/chromeos/directory_loader.cc
@@ -13,7 +13,7 @@ #include "base/callback_helpers.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "components/drive/chromeos/change_list_loader.h"
diff --git a/components/drive/chromeos/file_cache.cc b/components/drive/chromeos/file_cache.cc index b5a2f1f..a9597cf 100644 --- a/components/drive/chromeos/file_cache.cc +++ b/components/drive/chromeos/file_cache.cc
@@ -19,7 +19,7 @@ #include "base/files/file_util.h" #include "base/location.h" #include "base/logging.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h"
diff --git a/components/drive/chromeos/search_metadata.cc b/components/drive/chromeos/search_metadata.cc index b9d0251..186e2290 100644 --- a/components/drive/chromeos/search_metadata.cc +++ b/components/drive/chromeos/search_metadata.cc
@@ -11,7 +11,7 @@ #include "base/bind.h" #include "base/i18n/string_search.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h"
diff --git a/components/filesystem/BUILD.gn b/components/filesystem/BUILD.gn index dd20c8c8..65dad2d 100644 --- a/components/filesystem/BUILD.gn +++ b/components/filesystem/BUILD.gn
@@ -53,10 +53,6 @@ "//services/service_manager/public/cpp", "//services/tracing/public/cpp", ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/components/leveldb/BUILD.gn b/components/leveldb/BUILD.gn index ed49e2a5..68eb419 100644 --- a/components/leveldb/BUILD.gn +++ b/components/leveldb/BUILD.gn
@@ -50,10 +50,6 @@ "//services/service_manager/public/cpp", "//services/tracing/public/cpp", ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/components/nacl/broker/BUILD.gn b/components/nacl/broker/BUILD.gn index 3a2b360..aaf1de8 100644 --- a/components/nacl/broker/BUILD.gn +++ b/components/nacl/broker/BUILD.gn
@@ -38,10 +38,6 @@ } else { deps += [ ":content_dummy" ] } - - data_deps = [ - ":nacl_broker_manifest", - ] } # This exists just to make 'gn check' happy with :broker. It can't depend
diff --git a/components/password_manager/content/renderer/credential_manager_client.cc b/components/password_manager/content/renderer/credential_manager_client.cc index 24d26bc..bc8291f 100644 --- a/components/password_manager/content/renderer/credential_manager_client.cc +++ b/components/password_manager/content/renderer/credential_manager_client.cc
@@ -28,13 +28,14 @@ void WebCredentialToCredentialInfo(const blink::WebCredential& credential, CredentialInfo* out) { - out->id = credential.id(); - out->name = credential.name(); + out->id = credential.id().utf16(); + out->name = credential.name().utf16(); out->icon = credential.iconURL(); if (credential.isPasswordCredential()) { out->type = CredentialType::CREDENTIAL_TYPE_PASSWORD; - out->password = - static_cast<const blink::WebPasswordCredential&>(credential).password(); + out->password = static_cast<const blink::WebPasswordCredential&>(credential) + .password() + .utf16(); } else { DCHECK(credential.isFederatedCredential()); out->type = CredentialType::CREDENTIAL_TYPE_FEDERATED; @@ -49,10 +50,13 @@ switch (info.type) { case CredentialType::CREDENTIAL_TYPE_FEDERATED: return base::MakeUnique<blink::WebFederatedCredential>( - info.id, info.federation, info.name, info.icon); + blink::WebString::fromUTF16(info.id), info.federation, + blink::WebString::fromUTF16(info.name), info.icon); case CredentialType::CREDENTIAL_TYPE_PASSWORD: return base::MakeUnique<blink::WebPasswordCredential>( - info.id, info.password, info.name, info.icon); + blink::WebString::fromUTF16(info.id), + blink::WebString::fromUTF16(info.password), + blink::WebString::fromUTF16(info.name), info.icon); case CredentialType::CREDENTIAL_TYPE_EMPTY: return nullptr; }
diff --git a/components/password_manager/core/browser/password_bubble_experiment.cc b/components/password_manager/core/browser/password_bubble_experiment.cc index ff0b3ef..8e2a46e 100644 --- a/components/password_manager/core/browser/password_bubble_experiment.cc +++ b/components/password_manager/core/browser/password_bubble_experiment.cc
@@ -18,8 +18,6 @@ namespace password_bubble_experiment { -const char kChromeSignInPasswordPromoExperimentName[] = "SignInPasswordPromo"; -const char kChromeSignInPasswordPromoThresholdParam[] = "dismissal_threshold"; const char kSmartBubbleExperimentName[] = "PasswordSmartBubble"; const char kSmartBubbleThresholdParam[] = "dismissal_count"; @@ -66,20 +64,16 @@ bool ShouldShowChromeSignInPasswordPromo( PrefService* prefs, const syncer::SyncService* sync_service) { - // Query the group first for correct UMA reporting. - std::string param = variations::GetVariationParamValue( - kChromeSignInPasswordPromoExperimentName, - kChromeSignInPasswordPromoThresholdParam); if (!sync_service || !sync_service->IsSyncAllowed() || sync_service->IsFirstSetupComplete()) return false; - int threshold = 0; - return base::StringToInt(param, &threshold) && - !prefs->GetBoolean( + // Don't show the promo more than 3 times. + constexpr int kThreshold = 3; + return !prefs->GetBoolean( password_manager::prefs::kWasSignInPasswordPromoClicked) && prefs->GetInteger( password_manager::prefs::kNumberSignInPasswordPromoShown) < - threshold; + kThreshold; } } // namespace password_bubble_experiment
diff --git a/components/password_manager/core/browser/password_bubble_experiment.h b/components/password_manager/core/browser/password_bubble_experiment.h index 7d900a7b..19e982d 100644 --- a/components/password_manager/core/browser/password_bubble_experiment.h +++ b/components/password_manager/core/browser/password_bubble_experiment.h
@@ -14,8 +14,6 @@ namespace password_bubble_experiment { -extern const char kChromeSignInPasswordPromoExperimentName[]; -extern const char kChromeSignInPasswordPromoThresholdParam[]; extern const char kSmartBubbleExperimentName[]; extern const char kSmartBubbleThresholdParam[];
diff --git a/components/password_manager/core/browser/password_bubble_experiment_unittest.cc b/components/password_manager/core/browser/password_bubble_experiment_unittest.cc index b9ba053..80dba82 100644 --- a/components/password_manager/core/browser/password_bubble_experiment_unittest.cc +++ b/components/password_manager/core/browser/password_bubble_experiment_unittest.cc
@@ -6,7 +6,6 @@ #include <ostream> -#include "base/metrics/field_trial.h" #include "base/strings/string_number_conversions.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" @@ -14,7 +13,6 @@ #include "components/prefs/testing_pref_service.h" #include "components/sync/base/model_type.h" #include "components/sync/driver/fake_sync_service.h" -#include "components/variations/variations_associated_data.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -76,15 +74,10 @@ class PasswordManagerPasswordBubbleExperimentTest : public testing::Test { public: - PasswordManagerPasswordBubbleExperimentTest() : field_trial_list_(nullptr) { + PasswordManagerPasswordBubbleExperimentTest() { RegisterPrefs(pref_service_.registry()); } - ~PasswordManagerPasswordBubbleExperimentTest() override { - variations::testing::ClearAllVariationIDs(); - variations::testing::ClearAllVariationParams(); - } - PrefService* prefs() { return &pref_service_; } TestSyncService* sync_service() { return &fake_sync_service_; } @@ -102,7 +95,6 @@ private: TestSyncService fake_sync_service_; - base::FieldTrialList field_trial_list_; TestingPrefServiceSimple pref_service_; }; @@ -115,16 +107,12 @@ bool is_sync_allowed; bool is_first_setup_complete; int current_shown_count; - int experiment_threshold; bool result; } kTestData[] = { - {false, true, false, 0, 5, true}, {false, true, false, 5, 5, false}, - {true, true, false, 0, 5, false}, {true, true, false, 10, 5, false}, - {false, false, false, 0, 5, false}, {false, true, true, 0, 5, false}, + {false, true, false, 0, true}, {false, true, false, 5, false}, + {true, true, false, 0, false}, {true, true, false, 10, false}, + {false, false, false, 0, false}, {false, true, true, 0, false}, }; - const char kFakeGroup[] = "FakeGroup"; - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - kChromeSignInPasswordPromoExperimentName, kFakeGroup)); for (const auto& test_case : kTestData) { SCOPED_TRACE(testing::Message("#test_case = ") << (&test_case - kTestData)); prefs()->SetBoolean(password_manager::prefs::kWasSignInPasswordPromoClicked, @@ -134,10 +122,6 @@ test_case.current_shown_count); sync_service()->set_sync_allowed(test_case.is_sync_allowed); sync_service()->set_first_setup_complete(test_case.is_first_setup_complete); - variations::AssociateVariationParams( - kChromeSignInPasswordPromoExperimentName, kFakeGroup, - {{kChromeSignInPasswordPromoThresholdParam, - base::IntToString(test_case.experiment_threshold)}}); EXPECT_EQ(test_case.result, ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 28d3c99..076f6aa 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -8199,6 +8199,7 @@ 'dynamic_refresh': True, 'per_profile': False, }, + 'deprecated': True, 'example_value': 'ssl3', 'id': 279, 'caption': '''Minimum SSL version enabled''', @@ -8300,6 +8301,7 @@ 'dynamic_refresh': True, 'per_profile': False, }, + 'deprecated': True, 'example_value': False, 'id': 310, 'caption': '''Whether RC4 cipher suites in TLS are enabled''', @@ -8324,6 +8326,7 @@ 'dynamic_refresh': True, 'per_profile': False, }, + 'deprecated': True, 'example_value': False, 'id': 334, 'caption': '''Whether DHE cipher suites in TLS are enabled''',
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index b54f114..4f49e16 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -101,7 +101,7 @@ std::string json; base::JSONWriter::Write(parameters, &json); std::string script = base::StringPrintf(script_format, json.c_str()); - frame->executeScript(blink::WebString(base::UTF8ToUTF16(script))); + frame->executeScript(blink::WebString::fromUTF8(script)); } #else bool g_is_preview_enabled = false; @@ -607,7 +607,7 @@ base::StringPrintf("%d/%d", page_number, total_pages)); options->SetString("url", params.url); - base::string16 title = source_frame.document().title(); + base::string16 title = source_frame.document().title().utf16(); options->SetString("title", title.empty() ? params.title : title); ExecuteScript(frame, kPageSetupScriptFormat, *options);
diff --git a/components/ssl_config/ssl_config_prefs.cc b/components/ssl_config/ssl_config_prefs.cc index 540be23a..7a515124 100644 --- a/components/ssl_config/ssl_config_prefs.cc +++ b/components/ssl_config/ssl_config_prefs.cc
@@ -15,7 +15,6 @@ const char kSSLVersionMin[] = "ssl.version_min"; const char kSSLVersionMax[] = "ssl.version_max"; const char kCipherSuiteBlacklist[] = "ssl.cipher_suites.blacklist"; -const char kDHEEnabled[] = "ssl.dhe_enabled"; } // namespace prefs } // namespace ssl_config
diff --git a/components/ssl_config/ssl_config_prefs.h b/components/ssl_config/ssl_config_prefs.h index 7f19e1e..c10ed21 100644 --- a/components/ssl_config/ssl_config_prefs.h +++ b/components/ssl_config/ssl_config_prefs.h
@@ -14,7 +14,6 @@ extern const char kSSLVersionMin[]; extern const char kSSLVersionMax[]; extern const char kCipherSuiteBlacklist[]; -extern const char kDHEEnabled[]; } // namespace prefs } // namespace ssl_config
diff --git a/components/ssl_config/ssl_config_service_manager_pref.cc b/components/ssl_config/ssl_config_service_manager_pref.cc index 0dab204..9437237 100644 --- a/components/ssl_config/ssl_config_service_manager_pref.cc +++ b/components/ssl_config/ssl_config_service_manager_pref.cc
@@ -175,7 +175,6 @@ BooleanPrefMember sha1_local_anchors_enabled_; StringPrefMember ssl_version_min_; StringPrefMember ssl_version_max_; - BooleanPrefMember dhe_enabled_; // The cached list of disabled SSL cipher suites. std::vector<uint16_t> disabled_cipher_suites_; @@ -216,8 +215,6 @@ local_state_callback); ssl_version_max_.Init(ssl_config::prefs::kSSLVersionMax, local_state, local_state_callback); - dhe_enabled_.Init(ssl_config::prefs::kDHEEnabled, local_state, - local_state_callback); local_state_change_registrar_.Init(local_state); local_state_change_registrar_.Add(ssl_config::prefs::kCipherSuiteBlacklist, @@ -246,8 +243,6 @@ registry->RegisterStringPref(ssl_config::prefs::kSSLVersionMax, std::string()); registry->RegisterListPref(ssl_config::prefs::kCipherSuiteBlacklist); - registry->RegisterBooleanPref(ssl_config::prefs::kDHEEnabled, - default_config.dhe_enabled); } net::SSLConfigService* SSLConfigServiceManagerPref::Get() { @@ -295,7 +290,6 @@ config->version_max = version_max; } config->disabled_cipher_suites = disabled_cipher_suites_; - config->dhe_enabled = dhe_enabled_.GetValue(); } void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange(
diff --git a/components/sync/engine/browser_thread_model_worker_unittest.cc b/components/sync/engine/browser_thread_model_worker_unittest.cc index 4e3c01f..f05d2b8 100644 --- a/components/sync/engine/browser_thread_model_worker_unittest.cc +++ b/components/sync/engine/browser_thread_model_worker_unittest.cc
@@ -50,7 +50,6 @@ // This is the work that will be scheduled to be done on the DB thread. SyncerError DoWork() { EXPECT_TRUE(db_thread_.task_runner()->BelongsToCurrentThread()); - timer_.Stop(); // Stop the failure timer so the test succeeds. main_message_loop_.task_runner()->PostTask( FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); did_do_work_ = true;
diff --git a/components/task_scheduler_util/browser/initialization.cc b/components/task_scheduler_util/browser/initialization.cc index 70b28773..00bab9c 100644 --- a/components/task_scheduler_util/browser/initialization.cc +++ b/components/task_scheduler_util/browser/initialization.cc
@@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/logging.h" +#include "base/task_scheduler/scheduler_worker_params.h" #include "base/task_scheduler/switches.h" #include "base/task_scheduler/task_traits.h" #include "base/threading/platform_thread.h" @@ -40,21 +41,25 @@ if (!::variations::GetVariationParams(kFieldTrialName, &variation_params)) return std::vector<base::SchedulerWorkerPoolParams>(); - std::vector<SchedulerImmutableWorkerPoolParams> constant_worker_pool_params; - DCHECK_EQ(BACKGROUND, constant_worker_pool_params.size()); - constant_worker_pool_params.emplace_back("Background", - ThreadPriority::BACKGROUND); - DCHECK_EQ(BACKGROUND_FILE_IO, constant_worker_pool_params.size()); - constant_worker_pool_params.emplace_back("BackgroundFileIO", - ThreadPriority::BACKGROUND); - DCHECK_EQ(FOREGROUND, constant_worker_pool_params.size()); - constant_worker_pool_params.emplace_back("Foreground", - ThreadPriority::NORMAL); - DCHECK_EQ(FOREGROUND_FILE_IO, constant_worker_pool_params.size()); - constant_worker_pool_params.emplace_back("ForegroundFileIO", - ThreadPriority::NORMAL); + std::vector<SchedulerImmutableWorkerPoolParams> immutable_worker_pool_params; + DCHECK_EQ(BACKGROUND, immutable_worker_pool_params.size()); + immutable_worker_pool_params.emplace_back("Background", + ThreadPriority::BACKGROUND); + DCHECK_EQ(BACKGROUND_FILE_IO, immutable_worker_pool_params.size()); + immutable_worker_pool_params.emplace_back("BackgroundFileIO", + ThreadPriority::BACKGROUND); + DCHECK_EQ(FOREGROUND, immutable_worker_pool_params.size()); + immutable_worker_pool_params.emplace_back("Foreground", + ThreadPriority::NORMAL); + // Tasks posted to SequencedWorkerPool or BrowserThreadImpl may be redirected + // to this pool. Since COM STA is initialized in these environments, it must + // also be initialized in this pool. + DCHECK_EQ(FOREGROUND_FILE_IO, immutable_worker_pool_params.size()); + immutable_worker_pool_params.emplace_back( + "ForegroundFileIO", ThreadPriority::NORMAL, + base::SchedulerBackwardCompatibility::INIT_COM_STA); - return GetWorkerPoolParams(constant_worker_pool_params, variation_params); + return GetWorkerPoolParams(immutable_worker_pool_params, variation_params); } size_t BrowserWorkerPoolIndexForTraits(const base::TaskTraits& traits) {
diff --git a/components/task_scheduler_util/common/variations_util.cc b/components/task_scheduler_util/common/variations_util.cc index f703e11..bdca8c8 100644 --- a/components/task_scheduler_util/common/variations_util.cc +++ b/components/task_scheduler_util/common/variations_util.cc
@@ -86,8 +86,11 @@ SchedulerImmutableWorkerPoolParams::SchedulerImmutableWorkerPoolParams( const char* name, - base::ThreadPriority priority_hint) - : name_(name), priority_hint_(priority_hint) {} + base::ThreadPriority priority_hint, + base::SchedulerBackwardCompatibility backward_compatibility) + : name_(name), + priority_hint_(priority_hint), + backward_compatibility_(backward_compatibility) {} std::vector<base::SchedulerWorkerPoolParams> GetWorkerPoolParams( const std::vector<SchedulerImmutableWorkerPoolParams>& @@ -115,7 +118,8 @@ worker_pool_name, constant_worker_pool_params.priority_hint(), variable_worker_pool_params.standby_thread_policy, variable_worker_pool_params.max_threads, - variable_worker_pool_params.detach_period); + variable_worker_pool_params.detach_period, + constant_worker_pool_params.backward_compatibility()); } return worker_pool_params_vector; }
diff --git a/components/task_scheduler_util/common/variations_util.h b/components/task_scheduler_util/common/variations_util.h index 9859a16..f92b2977 100644 --- a/components/task_scheduler_util/common/variations_util.h +++ b/components/task_scheduler_util/common/variations_util.h
@@ -11,6 +11,7 @@ #include "build/build_config.h" #include "base/strings/string_piece.h" +#include "base/task_scheduler/scheduler_worker_params.h" #include "base/task_scheduler/scheduler_worker_pool_params.h" #include "base/threading/platform_thread.h" @@ -22,15 +23,22 @@ class SchedulerImmutableWorkerPoolParams { public: - SchedulerImmutableWorkerPoolParams(const char* name, - base::ThreadPriority priority_hint); + SchedulerImmutableWorkerPoolParams( + const char* name, + base::ThreadPriority priority_hint, + base::SchedulerBackwardCompatibility backward_compatibility = + base::SchedulerBackwardCompatibility::DISABLED); const char* name() const { return name_; } base::ThreadPriority priority_hint() const { return priority_hint_; } + base::SchedulerBackwardCompatibility backward_compatibility() const { + return backward_compatibility_; + } private: const char* name_; base::ThreadPriority priority_hint_; + base::SchedulerBackwardCompatibility backward_compatibility_; }; // Returns a SchedulerWorkerPoolParams vector to initialize pools specified in
diff --git a/components/task_scheduler_util/common/variations_util_unittest.cc b/components/task_scheduler_util/common/variations_util_unittest.cc index efdad2f..56181065 100644 --- a/components/task_scheduler_util/common/variations_util_unittest.cc +++ b/components/task_scheduler_util/common/variations_util_unittest.cc
@@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/metrics/field_trial.h" +#include "base/task_scheduler/scheduler_worker_params.h" #include "base/task_scheduler/scheduler_worker_pool_params.h" #include "base/threading/platform_thread.h" #include "components/variations/variations_associated_data.h" @@ -40,8 +41,9 @@ ThreadPriority::BACKGROUND); constant_worker_pool_params.emplace_back("Foreground", ThreadPriority::NORMAL); - constant_worker_pool_params.emplace_back("ForegroundFileIO", - ThreadPriority::NORMAL); + constant_worker_pool_params.emplace_back( + "ForegroundFileIO", ThreadPriority::NORMAL, + base::SchedulerBackwardCompatibility::INIT_COM_STA); return constant_worker_pool_params; } @@ -80,6 +82,8 @@ EXPECT_EQ(1U, params_vector[0].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(42), params_vector[0].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED, + params_vector[0].backward_compatibility()); EXPECT_EQ("BackgroundFileIO", params_vector[1].name()); EXPECT_EQ(ThreadPriority::BACKGROUND, params_vector[1].priority_hint()); @@ -87,6 +91,8 @@ EXPECT_EQ(2U, params_vector[1].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(52), params_vector[1].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED, + params_vector[1].backward_compatibility()); EXPECT_EQ("Foreground", params_vector[2].name()); EXPECT_EQ(ThreadPriority::NORMAL, params_vector[2].priority_hint()); @@ -94,6 +100,8 @@ EXPECT_EQ(4U, params_vector[2].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(62), params_vector[2].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED, + params_vector[2].backward_compatibility()); EXPECT_EQ("ForegroundFileIO", params_vector[3].name()); EXPECT_EQ(ThreadPriority::NORMAL, params_vector[3].priority_hint()); @@ -101,6 +109,8 @@ EXPECT_EQ(8U, params_vector[3].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(72), params_vector[3].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::INIT_COM_STA, + params_vector[3].backward_compatibility()); } TEST_F(TaskSchedulerUtilVariationsUtilTest, OrderingParams6) { @@ -121,6 +131,8 @@ EXPECT_EQ(1U, params_vector[0].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(42), params_vector[0].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED, + params_vector[0].backward_compatibility()); EXPECT_EQ("BackgroundFileIO", params_vector[1].name()); EXPECT_EQ(ThreadPriority::BACKGROUND, params_vector[1].priority_hint()); @@ -128,6 +140,8 @@ EXPECT_EQ(2U, params_vector[1].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(52), params_vector[1].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED, + params_vector[1].backward_compatibility()); EXPECT_EQ("Foreground", params_vector[2].name()); EXPECT_EQ(ThreadPriority::NORMAL, params_vector[2].priority_hint()); @@ -136,6 +150,8 @@ EXPECT_EQ(4U, params_vector[2].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(62), params_vector[2].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED, + params_vector[2].backward_compatibility()); EXPECT_EQ("ForegroundFileIO", params_vector[3].name()); EXPECT_EQ(ThreadPriority::NORMAL, params_vector[3].priority_hint()); @@ -143,6 +159,8 @@ EXPECT_EQ(8U, params_vector[3].max_threads()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(72), params_vector[3].suggested_reclaim_time()); + EXPECT_EQ(base::SchedulerBackwardCompatibility::INIT_COM_STA, + params_vector[3].backward_compatibility()); } TEST_F(TaskSchedulerUtilVariationsUtilTest, NoData) {
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc index 681f1fa..0eb37fc6 100644 --- a/components/update_client/update_checker_unittest.cc +++ b/components/update_client/update_checker_unittest.cc
@@ -17,6 +17,7 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "base/version.h" +#include "build/build_config.h" #include "components/prefs/testing_pref_service.h" #include "components/update_client/crx_update_item.h" #include "components/update_client/persisted_data.h"
diff --git a/components/update_client/updater_state.cc b/components/update_client/updater_state.cc index 0e588bf..035e6c2 100644 --- a/components/update_client/updater_state.cc +++ b/components/update_client/updater_state.cc
@@ -11,6 +11,7 @@ #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" namespace update_client {
diff --git a/components/update_client/updater_state_unittest.cc b/components/update_client/updater_state_unittest.cc index 9d34ba57..9fb5f5b 100644 --- a/components/update_client/updater_state_unittest.cc +++ b/components/update_client/updater_state_unittest.cc
@@ -5,6 +5,7 @@ #include "base/macros.h" #include "base/time/time.h" #include "base/version.h" +#include "build/build_config.h" #include "components/update_client/updater_state.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index 5144ed5..30fe455 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc
@@ -17,7 +17,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h"
diff --git a/components/user_prefs/tracked/pref_hash_calculator.cc b/components/user_prefs/tracked/pref_hash_calculator.cc index 12fb03d..8d73c1d 100644 --- a/components/user_prefs/tracked/pref_hash_calculator.cc +++ b/components/user_prefs/tracked/pref_hash_calculator.cc
@@ -79,27 +79,12 @@ return message; } -// Generates a device ID based on the input device ID. The derived device ID has -// no useful properties beyond those of the input device ID except that it is -// consistent with previous implementations. -// TODO(gab): Remove this once UMA reports for -// Settings.TrackedPreferenceMigratedLegacyDeviceId become insignificant. -std::string GenerateDeviceIdLikePrefMetricsServiceDid( - const std::string& original_device_id) { - if (original_device_id.empty()) - return std::string(); - return base::ToLowerASCII( - GetDigestString(original_device_id, "PrefMetricsService")); -} - } // namespace PrefHashCalculator::PrefHashCalculator(const std::string& seed, - const std::string& device_id) - : seed_(seed), - device_id_(device_id), - legacy_device_id_(GenerateDeviceIdLikePrefMetricsServiceDid(device_id)) { -} + const std::string& device_id, + const std::string& legacy_device_id) + : seed_(seed), device_id_(device_id), legacy_device_id_(legacy_device_id) {} PrefHashCalculator::~PrefHashCalculator() { }
diff --git a/components/user_prefs/tracked/pref_hash_calculator.h b/components/user_prefs/tracked/pref_hash_calculator.h index 1f9b74f..92b0c3a 100644 --- a/components/user_prefs/tracked/pref_hash_calculator.h +++ b/components/user_prefs/tracked/pref_hash_calculator.h
@@ -23,10 +23,13 @@ VALID_SECURE_LEGACY, }; - // Constructs a PrefHashCalculator using |seed| and |device_id|. The same - // parameters must be used in order to successfully validate generated hashes. - // |device_id| may be empty. - PrefHashCalculator(const std::string& seed, const std::string& device_id); + // Constructs a PrefHashCalculator using |seed|, |device_id| and + // |legacy_device_id|. The same parameters must be used in order to + // successfully validate generated hashes. |_device_id| or |legacy_device_id| + // may be empty. + PrefHashCalculator(const std::string& seed, + const std::string& device_id, + const std::string& legacy_device_id); ~PrefHashCalculator();
diff --git a/components/user_prefs/tracked/pref_hash_calculator_unittest.cc b/components/user_prefs/tracked/pref_hash_calculator_unittest.cc index 4d29146..752c3e1 100644 --- a/components/user_prefs/tracked/pref_hash_calculator_unittest.cc +++ b/components/user_prefs/tracked/pref_hash_calculator_unittest.cc
@@ -24,10 +24,10 @@ base::DictionaryValue dictionary_value_2; dictionary_value_2.SetInteger("int value", 2); - PrefHashCalculator calc1("seed1", "deviceid"); - PrefHashCalculator calc1_dup("seed1", "deviceid"); - PrefHashCalculator calc2("seed2", "deviceid"); - PrefHashCalculator calc3("seed1", "deviceid2"); + PrefHashCalculator calc1("seed1", "deviceid", "legacydeviceid"); + PrefHashCalculator calc1_dup("seed1", "deviceid", "legacydeviceid"); + PrefHashCalculator calc2("seed2", "deviceid", "legacydeviceid"); + PrefHashCalculator calc3("seed1", "deviceid2", "legacydeviceid"); // Two calculators with same seed produce same hash. ASSERT_EQ(calc1.Calculate("pref_path", &string_value_1), @@ -124,46 +124,46 @@ static const char kExpectedNullValue[] = "82A9F3BBC7F9FF84C76B033C854E79EEB162783FA7B3E99FF9372FA8E12C44F7"; EXPECT_EQ(PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", null_value.get(), kExpectedNullValue)); static const char kExpectedBooleanValue[] = "A520D8F43EA307B0063736DC9358C330539D0A29417580514C8B9862632C4CCC"; EXPECT_EQ( PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", bool_value.get(), kExpectedBooleanValue)); static const char kExpectedIntegerValue[] = "8D60DA1F10BF5AA29819D2D66D7CCEF9AABC5DA93C11A0D2BD21078D63D83682"; EXPECT_EQ(PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", int_value.get(), kExpectedIntegerValue)); static const char kExpectedDoubleValue[] = "C9D94772516125BEEDAE68C109D44BC529E719EE020614E894CC7FB4098C545D"; EXPECT_EQ( PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", double_value.get(), kExpectedDoubleValue)); static const char kExpectedStringValue[] = "05ACCBD3B05C45C36CD06190F63EC577112311929D8380E26E5F13182EB68318"; EXPECT_EQ( PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", string_value.get(), kExpectedStringValue)); static const char kExpectedDictValue[] = "7A84DCC710D796C771F789A4DA82C952095AA956B6F1667EE42D0A19ECAA3C4A"; EXPECT_EQ(PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", dict_value.get(), kExpectedDictValue)); static const char kExpectedListValue[] = "8D5A25972DF5AE20D041C780E7CA54E40F614AD53513A0724EE8D62D4F992740"; EXPECT_EQ(PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", list_value.get(), kExpectedListValue)); // Also test every value type together in the same dictionary. @@ -178,28 +178,22 @@ static const char kExpectedEverythingValue[] = "B97D09BE7005693574DCBDD03D8D9E44FB51F4008B73FB56A49A9FA671A1999B"; EXPECT_EQ(PrefHashCalculator::VALID, - PrefHashCalculator(kSeed, kDeviceId) + PrefHashCalculator(kSeed, kDeviceId, "legacydeviceid") .Validate("pref.path", &everything, kExpectedEverythingValue)); } -TEST(PrefHashCalculatorTest, TestCompatibilityWithLegacyPrefMetricsServiceId) { - static const char kSeed[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; - static const char kDeviceId[] = - "D730D9CBD98C734A4FB097A1922275FE9F7E026A4EA1BE0E84"; +TEST(PrefHashCalculatorTest, TestCompatibilityWithLegacyDeviceId) { + static const char kSeed[] = "0123456789ABCDEF0123456789ABCDEF"; + static const char kNewDeviceId[] = "new_test_device_id1"; + static const char kLegacyDeviceId[] = "test_device_id1"; + + // As in PrefHashCalculatorTest.CatchHashChanges. + const base::StringValue string_value( + "testing with special chars:\n<>{}:^^@#$\\/"); static const char kExpectedValue[] = - "845EF34663FF8D32BE6707F40258FBA531C2BFC532E3B014AFB3476115C2A9DE"; + "05ACCBD3B05C45C36CD06190F63EC577112311929D8380E26E5F13182EB68318"; - base::ListValue startup_urls; - startup_urls.Set(0, new base::StringValue("http://www.chromium.org/")); - - EXPECT_EQ( - PrefHashCalculator::VALID_SECURE_LEGACY, - PrefHashCalculator(std::string(kSeed, arraysize(kSeed)), kDeviceId) - .Validate("session.startup_urls", &startup_urls, kExpectedValue)); + EXPECT_EQ(PrefHashCalculator::VALID_SECURE_LEGACY, + PrefHashCalculator(kSeed, kNewDeviceId, kLegacyDeviceId) + .Validate("pref.path", &string_value, kExpectedValue)); }
diff --git a/components/user_prefs/tracked/pref_hash_store_impl.cc b/components/user_prefs/tracked/pref_hash_store_impl.cc index 80438d69..bb920ca 100644 --- a/components/user_prefs/tracked/pref_hash_store_impl.cc +++ b/components/user_prefs/tracked/pref_hash_store_impl.cc
@@ -9,9 +9,37 @@ #include "base/logging.h" #include "base/macros.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" +#include "components/user_prefs/tracked/device_id.h" #include "components/user_prefs/tracked/hash_store_contents.h" +namespace { + +// Returns a deterministic ID for this machine. +std::string GenerateDeviceId() { + static std::string cached_device_id; + if (!cached_device_id.empty()) + return cached_device_id; + + std::string device_id; + MachineIdStatus status = GetDeterministicMachineSpecificId(&device_id); + if (status != MachineIdStatus::NOT_IMPLEMENTED) { + // TODO(proberge): Remove this histogram once we validate that machine id + // generation is not flaky and consider adding a CHECK or DCHECK. + UMA_HISTOGRAM_BOOLEAN("Settings.MachineIdGenerationSuccess", + status == MachineIdStatus::SUCCESS); + } + + if (status == MachineIdStatus::SUCCESS) { + cached_device_id = device_id; + return device_id; + } + + return std::string(); +} + +} // namespace + class PrefHashStoreImpl::PrefHashStoreTransactionImpl : public PrefHashStoreTransaction { public: @@ -49,10 +77,10 @@ }; PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed, - const std::string& device_id, + const std::string& legacy_device_id, bool use_super_mac) - : pref_hash_calculator_(seed, device_id), use_super_mac_(use_super_mac) { -} + : pref_hash_calculator_(seed, GenerateDeviceId(), legacy_device_id), + use_super_mac_(use_super_mac) {} PrefHashStoreImpl::~PrefHashStoreImpl() { }
diff --git a/components/user_prefs/tracked/pref_hash_store_impl.h b/components/user_prefs/tracked/pref_hash_store_impl.h index 1b5682e..76b6f75 100644 --- a/components/user_prefs/tracked/pref_hash_store_impl.h +++ b/components/user_prefs/tracked/pref_hash_store_impl.h
@@ -25,12 +25,12 @@ }; // Constructs a PrefHashStoreImpl that calculates hashes using - // |seed| and |device_id| and stores them in |contents|. + // |seed| and |legacy_device_id| and stores them in |contents|. // - // The same |seed| and |device_id| must be used to load and validate + // The same |seed| and |legacy_device_id| must be used to load and validate // previously stored hashes in |contents|. PrefHashStoreImpl(const std::string& seed, - const std::string& device_id, + const std::string& legacy_device_id, bool use_super_mac); ~PrefHashStoreImpl() override;
diff --git a/components/wallpaper/wallpaper_manager_base.cc b/components/wallpaper/wallpaper_manager_base.cc index 01c4ca8..98022796 100644 --- a/components/wallpaper/wallpaper_manager_base.cc +++ b/components/wallpaper/wallpaper_manager_base.cc
@@ -12,7 +12,7 @@ #include "base/files/file_util.h" #include "base/lazy_instance.h" #include "base/logging.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 4a764be9..e4e9bb0 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1673,7 +1673,7 @@ ] deps += [ "//ppapi/host", - "//ppapi/proxy", + "//ppapi/proxy:common", "//ppapi/proxy:ipc", "//ppapi/shared_impl", ]
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index d6d917b..6eb0ca7 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -448,10 +448,14 @@ "Foreground", ThreadPriority::NORMAL, StandbyThreadPolicy::ONE, base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0), base::TimeDelta::FromSeconds(30)); + // Tasks posted to SequencedWorkerPool or BrowserThreadImpl may be redirected + // to this pool. Since COM STA is initialized in these environments, it must + // also be initialized in this pool. params_vector.emplace_back( "ForegroundFileIO", ThreadPriority::NORMAL, StandbyThreadPolicy::ONE, - base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0), - base::TimeDelta::FromSeconds(30)); + base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0), + base::TimeDelta::FromSeconds(30), + base::SchedulerBackwardCompatibility::INIT_COM_STA); #endif DCHECK_EQ(WORKER_POOL_COUNT, params_vector.size()); return params_vector;
diff --git a/content/browser/dom_storage/OWNERS b/content/browser/dom_storage/OWNERS index e765c6f..fdd8a71 100644 --- a/content/browser/dom_storage/OWNERS +++ b/content/browser/dom_storage/OWNERS
@@ -1,2 +1,5 @@ michaeln@chromium.org -marja@chromium.org +mek@chromium.org + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage>DOMStorage
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc index ba1c812..988fcc9b 100644 --- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/weak_ptr.h" #include "content/browser/frame_host/navigation_handle_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/web_contents.h" @@ -206,8 +207,9 @@ will_start_called_(0), will_redirect_called_(0), will_process_called_(0), - navigation_throttle_(nullptr) {} - ~TestNavigationThrottleInstaller() override{}; + navigation_throttle_(nullptr), + weak_factory_(this) {} + ~TestNavigationThrottleInstaller() override {} TestNavigationThrottle* navigation_throttle() { return navigation_throttle_; } @@ -244,11 +246,11 @@ std::unique_ptr<NavigationThrottle> throttle(new TestNavigationThrottle( handle, will_start_result_, will_redirect_result_, will_process_result_, base::Bind(&TestNavigationThrottleInstaller::DidCallWillStartRequest, - base::Unretained(this)), + weak_factory_.GetWeakPtr()), base::Bind(&TestNavigationThrottleInstaller::DidCallWillRedirectRequest, - base::Unretained(this)), + weak_factory_.GetWeakPtr()), base::Bind(&TestNavigationThrottleInstaller::DidCallWillProcessResponse, - base::Unretained(this)))); + weak_factory_.GetWeakPtr()))); navigation_throttle_ = static_cast<TestNavigationThrottle*>(throttle.get()); handle->RegisterThrottleForTesting(std::move(throttle)); } @@ -289,6 +291,10 @@ scoped_refptr<MessageLoopRunner> will_start_loop_runner_; scoped_refptr<MessageLoopRunner> will_redirect_loop_runner_; scoped_refptr<MessageLoopRunner> will_process_loop_runner_; + + // The throttle installer can be deleted before all tasks posted by its + // throttles are run, so it must be referenced via weak pointers. + base::WeakPtrFactory<TestNavigationThrottleInstaller> weak_factory_; }; // Records all navigation start URLs from the WebContents.
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc index 5476991..1ccb4d4c 100644 --- a/content/browser/media/capture/desktop_capture_device.cc +++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -64,7 +64,7 @@ #if defined(OS_WIN) const base::Feature kDirectXCapturer{"DirectXCapturer", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; #endif class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc index c0862f51..029a9de9 100644 --- a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -38,7 +38,7 @@ #include "ppapi/host/ppapi_host.h" #include "ppapi/host/resource_host.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/tcp_socket_resource_base.h" +#include "ppapi/proxy/tcp_socket_resource_constants.h" #include "ppapi/shared_impl/private/net_address_private_impl.h" #if defined(OS_CHROMEOS) @@ -47,7 +47,7 @@ using ppapi::NetAddressPrivateImpl; using ppapi::host::NetErrorToPepperError; -using ppapi::proxy::TCPSocketResourceBase; +using ppapi::proxy::TCPSocketResourceConstants; using ppapi::TCPSocketState; using ppapi::TCPSocketVersion; @@ -369,7 +369,7 @@ if (read_buffer_.get()) return PP_ERROR_INPROGRESS; if (bytes_to_read <= 0 || - bytes_to_read > TCPSocketResourceBase::kMaxReadSize) { + bytes_to_read > TCPSocketResourceConstants::kMaxReadSize) { return PP_ERROR_BADARGUMENT; } @@ -412,7 +412,8 @@ size_t data_size = data.size(); if (data_size == 0 || - data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) { + data_size > + static_cast<size_t>(TCPSocketResourceConstants::kMaxWriteSize)) { return PP_ERROR_BADARGUMENT; } @@ -524,9 +525,8 @@ } case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE: { int32_t integer_value = 0; - if (!value.GetInt32(&integer_value) || - integer_value <= 0 || - integer_value > TCPSocketResourceBase::kMaxSendBufferSize) + if (!value.GetInt32(&integer_value) || integer_value <= 0 || + integer_value > TCPSocketResourceConstants::kMaxSendBufferSize) return PP_ERROR_BADARGUMENT; // If the socket is already connected, proxy the value to TCPSocket. @@ -542,9 +542,8 @@ } case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: { int32_t integer_value = 0; - if (!value.GetInt32(&integer_value) || - integer_value <= 0 || - integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize) + if (!value.GetInt32(&integer_value) || integer_value <= 0 || + integer_value > TCPSocketResourceConstants::kMaxReceiveBufferSize) return PP_ERROR_BADARGUMENT; // If the socket is already connected, proxy the value to TCPSocket.
diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc index 132a4588..08491b97 100644 --- a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -31,8 +31,7 @@ #include "ppapi/host/ppapi_host.h" #include "ppapi/host/resource_host.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/udp_socket_filter.h" -#include "ppapi/proxy/udp_socket_resource_base.h" +#include "ppapi/proxy/udp_socket_resource_constants.h" #include "ppapi/shared_impl/private/net_address_private_impl.h" #include "ppapi/shared_impl/socket_option_data.h" @@ -42,8 +41,7 @@ using ppapi::NetAddressPrivateImpl; using ppapi::host::NetErrorToPepperError; -using ppapi::proxy::UDPSocketFilter; -using ppapi::proxy::UDPSocketResourceBase; +using ppapi::proxy::UDPSocketResourceConstants; namespace { @@ -76,7 +74,8 @@ multicast_ttl_(0), can_use_multicast_(PP_ERROR_FAILED), closed_(false), - remaining_recv_slots_(UDPSocketFilter::kPluginReceiveBufferSlots), + remaining_recv_slots_( + UDPSocketResourceConstants::kPluginReceiveBufferSlots), external_plugin_(host->external_plugin()), private_api_(private_api), render_process_id_(0), @@ -189,7 +188,7 @@ case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: { int32_t integer_value = 0; if (!value.GetInt32(&integer_value) || integer_value <= 0 || - integer_value > UDPSocketResourceBase::kMaxSendBufferSize) + integer_value > UDPSocketResourceConstants::kMaxSendBufferSize) return PP_ERROR_BADARGUMENT; // If the socket is already bound, proxy the value to UDPSocket. @@ -206,7 +205,7 @@ case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: { int32_t integer_value = 0; if (!value.GetInt32(&integer_value) || integer_value <= 0 || - integer_value > UDPSocketFilter::kMaxReceiveBufferSize) + integer_value > UDPSocketResourceConstants::kMaxReceiveBufferSize) return PP_ERROR_BADARGUMENT; // If the socket is already bound, proxy the value to UDPSocket. @@ -340,7 +339,8 @@ const ppapi::host::HostMessageContext* context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (remaining_recv_slots_ < UDPSocketFilter::kPluginReceiveBufferSlots) { + if (remaining_recv_slots_ < + UDPSocketResourceConstants::kPluginReceiveBufferSlots) { remaining_recv_slots_++; } @@ -553,7 +553,8 @@ DCHECK(!recvfrom_buffer_.get()); DCHECK_GT(remaining_recv_slots_, 0u); - recvfrom_buffer_ = new net::IOBuffer(UDPSocketFilter::kMaxReadSize); + recvfrom_buffer_ = + new net::IOBuffer(UDPSocketResourceConstants::kMaxReadSize); // Use base::Unretained(this), so that the lifespan of this object doesn't // have to last until the callback is called. @@ -561,7 +562,8 @@ // object gets destroyed (and so does |socket_|), the callback won't be // called. int net_result = socket_->RecvFrom( - recvfrom_buffer_.get(), UDPSocketFilter::kMaxReadSize, &recvfrom_address_, + recvfrom_buffer_.get(), UDPSocketResourceConstants::kMaxReadSize, + &recvfrom_address_, base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted, base::Unretained(this))); if (net_result != net::ERR_IO_PENDING) @@ -582,7 +584,8 @@ size_t num_bytes = data.size(); if (num_bytes == 0 || - num_bytes > static_cast<size_t>(UDPSocketResourceBase::kMaxWriteSize)) { + num_bytes > + static_cast<size_t>(UDPSocketResourceConstants::kMaxWriteSize)) { // Size of |data| is checked on the plugin side. NOTREACHED(); SendSendToError(context, PP_ERROR_BADARGUMENT); @@ -602,7 +605,7 @@ // Make sure a malicious plugin can't queue up an unlimited number of buffers. size_t num_pending_sends = pending_sends_.size(); - if (num_pending_sends == UDPSocketResourceBase::kPluginSendBufferSlots) { + if (num_pending_sends == UDPSocketResourceConstants::kPluginSendBufferSlots) { SendSendToError(context, PP_ERROR_FAILED); return; }
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 2339da0..46b56be6 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -475,7 +475,7 @@ if (enable_plugins) { deps += [ - "//ppapi/proxy", + "//ppapi/proxy:ipc", "//ppapi/shared_impl", ] } else {
diff --git a/content/common/dom_storage/OWNERS b/content/common/dom_storage/OWNERS index 924fa74..7b0a1fd 100644 --- a/content/common/dom_storage/OWNERS +++ b/content/common/dom_storage/OWNERS
@@ -1,5 +1,8 @@ -marja@chromium.org michaeln@chromium.org +mek@chromium.org per-file *_messages*.h=set noparent per-file *_messages*.h=file://ipc/SECURITY_OWNERS + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage>DOMStorage
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java index d15a9ca..23534fe 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
@@ -177,13 +177,18 @@ boundToUs = mService.bindToCaller(); } catch (RemoteException ex) { } - if (!boundToUs) { - if (mStartCallback != null) { + + if (mStartCallback != null) { + if (boundToUs) { + mStartCallback.onChildStarted(); + } else { mStartCallback.onChildStartFailed(); } + mStartCallback = null; + } + + if (!boundToUs) { return; - } else if (mStartCallback != null) { - mStartCallback.onChildStarted(); } // Run the setup if the connection parameters have already been provided. If
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 ce2ee82..9f97f23 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
@@ -964,6 +964,14 @@ public boolean onTouchEvent(MotionEvent event) { // TODO(mustaq): Should we include MotionEvent.TOOL_TYPE_STYLUS here? // crbug.com/592082 + if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) { + // Mouse button info is incomplete on L and below + int apiVersion = Build.VERSION.SDK_INT; + if (apiVersion >= android.os.Build.VERSION_CODES.M) { + return sendMouseEvent(event); + } + } + final boolean isTouchHandleEvent = false; return sendTouchEvent(event, isTouchHandleEvent); } @@ -1582,6 +1590,13 @@ event.getAxisValue(MotionEvent.AXIS_VSCROLL), mRenderCoordinates.getWheelScrollFactor()); return true; + case MotionEvent.ACTION_BUTTON_PRESS: + case MotionEvent.ACTION_BUTTON_RELEASE: + // TODO(mustaq): Should we include MotionEvent.TOOL_TYPE_STYLUS here? + // crbug.com/592082 + if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) { + return sendMouseEvent(event); + } } } else if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { if (mJoystickScrollProvider.onMotion(event)) return true;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java index d6ae7c6..5f1a34b 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
@@ -399,6 +399,8 @@ } }); + triggerConnectionSetup((ChildProcessConnectionImpl) conn); + assertEquals(0, conn.getServiceNumber()); assertEquals(-1, conn.getPid()); // PID gets set to -1 if service is already bound.
diff --git a/content/public/test/test_navigation_observer.cc b/content/public/test/test_navigation_observer.cc index 6f48b2f2..dcaf956 100644 --- a/content/public/test/test_navigation_observer.cc +++ b/content/public/test/test_navigation_observer.cc
@@ -79,32 +79,23 @@ TestNavigationObserver::TestNavigationObserver( WebContents* web_contents, - int number_of_navigations) + int number_of_navigations, + MessageLoopRunner::QuitMode quit_mode) : navigation_started_(false), navigations_completed_(0), number_of_navigations_(number_of_navigations), - message_loop_runner_(new MessageLoopRunner), + message_loop_runner_(new MessageLoopRunner(quit_mode)), web_contents_created_callback_( - base::Bind( - &TestNavigationObserver::OnWebContentsCreated, - base::Unretained(this))) { + base::Bind(&TestNavigationObserver::OnWebContentsCreated, + base::Unretained(this))) { if (web_contents) RegisterAsObserver(web_contents); } TestNavigationObserver::TestNavigationObserver( - WebContents* web_contents) - : navigation_started_(false), - navigations_completed_(0), - number_of_navigations_(1), - message_loop_runner_(new MessageLoopRunner), - web_contents_created_callback_( - base::Bind( - &TestNavigationObserver::OnWebContentsCreated, - base::Unretained(this))) { - if (web_contents) - RegisterAsObserver(web_contents); -} + WebContents* web_contents, + MessageLoopRunner::QuitMode quit_mode) + : TestNavigationObserver(web_contents, 1, quit_mode) {} TestNavigationObserver::~TestNavigationObserver() { StopWatchingNewWebContents();
diff --git a/content/public/test/test_navigation_observer.h b/content/public/test/test_navigation_observer.h index 93091ca..6409486 100644 --- a/content/public/test/test_navigation_observer.h +++ b/content/public/test/test_navigation_observer.h
@@ -27,9 +27,13 @@ // Create and register a new TestNavigationObserver against the // |web_contents|. TestNavigationObserver(WebContents* web_contents, - int number_of_navigations); + int number_of_navigations, + MessageLoopRunner::QuitMode quit_mode = + MessageLoopRunner::QuitMode::IMMEDIATE); // Like above but waits for one navigation. - explicit TestNavigationObserver(WebContents* web_contents); + explicit TestNavigationObserver(WebContents* web_contents, + MessageLoopRunner::QuitMode quit_mode = + MessageLoopRunner::QuitMode::IMMEDIATE); virtual ~TestNavigationObserver();
diff --git a/content/renderer/dom_storage/OWNERS b/content/renderer/dom_storage/OWNERS index 0bc093f..f3d5983 100644 --- a/content/renderer/dom_storage/OWNERS +++ b/content/renderer/dom_storage/OWNERS
@@ -1,8 +1,8 @@ michaeln@chromium.org +mek@chromium.org jsbell@chromium.org -marja@chromium.org -# Please include michaeln@ or marja@ if you make any functional/runtime changes. +# Please include michaeln@ or mek@ if you make any functional/runtime changes. # TEAM: storage-dev@chromium.org # COMPONENT: Blink>Storage>DOMStorage
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index f32cf8e3..e0013d70 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -5175,10 +5175,13 @@ request_params.has_user_gesture ? new blink::WebScopedUserGesture(frame_) : nullptr); + browser_side_navigation_pending_ = false; + NavigateInternal(common_params, StartNavigationParams(), request_params, std::move(stream_override)); - browser_side_navigation_pending_ = false; + // Don't add code after this since NavigateInternal may have destroyed this + // RenderFrameImpl. } // PlzNavigate
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 3a069ffe..af20071 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -352,6 +352,8 @@ self.Fail('conformance/textures/misc/' + 'copytexsubimage2d-large-partial-copy-corruption.html', ['win', 'intel', 'passthrough', 'd3d11'], bug=602688) + self.Flaky('conformance/textures/misc/copytexsubimage2d-subrects.html', + ['win10', 'intel', 'passthrough', 'd3d11'], bug=685232) # Mac failures self.Flaky('conformance/extensions/oes-texture-float-with-video.html', @@ -377,6 +379,9 @@ ['mac', ('nvidia', 0xfe9)], bug=635081) self.Fail('conformance/textures/misc/tex-input-validation.html', ['mac', ('nvidia', 0xfe9)], bug=635081) + self.Flaky('conformance/uniforms/' + + 'no-over-optimization-on-uniform-array-12.html', + ['mac', ('nvidia', 0xfe9)], bug=684903) # Mac ASAN only self.Fail(
diff --git a/ios/BUILD.gn b/ios/BUILD.gn index 79a7f39..98cb99a 100644 --- a/ios/BUILD.gn +++ b/ios/BUILD.gn
@@ -31,6 +31,7 @@ "//ios/clean/chrome/app:chrome_clean_skeleton", "//ios/showcase", "//ios/web/shell:ios_web_shell", + "//ios/web_view/shell:ios_web_view_shell", # List all the test targets that need to be build on iOS by default. "//ios/chrome/test:all_tests",
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm index dc8981e9..266f54d5 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -204,12 +204,7 @@ // Check that the error page is visible. void CheckErrorPageIsVisible() { - // The DNS error page is static HTML content, so it isn't part of the webview - // owned by the webstate. - id<GREYMatcher> webViewMatcher = - web::WebViewInWebState(chrome_test_util::GetCurrentWebState()); - [[EarlGrey selectElementWithMatcher:webViewMatcher] - assertWithMatcher:grey_nil()]; + // The DNS error page is static HTML content. NSString* const kError = l10n_util::GetNSString(IDS_ERRORPAGES_HEADING_NOT_AVAILABLE); [[EarlGrey @@ -515,8 +510,7 @@ // Verify correct recording of metrics when the reloading of an evicted tab // fails. -// TODO(crbug.com/684987): Re-enable this test. -- (void)DISABLED_testEvictedTabReloadFailure { +- (void)testEvictedTabReloadFailure { web::test::SetUpFileBasedHttpServer(); chrome_test_util::HistogramTester histogramTester; FailureBlock failureBlock = ^(NSString* error) {
diff --git a/ios/chrome/browser/passwords/resources/password_controller.js b/ios/chrome/browser/passwords/resources/password_controller.js index 6599b25..7c4b8b9c 100644 --- a/ios/chrome/browser/passwords/resources/password_controller.js +++ b/ios/chrome/browser/passwords/resources/password_controller.js
@@ -214,7 +214,12 @@ */ __gCrWeb.fillPasswordFormWithData = function(formData, username, password, win, opt_normalizedOrigin) { - var doc = win.document; + var doc = null; + + try { + doc = win.document; + } catch(e) { + } // If unable to read the 'document' property from a frame in a different // origin, do nothing.
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.cc b/ios/chrome/browser/reading_list/reading_list_download_service.cc index 6cc7c6c..32e0914 100644 --- a/ios/chrome/browser/reading_list/reading_list_download_service.cc +++ b/ios/chrome/browser/reading_list/reading_list_download_service.cc
@@ -7,7 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/files/file_enumerator.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "components/reading_list/ios/offline_url_utils.h" @@ -82,7 +84,7 @@ void ReadingListDownloadService::ReadingListModelLoaded( const ReadingListModel* model) { DCHECK_EQ(reading_list_model_, model); - DownloadAllEntries(); + SyncWithModel(); } void ReadingListDownloadService::ReadingListWillRemoveEntry( @@ -117,9 +119,49 @@ } } -void ReadingListDownloadService::DownloadAllEntries() { +void ReadingListDownloadService::SyncWithModel() { DCHECK(reading_list_model_->loaded()); + std::set<std::string> processed_directories; + std::set<GURL> unprocessed_entries; for (const auto& url : reading_list_model_->Keys()) { + const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url); + switch (entry->DistilledState()) { + case ReadingListEntry::PROCESSED: + processed_directories.insert(reading_list::OfflineURLDirectoryID(url)); + break; + case ReadingListEntry::WAITING: + case ReadingListEntry::PROCESSING: + case ReadingListEntry::WILL_RETRY: + unprocessed_entries.insert(url); + break; + case ReadingListEntry::ERROR: + break; + } + } + web::WebThread::PostTaskAndReply( + web::WebThread::FILE, FROM_HERE, + base::Bind(&ReadingListDownloadService::CleanUpFiles, + base::Unretained(this), processed_directories), + base::Bind(&ReadingListDownloadService::DownloadUnprocessedEntries, + base::Unretained(this), unprocessed_entries)); +} + +void ReadingListDownloadService::CleanUpFiles( + const std::set<std::string>& processed_directories) { + base::FileEnumerator file_enumerator(OfflineRoot(), false, + base::FileEnumerator::DIRECTORIES); + for (base::FilePath sub_directory = file_enumerator.Next(); + !sub_directory.empty(); sub_directory = file_enumerator.Next()) { + std::string directory_name = sub_directory.BaseName().value(); + if (!processed_directories.count(directory_name)) { + base::DeleteFile(sub_directory, true); + } + } +} + +void ReadingListDownloadService::DownloadUnprocessedEntries( + const std::set<GURL>& unprocessed_entries) { + for (const GURL& url : unprocessed_entries) { this->ScheduleDownloadEntry(url); } }
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.h b/ios/chrome/browser/reading_list/reading_list_download_service.h index 19b68f0..bbc1c8f 100644 --- a/ios/chrome/browser/reading_list/reading_list_download_service.h +++ b/ios/chrome/browser/reading_list/reading_list_download_service.h
@@ -27,9 +27,9 @@ } // Observes the reading list and downloads offline versions of its articles. -// Any calls made to DownloadAllEntries/DownloadEntry before the model is -// loaded will be ignored. When the model is loaded, DownloadAllEntries will be -// called automatically. +// Any calls made to DownloadEntry before the model is loaded will be ignored. +// When the model is loaded, offline directory is automatically synced with the +// entries in the model. class ReadingListDownloadService : public KeyedService, public ReadingListModelObserver, @@ -65,12 +65,21 @@ const GURL& url) override; private: - // Tries to save offline versions of all entries in the reading list that are - // not yet saved. Must only be called after reading list model is loaded. - void DownloadAllEntries(); - // Processes a new entry and schedule a download if needed. + // Checks the model and determines which entries are processed and which + // entries need to be processed. + // Initiates a cleanup of |OfflineRoot()| directory removing sub_directories + // not corresponding to a processed ReadingListEntry. + // Schedules unprocessed entries for distillation. + void SyncWithModel(); + // Scans |OfflineRoot()| directory and deletes all subdirectories not listed + // in |directories_to_keep|. + // Must be called on File thread. + void CleanUpFiles(const std::set<std::string>& directories_to_keep); + // Schedules all entries in |unprocessed_entries| for distillation. + void DownloadUnprocessedEntries(const std::set<GURL>& unprocessed_entries); + // Processes a new entry and schedules a download if needed. void ProcessNewEntry(const GURL& url); - // Schedule a download of an offline version of the reading list entry, + // Schedules a download of an offline version of the reading list entry, // according to the delay of the entry. Must only be called after reading list // model is loaded. void ScheduleDownloadEntry(const GURL& url);
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index e3ecd40..3ac08a4 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -22,7 +22,6 @@ "//components/signin/ios/browser", "//components/sync_sessions", "//ios/net", - "//ios/shared/chrome/browser/tabs", "//ios/web", "//ui/base", ]
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h index b108643a..96e137f5 100644 --- a/ios/chrome/browser/tabs/tab.h +++ b/ios/chrome/browser/tabs/tab.h
@@ -12,7 +12,6 @@ #import "components/signin/ios/browser/manage_accounts_delegate.h" #include "ios/net/request_tracker.h" -#import "ios/shared/chrome/browser/tabs/web_state_handle.h" #import "ios/web/public/web_state/ui/crw_web_delegate.h" #include "ui/base/page_transition_types.h" @@ -64,6 +63,7 @@ class NavigationManagerImpl; struct Referrer; class WebState; +class WebStateImpl; } // Notification sent by a Tab when it starts to load a new URL. This @@ -98,8 +98,7 @@ // desktop Chrome's TabContents in that it encapsulates rendering. Acts as the // delegate for the CRWWebController in order to process info about pages having // loaded. -@interface Tab - : NSObject<CRWWebDelegate, ManageAccountsDelegate, WebStateHandle> +@interface Tab : NSObject<CRWWebDelegate, ManageAccountsDelegate> // Browser state associated with this Tab. @property(nonatomic, readonly) ios::ChromeBrowserState* browserState; @@ -127,6 +126,10 @@ // |YES| if snapshot overlay should load from the grey image cache. @property(nonatomic, assign) BOOL useGreyImageCache; +// webStateImpl is deprecated: use webState instead. +@property(nonatomic, readonly) web::WebStateImpl* webStateImpl; +@property(nonatomic, readonly) web::WebState* webState; + @property(nonatomic, readonly) CRWWebController* webController; @property(nonatomic, readonly) PasswordController* passwordController; @property(nonatomic, readonly) BOOL canGoBack;
diff --git a/ios/chrome/browser/tabs/tab_model.h b/ios/chrome/browser/tabs/tab_model.h index bb888ac..e2e0a8fe 100644 --- a/ios/chrome/browser/tabs/tab_model.h +++ b/ios/chrome/browser/tabs/tab_model.h
@@ -10,8 +10,6 @@ #include <memory> -#import "ios/chrome/browser/tabs/tab.h" -#import "ios/shared/chrome/browser/tabs/web_state_list.h" #import "ios/web/public/navigation_manager.h" #include "ui/base/page_transition_types.h" @@ -19,6 +17,7 @@ class SessionID; @class SessionServiceIOS; @class SessionWindowIOS; +@class Tab; @protocol TabModelObserver; class TabModelSyncedWindowDelegate; class TabUsageRecorder; @@ -82,7 +81,7 @@ // The model knows about the currently selected tab in order to maintain // consistency between multiple views that need the current tab to be // synchronized. -@interface TabModel : WebStateList<Tab*> +@interface TabModel : NSObject<NSFastEnumeration> // Currently active tab. @property(nonatomic, weak) Tab* currentTab; @@ -113,6 +112,9 @@ // NO if the model has at least one tab. @property(nonatomic, readonly, getter=isEmpty) BOOL empty; +// Determines the number of tabs in the model. +@property(nonatomic, readonly) NSUInteger count; + // Initializes tabs from a restored session. |-setCurrentTab| needs to be called // in order to display the views associated with the tabs. Waits until the views // are ready. |browserState| cannot be nil. |service| cannot be nil; this class
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm index efc46db..de7719be 100644 --- a/ios/chrome/browser/tabs/tab_model.mm +++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -66,24 +66,23 @@ namespace { // Updates CRWSessionCertificatePolicyManager's certificate policy cache. -void UpdateCertificatePolicyCacheFromWebState(web::WebStateImpl* web_state) { +void UpdateCertificatePolicyCacheFromWebState(web::WebStateImpl* webState) { DCHECK([NSThread isMainThread]); - DCHECK(web_state); + DCHECK(webState); scoped_refptr<web::CertificatePolicyCache> policy_cache = - web::BrowserState::GetCertificatePolicyCache( - web_state->GetBrowserState()); + web::BrowserState::GetCertificatePolicyCache(webState->GetBrowserState()); CRWSessionController* controller = - web_state->GetNavigationManagerImpl().GetSessionController(); + webState->GetNavigationManagerImpl().GetSessionController(); [[controller sessionCertificatePolicyManager] updateCertificatePolicyCache:policy_cache]; } // Populates the certificate policy cache based on the current entries of the // given tabs. -void RestoreCertificatePolicyCacheFromTabs(WebStateList* web_state_list) { +void RestoreCertificatePolicyCacheFromTabs(NSArray* tabs) { DCHECK([NSThread isMainThread]); - for (id<WebStateHandle> web_state in web_state_list) { - UpdateCertificatePolicyCacheFromWebState(web_state.webStateImpl); + for (Tab* tab in tabs) { + UpdateCertificatePolicyCacheFromWebState(tab.webStateImpl); } } @@ -91,29 +90,13 @@ // those for the current entries of the given tabs. void CleanCertificatePolicyCache( scoped_refptr<web::CertificatePolicyCache> policy_cache, - WebStateList* web_state_list) { + NSArray* tabs) { DCHECK_CURRENTLY_ON(web::WebThread::IO); DCHECK(policy_cache); policy_cache->ClearCertificatePolicies(); web::WebThread::PostTask( web::WebThread::UI, FROM_HERE, - base::Bind(&RestoreCertificatePolicyCacheFromTabs, web_state_list)); -} - -// Creates a NSArray<Tab*>* with elements from |web_state_list| falling into -// |range|. This is for compatibility with TabUsageRecorder existing API. That -// API will be refactored in later CL and this method removed, see -// http://crbug.com/681867 for details. -NSArray<Tab*>* GetTabsFromWebStateList(WebStateList* web_state_list, - NSRange range) { - base::scoped_nsobject<NSMutableArray<Tab*>> mutableArray( - [[NSMutableArray alloc] initWithCapacity:range.length]); - - for (NSUInteger ii = range.location; NSLocationInRange(ii, range); ++ii) { - [mutableArray addObject:[web_state_list webStateAtIndex:ii]]; - } - - return [[mutableArray copy] autorelease]; + base::Bind(&RestoreCertificatePolicyCacheFromTabs, tabs)); } } // anonymous namespace @@ -124,6 +107,8 @@ @end @interface TabModel ()<TabUsageRecorderDelegate> { + // Array of |Tab| objects. + base::scoped_nsobject<NSMutableArray> _tabs; // Maintains policy for where new tabs go and the selection when a tab // is removed. base::scoped_nsobject<TabModelOrderController> _orderController; @@ -212,7 +197,7 @@ } - (void)setCurrentTab:(Tab*)newTab { - DCHECK([self containsWebState:newTab]); + DCHECK([_tabs containsObject:newTab]); if (_currentTab != newTab) { base::RecordAction(base::UserMetricsAction("MobileTabSwitched")); [self updateSnapshotCache:newTab]; @@ -239,6 +224,10 @@ return self.count == 0; } +- (NSUInteger)count { + return [_tabs count]; +} + - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window sessionService:(SessionServiceIOS*)service browserState:(ios::ChromeBrowserState*)browserState { @@ -262,6 +251,7 @@ } _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self)); + _tabs.reset([[NSMutableArray alloc] init]); NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; if (window) { while (window.unclaimedSessions) { @@ -275,20 +265,17 @@ [[Tab alloc] initWithWebState:std::move(webState) model:self]); [tab webController].usePlaceholderOverlay = YES; [tab fetchFavicon]; - [self addWebState:tab]; + [_tabs addObject:tab]; TabParentingGlobalObserver::GetInstance()->OnTabParented( [tab webStateImpl]); } - if (self.count) { - DCHECK(window.selectedIndex < self.count); + if ([_tabs count]) { + DCHECK(window.selectedIndex < [_tabs count]); _currentTab.reset([self tabAtIndex:window.selectedIndex]); DCHECK(_currentTab); - if (_tabUsageRecorder) { - _tabUsageRecorder->InitialRestoredTabs( - _currentTab, - GetTabsFromWebStateList(self, NSMakeRange(0, self.count))); - } + if (_tabUsageRecorder) + _tabUsageRecorder->InitialRestoredTabs(_currentTab, _tabs); // Perform initializations for affiliated objects which update the // session information related to the current tab. [_currentTab updateLastVisitedTimestamp]; @@ -330,7 +317,7 @@ DCHECK(window); if (!window.unclaimedSessions) return NO; - size_t oldCount = self.count; + size_t oldCount = [_tabs count]; size_t index = oldCount; while (window.unclaimedSessions) { std::unique_ptr<web::WebStateImpl> webState = [window nextSession]; @@ -341,36 +328,34 @@ // |webState| is invalid, so we need to get the webstate from |tab|. UpdateCertificatePolicyCacheFromWebState(tab.webStateImpl); } - DCHECK(self.count > oldCount); + DCHECK([_tabs count] > oldCount); // If any tab was restored, the saved selected tab must be selected. - if (self.count > oldCount) { + if ([_tabs count] > oldCount) { NSUInteger selectedIndex = window.selectedIndex; if (selectedIndex == NSNotFound) selectedIndex = oldCount; else selectedIndex += oldCount; - DCHECK(selectedIndex < self.count); + DCHECK(selectedIndex < [_tabs count]); Tab* newTab = [self tabAtIndex:selectedIndex]; DCHECK(newTab); [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES]; // If there was only one tab and it was the new tab page, clobber it. if (oldCount == 1) { - Tab* tab = [self firstWebState]; + Tab* tab = [_tabs objectAtIndex:0]; if (tab.url == GURL(kChromeUINewTabURL)) { [self closeTab:tab]; - if (_tabUsageRecorder) { - _tabUsageRecorder->InitialRestoredTabs( - _currentTab, - GetTabsFromWebStateList(self, NSMakeRange(0, self.count))); - } + if (_tabUsageRecorder) + _tabUsageRecorder->InitialRestoredTabs(_currentTab, _tabs); return YES; } } if (_tabUsageRecorder) { _tabUsageRecorder->InitialRestoredTabs( - _currentTab, GetTabsFromWebStateList( - self, NSMakeRange(oldCount, self.count - oldCount))); + _currentTab, + [_tabs subarrayWithRange:NSMakeRange(oldCount, + [_tabs count] - oldCount)]); } } return NO; @@ -379,7 +364,7 @@ - (void)saveSessionImmediately:(BOOL)immediately { // Do nothing if there are tabs in the model but no selected tab. This is // a transitional state. - if ((!_currentTab && self.count) || !_browserState) + if ((!_currentTab && [_tabs count]) || !_browserState) return; [_sessionService saveWindow:self.windowForSavingSession forBrowserState:_browserState @@ -387,17 +372,17 @@ } - (Tab*)tabAtIndex:(NSUInteger)index { - return [self webStateAtIndex:index]; + return [_tabs objectAtIndex:index]; } - (NSUInteger)indexOfTab:(Tab*)tab { - return [self indexOfWebState:tab]; + return [_tabs indexOfObject:tab]; } - (Tab*)tabWithWindowName:(NSString*)windowName { if (!windowName) return nil; - for (Tab* tab in self) { + for (Tab* tab in _tabs.get()) { if ([windowName isEqualToString:tab.windowName]) { return tab; } @@ -416,8 +401,8 @@ if (startIndex == NSNotFound) return nil; NSString* parentID = tab.tabId; - for (NSUInteger i = startIndex + 1; i < self.count; ++i) { - Tab* current = [self webStateAtIndex:i]; + for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) { + Tab* current = [_tabs objectAtIndex:i]; DCHECK([current navigationManager]); CRWSessionController* sessionController = [current navigationManager]->GetSessionController(); @@ -442,7 +427,7 @@ DCHECK([tab navigationManager]); NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex(); for (NSUInteger i = 0; i < stopIndex; ++i) { - Tab* tabToCheck = [self webStateAtIndex:i]; + Tab* tabToCheck = [_tabs objectAtIndex:i]; DCHECK([tabToCheck navigationManager]); CRWSessionController* sessionController = [tabToCheck navigationManager]->GetSessionController(); @@ -469,8 +454,8 @@ // tabs whose opener's id and opener's navigation index match. The navigation // index is used in addition to the session id to detect navigations changes // within the same session. - for (NSUInteger i = startIndex + 1; i < self.count; ++i) { - Tab* tabToCheck = [self webStateAtIndex:i]; + for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) { + Tab* tabToCheck = [_tabs objectAtIndex:i]; DCHECK([tabToCheck navigationManager]); CRWSessionController* sessionController = [tabToCheck navigationManager]->GetSessionController(); @@ -490,7 +475,7 @@ NSString* openerId = [tab navigationManager]->GetSessionController().openerId; if (!openerId.length) // Short-circuit if opener is empty. return nil; - for (Tab* iteratedTab in self) { + for (Tab* iteratedTab in _tabs.get()) { if ([iteratedTab.tabId isEqualToString:openerId]) return iteratedTab; } @@ -583,9 +568,9 @@ - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { DCHECK(tab); - DCHECK(index <= self.count); + DCHECK(index <= [_tabs count]); [tab fetchFavicon]; - [self insertWebState:tab atIndex:index]; + [_tabs insertObject:tab atIndex:index]; [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO]; [_observers tabModelDidChangeTabCount:self]; @@ -609,8 +594,8 @@ } base::scoped_nsobject<Tab> tabSaver([tab retain]); - [self removeWebState:tab]; - [self insertWebState:tab atIndex:toIndex]; + [_tabs removeObject:tab]; + [_tabs insertObject:tab atIndex:toIndex]; [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex]; } @@ -623,7 +608,7 @@ base::scoped_nsobject<Tab> tabSaver([oldTab retain]); [newTab fetchFavicon]; - [self replaceWebStateAtIndex:index withWebState:newTab]; + [_tabs replaceObjectAtIndex:index withObject:newTab]; [newTab setParentTabModel:self]; [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index]; @@ -641,8 +626,8 @@ } - (void)closeTabAtIndex:(NSUInteger)index { - DCHECK(index < self.count); - [self closeTab:[self webStateAtIndex:index]]; + DCHECK(index < [_tabs count]); + [self closeTab:[_tabs objectAtIndex:index]]; } - (void)closeTab:(Tab*)tab { @@ -662,7 +647,7 @@ } - (void)haltAllTabs { - for (Tab* tab in self) { + for (Tab* tab in _tabs.get()) { [tab terminateNetworkActivity]; } } @@ -699,7 +684,7 @@ } - (void)resetAllWebViews { - for (Tab* tab in self) { + for (Tab* tab in _tabs.get()) { [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)]; } } @@ -708,7 +693,7 @@ if (webUsageEnabled_ == webUsageEnabled) return; webUsageEnabled_ = webUsageEnabled; - for (Tab* tab in self) { + for (Tab* tab in _tabs.get()) { tab.webUsageEnabled = webUsageEnabled; } } @@ -723,7 +708,7 @@ if (!_browserState) return referencedFiles; // Check the currently open tabs for external files. - for (Tab* tab in self) { + for (Tab* tab in _tabs.get()) { if (UrlIsExternalFileReference(tab.url)) { NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName()); [referencedFiles addObject:fileName]; @@ -760,7 +745,7 @@ // Called when a tab is closing, but before its CRWWebController is destroyed. // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel. - (void)didCloseTab:(Tab*)closedTab { - NSUInteger closedTabIndex = [self indexOfWebState:closedTab]; + NSUInteger closedTabIndex = [_tabs indexOfObject:closedTab]; DCHECK(closedTab); DCHECK(closedTabIndex != NSNotFound); // Let the sessions::TabRestoreService know about that new tab. @@ -780,7 +765,7 @@ Tab* newSelection = [_orderController determineNewSelectedTabFromRemovedTab:closedTab]; base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]); - [self removeWebState:closedTab]; + [_tabs removeObject:closedTab]; // If closing the current tab, clear |_currentTab| before sending any // notification. This avoids various parts of the code getting confused @@ -831,11 +816,20 @@ UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tabCount, 1, 200, 50); } +#pragma mark - NSFastEnumeration + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state + objects:(id*)objects + count:(NSUInteger)count { + return [_tabs countByEnumeratingWithState:state objects:objects count:count]; +} + #pragma mark - TabUsageRecorderDelegate - (NSUInteger)liveTabsCount { NSUInteger count = 0; - for (Tab* tab in self) { + NSArray* tabs = _tabs.get(); + for (Tab* tab in tabs) { if ([tab.webController isViewAlive]) count++; } @@ -854,7 +848,7 @@ // TODO(crbug.com/661986): This could get expensive especially since this // window may never be saved (if another call comes in before the delay). SessionWindowIOS* window = [[[SessionWindowIOS alloc] init] autorelease]; - for (Tab* tab in self) { + for (Tab* tab in _tabs.get()) { DCHECK(tab.webStateImpl); std::unique_ptr<web::WebStateImpl> webStateCopy( tab.webStateImpl->CopyForSessionWindow()); @@ -1019,7 +1013,7 @@ DCHECK(policy_cache); web::WebThread::PostTask( web::WebThread::IO, FROM_HERE, - base::Bind(&CleanCertificatePolicyCache, policy_cache, self)); + base::Bind(&CleanCertificatePolicyCache, policy_cache, _tabs)); if (_tabUsageRecorder) _tabUsageRecorder->AppDidEnterBackground();
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm index 64a1ea0..e43859bc 100644 --- a/ios/chrome/browser/tabs/tab_model_unittest.mm +++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -838,7 +838,6 @@ TEST_F(TabModelTest, PersistSelectionChange) { TestChromeBrowserState::Builder test_cbs_builder; auto chrome_browser_state = test_cbs_builder.Build(); - base::mac::ScopedNSAutoreleasePool pool; NSString* stashPath = base::SysUTF8ToNSString(chrome_browser_state->GetStatePath().value()); @@ -876,7 +875,6 @@ browserState:chrome_browser_state.get()]); EXPECT_EQ(model.get().currentTab, [model tabAtIndex:1]); [model browserStateDestroyed]; - model.reset(); // Clean up. EXPECT_TRUE([[NSFileManager defaultManager] removeItemAtPath:stashPath
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm index 9b599f2..85f18be 100644 --- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm +++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -55,9 +55,7 @@ // Test that when trying to print a page redirected to an unprintable page, a // snackbar explaining that the page cannot be printed is displayed. -// TODO(crbug.com/684987): Re-enable this test. -- (void) - DISABLED_testActivityServiceControllerPrintAfterRedirectionToUnprintablePage { +- (void)testActivityServiceControllerPrintAfterRedirectionToUnprintablePage { std::map<GURL, std::string> responses; const GURL regularPageURL = web::test::HttpServer::MakeUrl("http://choux"); responses[regularPageURL] = "fleur"; @@ -71,10 +69,6 @@ // Open an error page. [ChromeEarlGrey loadURL:ErrorPageResponseProvider::GetDnsFailureUrl()]; - id<GREYMatcher> webViewMatcher = - web::WebViewInWebState(chrome_test_util::GetCurrentWebState()); - [[EarlGrey selectElementWithMatcher:webViewMatcher] - assertWithMatcher:grey_nil()]; NSString* const kError = l10n_util::GetNSString(IDS_ERRORPAGES_HEADING_NOT_AVAILABLE); [[EarlGrey
diff --git a/ios/chrome/browser/ui/error_page_egtest.mm b/ios/chrome/browser/ui/error_page_egtest.mm index 8864a80..7619bfc 100644 --- a/ios/chrome/browser/ui/error_page_egtest.mm +++ b/ios/chrome/browser/ui/error_page_egtest.mm
@@ -44,10 +44,6 @@ - (void)checkErrorPageIsVisible { // The DNS error page is static HTML content, so it isn't part of the webview // owned by the webstate. - id<GREYMatcher> webViewMatcher = - web::WebViewInWebState(chrome_test_util::GetCurrentWebState()); - [[EarlGrey selectElementWithMatcher:webViewMatcher] - assertWithMatcher:grey_nil()]; NSString* const kError = l10n_util::GetNSString(IDS_ERRORPAGES_HEADING_NOT_AVAILABLE); [[EarlGrey selectElementWithMatcher:StaticHtmlViewContainingText(kError)] @@ -70,8 +66,7 @@ #pragma mark - tests // Tests whether the error page is displayed for a bad URL. -// TODO(crbug.com/684987): Re-enable this test. -- (void)DISABLED_testErrorPage { +- (void)testErrorPage { std::unique_ptr<web::DataResponseProvider> provider( new ErrorPageResponseProvider()); web::test::SetUpHttpServer(std::move(provider)); @@ -82,8 +77,7 @@ } // Tests whether the error page is displayed if it is behind a redirect. -// TODO(crbug.com/684987): Re-enable this test. -- (void)DISABLED_testErrorPageRedirect { +- (void)testErrorPageRedirect { std::unique_ptr<web::DataResponseProvider> provider( new ErrorPageResponseProvider()); web::test::SetUpHttpServer(std::move(provider));
diff --git a/ios/chrome/browser/ui/infobars/infobar_view.mm b/ios/chrome/browser/ui/infobars/infobar_view.mm index 1e588e713..a0a79f6 100644 --- a/ios/chrome/browser/ui/infobars/infobar_view.mm +++ b/ios/chrome/browser/ui/infobars/infobar_view.mm
@@ -876,8 +876,10 @@ forState:UIControlStateDisabled]; if (palette) button.get().hasOpaqueBackground = YES; - if (customTitleColor) + if (customTitleColor) { + button.get().tintAdjustmentMode = UIViewTintAdjustmentModeNormal; button.get().customTitleColor = customTitleColor; + } button.get().titleLabel.adjustsFontSizeToFitWidth = YES; button.get().titleLabel.minimumScaleFactor = 0.6f; [button setTitle:message forState:UIControlStateNormal];
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index 715b40e..fd96524b 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -286,6 +286,11 @@ // Takes into account whether or not the mode toggle button is showing. - (CGFloat)tabStripVisibleSpace; +// Shift all of the tab strip subviews by an amount equal to the content offset +// change, which effectively places the subviews back where they were before the +// change, in terms of screen coordinates. +- (void)shiftTabStripSubviews:(CGPoint)oldContentOffset; + // Updates the scroll view's content size based on the current set of tabs and // closing tabs. After updating the content size, repositions views so they // they will appear stationary on screen. @@ -313,6 +318,11 @@ // Returns the minimum tab view width depending on the current layout mode. - (CGFloat)minTabWidth; +// Automatically scroll the tab strip view to keep the newly inserted tab view +// visible. +// This method must be called with a valid |tabIndex|. +- (void)autoScrollForNewTab:(NSUInteger)tabIndex; + // Updates the content offset of the tab strip view in order to keep the // selected tab view visible. // Content offset adjustement is only needed/performed in compact mode or @@ -1169,6 +1179,16 @@ [self updateScrollViewFrameForToggleButton]; } +- (void)shiftTabStripSubviews:(CGPoint)oldContentOffset { + CGFloat dx = [_tabStripView contentOffset].x - oldContentOffset.x; + for (UIView* view in [_tabStripView subviews]) { + CGRect frame = [view frame]; + frame.origin.x += dx; + [view setFrame:frame]; + _targetFrames.AddFrame(view, frame); + } +} + - (void)updateContentSizeAndRepositionViews { // TODO(rohitrao): The following lines are duplicated in // layoutTabStripSubviews. Find a way to consolidate this logic. @@ -1197,19 +1217,10 @@ // will never change if the content size is growing.) // // To handle this without making views appear to jump, shift all of the - // subviews by an amount equal to the size change. This effectively places - // the subviews back where they were before the change, in terms of screen - // coordinates. + // subviews by an amount equal to the size change. CGPoint oldOffset = [_tabStripView contentOffset]; [_tabStripView setContentSize:contentSize]; - - CGFloat dx = [_tabStripView contentOffset].x - oldOffset.x; - for (UIView* view in [_tabStripView subviews]) { - CGRect frame = [view frame]; - frame.origin.x += dx; - [view setFrame:frame]; - _targetFrames.AddFrame(view, frame); - } + [self shiftTabStripSubviews:oldOffset]; } - (CGRect)scrollViewFrameForTab:(TabView*)view { @@ -1252,36 +1263,58 @@ return IsCompactTablet() ? kMinTabWidthForCompactLayout : kMinTabWidth; } +- (void)autoScrollForNewTab:(NSUInteger)tabIndex { + DCHECK_NE(NSNotFound, static_cast<NSInteger>(tabIndex)); + + // The following code calculates the amount of scroll needed to make + // |tabIndex| visible in the "virtual" coordinate system, where root is x=0 + // and it contains all the tabs laid out as if the tabstrip was infinitely + // long. The amount of scroll is calculated as a desired length that it is + // just large enough to contain all the tabs to the left of |tabIndex|, with + // the standard overlap. + if (tabIndex == [_tabArray count] - 1) { + const CGFloat tabStripAvailableSpace = + _tabStripView.frame.size.width - _tabStripView.contentInset.right; + CGPoint oldOffset = [_tabStripView contentOffset]; + if (_tabStripView.contentSize.width > tabStripAvailableSpace) { + CGFloat scrollToPoint = + _tabStripView.contentSize.width - tabStripAvailableSpace; + [_tabStripView setContentOffset:CGPointMake(scrollToPoint, 0)]; + } + + // To handle content offset change without making views appear to jump, + // shift all of the subviews by an amount equal to the size change. + [self shiftTabStripSubviews:oldOffset]; + return; + } + + NSUInteger numNonClosingTabsToLeft = 0; + NSUInteger i = 0; + for (TabView* tab in _tabArray.get()) { + if ([_closingTabs containsObject:tab]) + ++i; + + if (i == tabIndex) + break; + + ++numNonClosingTabsToLeft; + ++i; + } + + const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); + CGRect scrollRect = + CGRectMake(_currentTabWidth * numNonClosingTabsToLeft - + ([self tabOverlap] * (numNonClosingTabsToLeft - 1)), + 0, _currentTabWidth, tabHeight); + [_tabStripView scrollRectToVisible:scrollRect animated:YES]; +} + - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex isNewTab:(BOOL)isNewTab { DCHECK_NE(NSNotFound, static_cast<NSInteger>(tabIndex)); if (experimental_flags::IsTabStripAutoScrollNewTabsEnabled() && isNewTab) { - // The following code calculates the amount of scroll needed to make - // |tabIndex| visible in the "virtual" coordinate system, where root is x=0 - // and it contains all the tabs laid out as if the tabstrip was infinitely - // long. The amount of scroll is calculated as a desired length that it is - // just large enough to contain all the tabs to the left of |tabIndex|, with - // the standard overlap. - NSUInteger numNonClosingTabsToLeft = 0; - NSUInteger i = 0; - for (TabView* tab in _tabArray.get()) { - if ([_closingTabs containsObject:tab]) - ++i; - - if (i == tabIndex) - break; - - ++numNonClosingTabsToLeft; - ++i; - } - - const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); - CGRect scrollRect = - CGRectMake(_currentTabWidth * numNonClosingTabsToLeft - - ([self tabOverlap] * (numNonClosingTabsToLeft - 1)), - 0, _currentTabWidth, tabHeight); - [_tabStripView scrollRectToVisible:scrollRect animated:YES]; + [self autoScrollForNewTab:tabIndex]; return; }
diff --git a/ios/shared/chrome/browser/tabs/BUILD.gn b/ios/shared/chrome/browser/tabs/BUILD.gn deleted file mode 100644 index 834cbc25..0000000 --- a/ios/shared/chrome/browser/tabs/BUILD.gn +++ /dev/null
@@ -1,16 +0,0 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("tabs") { - sources = [ - "web_state_handle.h", - "web_state_list.h", - "web_state_list.mm", - ] - deps = [ - "//base", - ] - libs = [ "Foundation.framework" ] - configs += [ "//build/config/compiler:enable_arc" ] -}
diff --git a/ios/shared/chrome/browser/tabs/web_state_handle.h b/ios/shared/chrome/browser/tabs/web_state_handle.h deleted file mode 100644 index da765b9..0000000 --- a/ios/shared/chrome/browser/tabs/web_state_handle.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_SHARED_CHROME_BROWSER_TABS_WEB_STATE_HANDLE_H_ -#define IOS_SHARED_CHROME_BROWSER_TABS_WEB_STATE_HANDLE_H_ - -namespace web { -class WebState; -class WebStateImpl; -} - -// Wraps a web::WebState instance in an Objective-C instance. Allows using -// Objective-C collection to reference web::WebStates. -@protocol WebStateHandle - -// Returns the wrapped web::WebState. -@property(nonatomic, readonly) web::WebState* webState; - -// Returns the wrapped web::WebState as a web::WebStateImpl. Deprecated, -// use webState instead if possible. -@property(nonatomic, readonly) web::WebStateImpl* webStateImpl; - -@end - -#endif // IOS_SHARED_CHROME_BROWSER_TABS_WEB_STATE_HANDLE_H_
diff --git a/ios/shared/chrome/browser/tabs/web_state_list.h b/ios/shared/chrome/browser/tabs/web_state_list.h deleted file mode 100644 index 5aff6ef9..0000000 --- a/ios/shared/chrome/browser/tabs/web_state_list.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_SHARED_CHROME_BROWSER_TABS_WEB_STATE_LIST_H_ -#define IOS_SHARED_CHROME_BROWSER_TABS_WEB_STATE_LIST_H_ - -#import <Foundation/Foundation.h> - -@protocol WebStateHandle; - -// Clang format incorrectly formats the <__covariant ObjectType> used -// to declare WebStateList as a lighweight generic class. Disable it -// until the underlying issue is fixed (b/34375672). -// clang-format off - -// A generic array of WebStateHandles. -@interface WebStateList<__covariant ObjectType: id<WebStateHandle>> - : NSObject<NSFastEnumeration> - -// The number of objects in the array. -@property(nonatomic, readonly) NSUInteger count; - -// The first WebStateHandle in the array. -@property(nonatomic, readonly) ObjectType firstWebState; - -// Inserts |webState| at the end of the array. -- (void)addWebState:(ObjectType)webState; - -// Inserts |webState| into the array at |index|. -- (void)insertWebState:(ObjectType)webState atIndex:(NSUInteger)index; - -// Replaces the WebStateHandle at |index| with |webState|. -- (void)replaceWebStateAtIndex:(NSUInteger)index - withWebState:(ObjectType)webState; - -// Removes all occurrences of |webState| in the array. -- (void)removeWebState:(ObjectType)webState; - -// Returns YES if |webState| is in the array. -- (BOOL)containsWebState:(ObjectType)webState; - -// Returns the WebStateHandle at |index|. -- (ObjectType)webStateAtIndex:(NSUInteger)index; - -// Returns the lowest index whose value is equal to |webState|. -- (NSUInteger)indexOfWebState:(ObjectType)webState; - -@end - -// clang-format on - -#endif // IOS_SHARED_CHROME_BROWSER_TABS_WEB_STATE_LIST_H_
diff --git a/ios/shared/chrome/browser/tabs/web_state_list.mm b/ios/shared/chrome/browser/tabs/web_state_list.mm deleted file mode 100644 index 2536117..0000000 --- a/ios/shared/chrome/browser/tabs/web_state_list.mm +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/shared/chrome/browser/tabs/web_state_list.h" - -#include "base/logging.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation WebStateList { - NSMutableArray<id<WebStateHandle>>* _list; -} - -#pragma mark - Lifecycle - -- (instancetype)init { - if ((self = [super init])) { - _list = [[NSMutableArray alloc] init]; - } - return self; -} - -#pragma mark - NSFastEnumeration - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state - objects:(id __unsafe_unretained*)buffer - count:(NSUInteger)len { - return [_list countByEnumeratingWithState:state objects:buffer count:len]; -} - -#pragma mark - Properties - -- (NSUInteger)count { - return _list.count; -} - -- (id<WebStateHandle>)firstWebState { - return _list.firstObject; -} - -#pragma mark - Public methods, mutation - -- (void)addWebState:(id<WebStateHandle>)webState { - [_list addObject:webState]; -} - -- (void)insertWebState:(id<WebStateHandle>)webState atIndex:(NSUInteger)index { - [_list insertObject:webState atIndex:index]; -} - -- (void)replaceWebStateAtIndex:(NSUInteger)index - withWebState:(id<WebStateHandle>)webState { - [_list replaceObjectAtIndex:index withObject:webState]; -} - -- (void)removeWebState:(id<WebStateHandle>)webState { - [_list removeObject:webState]; -} - -#pragma mark - Public methods, queries - -- (BOOL)containsWebState:(id<WebStateHandle>)webState { - return [_list containsObject:webState]; -} - -- (id<WebStateHandle>)webStateAtIndex:(NSUInteger)index { - DCHECK_LT(index, _list.count); - return [_list objectAtIndex:index]; -} - -- (NSUInteger)indexOfWebState:(id<WebStateHandle>)webState { - return [_list indexOfObject:webState]; -} - -@end
diff --git a/ios/web/navigation/history_state_operations_inttest.mm b/ios/web/navigation/history_state_operations_inttest.mm index d823e70b..88cf460 100644 --- a/ios/web/navigation/history_state_operations_inttest.mm +++ b/ios/web/navigation/history_state_operations_inttest.mm
@@ -392,3 +392,21 @@ // Verify that the NavigationItem no longer has POST data. EXPECT_FALSE(GetLastCommittedItem()->HasPostData()); } + +// Tests that performing a replaceState() on a page where only the URL fragment +// is updated does not trigger a hashchange event. +TEST_F(HistoryStateOperationsTest, ReplaceStateNoHashChangeEvent) { + // Set up the state parameters and tap the replace state button. + std::string empty_state; + std::string empty_title; + GURL new_url = state_operations_url().Resolve("#hash"); + SetStateParams(empty_state, empty_title, new_url); + ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); + // Verify that url has been replaced. + base::test::ios::WaitUntilCondition(^bool { + return GetLastCommittedItem()->GetURL() == new_url; + }); + // Verify that the hashchange event was not fired. + EXPECT_FALSE(static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()) + ->IsCreatedFromHashChange()); +}
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn new file mode 100644 index 0000000..1755748 --- /dev/null +++ b/ios/web_view/BUILD.gn
@@ -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. + +# Public target that should be used to depend on web_view. Only give access +# to the web_view public headers while still linking with the implementation. +group("web_view") { + public_deps = [ + "//ios/web_view/public", + ] + deps = [ + "//ios/web_view/internal", + ] +}
diff --git a/ios/web_view/DEPS b/ios/web_view/DEPS new file mode 100644 index 0000000..aa6a13b2 --- /dev/null +++ b/ios/web_view/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + # The subdirectories in ios/web_view/ will manually allow their own include + # directories in ios/web_view/ so we disallow all of them. + "-ios/web_view", +]
diff --git a/ios/web_view/OWNERS b/ios/web_view/OWNERS new file mode 100644 index 0000000..7ec8b42 --- /dev/null +++ b/ios/web_view/OWNERS
@@ -0,0 +1,6 @@ +eugenebut@chromium.org +rohitrao@chromium.org + +# These are for the common case of adding or renaming files. If you're doing +# structural changes, please get a review from an OWNER. +per-file BUILD.gn=*
diff --git a/ios/web_view/internal/BUILD.gn b/ios/web_view/internal/BUILD.gn new file mode 100644 index 0000000..61e7e6b --- /dev/null +++ b/ios/web_view/internal/BUILD.gn
@@ -0,0 +1,48 @@ +# 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. + +source_set("internal") { + visibility = [ + "//ios/web_view", + "//ios/web_view/internal/*", + ] + + sources = [ + "criwv.mm", + "criwv_browser_state.h", + "criwv_browser_state.mm", + "criwv_network_delegate.cc", + "criwv_network_delegate.h", + "criwv_url_request_context_getter.h", + "criwv_url_request_context_getter.mm", + "criwv_web_client.h", + "criwv_web_client.mm", + "criwv_web_main_delegate.h", + "criwv_web_main_delegate.mm", + "criwv_web_main_parts.h", + "criwv_web_main_parts.mm", + "criwv_web_view_impl.h", + "criwv_web_view_impl.mm", + "pref_names.cc", + "pref_names.h", + ] + deps = [ + "//base", + "//components/pref_registry", + "//components/prefs", + "//components/translate/core/browser", + "//components/translate/core/common", + "//ios/net", + "//ios/web", + "//ios/web:user_agent", + "//ios/web/public/app", + "//ios/web_view/internal/translate", + "//ios/web_view/public", + "//net", + "//net:extras", + "//ui/base", + "//url", + ] + allow_circular_includes_from = [ "//ios/web_view/internal/translate" ] +}
diff --git a/ios/web_view/internal/DEPS b/ios/web_view/internal/DEPS new file mode 100644 index 0000000..58dfe5d --- /dev/null +++ b/ios/web_view/internal/DEPS
@@ -0,0 +1,20 @@ +include_rules = [ + "+base", + "+components/infobars/core", + "+components/keyed_service/core", + "+components/keyed_service/ios", + "+components/pref_registry", + "+components/prefs", + "+components/translate/core", + "+components/translate/ios", + "+ios/net", + "+ios/web/public", + "+ios/web_view", + "+net", + "+ui/base", + + # TODO(crbug.com/622967): Remove these exceptions. + "+ios/web/navigation/crw_session_controller.h", + "+ios/web/web_state/ui/crw_web_controller.h", + "+ios/web/web_state/web_state_impl.h", +]
diff --git a/ios/web_view/internal/criwv.mm b/ios/web_view/internal/criwv.mm new file mode 100644 index 0000000..f4a40933 --- /dev/null +++ b/ios/web_view/internal/criwv.mm
@@ -0,0 +1,73 @@ +// 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. + +#import "ios/web_view/public/criwv.h" + +#include <memory> + +#include "base/location.h" +#import "base/mac/bind_objc_block.h" +#include "base/single_thread_task_runner.h" +#include "ios/web/public/app/web_main.h" +#include "ios/web/public/web_thread.h" +#include "ios/web_view/internal/criwv_browser_state.h" +#import "ios/web_view/internal/criwv_web_client.h" +#import "ios/web_view/internal/criwv_web_main_delegate.h" +#import "ios/web_view/internal/criwv_web_view_impl.h" +#import "ios/web_view/public/criwv_delegate.h" + +namespace { +CRIWV* g_criwv = nil; +} + +@interface CRIWV () { + id<CRIWVDelegate> _delegate; + std::unique_ptr<ios_web_view::CRIWVWebMainDelegate> _webMainDelegate; + std::unique_ptr<web::WebMain> _webMain; +} + +- (instancetype)initWithDelegate:(id<CRIWVDelegate>)delegate; +- (ios_web_view::CRIWVBrowserState*)browserState; +@end + +@implementation CRIWV + ++ (void)configureWithDelegate:(id<CRIWVDelegate>)delegate { + g_criwv = [[CRIWV alloc] initWithDelegate:delegate]; +} + ++ (void)shutDown { + [g_criwv release]; + g_criwv = nil; +} + ++ (id<CRIWVWebView>)webView { + return [[[CRIWVWebViewImpl alloc] initWithBrowserState:[g_criwv browserState]] + autorelease]; +} + +- (instancetype)initWithDelegate:(id<CRIWVDelegate>)delegate { + self = [super init]; + if (self) { + _delegate = delegate; + _webMainDelegate.reset(new ios_web_view::CRIWVWebMainDelegate(_delegate)); + web::WebMainParams params(_webMainDelegate.get()); + _webMain.reset(new web::WebMain(params)); + } + return self; +} + +- (void)dealloc { + _webMain.reset(); + _webMainDelegate.reset(); + [super dealloc]; +} + +- (ios_web_view::CRIWVBrowserState*)browserState { + ios_web_view::CRIWVWebClient* client = + static_cast<ios_web_view::CRIWVWebClient*>(web::GetWebClient()); + return client->browser_state(); +} + +@end
diff --git a/ios/web_view/internal/criwv_browser_state.h b/ios/web_view/internal/criwv_browser_state.h new file mode 100644 index 0000000..636a200e --- /dev/null +++ b/ios/web_view/internal/criwv_browser_state.h
@@ -0,0 +1,59 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_BROWSER_STATE_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_BROWSER_STATE_H_ + +#include <memory> + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "components/prefs/pref_service.h" +#include "ios/web/public/browser_state.h" + +namespace user_prefs { +class PrefRegistrySyncable; +} + +namespace ios_web_view { + +class CRIWVURLRequestContextGetter; + +// CRIWV implementation of BrowserState. Can only be called from the UI thread. +class CRIWVBrowserState : public web::BrowserState { + public: + CRIWVBrowserState(); + ~CRIWVBrowserState() override; + + // web::BrowserState implementation. + bool IsOffTheRecord() const override; + base::FilePath GetStatePath() const override; + net::URLRequestContextGetter* GetRequestContext() override; + + // Returns the associated PrefService. + PrefService* GetPrefs(); + + // Converts from web::BrowserState to CRIWVBrowserState. + static CRIWVBrowserState* FromBrowserState(web::BrowserState* browser_state); + + private: + // Registers the preferences for this BrowserState. + void RegisterPrefs(user_prefs::PrefRegistrySyncable* pref_registry); + + // The path associated with this BrowserState object. + base::FilePath path_; + + // The request context getter for this BrowserState object. + scoped_refptr<CRIWVURLRequestContextGetter> request_context_getter_; + + // The PrefService associated with this BrowserState. + std::unique_ptr<PrefService> prefs_; + + DISALLOW_COPY_AND_ASSIGN(CRIWVBrowserState); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_BROWSER_STATE_H_
diff --git a/ios/web_view/internal/criwv_browser_state.mm b/ios/web_view/internal/criwv_browser_state.mm new file mode 100644 index 0000000..5833f99 --- /dev/null +++ b/ios/web_view/internal/criwv_browser_state.mm
@@ -0,0 +1,92 @@ +// 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 "ios/web_view/internal/criwv_browser_state.h" + +#include <memory> + +#include "base/base_paths.h" +#include "base/files/file_path.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/threading/thread_restrictions.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/prefs/json_pref_store.h" +#include "components/prefs/pref_filter.h" +#include "components/prefs/pref_service_factory.h" +#include "components/translate/core/browser/translate_prefs.h" +#include "components/translate/core/common/translate_pref_names.h" +#include "ios/web/public/web_thread.h" +#include "ios/web_view/internal/criwv_url_request_context_getter.h" +#include "ios/web_view/internal/pref_names.h" +#include "ui/base/l10n/l10n_util_mac.h" + +namespace { +const char kPreferencesFilename[] = FILE_PATH_LITERAL("Preferences"); +} + +namespace ios_web_view { + +CRIWVBrowserState::CRIWVBrowserState() : web::BrowserState() { + CHECK(PathService::Get(base::DIR_APP_DATA, &path_)); + + request_context_getter_ = new CRIWVURLRequestContextGetter( + GetStatePath(), + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), + web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE), + web::WebThread::GetTaskRunnerForThread(web::WebThread::CACHE)); + + // Initialize prefs. + scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry = + new user_prefs::PrefRegistrySyncable; + RegisterPrefs(pref_registry.get()); + scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner = + JsonPrefStore::GetTaskRunnerForFile(path_, + web::WebThread::GetBlockingPool()); + + scoped_refptr<PersistentPrefStore> user_pref_store = new JsonPrefStore( + path_.Append(kPreferencesFilename), sequenced_task_runner, nullptr); + + PrefServiceFactory factory; + factory.set_user_prefs(user_pref_store); + prefs_ = factory.Create(pref_registry.get()); +} + +CRIWVBrowserState::~CRIWVBrowserState() {} + +PrefService* CRIWVBrowserState::GetPrefs() { + DCHECK(prefs_); + return prefs_.get(); +} + +// static +CRIWVBrowserState* CRIWVBrowserState::FromBrowserState( + web::BrowserState* browser_state) { + return static_cast<CRIWVBrowserState*>(browser_state); +} + +bool CRIWVBrowserState::IsOffTheRecord() const { + return false; +} + +base::FilePath CRIWVBrowserState::GetStatePath() const { + return path_; +} + +net::URLRequestContextGetter* CRIWVBrowserState::GetRequestContext() { + return request_context_getter_.get(); +} + +void CRIWVBrowserState::RegisterPrefs( + user_prefs::PrefRegistrySyncable* pref_registry) { + // TODO(crbug.com/679895): Find a good value for the kAcceptLanguages pref. + // TODO(crbug.com/679895): Pass this value to the network stack somehow, for + // the HTTP header. + pref_registry->RegisterStringPref(prefs::kAcceptLanguages, + l10n_util::GetLocaleOverride()); + pref_registry->RegisterBooleanPref(prefs::kEnableTranslate, true); + translate::TranslatePrefs::RegisterProfilePrefs(pref_registry); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_network_delegate.cc b/ios/web_view/internal/criwv_network_delegate.cc new file mode 100644 index 0000000..440e0c0 --- /dev/null +++ b/ios/web_view/internal/criwv_network_delegate.cc
@@ -0,0 +1,82 @@ +// 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 "ios/web_view/internal/criwv_network_delegate.h" + +#include "net/base/net_errors.h" + +namespace ios_web_view { + +CRIWVNetworkDelegate::CRIWVNetworkDelegate() {} + +CRIWVNetworkDelegate::~CRIWVNetworkDelegate() {} + +int CRIWVNetworkDelegate::OnBeforeURLRequest( + net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) { + return net::OK; +} + +int CRIWVNetworkDelegate::OnBeforeStartTransaction( + net::URLRequest* request, + const net::CompletionCallback& callback, + net::HttpRequestHeaders* headers) { + return net::OK; +} + +void CRIWVNetworkDelegate::OnStartTransaction( + net::URLRequest* request, + const net::HttpRequestHeaders& headers) {} + +int CRIWVNetworkDelegate::OnHeadersReceived( + net::URLRequest* request, + const net::CompletionCallback& callback, + const net::HttpResponseHeaders* original_response_headers, + scoped_refptr<net::HttpResponseHeaders>* override_response_headers, + GURL* allowed_unsafe_redirect_url) { + return net::OK; +} + +void CRIWVNetworkDelegate::OnBeforeRedirect(net::URLRequest* request, + const GURL& new_location) {} + +void CRIWVNetworkDelegate::OnResponseStarted(net::URLRequest* request) {} + +void CRIWVNetworkDelegate::OnNetworkBytesReceived(net::URLRequest* request, + int64_t bytes_received) {} + +void CRIWVNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) { +} + +void CRIWVNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {} + +void CRIWVNetworkDelegate::OnPACScriptError(int line_number, + const base::string16& error) {} + +CRIWVNetworkDelegate::AuthRequiredResponse CRIWVNetworkDelegate::OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) { + return AUTH_REQUIRED_RESPONSE_NO_ACTION; +} + +bool CRIWVNetworkDelegate::OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) { + return true; +} + +bool CRIWVNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions* options) { + return true; +} + +bool CRIWVNetworkDelegate::OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& path) const { + return true; +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_network_delegate.h b/ios/web_view/internal/criwv_network_delegate.h new file mode 100644 index 0000000..29858074 --- /dev/null +++ b/ios/web_view/internal/criwv_network_delegate.h
@@ -0,0 +1,61 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_NETWORK_DELEGATE_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_NETWORK_DELEGATE_H_ + +#include "base/macros.h" +#include "net/base/network_delegate_impl.h" + +namespace ios_web_view { + +// CRIWV-specific implementation of NetworkDelegate. +class CRIWVNetworkDelegate : public net::NetworkDelegateImpl { + public: + CRIWVNetworkDelegate(); + ~CRIWVNetworkDelegate() override; + + private: + // net::NetworkDelegate implementation. + int OnBeforeURLRequest(net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) override; + int OnBeforeStartTransaction(net::URLRequest* request, + const net::CompletionCallback& callback, + net::HttpRequestHeaders* headers) override; + void OnStartTransaction(net::URLRequest* request, + const net::HttpRequestHeaders& headers) override; + int OnHeadersReceived( + net::URLRequest* request, + const net::CompletionCallback& callback, + const net::HttpResponseHeaders* original_response_headers, + scoped_refptr<net::HttpResponseHeaders>* override_response_headers, + GURL* allowed_unsafe_redirect_url) override; + void OnBeforeRedirect(net::URLRequest* request, + const GURL& new_location) override; + void OnResponseStarted(net::URLRequest* request) override; + void OnNetworkBytesReceived(net::URLRequest* request, + int64_t bytes_received) override; + void OnCompleted(net::URLRequest* request, bool started) override; + void OnURLRequestDestroyed(net::URLRequest* request) override; + void OnPACScriptError(int line_number, const base::string16& error) override; + AuthRequiredResponse OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) override; + bool OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) override; + bool OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions* options) override; + bool OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& path) const override; + + DISALLOW_COPY_AND_ASSIGN(CRIWVNetworkDelegate); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_NETWORK_DELEGATE_H_
diff --git a/ios/web_view/internal/criwv_url_request_context_getter.h b/ios/web_view/internal/criwv_url_request_context_getter.h new file mode 100644 index 0000000..ad0f5cff --- /dev/null +++ b/ios/web_view/internal/criwv_url_request_context_getter.h
@@ -0,0 +1,61 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_URL_REQUEST_CONTEXT_GETTER_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_URL_REQUEST_CONTEXT_GETTER_H_ + +#include <memory> +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/single_thread_task_runner.h" +#include "net/url_request/url_request_context_getter.h" + +namespace net { +class NetworkDelegate; +class NetLog; +class ProxyConfigService; +class TransportSecurityPersister; +class URLRequestContext; +class URLRequestContextStorage; +} + +namespace ios_web_view { + +// CRIWV-specific implementation of URLRequestContextGetter. +class CRIWVURLRequestContextGetter : public net::URLRequestContextGetter { + public: + CRIWVURLRequestContextGetter( + const base::FilePath& base_path, + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& cache_task_runner); + + // net::URLRequestContextGetter implementation. + net::URLRequestContext* GetURLRequestContext() override; + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() + const override; + + protected: + ~CRIWVURLRequestContextGetter() override; + + private: + base::FilePath base_path_; + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner_; + std::unique_ptr<net::ProxyConfigService> proxy_config_service_; + std::unique_ptr<net::NetworkDelegate> network_delegate_; + std::unique_ptr<net::URLRequestContextStorage> storage_; + std::unique_ptr<net::URLRequestContext> url_request_context_; + std::unique_ptr<net::NetLog> net_log_; + std::unique_ptr<net::TransportSecurityPersister> + transport_security_persister_; + + DISALLOW_COPY_AND_ASSIGN(CRIWVURLRequestContextGetter); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/ios/web_view/internal/criwv_url_request_context_getter.mm b/ios/web_view/internal/criwv_url_request_context_getter.mm new file mode 100644 index 0000000..f26690a --- /dev/null +++ b/ios/web_view/internal/criwv_url_request_context_getter.mm
@@ -0,0 +1,163 @@ +// 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 "ios/web_view/internal/criwv_url_request_context_getter.h" + +#include <utility> + +#include "base/base_paths.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/path_service.h" +#include "base/threading/worker_pool.h" +#import "ios/net/cookies/cookie_store_ios.h" +#import "ios/web/public/web_client.h" +#include "ios/web/public/web_thread.h" +#include "ios/web_view/internal/criwv_network_delegate.h" +#include "net/base/cache_type.h" +#include "net/cert/cert_verifier.h" +#include "net/dns/host_resolver.h" +#include "net/extras/sqlite/sqlite_persistent_cookie_store.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties_impl.h" +#include "net/http/transport_security_persister.h" +#include "net/http/transport_security_state.h" +#include "net/proxy/proxy_config_service_ios.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/static_http_user_agent_settings.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_job_factory_impl.h" + +namespace ios_web_view { + +CRIWVURLRequestContextGetter::CRIWVURLRequestContextGetter( + const base::FilePath& base_path, + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& cache_task_runner) + : base_path_(base_path), + file_task_runner_(file_task_runner), + network_task_runner_(network_task_runner), + cache_task_runner_(cache_task_runner), + proxy_config_service_(new net::ProxyConfigServiceIOS), + net_log_(new net::NetLog()) {} + +CRIWVURLRequestContextGetter::~CRIWVURLRequestContextGetter() {} + +net::URLRequestContext* CRIWVURLRequestContextGetter::GetURLRequestContext() { + DCHECK(network_task_runner_->BelongsToCurrentThread()); + + if (!url_request_context_) { + url_request_context_.reset(new net::URLRequestContext()); + url_request_context_->set_net_log(net_log_.get()); + DCHECK(!network_delegate_.get()); + network_delegate_.reset(new CRIWVNetworkDelegate); + url_request_context_->set_network_delegate(network_delegate_.get()); + + storage_.reset( + new net::URLRequestContextStorage(url_request_context_.get())); + + // Setup the cookie store. + base::FilePath cookie_path; + bool cookie_path_found = PathService::Get(base::DIR_APP_DATA, &cookie_path); + DCHECK(cookie_path_found); + cookie_path = cookie_path.Append("WebShell").Append("Cookies"); + scoped_refptr<net::CookieMonster::PersistentCookieStore> persistent_store = + new net::SQLitePersistentCookieStore( + cookie_path, network_task_runner_, + web::WebThread::GetBlockingPool()->GetSequencedTaskRunner( + web::WebThread::GetBlockingPool()->GetSequenceToken()), + true, nullptr); + std::unique_ptr<net::CookieStoreIOS> cookie_store( + new net::CookieStoreIOS(persistent_store.get())); + storage_->set_cookie_store(std::move(cookie_store)); + + std::string user_agent = web::GetWebClient()->GetUserAgent(false); + + storage_->set_http_user_agent_settings( + base::MakeUnique<net::StaticHttpUserAgentSettings>("en-us,en", + user_agent)); + storage_->set_proxy_service( + net::ProxyService::CreateUsingSystemProxyResolver( + std::move(proxy_config_service_), 0, + url_request_context_->net_log())); + storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); + storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); + + std::unique_ptr<net::TransportSecurityState> transport_security_state = + base::MakeUnique<net::TransportSecurityState>(); + storage_->set_transport_security_state(std::move(transport_security_state)); + transport_security_persister_.reset(new net::TransportSecurityPersister( + transport_security_state.get(), base_path_, file_task_runner_, false)); + storage_->set_channel_id_service(base::MakeUnique<net::ChannelIDService>( + new net::DefaultChannelIDStore(nullptr), + base::WorkerPool::GetTaskRunner(true))); + storage_->set_http_server_properties( + std::unique_ptr<net::HttpServerProperties>( + new net::HttpServerPropertiesImpl())); + + std::unique_ptr<net::HostResolver> host_resolver( + net::HostResolver::CreateDefaultResolver( + url_request_context_->net_log())); + storage_->set_http_auth_handler_factory( + net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); + storage_->set_host_resolver(std::move(host_resolver)); + + net::HttpNetworkSession::Params network_session_params; + network_session_params.cert_verifier = + url_request_context_->cert_verifier(); + network_session_params.transport_security_state = + url_request_context_->transport_security_state(); + network_session_params.channel_id_service = + url_request_context_->channel_id_service(); + network_session_params.net_log = url_request_context_->net_log(); + network_session_params.proxy_service = + url_request_context_->proxy_service(); + network_session_params.ssl_config_service = + url_request_context_->ssl_config_service(); + network_session_params.http_auth_handler_factory = + url_request_context_->http_auth_handler_factory(); + network_session_params.http_server_properties = + url_request_context_->http_server_properties(); + network_session_params.host_resolver = + url_request_context_->host_resolver(); + + base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache")); + std::unique_ptr<net::HttpCache::DefaultBackend> main_backend( + new net::HttpCache::DefaultBackend(net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + cache_path, 0, cache_task_runner_)); + + storage_->set_http_network_session( + base::MakeUnique<net::HttpNetworkSession>(network_session_params)); + storage_->set_http_transaction_factory(base::MakeUnique<net::HttpCache>( + storage_->http_network_session(), std::move(main_backend), + true /* set_up_quic_server_info */)); + + std::unique_ptr<net::URLRequestJobFactoryImpl> job_factory( + new net::URLRequestJobFactoryImpl()); + bool set_protocol = job_factory->SetProtocolHandler( + "data", base::MakeUnique<net::DataProtocolHandler>()); + DCHECK(set_protocol); + + storage_->set_job_factory(std::move(job_factory)); + } + + return url_request_context_.get(); +} + +scoped_refptr<base::SingleThreadTaskRunner> +CRIWVURLRequestContextGetter::GetNetworkTaskRunner() const { + return network_task_runner_; +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_web_client.h b/ios/web_view/internal/criwv_web_client.h new file mode 100644 index 0000000..9c325ce --- /dev/null +++ b/ios/web_view/internal/criwv_web_client.h
@@ -0,0 +1,46 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_CLIENT_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_CLIENT_H_ + +#include <memory> +#include "base/compiler_specific.h" +#import "ios/web/public/web_client.h" + +@protocol CRIWVDelegate; + +namespace ios_web_view { +class CRIWVBrowserState; +class CRIWVWebMainParts; + +// CRIWV-specific implementation of WebClient. Delegates some functionality to +// CRIWVDelegate. +class CRIWVWebClient : public web::WebClient { + public: + explicit CRIWVWebClient(id<CRIWVDelegate> delegate); + ~CRIWVWebClient() override; + + // WebClient implementation. + web::WebMainParts* CreateWebMainParts() override; + std::string GetProduct() const override; + std::string GetUserAgent(bool desktop_user_agent) const override; + + // TODO(crbug.com/679895): Find a better way to get a BrowserState object to + // AppDelegate. + CRIWVBrowserState* browser_state() const; + + private: + // This object's delegate. + id<CRIWVDelegate> delegate_; + + // The WebMainParts created by |CreateWebMainParts()|. + CRIWVWebMainParts* web_main_parts_; + + DISALLOW_COPY_AND_ASSIGN(CRIWVWebClient); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_CLIENT_H_
diff --git a/ios/web_view/internal/criwv_web_client.mm b/ios/web_view/internal/criwv_web_client.mm new file mode 100644 index 0000000..18239dd --- /dev/null +++ b/ios/web_view/internal/criwv_web_client.mm
@@ -0,0 +1,38 @@ +// 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. + +#import "ios/web_view/internal/criwv_web_client.h" + +#include "base/strings/sys_string_conversions.h" +#include "ios/web/public/user_agent.h" +#include "ios/web_view/internal/criwv_browser_state.h" +#import "ios/web_view/internal/criwv_web_main_parts.h" +#import "ios/web_view/public/criwv_delegate.h" + +namespace ios_web_view { + +CRIWVWebClient::CRIWVWebClient(id<CRIWVDelegate> delegate) + : delegate_(delegate), web_main_parts_(nullptr) {} + +CRIWVWebClient::~CRIWVWebClient() {} + +web::WebMainParts* CRIWVWebClient::CreateWebMainParts() { + web_main_parts_ = new CRIWVWebMainParts(delegate_); + return web_main_parts_; +} + +CRIWVBrowserState* CRIWVWebClient::browser_state() const { + return web_main_parts_->browser_state(); +} + +std::string CRIWVWebClient::GetProduct() const { + return base::SysNSStringToUTF8([delegate_ partialUserAgent]); +} + +std::string CRIWVWebClient::GetUserAgent(bool desktop_user_agent) const { + std::string product = GetProduct(); + return web::BuildUserAgentFromProduct(product); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_web_main_delegate.h b/ios/web_view/internal/criwv_web_main_delegate.h new file mode 100644 index 0000000..0e33793 --- /dev/null +++ b/ios/web_view/internal/criwv_web_main_delegate.h
@@ -0,0 +1,38 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_MAIN_DELEGATE_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_MAIN_DELEGATE_H_ + +#include <memory> +#include "base/macros.h" +#include "ios/web/public/app/web_main_delegate.h" + +@protocol CRIWVDelegate; + +namespace ios_web_view { +class CRIWVWebClient; + +// CRIWV-specific implementation of WebMainDelegate. +class CRIWVWebMainDelegate : public web::WebMainDelegate { + public: + explicit CRIWVWebMainDelegate(id<CRIWVDelegate> delegate); + ~CRIWVWebMainDelegate() override; + + // WebMainDelegate implementation. + void BasicStartupComplete() override; + + private: + // This object's delegate. + id<CRIWVDelegate> delegate_; + + // The content and web clients registered by this object. + std::unique_ptr<CRIWVWebClient> web_client_; + + DISALLOW_COPY_AND_ASSIGN(CRIWVWebMainDelegate); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_MAIN_DELEGATE_H_
diff --git a/ios/web_view/internal/criwv_web_main_delegate.mm b/ios/web_view/internal/criwv_web_main_delegate.mm new file mode 100644 index 0000000..afa4ad1 --- /dev/null +++ b/ios/web_view/internal/criwv_web_main_delegate.mm
@@ -0,0 +1,23 @@ +// 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. + +#import "ios/web_view/internal/criwv_web_main_delegate.h" + +#include "base/memory/ptr_util.h" +#import "ios/web_view/internal/criwv_web_client.h" +#import "ios/web_view/public/criwv_delegate.h" + +namespace ios_web_view { + +CRIWVWebMainDelegate::CRIWVWebMainDelegate(id<CRIWVDelegate> delegate) + : delegate_(delegate) {} + +CRIWVWebMainDelegate::~CRIWVWebMainDelegate() {} + +void CRIWVWebMainDelegate::BasicStartupComplete() { + web_client_ = base::MakeUnique<CRIWVWebClient>(delegate_); + web::SetWebClient(web_client_.get()); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_web_main_parts.h b/ios/web_view/internal/criwv_web_main_parts.h new file mode 100644 index 0000000..67f946b --- /dev/null +++ b/ios/web_view/internal/criwv_web_main_parts.h
@@ -0,0 +1,39 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_MAIN_PARTS_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_MAIN_PARTS_H_ + +#include "ios/web/public/app/web_main_parts.h" + +#include <memory> + +@protocol CRIWVDelegate; + +namespace ios_web_view { +class CRIWVBrowserState; + +// CRIWV-specific implementation of WebMainParts. +class CRIWVWebMainParts : public web::WebMainParts { + public: + explicit CRIWVWebMainParts(id<CRIWVDelegate> delegate); + ~CRIWVWebMainParts() override; + + // WebMainParts implementation. + void PreMainMessageLoopRun() override; + + // Returns the CRIWVBrowserState for this embedder. + CRIWVBrowserState* browser_state() const { return browser_state_.get(); } + + private: + // This object's delegate. + id<CRIWVDelegate> delegate_; + + // The BrowserState for this embedder. + std::unique_ptr<CRIWVBrowserState> browser_state_; +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_MAIN_PARTS_H_
diff --git a/ios/web_view/internal/criwv_web_main_parts.mm b/ios/web_view/internal/criwv_web_main_parts.mm new file mode 100644 index 0000000..b1ec766e --- /dev/null +++ b/ios/web_view/internal/criwv_web_main_parts.mm
@@ -0,0 +1,47 @@ +// 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. + +#import "ios/web_view/internal/criwv_web_main_parts.h" + +#include "base/base_paths.h" +#include "base/memory/ptr_util.h" +#include "base/path_service.h" +#include "components/translate/core/browser/translate_download_manager.h" +#include "ios/web_view/internal/criwv_browser_state.h" +#import "ios/web_view/public/criwv_delegate.h" +#include "ui/base/l10n/l10n_util_mac.h" +#include "ui/base/resource/resource_bundle.h" + +namespace ios_web_view { + +CRIWVWebMainParts::CRIWVWebMainParts(id<CRIWVDelegate> delegate) { + delegate_ = delegate; +} + +CRIWVWebMainParts::~CRIWVWebMainParts() {} + +void CRIWVWebMainParts::PreMainMessageLoopRun() { + // Initialize resources. + l10n_util::OverrideLocaleWithCocoaLocale(); + ui::ResourceBundle::InitSharedInstanceWithLocale( + std::string(), nullptr, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); + base::FilePath pak_file; + PathService::Get(base::DIR_MODULE, &pak_file); + pak_file = pak_file.Append(FILE_PATH_LITERAL("web_view_resources.pak")); + ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath( + pak_file, ui::SCALE_FACTOR_NONE); + + browser_state_ = base::MakeUnique<CRIWVBrowserState>(); + + // Initialize translate. + translate::TranslateDownloadManager* download_manager = + translate::TranslateDownloadManager::GetInstance(); + // TODO(crbug.com/679895): See if we need the system request context here. + download_manager->set_request_context(browser_state_->GetRequestContext()); + // TODO(crbug.com/679895): Bring up application locale correctly. + download_manager->set_application_locale(l10n_util::GetLocaleOverride()); + download_manager->language_list()->SetResourceRequestsAllowed(true); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/criwv_web_view_impl.h b/ios/web_view/internal/criwv_web_view_impl.h new file mode 100644 index 0000000..fbd9170 --- /dev/null +++ b/ios/web_view/internal/criwv_web_view_impl.h
@@ -0,0 +1,23 @@ +// 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 IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_VIEW_IMPL_H_ +#define IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_VIEW_IMPL_H_ + +#import "ios/web_view/public/criwv_web_view.h" + +namespace ios_web_view { +class CRIWVBrowserState; +} + +@interface CRIWVWebViewImpl : NSObject<CRIWVWebView> + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithBrowserState: + (ios_web_view::CRIWVBrowserState*)browserState NS_DESIGNATED_INITIALIZER; + +@end + +#endif // IOS_WEB_VIEW_INTERNAL_CRIWV_WEB_VIEW_IMPL_H_
diff --git a/ios/web_view/internal/criwv_web_view_impl.mm b/ios/web_view/internal/criwv_web_view_impl.mm new file mode 100644 index 0000000..76709d3 --- /dev/null +++ b/ios/web_view/internal/criwv_web_view_impl.mm
@@ -0,0 +1,242 @@ +// 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. + +#import "ios/web_view/internal/criwv_web_view_impl.h" + +#include <memory> +#include <utility> + +#import "base/ios/weak_nsobject.h" +#include "base/memory/ptr_util.h" +#include "base/strings/sys_string_conversions.h" +#import "ios/web/navigation/crw_session_controller.h" +#include "ios/web/public/referrer.h" +#import "ios/web/public/navigation_manager.h" +#import "ios/web/public/web_state/ui/crw_web_delegate.h" +#import "ios/web/public/web_state/web_state.h" +#import "ios/web/public/web_state/web_state_delegate_bridge.h" +#import "ios/web/web_state/ui/crw_web_controller.h" +#import "ios/web/web_state/web_state_impl.h" +#include "ios/web_view/internal/criwv_browser_state.h" +#import "ios/web_view/internal/translate/criwv_translate_client.h" +#import "ios/web_view/public/criwv_web_view_delegate.h" +#import "net/base/mac/url_conversions.h" +#include "ui/base/page_transition_types.h" +#include "url/gurl.h" + +@interface CRIWVWebViewImpl ()<CRWWebDelegate, CRWWebStateDelegate> { + id<CRIWVWebViewDelegate> _delegate; + ios_web_view::CRIWVBrowserState* _browserState; + std::unique_ptr<web::WebStateImpl> _webStateImpl; + base::WeakNSObject<CRWWebController> _webController; + std::unique_ptr<web::WebStateDelegateBridge> _webStateDelegate; + + CGFloat _loadProgress; +} + +@end + +@implementation CRIWVWebViewImpl + +@synthesize delegate = _delegate; +@synthesize loadProgress = _loadProgress; + +- (instancetype)initWithBrowserState: + (ios_web_view::CRIWVBrowserState*)browserState { + self = [super init]; + if (self) { + _browserState = browserState; + _webStateImpl = base::MakeUnique<web::WebStateImpl>(_browserState); + _webStateImpl->GetNavigationManagerImpl().InitializeSession(nil, nil, NO, + 0); + _webStateDelegate = base::MakeUnique<web::WebStateDelegateBridge>(self); + _webStateImpl->SetDelegate(_webStateDelegate.get()); + _webController.reset(_webStateImpl->GetWebController()); + [_webController setDelegate:self]; + [_webController setWebUsageEnabled:YES]; + + // Initialize Translate. + ios_web_view::CRIWVTranslateClient::CreateForWebState(_webStateImpl.get()); + } + return self; +} + +- (UIView*)view { + return [_webController view]; +} + +- (BOOL)canGoBack { + return _webStateImpl && _webStateImpl->GetNavigationManager()->CanGoBack(); +} + +- (BOOL)canGoForward { + return _webStateImpl && _webStateImpl->GetNavigationManager()->CanGoForward(); +} + +- (BOOL)isLoading { + return _webStateImpl->IsLoading(); +} + +- (NSURL*)visibleURL { + return net::NSURLWithGURL(_webStateImpl->GetVisibleURL()); +} + +- (NSString*)pageTitle { + return base::SysUTF16ToNSString(_webStateImpl->GetTitle()); +} + +- (void)goBack { + if (_webStateImpl->GetNavigationManager()) + _webStateImpl->GetNavigationManager()->GoBack(); +} + +- (void)goForward { + if (_webStateImpl->GetNavigationManager()) + _webStateImpl->GetNavigationManager()->GoForward(); +} + +- (void)reload { + [_webController reload]; +} + +- (void)stopLoading { + [_webController stopLoading]; +} + +- (void)loadURL:(NSURL*)URL { + web::NavigationManager::WebLoadParams params(net::GURLWithNSURL(URL)); + params.transition_type = ui::PAGE_TRANSITION_TYPED; + [_webController loadWithParams:params]; +} + +- (void)evaluateJavaScript:(NSString*)javaScriptString + completionHandler:(void (^)(id, NSError*))completionHandler { + [_webStateImpl->GetJSInjectionReceiver() executeJavaScript:javaScriptString + completionHandler:completionHandler]; +} + +- (void)setDelegate:(id<CRIWVWebViewDelegate>)delegate { + _delegate = delegate; + + // Set up the translate delegate. + ios_web_view::CRIWVTranslateClient* translateClient = + ios_web_view::CRIWVTranslateClient::FromWebState(_webStateImpl.get()); + id<CRIWVTranslateDelegate> translateDelegate = nil; + if ([_delegate respondsToSelector:@selector(translateDelegate)]) + translateDelegate = [_delegate translateDelegate]; + translateClient->set_translate_delegate(translateDelegate); +} + +// ----------------------------------------------------------------------- +// WebDelegate implementation. + +- (void)notifyDidUpdateWithChanges:(CRIWVWebViewUpdateType)changes { + SEL selector = @selector(webView:didUpdateWithChanges:); + if ([_delegate respondsToSelector:selector]) { + [_delegate webView:self didUpdateWithChanges:changes]; + } +} + +- (void)webController:(CRWWebController*)webController + titleDidChange:(NSString*)title { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeTitle]; +} + +- (void)webDidUpdateSessionForLoadWithParams: + (const web::NavigationManager::WebLoadParams&)params + wasInitialNavigation:(BOOL)initialNavigation { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webWillFinishHistoryNavigationFromEntry:(CRWSessionEntry*)fromEntry { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webDidAddPendingURL { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webDidUpdateHistoryStateWithPageURL:(const GURL&)pageUrl { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webCancelStartLoadingRequest { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webDidStartLoadingURL:(const GURL&)currentUrl + shouldUpdateHistory:(BOOL)updateHistory { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webDidFinishWithURL:(const GURL&)url loadSuccess:(BOOL)loadSuccess { + SEL selector = @selector(webView:didFinishLoadingWithURL:loadSuccess:); + if ([_delegate respondsToSelector:selector]) { + [_delegate webView:self + didFinishLoadingWithURL:net::NSURLWithGURL(url) + loadSuccess:loadSuccess]; + } +} + +- (void)webLoadCancelled:(const GURL&)url { + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeURL]; +} + +- (void)webWillAddPendingURL:(const GURL&)url + transition:(ui::PageTransition)transition { +} +- (CRWWebController*)webPageOrderedOpen:(const GURL&)url + referrer:(const web::Referrer&)referrer + windowName:(NSString*)windowName + inBackground:(BOOL)inBackground { + return nil; +} + +- (CRWWebController*)webPageOrderedOpen { + return nil; +} + +- (void)webPageOrderedClose { +} +- (void)openURLWithParams:(const web::WebState::OpenURLParams&)params { +} +- (BOOL)openExternalURL:(const GURL&)url linkClicked:(BOOL)linkClicked { + return NO; +} +- (void)webController:(CRWWebController*)webController + retrievePlaceholderOverlayImage:(void (^)(UIImage*))block { +} +- (void)webController:(CRWWebController*)webController + onFormResubmissionForRequest:(NSURLRequest*)request + continueBlock:(ProceduralBlock)continueBlock + cancelBlock:(ProceduralBlock)cancelBlock { +} +- (void)webWillReload { +} +- (void)webWillInitiateLoadWithParams: + (web::NavigationManager::WebLoadParams&)params { +} +- (BOOL)webController:(CRWWebController*)webController + shouldOpenURL:(const GURL&)url + mainDocumentURL:(const GURL&)mainDocumentURL + linkClicked:(BOOL)linkClicked { + SEL selector = @selector(webView:shouldOpenURL:mainDocumentURL:linkClicked:); + if ([_delegate respondsToSelector:selector]) { + return [_delegate webView:self + shouldOpenURL:net::NSURLWithGURL(url) + mainDocumentURL:net::NSURLWithGURL(mainDocumentURL) + linkClicked:linkClicked]; + } + return YES; +} + +// ----------------------------------------------------------------------- +// CRWWebStateDelegate implementation. + +- (void)webState:(web::WebState*)webState didChangeProgress:(double)progress { + _loadProgress = progress; + [self notifyDidUpdateWithChanges:CRIWVWebViewUpdateTypeProgress]; +} + +@end
diff --git a/ios/web_view/internal/pref_names.cc b/ios/web_view/internal/pref_names.cc new file mode 100644 index 0000000..a56767a --- /dev/null +++ b/ios/web_view/internal/pref_names.cc
@@ -0,0 +1,13 @@ +// 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 "ios/web_view/internal/pref_names.h" + +namespace prefs { + +// The value to use for Accept-Languages HTTP header when making an HTTP +// request. +const char kAcceptLanguages[] = "intl.accept_languages"; + +} // namespace prefs
diff --git a/ios/web_view/internal/pref_names.h b/ios/web_view/internal/pref_names.h new file mode 100644 index 0000000..227ffb7 --- /dev/null +++ b/ios/web_view/internal/pref_names.h
@@ -0,0 +1,14 @@ +// 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 IOS_WEB_VIEW_INTERNAL_PREF_NAMES_H_ +#define IOS_WEB_VIEW_INTERNAL_PREF_NAMES_H_ + +namespace prefs { + +extern const char kAcceptLanguages[]; + +} // namespace prefs + +#endif // IOS_WEB_VIEW_INTERNAL_PREF_NAMES_H_
diff --git a/ios/web_view/internal/translate/BUILD.gn b/ios/web_view/internal/translate/BUILD.gn new file mode 100644 index 0000000..337277f --- /dev/null +++ b/ios/web_view/internal/translate/BUILD.gn
@@ -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. + +source_set("translate") { + visibility = [ + "//ios/web_view", + "//ios/web_view/internal/*", + ] + + sources = [ + "criwv_translate_accept_languages_factory.cc", + "criwv_translate_accept_languages_factory.h", + "criwv_translate_client.h", + "criwv_translate_client.mm", + "criwv_translate_manager_impl.h", + "criwv_translate_manager_impl.mm", + ] + deps = [ + "//base", + "//components/infobars/core", + "//components/keyed_service/core", + "//components/keyed_service/ios", + "//components/prefs", + "//components/translate/core/browser", + "//components/translate/core/common", + "//components/translate/ios/browser", + "//ios/web", + "//ios/web_view/public", + "//url", + ] +}
diff --git a/ios/web_view/internal/translate/criwv_translate_accept_languages_factory.cc b/ios/web_view/internal/translate/criwv_translate_accept_languages_factory.cc new file mode 100644 index 0000000..fe64d96f --- /dev/null +++ b/ios/web_view/internal/translate/criwv_translate_accept_languages_factory.cc
@@ -0,0 +1,78 @@ +// 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 "ios/web_view/internal/translate/criwv_translate_accept_languages_factory.h" + +#include "base/memory/ptr_util.h" +#include "base/memory/singleton.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/keyed_service/ios/browser_state_dependency_manager.h" +#include "components/prefs/pref_service.h" +#include "components/translate/core/browser/translate_accept_languages.h" +#include "ios/web_view/internal/criwv_browser_state.h" +#include "ios/web_view/internal/pref_names.h" + +namespace { + +// TranslateAcceptLanguagesService is a thin container for +// TranslateAcceptLanguages to enable associating it with a BrowserState. +class TranslateAcceptLanguagesService : public KeyedService { + public: + explicit TranslateAcceptLanguagesService(PrefService* prefs); + ~TranslateAcceptLanguagesService() override; + + // Returns the associated TranslateAcceptLanguages. + translate::TranslateAcceptLanguages& accept_languages() { + return accept_languages_; + } + + private: + translate::TranslateAcceptLanguages accept_languages_; + + DISALLOW_COPY_AND_ASSIGN(TranslateAcceptLanguagesService); +}; + +TranslateAcceptLanguagesService::TranslateAcceptLanguagesService( + PrefService* prefs) + : accept_languages_(prefs, prefs::kAcceptLanguages) {} + +TranslateAcceptLanguagesService::~TranslateAcceptLanguagesService() {} + +} // namespace + +namespace ios_web_view { + +// static +CRIWVTranslateAcceptLanguagesFactory* +CRIWVTranslateAcceptLanguagesFactory::GetInstance() { + return base::Singleton<CRIWVTranslateAcceptLanguagesFactory>::get(); +} + +// static +translate::TranslateAcceptLanguages* +CRIWVTranslateAcceptLanguagesFactory::GetForBrowserState( + CRIWVBrowserState* state) { + TranslateAcceptLanguagesService* service = + static_cast<TranslateAcceptLanguagesService*>( + GetInstance()->GetServiceForBrowserState(state, true)); + return &service->accept_languages(); +} + +CRIWVTranslateAcceptLanguagesFactory::CRIWVTranslateAcceptLanguagesFactory() + : BrowserStateKeyedServiceFactory( + "TranslateAcceptLanguagesService", + BrowserStateDependencyManager::GetInstance()) {} + +CRIWVTranslateAcceptLanguagesFactory::~CRIWVTranslateAcceptLanguagesFactory() {} + +std::unique_ptr<KeyedService> +CRIWVTranslateAcceptLanguagesFactory::BuildServiceInstanceFor( + web::BrowserState* context) const { + CRIWVBrowserState* criwv_browser_state = + CRIWVBrowserState::FromBrowserState(context); + return base::MakeUnique<TranslateAcceptLanguagesService>( + criwv_browser_state->GetPrefs()); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/translate/criwv_translate_accept_languages_factory.h b/ios/web_view/internal/translate/criwv_translate_accept_languages_factory.h new file mode 100644 index 0000000..15254504 --- /dev/null +++ b/ios/web_view/internal/translate/criwv_translate_accept_languages_factory.h
@@ -0,0 +1,50 @@ +// 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 IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_ACCEPT_LANGUAGES_FACTORY_H_ +#define IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_ACCEPT_LANGUAGES_FACTORY_H_ + +#include <memory> +#include "base/macros.h" +#include "components/keyed_service/ios/browser_state_keyed_service_factory.h" + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} // namespace base + +namespace translate { +class TranslateAcceptLanguages; +} + +namespace ios_web_view { + +class CRIWVBrowserState; + +// TranslateAcceptLanguagesFactory is a way to associate a +// TranslateAcceptLanguages instance to a BrowserState. +class CRIWVTranslateAcceptLanguagesFactory + : public BrowserStateKeyedServiceFactory { + public: + static translate::TranslateAcceptLanguages* GetForBrowserState( + CRIWVBrowserState* browser_state); + static CRIWVTranslateAcceptLanguagesFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits< + CRIWVTranslateAcceptLanguagesFactory>; + + CRIWVTranslateAcceptLanguagesFactory(); + ~CRIWVTranslateAcceptLanguagesFactory() override; + + // BrowserStateKeyedServiceFactory implementation. + std::unique_ptr<KeyedService> BuildServiceInstanceFor( + web::BrowserState* context) const override; + + DISALLOW_COPY_AND_ASSIGN(CRIWVTranslateAcceptLanguagesFactory); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_ACCEPT_LANGUAGES_FACTORY_H_
diff --git a/ios/web_view/internal/translate/criwv_translate_client.h b/ios/web_view/internal/translate/criwv_translate_client.h new file mode 100644 index 0000000..277b329 --- /dev/null +++ b/ios/web_view/internal/translate/criwv_translate_client.h
@@ -0,0 +1,82 @@ +// 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 IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_CLIENT_H_ +#define IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_CLIENT_H_ + +#include <memory> +#include <string> + +#include "components/translate/core/browser/translate_client.h" +#include "components/translate/core/browser/translate_step.h" +#include "components/translate/core/common/translate_errors.h" +#import "components/translate/ios/browser/ios_translate_driver.h" +#include "ios/web/public/web_state/web_state_observer.h" +#import "ios/web/public/web_state/web_state_user_data.h" + +@protocol CRIWVTranslateDelegate; +class PrefService; + +namespace translate { +class TranslateAcceptLanguages; +class TranslatePrefs; +class TranslateManager; +} // namespace translate + +namespace web { +class WebState; +} + +namespace ios_web_view { + +class CRIWVTranslateClient + : public translate::TranslateClient, + public web::WebStateObserver, + public web::WebStateUserData<CRIWVTranslateClient> { + public: + // Sets the delegate passed by the embedder. + // |delegate| is assumed to outlive this CRIWVTranslateClient. + void set_translate_delegate(id<CRIWVTranslateDelegate> delegate) { + delegate_ = delegate; + } + + private: + friend class web::WebStateUserData<CRIWVTranslateClient>; + + // The lifetime of CRIWVTranslateClient is managed by WebStateUserData. + explicit CRIWVTranslateClient(web::WebState* web_state); + ~CRIWVTranslateClient() override; + + // TranslateClient implementation. + translate::TranslateDriver* GetTranslateDriver() override; + PrefService* GetPrefs() override; + std::unique_ptr<translate::TranslatePrefs> GetTranslatePrefs() override; + translate::TranslateAcceptLanguages* GetTranslateAcceptLanguages() override; + int GetInfobarIconID() const override; + std::unique_ptr<infobars::InfoBar> CreateInfoBar( + std::unique_ptr<translate::TranslateInfoBarDelegate> delegate) + const override; + void ShowTranslateUI(translate::TranslateStep step, + const std::string& source_language, + const std::string& target_language, + translate::TranslateErrors::Type error_type, + bool triggered_from_menu) override; + bool IsTranslatableURL(const GURL& url) override; + void ShowReportLanguageDetectionErrorUI(const GURL& report_url) override; + + // web::WebStateObserver implementation. + void WebStateDestroyed() override; + + std::unique_ptr<translate::TranslateManager> translate_manager_; + translate::IOSTranslateDriver translate_driver_; + + // Delegate provided by the embedder. + id<CRIWVTranslateDelegate> delegate_; // Weak. + + DISALLOW_COPY_AND_ASSIGN(CRIWVTranslateClient); +}; + +} // namespace ios_web_view + +#endif // IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_CLIENT_H_
diff --git a/ios/web_view/internal/translate/criwv_translate_client.mm b/ios/web_view/internal/translate/criwv_translate_client.mm new file mode 100644 index 0000000..af7db46 --- /dev/null +++ b/ios/web_view/internal/translate/criwv_translate_client.mm
@@ -0,0 +1,146 @@ +// 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. + +#import "ios/web_view/internal/translate/criwv_translate_client.h" + +#include <vector> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#import "base/mac/scoped_nsobject.h" +#include "components/infobars/core/infobar.h" +#include "components/prefs/pref_service.h" +#include "components/translate/core/browser/page_translated_details.h" +#include "components/translate/core/browser/translate_accept_languages.h" +#include "components/translate/core/browser/translate_infobar_delegate.h" +#include "components/translate/core/browser/translate_manager.h" +#include "components/translate/core/browser/translate_prefs.h" +#include "components/translate/core/browser/translate_step.h" +#include "ios/web/public/browser_state.h" +#import "ios/web/public/web_state/web_state.h" +#include "ios/web_view/internal/criwv_browser_state.h" +#include "ios/web_view/internal/pref_names.h" +#include "ios/web_view/internal/translate/criwv_translate_accept_languages_factory.h" +#import "ios/web_view/internal/translate/criwv_translate_manager_impl.h" +#import "ios/web_view/public/criwv_translate_delegate.h" +#include "url/gurl.h" + +DEFINE_WEB_STATE_USER_DATA_KEY(ios_web_view::CRIWVTranslateClient); + +namespace ios_web_view { + +CRIWVTranslateClient::CRIWVTranslateClient(web::WebState* web_state) + : web::WebStateObserver(web_state), + translate_manager_(base::MakeUnique<translate::TranslateManager>( + this, + prefs::kAcceptLanguages)), + translate_driver_(web_state, + web_state->GetNavigationManager(), + translate_manager_.get()) {} + +CRIWVTranslateClient::~CRIWVTranslateClient() {} + +// TranslateClient implementation: + +std::unique_ptr<infobars::InfoBar> CRIWVTranslateClient::CreateInfoBar( + std::unique_ptr<translate::TranslateInfoBarDelegate> delegate) const { + NOTREACHED(); + return nullptr; +} + +void CRIWVTranslateClient::ShowTranslateUI( + translate::TranslateStep step, + const std::string& source_language, + const std::string& target_language, + translate::TranslateErrors::Type error_type, + bool triggered_from_menu) { + if (!delegate_) + return; + + if (error_type != translate::TranslateErrors::NONE) + step = translate::TRANSLATE_STEP_TRANSLATE_ERROR; + + translate_manager_->GetLanguageState().SetTranslateEnabled(true); + + if (step == translate::TRANSLATE_STEP_BEFORE_TRANSLATE && + !translate_manager_->GetLanguageState().HasLanguageChanged()) { + return; + } + + base::scoped_nsobject<CRIWVTranslateManagerImpl> criwv_manager( + [[CRIWVTranslateManagerImpl alloc] + initWithTranslateManager:translate_manager_.get() + sourceLanguage:source_language + targetLanguage:target_language]); + + ios_web_view::CRIWVTransateStep criwv_step; + switch (step) { + case translate::TRANSLATE_STEP_BEFORE_TRANSLATE: + criwv_step = ios_web_view::CRIWVTransateStepBeforeTranslate; + break; + case translate::TRANSLATE_STEP_TRANSLATING: + criwv_step = ios_web_view::CRIWVTransateStepTranslating; + break; + case translate::TRANSLATE_STEP_AFTER_TRANSLATE: + criwv_step = ios_web_view::CRIWVTransateStepAfterTranslate; + break; + case translate::TRANSLATE_STEP_TRANSLATE_ERROR: + criwv_step = ios_web_view::CRIWVTransateStepError; + break; + case translate::TRANSLATE_STEP_NEVER_TRANSLATE: + NOTREACHED() << "Never translate is not supported yet in web_view."; + criwv_step = ios_web_view::CRIWVTransateStepError; + break; + } + [delegate_ translateStepChanged:criwv_step manager:criwv_manager.get()]; +} + +translate::TranslateDriver* CRIWVTranslateClient::GetTranslateDriver() { + return &translate_driver_; +} + +PrefService* CRIWVTranslateClient::GetPrefs() { + DCHECK(web_state()); + return CRIWVBrowserState::FromBrowserState(web_state()->GetBrowserState()) + ->GetPrefs(); +} + +std::unique_ptr<translate::TranslatePrefs> +CRIWVTranslateClient::GetTranslatePrefs() { + DCHECK(web_state()); + return base::MakeUnique<translate::TranslatePrefs>( + GetPrefs(), prefs::kAcceptLanguages, nullptr); +} + +translate::TranslateAcceptLanguages* +CRIWVTranslateClient::GetTranslateAcceptLanguages() { + translate::TranslateAcceptLanguages* accept_languages = + CRIWVTranslateAcceptLanguagesFactory::GetForBrowserState( + CRIWVBrowserState::FromBrowserState(web_state()->GetBrowserState())); + DCHECK(accept_languages); + return accept_languages; +} + +int CRIWVTranslateClient::GetInfobarIconID() const { + NOTREACHED(); + return 0; +} + +bool CRIWVTranslateClient::IsTranslatableURL(const GURL& url) { + return !url.is_empty() && !url.SchemeIs(url::kFtpScheme); +} + +void CRIWVTranslateClient::ShowReportLanguageDetectionErrorUI( + const GURL& report_url) { + NOTREACHED(); +} + +void CRIWVTranslateClient::WebStateDestroyed() { + // Translation process can be interrupted. + // Destroying the TranslateManager now guarantees that it never has to deal + // with nullptr WebState. + translate_manager_.reset(); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/translate/criwv_translate_manager_impl.h b/ios/web_view/internal/translate/criwv_translate_manager_impl.h new file mode 100644 index 0000000..beb4275 --- /dev/null +++ b/ios/web_view/internal/translate/criwv_translate_manager_impl.h
@@ -0,0 +1,30 @@ +// 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 IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_MANAGER_IMPL_H_ +#define IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_MANAGER_IMPL_H_ + +#include <string> + +#import "ios/web_view/public/criwv_translate_manager.h" + +namespace translate { +class TranslateManager; +} + +// CRIWVTranslateManagerImpl is mostly an Objective-C wrapper around +// translate::TranslateUIDelegate. +@interface CRIWVTranslateManagerImpl : NSObject<CRIWVTranslateManager> + +- (instancetype)init NS_UNAVAILABLE; + +// |manager| is expexted to outlive this CRIWVTranslateManagerImpl. +- (instancetype)initWithTranslateManager:(translate::TranslateManager*)manager + sourceLanguage:(const std::string&)source + targetLanguage:(const std::string&)target + NS_DESIGNATED_INITIALIZER; + +@end + +#endif // IOS_WEB_VIEW_INTERNAL_TRANSLATE_CRIWV_TRANSLATE_MANAGER_IMPL_H_
diff --git a/ios/web_view/internal/translate/criwv_translate_manager_impl.mm b/ios/web_view/internal/translate/criwv_translate_manager_impl.mm new file mode 100644 index 0000000..8d7f768 --- /dev/null +++ b/ios/web_view/internal/translate/criwv_translate_manager_impl.mm
@@ -0,0 +1,37 @@ +// 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. + +#import "ios/web_view/internal/translate/criwv_translate_manager_impl.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "components/translate/core/browser/translate_manager.h" +#include "components/translate/core/browser/translate_ui_delegate.h" + +@implementation CRIWVTranslateManagerImpl { + std::unique_ptr<translate::TranslateUIDelegate> _translateUIDelegate; +} + +- (instancetype)initWithTranslateManager:(translate::TranslateManager*)manager + sourceLanguage:(const std::string&)source + targetLanguage:(const std::string&)target { + if ((self = [super init])) { + DCHECK(manager); + _translateUIDelegate = base::MakeUnique<translate::TranslateUIDelegate>( + manager->GetWeakPtr(), source, target); + } + return self; +} + +#pragma mark CRIWVTranslateManager methods + +- (void)translate { + _translateUIDelegate->Translate(); +} + +- (void)revertTranslation { + _translateUIDelegate->RevertTranslation(); +} + +@end
diff --git a/ios/web_view/public/BUILD.gn b/ios/web_view/public/BUILD.gn new file mode 100644 index 0000000..8b3eb9f --- /dev/null +++ b/ios/web_view/public/BUILD.gn
@@ -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. + +source_set("public") { + visibility = [ + "//ios/web_view", + "//ios/web_view/internal/*", + ] + + sources = [ + "criwv.h", + "criwv_delegate.h", + "criwv_translate_delegate.h", + "criwv_translate_manager.h", + "criwv_web_view.h", + "criwv_web_view_delegate.h", + ] + + libs = [ "UIKit.framework" ] +}
diff --git a/ios/web_view/public/criwv.h b/ios/web_view/public/criwv.h new file mode 100644 index 0000000..a858af2 --- /dev/null +++ b/ios/web_view/public/criwv.h
@@ -0,0 +1,29 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CRIWV_H_ +#define IOS_WEB_VIEW_PUBLIC_CRIWV_H_ + +#import <Foundation/Foundation.h> + +@protocol CRIWVDelegate; +@protocol CRIWVWebView; + +// Main interface for the CRIWV library. +@interface CRIWV : NSObject + +// Initializes the CRIWV library. This function should be called from +// |application:didFinishLaunchingWithOptions:|. ++ (void)configureWithDelegate:(id<CRIWVDelegate>)delegate; + +// Shuts down the CRIWV library. This function should be called from +// |applicationwillTerminate:|. ++ (void)shutDown; + +// Creates and returns a web view. ++ (id<CRIWVWebView>)webView; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CRIWV_H_
diff --git a/ios/web_view/public/criwv_delegate.h b/ios/web_view/public/criwv_delegate.h new file mode 100644 index 0000000..d4123ce --- /dev/null +++ b/ios/web_view/public/criwv_delegate.h
@@ -0,0 +1,18 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CRIWV_DELEGATE_H_ +#define IOS_WEB_VIEW_PUBLIC_CRIWV_DELEGATE_H_ + +@class NSString; + +// Delegate interface for the CRIWV library. Embedders can implement the +// functions in order to customize library behavior. +@protocol CRIWVDelegate + +// Returns a partial user agent of the form "ProductName/Version". +- (NSString*)partialUserAgent; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CRIWV_DELEGATE_H_
diff --git a/ios/web_view/public/criwv_translate_delegate.h b/ios/web_view/public/criwv_translate_delegate.h new file mode 100644 index 0000000..c1a4f05 --- /dev/null +++ b/ios/web_view/public/criwv_translate_delegate.h
@@ -0,0 +1,32 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CRIWV_TRANSLATE_DELEGATE_H_ +#define IOS_WEB_VIEW_PUBLIC_CRIWV_TRANSLATE_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +@protocol CRIWVTranslateManager; + +namespace ios_web_view { + +typedef NS_ENUM(NSInteger, CRIWVTransateStep) { + CRIWVTransateStepBeforeTranslate, + CRIWVTransateStepTranslating, + CRIWVTransateStepAfterTranslate, + CRIWVTransateStepError, +}; + +} // namespace ios_web_view + +// Delegate interface for the CRIWVTranslate. Embedders can implement the +// functions in order to customize the behavior. +@protocol CRIWVTranslateDelegate + +- (void)translateStepChanged:(ios_web_view::CRIWVTransateStep)step + manager:(id<CRIWVTranslateManager>)manager; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CRIWV_TRANSLATE_DELEGATE_H_
diff --git a/ios/web_view/public/criwv_translate_manager.h b/ios/web_view/public/criwv_translate_manager.h new file mode 100644 index 0000000..8acd498 --- /dev/null +++ b/ios/web_view/public/criwv_translate_manager.h
@@ -0,0 +1,20 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CRIWV_TRANSLATE_MANAGER_H_ +#define IOS_WEB_VIEW_PUBLIC_CRIWV_TRANSLATE_MANAGER_H_ + +#import <Foundation/Foundation.h> + +// Interface to manage the translation flow. +// Clients are not supposed to instantiate or subclass it. +@protocol CRIWVTranslateManager<NSObject> + +- (void)translate; + +- (void)revertTranslation; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CRIWV_TRANSLATE_MANAGER_H_
diff --git a/ios/web_view/public/criwv_web_view.h b/ios/web_view/public/criwv_web_view.h new file mode 100644 index 0000000..5d2aeb4 --- /dev/null +++ b/ios/web_view/public/criwv_web_view.h
@@ -0,0 +1,59 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_H_ +#define IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_H_ + +#import <UIKit/UIKit.h> + +@protocol CRIWVWebViewDelegate; + +// Primary objective-c interface for web/. Just like a WKWebView, but better. +// Concrete instances can be created through CRIWV. +@protocol CRIWVWebView<NSObject> + +// The view used to display web content. +@property(nonatomic, readonly) UIView* view; + +// This web view's delegate. +@property(nonatomic, readwrite, assign) id<CRIWVWebViewDelegate> delegate; + +// Whether or not this web view can go backwards or forwards. +@property(nonatomic, readonly) BOOL canGoBack; +@property(nonatomic, readonly) BOOL canGoForward; + +// Whether or not this web view is loading a page. +@property(nonatomic, readonly) BOOL isLoading; + +// The current URL, for display to the user. +@property(nonatomic, readonly) NSURL* visibleURL; + +// The current page title. +@property(nonatomic, readonly) NSString* pageTitle; + +// The current load progress, as a fraction between 0 and 1. This value is +// undefined if the web view is not currently loading. +@property(nonatomic, readonly) CGFloat loadProgress; + +// Navigates backwards or forwards by one page. Does nothing if the +// corresponding |canGoBack| or |canGoForward| method returns NO. +- (void)goBack; +- (void)goForward; + +// Reloads the current page. +- (void)reload; + +// Stops loading the current page. +- (void)stopLoading; + +// Loads the given |url| in this web view. +- (void)loadURL:(NSURL*)url; + +// Evaluates a JavaScript string. +// The completion handler is invoked when script evaluation completes. +- (void)evaluateJavaScript:(NSString*)javaScriptString + completionHandler:(void (^)(id, NSError*))completionHandler; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_H_
diff --git a/ios/web_view/public/criwv_web_view_delegate.h b/ios/web_view/public/criwv_web_view_delegate.h new file mode 100644 index 0000000..6c00c03 --- /dev/null +++ b/ios/web_view/public/criwv_web_view_delegate.h
@@ -0,0 +1,42 @@ +// 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 IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_DELEGATE_H_ +#define IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +@protocol CRIWVTranslateDelegate; +@protocol CRIWVWebView; + +typedef NS_OPTIONS(NSUInteger, CRIWVWebViewUpdateType) { + CRIWVWebViewUpdateTypeProgress = 1 << 0, + CRIWVWebViewUpdateTypeTitle = 1 << 1, + CRIWVWebViewUpdateTypeURL = 1 << 2 +}; + +// Delegate protocol for CRIWVWebViews. Allows embedders to customize web view +// behavior and receive updates on page load progress. +@protocol CRIWVWebViewDelegate<NSObject> + +@optional + +- (void)webView:(id<CRIWVWebView>)webView + didFinishLoadingWithURL:(NSURL*)url + loadSuccess:(BOOL)loadSuccess; + +- (void)webView:(id<CRIWVWebView>)webView + didUpdateWithChanges:(CRIWVWebViewUpdateType)changes; + +- (id<CRIWVTranslateDelegate>)translateDelegate; + +// Returns YES if the web view should load |url| or NO for a custom handling. +- (BOOL)webView:(id<CRIWVWebView>)webView + shouldOpenURL:(NSURL*)url + mainDocumentURL:(NSURL*)mainDocumentURL + linkClicked:(BOOL)linkClicked; + +@end + +#endif // IOS_WEB_VIEW_PUBLIC_CRIWV_WEB_VIEW_DELEGATE_H_
diff --git a/ios/web_view/shell/BUILD.gn b/ios/web_view/shell/BUILD.gn new file mode 100644 index 0000000..9683ad8 --- /dev/null +++ b/ios/web_view/shell/BUILD.gn
@@ -0,0 +1,81 @@ +# 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("//tools/grit/repack.gni") +import("//build/config/ios/rules.gni") + +ios_app_bundle("ios_web_view_shell") { + deps = [ + "//base", + "//ios/web_view", + ] + bundle_deps = [ + ":resources", + ":packed_resources", + ] + info_plist = "Info.plist" + sources = [ + "shell_app_delegate.h", + "shell_app_delegate.mm", + "shell_delegate.h", + "shell_delegate.mm", + "shell_exe_main.mm", + "shell_view_controller.h", + "shell_view_controller.mm", + "translate_controller.h", + "translate_controller.mm", + ] + libs = [ + "CFNetwork.framework", + "CoreFoundation.framework", + "CoreGraphics.framework", + "CoreText.framework", + "Foundation.framework", + "ImageIO.framework", + "MobileCoreServices.framework", + "Security.framework", + "SystemConfiguration.framework", + "UIKit.framework", + "WebKit.framework", + "resolv", + ] +} + +bundle_data("resources") { + visibility = [ ":ios_web_view_shell" ] + sources = [ + "Default-568h@2x.png", + "textfield_background@2x.png", + "toolbar_back@2x.png", + "toolbar_forward@2x.png", + "toolbar_stop@2x.png", + ] + outputs = [ + "{{bundle_resources_dir}}/{{source_file_part}}", + ] +} + +repack("repack_resources") { + visibility = [ ":packed_resources" ] + deps = [ + "//components/resources:components_resources", + ] + sources = [ + "$root_gen_dir/components/components_resources.pak", + ] + output = "$target_gen_dir/web_view_resources.pak" +} + +bundle_data("packed_resources") { + visibility = [ ":ios_web_view_shell" ] + public_deps = [ + ":repack_resources", + ] + sources = [ + "$target_gen_dir/web_view_resources.pak", + ] + outputs = [ + "{{bundle_resources_dir}}/{{source_file_part}}", + ] +}
diff --git a/ios/web_view/shell/DEPS b/ios/web_view/shell/DEPS new file mode 100644 index 0000000..c163ac3e --- /dev/null +++ b/ios/web_view/shell/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+base", + "+ios/web_view/public", + "+ios/web_view/shell", +]
diff --git a/ios/web_view/shell/Default-568h@2x.png b/ios/web_view/shell/Default-568h@2x.png new file mode 100644 index 0000000..8c9089d5 --- /dev/null +++ b/ios/web_view/shell/Default-568h@2x.png Binary files differ
diff --git a/ios/web_view/shell/Info.plist b/ios/web_view/shell/Info.plist new file mode 100644 index 0000000..c89c650 --- /dev/null +++ b/ios/web_view/shell/Info.plist
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${IOS_BUNDLE_ID_PREFIX}.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSAllowsArbitraryLoads</key> + <true/> + </dict> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist>
diff --git a/ios/web_view/shell/shell_app_delegate.h b/ios/web_view/shell/shell_app_delegate.h new file mode 100644 index 0000000..0836e0c --- /dev/null +++ b/ios/web_view/shell/shell_app_delegate.h
@@ -0,0 +1,17 @@ +// 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 IOS_WEB_VIEW_SHELL_SHELL_APP_DELEGATE_H_ +#define IOS_WEB_VIEW_SHELL_SHELL_APP_DELEGATE_H_ + +#import <UIKit/UIKit.h> + +// UIApplicationDelegate implementation for web_view_shell. +@interface ShellAppDelegate : UIResponder<UIApplicationDelegate> + +// The main window for the application. +@property(nonatomic, retain) UIWindow* window; + +@end + +#endif // IOS_WEB_VIEW_SHELL_SHELL_APP_DELEGATE_H_
diff --git a/ios/web_view/shell/shell_app_delegate.mm b/ios/web_view/shell/shell_app_delegate.mm new file mode 100644 index 0000000..61da172c --- /dev/null +++ b/ios/web_view/shell/shell_app_delegate.mm
@@ -0,0 +1,59 @@ +// 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. + +#import "ios/web_view/shell/shell_app_delegate.h" + +#import "base/mac/scoped_nsobject.h" +#import "ios/web_view/public/criwv.h" +#import "ios/web_view/shell/shell_delegate.h" +#import "ios/web_view/shell/shell_view_controller.h" + +@interface ShellAppDelegate () { + base::scoped_nsobject<ShellDelegate> _delegate; +} +@end + +@implementation ShellAppDelegate + +@synthesize window = _window; + +- (BOOL)application:(UIApplication*)application + didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.backgroundColor = [UIColor whiteColor]; + + _delegate.reset([[ShellDelegate alloc] init]); + [CRIWV configureWithDelegate:_delegate]; + + [self.window makeKeyAndVisible]; + + base::scoped_nsobject<ShellViewController> controller( + [[ShellViewController alloc] init]); + self.window.rootViewController = controller; + + return YES; +} + +- (void)applicationWillResignActive:(UIApplication*)application { +} + +- (void)applicationDidEnterBackground:(UIApplication*)application { +} + +- (void)applicationWillEnterForeground:(UIApplication*)application { +} + +- (void)applicationDidBecomeActive:(UIApplication*)application { +} + +- (void)applicationWillTerminate:(UIApplication*)application { + [CRIWV shutDown]; +} + +- (void)dealloc { + [_window release]; + [super dealloc]; +} + +@end
diff --git a/ios/web_view/shell/shell_delegate.h b/ios/web_view/shell/shell_delegate.h new file mode 100644 index 0000000..917af95 --- /dev/null +++ b/ios/web_view/shell/shell_delegate.h
@@ -0,0 +1,15 @@ +// 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 IOS_WEB_VIEW_SHELL_SHELL_DELEGATE_H_ +#define IOS_WEB_VIEW_SHELL_SHELL_DELEGATE_H_ + +#import <UIKit/UIKit.h> + +#import "ios/web_view/public/criwv_delegate.h" + +// Shell-specific implementation of CRIWVDelegate. +@interface ShellDelegate : NSObject<CRIWVDelegate> +@end + +#endif // IOS_WEB_VIEW_SHELL_SHELL_DELEGATE_H_
diff --git a/ios/web_view/shell/shell_delegate.mm b/ios/web_view/shell/shell_delegate.mm new file mode 100644 index 0000000..fea811a --- /dev/null +++ b/ios/web_view/shell/shell_delegate.mm
@@ -0,0 +1,13 @@ +// 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. + +#import "ios/web_view/shell/shell_delegate.h" + +@implementation ShellDelegate + +- (NSString*)partialUserAgent { + return @"Dummy/1.0"; +} + +@end
diff --git a/ios/web_view/shell/shell_exe_main.mm b/ios/web_view/shell/shell_exe_main.mm new file mode 100644 index 0000000..0db7149 --- /dev/null +++ b/ios/web_view/shell/shell_exe_main.mm
@@ -0,0 +1,14 @@ +// 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. + +#import <UIKit/UIKit.h> + +#import "ios/web_view/shell/shell_app_delegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, + NSStringFromClass([ShellAppDelegate class])); + } +}
diff --git a/ios/web_view/shell/shell_view_controller.h b/ios/web_view/shell/shell_view_controller.h new file mode 100644 index 0000000..a6d4cfc --- /dev/null +++ b/ios/web_view/shell/shell_view_controller.h
@@ -0,0 +1,19 @@ +// 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 IOS_WEB_VIEW_SHELL_SHELL_VIEW_CONTROLLER_H_ +#define IOS_WEB_VIEW_SHELL_SHELL_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/web_view/public/criwv_web_view_delegate.h" + +// Implements the main UI for web_view_shell, including the toolbar and web +// view. +@interface ShellViewController + : UIViewController<CRIWVWebViewDelegate, UITextFieldDelegate> + +@end + +#endif // IOS_WEB_VIEW_SHELL_SHELL_VIEW_CONTROLLER_H_
diff --git a/ios/web_view/shell/shell_view_controller.mm b/ios/web_view/shell/shell_view_controller.mm new file mode 100644 index 0000000..c164096a --- /dev/null +++ b/ios/web_view/shell/shell_view_controller.mm
@@ -0,0 +1,193 @@ +// 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. + +#import "ios/web_view/shell/shell_view_controller.h" + +#import "base/mac/scoped_nsobject.h" +#include "base/strings/sys_string_conversions.h" +#import "ios/web_view/public/criwv.h" +#import "ios/web_view/public/criwv_web_view.h" +#import "ios/web_view/shell/translate_controller.h" + +namespace { +const CGFloat kButtonSize = 44; +} + +@interface ShellViewController () { + base::scoped_nsobject<UIView> _containerView; + base::scoped_nsobject<UITextField> _field; + base::scoped_nsobject<UIToolbar> _toolbar; + base::scoped_nsprotocol<id<CRIWVWebView>> _webView; + base::scoped_nsobject<TranslateController> _translateController; +} +- (void)back; +- (void)forward; +- (void)stopLoading; +@end + +@implementation ShellViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + CGRect bounds = self.view.bounds; + + // Set up the toolbar. + _toolbar.reset([[UIToolbar alloc] init]); + [_toolbar setBarTintColor:[UIColor colorWithRed:0.337 + green:0.467 + blue:0.988 + alpha:1.0]]; + [_toolbar setFrame:CGRectMake(0, 20, CGRectGetWidth(bounds), 44)]; + [_toolbar setAutoresizingMask:UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleBottomMargin]; + [self.view addSubview:_toolbar]; + + // Set up the container view. + _containerView.reset([[UIView alloc] init]); + [_containerView setFrame:CGRectMake(0, 64, CGRectGetWidth(bounds), + CGRectGetHeight(bounds) - 64)]; + [_containerView setBackgroundColor:[UIColor lightGrayColor]]; + [_containerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight]; + [self.view addSubview:_containerView]; + + // Text field. + const int kButtonCount = 3; + _field.reset([[UITextField alloc] + initWithFrame:CGRectMake(kButtonCount * kButtonSize, 6, + CGRectGetWidth([_toolbar frame]) - + kButtonCount * kButtonSize - 10, + 31)]); + [_field setDelegate:self]; + [_field setBackground:[[UIImage imageNamed:@"textfield_background"] + resizableImageWithCapInsets:UIEdgeInsetsMake( + 12, 12, 12, 12)]]; + [_field setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; + [_field setKeyboardType:UIKeyboardTypeWebSearch]; + [_field setAutocorrectionType:UITextAutocorrectionTypeNo]; + [_field setClearButtonMode:UITextFieldViewModeWhileEditing]; + + // Set up the toolbar buttons. + // Back. + UIButton* back = [UIButton buttonWithType:UIButtonTypeCustom]; + [back setImage:[UIImage imageNamed:@"toolbar_back"] + forState:UIControlStateNormal]; + [back setFrame:CGRectMake(0, 0, kButtonSize, kButtonSize)]; + UIEdgeInsets insets = UIEdgeInsetsMake(5, 5, 4, 4); + [back setImageEdgeInsets:insets]; + [back setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin]; + [back addTarget:self + action:@selector(back) + forControlEvents:UIControlEventTouchUpInside]; + + // Forward. + UIButton* forward = [UIButton buttonWithType:UIButtonTypeCustom]; + [forward setImage:[UIImage imageNamed:@"toolbar_forward"] + forState:UIControlStateNormal]; + [forward setFrame:CGRectMake(kButtonSize, 0, kButtonSize, kButtonSize)]; + [forward setImageEdgeInsets:insets]; + [forward setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin]; + [forward addTarget:self + action:@selector(forward) + forControlEvents:UIControlEventTouchUpInside]; + + // Stop. + UIButton* stop = [UIButton buttonWithType:UIButtonTypeCustom]; + [stop setImage:[UIImage imageNamed:@"toolbar_stop"] + forState:UIControlStateNormal]; + [stop setFrame:CGRectMake(2 * kButtonSize, 0, kButtonSize, kButtonSize)]; + [stop setImageEdgeInsets:insets]; + [stop setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin]; + [stop addTarget:self + action:@selector(stopLoading) + forControlEvents:UIControlEventTouchUpInside]; + + [_toolbar addSubview:back]; + [_toolbar addSubview:forward]; + [_toolbar addSubview:stop]; + [_toolbar addSubview:_field]; + + _webView.reset([[CRIWV webView] retain]); + [_webView setDelegate:self]; + UIView* view = [_webView view]; + [_containerView addSubview:view]; + [view setFrame:[_containerView bounds]]; + [view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight]; + + [_webView loadURL:[NSURL URLWithString:@"https://www.google.com/"]]; +} + +- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar { + if (bar == _toolbar.get()) { + return UIBarPositionTopAttached; + } + return UIBarPositionAny; +} + +- (void)back { + if ([_webView canGoBack]) { + [_webView goBack]; + } +} + +- (void)forward { + if ([_webView canGoForward]) { + [_webView goForward]; + } +} + +- (void)stopLoading { + [_webView stopLoading]; +} + +- (BOOL)textFieldShouldReturn:(UITextField*)field { + [_webView loadURL:[NSURL URLWithString:[field text]]]; + [field resignFirstResponder]; + [self updateToolbar]; + return YES; +} + +- (void)updateToolbar { + // Do not update the URL if the text field is currently being edited. + if ([_field isFirstResponder]) { + return; + } + + [_field setText:[[_webView visibleURL] absoluteString]]; +} + +#pragma mark CRIWVWebViewDelegate methods + +- (void)webView:(id<CRIWVWebView>)webView + didFinishLoadingWithURL:(NSURL*)url + loadSuccess:(BOOL)loadSuccess { + // TODO(crbug.com/679895): Add some visual indication that the page load has + // finished. + [self updateToolbar]; +} + +- (void)webView:(id<CRIWVWebView>)webView + didUpdateWithChanges:(CRIWVWebViewUpdateType)changes { + if (changes & CRIWVWebViewUpdateTypeProgress) { + // TODO(crbug.com/679895): Add a progress indicator. + } + + if (changes & CRIWVWebViewUpdateTypeTitle) { + // TODO(crbug.com/679895): Add a title display. + } + + if (changes & CRIWVWebViewUpdateTypeURL) { + [self updateToolbar]; + } +} + +- (id<CRIWVTranslateDelegate>)translateDelegate { + if (!_translateController) + _translateController.reset([[TranslateController alloc] init]); + return _translateController; +} + +@end
diff --git a/ios/web_view/shell/textfield_background@2x.png b/ios/web_view/shell/textfield_background@2x.png new file mode 100644 index 0000000..5428d1d6 --- /dev/null +++ b/ios/web_view/shell/textfield_background@2x.png Binary files differ
diff --git a/ios/web_view/shell/toolbar_back@2x.png b/ios/web_view/shell/toolbar_back@2x.png new file mode 100644 index 0000000..885ca0f --- /dev/null +++ b/ios/web_view/shell/toolbar_back@2x.png Binary files differ
diff --git a/ios/web_view/shell/toolbar_forward@2x.png b/ios/web_view/shell/toolbar_forward@2x.png new file mode 100644 index 0000000..608ba20 --- /dev/null +++ b/ios/web_view/shell/toolbar_forward@2x.png Binary files differ
diff --git a/ios/web_view/shell/toolbar_stop@2x.png b/ios/web_view/shell/toolbar_stop@2x.png new file mode 100644 index 0000000..0330efd9 --- /dev/null +++ b/ios/web_view/shell/toolbar_stop@2x.png Binary files differ
diff --git a/ios/web_view/shell/translate_controller.h b/ios/web_view/shell/translate_controller.h new file mode 100644 index 0000000..c920bf7 --- /dev/null +++ b/ios/web_view/shell/translate_controller.h
@@ -0,0 +1,15 @@ +// 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 IOS_WEB_VIEW_SHELL_TRANSLATE_CONTROLLER_H_ +#define IOS_WEB_VIEW_SHELL_TRANSLATE_CONTROLLER_H_ + +#import <Foundation/Foundation.h> + +#import "ios/web_view/public/criwv_translate_delegate.h" + +@interface TranslateController : NSObject<CRIWVTranslateDelegate> +@end + +#endif // IOS_WEB_VIEW_SHELL_TRANSLATE_CONTROLLER_H_
diff --git a/ios/web_view/shell/translate_controller.mm b/ios/web_view/shell/translate_controller.mm new file mode 100644 index 0000000..8306de62 --- /dev/null +++ b/ios/web_view/shell/translate_controller.mm
@@ -0,0 +1,69 @@ +// 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. + +#import "ios/web_view/shell/translate_controller.h" + +#import <UIKit/UIKit.h> + +#include "base/logging.h" +#import "base/mac/scoped_nsobject.h" +#import "ios/web_view/public/criwv_translate_manager.h" + +@interface TranslateController () { + base::scoped_nsobject<UIAlertController> _beforeTranslateActionSheet; + base::scoped_nsprotocol<id<CRIWVTranslateManager>> _translateManager; +} +@end + +@implementation TranslateController + +- (void)dealloc { + [_beforeTranslateActionSheet dismissViewControllerAnimated:YES + completion:nil]; + [super dealloc]; +} + +#pragma mark CRIWVTranslateDelegate methods + +- (void)translateStepChanged:(ios_web_view::CRIWVTransateStep)step + manager:(id<CRIWVTranslateManager>)manager { + if (step == ios_web_view::CRIWVTransateStepBeforeTranslate) { + DCHECK(!_translateManager); + DCHECK(!_beforeTranslateActionSheet); + _translateManager.reset([manager retain]); + _beforeTranslateActionSheet.reset([[UIAlertController + alertControllerWithTitle:nil + message:@"Translate?" + preferredStyle:UIAlertControllerStyleActionSheet] retain]); + UIAlertAction* cancelAction = + [UIAlertAction actionWithTitle:@"Nope." + style:UIAlertActionStyleCancel + handler:^(UIAlertAction* action) { + DCHECK(_beforeTranslateActionSheet); + _beforeTranslateActionSheet.reset(); + DCHECK(_translateManager); + _translateManager.reset(); + }]; + [_beforeTranslateActionSheet addAction:cancelAction]; + + UIAlertAction* translateAction = + [UIAlertAction actionWithTitle:@"Yes!" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction* action) { + DCHECK(_beforeTranslateActionSheet); + _beforeTranslateActionSheet.reset(); + DCHECK(_translateManager); + [_translateManager translate]; + _translateManager.reset(); + }]; + [_beforeTranslateActionSheet addAction:translateAction]; + + [[UIApplication sharedApplication].keyWindow.rootViewController + presentViewController:_beforeTranslateActionSheet + animated:YES + completion:nil]; + } +} + +@end
diff --git a/mash/browser/BUILD.gn b/mash/browser/BUILD.gn index af445e38..780ef02 100644 --- a/mash/browser/BUILD.gn +++ b/mash/browser/BUILD.gn
@@ -56,7 +56,6 @@ resources = [ "$root_out_dir/views_mus_resources.pak" ] data_deps = [ - ":manifest", "//services/ui", ] }
diff --git a/mash/catalog_viewer/BUILD.gn b/mash/catalog_viewer/BUILD.gn index d7250b6..4161334 100644 --- a/mash/catalog_viewer/BUILD.gn +++ b/mash/catalog_viewer/BUILD.gn
@@ -48,10 +48,6 @@ ] resources = [ "$root_out_dir/views_mus_resources.pak" ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/mash/example/views_examples/BUILD.gn b/mash/example/views_examples/BUILD.gn index 5291293b..eb2800a 100644 --- a/mash/example/views_examples/BUILD.gn +++ b/mash/example/views_examples/BUILD.gn
@@ -33,10 +33,6 @@ ] resources = [ "$root_out_dir/views_mus_resources.pak" ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/mash/example/window_type_launcher/BUILD.gn b/mash/example/window_type_launcher/BUILD.gn index af6b7f5..da4fe5a2 100644 --- a/mash/example/window_type_launcher/BUILD.gn +++ b/mash/example/window_type_launcher/BUILD.gn
@@ -37,7 +37,6 @@ resources = [ "$root_out_dir/views_mus_resources.pak" ] data_deps = [ - ":manifest", "//services/ui", ] }
diff --git a/mash/session/BUILD.gn b/mash/session/BUILD.gn index edb0df5..f23e78b 100644 --- a/mash/session/BUILD.gn +++ b/mash/session/BUILD.gn
@@ -49,10 +49,6 @@ "//services/service_manager/public/cpp", "//services/service_manager/public/cpp:sources", ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/mash/session/session.cc b/mash/session/session.cc index cd22965..2fdb9c99 100644 --- a/mash/session/session.cc +++ b/mash/session/session.cc
@@ -10,21 +10,9 @@ #include "content/public/common/service_names.mojom.h" #include "mash/common/config.h" #include "mash/quick_launch/public/interfaces/constants.mojom.h" -#include "services/service_manager/public/cpp/connection.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/interface_registry.h" #include "services/service_manager/public/cpp/service_context.h" -namespace { - -void LogAndCallServiceRestartCallback(const std::string& url, - const base::Closure& callback) { - LOG(ERROR) << "Restarting service: " << url; - callback.Run(); -} - -} // namespace - namespace mash { namespace session { @@ -40,33 +28,15 @@ } void Session::StartWindowManager() { - StartRestartableService( - common::GetWindowManagerServiceName(), - base::Bind(&Session::StartWindowManager, - base::Unretained(this))); + // TODO(beng): monitor this service for death & bring down the whole system + // if necessary. + context()->connector()->Connect(common::GetWindowManagerServiceName()); } void Session::StartQuickLaunch() { - StartRestartableService( - quick_launch::mojom::kServiceName, - base::Bind(&Session::StartQuickLaunch, - base::Unretained(this))); -} - -void Session::StartRestartableService( - const std::string& url, - const base::Closure& restart_callback) { - // TODO(beng): This would be the place to insert logic that counted restarts - // to avoid infinite crash-restart loops. - std::unique_ptr<service_manager::Connection> connection = - context()->connector()->Connect(url); - // Note: |connection| may be null if we've lost our connection to the service - // manager. - if (connection) { - connection->SetConnectionLostClosure( - base::Bind(&LogAndCallServiceRestartCallback, url, restart_callback)); - connections_[url] = std::move(connection); - } + // TODO(beng): monitor this service for death & bring down the whole system + // if necessary. + context()->connector()->Connect(quick_launch::mojom::kServiceName); } } // namespace session
diff --git a/mash/session/session.h b/mash/session/session.h index 1887918..ac67cbd8 100644 --- a/mash/session/session.h +++ b/mash/session/session.h
@@ -5,20 +5,9 @@ #ifndef MASH_SESSION_SESSION_H_ #define MASH_SESSION_SESSION_H_ -#include <map> -#include <memory> - -#include "base/callback.h" #include "base/macros.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" -#include "services/service_manager/public/cpp/interface_factory.h" #include "services/service_manager/public/cpp/service.h" -namespace service_manager { -class Connection; -} - namespace mash { namespace session { @@ -34,14 +23,6 @@ void StartWindowManager(); void StartQuickLaunch(); - // Starts the application at |url|, running |restart_callback| if the - // connection to the application is closed. - void StartRestartableService(const std::string& url, - const base::Closure& restart_callback); - - std::map<std::string, std::unique_ptr<service_manager::Connection>> - connections_; - DISALLOW_COPY_AND_ASSIGN(Session); };
diff --git a/mash/simple_wm/BUILD.gn b/mash/simple_wm/BUILD.gn index 1b90ddf..bfb156a3 100644 --- a/mash/simple_wm/BUILD.gn +++ b/mash/simple_wm/BUILD.gn
@@ -55,7 +55,6 @@ ] data_deps = [ - ":manifest", "//services/ui", ] }
diff --git a/mash/task_viewer/BUILD.gn b/mash/task_viewer/BUILD.gn index 0dd52ca4..d0abf88 100644 --- a/mash/task_viewer/BUILD.gn +++ b/mash/task_viewer/BUILD.gn
@@ -43,10 +43,6 @@ ] resources = [ "$root_out_dir/views_mus_resources.pak" ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/mash/webtest/BUILD.gn b/mash/webtest/BUILD.gn index 9b75776..ea3574f 100644 --- a/mash/webtest/BUILD.gn +++ b/mash/webtest/BUILD.gn
@@ -50,10 +50,6 @@ ] resources = [ "$root_out_dir/views_mus_resources.pak" ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/media/audio/audio_device_description.cc b/media/audio/audio_device_description.cc index f1e0e89c..9d822a7 100644 --- a/media/audio/audio_device_description.cc +++ b/media/audio/audio_device_description.cc
@@ -4,7 +4,7 @@ #include "base/logging.h" #include "media/audio/audio_device_description.h" -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" namespace media { const char AudioDeviceDescription::kDefaultDeviceId[] = "default";
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index c4bef24..3cc1d2a9 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -12,7 +12,7 @@ #include "base/environment.h" #include "base/logging.h" #include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/nix/xdg_util.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -23,7 +23,7 @@ #include "media/audio/cras/cras_input.h" #include "media/audio/cras/cras_unified.h" #include "media/base/channel_layout.h" -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" // cras_util.h headers pull in min/max macros... // TODO(dgreid): Fix headers such that these aren't imported.
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index 80efe05..29dcccd 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -151,6 +151,8 @@ "key_system_properties.h", "key_systems.cc", "key_systems.h", + "localized_strings.cc", + "localized_strings.h", "loopback_audio_converter.cc", "loopback_audio_converter.h", "media.cc", @@ -166,8 +168,6 @@ "media_observer.h", "media_permission.cc", "media_permission.h", - "media_resources.cc", - "media_resources.h", "media_switches.cc", "media_switches.h", "media_track.cc", @@ -364,8 +364,8 @@ "fake_audio_renderer_sink.h", "fake_demuxer_stream.cc", "fake_demuxer_stream.h", - "fake_media_resources.cc", - "fake_media_resources.h", + "fake_localized_strings.cc", + "fake_localized_strings.h", "fake_single_thread_task_runner.cc", "fake_single_thread_task_runner.h", "fake_text_track_stream.cc",
diff --git a/media/base/fake_media_resources.cc b/media/base/fake_localized_strings.cc similarity index 86% rename from media/base/fake_media_resources.cc rename to media/base/fake_localized_strings.cc index 67ac726..a497483 100644 --- a/media/base/fake_media_resources.cc +++ b/media/base/fake_localized_strings.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/strings/utf_string_conversions.h" -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" namespace media { @@ -14,7 +14,7 @@ return base::ASCIIToUTF16("FakeString"); } -void SetUpFakeMediaResources() { +void SetUpFakeLocalizedStrings() { SetLocalizedStringProvider(FakeLocalizedStringProvider); }
diff --git a/media/base/fake_media_resources.h b/media/base/fake_localized_strings.h similarity index 60% rename from media/base/fake_media_resources.h rename to media/base/fake_localized_strings.h index 9a374bf..29e8f2e3 100644 --- a/media/base/fake_media_resources.h +++ b/media/base/fake_localized_strings.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 MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_ -#define MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_ +#ifndef MEDIA_BASE_FAKE_LOCALIZED_STRINGS_H_ +#define MEDIA_BASE_FAKE_LOCALIZED_STRINGS_H_ namespace media { // Call if tests require non-empty resource strings. -void SetUpFakeMediaResources(); +void SetUpFakeLocalizedStrings(); } // namespace media -#endif // MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_ +#endif // MEDIA_BASE_FAKE_LOCALIZED_STRINGS_H_
diff --git a/media/base/media_resources.cc b/media/base/localized_strings.cc similarity index 94% rename from media/base/media_resources.cc rename to media/base/localized_strings.cc index 3a23632..5c1f24b 100644 --- a/media/base/media_resources.cc +++ b/media/base/localized_strings.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 "media/base/media_resources.h" +#include "media/base/localized_strings.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h"
diff --git a/media/base/media_resources.h b/media/base/localized_strings.h similarity index 92% rename from media/base/media_resources.h rename to media/base/localized_strings.h index 574b96b..0678f9b2 100644 --- a/media/base/media_resources.h +++ b/media/base/localized_strings.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 MEDIA_BASE_MEDIA_RESOURCES_H_ -#define MEDIA_BASE_MEDIA_RESOURCES_H_ +#ifndef MEDIA_BASE_MEDIA_LOCALIZED_STRINGS_H_ +#define MEDIA_BASE_MEDIA_LOCALIZED_STRINGS_H_ #include <string> @@ -55,4 +55,4 @@ } // namespace media -#endif // MEDIA_BASE_MEDIA_RESOURCES_H_ +#endif // MEDIA_BASE_MEDIA_LOCALIZED_STRINGS_H_
diff --git a/media/gpu/vaapi_jpeg_decode_accelerator.cc b/media/gpu/vaapi_jpeg_decode_accelerator.cc index 0303d7d..4b8851cc 100644 --- a/media/gpu/vaapi_jpeg_decode_accelerator.cc +++ b/media/gpu/vaapi_jpeg_decode_accelerator.cc
@@ -12,7 +12,7 @@ #include "base/bind.h" #include "base/logging.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "gpu/ipc/service/gpu_channel.h"
diff --git a/media/gpu/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi_video_decode_accelerator.cc index cd97f57..fcacf90 100644 --- a/media/gpu/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi_video_decode_accelerator.cc
@@ -12,7 +12,7 @@ #include "base/files/scoped_file.h" #include "base/logging.h" #include "base/macros.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/synchronization/waitable_event.h"
diff --git a/media/gpu/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi_video_encode_accelerator.cc index bf77ad7..f44efc6 100644 --- a/media/gpu/vaapi_video_encode_accelerator.cc +++ b/media/gpu/vaapi_video_encode_accelerator.cc
@@ -12,7 +12,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/macros.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h"
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index a92031bd..6450f6a9 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -153,10 +153,6 @@ "//mojo/public/c/system", "//services/service_manager/public/cpp", ] - - data_deps = [ - ":media_manifest", - ] } # crbug.com/676055: media_service_unittests currently fails to link in Windows @@ -210,7 +206,6 @@ data_deps = [ ":media", - ":pipeline_test_manifest", ] }
diff --git a/media/remoting/interstitial.cc b/media/remoting/interstitial.cc index 0a33e22..4e32bd8 100644 --- a/media/remoting/interstitial.cc +++ b/media/remoting/interstitial.cc
@@ -6,7 +6,7 @@ #include <algorithm> // for std::max() -#include "media/base/media_resources.h" +#include "media/base/localized_strings.h" #include "media/base/video_frame.h" #include "media/base/video_renderer_sink.h" #include "media/base/video_util.h"
diff --git a/media/test/run_all_unittests.cc b/media/test/run_all_unittests.cc index 10b42b59..57d384c6 100644 --- a/media/test/run_all_unittests.cc +++ b/media/test/run_all_unittests.cc
@@ -8,7 +8,7 @@ #include "base/test/test_discardable_memory_allocator.h" #include "base/test/test_suite.h" #include "build/build_config.h" -#include "media/base/fake_media_resources.h" +#include "media/base/fake_localized_strings.h" #include "media/base/media.h" #include "media/base/media_switches.h" #include "mojo/edk/embedder/embedder.h" @@ -54,7 +54,7 @@ // Run this here instead of main() to ensure an AtExitManager is already // present. media::InitializeMediaLibrary(); - media::SetUpFakeMediaResources(); + media::SetUpFakeLocalizedStrings(); base::DiscardableMemoryAllocator::SetInstance(&discardable_memory_allocator_); }
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 41d48d4dc2..17cfe7d 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc
@@ -155,11 +155,6 @@ } #endif -ScopedMessagePipeHandle CreateMessagePipe( - ScopedPlatformHandle platform_handle) { - return internal::g_core->CreateMessagePipe(std::move(platform_handle)); -} - ScopedMessagePipeHandle CreateParentMessagePipe( const std::string& token, const std::string& child_token) { return internal::g_core->CreateParentMessagePipe(token, child_token);
diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index c0672aa8..b7ceaa92 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h
@@ -170,15 +170,6 @@ base::PortProvider* port_provider); #endif -// Creates a message pipe over an arbitrary platform channel. The other end of -// the channel must also be passed to this function. Either endpoint can be in -// any process. -// -// Note that the channel is only used to negotiate pipe connection, not as the -// transport for messages on the pipe. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -CreateMessagePipe(ScopedPlatformHandle platform_handle); - // Creates a message pipe from a token. A child embedder must also have this // token and call CreateChildMessagePipe() with it in order for the pipe to get // connected. |child_token| identifies the child process and should be the same
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index c24458a..cfede0e 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn
@@ -58,8 +58,6 @@ "platform_handle_dispatcher.h", "ports_message.cc", "ports_message.h", - "remote_message_pipe_bootstrap.cc", - "remote_message_pipe_bootstrap.h", "request_context.cc", "request_context.h", "shared_buffer_dispatcher.cc", @@ -109,7 +107,6 @@ "broker_host.cc", "broker_posix.cc", "channel_posix.cc", - "remote_message_pipe_bootstrap.cc", ] }
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index 308c2879..a5e432b 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc
@@ -31,7 +31,6 @@ #include "mojo/edk/system/platform_handle_dispatcher.h" #include "mojo/edk/system/ports/name.h" #include "mojo/edk/system/ports/node.h" -#include "mojo/edk/system/remote_message_pipe_bootstrap.h" #include "mojo/edk/system/request_context.h" #include "mojo/edk/system/shared_buffer_dispatcher.h" #include "mojo/edk/system/wait_set_dispatcher.h" @@ -335,23 +334,6 @@ GetNodeController()->RequestShutdown(callback); } -ScopedMessagePipeHandle Core::CreateMessagePipe( - ScopedPlatformHandle platform_handle) { -#if defined(OS_NACL) - NOTREACHED(); - return ScopedMessagePipeHandle(); -#else - ports::PortRef port0, port1; - GetNodeController()->node()->CreatePortPair(&port0, &port1); - MojoHandle handle = AddDispatcher( - new MessagePipeDispatcher(GetNodeController(), port0, - kUnknownPipeIdForDebug, 0)); - RemoteMessagePipeBootstrap::Create( - GetNodeController(), std::move(platform_handle), port1); - return ScopedMessagePipeHandle(MessagePipeHandle(handle)); -#endif -} - ScopedMessagePipeHandle Core::CreateParentMessagePipe( const std::string& token, const std::string& child_token) { RequestContext request_context;
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 21b44b1..db2e8cf 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h
@@ -74,12 +74,6 @@ // Called in a child process exactly once during early initialization. void InitChild(ScopedPlatformHandle platform_handle); - // Creates a message pipe endpoint connected to an endpoint in a remote - // embedder. |platform_handle| is used as a channel to negotiate the - // connection. - ScopedMessagePipeHandle CreateMessagePipe( - ScopedPlatformHandle platform_handle); - // Creates a message pipe endpoint associated with |token|, which a child // holding the token can later locate and connect to. ScopedMessagePipeHandle CreateParentMessagePipe(
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 11bb405..2ba0c388 100644 --- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -1258,44 +1258,6 @@ END_CHILD() } -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BootstrapMessagePipeAsyncClient, - MultiprocessMessagePipeTest, parent) { - // Receive one end of a platform channel from the parent. - MojoHandle channel_handle; - EXPECT_EQ("hi", ReadMessageWithHandles(parent, &channel_handle, 1)); - ScopedPlatformHandle channel; - EXPECT_EQ(MOJO_RESULT_OK, - edk::PassWrappedPlatformHandle(channel_handle, &channel)); - ASSERT_TRUE(channel.is_valid()); - - // Create a new pipe using our end of the channel. - ScopedMessagePipeHandle pipe = edk::CreateMessagePipe(std::move(channel)); - - // Ensure that we can read and write on the new pipe. - VerifyEcho(pipe.get().value(), "goodbye"); -} - -TEST_F(MultiprocessMessagePipeTest, BootstrapMessagePipeAsync) { - // Tests that new cross-process message pipes can be created synchronously - // using asynchronous negotiation over an arbitrary platform channel. - RUN_CHILD_ON_PIPE(BootstrapMessagePipeAsyncClient, child) - // Pass one end of a platform channel to the child. - PlatformChannelPair platform_channel; - MojoHandle client_channel_handle; - EXPECT_EQ(MOJO_RESULT_OK, - CreatePlatformHandleWrapper(platform_channel.PassClientHandle(), - &client_channel_handle)); - WriteMessageWithHandles(child, "hi", &client_channel_handle, 1); - - // Create a new pipe using our end of the channel. - ScopedMessagePipeHandle pipe = - edk::CreateMessagePipe(platform_channel.PassServerHandle()); - - // Ensure that we can read and write on the new pipe. - VerifyEcho(pipe.get().value(), "goodbye"); - END_CHILD() -} - DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient, MultiprocessMessagePipeTest, parent) { // This test verifies that peer closure is detectable through various
diff --git a/mojo/edk/system/remote_message_pipe_bootstrap.cc b/mojo/edk/system/remote_message_pipe_bootstrap.cc deleted file mode 100644 index d376cca..0000000 --- a/mojo/edk/system/remote_message_pipe_bootstrap.cc +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/remote_message_pipe_bootstrap.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/macros.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/ports/name.h" - -namespace mojo { -namespace edk { - -namespace { - -struct BootstrapData { - // The node name of the sender. - ports::NodeName node_name; - - // The port name of the sender's local bootstrap port. - ports::PortName port_name; -}; - -} // namespace - -// static -void RemoteMessagePipeBootstrap::Create( - NodeController* node_controller, - ScopedPlatformHandle platform_handle, - const ports::PortRef& port) { - CHECK(node_controller); - CHECK(node_controller->io_task_runner()); - if (node_controller->io_task_runner()->RunsTasksOnCurrentThread()) { - // Owns itself. - new RemoteMessagePipeBootstrap( - node_controller, std::move(platform_handle), port); - } else { - node_controller->io_task_runner()->PostTask( - FROM_HERE, - base::Bind(&RemoteMessagePipeBootstrap::Create, - base::Unretained(node_controller), - base::Passed(&platform_handle), port)); - } -} - -RemoteMessagePipeBootstrap::~RemoteMessagePipeBootstrap() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - base::MessageLoop::current()->RemoveDestructionObserver(this); - if (channel_) - channel_->ShutDown(); -} - -RemoteMessagePipeBootstrap::RemoteMessagePipeBootstrap( - NodeController* node_controller, - ScopedPlatformHandle platform_handle, - const ports::PortRef& port) - : node_controller_(node_controller), - local_port_(port), - io_task_runner_(base::ThreadTaskRunnerHandle::Get()), - channel_(Channel::Create(this, std::move(platform_handle), - io_task_runner_)) { - base::MessageLoop::current()->AddDestructionObserver(this); - channel_->Start(); - - Channel::MessagePtr message(new Channel::Message(sizeof(BootstrapData), 0)); - BootstrapData* data = static_cast<BootstrapData*>(message->mutable_payload()); - data->node_name = node_controller_->name(); - data->port_name = local_port_.name(); - channel_->Write(std::move(message)); -} - -void RemoteMessagePipeBootstrap::ShutDown() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - if (shutting_down_) - return; - - shutting_down_ = true; - - // Shut down asynchronously so ShutDown() can be called from within - // OnChannelMessage and OnChannelError. - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&RemoteMessagePipeBootstrap::ShutDownNow, - base::Unretained(this))); -} - -void RemoteMessagePipeBootstrap::WillDestroyCurrentMessageLoop() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - ShutDownNow(); -} - -void RemoteMessagePipeBootstrap::OnChannelMessage( - const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(!handles || !handles->size()); - - const BootstrapData* data = static_cast<const BootstrapData*>(payload); - if (peer_info_received_) { - // This should only be a confirmation from the other end, which tells us - // it's now safe to shut down. - if (payload_size != 0) - DLOG(ERROR) << "Unexpected message received in message pipe bootstrap."; - ShutDown(); - return; - } - - if (payload_size != sizeof(BootstrapData)) { - DLOG(ERROR) << "Invalid bootstrap payload."; - ShutDown(); - return; - } - - peer_info_received_ = true; - - // We need to choose one side to initiate the port merge. It doesn't matter - // who does it as long as they don't both try. Simple solution: pick the one - // with the "smaller" port name. - if (local_port_.name() < data->port_name) { - node_controller_->node()->MergePorts(local_port_, data->node_name, - data->port_name); - } - - // Send another ping to the other end to trigger shutdown. This may race with - // the other end sending its own ping, but it doesn't matter. Whoever wins - // will cause the other end to tear down, and the ensuing channel error will - // in turn clean up the remaining end. - - Channel::MessagePtr message(new Channel::Message(0, 0)); - channel_->Write(std::move(message)); -} - -void RemoteMessagePipeBootstrap::OnChannelError() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - ShutDown(); -} - -void RemoteMessagePipeBootstrap::ShutDownNow() { - delete this; -} - -} // namespace edk -} // namespace mojo
diff --git a/mojo/edk/system/remote_message_pipe_bootstrap.h b/mojo/edk/system/remote_message_pipe_bootstrap.h deleted file mode 100644 index 2a24680..0000000 --- a/mojo/edk/system/remote_message_pipe_bootstrap.h +++ /dev/null
@@ -1,89 +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 MOJO_EDK_SYSTEM_REMOTE_MESSAGE_PIPE_BOOTSTRAP_H_ -#define MOJO_EDK_SYSTEM_REMOTE_MESSAGE_PIPE_BOOTSTRAP_H_ - -#include <string> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/channel.h" -#include "mojo/edk/system/ports/name.h" -#include "mojo/edk/system/ports/port_ref.h" - -namespace mojo { -namespace edk { - -class NodeController; - -// This is used by Core to negotiate a new cross-process message pipe given -// an arbitrary platform channel. Both ends of the channel must be passed to -// RemoteMessagePipeBootstrap::Create() in their respective processes. -// -// The bootstrapping procedure the same on either end: -// -// 1. Select a local port P to be merged with a remote port. -// 2. Write the local node name and P's name to the bootstrap pipe. -// 3. When a message is read from the pipe: -// - If it's the first message read, extract the remote node+port name and -// and send an empty ACK message on the pipe. -// - If it's the second message read, close the channel, and delete |this|. -// 4. When an error occus on the pipe, delete |this|. -// -// Excluding irrecoverable error conditions such as either process dying, -// armageddon, etc., this ensures neither end closes the channel until both ends -// are aware of each other's port-to-merge. -// -// At step 3, one side of the channel is chosen to issue a message at the Ports -// layer which eventually merges the two ports. -class RemoteMessagePipeBootstrap - : public Channel::Delegate, - public base::MessageLoop::DestructionObserver { - public: - ~RemoteMessagePipeBootstrap() override; - - // |port| must be a reference to an uninitialized local port. - static void Create(NodeController* node_controller, - ScopedPlatformHandle platform_handle, - const ports::PortRef& port); - - protected: - explicit RemoteMessagePipeBootstrap(NodeController* node_controller, - ScopedPlatformHandle platform_handle, - const ports::PortRef& port); - - void ShutDown(); - - bool shutting_down_ = false; - NodeController* node_controller_; - const ports::PortRef local_port_; - - scoped_refptr<base::TaskRunner> io_task_runner_; - scoped_refptr<Channel> channel_; - - bool peer_info_received_ = false; - - private: - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override; - - // Channel::Delegate: - void OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) override; - void OnChannelError() override; - - void ShutDownNow(); - - DISALLOW_COPY_AND_ASSIGN(RemoteMessagePipeBootstrap); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_REMOTE_MESSAGE_PIPE_BOOTSTRAP_H_
diff --git a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc index f556c4c2..5ae763b 100644 --- a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc +++ b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
@@ -13,7 +13,7 @@ namespace mojo { namespace { -base::LazyInstance<base::ThreadLocalPointer<SyncHandleRegistry>> +base::LazyInstance<base::ThreadLocalPointer<SyncHandleRegistry>>::Leaky g_current_sync_handle_watcher = LAZY_INSTANCE_INITIALIZER; } // namespace
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc index 0b280ca..608f870 100644 --- a/net/base/mime_sniffer.cc +++ b/net/base/mime_sniffer.cc
@@ -116,7 +116,7 @@ }; #define MAGIC_NUMBER(mime_type, magic) \ - { (mime_type), (magic), sizeof(magic)-1, false, NULL }, + { (mime_type), (magic), sizeof(magic)-1, false, NULL } template <int MagicSize, int MaskSize> class VerifySizes { @@ -130,46 +130,46 @@ VerifySizes<sizeof(magic), sizeof(mask)>::SIZES #define MAGIC_MASK(mime_type, magic, mask) \ - { (mime_type), (magic), verified_sizeof(magic, mask)-1, false, (mask) }, + { (mime_type), (magic), verified_sizeof(magic, mask)-1, false, (mask) } // Magic strings are case insensitive and must not include '\0' characters #define MAGIC_STRING(mime_type, magic) \ - { (mime_type), (magic), sizeof(magic)-1, true, NULL }, + { (mime_type), (magic), sizeof(magic)-1, true, NULL } static const MagicNumber kMagicNumbers[] = { // Source: HTML 5 specification - MAGIC_NUMBER("application/pdf", "%PDF-") - MAGIC_NUMBER("application/postscript", "%!PS-Adobe-") - MAGIC_NUMBER("image/gif", "GIF87a") - MAGIC_NUMBER("image/gif", "GIF89a") - MAGIC_NUMBER("image/png", "\x89" "PNG\x0D\x0A\x1A\x0A") - MAGIC_NUMBER("image/jpeg", "\xFF\xD8\xFF") - MAGIC_NUMBER("image/bmp", "BM") + MAGIC_NUMBER("application/pdf", "%PDF-"), + MAGIC_NUMBER("application/postscript", "%!PS-Adobe-"), + MAGIC_NUMBER("image/gif", "GIF87a"), + MAGIC_NUMBER("image/gif", "GIF89a"), + MAGIC_NUMBER("image/png", "\x89" "PNG\x0D\x0A\x1A\x0A"), + MAGIC_NUMBER("image/jpeg", "\xFF\xD8\xFF"), + MAGIC_NUMBER("image/bmp", "BM"), // Source: Mozilla - MAGIC_NUMBER("text/plain", "#!") // Script - MAGIC_NUMBER("text/plain", "%!") // Script, similar to PS - MAGIC_NUMBER("text/plain", "From") - MAGIC_NUMBER("text/plain", ">From") + MAGIC_NUMBER("text/plain", "#!"), // Script + MAGIC_NUMBER("text/plain", "%!"), // Script, similar to PS + MAGIC_NUMBER("text/plain", "From"), + MAGIC_NUMBER("text/plain", ">From"), // Chrome specific - MAGIC_NUMBER("application/x-gzip", "\x1F\x8B\x08") - MAGIC_NUMBER("audio/x-pn-realaudio", "\x2E\x52\x4D\x46") + MAGIC_NUMBER("application/x-gzip", "\x1F\x8B\x08"), + MAGIC_NUMBER("audio/x-pn-realaudio", "\x2E\x52\x4D\x46"), MAGIC_NUMBER("video/x-ms-asf", - "\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C") - MAGIC_NUMBER("image/tiff", "I I") - MAGIC_NUMBER("image/tiff", "II*") - MAGIC_NUMBER("image/tiff", "MM\x00*") - MAGIC_NUMBER("audio/mpeg", "ID3") - MAGIC_NUMBER("image/webp", "RIFF....WEBPVP8 ") - MAGIC_NUMBER("video/webm", "\x1A\x45\xDF\xA3") - MAGIC_NUMBER("application/zip", "PK\x03\x04") - MAGIC_NUMBER("application/x-rar-compressed", "Rar!\x1A\x07\x00") - MAGIC_NUMBER("application/x-msmetafile", "\xD7\xCD\xC6\x9A") - MAGIC_NUMBER("application/octet-stream", "MZ") // EXE + "\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C"), + MAGIC_NUMBER("image/tiff", "I I"), + MAGIC_NUMBER("image/tiff", "II*"), + MAGIC_NUMBER("image/tiff", "MM\x00*"), + MAGIC_NUMBER("audio/mpeg", "ID3"), + MAGIC_NUMBER("image/webp", "RIFF....WEBPVP8 "), + MAGIC_NUMBER("video/webm", "\x1A\x45\xDF\xA3"), + MAGIC_NUMBER("application/zip", "PK\x03\x04"), + MAGIC_NUMBER("application/x-rar-compressed", "Rar!\x1A\x07\x00"), + MAGIC_NUMBER("application/x-msmetafile", "\xD7\xCD\xC6\x9A"), + MAGIC_NUMBER("application/octet-stream", "MZ"), // EXE // Sniffing for Flash: // - // MAGIC_NUMBER("application/x-shockwave-flash", "CWS") - // MAGIC_NUMBER("application/x-shockwave-flash", "FLV") - // MAGIC_NUMBER("application/x-shockwave-flash", "FWS") + // MAGIC_NUMBER("application/x-shockwave-flash", "CWS"), + // MAGIC_NUMBER("application/x-shockwave-flash", "FLV"), + // MAGIC_NUMBER("application/x-shockwave-flash", "FWS"), // // Including these magic number for Flash is a trade off. // @@ -190,8 +190,8 @@ static const size_t kBytesRequiredForOfficeMagic = 8; static const MagicNumber kOfficeMagicNumbers[] = { - MAGIC_NUMBER("CFB", "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1") - MAGIC_NUMBER("OOXML", "PK\x03\x04") + MAGIC_NUMBER("CFB", "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"), + MAGIC_NUMBER("OOXML", "PK\x03\x04"), }; enum OfficeDocType { @@ -208,49 +208,49 @@ }; #define OFFICE_EXTENSION(type, extension) \ - { (type), (extension), sizeof(extension) - 1 }, + { (type), (extension), sizeof(extension) - 1 } static const OfficeExtensionType kOfficeExtensionTypes[] = { - OFFICE_EXTENSION(DOC_TYPE_WORD, ".doc") - OFFICE_EXTENSION(DOC_TYPE_EXCEL, ".xls") - OFFICE_EXTENSION(DOC_TYPE_POWERPOINT, ".ppt") - OFFICE_EXTENSION(DOC_TYPE_WORD, ".docx") - OFFICE_EXTENSION(DOC_TYPE_EXCEL, ".xlsx") - OFFICE_EXTENSION(DOC_TYPE_POWERPOINT, ".pptx") + OFFICE_EXTENSION(DOC_TYPE_WORD, ".doc"), + OFFICE_EXTENSION(DOC_TYPE_EXCEL, ".xls"), + OFFICE_EXTENSION(DOC_TYPE_POWERPOINT, ".ppt"), + OFFICE_EXTENSION(DOC_TYPE_WORD, ".docx"), + OFFICE_EXTENSION(DOC_TYPE_EXCEL, ".xlsx"), + OFFICE_EXTENSION(DOC_TYPE_POWERPOINT, ".pptx"), }; static const MagicNumber kExtraMagicNumbers[] = { - MAGIC_NUMBER("image/x-xbitmap", "#define") - MAGIC_NUMBER("image/x-icon", "\x00\x00\x01\x00") - MAGIC_NUMBER("image/svg+xml", "<?xml_version=") - MAGIC_NUMBER("audio/wav", "RIFF....WAVEfmt ") - MAGIC_NUMBER("video/avi", "RIFF....AVI LIST") - MAGIC_NUMBER("audio/ogg", "OggS") - MAGIC_MASK("video/mpeg", "\x00\x00\x01\xB0", "\xFF\xFF\xFF\xF0") - MAGIC_MASK("audio/mpeg", "\xFF\xE0", "\xFF\xE0") - MAGIC_NUMBER("video/3gpp", "....ftyp3g") - MAGIC_NUMBER("video/3gpp", "....ftypavcl") - MAGIC_NUMBER("video/mp4", "....ftyp") - MAGIC_NUMBER("video/quicktime", "....moov") - MAGIC_NUMBER("application/x-shockwave-flash", "CWS") - MAGIC_NUMBER("application/x-shockwave-flash", "FWS") - MAGIC_NUMBER("video/x-flv", "FLV") - MAGIC_NUMBER("audio/x-flac", "fLaC") + MAGIC_NUMBER("image/x-xbitmap", "#define"), + MAGIC_NUMBER("image/x-icon", "\x00\x00\x01\x00"), + MAGIC_NUMBER("image/svg+xml", "<?xml_version="), + MAGIC_NUMBER("audio/wav", "RIFF....WAVEfmt "), + MAGIC_NUMBER("video/avi", "RIFF....AVI LIST"), + MAGIC_NUMBER("audio/ogg", "OggS\0"), + MAGIC_MASK("video/mpeg", "\x00\x00\x01\xB0", "\xFF\xFF\xFF\xF0"), + MAGIC_MASK("audio/mpeg", "\xFF\xE0", "\xFF\xE0"), + MAGIC_NUMBER("video/3gpp", "....ftyp3g"), + MAGIC_NUMBER("video/3gpp", "....ftypavcl"), + MAGIC_NUMBER("video/mp4", "....ftyp"), + MAGIC_NUMBER("video/quicktime", "....moov"), + MAGIC_NUMBER("application/x-shockwave-flash", "CWS"), + MAGIC_NUMBER("application/x-shockwave-flash", "FWS"), + MAGIC_NUMBER("video/x-flv", "FLV"), + MAGIC_NUMBER("audio/x-flac", "fLaC"), // RAW image types. - MAGIC_NUMBER("image/x-canon-cr2", "II\x2a\x00\x10\x00\x00\x00CR") - MAGIC_NUMBER("image/x-canon-crw", "II\x1a\x00\x00\x00HEAPCCDR") - MAGIC_NUMBER("image/x-minolta-mrw", "\x00MRM") - MAGIC_NUMBER("image/x-olympus-orf", "MMOR") // big-endian - MAGIC_NUMBER("image/x-olympus-orf", "IIRO") // little-endian - MAGIC_NUMBER("image/x-olympus-orf", "IIRS") // little-endian - MAGIC_NUMBER("image/x-fuji-raf", "FUJIFILMCCD-RAW ") + MAGIC_NUMBER("image/x-canon-cr2", "II\x2a\x00\x10\x00\x00\x00CR"), + MAGIC_NUMBER("image/x-canon-crw", "II\x1a\x00\x00\x00HEAPCCDR"), + MAGIC_NUMBER("image/x-minolta-mrw", "\x00MRM"), + MAGIC_NUMBER("image/x-olympus-orf", "MMOR"), // big-endian + MAGIC_NUMBER("image/x-olympus-orf", "IIRO"), // little-endian + MAGIC_NUMBER("image/x-olympus-orf", "IIRS"), // little-endian + MAGIC_NUMBER("image/x-fuji-raf", "FUJIFILMCCD-RAW "), MAGIC_NUMBER("image/x-panasonic-raw", - "IIU\x00\x08\x00\x00\x00") // Panasonic .raw + "IIU\x00\x08\x00\x00\x00"), // Panasonic .raw MAGIC_NUMBER("image/x-panasonic-raw", - "IIU\x00\x18\x00\x00\x00") // Panasonic .rw2 - MAGIC_NUMBER("image/x-phaseone-raw", "MMMMRaw") - MAGIC_NUMBER("image/x-x3f", "FOVb") + "IIU\x00\x18\x00\x00\x00"), // Panasonic .rw2 + MAGIC_NUMBER("image/x-phaseone-raw", "MMMMRaw"), + MAGIC_NUMBER("image/x-x3f", "FOVb"), }; // Our HTML sniffer differs slightly from Mozilla. For example, Mozilla will @@ -264,26 +264,26 @@ // XML processing directive. Although this is not an HTML mime type, we sniff // for this in the HTML phase because text/xml is just as powerful as HTML and // we want to leverage our white space skipping technology. - MAGIC_NUMBER("text/xml", "<?xml") // Mozilla + MAGIC_NUMBER("text/xml", "<?xml"), // Mozilla // DOCTYPEs - MAGIC_HTML_TAG("!DOCTYPE html") // HTML5 spec + MAGIC_HTML_TAG("!DOCTYPE html"), // HTML5 spec // Sniffable tags, ordered by how often they occur in sniffable documents. - MAGIC_HTML_TAG("script") // HTML5 spec, Mozilla - MAGIC_HTML_TAG("html") // HTML5 spec, Mozilla - MAGIC_HTML_TAG("!--") - MAGIC_HTML_TAG("head") // HTML5 spec, Mozilla - MAGIC_HTML_TAG("iframe") // Mozilla - MAGIC_HTML_TAG("h1") // Mozilla - MAGIC_HTML_TAG("div") // Mozilla - MAGIC_HTML_TAG("font") // Mozilla - MAGIC_HTML_TAG("table") // Mozilla - MAGIC_HTML_TAG("a") // Mozilla - MAGIC_HTML_TAG("style") // Mozilla - MAGIC_HTML_TAG("title") // Mozilla - MAGIC_HTML_TAG("b") // Mozilla - MAGIC_HTML_TAG("body") // Mozilla - MAGIC_HTML_TAG("br") - MAGIC_HTML_TAG("p") // Mozilla + MAGIC_HTML_TAG("script"), // HTML5 spec, Mozilla + MAGIC_HTML_TAG("html"), // HTML5 spec, Mozilla + MAGIC_HTML_TAG("!--"), + MAGIC_HTML_TAG("head"), // HTML5 spec, Mozilla + MAGIC_HTML_TAG("iframe"), // Mozilla + MAGIC_HTML_TAG("h1"), // Mozilla + MAGIC_HTML_TAG("div"), // Mozilla + MAGIC_HTML_TAG("font"), // Mozilla + MAGIC_HTML_TAG("table"), // Mozilla + MAGIC_HTML_TAG("a"), // Mozilla + MAGIC_HTML_TAG("style"), // Mozilla + MAGIC_HTML_TAG("title"), // Mozilla + MAGIC_HTML_TAG("b"), // Mozilla + MAGIC_HTML_TAG("body"), // Mozilla + MAGIC_HTML_TAG("br"), + MAGIC_HTML_TAG("p"), // Mozilla }; // Compare content header to a magic number where magic_entry can contain '.' @@ -547,9 +547,9 @@ // So we match explicitly on this, and don't match other ways of writing // it in semantically-equivalent ways. MAGIC_STRING("application/xhtml+xml", - "<html xmlns=\"http://www.w3.org/1999/xhtml\"") - MAGIC_STRING("application/atom+xml", "<feed") - MAGIC_STRING("application/rss+xml", "<rss") // UTF-8 + "<html xmlns=\"http://www.w3.org/1999/xhtml\""), + MAGIC_STRING("application/atom+xml", "<feed"), + MAGIC_STRING("application/rss+xml", "<rss"), // UTF-8 }; // Returns true and sets result if the content appears to contain XHTML or a @@ -620,9 +620,9 @@ // Byte order marks static const MagicNumber kByteOrderMark[] = { - MAGIC_NUMBER("text/plain", "\xFE\xFF") // UTF-16BE - MAGIC_NUMBER("text/plain", "\xFF\xFE") // UTF-16LE - MAGIC_NUMBER("text/plain", "\xEF\xBB\xBF") // UTF-8 + MAGIC_NUMBER("text/plain", "\xFE\xFF"), // UTF-16BE + MAGIC_NUMBER("text/plain", "\xFF\xFE"), // UTF-16LE + MAGIC_NUMBER("text/plain", "\xEF\xBB\xBF"), // UTF-8 }; // Returns true and sets result to "application/octet-stream" if the content
diff --git a/net/base/mime_sniffer_unittest.cc b/net/base/mime_sniffer_unittest.cc index 6e52baf5..590dd77 100644 --- a/net/base/mime_sniffer_unittest.cc +++ b/net/base/mime_sniffer_unittest.cc
@@ -454,18 +454,27 @@ // RAW images. TEST(MimeSnifferTest, AudioVideoTest) { std::string mime_type; + const char kOggTestData[] = "OggS\x00"; + EXPECT_TRUE(SniffMimeTypeFromLocalData(kOggTestData, sizeof(kOggTestData) - 1, + &mime_type)); + EXPECT_EQ("audio/ogg", mime_type); + mime_type.clear(); + // Check ogg header requires the terminal '\0' to be sniffed. + EXPECT_FALSE(SniffMimeTypeFromLocalData( + kOggTestData, sizeof(kOggTestData) - 2, &mime_type)); + EXPECT_EQ("", mime_type); + mime_type.clear(); + const char kFlacTestData[] = "fLaC\x00\x00\x00\x22\x12\x00\x12\x00\x00\x00\x00\x00"; - EXPECT_TRUE(SniffMimeTypeFromLocalData(kFlacTestData, - sizeof(kFlacTestData), - &mime_type)); + EXPECT_TRUE(SniffMimeTypeFromLocalData( + kFlacTestData, sizeof(kFlacTestData) - 1, &mime_type)); EXPECT_EQ("audio/x-flac", mime_type); mime_type.clear(); const char kWMATestData[] = "\x30\x26\xb2\x75\x8e\x66\xcf\x11\xa6\xd9\x00\xaa\x00\x62\xce\x6c"; - EXPECT_TRUE(SniffMimeTypeFromLocalData(kWMATestData, - sizeof(kWMATestData), + EXPECT_TRUE(SniffMimeTypeFromLocalData(kWMATestData, sizeof(kWMATestData) - 1, &mime_type)); EXPECT_EQ("video/x-ms-asf", mime_type); mime_type.clear(); @@ -474,16 +483,14 @@ // format. const char kMP4TestData[] = "\x00\x00\x00\x20\x66\x74\x79\x70\x4d\x34\x41\x20\x00\x00\x00\x00"; - EXPECT_TRUE(SniffMimeTypeFromLocalData(kMP4TestData, - sizeof(kMP4TestData), + EXPECT_TRUE(SniffMimeTypeFromLocalData(kMP4TestData, sizeof(kMP4TestData) - 1, &mime_type)); EXPECT_EQ("video/mp4", mime_type); mime_type.clear(); const char kAACTestData[] = "\xff\xf1\x50\x80\x02\x20\xb0\x23\x0a\x83\x20\x7d\x61\x90\x3e\xb1"; - EXPECT_TRUE(SniffMimeTypeFromLocalData(kAACTestData, - sizeof(kAACTestData), + EXPECT_TRUE(SniffMimeTypeFromLocalData(kAACTestData, sizeof(kAACTestData) - 1, &mime_type)); EXPECT_EQ("audio/mpeg", mime_type); mime_type.clear();
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index ab340cd4..a7aa7e9 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h
@@ -29,7 +29,8 @@ // Describes the kind of connection used to fetch this response. // // NOTE: Please keep in sync with Net.HttpResponseInfo.ConnectionInfo - // histogram. Because of that, and also because these values are persisted to + // histogram in tools/metrics/histograms/histograms.xml. + // Because of that, and also because these values are persisted to // the cache, please make sure not to delete or reorder values. enum ConnectionInfo { CONNECTION_INFO_UNKNOWN = 0,
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc index 4308c62..bbca1e3 100644 --- a/net/quic/core/quic_connection.cc +++ b/net/quic/core/quic_connection.cc
@@ -249,7 +249,6 @@ time_of_last_received_packet_(clock_->ApproximateNow()), time_of_last_sent_new_packet_(clock_->ApproximateNow()), last_send_for_timeout_(clock_->ApproximateNow()), - packet_number_of_last_sent_packet_(0), sent_packet_manager_(perspective, clock_, &stats_, kCubicBytes, kNack), version_negotiation_state_(START_NEGOTIATION), perspective_(perspective), @@ -1527,11 +1526,6 @@ } QuicPacketNumber packet_number = packet->packet_number; - // TODO(ianswett): Remove packet_number_of_last_sent_packet_ because it's - // redundant to SentPacketManager_->GetLargestPacket in most cases, and wrong - // for multipath. - DCHECK_LE(packet_number_of_last_sent_packet_, packet_number); - packet_number_of_last_sent_packet_ = packet_number; QuicPacketLength encrypted_length = packet->encrypted_length; // Termination packets are eventually owned by TimeWaitListManager. @@ -1627,7 +1621,7 @@ last_send_for_timeout_ = packet_send_time; } SetPingAlarm(); - MaybeSetMtuAlarm(); + MaybeSetMtuAlarm(packet_number); QUIC_DVLOG(1) << ENDPOINT << "time we began writing last sent packet: " << packet_send_time.ToDebuggingValue(); @@ -2147,7 +2141,7 @@ QuicTime::Delta::FromMilliseconds(1)); } -void QuicConnection::MaybeSetMtuAlarm() { +void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) { // Do not set the alarm if the target size is less than the current size. // This covers the case when |mtu_discovery_target_| is at its default value, // zero. @@ -2163,7 +2157,7 @@ return; } - if (packet_number_of_last_sent_packet_ >= next_mtu_probe_at_) { + if (sent_packet_number >= next_mtu_probe_at_) { // Use an alarm to send the MTU probe to ensure that no ScopedPacketBundlers // are active. mtu_discovery_alarm_->Set(clock_->ApproximateNow()); @@ -2336,8 +2330,8 @@ // MaybeSetMtuAlarm() will not realize that the probe has been just sent, and // will reschedule this probe again. packets_between_mtu_probes_ *= 2; - next_mtu_probe_at_ = - packet_number_of_last_sent_packet_ + packets_between_mtu_probes_ + 1; + next_mtu_probe_at_ = sent_packet_manager_.GetLargestSentPacket() + + packets_between_mtu_probes_ + 1; ++mtu_probe_count_; QUIC_DVLOG(2) << "Sending a path MTU discovery packet #" << mtu_probe_count_; @@ -2375,7 +2369,7 @@ << ", migrating connection."; highest_packet_sent_before_peer_migration_ = - packet_number_of_last_sent_packet_; + sent_packet_manager_.GetLargestSentPacket(); peer_address_ = last_packet_source_address_; active_peer_migration_type_ = peer_migration_type;
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h index 666d03b..c936e210 100644 --- a/net/quic/core/quic_connection.h +++ b/net/quic/core/quic_connection.h
@@ -645,10 +645,6 @@ const bool already_delayed_; }; - QuicPacketNumber packet_number_of_last_sent_packet() const { - return packet_number_of_last_sent_packet_; - } - QuicPacketWriter* writer() { return writer_; } const QuicPacketWriter* writer() const { return writer_; } @@ -822,7 +818,8 @@ void SetRetransmissionAlarm(); // Sets the MTU discovery alarm if necessary. - void MaybeSetMtuAlarm(); + // |sent_packet_number| is the recently sent packet number. + void MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number); HasRetransmittableData IsRetransmittable(const SerializedPacket& packet); bool IsTerminationPacket(const SerializedPacket& packet); @@ -1023,10 +1020,6 @@ // |time_of_last_received_packet_|. QuicTime last_send_for_timeout_; - // packet number of the last sent packet. Packets are guaranteed to be sent - // in packet number order. - QuicPacketNumber packet_number_of_last_sent_packet_; - // Sent packet manager which tracks the status of packets sent by this // connection and contains the send and receive algorithms to determine when // to send packets.
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index 1c0d6e5..86f5196 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -69,7 +69,7 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_36_v3, true) // If true, use async codepaths to invoke ProofSource::GetProof. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_enable_async_get_proof, true) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_enable_async_get_proof, false) // If true, only open limited number of quic sessions per epoll event. Leave the // rest to next event. @@ -211,9 +211,9 @@ // Allow quic to properly support proxying 100 Continue responses. QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_supports_100_continue, false) -// If true, enable QUIC v38. +// If true, enable quic version 38 QUIC_FLAG(bool, FLAGS_quic_enable_version_38, false) -// Log information about whether the connection is application-limited -// into QUIC BBR traces. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_log_app_limited, false) +// When true, ensures the session's flow control window is always at least 1.5x +// larger than the largest stream flow control window. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_flow_control_invariant, false)
diff --git a/net/quic/core/quic_flow_controller.cc b/net/quic/core/quic_flow_controller.cc index 976c0ff1..274831c 100644 --- a/net/quic/core/quic_flow_controller.cc +++ b/net/quic/core/quic_flow_controller.cc
@@ -17,12 +17,14 @@ #define ENDPOINT \ (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ") -QuicFlowController::QuicFlowController(QuicConnection* connection, - QuicStreamId id, - Perspective perspective, - QuicStreamOffset send_window_offset, - QuicStreamOffset receive_window_offset, - bool should_auto_tune_receive_window) +QuicFlowController::QuicFlowController( + QuicConnection* connection, + QuicStreamId id, + Perspective perspective, + QuicStreamOffset send_window_offset, + QuicStreamOffset receive_window_offset, + bool should_auto_tune_receive_window, + QuicFlowControllerInterface* session_flow_controller) : connection_(connection), id_(id), perspective_(perspective), @@ -33,6 +35,7 @@ receive_window_offset_(receive_window_offset), receive_window_size_(receive_window_offset), auto_tune_receive_window_(should_auto_tune_receive_window), + session_flow_controller_(session_flow_controller), last_blocked_send_window_offset_(0), prev_window_update_time_(QuicTime::Zero()) { receive_window_size_limit_ = (id_ == kConnectionLevelId) @@ -141,17 +144,18 @@ // is no need to increase receive_window_size_. return; } - QuicByteCount old_window = receive_window_size_; - receive_window_size_ *= 2; - receive_window_size_ = - std::min(receive_window_size_, receive_window_size_limit_); + IncreaseWindowSize(); if (receive_window_size_ > old_window) { QUIC_DVLOG(1) << ENDPOINT << "New max window increase for stream " << id_ << " after " << since_last.ToMicroseconds() << " us, and RTT is " << rtt.ToMicroseconds() << "us. max wndw: " << receive_window_size_; + if (session_flow_controller_ != nullptr) { + session_flow_controller_->EnsureWindowAtLeast( + kSessionFlowControlMultiplier * receive_window_size_); + } } else { // TODO(ckrasic) - add a varz to track this (?). QUIC_LOG_FIRST_N(INFO, 1) << ENDPOINT << "Max window at limit for stream " @@ -161,6 +165,12 @@ } } +void QuicFlowController::IncreaseWindowSize() { + receive_window_size_ *= 2; + receive_window_size_ = + std::min(receive_window_size_, receive_window_size_limit_); +} + QuicByteCount QuicFlowController::WindowUpdateThreshold() { return receive_window_size_ / 2; } @@ -181,14 +191,17 @@ } MaybeIncreaseMaxWindowSize(); + SendWindowUpdate(available_window); +} +void QuicFlowController::SendWindowUpdate(QuicStreamOffset available_window) { // Update our receive window. receive_window_offset_ += (receive_window_size_ - available_window); QUIC_DVLOG(1) << ENDPOINT << "Sending WindowUpdate frame for stream " << id_ << ", consumed bytes: " << bytes_consumed_ << ", available window: " << available_window - << ", and threshold: " << threshold + << ", and threshold: " << WindowUpdateThreshold() << ", and receive window size: " << receive_window_size_ << ". New receive window offset is: " << receive_window_offset_; @@ -231,6 +244,16 @@ return blocked; } +void QuicFlowController::EnsureWindowAtLeast(QuicByteCount window_size) { + if (receive_window_size_limit_ >= window_size) { + return; + } + + QuicStreamOffset available_window = receive_window_offset_ - bytes_consumed_; + IncreaseWindowSize(); + SendWindowUpdate(available_window); +} + bool QuicFlowController::IsBlocked() const { return SendWindowSize() == 0; }
diff --git a/net/quic/core/quic_flow_controller.h b/net/quic/core/quic_flow_controller.h index 94225636c..b955da15 100644 --- a/net/quic/core/quic_flow_controller.h +++ b/net/quic/core/quic_flow_controller.h
@@ -19,20 +19,35 @@ const QuicStreamId kConnectionLevelId = 0; +// How much larger the session flow control window needs to be relative to any +// stream's flow control window. +const float kSessionFlowControlMultiplier = 1.5; + +class QUIC_EXPORT_PRIVATE QuicFlowControllerInterface { + public: + virtual ~QuicFlowControllerInterface() {} + + // Ensures the flow control window is at least |window_size| and send out an + // update frame if it is increased. + virtual void EnsureWindowAtLeast(QuicByteCount window_size) = 0; +}; + // QuicFlowController allows a QUIC stream or connection to perform flow // control. The stream/connection owns a QuicFlowController which keeps track of // bytes sent/received, can tell the owner if it is flow control blocked, and // can send WINDOW_UPDATE or BLOCKED frames when needed. -class QUIC_EXPORT_PRIVATE QuicFlowController { +class QUIC_EXPORT_PRIVATE QuicFlowController + : public QuicFlowControllerInterface { public: QuicFlowController(QuicConnection* connection, QuicStreamId id, Perspective perspective, - QuicStreamOffset send_window_offset, - QuicStreamOffset receive_window_offset, - bool should_auto_tune_receive_window); + QuicStreamOffset send_window_size, + QuicStreamOffset receive_window_size, + bool should_auto_tune_receive_window, + QuicFlowControllerInterface* session_flow_controller); - ~QuicFlowController() {} + ~QuicFlowController() override {} // Called when we see a new highest received byte offset from the peer, either // via a data frame or a RST. @@ -51,6 +66,9 @@ // Returns true if this increases send_window_offset_ and is now blocked. bool UpdateSendWindowOffset(QuicStreamOffset new_send_window_offset); + // QuicFlowControllerInterface. + void EnsureWindowAtLeast(QuicByteCount window_size) override; + // Returns the current available send window. QuicByteCount SendWindowSize() const; @@ -92,6 +110,12 @@ // Auto-tune the max receive window size. void MaybeIncreaseMaxWindowSize(); + // Updates the current offset and sends a window update frame. + void SendWindowUpdate(QuicStreamOffset available_window); + + // Double the window size as long as we haven't hit the max window size. + void IncreaseWindowSize(); + // The parent connection, used to send connection close on flow control // violation, and WINDOW_UPDATE and BLOCKED frames when appropriate. // Not owned. @@ -152,6 +176,11 @@ // Used to dynamically enable receive window auto-tuning. bool auto_tune_receive_window_; + // The session's flow controller. null if this is stream id 0 or + // FLAGS_quic_reloadable_flag_quic_flow_control_invariant is false. + // Not owned. + QuicFlowControllerInterface* session_flow_controller_; + // Send window update when receive window size drops below this. QuicByteCount WindowUpdateThreshold();
diff --git a/net/quic/core/quic_flow_controller_test.cc b/net/quic/core/quic_flow_controller_test.cc index 93a07a5..4b4bd76 100644 --- a/net/quic/core/quic_flow_controller_test.cc +++ b/net/quic/core/quic_flow_controller_test.cc
@@ -22,6 +22,17 @@ // Receive window auto-tuning uses RTT in its logic. const int64_t kRtt = 100; +class MockFlowController : public QuicFlowControllerInterface { + public: + MockFlowController() {} + ~MockFlowController() override {} + + MOCK_METHOD1(EnsureWindowAtLeast, void(QuicByteCount)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockFlowController); +}; + class QuicFlowControllerTest : public ::testing::Test { public: QuicFlowControllerTest() @@ -31,9 +42,9 @@ connection_(&helper_, &alarm_factory_, Perspective::IS_CLIENT) {} void Initialize() { - flow_controller_.reset( - new QuicFlowController(&connection_, stream_id_, Perspective::IS_CLIENT, - send_window_, receive_window_, false)); + flow_controller_.reset(new QuicFlowController( + &connection_, stream_id_, Perspective::IS_CLIENT, send_window_, + receive_window_, false, &session_flow_controller_)); } protected: @@ -44,6 +55,7 @@ MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; MockQuicConnection connection_; + MockFlowController session_flow_controller_; }; TEST_F(QuicFlowControllerTest, SendingBytes) { @@ -195,6 +207,10 @@ // Move time forward, but by less than two RTTs. Then receive and consume // some more, forcing a second WINDOW_UPDATE with an increased max window // size. + EXPECT_CALL( + session_flow_controller_, + EnsureWindowAtLeast(kInitialSessionFlowControlWindowForTest * 2 * 1.5)); + connection_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2 * kRtt - 1)); receive_offset += threshold + 1; EXPECT_TRUE(flow_controller_->UpdateHighestReceivedOffset(receive_offset));
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc index 117de38..09f0617 100644 --- a/net/quic/core/quic_headers_stream_test.cc +++ b/net/quic/core/quic_headers_stream_test.cc
@@ -15,6 +15,7 @@ #include "net/quic/core/spdy_utils.h" #include "net/quic/platform/api/quic_bug_tracker.h" #include "net/quic/platform/api/quic_logging.h" +#include "net/quic/platform/api/quic_ptr_util.h" #include "net/quic/platform/api/quic_str_cat.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" @@ -228,8 +229,6 @@ session_(connection_), headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)), body_("hello world"), - hpack_encoder_visitor_(new StrictMock<MockQuicHpackDebugVisitor>), - hpack_decoder_visitor_(new StrictMock<MockQuicHpackDebugVisitor>), stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""), next_promised_stream_id_(2) { headers_[":version"] = "HTTP/1.1"; @@ -398,8 +397,6 @@ string saved_payloads_; std::unique_ptr<SpdyFramer> framer_; StrictMock<MockVisitor> visitor_; - std::unique_ptr<StrictMock<MockQuicHpackDebugVisitor>> hpack_encoder_visitor_; - std::unique_ptr<StrictMock<MockQuicHpackDebugVisitor>> hpack_decoder_visitor_; QuicStreamFrame stream_frame_; QuicStreamId next_promised_stream_id_; }; @@ -849,16 +846,8 @@ } TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) { - StrictMock<MockQuicHpackDebugVisitor>* hpack_decoder_visitor = - hpack_decoder_visitor_.get(); - QuicSpdySessionPeer::SetHpackDecoderDebugVisitor( - &session_, std::move(hpack_decoder_visitor_)); - - // Create some headers we expect to generate entries in HPACK's - // dynamic table, in addition to content-length. - headers_["key0"] = string(1 << 1, '.'); - headers_["key1"] = string(1 << 2, '.'); - headers_["key2"] = string(1 << 3, '.'); + auto hpack_decoder_visitor = + QuicMakeUnique<StrictMock<MockQuicHpackDebugVisitor>>(); { InSequence seq; // Number of indexed representations generated in headers below. @@ -868,6 +857,14 @@ .Times(4); } } + QuicSpdySessionPeer::SetHpackDecoderDebugVisitor( + &session_, std::move(hpack_decoder_visitor)); + + // Create some headers we expect to generate entries in HPACK's + // dynamic table, in addition to content-length. + headers_["key0"] = string(1 << 1, '.'); + headers_["key1"] = string(1 << 2, '.'); + headers_["key2"] = string(1 << 3, '.'); for (QuicStreamId stream_id = kClientDataStreamId1; stream_id < kClientDataStreamId3; stream_id += 2) { for (bool fin : {false, true}) { @@ -901,11 +898,8 @@ } TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) { - StrictMock<MockQuicHpackDebugVisitor>* hpack_encoder_visitor = - hpack_encoder_visitor_.get(); - QuicSpdySessionPeer::SetHpackEncoderDebugVisitor( - &session_, std::move(hpack_encoder_visitor_)); - + auto hpack_encoder_visitor = + QuicMakeUnique<StrictMock<MockQuicHpackDebugVisitor>>(); if (perspective() == Perspective::IS_SERVER) { InSequence seq; for (int i = 1; i < 4; i++) { @@ -919,6 +913,9 @@ OnUseEntry(QuicTime::Delta::FromMilliseconds(i))); } } + QuicSpdySessionPeer::SetHpackEncoderDebugVisitor( + &session_, std::move(hpack_encoder_visitor)); + for (QuicStreamId stream_id = kClientDataStreamId1; stream_id < kClientDataStreamId3; stream_id += 2) { for (bool fin : {false, true}) {
diff --git a/net/quic/core/quic_server_session_base.cc b/net/quic/core/quic_server_session_base.cc index d427544..3f00b27 100644 --- a/net/quic/core/quic_server_session_base.cc +++ b/net/quic/core/quic_server_session_base.cc
@@ -113,7 +113,7 @@ sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds(); int64_t now_ms = (now - last_scup_time_).ToMilliseconds(); int64_t packets_since_last_scup = - connection()->packet_number_of_last_sent_packet() - + connection()->sent_packet_manager().GetLargestSentPacket() - last_scup_packet_number_; if (now_ms < (kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms) || now_ms < kMinIntervalBetweenServerConfigUpdatesMs || @@ -190,7 +190,8 @@ connection()->OnSendConnectionState(cached_network_params); last_scup_time_ = now; - last_scup_packet_number_ = connection()->packet_number_of_last_sent_packet(); + last_scup_packet_number_ = + connection()->sent_packet_manager().GetLargestSentPacket(); } bool QuicServerSessionBase::ShouldCreateIncomingDynamicStream(QuicStreamId id) {
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc index 5baad16..fdbb61b 100644 --- a/net/quic/core/quic_server_session_base_test.cc +++ b/net/quic/core/quic_server_session_base_test.cc
@@ -474,8 +474,11 @@ // Bandwidth estimate has now changed sufficiently, enough time has passed, // and enough packets have been sent. - QuicConnectionPeer::SetPacketNumberOfLastSentPacket( - session_->connection(), kMinPacketsBetweenServerConfigUpdates); + SerializedPacket packet( + kDefaultPathId, 1 + kMinPacketsBetweenServerConfigUpdates, + PACKET_6BYTE_PACKET_NUMBER, nullptr, 1000, false, false); + sent_packet_manager->OnPacketSent(&packet, 0, now, NOT_RETRANSMISSION, + HAS_RETRANSMITTABLE_DATA); // Verify that the proto has exactly the values we expect. CachedNetworkParameters expected_network_params;
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index 0f8040e..6161ad4 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -41,8 +41,11 @@ perspective(), kMinimumFlowControlSendWindow, config_.GetInitialSessionFlowControlWindowToSend(), - perspective() == Perspective::IS_SERVER), - currently_writing_stream_id_(0) {} + perspective() == Perspective::IS_SERVER, + nullptr), + currently_writing_stream_id_(0), + flow_control_invariant_( + FLAGS_quic_reloadable_flag_quic_flow_control_invariant) {} void QuicSession::Initialize() { connection_->set_visitor(this);
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index 7397b719..87d60f0d 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -247,6 +247,8 @@ // Returns true if this stream should yield writes to another blocked stream. bool ShouldYield(QuicStreamId stream_id); + bool flow_control_invariant() { return flow_control_invariant_; } + protected: using StaticStreamMap = base::SmallMap<std::unordered_map<QuicStreamId, QuicStream*>, 2>; @@ -440,6 +442,9 @@ // call stack of OnCanWrite. QuicStreamId currently_writing_stream_id_; + // Latched value of gfe2_reloadable_flag_quic_flow_control_invariant. + const bool flow_control_invariant_; + DISALLOW_COPY_AND_ASSIGN(QuicSession); };
diff --git a/net/quic/core/quic_spdy_stream.cc b/net/quic/core/quic_spdy_stream.cc index 3fb5e23..b004fcd7 100644 --- a/net/quic/core/quic_spdy_stream.cc +++ b/net/quic/core/quic_spdy_stream.cc
@@ -294,18 +294,15 @@ return false; } - unsigned int result; - if (!ParseUint32(status, &result, nullptr)) { + // First character must be an integer in range [1,5]. + if (status[0] < '1' || status[0] > '5') { return false; } - - // Valid status codes are only in the range [100, 599]. - if (result < 100 || result >= 600) { + // The remaining two characters must be integers. + if (!isdigit(status[1]) || !isdigit(status[2])) { return false; } - - *status_code = static_cast<int>(result); - return true; + return QuicTextUtils::StringToInt(status, status_code); } bool QuicSpdyStream::FinishedReadingTrailers() const {
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc index 04bfec2..9ae75a7 100644 --- a/net/quic/core/quic_stream.cc +++ b/net/quic/core/quic_stream.cc
@@ -72,7 +72,10 @@ perspective_, GetReceivedFlowControlWindow(session), GetInitialStreamFlowControlWindowToSend(session), - session_->flow_controller()->auto_tune_receive_window()), + session_->flow_controller()->auto_tune_receive_window(), + session_->flow_control_invariant() + ? session_->flow_controller() + : nullptr), connection_flow_controller_(session_->flow_controller()), stream_contributes_to_connection_flow_control_(true), busy_counter_(0) { @@ -347,6 +350,9 @@ } else { session_->MarkConnectionLevelWriteBlocked(id()); } + if (consumed_data.bytes_consumed > 0 || consumed_data.fin_consumed) { + busy_counter_ = 0; + } return consumed_data; }
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h index 5e5cfb0..8adfd57b 100644 --- a/net/quic/core/quic_stream.h +++ b/net/quic/core/quic_stream.h
@@ -315,7 +315,8 @@ // limited). bool stream_contributes_to_connection_flow_control_; - // For debugging only, used for busy loop check. + // A counter incremented when OnCanWrite() is called and no progress is made. + // For debugging only. size_t busy_counter_; DISALLOW_COPY_AND_ASSIGN(QuicStream);
diff --git a/net/quic/core/spdy_utils.cc b/net/quic/core/spdy_utils.cc index 237dcc91..ff3484f 100644 --- a/net/quic/core/spdy_utils.cc +++ b/net/quic/core/spdy_utils.cc
@@ -61,8 +61,8 @@ std::vector<StringPiece> values = QuicTextUtils::Split(content_length_header, '\0'); for (const StringPiece& value : values) { - int64_t new_value; - if (!base::StringToInt64(value, &new_value) || new_value < 0) { + uint64_t new_value; + if (!QuicTextUtils::StringToUint64(value, &new_value)) { QUIC_DLOG(ERROR) << "Content length was either unparseable or negative."; return false; @@ -71,7 +71,7 @@ *content_length = new_value; continue; } - if (new_value != *content_length) { + if (new_value != static_cast<uint64_t>(*content_length)) { QUIC_DLOG(ERROR) << "Parsed content length " << new_value << " is " << "inconsistent with previously detected content length " @@ -99,7 +99,7 @@ // response body bytes expected. auto it = trailers->find(kFinalOffsetHeaderKey); if (it == trailers->end() || - !base::StringToSizeT(it->second, final_byte_offset)) { + !QuicTextUtils::StringToSizeT(it->second, final_byte_offset)) { QUIC_DVLOG(1) << "Required key '" << kFinalOffsetHeaderKey << "' not present"; return false; @@ -161,10 +161,8 @@ // Pull out the final offset pseudo header which indicates the number of // response body bytes expected. - int offset; if (!found_final_byte_offset && name == kFinalOffsetHeaderKey && - base::StringToInt(p.second, &offset)) { - *final_byte_offset = offset; + QuicTextUtils::StringToSizeT(p.second, final_byte_offset)) { found_final_byte_offset = true; continue; }
diff --git a/net/quic/platform/api/quic_text_utils.h b/net/quic/platform/api/quic_text_utils.h index 7eabe73..3509e9de 100644 --- a/net/quic/platform/api/quic_text_utils.h +++ b/net/quic/platform/api/quic_text_utils.h
@@ -40,6 +40,24 @@ return QuicTextUtilsImpl::StringToUint64(in, out); } + // Returns true if |in| represents a valid int, and stores that value in + // |out|. + static bool StringToInt(base::StringPiece in, int* out) { + return QuicTextUtilsImpl::StringToInt(in, out); + } + + // Returns true if |in| represents a valid uint32, and stores that value in + // |out|. + static bool StringToUint32(base::StringPiece in, uint32_t* out) { + return QuicTextUtilsImpl::StringToUint32(in, out); + } + + // Returns true if |in| represents a valid size_t, and stores that value in + // |out|. + static bool StringToSizeT(base::StringPiece in, size_t* out) { + return QuicTextUtilsImpl::StringToSizeT(in, out); + } + // Returns a new string representing |in|. static std::string Uint64ToString(uint64_t in) { return QuicTextUtilsImpl::Uint64ToString(in);
diff --git a/net/quic/platform/api/quic_text_utils_test.cc b/net/quic/platform/api/quic_text_utils_test.cc index 49efeb1..06b25620 100644 --- a/net/quic/platform/api/quic_text_utils_test.cc +++ b/net/quic/platform/api/quic_text_utils_test.cc
@@ -51,15 +51,77 @@ } } -TEST(QuicTextUtilsText, StringToUint64) { - uint64_t val = 0; - EXPECT_TRUE(QuicTextUtils::StringToUint64("123", &val)); - EXPECT_EQ(123u, val); - EXPECT_TRUE(QuicTextUtils::StringToUint64("1234", &val)); - EXPECT_EQ(1234u, val); - EXPECT_FALSE(QuicTextUtils::StringToUint64("", &val)); - EXPECT_FALSE(QuicTextUtils::StringToUint64("-123", &val)); - EXPECT_FALSE(QuicTextUtils::StringToUint64("-123.0", &val)); +TEST(QuicTextUtilsText, StringToNumbers) { + const string kMaxInt32Plus1 = "2147483648"; + const string kMinInt32Minus1 = "-2147483649"; + const string kMaxUint32Plus1 = "4294967296"; + + { + // StringToUint64 + uint64_t uint64_val = 0; + EXPECT_TRUE(QuicTextUtils::StringToUint64("123", &uint64_val)); + EXPECT_EQ(123u, uint64_val); + EXPECT_TRUE(QuicTextUtils::StringToUint64("1234", &uint64_val)); + EXPECT_EQ(1234u, uint64_val); + EXPECT_FALSE(QuicTextUtils::StringToUint64("", &uint64_val)); + EXPECT_FALSE(QuicTextUtils::StringToUint64("-123", &uint64_val)); + EXPECT_FALSE(QuicTextUtils::StringToUint64("-123.0", &uint64_val)); + EXPECT_TRUE(QuicTextUtils::StringToUint64(kMaxUint32Plus1, &uint64_val)); + EXPECT_EQ(4294967296u, uint64_val); + } + + { + // StringToint + int int_val = 0; + EXPECT_TRUE(QuicTextUtils::StringToInt("123", &int_val)); + EXPECT_EQ(123, int_val); + EXPECT_TRUE(QuicTextUtils::StringToInt("1234", &int_val)); + EXPECT_EQ(1234, int_val); + EXPECT_FALSE(QuicTextUtils::StringToInt("", &int_val)); + EXPECT_TRUE(QuicTextUtils::StringToInt("-123", &int_val)); + EXPECT_EQ(-123, int_val); + EXPECT_FALSE(QuicTextUtils::StringToInt("-123.0", &int_val)); + if (sizeof(int) > 4) { + EXPECT_TRUE(QuicTextUtils::StringToInt(kMinInt32Minus1, &int_val)); + EXPECT_EQ(-2147483649ll, int_val); + EXPECT_TRUE(QuicTextUtils::StringToInt(kMaxInt32Plus1, &int_val)); + EXPECT_EQ(2147483648ll, int_val); + } else { + EXPECT_FALSE(QuicTextUtils::StringToInt(kMinInt32Minus1, &int_val)); + EXPECT_FALSE(QuicTextUtils::StringToInt(kMaxInt32Plus1, &int_val)); + } + } + + { + // StringToUint32 + uint32_t uint32_val = 0; + EXPECT_TRUE(QuicTextUtils::StringToUint32("123", &uint32_val)); + EXPECT_EQ(123u, uint32_val); + EXPECT_TRUE(QuicTextUtils::StringToUint32("1234", &uint32_val)); + EXPECT_EQ(1234u, uint32_val); + EXPECT_FALSE(QuicTextUtils::StringToUint32("", &uint32_val)); + EXPECT_FALSE(QuicTextUtils::StringToUint32("-123", &uint32_val)); + EXPECT_FALSE(QuicTextUtils::StringToUint32("-123.0", &uint32_val)); + EXPECT_FALSE(QuicTextUtils::StringToUint32(kMaxUint32Plus1, &uint32_val)); + } + + { + // StringToSizeT + size_t size_t_val = 0; + EXPECT_TRUE(QuicTextUtils::StringToSizeT("123", &size_t_val)); + EXPECT_EQ(123u, size_t_val); + EXPECT_TRUE(QuicTextUtils::StringToSizeT("1234", &size_t_val)); + EXPECT_EQ(1234u, size_t_val); + EXPECT_FALSE(QuicTextUtils::StringToSizeT("", &size_t_val)); + EXPECT_FALSE(QuicTextUtils::StringToSizeT("-123", &size_t_val)); + EXPECT_FALSE(QuicTextUtils::StringToSizeT("-123.0", &size_t_val)); + if (sizeof(size_t) > 4) { + EXPECT_TRUE(QuicTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val)); + EXPECT_EQ(4294967296ull, size_t_val); + } else { + EXPECT_FALSE(QuicTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val)); + } + } } TEST(QuicTextUtilsText, Uint64ToString) {
diff --git a/net/quic/platform/impl/quic_text_utils_impl.h b/net/quic/platform/impl/quic_text_utils_impl.h index a3cce167..c797ac6 100644 --- a/net/quic/platform/impl/quic_text_utils_impl.h +++ b/net/quic/platform/impl/quic_text_utils_impl.h
@@ -13,6 +13,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "net/base/parse_number.h" namespace net { @@ -46,6 +47,24 @@ return base::StringToUint64(in, out); } + // Returns true if |in| represents a valid int, and stores that value in + // |out|. + static bool StringToInt(base::StringPiece in, int* out) { + return base::StringToInt(in, out); + } + + // Returns true if |in| represents a valid uint32, and stores that value in + // |out|. + static bool StringToUint32(base::StringPiece in, uint32_t* out) { + return ParseUint32(in, out, nullptr); + } + + // Returns true if |in| represents a valid size_t, and stores that value in + // |out|. + static bool StringToSizeT(base::StringPiece in, size_t* out) { + return base::StringToSizeT(in, out); + } + // Returns a new std::string representing |in|. static std::string Uint64ToString(uint64_t in) { return base::Uint64ToString(in);
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc index 11e3419..84cd402 100644 --- a/net/quic/test_tools/quic_connection_peer.cc +++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -216,13 +216,6 @@ } // static -void QuicConnectionPeer::SetPacketNumberOfLastSentPacket( - QuicConnection* connection, - QuicPacketNumber number) { - connection->packet_number_of_last_sent_packet_ = number; -} - -// static QuicConnectionStats* QuicConnectionPeer::GetStats(QuicConnection* connection) { return &connection->stats_; }
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 4be80d7..c993fa8f 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -993,24 +993,12 @@ SSL_clear_mode(ssl_.get(), mode.clear_mask); // Use BoringSSL defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers - // (note that SHA256 and SHA384 only select legacy CBC ciphers). Also disable - // DHE_RSA_WITH_AES_256_GCM_SHA384. Historically, AES_256_GCM was not - // supported. As DHE is being deprecated, don't add a cipher only to remove - // it immediately. - // - // TODO(davidben): Remove the DHE_RSA_WITH_AES_256_GCM_SHA384 exclusion when - // the DHEEnabled administrative policy expires. - std::string command( - "ALL:!SHA256:!SHA384:!DHE-RSA-AES256-GCM-SHA384:!aPSK:!RC4"); + // (note that SHA256 and SHA384 only select legacy CBC ciphers). + std::string command("ALL:!SHA256:!SHA384:!kDHE:!aPSK:!RC4"); if (ssl_config_.require_ecdhe) command.append(":!kRSA:!kDHE"); - if (!ssl_config_.deprecated_cipher_suites_enabled) { - // Only offer DHE on the second handshake. https://crbug.com/538690 - command.append(":!kDHE"); - } - // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining // CBC-mode ECDSA ciphers. if (!AreLegacyECDSACiphersEnabled()) @@ -1161,16 +1149,6 @@ ssl_session_cache_lookup_count_, 20); } - // DHE is offered on the deprecated cipher fallback and then rejected - // afterwards. This is to aid in diagnosing connection failures because a - // server requires DHE ciphers. - // - // TODO(davidben): A few releases after DHE's removal, remove this logic. - if (!ssl_config_.dhe_enabled && - SSL_CIPHER_is_DHE(SSL_get_current_cipher(ssl_.get()))) { - return ERR_SSL_OBSOLETE_CIPHER; - } - // Check that if token binding was negotiated, then extended master secret // and renegotiation indication must also be negotiated. if (tb_was_negotiated_ &&
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 58c7fa8..ec24dcb 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2596,34 +2596,17 @@ EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); } -// Test that DHE is removed but gives a dedicated error. Also test that the -// dhe_enabled option can restore it. -TEST_F(SSLClientSocketTest, DHE) { +// Test that DHE is removed. +TEST_F(SSLClientSocketTest, NoDHE) { SpawnedTestServer::SSLOptions ssl_options; ssl_options.key_exchanges = SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; ASSERT_TRUE(StartTestServer(ssl_options)); - // Normal handshakes with DHE do not work, with or without DHE enabled. SSLConfig ssl_config; int rv; ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); - - ssl_config.dhe_enabled = true; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); - - // Enabling deprecated ciphers gives DHE a dedicated error code. - ssl_config.dhe_enabled = false; - ssl_config.deprecated_cipher_suites_enabled = true; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - EXPECT_THAT(rv, IsError(ERR_SSL_OBSOLETE_CIPHER)); - - // Enabling both deprecated ciphers and DHE restores it. - ssl_config.dhe_enabled = true; - ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); - EXPECT_THAT(rv, IsOk()); } // Tests that enabling deprecated ciphers shards the session cache. @@ -2776,21 +2759,6 @@ TestFalseStart(server_options, client_config, false)); } -// Test that False Start is disabled with DHE_RSA ciphers. -TEST_F(SSLClientSocketFalseStartTest, DHE_RSA) { - SpawnedTestServer::SSLOptions server_options; - server_options.key_exchanges = - SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; - server_options.bulk_ciphers = - SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM; - server_options.alpn_protocols.push_back("http/1.1"); - SSLConfig client_config; - client_config.alpn_protos.push_back(kProtoHTTP11); - // DHE is only advertised when deprecated ciphers are enabled. - client_config.deprecated_cipher_suites_enabled = true; - ASSERT_NO_FATAL_FAILURE(TestFalseStart(server_options, client_config, false)); -} - // Test that False Start is disabled without an AEAD. TEST_F(SSLClientSocketFalseStartTest, NoAEAD) { SpawnedTestServer::SSLOptions server_options;
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc index 3275ac4..62e192e1 100644 --- a/net/ssl/ssl_config.cc +++ b/net/ssl/ssl_config.cc
@@ -27,7 +27,6 @@ version_min(kDefaultSSLVersionMin), version_max(kDefaultSSLVersionMax), deprecated_cipher_suites_enabled(false), - dhe_enabled(false), channel_id_enabled(true), false_start_enabled(true), signed_cert_timestamps_enabled(true),
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h index 0cc7f552..1188a0d 100644 --- a/net/ssl/ssl_config.h +++ b/net/ssl/ssl_config.h
@@ -103,11 +103,11 @@ // to them as far as downgrades are concerned, so this should only be used for // measurement of ciphers not to be carried long-term. It is no fix for // servers with bad configurations without full removal. + // + // TODO(davidben): This is no longer used. Remove + // it. https://crbug.com/684730. bool deprecated_cipher_suites_enabled; - // Enables DHE cipher suites. - bool dhe_enabled; - bool channel_id_enabled; // True if TLS channel ID extension is enabled. // List of Token Binding key parameters supported by the client. If empty,
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc index dc07949..bbdadfd 100644 --- a/net/tools/quic/quic_client_base.cc +++ b/net/tools/quic/quic_client_base.cc
@@ -68,7 +68,7 @@ if (store_response_) { auto status = response_headers.find(":status"); if (status == response_headers.end() || - !StringToInt(status->second, &latest_response_code_)) { + !QuicTextUtils::StringToInt(status->second, &latest_response_code_)) { QUIC_LOG(ERROR) << "Invalid response headers"; } latest_response_headers_ = response_headers.DebugString();
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index 2a7a4d28..ff5e5d4d 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc
@@ -82,7 +82,6 @@ delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()), load_flags_(LOAD_NORMAL), response_code_(URLFetcher::RESPONSE_CODE_INVALID), - buffer_(new IOBuffer(kBufferSize)), url_request_data_key_(NULL), was_fetched_via_proxy_(false), was_cached_(false), @@ -428,6 +427,9 @@ total_response_bytes_ = request_->GetExpectedContentSize(); } + DCHECK(!buffer_); + if (request_type_ != URLFetcher::HEAD) + buffer_ = new IOBuffer(kBufferSize); ReadResponse(); } @@ -816,6 +818,7 @@ request_context_getter_->RemoveObserver(this); upload_progress_checker_timer_.reset(); request_.reset(); + buffer_ = nullptr; g_registry.Get().RemoveURLFetcherCore(this); }
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 58076877..ebebfac 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -8875,31 +8875,6 @@ EXPECT_EQ(kOriginHeaderValue, received_cors_header); } -// Test that DHE-only servers fail with the expected dedicated error code. -TEST_F(HTTPSRequestTest, DHE) { - SpawnedTestServer::SSLOptions ssl_options; - ssl_options.key_exchanges = - SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; - SpawnedTestServer test_server( - SpawnedTestServer::TYPE_HTTPS, ssl_options, - base::FilePath(FILE_PATH_LITERAL("net/data/ssl"))); - ASSERT_TRUE(test_server.Start()); - - TestDelegate d; - { - std::unique_ptr<URLRequest> r(default_context_.CreateRequest( - test_server.GetURL("/defaultresponse"), DEFAULT_PRIORITY, &d)); - - r->Start(); - EXPECT_TRUE(r->is_pending()); - - base::RunLoop().Run(); - - EXPECT_EQ(1, d.response_started_count()); - EXPECT_EQ(ERR_SSL_OBSOLETE_CIPHER, d.request_status()); - } -} - namespace { class SSLClientAuthTestDelegate : public TestDelegate {
diff --git a/ppapi/host/BUILD.gn b/ppapi/host/BUILD.gn index 9df23ac..2404a67a 100644 --- a/ppapi/host/BUILD.gn +++ b/ppapi/host/BUILD.gn
@@ -34,7 +34,6 @@ "//ipc", "//media:shared_memory_support", "//ppapi/c", - "//ppapi/proxy", "//ppapi/proxy:ipc", "//ppapi/shared_impl", "//ui/events:events_base",
diff --git a/ppapi/proxy/BUILD.gn b/ppapi/proxy/BUILD.gn index 140c718..ce07d16a 100644 --- a/ppapi/proxy/BUILD.gn +++ b/ppapi/proxy/BUILD.gn
@@ -102,7 +102,6 @@ "plugin_var_tracker.h", "ppapi_command_buffer_proxy.cc", "ppapi_command_buffer_proxy.h", - "ppapi_message_utils.h", "ppapi_messages.h", "ppb_audio_proxy.cc", "ppb_audio_proxy.h", @@ -279,6 +278,7 @@ ] deps = [ + ":common", "//base", "//gpu/command_buffer/client:gles2_implementation", "//gpu/ipc/common:command_buffer_traits", @@ -306,6 +306,17 @@ } } +source_set("common") { + sources = [ + "tcp_socket_resource_constants.cc", + "tcp_socket_resource_constants.h", + "udp_socket_resource_constants.cc", + "udp_socket_resource_constants.h", + ] + + configs += [ ":proxy_implementation" ] +} + group("ipc") { if (is_component_build) { public_deps = [ @@ -322,6 +333,7 @@ sources = [ "nacl_message_scanner.cc", "nacl_message_scanner.h", + "ppapi_message_utils.h", "ppapi_messages.cc", "ppapi_messages.h", "ppapi_param_traits.cc",
diff --git a/ppapi/proxy/tcp_socket_resource_base.cc b/ppapi/proxy/tcp_socket_resource_base.cc index 3cc4fdd..2ec45c2 100644 --- a/ppapi/proxy/tcp_socket_resource_base.cc +++ b/ppapi/proxy/tcp_socket_resource_base.cc
@@ -13,6 +13,7 @@ #include "ppapi/c/pp_errors.h" #include "ppapi/proxy/error_conversion.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/tcp_socket_resource_constants.h" #include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h" #include "ppapi/shared_impl/socket_option_data.h" @@ -24,13 +25,6 @@ namespace ppapi { namespace proxy { -const int32_t TCPSocketResourceBase::kMaxReadSize = 1024 * 1024; -const int32_t TCPSocketResourceBase::kMaxWriteSize = 1024 * 1024; -const int32_t TCPSocketResourceBase::kMaxSendBufferSize = - 1024 * TCPSocketResourceBase::kMaxWriteSize; -const int32_t TCPSocketResourceBase::kMaxReceiveBufferSize = - 1024 * TCPSocketResourceBase::kMaxReadSize; - TCPSocketResourceBase::TCPSocketResourceBase(Connection connection, PP_Instance instance, TCPSocketVersion version) @@ -212,7 +206,8 @@ state_.IsPending(TCPSocketState::SSL_CONNECT)) return PP_ERROR_INPROGRESS; read_buffer_ = buffer; - bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize); + bytes_to_read_ = + std::min(bytes_to_read, TCPSocketResourceConstants::kMaxReadSize); read_callback_ = callback; Call<PpapiPluginMsg_TCPSocket_ReadReply>( @@ -237,8 +232,8 @@ state_.IsPending(TCPSocketState::SSL_CONNECT)) return PP_ERROR_INPROGRESS; - if (bytes_to_write > kMaxWriteSize) - bytes_to_write = kMaxWriteSize; + if (bytes_to_write > TCPSocketResourceConstants::kMaxWriteSize) + bytes_to_write = TCPSocketResourceConstants::kMaxWriteSize; write_callback_ = callback;
diff --git a/ppapi/proxy/tcp_socket_resource_base.h b/ppapi/proxy/tcp_socket_resource_base.h index 1df1c583..382766c 100644 --- a/ppapi/proxy/tcp_socket_resource_base.h +++ b/ppapi/proxy/tcp_socket_resource_base.h
@@ -28,26 +28,6 @@ namespace proxy { class PPAPI_PROXY_EXPORT TCPSocketResourceBase : public PluginResource { - public: - // TODO(yzshen): Move these constants to ppb_tcp_socket_shared. - // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read - // message is allowed to request. - static const int32_t kMaxReadSize; - // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write - // message is allowed to carry. - static const int32_t kMaxWriteSize; - - // The maximum number that we allow for setting - // PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE. This number is only for input - // argument sanity check, it doesn't mean the browser guarantees to support - // such a buffer size. - static const int32_t kMaxSendBufferSize; - // The maximum number that we allow for setting - // PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE. This number is only for input - // argument sanity check, it doesn't mean the browser guarantees to support - // such a buffer size. - static const int32_t kMaxReceiveBufferSize; - protected: // C-tor used for new sockets. TCPSocketResourceBase(Connection connection,
diff --git a/ppapi/proxy/tcp_socket_resource_constants.cc b/ppapi/proxy/tcp_socket_resource_constants.cc new file mode 100644 index 0000000..49fb59f --- /dev/null +++ b/ppapi/proxy/tcp_socket_resource_constants.cc
@@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/proxy/tcp_socket_resource_constants.h" + +namespace ppapi { +namespace proxy { + +const int32_t TCPSocketResourceConstants::kMaxReadSize = 1024 * 1024; +const int32_t TCPSocketResourceConstants::kMaxWriteSize = 1024 * 1024; +const int32_t TCPSocketResourceConstants::kMaxSendBufferSize = + 1024 * TCPSocketResourceConstants::kMaxWriteSize; +const int32_t TCPSocketResourceConstants::kMaxReceiveBufferSize = + 1024 * TCPSocketResourceConstants::kMaxReadSize; + +} // namespace proxy +} // namespace ppapi
diff --git a/ppapi/proxy/tcp_socket_resource_constants.h b/ppapi/proxy/tcp_socket_resource_constants.h new file mode 100644 index 0000000..9c5833a --- /dev/null +++ b/ppapi/proxy/tcp_socket_resource_constants.h
@@ -0,0 +1,38 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include "base/macros.h" +#include "ppapi/proxy/ppapi_proxy_export.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT TCPSocketResourceConstants { + public: + // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read + // message is allowed to request. + static const int32_t kMaxReadSize; + // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write + // message is allowed to carry. + static const int32_t kMaxWriteSize; + + // The maximum number that we allow for setting + // PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE. This number is only for input + // argument sanity check, it doesn't mean the browser guarantees to support + // such a buffer size. + static const int32_t kMaxSendBufferSize; + // The maximum number that we allow for setting + // PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE. This number is only for input + // argument sanity check, it doesn't mean the browser guarantees to support + // such a buffer size. + static const int32_t kMaxReceiveBufferSize; + + private: + DISALLOW_COPY_AND_ASSIGN(TCPSocketResourceConstants); +}; + +} // namespace proxy +} // namespace ppapi
diff --git a/ppapi/proxy/udp_socket_filter.cc b/ppapi/proxy/udp_socket_filter.cc index 4928dee..85cab0546 100644 --- a/ppapi/proxy/udp_socket_filter.cc +++ b/ppapi/proxy/udp_socket_filter.cc
@@ -14,17 +14,13 @@ #include "ppapi/proxy/error_conversion.h" #include "ppapi/proxy/plugin_globals.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/udp_socket_resource_constants.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/resource_creation_api.h" namespace ppapi { namespace proxy { -const int32_t UDPSocketFilter::kMaxReadSize = 128 * 1024; -const int32_t UDPSocketFilter::kMaxReceiveBufferSize = - 1024 * UDPSocketFilter::kMaxReadSize; -const size_t UDPSocketFilter::kPluginReceiveBufferSlots = 32u; - namespace { int32_t SetRecvFromOutput(PP_Instance pp_instance, @@ -156,7 +152,8 @@ const std::string& data, const PP_NetAddress_Private& addr) { DCHECK(PluginGlobals::Get()->ipc_task_runner()->RunsTasksOnCurrentThread()); - DCHECK_LT(recv_buffers_.size(), UDPSocketFilter::kPluginReceiveBufferSlots); + DCHECK_LT(recv_buffers_.size(), + UDPSocketResourceConstants::kPluginReceiveBufferSlots); if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) { recv_buffers_.push(RecvBuffer()); @@ -216,7 +213,8 @@ if (recv_buffers_.empty()) { read_buffer_ = buffer_out; - bytes_to_read_ = std::min(num_bytes, UDPSocketFilter::kMaxReadSize); + bytes_to_read_ = + std::min(num_bytes, UDPSocketResourceConstants::kMaxReadSize); recvfrom_addr_resource_ = addr_out; recvfrom_callback_ = callback; return PP_OK_COMPLETIONPENDING;
diff --git a/ppapi/proxy/udp_socket_resource_base.cc b/ppapi/proxy/udp_socket_resource_base.cc index 795b63b..552d9f10 100644 --- a/ppapi/proxy/udp_socket_resource_base.cc +++ b/ppapi/proxy/udp_socket_resource_base.cc
@@ -12,17 +12,13 @@ #include "ppapi/proxy/error_conversion.h" #include "ppapi/proxy/plugin_globals.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/udp_socket_resource_constants.h" #include "ppapi/shared_impl/socket_option_data.h" #include "ppapi/thunk/enter.h" namespace ppapi { namespace proxy { -const int32_t UDPSocketResourceBase::kMaxWriteSize = 128 * 1024; -const int32_t UDPSocketResourceBase::kMaxSendBufferSize = - 1024 * UDPSocketResourceBase::kMaxWriteSize; -const size_t UDPSocketResourceBase::kPluginSendBufferSlots = 8u; - namespace { void RunCallback(scoped_refptr<TrackedCallback> callback, @@ -193,11 +189,12 @@ return PP_ERROR_BADARGUMENT; if (!bound_) return PP_ERROR_FAILED; - if (sendto_callbacks_.size() == kPluginSendBufferSlots) + if (sendto_callbacks_.size() == + UDPSocketResourceConstants::kPluginSendBufferSlots) return PP_ERROR_INPROGRESS; - if (num_bytes > kMaxWriteSize) - num_bytes = kMaxWriteSize; + if (num_bytes > UDPSocketResourceConstants::kMaxWriteSize) + num_bytes = UDPSocketResourceConstants::kMaxWriteSize; sendto_callbacks_.push(callback);
diff --git a/ppapi/proxy/udp_socket_resource_base.h b/ppapi/proxy/udp_socket_resource_base.h index 30599422..97512b3 100644 --- a/ppapi/proxy/udp_socket_resource_base.h +++ b/ppapi/proxy/udp_socket_resource_base.h
@@ -26,32 +26,6 @@ class ResourceMessageReplyParams; class PPAPI_PROXY_EXPORT UDPSocketResourceBase : public PluginResource { - public: - // The maximum number of bytes that each - // PpapiPluginMsg_PPBUDPSocket_PushRecvResult message is allowed to carry. - static const int32_t kMaxReadSize; - // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_SendTo - // message is allowed to carry. - static const int32_t kMaxWriteSize; - - // The maximum number that we allow for setting - // PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE. This number is only for input - // argument sanity check, it doesn't mean the browser guarantees to support - // such a buffer size. - static const int32_t kMaxSendBufferSize; - // The maximum number that we allow for setting - // PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE. This number is only for input - // argument sanity check, it doesn't mean the browser guarantees to support - // such a buffer size. - static const int32_t kMaxReceiveBufferSize; - - // The maximum number of received packets that we allow instances of this - // class to buffer. - static const size_t kPluginReceiveBufferSlots; - // The maximum number of buffers that we allow instances of this class to be - // sending before we block the plugin. - static const size_t kPluginSendBufferSlots; - protected: UDPSocketResourceBase(Connection connection, PP_Instance instance,
diff --git a/ppapi/proxy/udp_socket_resource_constants.cc b/ppapi/proxy/udp_socket_resource_constants.cc new file mode 100644 index 0000000..3f4f1296 --- /dev/null +++ b/ppapi/proxy/udp_socket_resource_constants.cc
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/proxy/udp_socket_resource_constants.h" + +namespace ppapi { +namespace proxy { + +const int32_t UDPSocketResourceConstants::kMaxWriteSize = 128 * 1024; +const int32_t UDPSocketResourceConstants::kMaxReadSize = 128 * 1024; + +const int32_t UDPSocketResourceConstants::kMaxSendBufferSize = + 1024 * UDPSocketResourceConstants::kMaxWriteSize; +const int32_t UDPSocketResourceConstants::kMaxReceiveBufferSize = + 1024 * UDPSocketResourceConstants::kMaxReadSize; + +const size_t UDPSocketResourceConstants::kPluginSendBufferSlots = 8u; +const size_t UDPSocketResourceConstants::kPluginReceiveBufferSlots = 32u; + +} // namespace proxy +} // namespace ppapi
diff --git a/ppapi/proxy/udp_socket_resource_constants.h b/ppapi/proxy/udp_socket_resource_constants.h new file mode 100644 index 0000000..e9dd953 --- /dev/null +++ b/ppapi/proxy/udp_socket_resource_constants.h
@@ -0,0 +1,45 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include "base/macros.h" +#include "ppapi/proxy/ppapi_proxy_export.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT UDPSocketResourceConstants { + public: + // The maximum number of bytes that each + // PpapiPluginMsg_PPBUDPSocket_PushRecvResult message is allowed to carry. + static const int32_t kMaxReadSize; + // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_SendTo + // message is allowed to carry. + static const int32_t kMaxWriteSize; + + // The maximum number that we allow for setting + // PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE. This number is only for input + // argument sanity check, it doesn't mean the browser guarantees to support + // such a buffer size. + static const int32_t kMaxSendBufferSize; + // The maximum number that we allow for setting + // PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE. This number is only for input + // argument sanity check, it doesn't mean the browser guarantees to support + // such a buffer size. + static const int32_t kMaxReceiveBufferSize; + + // The maximum number of received packets that we allow instances of this + // class to buffer. + static const size_t kPluginReceiveBufferSlots; + // The maximum number of buffers that we allow instances of this class to be + // sending before we block the plugin. + static const size_t kPluginSendBufferSlots; + + private: + DISALLOW_COPY_AND_ASSIGN(UDPSocketResourceConstants); +}; + +} // namespace proxy +} // namespace ppapi
diff --git a/remoting/host/desktop_environment_options.cc b/remoting/host/desktop_environment_options.cc index 842c28e..ec1995e 100644 --- a/remoting/host/desktop_environment_options.cc +++ b/remoting/host/desktop_environment_options.cc
@@ -37,7 +37,8 @@ void DesktopEnvironmentOptions::Initialize() { desktop_capture_options_.set_detect_updated_region(true); #if defined (OS_WIN) - desktop_capture_options_.set_allow_directx_capturer(true); + // TODO(joedow): Enable the DirectX capturer once the blocking bugs are fixed. + // desktop_capture_options_.set_allow_directx_capturer(true); #endif }
diff --git a/services/service_manager/README.md b/services/service_manager/README.md index 8245c46..ce4e2130 100644 --- a/services/service_manager/README.md +++ b/services/service_manager/README.md
@@ -130,7 +130,6 @@ service("my_service") { sources = [ "my_service.cc" ] deps = [ "//base", "//services/service_manager/public/cpp" ] - data_deps = [ ":manifest" ] } service_manifest("manifest") {
diff --git a/services/service_manager/background/tests/BUILD.gn b/services/service_manager/background/tests/BUILD.gn index 4ca19a00..40d46e8 100644 --- a/services/service_manager/background/tests/BUILD.gn +++ b/services/service_manager/background/tests/BUILD.gn
@@ -25,7 +25,6 @@ data_deps = [ ":background_service_manager_test_service", - ":test_manifest", ] } @@ -46,10 +45,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - - data_deps = [ - ":test_service_manifest", - ] } service_manifest("test_manifest") {
diff --git a/services/service_manager/runner/host/BUILD.gn b/services/service_manager/runner/host/BUILD.gn index 3c26d35..bfba14a 100644 --- a/services/service_manager/runner/host/BUILD.gn +++ b/services/service_manager/runner/host/BUILD.gn
@@ -64,10 +64,6 @@ "//mojo/public/cpp/system", "//services/service_manager/public/cpp/standalone_service:main", ] - - data_deps = [ - ":host_test_service_manifest", - ] } service_manifest("host_test_service_manifest") {
diff --git a/services/service_manager/tests/connect/BUILD.gn b/services/service_manager/tests/connect/BUILD.gn index 579389c..38aa864 100644 --- a/services/service_manager/tests/connect/BUILD.gn +++ b/services/service_manager/tests/connect/BUILD.gn
@@ -29,7 +29,6 @@ ":connect_test_singleton_app", ":connect_test_exe", ":connect_test_package", - ":manifest", ] } @@ -69,9 +68,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - data_deps = [ - ":connect_test_package_manifest", - ] } service_manifest("connect_test_package_manifest") { @@ -95,9 +91,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - data_deps = [ - ":connect_test_app_manifest", - ] } service_manifest("connect_test_app_manifest") { @@ -117,9 +110,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - data_deps = [ - ":connect_test_class_app_manifest", - ] } service_manifest("connect_test_class_app_manifest") { @@ -137,9 +127,6 @@ "//mojo/common:common_base", "//services/service_manager/public/cpp:sources", ] - data_deps = [ - ":connect_test_singleton_app_manifest", - ] } service_manifest("connect_test_singleton_app_manifest") { @@ -161,10 +148,6 @@ "//services/service_manager/public/cpp", "//services/service_manager/public/cpp/standalone_service:main", ] - - data_deps = [ - ":connect_test_exe_manifest", - ] } service_manifest("connect_test_exe_manifest") {
diff --git a/services/service_manager/tests/lifecycle/BUILD.gn b/services/service_manager/tests/lifecycle/BUILD.gn index 2e70540f..faf41b14 100644 --- a/services/service_manager/tests/lifecycle/BUILD.gn +++ b/services/service_manager/tests/lifecycle/BUILD.gn
@@ -29,7 +29,6 @@ ":lifecycle_unittest_parent", ":lifecycle_unittest_exe", ":lifecycle_unittest_package", - ":manifest", ] } @@ -79,9 +78,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/interfaces", ] - data_deps = [ - ":lifecycle_unittest_package_manifest", - ] } service_manifest("lifecycle_unittest_package_manifest") { @@ -104,10 +100,6 @@ "//base", "//services/service_manager/public/cpp:sources", ] - - data_deps = [ - ":lifecycle_unittest_app_manifest", - ] } service_manifest("lifecycle_unittest_app_manifest") { @@ -125,10 +117,6 @@ "//base", "//services/service_manager/public/cpp:sources", ] - - data_deps = [ - ":lifecycle_unittest_parent_manifest", - ] } service_manifest("lifecycle_unittest_parent_manifest") { @@ -148,10 +136,6 @@ "//services/service_manager/public/cpp:sources", "//services/service_manager/public/cpp/standalone_service:main", ] - - data_deps = [ - ":lifecycle_unittest_exe_manifest", - ] } service_manifest("lifecycle_unittest_exe_manifest") {
diff --git a/services/service_manager/tests/service_manager/BUILD.gn b/services/service_manager/tests/service_manager/BUILD.gn index a59bba4..3a34cf5 100644 --- a/services/service_manager/tests/service_manager/BUILD.gn +++ b/services/service_manager/tests/service_manager/BUILD.gn
@@ -27,7 +27,6 @@ ] data_deps = [ - ":manifest", ":service_manager_unittest_embedder", ":service_manager_unittest_target", ] @@ -62,10 +61,6 @@ "//services/service_manager/public/cpp", "//services/service_manager/public/cpp/standalone_service:main", ] - - data_deps = [ - ":target_manifest", - ] } service_manifest("target_manifest") {
diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn index 05fdfb2..7c85748 100644 --- a/services/shape_detection/BUILD.gn +++ b/services/shape_detection/BUILD.gn
@@ -33,10 +33,6 @@ "//services/service_manager/public/cpp", "//services/shape_detection/public/interfaces", ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") {
diff --git a/services/ui/demo/BUILD.gn b/services/ui/demo/BUILD.gn index 43e89cf..5ff9b13 100644 --- a/services/ui/demo/BUILD.gn +++ b/services/ui/demo/BUILD.gn
@@ -43,7 +43,6 @@ ] data_deps = [ - ":manifest", "//services/ui", ] }
diff --git a/services/ui/gpu/BUILD.gn b/services/ui/gpu/BUILD.gn index 46ff616..c046f6f3 100644 --- a/services/ui/gpu/BUILD.gn +++ b/services/ui/gpu/BUILD.gn
@@ -57,10 +57,6 @@ "//ui/gfx:memory_buffer", "//ui/gfx/geometry", ] - - data_deps = [ - ":mus_gpu_unittests_app_manifest", - ] } service_manifest("mus_gpu_unittests_app_manifest") {
diff --git a/services/ui/test_wm/BUILD.gn b/services/ui/test_wm/BUILD.gn index 3279c746..41c8693 100644 --- a/services/ui/test_wm/BUILD.gn +++ b/services/ui/test_wm/BUILD.gn
@@ -25,7 +25,6 @@ ] data_deps = [ - ":manifest", "//services/ui", ] }
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn index 956e0274..eeb080e 100644 --- a/services/video_capture/BUILD.gn +++ b/services/video_capture/BUILD.gn
@@ -17,10 +17,6 @@ ":lib", "//mojo/public/cpp/system", ] - - data_deps = [ - ":manifest", - ] } service_manifest("manifest") { @@ -82,10 +78,6 @@ "//testing/gtest", "//ui/gfx:test_support", ] - - data_deps = [ - ":unittest_manifest", - ] } service_manifest("unittest_manifest") {
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index a05f055..5c58276d 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -336,6 +336,37 @@ } ] }, + "Memory Infra Tester": { + "isolated_scripts": [ + { + "args": [ + "system_health.memory_mobile", + "-v", + "--upload-results", + "--output-format=chartjson", + "--browser=android-chromium", + "--story-filter load:search:google", + "--extra-browser-args \"--enable-heap-profiler\"" + ], + "isolate_name": "telemetry_perf_tests", + "name": "system_health.memory_mobile", + "override_compile_targets": [ + "telemetry_perf_tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "4", + "device_os": "KTU84P", + "device_type": "hammerhead" + } + ], + "hard_timeout": 600 + } + } + ] + }, "Nougat Phone Tester": { "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 7946643..c2f04d0 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -37,6 +37,9 @@ "test": "app_shell_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -55,6 +58,9 @@ "test": "aura_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -76,12 +82,18 @@ "test": "browser_tests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "cacheinvalidation_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -119,12 +131,18 @@ "test": "content_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "crypto_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -137,12 +155,18 @@ "test": "display_service_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "display_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -161,12 +185,18 @@ "test": "extensions_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "gcm_unit_tests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -206,6 +236,9 @@ "test": "gpu_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -225,18 +258,27 @@ "test": "ipc_tests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "jingle_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "mash_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -249,6 +291,9 @@ "test": "media_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -262,10 +307,10 @@ }, { "args": [ - "--override-use-gl-with-osmesa-for-tests" + "--ozone-platform=x11" ], "swarming": { - "can_use_on_swarming_builders": false + "can_use_on_swarming_builders": true }, "test": "mus_demo_unittests" }, @@ -288,6 +333,9 @@ "test": "nacl_loader_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -306,12 +354,18 @@ "test": "ozone_gl_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "ozone_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -345,18 +399,27 @@ "test": "sandbox_linux_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "skia_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "sql_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -369,6 +432,9 @@ "test": "ui_arc_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, @@ -381,12 +447,18 @@ "test": "ui_chromeos_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true }, "test": "ui_struct_traits_unittests" }, { + "args": [ + "--ozone-platform=x11" + ], "swarming": { "can_use_on_swarming_builders": true },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 3e6459ec..3aa126b 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -649,7 +649,8 @@ }, { "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "shards": 5 }, "test": "content_browsertests" },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index a6bc5a9..1ebd4ac 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -86,9 +86,9 @@ ], "experiments": [ { - "name": "EnabledFive", + "name": "EnabledThree", "params": { - "impression_limit": "5" + "impression_limit": "3" }, "enable_features": [ "AutofillCreditCardSigninPromo"
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation index feab190f..7a45edd 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -30,10 +30,6 @@ crbug.com/551000 http/tests/inspector/network/network-initiator.html [ Failure ] crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-document-initiator.html [ Failure ] crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-initiator.html [ Failure ] -# Duplicate started loading output. -# Fixed by https://codereview.chromium.org/2622083004/ -crbug.com/551000 inspector-protocol/page/frameAttachedDetached.html [ Failure ] -crbug.com/551000 inspector-protocol/page/frameStartedLoading.html [ Failure ] # https://crbug.com/625765: Need to solve duplicate output from # WebFrameTestClient::willSendRequest() that causes text failures.
diff --git a/third_party/WebKit/LayoutTests/external/README b/third_party/WebKit/LayoutTests/external/README index 6b54aedd..2547008 100644 --- a/third_party/WebKit/LayoutTests/external/README +++ b/third_party/WebKit/LayoutTests/external/README
@@ -4,8 +4,8 @@ imported from the W3C's test suite repositories on GitHub, and changes to web-platform-tests should be exported to the upstream repo. -Use Tools/Scripts/update-w3c-deps to update the tests from the tip of -tree in those repositories. +Use Tools/Scripts/wpt-import to update the tests from the tip of tree +in those repositories. It is safe and okay to check in generic baselines for any tests that fail. The baselines will not be overwritten.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-cancelBubble-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-cancelBubble-expected.txt deleted file mode 100644 index 073ac2b6..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-cancelBubble-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -PASS cancelBubble must be false when an event is initially created. -FAIL Initializing an event must set cancelBubble to false. assert_false: initEvent() must set cancelBubble to false. [bubbles=true] expected false got true -FAIL stopPropagation() must set cancelBubble to true. assert_true: stopPropagation() must set cancelBubble to true. expected true got false -FAIL stopImmediatePropagation() must set cancelBubble to true. assert_true: stopImmediatePropagation() must set cancelBubble to true. expected true got false -FAIL Event.cancelBubble=false must have no effect. assert_true: cancelBubble must still be true after attempting to set it to false. expected true got false -FAIL Event.cancelBubble=false must have no effect during event propagation. assert_unreached: Setting Event.cancelBubble=false after setting Event.cancelBubble=true should have no effect. Reached unreachable code -PASS cancelBubble must be false after an event has been dispatched. -FAIL Event.cancelBubble=true must set the stop propagation flag. assert_unreached: Setting cancelBubble=true should stop the event from propagating further, including during the Capture Phase. Reached unreachable code -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubble-canceled-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubble-canceled-expected.txt deleted file mode 100644 index 1c3c1b8..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubble-canceled-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Setting cancelBubble=true prior to dispatchEvent() assert_array_equals: actual_targets lengths differ, expected 0 got 9 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-multiple-cancelBubble-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-multiple-cancelBubble-expected.txt deleted file mode 100644 index fc880274..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-multiple-cancelBubble-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Multiple dispatchEvent() and cancelBubble assert_array_equals: lengths differ, expected 2 got 1 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-propagation-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-propagation-expected.txt deleted file mode 100644 index 718901d..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-propagation-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -This is a testharness.js-based test. -PASS Newly-created Event -PASS After stopPropagation() -PASS Reinitialized after stopPropagation() -PASS After stopImmediatePropagation() -PASS Reinitialized after stopImmediatePropagation() -FAIL After cancelBubble=true assert_equals: Propagation flag expected false but got true -PASS Reinitialized after cancelBubble=true -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/fast/text/international/thai-baht-space.html b/third_party/WebKit/LayoutTests/fast/text/international/thai-baht-space.html index 5e312a2c..eaa8ce34 100644 --- a/third_party/WebKit/LayoutTests/fast/text/international/thai-baht-space.html +++ b/third_party/WebKit/LayoutTests/fast/text/international/thai-baht-space.html
@@ -4,7 +4,7 @@ <title>Test for bug 25464 : Thai Baht and Space</title> </HEAD> <BODY> -Test for <a href="http://bugs.webkit.org/show_bug.cgi?id=25464">bug 25464</a>. Characters belonging to 'Common' script followed / preceeded by a space should be rendered correctly. Two lines below have 4 Thai currency signs +Test for <a href="http://bugs.webkit.org/show_bug.cgi?id=25464">bug 25464</a>. Characters belonging to 'Common' script followed / preceded by a space should be rendered correctly. Two lines below have 4 Thai currency signs (U+0E3F) and all of them should be rendered. <p> abc ลงทุน4000฿ รับประกันรายได้ 50000฿/M<br>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-replay-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-replay-expected.txt index 627c9e8..74a32a4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-replay-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-replay-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE WARNING: line 37: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. CONSOLE MESSAGE: line 6: XHR loaded: 1 CONSOLE WARNING: line 33: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. CONSOLE MESSAGE: line 6: XHR loaded: 2
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/multiple-report-policies-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/multiple-report-policies-expected.txt index 6df1da9..bca6a5d49 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/multiple-report-policies-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/multiple-report-policies-expected.txt
@@ -4,4 +4,5 @@ CONSOLE ERROR: line 8: [Report Only] Refused to load the image 'ftp://blah.test/' because it violates the following Content Security Policy directive: "img-src http://*". PingLoader dispatched to 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/save-report.php?test=multiple-report-policies-2'. +CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details.
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/deprecated-subresource-requests-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/deprecated-subresource-requests-expected.txt new file mode 100644 index 0000000..fc3e6bf --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/deprecated-subresource-requests-expected.txt
@@ -0,0 +1,6 @@ +CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details. +CONSOLE WARNING: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. +This is a testharness.js-based test. +PASS Untitled +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/deprecated-subresource-requests.html b/third_party/WebKit/LayoutTests/http/tests/security/deprecated-subresource-requests.html new file mode 100644 index 0000000..fb144d6e --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/deprecated-subresource-requests.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<img src="ftp://example.test/img.png"> +<img src="http://user:pass@example.test/img.png"> +<script> +test(() => { + // Doing nothing, we just want to check the warnings. +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/location-href-clears-username-password-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/location-href-clears-username-password-expected.txt index 1521acf8..9752bd9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/location-href-clears-username-password-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/security/location-href-clears-username-password-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE WARNING: line 17: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. ALERT: PASS This test passes if it alerts the string "PASS".
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt index d976089..5dcde08 100644 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects-async-expected.txt
@@ -1,4 +1,5 @@ CONSOLE ERROR: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?url=http://localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi. Redirect from 'http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?url=http://localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi' to 'http://localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. +CONSOLE WARNING: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. CONSOLE ERROR: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?url=http://username:password@localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&%20%20access-control-allow-origin=http://127.0.0.1:8000. Redirect from 'http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?url=http://username:password@localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&%20%20access-control-allow-origin=http://127.0.0.1:8000' has been blocked by CORS policy: Redirect location 'http://username:password@localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi' contains a username and password, which is disallowed for cross-origin requests. CONSOLE ERROR: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?url=foo://bar.cgi&%20%20access-control-allow-origin=http://127.0.0.1:8000. Redirect from 'http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?url=foo://bar.cgi&%20%20access-control-allow-origin=http://127.0.0.1:8000' has been blocked by CORS policy: Redirect location 'foo://bar.cgi' has a disallowed scheme for cross-origin requests. CONSOLE ERROR: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/redirect-cors.php?redirect-preflight=true&%20%20url=http://localhost:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi&%20%20access-control-allow-origin=*. Response for preflight is invalid (redirect)
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/failed-auth-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/failed-auth-expected.txt index fe156974..ce349cd 100644 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/failed-auth-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/failed-auth-expected.txt
@@ -1,4 +1,5 @@ CONSOLE WARNING: line 30: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. +CONSOLE WARNING: line 40: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. Test for bug 13075: XMLHttpRequest with failed authentication should set status to 401. Sync, no credentials: OK
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/logout-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/logout-expected.txt index 00d7c731..aacb566 100644 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/logout-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/logout-expected.txt
@@ -1,4 +1,5 @@ CONSOLE WARNING: line 17: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. +CONSOLE WARNING: line 18: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. rdar://problem/6447115 Test that a method for logging out of a site that is used by SAP works. If an authentication dialog appears, please cancel it.
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt index ddd4f16..127444c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/null-auth-expected.txt
@@ -1,4 +1,5 @@ CONSOLE WARNING: line 9: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. +CONSOLE WARNING: line 10: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. Test that null values in XHR login/password parameters are treated correctly. No auth tokens should be sent with this request.
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/remember-bad-password-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/remember-bad-password-expected.txt index 585d0516..dae7745 100644 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/remember-bad-password-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/remember-bad-password-expected.txt
@@ -1,4 +1,5 @@ CONSOLE WARNING: line 53: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. +CONSOLE WARNING: line 23: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. rdar://problem/7062824 A wrong password entered for site or proxy auth remains in WebCore credential storage, and is sent with subsequent requests. This test counts the number of failed requests server side.
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/referer-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/referer-expected.txt index 040d2f4..29b4e33 100644 --- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/referer-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/referer-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE WARNING: line 3: Subresource requests whose URLs contain embedded credentials (e.g. `https://user:pass@host/`) are deprecated, and will be blocked in M59, around June 2017. See https://www.chromestatus.com/feature/5669008342777856 for more details. Referer should be set for XMLHttpRequest from Workers. PASS: Sync referer.
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.png index eda9add..5abdae5 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.txt index 619f4538..ae9bc55 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/thai-baht-space-expected.txt
@@ -9,8 +9,8 @@ LayoutInline {A} at (0,0) size 67x19 [color=#0000EE] LayoutText {#text} at (49,0) size 67x19 text run at (49,0) width 67: "bug 25464" - LayoutText {#text} at (115,0) size 782x39 - text run at (115,0) width 667: ". Characters belonging to 'Common' script followed / preceeded by a space should be rendered correctly. Two" + LayoutText {#text} at (115,0) size 775x39 + text run at (115,0) width 660: ". Characters belonging to 'Common' script followed / preceded by a space should be rendered correctly. Two" text run at (0,20) width 514: "lines below have 4 Thai currency signs (U+0E3F) and all of them should be rendered." LayoutBlockFlow {P} at (0,56) size 784x60 LayoutText {#text} at (0,6) size 290x19
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/thai-baht-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/thai-baht-space-expected.png index 86f54a9..d510465 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/thai-baht-space-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/thai-baht-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/thai-baht-space-expected.png index 4b4b50d..878631c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/thai-baht-space-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.png index 5c3c0d9..686d17419a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.txt index 1e89a21b..cc67013 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/thai-baht-space-expected.txt
@@ -9,9 +9,9 @@ LayoutInline {A} at (0,0) size 69x18 [color=#0000EE] LayoutText {#text} at (53,0) size 69x18 text run at (53,0) width 69: "bug 25464" - LayoutText {#text} at (121,0) size 726x36 - text run at (121,0) width 605: ". Characters belonging to 'Common' script followed / preceeded by a space should be rendered" - text run at (0,18) width 646: "correctly. Two lines below have 4 Thai currency signs (U+0E3F) and all of them should be rendered." + LayoutText {#text} at (121,0) size 783x36 + text run at (121,0) width 662: ". Characters belonging to 'Common' script followed / preceded by a space should be rendered correctly." + text run at (0,18) width 582: "Two lines below have 4 Thai currency signs (U+0E3F) and all of them should be rendered." LayoutBlockFlow {P} at (0,52) size 784x44 LayoutText {#text} at (0,3) size 286x18 text run at (0,3) width 286: "abc \x{E25}\x{E07}\x{E17}\x{E38}\x{E19}4000\x{E3F} \x{E23}\x{E31}\x{E1A}\x{E1B}\x{E23}\x{E30}\x{E01}\x{E31}\x{E19}\x{E23}\x{E32}\x{E22}\x{E44}\x{E14}\x{E49} 50000\x{E3F}/M"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.png index df8bcec..0d3ea9eb 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.txt index 8041e93..b7f6d34 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/thai-baht-space-expected.txt
@@ -9,9 +9,9 @@ LayoutInline {A} at (0,0) size 69x17 [color=#0000EE] LayoutText {#text} at (53,0) size 69x17 text run at (53,0) width 69: "bug 25464" - LayoutText {#text} at (121,0) size 726x35 - text run at (121,0) width 605: ". Characters belonging to 'Common' script followed / preceeded by a space should be rendered" - text run at (0,18) width 646: "correctly. Two lines below have 4 Thai currency signs (U+0E3F) and all of them should be rendered." + LayoutText {#text} at (121,0) size 783x35 + text run at (121,0) width 662: ". Characters belonging to 'Common' script followed / preceded by a space should be rendered correctly." + text run at (0,18) width 582: "Two lines below have 4 Thai currency signs (U+0E3F) and all of them should be rendered." LayoutBlockFlow {P} at (0,52) size 784x40 LayoutText {#text} at (0,2) size 285x17 text run at (0,2) width 285: "abc \x{E25}\x{E07}\x{E17}\x{E38}\x{E19}4000\x{E3F} \x{E23}\x{E31}\x{E1A}\x{E1B}\x{E23}\x{E30}\x{E01}\x{E31}\x{E19}\x{E23}\x{E32}\x{E22}\x{E44}\x{E14}\x{E49} 50000\x{E3F}/M"
diff --git a/third_party/WebKit/LayoutTests/security/block-test-expected.txt b/third_party/WebKit/LayoutTests/security/block-test-expected.txt index 630f04f..846c463 100644 --- a/third_party/WebKit/LayoutTests/security/block-test-expected.txt +++ b/third_party/WebKit/LayoutTests/security/block-test-expected.txt
@@ -131,6 +131,7 @@ CONSOLE MESSAGE: line 32: PASS: error event fired for http://255.255.255.255:65536/test.jpg CONSOLE MESSAGE: line 32: PASS: error event fired for http://255.255.255.255:4294967295/test.jpg CONSOLE MESSAGE: line 32: PASS: error event fired for http://255.255.255.255:4294967296/test.jpg +CONSOLE WARNING: Subresource requests using legacy protocols (like `ftp:`) are deprecated, and will be blocked in M59, around June 2017. Please deliver web-accessible resources over modern protocols like HTTPS. See https://www.chromestatus.com/feature/5709390967472128 for more details. ftp://255.255.255.255/test.jpg - willSendRequest <NSURLRequest URL ftp://255.255.255.255/test.jpg, main document URL block-test.html, http method GET> CONSOLE MESSAGE: line 32: PASS: error event fired for ftp://255.255.255.255/test.jpg ftp://255.255.255.255/test.jpg - willSendRequest <NSURLRequest URL ftp://255.255.255.255/test.jpg, main document URL block-test.html, http method GET>
diff --git a/third_party/WebKit/Source/core/events/Event.cpp b/third_party/WebKit/Source/core/events/Event.cpp index 3c9428ad..3b27344 100644 --- a/third_party/WebKit/Source/core/events/Event.cpp +++ b/third_party/WebKit/Source/core/events/Event.cpp
@@ -87,7 +87,6 @@ m_immediatePropagationStopped(false), m_defaultPrevented(false), m_defaultHandled(false), - m_cancelBubble(false), m_wasInitialized(true), m_isTrusted(false), m_preventDefaultCalledOnUncancelableEvent(false), @@ -337,11 +336,8 @@ } void Event::setCancelBubble(ExecutionContext* context, bool cancel) { - if (!m_cancelBubble && cancel) - UseCounter::count(context, UseCounter::EventCancelBubbleWasChangedToTrue); - else if (m_cancelBubble && !cancel) - UseCounter::count(context, UseCounter::EventCancelBubbleWasChangedToFalse); - m_cancelBubble = cancel; + if (cancel) + m_propagationStopped = true; } DEFINE_TRACE(Event) {
diff --git a/third_party/WebKit/Source/core/events/Event.h b/third_party/WebKit/Source/core/events/Event.h index b5d4bb5..d85ac87 100644 --- a/third_party/WebKit/Source/core/events/Event.h +++ b/third_party/WebKit/Source/core/events/Event.h
@@ -199,7 +199,7 @@ void setDefaultHandled() { m_defaultHandled = true; } bool cancelBubble(ExecutionContext* = nullptr) const { - return m_cancelBubble; + return propagationStopped(); } void setCancelBubble(ExecutionContext*, bool); @@ -285,7 +285,6 @@ unsigned m_immediatePropagationStopped : 1; unsigned m_defaultPrevented : 1; unsigned m_defaultHandled : 1; - unsigned m_cancelBubble : 1; unsigned m_wasInitialized : 1; unsigned m_isTrusted : 1;
diff --git a/third_party/WebKit/Source/core/events/EventDispatcher.cpp b/third_party/WebKit/Source/core/events/EventDispatcher.cpp index eb277c1..c89649f3 100644 --- a/third_party/WebKit/Source/core/events/EventDispatcher.cpp +++ b/third_party/WebKit/Source/core/events/EventDispatcher.cpp
@@ -218,11 +218,6 @@ } else if (m_event->bubbles() && !m_event->cancelBubble()) { m_event->setEventPhase(Event::kBubblingPhase); } else { - if (m_event->bubbles() && m_event->cancelBubble() && - eventContext.node() && - eventContext.node()->hasEventListeners(m_event->type())) - UseCounter::count(eventContext.node()->document(), - UseCounter::EventCancelBubbleAffected); continue; } eventContext.handleLocalEvents(*m_event); @@ -232,17 +227,6 @@ if (m_event->bubbles() && !m_event->cancelBubble()) { m_event->setEventPhase(Event::kBubblingPhase); m_event->eventPath().windowEventContext().handleLocalEvents(*m_event); - } else if (m_event->bubbles() && - m_event->eventPath().windowEventContext().window() && - m_event->eventPath() - .windowEventContext() - .window() - ->hasEventListeners(m_event->type())) { - UseCounter::count(m_event->eventPath() - .windowEventContext() - .window() - ->getExecutionContext(), - UseCounter::EventCancelBubbleAffected); } }
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp index 07966da0..e19e368 100644 --- a/third_party/WebKit/Source/core/frame/Deprecation.cpp +++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -263,6 +263,24 @@ case UseCounter::RangeExpand: return replacedBy("'Range.expand()'", "'Selection.modify()'"); + // Blocked subresource requests: + case UseCounter::LegacyProtocolEmbeddedAsSubresource: + return String::format( + "Subresource requests using legacy protocols (like `ftp:`) are " + "deprecated, and will be blocked in %s. Please deliver " + "web-accessible resources over modern protocols like HTTPS. " + "See https://www.chromestatus.com/feature/5709390967472128 for more " + "details.", + milestoneString(M59)); + + case UseCounter::RequestedSubresourceWithEmbeddedCredentials: + return String::format( + "Subresource requests whose URLs contain embedded credentials (e.g. " + "`https://user:pass@host/`) are deprecated, and will be blocked in " + "%s. See https://www.chromestatus.com/feature/5669008342777856 for " + "more details.", + milestoneString(M59)); + // Powerful features on insecure origins (https://goo.gl/rStTGz) case UseCounter::DeviceMotionInsecureOrigin: return "The devicemotion event is deprecated on insecure origins, and "
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index d8e3896..dc8e309 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1019,9 +1019,6 @@ ProgressElementWithNoneAppearance = 1345, ProgressElementWithProgressBarAppearance = 1346, PointerEventAddListenerCount = 1347, - EventCancelBubbleAffected = 1348, - EventCancelBubbleWasChangedToTrue = 1349, - EventCancelBubbleWasChangedToFalse = 1350, CSSValueAppearanceNone = 1351, CSSValueAppearanceNotNone = 1352, CSSValueAppearanceOthers = 1353,
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h b/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h index fecf48c0..d21ec61 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElementTypes.h
@@ -79,6 +79,8 @@ // ---------------------------- +// TODO(mustaq): The Media control elements that use MouseEvents should be +// ported to use PointerEvents instead. class MediaControlElement : public GarbageCollectedMixin { public: // These hold the state about whether this control should be shown if
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp index b5a95e3..fd86d75 100644 --- a/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp +++ b/third_party/WebKit/Source/core/html/shadow/MediaControlElements.cpp
@@ -97,7 +97,11 @@ const AtomicString& type = event->type(); return type == EventTypeNames::mouseover || - type == EventTypeNames::mouseout || type == EventTypeNames::mousemove; + type == EventTypeNames::mouseout || + type == EventTypeNames::mousemove || + type == EventTypeNames::pointerover || + type == EventTypeNames::pointerout || + type == EventTypeNames::pointermove; } Element* elementFromCenter(Element& element) { @@ -753,18 +757,15 @@ MediaControlInputElement::defaultEventHandler(event); - if (event->type() == EventTypeNames::mouseover || - event->type() == EventTypeNames::mouseout || - event->type() == EventTypeNames::mousemove) + if (event->type() != EventTypeNames::input) return; double time = value().toDouble(); - if (event->type() == EventTypeNames::input) { - // FIXME: This will need to take the timeline offset into consideration - // once that concept is supported, see https://crbug.com/312699 - if (mediaElement().seekable()->contain(time)) - mediaElement().setCurrentTime(time); - } + + // FIXME: This will need to take the timeline offset into consideration + // once that concept is supported, see https://crbug.com/312699 + if (mediaElement().seekable()->contain(time)) + mediaElement().setCurrentTime(time); LayoutSliderItem slider = LayoutSliderItem(toLayoutSlider(layoutObject())); if (!slider.isNull() && slider.inDragMode()) @@ -813,21 +814,11 @@ } void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) { - if (event->isMouseEvent() && - toMouseEvent(event)->button() != - static_cast<short>(WebPointerProperties::Button::Left)) - return; - if (!isConnected() || !document().isActive()) return; MediaControlInputElement::defaultEventHandler(event); - if (event->type() == EventTypeNames::mouseover || - event->type() == EventTypeNames::mouseout || - event->type() == EventTypeNames::mousemove) - return; - if (event->type() == EventTypeNames::mousedown) Platform::current()->recordAction( UserMetricsAction("Media.Controls.VolumeChangeBegin")); @@ -836,9 +827,11 @@ Platform::current()->recordAction( UserMetricsAction("Media.Controls.VolumeChangeEnd")); - double volume = value().toDouble(); - mediaElement().setVolume(volume); - mediaElement().setMuted(false); + if (event->type() == EventTypeNames::input) { + double volume = value().toDouble(); + mediaElement().setVolume(volume); + mediaElement().setMuted(false); + } } bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents() {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc index 2d7a45b..56ce36f 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc
@@ -379,17 +379,6 @@ return AbsoluteVerticalNeedsEstimate(style); } -bool IsContainingBlockForAbsoluteChild(const ComputedStyle& container_style, - const ComputedStyle& child_style) { - EPosition position = child_style.position(); - bool contains_fixed = container_style.canContainFixedPositionObjects(); - bool contains_absolute = - container_style.canContainAbsolutePositionObjects() || contains_fixed; - - return (contains_absolute && position == AbsolutePosition) || - (contains_fixed && position == FixedPosition); -} - NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize( const NGConstraintSpace& space, const ComputedStyle& style,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.h b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.h index 91e0eaf5..1513af4 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.h
@@ -43,11 +43,6 @@ // estimated block size. CORE_EXPORT bool AbsoluteNeedsChildBlockSize(const ComputedStyle&); -// True if the container will contain an absolute child. -CORE_EXPORT bool IsContainingBlockForAbsoluteChild( - const ComputedStyle& container_style, - const ComputedStyle& child_style); - // Compute part of position that depends on child's inline_size // returns partially filled position. CORE_EXPORT NGAbsolutePhysicalPosition
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc index bd10701..aadb712 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -308,7 +308,8 @@ ComputeBlockSizeForFragment(ConstraintSpace(), Style(), content_size_); builder_->SetBlockSize(block_size); - LayoutOutOfFlowChildren(); + // Layout our absolute and fixed positioned children. + NGOutOfFlowLayoutPart(Style(), builder_).Run(); builder_->SetInlineOverflow(max_inline_size_).SetBlockOverflow(content_size_); @@ -339,32 +340,6 @@ builder_->AddChild(fragment, fragment_offset); } -void NGBlockLayoutAlgorithm::LayoutOutOfFlowChildren() { - HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; - Vector<NGStaticPosition> out_of_flow_candidate_positions; - builder_->GetAndClearOutOfFlowDescendantCandidates( - &out_of_flow_candidates, &out_of_flow_candidate_positions); - - Member<NGOutOfFlowLayoutPart> out_of_flow_layout = - new NGOutOfFlowLayoutPart(&Style(), builder_->Size()); - size_t candidate_positions_index = 0; - - for (auto& child : out_of_flow_candidates) { - NGStaticPosition static_position = - out_of_flow_candidate_positions[candidate_positions_index++]; - - if (IsContainingBlockForAbsoluteChild(Style(), *child->Style())) { - NGFragment* fragment; - NGLogicalOffset offset; - out_of_flow_layout->Layout(*child, static_position, &fragment, &offset); - // TODO(atotic) Need to adjust size of overflow rect per spec. - builder_->AddChild(fragment, offset); - } else { - builder_->AddOutOfFlowDescendant(child, static_position); - } - } -} - bool NGBlockLayoutAlgorithm::ProceedToNextUnfinishedSibling( NGPhysicalFragment* child_fragment) { DCHECK(current_child_);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h index b0599801..6728849 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -53,7 +53,6 @@ // Creates a new constraint space for the current child. NGConstraintSpace* CreateConstraintSpaceForCurrentChild(); void FinishCurrentChildLayout(NGFragment* fragment); - void LayoutOutOfFlowChildren(); // Proceed to the next sibling that still needs layout. //
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc index 45eaca4..70250224 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -75,8 +75,8 @@ NGFragmentBuilder& NGFragmentBuilder::AddFloatingObject( NGFloatingObject* floating_object, const NGLogicalOffset& floating_object_offset) { - positioned_floats_.append(floating_object); - floating_object_offsets_.append(floating_object_offset); + positioned_floats_.push_back(floating_object); + floating_object_offsets_.push_back(floating_object_offset); return *this; } @@ -94,7 +94,7 @@ NGFragmentBuilder& NGFragmentBuilder::AddUnpositionedFloat( NGFloatingObject* floating_object) { - unpositioned_floats_.append(floating_object); + unpositioned_floats_.push_back(floating_object); return *this; } @@ -177,7 +177,7 @@ NGPhysicalFragment* floating_fragment = floating_object->fragment; floating_fragment->SetOffset(floating_object_offsets_[i].ConvertToPhysical( writing_mode_, direction_, physical_size, floating_fragment->Size())); - positioned_floats.append(floating_object); + positioned_floats.push_back(floating_object); } return new NGPhysicalBoxFragment(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h index d1a7301..901cf7b 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
@@ -56,26 +56,13 @@ // builder->AddChild(fragment) // end // - // Part 2: layout algorithm positions out-of-flow descendants. - // // builder->SetInlineSize/SetBlockSize - // builder->GetAndClearOutOfFlowDescendantCandidates(oof_candidates); - // NGOutOfFlowLayoutPart out_of_flow_layout(container_style, - // builder->Size()); - // while (oof_candidates.size() > 0) - // { - // candidate = oof_candidates.shift(); - // if (IsContainingBlockForAbsoluteChild(style, candidate_style)) { - // NGFragmentBase* fragment; - // NGLogicalOffset* fragment_offset; - // out_of_flow_layout.Layout(candidate, &fragment, &offset); - // builder->AddChild(fragment); - // builder->GetAndClearOutOfFlowDescendantCandidates(child_oof_candidates); - // oof_candidates.prepend(child_oof_candidates); - // } else { - // builder->AddOutOfFlowDescendant(); - // } - // } + // + // Part 2: Out-of-flow layout part positions out-of-flow descendants. + // + // NGOutOfFlowLayoutPart(container_style, builder).Run(); + // + // See layout part for builder interaction. NGFragmentBuilder& AddOutOfFlowChildCandidate(NGBlockNode*, NGLogicalOffset); void GetAndClearOutOfFlowDescendantCandidates(WeakBoxList*,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc index be0f9ab1..95191f7 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc
@@ -179,7 +179,7 @@ LineLayoutItem(layout_object)); } bidi_runs.addRun(run); - fragments_for_bidi_runs.append(fragment); + fragments_for_bidi_runs.push_back(fragment); } } // TODO(kojii): bidi needs to find the logical last run.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc index cb2e9063..87f50db 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -9,26 +9,47 @@ #include "core/layout/ng/ng_box_fragment.h" #include "core/layout/ng/ng_constraint_space_builder.h" #include "core/layout/ng/ng_fragment.h" +#include "core/layout/ng/ng_fragment_builder.h" #include "core/layout/ng/ng_length_utils.h" #include "core/layout/ng/ng_physical_fragment.h" #include "core/style/ComputedStyle.h" namespace blink { +namespace { + +// True if the container will contain an absolute descendant. +bool IsContainingBlockForAbsoluteDescendant( + const ComputedStyle& container_style, + const ComputedStyle& descendant_style) { + EPosition position = descendant_style.position(); + bool contains_fixed = container_style.canContainFixedPositionObjects(); + bool contains_absolute = + container_style.canContainAbsolutePositionObjects() || contains_fixed; + + return (contains_absolute && position == AbsolutePosition) || + (contains_fixed && position == FixedPosition); +} + +} // namespace + NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( - PassRefPtr<const ComputedStyle> container_style, - NGLogicalSize container_size) { + const ComputedStyle& container_style, + NGFragmentBuilder* container_builder) + : container_style_(container_style), container_builder_(container_builder) { NGWritingMode writing_mode( - FromPlatformWritingMode(container_style->getWritingMode())); + FromPlatformWritingMode(container_style_.getWritingMode())); - NGBoxStrut borders = ComputeBorders(*container_style); - parent_border_offset_ = + NGBoxStrut borders = ComputeBorders(container_style_); + container_border_offset_ = NGLogicalOffset{borders.inline_start, borders.block_start}; - parent_border_physical_offset_ = parent_border_offset_.ConvertToPhysical( - writing_mode, container_style->direction(), - container_size.ConvertToPhysical(writing_mode), NGPhysicalSize()); + container_border_physical_offset_ = + container_border_offset_.ConvertToPhysical( + writing_mode, container_style_.direction(), + container_builder_->Size().ConvertToPhysical(writing_mode), + NGPhysicalSize()); - NGLogicalSize space_size = container_size; + NGLogicalSize space_size = container_builder_->Size(); space_size.block_size -= borders.BlockSum(); space_size.inline_size -= borders.InlineSum(); @@ -37,96 +58,119 @@ space_builder.SetAvailableSize(space_size); space_builder.SetPercentageResolutionSize(space_size); space_builder.SetIsNewFormattingContext(true); - space_builder.SetTextDirection(container_style->direction()); - parent_space_ = space_builder.ToConstraintSpace(); + space_builder.SetTextDirection(container_style_.direction()); + container_space_ = space_builder.ToConstraintSpace(); } -void NGOutOfFlowLayoutPart::Layout(NGBlockNode& node, - NGStaticPosition static_position, - NGFragment** fragment_out, - NGLogicalOffset* offset) { +void NGOutOfFlowLayoutPart::Run() { + HeapLinkedHashSet<WeakMember<NGBlockNode>> out_of_flow_candidates; + Vector<NGStaticPosition> out_of_flow_candidate_positions; + container_builder_->GetAndClearOutOfFlowDescendantCandidates( + &out_of_flow_candidates, &out_of_flow_candidate_positions); + + size_t position_index = 0; + + for (auto& descendant : out_of_flow_candidates) { + NGStaticPosition static_position = + out_of_flow_candidate_positions[position_index++]; + + if (IsContainingBlockForAbsoluteDescendant(container_style_, + *descendant->Style())) { + NGLogicalOffset offset; + NGFragment* fragment = + LayoutDescendant(*descendant, static_position, &offset); + // TODO(atotic) Need to adjust size of overflow rect per spec. + container_builder_->AddChild(fragment, offset); + } else { + container_builder_->AddOutOfFlowDescendant(descendant, static_position); + } + } +} + +NGFragment* NGOutOfFlowLayoutPart::LayoutDescendant( + NGBlockNode& descendant, + NGStaticPosition static_position, + NGLogicalOffset* offset) { // Adjust the static_position origin. The static_position coordinate origin is - // relative to the parent's border box, ng_absolute_utils expects it to be - // relative to the parent's padding box. - static_position.offset -= parent_border_physical_offset_; + // relative to the container's border box, ng_absolute_utils expects it to be + // relative to the container's padding box. + static_position.offset -= container_border_physical_offset_; NGFragment* fragment = nullptr; Optional<MinAndMaxContentSizes> inline_estimate; Optional<LayoutUnit> block_estimate; - if (AbsoluteNeedsChildInlineSize(*node.Style())) { - inline_estimate = node.ComputeMinAndMaxContentSizesSync(); + if (AbsoluteNeedsChildInlineSize(*descendant.Style())) { + inline_estimate = descendant.ComputeMinAndMaxContentSizesSync(); } NGAbsolutePhysicalPosition node_position = ComputePartialAbsoluteWithChildInlineSize( - *parent_space_, *node.Style(), static_position, inline_estimate); + *container_space_, *descendant.Style(), static_position, + inline_estimate); - if (AbsoluteNeedsChildBlockSize(*node.Style())) { - fragment = GenerateFragment(node, block_estimate, node_position); + if (AbsoluteNeedsChildBlockSize(*descendant.Style())) { + fragment = GenerateFragment(descendant, block_estimate, node_position); block_estimate = fragment->BlockSize(); } - ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node.Style(), + ComputeFullAbsoluteWithChildBlockSize(*container_space_, *descendant.Style(), static_position, block_estimate, &node_position); // Skip this step if we produced a fragment when estimating the block size. if (!fragment) { block_estimate = - node_position.size.ConvertToLogical(parent_space_->WritingMode()) + node_position.size.ConvertToLogical(container_space_->WritingMode()) .block_size; - fragment = GenerateFragment(node, block_estimate, node_position); + fragment = GenerateFragment(descendant, block_estimate, node_position); } - *fragment_out = fragment; - // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative - // to the padding box so add back the parent's borders. + // to the padding box so add back the container's borders. NGBoxStrut inset = node_position.inset.ConvertToLogical( - parent_space_->WritingMode(), parent_space_->Direction()); + container_space_->WritingMode(), container_space_->Direction()); offset->inline_offset = - inset.inline_start + parent_border_offset_.inline_offset; - offset->block_offset = inset.block_start + parent_border_offset_.block_offset; + inset.inline_start + container_border_offset_.inline_offset; + offset->block_offset = + inset.block_start + container_border_offset_.block_offset; + + return fragment; } NGFragment* NGOutOfFlowLayoutPart::GenerateFragment( - NGBlockNode& node, + NGBlockNode& descendant, const Optional<LayoutUnit>& block_estimate, const NGAbsolutePhysicalPosition node_position) { // The fragment is generated in one of these two scenarios: - // 1. To estimate child's block size, in this case block_size is parent's - // available size. + // 1. To estimate descendant's block size, in this case block_size is + // container's available size. // 2. To compute final fragment, when block size is known from the absolute // position calculation. LayoutUnit inline_size = - node_position.size.ConvertToLogical(parent_space_->WritingMode()) + node_position.size.ConvertToLogical(container_space_->WritingMode()) .inline_size; LayoutUnit block_size = block_estimate ? *block_estimate - : parent_space_->AvailableSize().block_size; + : container_space_->AvailableSize().block_size; NGLogicalSize available_size{inline_size, block_size}; - NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); + NGConstraintSpaceBuilder builder(container_space_->WritingMode()); builder.SetAvailableSize(available_size); - builder.SetPercentageResolutionSize(parent_space_->AvailableSize()); + builder.SetPercentageResolutionSize(container_space_->AvailableSize()); if (block_estimate) builder.SetIsFixedSizeBlock(true); builder.SetIsFixedSizeInline(true); builder.SetIsNewFormattingContext(true); NGConstraintSpace* space = builder.ToConstraintSpace(); - NGPhysicalFragment* fragment = node.Layout(space); + NGPhysicalFragment* fragment = descendant.Layout(space); // TODO(ikilpatrick): the writing mode switching here looks wrong. - return new NGBoxFragment(parent_space_->WritingMode(), - parent_space_->Direction(), + return new NGBoxFragment(container_space_->WritingMode(), + container_space_->Direction(), toNGPhysicalBoxFragment(fragment)); } -DEFINE_TRACE(NGOutOfFlowLayoutPart) { - visitor->trace(parent_space_); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h index fa30ecb..fcf64753 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -19,29 +19,36 @@ class ComputedStyle; class NGBlockNode; class NGFragment; +class NGFragmentBuilder; class NGConstraintSpace; // Helper class for positioning of out-of-flow blocks. // It should be used together with NGFragmentBuilder. // See NGFragmentBuilder::AddOutOfFlowChildCandidate documentation // for example of using these classes together. -class CORE_EXPORT NGOutOfFlowLayoutPart - : public GarbageCollectedFinalized<NGOutOfFlowLayoutPart> { +class CORE_EXPORT NGOutOfFlowLayoutPart { + STACK_ALLOCATED(); + public: - NGOutOfFlowLayoutPart(PassRefPtr<const ComputedStyle>, NGLogicalSize); - - void Layout(NGBlockNode&, NGStaticPosition, NGFragment**, NGLogicalOffset*); - - DECLARE_TRACE(); + NGOutOfFlowLayoutPart(const ComputedStyle& container_style, + NGFragmentBuilder* container_builder); + void Run(); private: + NGFragment* LayoutDescendant(NGBlockNode& descendant, + NGStaticPosition static_position, + NGLogicalOffset* offset); + NGFragment* GenerateFragment(NGBlockNode& node, const Optional<LayoutUnit>& block_estimate, const NGAbsolutePhysicalPosition node_position); - NGLogicalOffset parent_border_offset_; - NGPhysicalOffset parent_border_physical_offset_; - Member<NGConstraintSpace> parent_space_; + const ComputedStyle& container_style_; + Member<NGFragmentBuilder> container_builder_; + + NGLogicalOffset container_border_offset_; + NGPhysicalOffset container_border_physical_offset_; + Member<NGConstraintSpace> container_space_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 379d3e4..1bcf7cab 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -33,6 +33,7 @@ #include "bindings/core/v8/ScriptController.h" #include "bindings/core/v8/V8DOMActivityLogger.h" #include "core/dom/Document.h" +#include "core/frame/Deprecation.h" #include "core/frame/FrameConsole.h" #include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" @@ -764,11 +765,11 @@ if (SchemeRegistry::shouldTreatURLSchemeAsLegacy(url.protocol()) && !SchemeRegistry::shouldTreatURLSchemeAsLegacy( frame()->document()->getSecurityOrigin()->protocol())) { - UseCounter::count(frame()->document(), - UseCounter::LegacyProtocolEmbeddedAsSubresource); + Deprecation::countDeprecation( + frame()->document(), UseCounter::LegacyProtocolEmbeddedAsSubresource); } if (!url.user().isEmpty() || !url.pass().isEmpty()) { - UseCounter::count( + Deprecation::countDeprecation( frame()->document(), UseCounter::RequestedSubresourceWithEmbeddedCredentials); }
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 72c6c4c..7f196f9 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1610,8 +1610,6 @@ bool replacesCurrentHistoryItem, bool isClientRedirect, HTMLFormElement* form) { - m_isNavigationHandledByClient = false; - // Don't ask if we are loading an empty URL. if (request.url().isEmpty() || substituteData.isValid()) return true; @@ -1673,14 +1671,47 @@ return false; } +bool FrameLoader::checkLoadCanStart(FrameLoadRequest& frameLoadRequest, + FrameLoadType type, + NavigationPolicy navigationPolicy, + NavigationType navigationType) { + if (m_frame->document()->pageDismissalEventBeingDispatched() != + Document::NoDismissal) { + return false; + } + + // Record the latest requiredCSP value that will be used when sending this + // request. + ResourceRequest& resourceRequest = frameLoadRequest.resourceRequest(); + recordLatestRequiredCSP(); + modifyRequestForCSP(resourceRequest, nullptr); + + if (!shouldContinueForNavigationPolicy( + resourceRequest, frameLoadRequest.substituteData(), nullptr, + frameLoadRequest.shouldCheckMainWorldContentSecurityPolicy(), + navigationType, navigationPolicy, + type == FrameLoadTypeReplaceCurrentItem, + frameLoadRequest.clientRedirect() == + ClientRedirectPolicy::ClientRedirect, + frameLoadRequest.form())) { + return false; + } + + m_frame->document()->cancelParsing(); + detachDocumentLoader(m_provisionalDocumentLoader); + + // beforeunload fired above, and detaching a DocumentLoader can fire events, + // which can detach this frame. + if (!m_frame->host()) + return false; + + return true; +} + void FrameLoader::startLoad(FrameLoadRequest& frameLoadRequest, FrameLoadType type, NavigationPolicy navigationPolicy) { DCHECK(client()->hasWebView()); - if (m_frame->document()->pageDismissalEventBeingDispatched() != - Document::NoDismissal) - return; - ResourceRequest& resourceRequest = frameLoadRequest.resourceRequest(); NavigationType navigationType = determineNavigationType( type, resourceRequest.httpBody() || frameLoadRequest.form(), @@ -1691,32 +1722,17 @@ ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested); - // Record the latest requiredCSP value that will be used when sending this - // request. - recordLatestRequiredCSP(); - modifyRequestForCSP(resourceRequest, nullptr); - - // We remember this flag here because shouldContinueForNavigationPolicy() - // resets it. - bool navigationWasHandledByClient = m_isNavigationHandledByClient; - - if (!shouldContinueForNavigationPolicy( - resourceRequest, frameLoadRequest.substituteData(), nullptr, - frameLoadRequest.shouldCheckMainWorldContentSecurityPolicy(), - navigationType, navigationPolicy, - type == FrameLoadTypeReplaceCurrentItem, - frameLoadRequest.clientRedirect() == - ClientRedirectPolicy::ClientRedirect, - frameLoadRequest.form())) + if (!checkLoadCanStart(frameLoadRequest, type, navigationPolicy, + navigationType)) { + // PlzNavigate: if the navigation is a commit of a client-handled + // navigation, record that there is no longer a navigation handled by the + // client. + if (m_isNavigationHandledByClient && + !frameLoadRequest.resourceRequest().checkForBrowserSideNavigation()) { + m_isNavigationHandledByClient = false; + } return; - - m_frame->document()->cancelParsing(); - detachDocumentLoader(m_provisionalDocumentLoader); - - // beforeunload fired above, and detaching a DocumentLoader can fire events, - // which can detach this frame. - if (!m_frame->host()) - return; + } m_provisionalDocumentLoader = client()->createDocumentLoader( m_frame, resourceRequest, @@ -1730,7 +1746,7 @@ // PlzNavigate: We need to ensure that script initiated navigations are // honored. - if (!navigationWasHandledByClient) { + if (!m_isNavigationHandledByClient) { m_frame->navigationScheduler().cancel(); m_checkTimer.stop(); } @@ -1740,7 +1756,14 @@ if (frameLoadRequest.form()) client()->dispatchWillSubmitForm(frameLoadRequest.form()); - m_progressTracker->progressStarted(); + // If the loader wasn't waiting for the client to handle a navigation, update + // the progress tracker. Otherwise don't, as it was already notified before + // sending the navigation to teh client. + if (!m_isNavigationHandledByClient) + m_progressTracker->progressStarted(); + else + m_isNavigationHandledByClient = false; + m_provisionalDocumentLoader->appendRedirect( m_provisionalDocumentLoader->getRequest().url()); client()->dispatchDidStartProvisionalLoad();
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.h b/third_party/WebKit/Source/core/loader/FrameLoader.h index 0f26e182..672c3a39 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.h +++ b/third_party/WebKit/Source/core/loader/FrameLoader.h
@@ -242,6 +242,10 @@ const KURL&); void processFragment(const KURL&, LoadStartType); + bool checkLoadCanStart(FrameLoadRequest&, + FrameLoadType, + NavigationPolicy, + NavigationType); void startLoad(FrameLoadRequest&, FrameLoadType, NavigationPolicy); enum class HistoryNavigationType { DifferentDocument, Fragment, HistoryApi };
diff --git a/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp b/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp index 7b47794..598859d 100644 --- a/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp +++ b/third_party/WebKit/Source/core/svg/SVGTreeScopeResources.cpp
@@ -111,7 +111,7 @@ elements->remove(element); if (elements->isEmpty()) - toBeRemoved.append(entry.key); + toBeRemoved.push_back(entry.key); } clearHasPendingResourcesIfPossible(element);
diff --git a/third_party/WebKit/Source/devtools/scripts/compile_frontend.py b/third_party/WebKit/Source/devtools/scripts/compile_frontend.py index 71ded46..11b51a0a 100755 --- a/third_party/WebKit/Source/devtools/scripts/compile_frontend.py +++ b/third_party/WebKit/Source/devtools/scripts/compile_frontend.py
@@ -93,11 +93,6 @@ loaded_css_regex = re.compile(r'(?:registerRequiredCSS|WebInspector\.View\.createStyleElement)\s*\(\s*"(.+)"\s*\)') java_build_regex = re.compile(r'^\w+ version "(\d+)\.(\d+)') -errors_found = False - -generate_protocol_externs.generate_protocol_externs(protocol_externs_file, - path.join(inspector_path, 'browser_protocol.json'), - path.join(v8_inspector_path, 'js_protocol.json')) def log_error(message): @@ -119,9 +114,6 @@ 'heap_snapshot_worker.json', 'utility_shared_worker.json', ] -loader = modular_build.DescriptorLoader(devtools_frontend_path) -descriptors = loader.load_applications(application_descriptors) -modules_by_name = descriptors.modules def has_errors(output): @@ -130,9 +122,10 @@ class JSDocChecker: - def __init__(self): + def __init__(self, descriptors, java_exec): self._error_found = False self._all_files = descriptors.all_compiled_files() + self._java_exec = java_exec def check(self): print 'Verifying JSDoc comments...' @@ -147,7 +140,7 @@ file_list.write('\n'.join(files)) finally: file_list.close() - proc = popen(java_exec + ['-jar', jsdoc_validator_jar, '--files-list-name', to_platform_path_exact(file_list.name)]) + proc = popen(self._java_exec + ['-jar', jsdoc_validator_jar, '--files-list-name', to_platform_path_exact(file_list.name)]) (out, _) = proc.communicate() if out: print('JSDoc validator output:%s%s' % (os.linesep, out)) @@ -234,8 +227,6 @@ return exec_command -java_exec = find_java() - common_closure_args = [ '--summary_detail_level', '3', @@ -257,7 +248,7 @@ ] -def check_conditional_dependencies(): +def check_conditional_dependencies(modules_by_name): errors_found = False for name in modules_by_name: for dep_name in modules_by_name[name].get('dependencies', []): @@ -268,14 +259,7 @@ return errors_found -errors_found |= check_conditional_dependencies() - -print 'Compiling frontend...' - -temp_devtools_path = tempfile.mkdtemp() - - -def prepare_closure_frontend_compile(): +def prepare_closure_frontend_compile(temp_devtools_path, descriptors): temp_frontend_path = path.join(temp_devtools_path, 'front_end') checker = dependency_preprocessor.DependencyPreprocessor(descriptors, temp_frontend_path, devtools_frontend_path) checker.enforce_dependencies() @@ -303,40 +287,58 @@ return compiler_args_file.name -compiler_args_file_path = prepare_closure_frontend_compile() -frontend_compile_proc = popen(java_exec + - ['-jar', closure_runner_jar, '--compiler-args-file', to_platform_path_exact(compiler_args_file_path)]) +def main(): + errors_found = False + generate_protocol_externs.generate_protocol_externs(protocol_externs_file, + path.join(inspector_path, 'browser_protocol.json'), + path.join(v8_inspector_path, 'js_protocol.json')) + loader = modular_build.DescriptorLoader(devtools_frontend_path) + descriptors = loader.load_applications(application_descriptors) + modules_by_name = descriptors.modules -print 'Compiling devtools_compatibility.js...' + java_exec = find_java() + errors_found |= check_conditional_dependencies(modules_by_name) -closure_compiler_command = java_exec + ['-jar', closure_compiler_jar] + common_closure_args + print 'Compiling frontend...' + temp_devtools_path = tempfile.mkdtemp() + compiler_args_file_path = prepare_closure_frontend_compile(temp_devtools_path, descriptors) + frontend_compile_proc = popen( + java_exec + ['-jar', closure_runner_jar, '--compiler-args-file', to_platform_path_exact(compiler_args_file_path)]) -devtools_js_compile_command = closure_compiler_command + [ - '--externs', to_platform_path(global_externs_file), '--externs', - to_platform_path(path.join(devtools_frontend_path, 'host', 'InspectorFrontendHostAPI.js')), '--jscomp_off=externsValidation', - '--js', to_platform_path(path.join(devtools_frontend_path, 'devtools_compatibility.js')) -] -devtools_js_compile_proc = popen(devtools_js_compile_command) + print 'Compiling devtools_compatibility.js...' -errors_found |= JSDocChecker().check() + closure_compiler_command = java_exec + ['-jar', closure_compiler_jar] + common_closure_args -(devtools_js_compile_out, _) = devtools_js_compile_proc.communicate() -print 'devtools_compatibility.js compilation output:%s' % os.linesep, devtools_js_compile_out -errors_found |= has_errors(devtools_js_compile_out) + devtools_js_compile_command = closure_compiler_command + [ + '--externs', to_platform_path(global_externs_file), '--externs', + to_platform_path(path.join(devtools_frontend_path, 'host', 'InspectorFrontendHostAPI.js')), + '--jscomp_off=externsValidation', '--js', to_platform_path(path.join(devtools_frontend_path, 'devtools_compatibility.js')) + ] + devtools_js_compile_proc = popen(devtools_js_compile_command) -(frontend_compile_out, _) = frontend_compile_proc.communicate() -print 'devtools frontend compilation output:' -for line in frontend_compile_out.splitlines(): - if "@@ START_MODULE" in line or "@@ END_MODULE" in line: - continue - print line -errors_found |= has_errors(frontend_compile_out) + errors_found |= JSDocChecker(descriptors, java_exec).check() -os.remove(protocol_externs_file) -os.remove(compiler_args_file_path) -shutil.rmtree(temp_devtools_path, True) + (devtools_js_compile_out, _) = devtools_js_compile_proc.communicate() + print 'devtools_compatibility.js compilation output:%s' % os.linesep, devtools_js_compile_out + errors_found |= has_errors(devtools_js_compile_out) -if errors_found: - print 'ERRORS DETECTED' - sys.exit(1) -print 'DONE - compiled without errors' + (frontend_compile_out, _) = frontend_compile_proc.communicate() + print 'devtools frontend compilation output:' + for line in frontend_compile_out.splitlines(): + if "@@ START_MODULE" in line or "@@ END_MODULE" in line: + continue + print line + errors_found |= has_errors(frontend_compile_out) + + os.remove(protocol_externs_file) + os.remove(compiler_args_file_path) + shutil.rmtree(temp_devtools_path, True) + + if errors_found: + print 'ERRORS DETECTED' + sys.exit(1) + print 'DONE - compiled without errors' + + +if __name__ == "__main__": + main()
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp index 5053e3ea..77979a5 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -165,7 +165,7 @@ if (Element* idElement = scope.getElementById(AtomicString(id))) { AXObject* axIdElement = obj.axObjectCache().getOrCreate(idElement); if (axIdElement && !axIdElement->accessibilityIsIgnored()) - objects.append(axIdElement); + objects.push_back(axIdElement); } } @@ -2467,7 +2467,7 @@ // default label nameFrom = AXNameFromContents; if (nameSources) { - nameSources->append(NameSource(*foundTextAlternative)); + nameSources->push_back(NameSource(*foundTextAlternative)); nameSources->back().type = nameFrom; } textAlternative = defaultLabel;
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp index f68c814..357f53f 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/modules/csspaint/PaintWorkletGlobalScope.cpp
@@ -126,7 +126,7 @@ exceptionState.throwTypeError("Invalid argument types."); return; } - inputArgumentTypes.append(syntaxDescriptor); + inputArgumentTypes.push_back(syntaxDescriptor); } } }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp index a17f89b..1c8d91b7b 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBEventDispatcher.cpp
@@ -28,7 +28,6 @@ #include "modules/indexeddb/IDBEventDispatcher.h" -#include "core/frame/UseCounter.h" #include "modules/EventModules.h" #include "modules/EventTargetModules.h" @@ -51,31 +50,15 @@ event->setEventPhase(Event::kAtTarget); event->setCurrentTarget(eventTargets[0].get()); eventTargets[0]->fireEventListeners(event); - if (event->propagationStopped() || !event->bubbles()) + if (event->propagationStopped() || !event->bubbles() || event->cancelBubble()) goto doneDispatching; - if (event->bubbles() && event->cancelBubble()) { - for (size_t i = 1; i < size; ++i) { // Don't do the first element. - if (eventTargets[i]->hasEventListeners(event->type())) - UseCounter::count(eventTargets[i]->getExecutionContext(), - UseCounter::EventCancelBubbleAffected); - } - goto doneDispatching; - } event->setEventPhase(Event::kBubblingPhase); for (size_t i = 1; i < size; ++i) { // Don't do the first element. event->setCurrentTarget(eventTargets[i].get()); eventTargets[i]->fireEventListeners(event); - if (event->propagationStopped()) + if (event->propagationStopped() || event->cancelBubble()) goto doneDispatching; - if (event->cancelBubble()) { - for (size_t j = i + 1; j < size; ++j) { - if (eventTargets[j]->hasEventListeners(event->type())) - UseCounter::count(eventTargets[j]->getExecutionContext(), - UseCounter::EventCancelBubbleAffected); - } - goto doneDispatching; - } } doneDispatching:
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationAvailabilityTest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationAvailabilityTest.cpp index 3f273a3d1..030c24dd 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationAvailabilityTest.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationAvailabilityTest.cpp
@@ -23,8 +23,8 @@ TEST(PresentationAvailabilityTest, NoPageVisibilityChangeAfterDetach) { V8TestingScope scope; WTF::Vector<KURL> urls; - urls.append(URLTestHelpers::toKURL("https://example.com")); - urls.append(URLTestHelpers::toKURL("https://another.com")); + urls.push_back(URLTestHelpers::toKURL("https://example.com")); + urls.push_back(URLTestHelpers::toKURL("https://another.com")); Persistent<PresentationAvailabilityProperty> resolver = new PresentationAvailabilityProperty(
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationRequestTest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationRequestTest.cpp index ceed6901..effc165 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationRequestTest.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationRequestTest.cpp
@@ -28,8 +28,8 @@ TEST(PresentationRequestTest, TestMultipleUrlConstructor) { V8TestingScope scope; WTF::Vector<String> urls; - urls.append("https://example.com"); - urls.append("cast://deadbeef?param=foo"); + urls.push_back("https://example.com"); + urls.push_back("cast://deadbeef?param=foo"); PresentationRequest* request = PresentationRequest::create( scope.getExecutionContext(), urls, scope.getExceptionState()); @@ -46,8 +46,8 @@ TEST(PresentationRequestTest, TestMultipleUrlConstructorInvalidURLFamily) { V8TestingScope scope; WTF::Vector<String> urls; - urls.append("https://example.com"); - urls.append("about://deadbeef?param=foo"); + urls.push_back("https://example.com"); + urls.push_back("about://deadbeef?param=foo"); PresentationRequest::create(scope.getExecutionContext(), urls, scope.getExceptionState()); @@ -59,8 +59,8 @@ TEST(PresentationRequestTest, TestMultipleUrlConstructorInvalidUrl) { V8TestingScope scope; WTF::Vector<String> urls; - urls.append("https://example.com"); - urls.append(""); + urls.push_back("https://example.com"); + urls.push_back(""); PresentationRequest::create(scope.getExecutionContext(), urls, scope.getExceptionState()); @@ -85,8 +85,8 @@ SecurityOrigin::createFromString("https://example.test")); WTF::Vector<String> urls; - urls.append("http://example.com"); - urls.append("https://example1.com"); + urls.push_back("http://example.com"); + urls.push_back("https://example1.com"); PresentationRequest::create(scope.getExecutionContext(), urls, scope.getExceptionState());
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc index e99519df..94694b6 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
@@ -576,10 +576,16 @@ any_thread().time_domain = time_domain; } - // We rely here on TimeDomain::MigrateQueue being thread-safe to use with - // TimeDomain::Register. - main_thread_only().time_domain->MigrateQueue(this, time_domain); + + main_thread_only().time_domain->UnregisterQueue(this); main_thread_only().time_domain = time_domain; + time_domain->RegisterQueue(this); + + if (!main_thread_only().delayed_incoming_queue.empty()) { + time_domain->ScheduleDelayedWork( + this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, + time_domain->Now()); + } } TimeDomain* TaskQueueImpl::GetTimeDomain() const {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc index 0e4a333..919543e9 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
@@ -31,31 +31,11 @@ CancelDelayedWork(queue); } -void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue, - TimeDomain* destination_time_domain) { - DCHECK(main_thread_checker_.CalledOnValidThread()); - DCHECK_EQ(queue->GetTimeDomain(), this); - DCHECK(destination_time_domain); - - // If no wakeup has been requested then bail out. - if (!queue->heap_handle().IsValid()) - return; - - base::TimeTicks wake_up_time = queue->scheduled_time_domain_wakeup(); - DCHECK_NE(wake_up_time, base::TimeTicks()); - - // O(log n) - delayed_wakeup_queue_.erase(queue->heap_handle()); - - base::TimeTicks destination_now = destination_time_domain->Now(); - destination_time_domain->ScheduleDelayedWork(queue, wake_up_time, - destination_now); -} - void TimeDomain::ScheduleDelayedWork(internal::TaskQueueImpl* queue, base::TimeTicks delayed_run_time, base::TimeTicks now) { DCHECK(main_thread_checker_.CalledOnValidThread()); + DCHECK_EQ(queue->GetTimeDomain(), this); // We only want to store a single wakeup per queue, so we need to remove any // previously registered wake up for |queue|. if (queue->heap_handle().IsValid()) {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h index 10202f5..09e3f70a 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
@@ -82,11 +82,6 @@ void AsValueInto(base::trace_event::TracedValue* state) const; - // Migrates |queue| from this time domain to |destination_time_domain|. - // Main-thread only. - void MigrateQueue(internal::TaskQueueImpl* queue, - TimeDomain* destination_time_domain); - // If there is a scheduled delayed task, |out_task_queue| is set to the queue // the next task was posted to and it returns true. Returns false otherwise. bool NextScheduledTaskQueue(TaskQueue** out_task_queue) const;
diff --git a/third_party/WebKit/Source/web/FullscreenController.cpp b/third_party/WebKit/Source/web/FullscreenController.cpp index bc592d2..7470776 100644 --- a/third_party/WebKit/Source/web/FullscreenController.cpp +++ b/third_party/WebKit/Source/web/FullscreenController.cpp
@@ -219,7 +219,7 @@ void FullscreenController::updateSize() { DCHECK(m_webViewImpl->page()); - if (m_state != State::Fullscreen) + if (m_state != State::Fullscreen && m_state != State::ExitingFullscreen) return; updatePageScaleConstraints(false);
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 5ee9604..3f3388e21 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -227,7 +227,7 @@ def _commit_message(self, chromium_commit, import_commit): return ('Import %s\n\n' - 'Using update-w3c-deps in Chromium %s.\n\n' + 'Using wpt-import in Chromium %s.\n\n' 'NOEXPORT=true' % (import_commit, chromium_commit))
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 index a590744..46add4a2 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
@@ -76,7 +76,7 @@ self.assertEqual( updater._commit_message('aaaa', '1111'), 'Import 1111\n\n' - 'Using update-w3c-deps in Chromium aaaa.\n\n' + 'Using wpt-import in Chromium aaaa.\n\n' 'NOEXPORT=true') def test_cl_description_with_empty_environ(self):
diff --git a/third_party/WebKit/Tools/Scripts/update-w3c-deps b/third_party/WebKit/Tools/Scripts/wpt-import similarity index 100% rename from third_party/WebKit/Tools/Scripts/update-w3c-deps rename to third_party/WebKit/Tools/Scripts/wpt-import
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index ee72742..726787f 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 0567536f86fb10f9663fb30d6ebf08a7c35b975d +Revision: 1e4be91918b614e74a3882132fa4442e758f0e4d License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/.gitignore b/third_party/crashpad/crashpad/.gitignore index c4f8fbb..65bb4418 100644 --- a/third_party/crashpad/crashpad/.gitignore +++ b/third_party/crashpad/crashpad/.gitignore
@@ -12,6 +12,7 @@ /out /third_party/gtest/gtest /third_party/gyp/gyp +/third_party/llvm /third_party/mini_chromium/mini_chromium /xcodebuild tags
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 8615c43..7742853 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -17,18 +17,28 @@ } deps = { + 'buildtools': + Var('chromium_git') + '/chromium/buildtools.git@' + + 'f8fc76ea5ce4a60cda2fa5d7df3d4a62935b3113', 'crashpad/third_party/gtest/gtest': Var('chromium_git') + '/external/github.com/google/googletest@' + 'ec44c6c1675c25b9827aacd08c02433cccde7780', 'crashpad/third_party/gyp/gyp': Var('chromium_git') + '/external/gyp@' + '93cc6e2c23e4d5ebd179f388e67aa907d0dfd43d', + + # TODO(scottmg): Consider pinning these. For now, we don't have any particular + # reason to do so. + 'crashpad/third_party/llvm': + Var('chromium_git') + '/external/llvm.org/llvm.git@HEAD', + 'crashpad/third_party/llvm/tools/clang': + Var('chromium_git') + '/external/llvm.org/clang.git@HEAD', + 'crashpad/third_party/llvm/tools/lldb': + Var('chromium_git') + '/external/llvm.org/lldb.git@HEAD', + 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + 'de1afb04f4afc074ec6d23bd9ee7b1e6b365427f', - 'buildtools': - Var('chromium_git') + '/chromium/buildtools.git@' + - 'f8fc76ea5ce4a60cda2fa5d7df3d4a62935b3113', } hooks = [ @@ -41,7 +51,6 @@ '--no_resume', '--no_auth', '--bucket=chromium-clang-format', - '--output=buildtools/mac/clang-format', '--sha1_file', 'buildtools/mac/clang-format.sha1', ], @@ -55,12 +64,37 @@ '--no_resume', '--no_auth', '--bucket=chromium-clang-format', - '--output=buildtools/win/clang-format.exe', '--sha1_file', 'buildtools/win/clang-format.exe.sha1', ], }, { + 'name': 'gn_mac', + 'pattern': '.', + 'action': [ + 'download_from_google_storage', + '--platform=^darwin$', + '--no_resume', + '--no_auth', + '--bucket=chromium-gn', + '--sha1_file', + 'buildtools/mac/gn.sha1', + ], + }, + { + 'name': 'gn_win', + 'pattern': '.', + 'action': [ + 'download_from_google_storage', + '--platform=^win32$', + '--no_resume', + '--no_auth', + '--bucket=chromium-gn', + '--sha1_file', + 'buildtools/win/gn.exe.sha1', + ], + }, + { 'name': 'gyp', 'pattern': '\.gypi?$', 'action': ['python', 'crashpad/build/gyp_crashpad.py'],
diff --git a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc index 2a11562..7784afe 100644 --- a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc +++ b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc
@@ -66,7 +66,7 @@ const mach_msg_trailer_t* trailer, bool* destroy_complex_request) { Metrics::ExceptionEncountered(); - Metrics::ExceptionCode(exception); + Metrics::ExceptionCode(ExceptionCodeForMetrics(exception, code[0])); *destroy_complex_request = true; // The expected behavior is EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc index c5d32b5..92c8450 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc
@@ -66,20 +66,7 @@ exception_ = ExcCrashRecoverOriginalException( exception_code_0, &exception_code_0, nullptr); - if (exception_ == EXC_CRASH || - exception_ == EXC_RESOURCE || - exception_ == EXC_GUARD) { - // EXC_CRASH should never be wrapped in another EXC_CRASH. - // - // EXC_RESOURCE and EXC_GUARD are software exceptions that are never - // wrapped in EXC_CRASH. The only time EXC_CRASH is generated is for - // processes exiting due to an unhandled core-generating signal or being - // killed by SIGKILL for code-signing reasons. Neither of these applies to - // EXC_RESOURCE or EXC_GUARD. See 10.10 xnu-2782.1.97/bsd/kern/kern_exit.c - // proc_prepareexit(). Receiving these exception types wrapped in - // EXC_CRASH would lose information because their code[0] uses all 64 bits - // (see below) and the code[0] recovered from EXC_CRASH only contains 20 - // significant bits. + if (!ExcCrashCouldContainException(exception_)) { LOG(WARNING) << base::StringPrintf( "exception %s invalid in EXC_CRASH", ExceptionToString(exception_, kUseFullName | kUnknownIsNumeric)
diff --git a/third_party/crashpad/crashpad/util/mach/exception_types.cc b/third_party/crashpad/crashpad/util/mach/exception_types.cc index 09366b57..d33fa937 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_types.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_types.cc
@@ -20,10 +20,13 @@ #include <errno.h> #include <libproc.h> #include <kern/exc_resource.h> +#include <strings.h> #include "base/logging.h" #include "base/mac/mach_logging.h" #include "util/mac/mac_util.h" +#include "util/mach/mach_extensions.h" +#include "util/numeric/in_range_cast.h" #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 @@ -128,6 +131,117 @@ return (code_0 >> 20) & 0xf; } +bool ExcCrashCouldContainException(exception_type_t exception) { + // EXC_CRASH should never be wrapped in another EXC_CRASH. + // + // EXC_RESOURCE and EXC_GUARD are software exceptions that are never wrapped + // in EXC_CRASH. The only time EXC_CRASH is generated is for processes exiting + // due to an unhandled core-generating signal or being killed by SIGKILL for + // code-signing reasons. Neither of these apply to EXC_RESOURCE or EXC_GUARD. + // See 10.10 xnu-2782.1.97/bsd/kern/kern_exit.c proc_prepareexit(). Receiving + // these exception types wrapped in EXC_CRASH would lose information because + // their code[0] uses all 64 bits (see ExceptionSnapshotMac::Initialize()) and + // the code[0] recovered from EXC_CRASH only contains 20 significant bits. + // + // EXC_CORPSE_NOTIFY may be generated from EXC_CRASH, but the opposite should + // never occur. + // + // kMachExceptionSimulated is a non-fatal Crashpad-specific pseudo-exception + // that never exists as an exception within the kernel and should thus never + // be wrapped in EXC_CRASH. + return exception != EXC_CRASH && + exception != EXC_RESOURCE && + exception != EXC_GUARD && + exception != EXC_CORPSE_NOTIFY && + exception != kMachExceptionSimulated; +} + +int32_t ExceptionCodeForMetrics(exception_type_t exception, + mach_exception_code_t code_0) { + if (exception == kMachExceptionSimulated) { + return exception; + } + + int signal = 0; + if (exception == EXC_CRASH) { + const exception_type_t original_exception = + ExcCrashRecoverOriginalException(code_0, &code_0, &signal); + if (!ExcCrashCouldContainException(original_exception)) { + LOG(WARNING) << "EXC_CRASH should not contain exception " + << original_exception; + return InRangeCast<uint16_t>(original_exception, 0xffff) << 16; + } + exception = original_exception; + } + + uint16_t metrics_exception = InRangeCast<uint16_t>(exception, 0xffff); + + uint16_t metrics_code_0; + switch (exception) { + case EXC_RESOURCE: + metrics_code_0 = (EXC_RESOURCE_DECODE_RESOURCE_TYPE(code_0) << 8) | + EXC_RESOURCE_DECODE_FLAVOR(code_0); + break; + + case EXC_GUARD: { + // This will be GUARD_TYPE_MACH_PORT (1) from <mach/port.h> or + // GUARD_TYPE_FD (2) from 10.12.2 xnu-3789.31.2/bsd/sys/guarded.h + const uint8_t guard_type = (code_0) >> 61; + + // These exceptions come through 10.12.2 + // xnu-3789.31.2/osfmk/ipc/mach_port.c mach_port_guard_exception() or + // xnu-3789.31.2/bsd/kern/kern_guarded.c fp_guard_exception(). In each + // case, bits 32-60 of code_0 encode the guard type-specific “flavor”. For + // Mach port guards, these flavor codes come from the + // mach_port_guard_exception_codes enum in <mach/port.h>. For file + // descriptor guards, they come from the guard_exception_codes enum in + // xnu-3789.31.2/bsd/sys/guarded.h. Both of these enums define shifted-bit + // values (1 << 0, 1 << 1, 1 << 2, etc.) In actual usage as determined by + // callers to these functions, these “flavor” codes are never ORed with + // one another. For the purposes of encoding these codes for metrics, + // convert the flavor codes to their corresponding bit shift values. + const uint32_t guard_flavor = (code_0 >> 32) & 0x1fffffff; + const int first_bit = ffs(guard_flavor); + uint8_t metrics_guard_flavor; + if (first_bit) { + metrics_guard_flavor = first_bit - 1; + + const uint32_t test_guard_flavor = 1 << metrics_guard_flavor; + if (guard_flavor != test_guard_flavor) { + // Another bit is set. + DCHECK_EQ(guard_flavor, test_guard_flavor); + metrics_guard_flavor = 0xff; + } + } else { + metrics_guard_flavor = 0xff; + } + + metrics_code_0 = (guard_type << 8) | metrics_guard_flavor; + break; + } + + case EXC_CORPSE_NOTIFY: + // code_0 may be a pointer. See 10.12.2 xnu-3789.31.2/osfmk/kern/task.c + // task_deliver_crash_notification(). Just encode 0 for metrics purposes. + metrics_code_0 = 0; + break; + + default: + metrics_code_0 = InRangeCast<uint16_t>(code_0, 0xffff); + if (exception == 0 && metrics_code_0 == 0 && signal != 0) { + // This exception came from a signal that did not originate as another + // Mach exception. Encode the signal number, using EXC_CRASH as the + // top-level exception type. This is safe because EXC_CRASH will not + // otherwise appear as metrics_exception. + metrics_exception = EXC_CRASH; + metrics_code_0 = signal; + } + break; + } + + return (metrics_exception << 16) | metrics_code_0; +} + bool IsExceptionNonfatalResource(exception_type_t exception, mach_exception_code_t code_0, pid_t pid) {
diff --git a/third_party/crashpad/crashpad/util/mach/exception_types.h b/third_party/crashpad/crashpad/util/mach/exception_types.h index 834f212..5082ed1 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_types.h +++ b/third_party/crashpad/crashpad/util/mach/exception_types.h
@@ -15,6 +15,7 @@ #ifndef CRASHPAD_UTIL_MACH_EXCEPTION_TYPES_H_ #define CRASHPAD_UTIL_MACH_EXCEPTION_TYPES_H_ +#include <inttypes.h> #include <mach/mach.h> #include <sys/types.h> @@ -54,6 +55,55 @@ mach_exception_code_t* original_code_0, int* signal); +//! \brief Determines whether a given exception type could plausibly be carried +//! within an `EXC_CRASH` exception. +//! +//! \param[in] exception The exception type to test. +//! +//! \return `true` if an `EXC_CRASH` exception could plausibly carry \a +//! exception. +//! +//! An `EXC_CRASH` exception can wrap exceptions that originate as hardware +//! faults, as well as exceptions that originate from certain software sources +//! such as POSIX signals. It cannot wrap another `EXC_CRASH` exception, nor can +//! it wrap `EXC_RESOURCE`, `EXC_GUARD`, or `EXC_CORPSE_NOTIFY` exceptions. It +//! also cannot wrap Crashpad-specific #kMachExceptionSimulated exceptions. +bool ExcCrashCouldContainException(exception_type_t exception); + +//! \brief Returns the exception code to report via a configured metrics system. +//! +//! \param[in] exception The exception type as received by a Mach exception +//! handler. +//! \param[in] code_0 The first exception code (`code[0]`) as received by a +//! Mach exception handler. +//! +//! \return An exception code that maps useful information from \a exception and +//! \a code_0 to the more limited data type available for metrics reporting. +//! +//! For classic Mach exceptions (including hardware faults reported as Mach +//! exceptions), the mapping is `(exception << 16) | code_0`. +//! +//! For `EXC_CRASH` exceptions that originate as Mach exceptions described +//! above, the mapping above is used, with the original exception’s values. For +//! `EXC_CRASH` exceptions that originate as POSIX signals without an underlying +//! Mach exception, the mapping is `(EXC_CRASH << 16) | code_0`. +//! +//! `EXC_RESOURCE` and `EXC_GUARD` exceptions both contain exception-specific +//! “type” values and type-specific “flavor” values. In these cases, the mapping +//! is `(exception << 16) | (type << 8) | flavor`. For `EXC_GUARD`, the “flavor” +//! value is rewritten to be more space-efficient by replacing the +//! kernel-supplied bitmask having exactly one bit set with the index of the set +//! bit. +//! +//! `EXC_CORPSE_NOTIFY` exceptions are reported as classic Mach exceptions with +//! the \a code_0 field set to `0`. +//! +//! If \a exception is #kMachExceptionSimulated, that value is returned as-is. +//! +//! Overflow conditions in any field are handled via saturation. +int32_t ExceptionCodeForMetrics(exception_type_t exception, + mach_exception_code_t code_0); + //! \brief Determines whether an exception is a non-fatal `EXC_RESOURCE`. //! //! \param[in] exception The exception type as received by a Mach exception
diff --git a/third_party/crashpad/crashpad/util/mach/exception_types_test.cc b/third_party/crashpad/crashpad/util/mach/exception_types_test.cc index d82dcbb9..7ecdd25 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_types_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_types_test.cc
@@ -41,9 +41,21 @@ {0xb100001, EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, SIGSEGV}, {0xb100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGSEGV}, {0xa100002, EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE, SIGBUS}, - {0x4200001, EXC_BAD_INSTRUCTION, 1, SIGILL}, - {0x8300001, EXC_ARITHMETIC, 1, SIGFPE}, - {0x5600002, EXC_BREAKPOINT, 2, SIGTRAP}, + {0xa100005, EXC_BAD_ACCESS, VM_PROT_READ | VM_PROT_EXECUTE, SIGBUS}, + {0xa10000d, EXC_BAD_ACCESS, EXC_I386_GPFLT, SIGBUS}, + {0x9100032, EXC_BAD_ACCESS, KERN_CODESIGN_ERROR, SIGKILL}, + {0x4200001, EXC_BAD_INSTRUCTION, EXC_I386_INVOP, SIGILL}, + {0x420000b, EXC_BAD_INSTRUCTION, EXC_I386_SEGNPFLT, SIGILL}, + {0x420000c, EXC_BAD_INSTRUCTION, EXC_I386_STKFLT, SIGILL}, + {0x8300001, EXC_ARITHMETIC, EXC_I386_DIV, SIGFPE}, + {0x8300002, EXC_ARITHMETIC, EXC_I386_INTO, SIGFPE}, + {0x8300005, EXC_ARITHMETIC, EXC_I386_EXTERR, SIGFPE}, + {0x8300008, EXC_ARITHMETIC, EXC_I386_SSEEXTERR, SIGFPE}, + {0x5500007, EXC_SOFTWARE, EXC_I386_BOUND, SIGTRAP}, + {0x5600001, EXC_BREAKPOINT, EXC_I386_SGL, SIGTRAP}, + {0x5600002, EXC_BREAKPOINT, EXC_I386_BPT, SIGTRAP}, + {0x0700080, EXC_SYSCALL, 128, 0}, + {0x0706000, EXC_SYSCALL, 0x6000, 0}, {0x3000000, 0, 0, SIGQUIT}, {0x6000000, 0, 0, SIGABRT}, {0xc000000, 0, 0, SIGSYS}, @@ -86,40 +98,173 @@ EXPECT_EQ(test_data.signal, signal); } -// These macros come from the #ifdef KERNEL section of <kern/exc_resource.h>: -// 10.10 xnu-2782.1.97/osfmk/kern/exc_resource.h. -#define EXC_RESOURCE_ENCODE_TYPE(code, type) \ - ((code) |= ((static_cast<uint64_t>(type) & 0x7ull) << 61)) -#define EXC_RESOURCE_ENCODE_FLAVOR(code, flavor) \ - ((code) |= ((static_cast<uint64_t>(flavor) & 0x7ull) << 58)) +TEST(ExceptionTypes, ExcCrashCouldContainException) { + // This seems wrong, but it happens when EXC_CRASH carries an exception not + // originally caused by a hardware fault, such as SIGABRT. + EXPECT_TRUE(ExcCrashCouldContainException(0)); + + EXPECT_TRUE(ExcCrashCouldContainException(EXC_BAD_ACCESS)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_BAD_INSTRUCTION)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_ARITHMETIC)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_EMULATION)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_SOFTWARE)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_BREAKPOINT)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_SYSCALL)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_MACH_SYSCALL)); + EXPECT_TRUE(ExcCrashCouldContainException(EXC_RPC_ALERT)); + EXPECT_FALSE(ExcCrashCouldContainException(EXC_CRASH)); + EXPECT_FALSE(ExcCrashCouldContainException(EXC_RESOURCE)); + EXPECT_FALSE(ExcCrashCouldContainException(EXC_GUARD)); + EXPECT_FALSE(ExcCrashCouldContainException(EXC_CORPSE_NOTIFY)); + EXPECT_FALSE(ExcCrashCouldContainException(kMachExceptionSimulated)); +} + +// This macro is adapted from those in the #ifdef KERNEL section of +// <kern/exc_resource.h>: 10.12.2 xnu-3789.31.2/osfmk/kern/exc_resource.h. +#define EXC_RESOURCE_ENCODE_TYPE_FLAVOR(type, flavor) \ + (static_cast<mach_exception_code_t>( \ + (((static_cast<uint64_t>(type) & 0x7ull) << 61) | \ + (static_cast<uint64_t>(flavor) & 0x7ull) << 58))) + +TEST(ExceptionTypes, ExceptionCodeForMetrics) { + struct TestData { + exception_type_t exception; + mach_exception_code_t code_0; + int32_t metrics_code; + }; + const TestData kTestData[] = { +#define ENCODE_EXC(type, code_0) \ + { (type), (code_0), ((type) << 16) | (code_0) } + ENCODE_EXC(EXC_BAD_ACCESS, KERN_INVALID_ADDRESS), + ENCODE_EXC(EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE), + ENCODE_EXC(EXC_BAD_ACCESS, VM_PROT_READ | VM_PROT_EXECUTE), + ENCODE_EXC(EXC_BAD_ACCESS, EXC_I386_GPFLT), + ENCODE_EXC(EXC_BAD_ACCESS, KERN_CODESIGN_ERROR), + ENCODE_EXC(EXC_BAD_INSTRUCTION, EXC_I386_INVOP), + ENCODE_EXC(EXC_BAD_INSTRUCTION, EXC_I386_SEGNPFLT), + ENCODE_EXC(EXC_BAD_INSTRUCTION, EXC_I386_STKFLT), + ENCODE_EXC(EXC_ARITHMETIC, EXC_I386_DIV), + ENCODE_EXC(EXC_ARITHMETIC, EXC_I386_INTO), + ENCODE_EXC(EXC_ARITHMETIC, EXC_I386_EXTERR), + ENCODE_EXC(EXC_ARITHMETIC, EXC_I386_SSEEXTERR), + ENCODE_EXC(EXC_SOFTWARE, EXC_I386_BOUND), + ENCODE_EXC(EXC_BREAKPOINT, EXC_I386_SGL), + ENCODE_EXC(EXC_BREAKPOINT, EXC_I386_BPT), + ENCODE_EXC(EXC_SYSCALL, 128), + ENCODE_EXC(EXC_SYSCALL, 0x6000), +#undef ENCODE_EXC + +#define ENCODE_EXC_CRASH(type, code_0) \ + { \ + EXC_CRASH, (((type) & 0xf) << 20) | ((code_0) & 0xfffff), \ + ((type) << 16) | (code_0) \ + } + ENCODE_EXC_CRASH(EXC_BAD_ACCESS, KERN_INVALID_ADDRESS), + ENCODE_EXC_CRASH(EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE), + ENCODE_EXC_CRASH(EXC_BAD_ACCESS, VM_PROT_READ | VM_PROT_EXECUTE), + ENCODE_EXC_CRASH(EXC_BAD_ACCESS, EXC_I386_GPFLT), + ENCODE_EXC_CRASH(EXC_BAD_ACCESS, KERN_CODESIGN_ERROR), + ENCODE_EXC_CRASH(EXC_BAD_INSTRUCTION, EXC_I386_INVOP), + ENCODE_EXC_CRASH(EXC_BAD_INSTRUCTION, EXC_I386_SEGNPFLT), + ENCODE_EXC_CRASH(EXC_BAD_INSTRUCTION, EXC_I386_STKFLT), + ENCODE_EXC_CRASH(EXC_ARITHMETIC, EXC_I386_DIV), + ENCODE_EXC_CRASH(EXC_ARITHMETIC, EXC_I386_INTO), + ENCODE_EXC_CRASH(EXC_ARITHMETIC, EXC_I386_EXTERR), + ENCODE_EXC_CRASH(EXC_ARITHMETIC, EXC_I386_SSEEXTERR), + ENCODE_EXC_CRASH(EXC_SOFTWARE, EXC_I386_BOUND), + ENCODE_EXC_CRASH(EXC_BREAKPOINT, EXC_I386_SGL), + ENCODE_EXC_CRASH(EXC_BREAKPOINT, EXC_I386_BPT), + ENCODE_EXC_CRASH(EXC_SYSCALL, 128), + ENCODE_EXC_CRASH(EXC_SYSCALL, 0x6000), +#undef ENCODE_EXC_CRASH + +#define ENCODE_EXC_CRASH_SIGNAL(signal) \ + { EXC_CRASH, (((signal) & 0xff) << 24), (EXC_CRASH << 16) | (signal) } + ENCODE_EXC_CRASH_SIGNAL(SIGQUIT), + ENCODE_EXC_CRASH_SIGNAL(SIGABRT), + ENCODE_EXC_CRASH_SIGNAL(SIGSYS), +#undef ENCODE_EXC_CRASH_SIGNAL + +#define ENCODE_EXC_RESOURCE(type, flavor) \ + { \ + EXC_RESOURCE, EXC_RESOURCE_ENCODE_TYPE_FLAVOR((type), (flavor)), \ + (EXC_RESOURCE << 16) | ((type) << 8) | (flavor) \ + } + ENCODE_EXC_RESOURCE(RESOURCE_TYPE_CPU, FLAVOR_CPU_MONITOR), + ENCODE_EXC_RESOURCE(RESOURCE_TYPE_CPU, FLAVOR_CPU_MONITOR_FATAL), + ENCODE_EXC_RESOURCE(RESOURCE_TYPE_WAKEUPS, FLAVOR_WAKEUPS_MONITOR), + ENCODE_EXC_RESOURCE(RESOURCE_TYPE_MEMORY, FLAVOR_HIGH_WATERMARK), + ENCODE_EXC_RESOURCE(RESOURCE_TYPE_IO, FLAVOR_IO_PHYSICAL_WRITES), + ENCODE_EXC_RESOURCE(RESOURCE_TYPE_IO, FLAVOR_IO_LOGICAL_WRITES), +#undef ENCODE_EXC_RESOURCE + +#define ENCODE_EXC_GUARD(type, flavor) \ + { \ + EXC_GUARD, \ + static_cast<mach_exception_code_t>(static_cast<uint64_t>((type) & 0x7) \ + << 61) | \ + (static_cast<uint64_t>((1 << (flavor)) & 0x1ffffffff) << 32), \ + (EXC_GUARD << 16) | ((type) << 8) | (flavor) \ + } + ENCODE_EXC_GUARD(GUARD_TYPE_MACH_PORT, 0), // kGUARD_EXC_DESTROY + ENCODE_EXC_GUARD(GUARD_TYPE_MACH_PORT, 1), // kGUARD_EXC_MOD_REFS + ENCODE_EXC_GUARD(GUARD_TYPE_MACH_PORT, 2), // kGUARD_EXC_SET_CONTEXT + ENCODE_EXC_GUARD(GUARD_TYPE_MACH_PORT, 3), // kGUARD_EXC_UNGUARDED + ENCODE_EXC_GUARD(GUARD_TYPE_MACH_PORT, 4), // kGUARD_EXC_INCORRECT_GUARD + + // 2 is GUARD_TYPE_FD from 10.12.2 xnu-3789.31.2/bsd/sys/guarded.h. + ENCODE_EXC_GUARD(2, 0), // kGUARD_EXC_CLOSE + ENCODE_EXC_GUARD(2, 1), // kGUARD_EXC_DUP + ENCODE_EXC_GUARD(2, 2), // kGUARD_EXC_NOCLOEXEC + ENCODE_EXC_GUARD(2, 3), // kGUARD_EXC_SOCKET_IPC + ENCODE_EXC_GUARD(2, 4), // kGUARD_EXC_FILEPORT + ENCODE_EXC_GUARD(2, 5), // kGUARD_EXC_MISMATCH + ENCODE_EXC_GUARD(2, 6), // kGUARD_EXC_WRITE +#undef ENCODE_EXC_GUARD + + // Test that overflow saturates. + {0x00010000, 0x00001000, static_cast<int32_t>(0xffff1000)}, + {0x00001000, 0x00010000, 0x1000ffff}, + {0x00010000, 0x00010000, static_cast<int32_t>(0xffffffff)}, + }; + + for (size_t index = 0; index < arraysize(kTestData); ++index) { + const TestData& test_data = kTestData[index]; + SCOPED_TRACE(base::StringPrintf("index %zu, exception 0x%x, code_0 0x%llx", + index, + test_data.exception, + test_data.code_0)); + + int32_t metrics_code = + ExceptionCodeForMetrics(test_data.exception, test_data.code_0); + + EXPECT_EQ(test_data.metrics_code, metrics_code); + } +} TEST(ExceptionTypes, IsExceptionNonfatalResource) { const pid_t pid = getpid(); - mach_exception_code_t code = 0; - EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_CPU); - EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_CPU_MONITOR); + mach_exception_code_t code = + EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_CPU, FLAVOR_CPU_MONITOR); EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); if (MacOSXMinorVersion() >= 10) { // FLAVOR_CPU_MONITOR_FATAL was introduced in OS X 10.10. - code = 0; - EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_CPU); - EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_CPU_MONITOR_FATAL); + code = EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_CPU, + FLAVOR_CPU_MONITOR_FATAL); EXPECT_FALSE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); } // This assumes that WAKEMON_MAKE_FATAL is not set for this process. The // default is for WAKEMON_MAKE_FATAL to not be set, there’s no public API to // enable it, and nothing in this process should have enabled it. - code = 0; - EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_WAKEUPS); - EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_WAKEUPS_MONITOR); + code = EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_WAKEUPS, + FLAVOR_WAKEUPS_MONITOR); EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); - code = 0; - EXC_RESOURCE_ENCODE_TYPE(code, RESOURCE_TYPE_MEMORY); - EXC_RESOURCE_ENCODE_FLAVOR(code, FLAVOR_HIGH_WATERMARK); + code = EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_MEMORY, + FLAVOR_HIGH_WATERMARK); EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); // Non-EXC_RESOURCE exceptions should never be considered nonfatal resource
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium index e7ad373..52a0463 100644 --- a/third_party/libxml/README.chromium +++ b/third_party/libxml/README.chromium
@@ -18,6 +18,7 @@ - Apply patch contributed here: https://crbug.com/624011 - Apply patch contributed here: https://crbug.com/628581#c18 - Apply patch contributed here: https://crbug.com/620679#c34 +- Apply patch contributed here: https://crbug.com/683629#c9 This import was generated by this script: https://goo.gl/72CTWf
diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c index 33786f08..745c3da 100644 --- a/third_party/libxml/src/parser.c +++ b/third_party/libxml/src/parser.c
@@ -3426,7 +3426,7 @@ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); return(NULL); } - if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) { + if (ctxt->input->cur > ctxt->input->base && (*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) { if (ctxt->input->base > ctxt->input->cur - (len + 1)) { return(NULL); }
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp index eced8e2d..452861036 100644 --- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp +++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -1533,6 +1533,7 @@ // there's nothing interesting to rewrite in those either. unless(hasAncestor(functionDecl(isDefaulted()))))); auto decl_ref_matcher = id("expr", declRefExpr(to(var_decl_matcher))); + auto type_trait_ref_matcher = id("expr", declRefExpr(to(type_trait_matcher))); auto enum_member_ref_matcher = id("expr", declRefExpr(to(enum_member_decl_matcher))); @@ -1542,6 +1543,10 @@ DeclRefRewriter decl_ref_rewriter(&replacements); match_finder.addMatcher(decl_ref_matcher, &decl_ref_rewriter); + DeclRefRewriter type_trait_ref_rewriter(&replacements); + type_trait_ref_rewriter.set_for_type_traits(true); + match_finder.addMatcher(type_trait_ref_matcher, &type_trait_ref_rewriter); + EnumConstantDeclRefRewriter enum_member_ref_rewriter(&replacements); match_finder.addMatcher(enum_member_ref_matcher, &enum_member_ref_rewriter);
diff --git a/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc index 89bc554..0b54069 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc
@@ -86,6 +86,11 @@ namespace WTF { +void TestForTraits() { + bool a = blink::IsGarbageCollectedMixin::safe_to_compare_to_empty_or_deleted; + bool b = not_blink::GloballyKnownTraits::safe_to_compare_to_empty_or_deleted; +} + // We don't want to capitalize fields in type traits // (i.e. the |value| -> |kValue| rename is undesirable below). struct TypeTrait1 {
diff --git a/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc b/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc index 5f0fda0..bceaa95 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc
@@ -83,6 +83,11 @@ namespace WTF { +void testForTraits() { + bool a = blink::IsGarbageCollectedMixin::safeToCompareToEmptyOrDeleted; + bool b = not_blink::GloballyKnownTraits::safeToCompareToEmptyOrDeleted; +} + // We don't want to capitalize fields in type traits // (i.e. the |value| -> |kValue| rename is undesirable below). struct TypeTrait1 {
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md index d27db44..7e85b10 100644 --- a/tools/gn/docs/reference.md +++ b/tools/gn/docs/reference.md
@@ -325,16 +325,20 @@ ``` ### **Usage** + ``` gn args <out_dir> - Open the arguments for the given build directory in an editor (as - specified by the EDITOR environment variable). If the given build - directory doesn't exist, it will be created and an empty args file will - be opened in the editor. You would type something like this into that - file: + Open the arguments for the given build directory in an editor. If the + given build directory doesn't exist, it will be created and an empty args + file will be opened in the editor. You would type something like this + into that file: enable_doom_melon=false os="android" + To find your editor on Posix, GN will search the environment variables in + order: GN_EDITOR, VISUAL, and EDITOR. On Windows GN will open the command + associated with .txt files. + Note: you can edit the build args manually by editing the file "args.gn" in the build directory and then running "gn gen <out_dir>". @@ -343,20 +347,12 @@ an exact_arg is specified for the list flag, just that one build argument. - The output will list the declaration location, default value, and comment - preceeding the declaration. If --short is specified, only the names and - values will be printed. + The output will list the declaration location, current value for the + build, default value (if different than the current value), and comment + preceeding the declaration. - If the out_dir is specified, the build configuration will be taken from - that build directory. The reason this is needed is that the definition of - some arguments is dependent on the build configuration, so setting some - values might add, remove, or change the default values for other - arguments. Specifying your exact configuration allows the proper - arguments to be displayed. - - Instead of specifying the out_dir, you can also use the command-line flag - to specify the build configuration: - --args=<exact list of args to use> + If --short is specified, only the names and current values will be + printed. ``` @@ -5730,6 +5726,9 @@ - target_cpu - target_os + Next, project-specific overrides are applied. These are specified inside + the default_args variable of //.gn. See "gn help dotfile" for more. + If specified, arguments from the --args command line flag are used. If that flag is not specified, args from previous builds in the build directory will be used (this is in the file args.gn in the build directory). @@ -5845,6 +5844,15 @@ The secondary source root must be inside the main source tree. + default_args [optional] + Scope containing the default overrides for declared arguments. These + overrides take precedence over the default values specified in the + declare_args() block, but can be overriden using --args or the + args.gn file. + + This is intended to be used when subprojects declare arguments with + default values that need to be changed for whatever reason. + ``` ### **Example .gn file contents** @@ -5861,6 +5869,12 @@ secondary_source = "//build/config/temporary_buildfiles/" + default_args = { + # Default to release builds for this project. + is_debug = false + is_component_build = false + } + ``` ## **Build graph and execution overview**
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 6767f94a..c976db80 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -55,6 +55,7 @@ }, 'chromium.android.fyi': { + 'Memory Infra Tester': 'android_release_thumb_bot', 'NDK Next MIPS Builder': 'android_ndk_next_release_bot_minimal_symbols_mipsel', 'NDK Next arm Builder': @@ -809,6 +810,10 @@ 'android', 'release_bot', 'minimal_symbols', 'arm64', ], + 'android_release_thumb_bot': [ + 'android', 'release_bot', 'arm_thumb', + ], + 'android_release_trybot': [ 'android', 'release_trybot', ], @@ -1527,6 +1532,10 @@ 'gn_args': 'arm_use_neon=false', }, + 'arm_thumb': { + 'gn_args': 'arm_use_thumb=true', + }, + 'asan': { 'gn_args': 'is_asan=true', },
diff --git a/tools/metrics/histograms/extract_histograms.py b/tools/metrics/histograms/extract_histograms.py index c8da0ccb..7ed28318 100644 --- a/tools/metrics/histograms/extract_histograms.py +++ b/tools/metrics/histograms/extract_histograms.py
@@ -142,6 +142,12 @@ ordering = histogram_suffixes_node.getAttribute('ordering') else: ordering = 'suffix' + parts = ordering.split(',') + ordering = parts[0] + if len(parts) > 1: + placement = int(parts[1]) + else: + placement = 1 if ordering not in ['prefix', 'suffix']: logging.error('ordering needs to be prefix or suffix, value is %s', ordering) @@ -156,15 +162,16 @@ # For prefixes, the suffix_name is inserted between the "cluster" and the # "remainder", e.g. Foo.BarHist expanded with gamma becomes Foo.gamma_BarHist. sections = histogram_name.split('.') - if len(sections) <= 1: + if len(sections) <= placement: logging.error( - 'Prefix Field Trial expansions require histogram names which include a ' - 'dot separator. Histogram name is %s, and Field Trial is %s', - histogram_name, histogram_suffixes_node.getAttribute('name')) + 'Prefix histogram_suffixes expansions require histogram names which ' + 'include a dot separator. Histogram name is %s, histogram_suffixes is ' + '%s, and placment is %d', + histogram_name, histogram_suffixes_node.getAttribute('name'), placement) raise Error() - cluster = sections[0] + '.' - remainder = '.'.join(sections[1:]) + cluster = '.'.join(sections[0:placement]) + '.' + remainder = '.'.join(sections[placement:]) return cluster + suffix_name + separator + remainder
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8888d50..e61b959 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -64,7 +64,9 @@ When 'ordering="prefix"' is present in the histogram_suffixes tag, the suffix will be inserted after the first dot separator of the affected-histogram name. -Therefore, the affected-histogram name has to have at least one dot in it. +Optionally, ordering can be specified as "prefix,N" where N indicates after +how many dots the suffix should be inserted (default=1). The affected-histogram +name has to have at least N dots in it. Googlers: There are also a small number of private internal histograms found at http://cs/file:chrome/histograms.xml - but prefer this file for new entries. @@ -2131,6 +2133,33 @@ </summary> </histogram> +<histogram name="Ash.WindowSelector.AnimationSmoothness.Close" units="%"> + <owner>varkha@chromium.org</owner> + <owner>tdanderson@chromium.org</owner> + <summary> + Relative smoothness of animations when closing a window in overview mode. + 100% represents ideally smooth 60 frames per second. + </summary> +</histogram> + +<histogram name="Ash.WindowSelector.AnimationSmoothness.Enter" units="%"> + <owner>varkha@chromium.org</owner> + <owner>tdanderson@chromium.org</owner> + <summary> + Relative smoothness of animations when entering overview mode. 100% + represents ideally smooth 60 frames per second. + </summary> +</histogram> + +<histogram name="Ash.WindowSelector.AnimationSmoothness.Exit" units="%"> + <owner>varkha@chromium.org</owner> + <owner>tdanderson@chromium.org</owner> + <summary> + Relative smoothness of animations when exiting overview mode. 100% + represents ideally smooth 60 frames per second. + </summary> +</histogram> + <histogram name="Ash.WindowSelector.ArrowKeyPresses"> <owner>flackr@chromium.org</owner> <owner>tdanderson@chromium.org</owner> @@ -26322,7 +26351,7 @@ <histogram name="Media.Video.TimeFromForegroundToFirstFrame" units="ms"> <obsolete> Deprecated as of 01/18/2017 in issue 670150. Replaced by - Media.Video.TimeFromForegroundToFirstFrame.DisabledTrack and + Media.Video.TimeFromForegroundToFirstFrame.DisableTrack and Media.Video.TimeFromForegroundToFirstFrame.Paused. </obsolete> <owner>avayvod@chromium.org</owner> @@ -26333,7 +26362,7 @@ </summary> </histogram> -<histogram name="Media.Video.TimeFromForegroundToFirstFrame.DisabledTrack" +<histogram name="Media.Video.TimeFromForegroundToFirstFrame.DisableTrack" units="ms"> <owner>avayvod@chromium.org</owner> <owner>dalecurtis@chromium.org</owner> @@ -44953,11 +44982,12 @@ </summary> </histogram> -<histogram name="PasswordManager.HttpPasswordMigrationCount"> +<histogram name="PasswordManager.HttpPasswordMigrationCount" + units="saved credentials"> <owner>vasilii@chromium.org</owner> <summary> Number of HTTP saved passwords that were migrated to HTTPS. Recorded on - password form load. + HTTPS password form load when there are no credentials saved. </summary> </histogram> @@ -45484,6 +45514,52 @@ </summary> </histogram> +<histogram + name="PaymentRequest.CanMakePayment.NotUsed.WithShowEffectOnCompletion" + enum="PaymentRequestFlowCompletionStatus"> + <owner>sebsg@chromium.org</owner> + <summary> + Whether the flow was completed when CanMakePayment was not called by the + merchant. + </summary> +</histogram> + +<histogram name="PaymentRequest.CanMakePayment.Usage" enum="Boolean"> + <owner>sebsg@chromium.org</owner> + <summary> + Whether the merchant used the CanMakePayment method during a Payment + Request. + </summary> +</histogram> + +<histogram name="PaymentRequest.CanMakePayment.Used.EffectOnShow" + enum="PaymentRequestCanMakePaymentEffectOnShow"> + <owner>sebsg@chromium.org</owner> + <summary> + The effect of the CanMakePayment return value on whether Show was called. + </summary> +</histogram> + +<histogram + name="PaymentRequest.CanMakePayment.Used.FalseWithShowEffectOnCompletion" + enum="PaymentRequestFlowCompletionStatus"> + <owner>sebsg@chromium.org</owner> + <summary> + Whether the flow was completed when CanMakePayment was called by the + merchant and returned false. + </summary> +</histogram> + +<histogram + name="PaymentRequest.CanMakePayment.Used.TrueWithShowEffectOnCompletion" + enum="PaymentRequestFlowCompletionStatus"> + <owner>sebsg@chromium.org</owner> + <summary> + Whether the flow was completed when CanMakePayment was called by the + merchant and returned true. + </summary> +</histogram> + <histogram name="PaymentRequest.CheckoutFunnel.Aborted" enum="PaymentRequestAbortReason"> <owner>sebsg@chromium.org</owner> @@ -61491,6 +61567,14 @@ </summary> </histogram> +<histogram name="Settings.MachineIdGenerationSuccess" enum="BooleanSuccess"> + <owner>proberge@chromium.org</owner> + <summary> + Whether generation of the deterministic machine-specific device id was + successful when initializing the PrefHashStore. + </summary> +</histogram> + <histogram name="Settings.MigratedHashesFromLocalState" enum="BooleanMigrated"> <obsolete> Deprecated in Chrome 54, as we stopped legacy migration of preferences. @@ -70827,185 +70911,26 @@ </summary> </histogram> -<histogram name="UMA.PersistentAllocator.BrowserMetrics.Allocs" units="bytes"> +<histogram base="true" name="UMA.PersistentAllocator.Allocs" units="bytes"> <owner>bcwhite@chromium.org</owner> <owner>asvitkine@chromium.org</owner> <summary> - Size, before padding, of objects allocated from persistent memory in the - browser process. This is updated with every allocation. + Size, before padding, of objects allocated from persistent memory. This is + updated with every allocation. </summary> </histogram> -<histogram name="UMA.PersistentAllocator.BrowserMetrics.UsedPct" units="%"> +<histogram base="true" name="UMA.PersistentAllocator.Errors" + enum="PersistentAllocatorErrors"> <owner>bcwhite@chromium.org</owner> <owner>asvitkine@chromium.org</owner> <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. + Errors detected by the persistent memory allocator. These are set when they + occur. </summary> </histogram> -<histogram name="UMA.PersistentAllocator.FieldTrialAllocator.Allocs" - units="bytes"> - <owner>lawrencewu@chromium.org</owner> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size of objects allocated from persistent memory in the browser process for - field trials. Updated on each subprocess launch. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.FieldTrialAllocator.UsedPct" units="%"> - <owner>lawrencewu@chromium.org</owner> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated on each subprocess launch. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.GpuMetrics.Allocs" units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a GPU - process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.GpuMetrics.UsedPct" units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.PpapiBrokerMetrics.Allocs" - units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a - "PPAPI broker" process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.PpapiBrokerMetrics.UsedPct" units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.PpapiPluginMetrics.Allocs" - units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a - "PPAPI plugin" process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.PpapiPluginMetrics.UsedPct" units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.RendererMetrics.Allocs" units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a - renderer process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.RendererMetrics.UsedPct" units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.SandboxHelperMetrics.Allocs" - units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a - "sandbox helper" process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.SandboxHelperMetrics.UsedPct" - units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.SetupMetrics.Allocs" units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a setup - process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.SetupMetrics.UsedPct" units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.UtilityMetrics.Allocs" units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a - "utility" process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.UtilityMetrics.UsedPct" units="%"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Percentage of persistent memory segment that has been allocated. This is - updated only once per reporting cycle. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.ZygoteMetrics.Allocs" units="bytes"> - <owner>bcwhite@chromium.org</owner> - <owner>asvitkine@chromium.org</owner> - <summary> - Size, before padding, of objects allocated from persistent memory in a - "zygote" process. This is updated with every allocation. - </summary> -</histogram> - -<histogram name="UMA.PersistentAllocator.ZygoteMetrics.UsedPct" units="%"> +<histogram base="true" name="UMA.PersistentAllocator.UsedPct" units="%"> <owner>bcwhite@chromium.org</owner> <owner>asvitkine@chromium.org</owner> <summary> @@ -81834,6 +81759,8 @@ <int value="12" label="QUIC/34"/> <int value="13" label="QUIC/35"/> <int value="14" label="QUIC/36"/> + <int value="15" label="QUIC/37"/> + <int value="16" label="QUIC/38"/> </enum> <enum name="ConnectionResult" type="int"> @@ -82641,6 +82568,57 @@ <int value="11" label="EXC_RESOURCE"/> <int value="12" label="EXC_GUARD"/> <int value="13" label="EXC_CORPSE_NOTIFY"/> + <int value="65537" label="EXC_BAD_ACCESS/KERN_INVALID_ADDRESS"/> + <int value="65538" label="EXC_BAD_ACCESS/KERN_PROTECTION_FAILURE"/> + <int value="65541" label="EXC_BAD_ACCESS/(VM_PROT_READ|VM_PROT_EXECUTE)"/> + <int value="65549" label="EXC_BAD_ACCESS/EXC_I386_GPFLT"/> + <int value="65586" label="EXC_BAD_ACCESS/KERN_CODESIGN_ERROR"/> + <int value="131073" label="EXC_BAD_INSTRUCTION/EXC_I386_INVOP"/> + <int value="131083" label="EXC_BAD_INSTRUCTION/EXC_I386_SEGNPFLT"/> + <int value="131084" label="EXC_BAD_INSTRUCTION/EXC_I386_STKFLT"/> + <int value="196609" label="EXC_ARITHMETIC/EXC_I386_DIV"/> + <int value="196610" label="EXC_ARITHMETIC/EXC_I386_INTO"/> + <int value="196613" label="EXC_ARITHMETIC/EXC_I386_EXTERR"/> + <int value="196616" label="EXC_ARITHMETIC/EXC_I386_SSEEXTERR"/> + <int value="327687" label="EXC_SOFTWARE/EXC_I386_BOUND"/> + <int value="393217" label="EXC_BREAKPOINT/EXC_I386_SGL"/> + <int value="393218" label="EXC_BREAKPOINT/EXC_I386_BPT"/> + <int value="458752" label="EXC_SYSCALL/0"/> + <int value="458880" label="EXC_SYSCALL/128"/> + <int value="483328" label="EXC_SYSCALL/0x6000"/> + <int value="655363" label="EXC_CRASH/SIGQUIT"/> + <int value="655366" label="EXC_CRASH/SIGABRT"/> + <int value="655372" label="EXC_CRASH/SIGSYS"/> + <int value="721153" + label="EXC_RESOURCE/RESOURCE_TYPE_CPU/FLAVOR_CPU_MONITOR"/> + <int value="721154" + label="EXC_RESOURCE/RESOURCE_TYPE_CPU/FLAVOR_CPU_MONITOR_FATAL"/> + <int value="721409" + label="EXC_RESOURCE/RESOURCE_TYPE_WAKEUPS/FLAVOR_WAKEUPS_MONITOR"/> + <int value="721665" + label="EXC_RESOURCE/RESOURCE_TYPE_MEMORY/FLAVOR_HIGH_WATERMARK"/> + <int value="721921" + label="EXC_RESOURCE/RESOURCE_TYPE_IO/FLAVOR_IO_PHYSICAL_WRITES"/> + <int value="721922" + label="EXC_RESOURCE/RESOURCE_TYPE_IO/FLAVOR_IO_LOGICAL_WRITES"/> + <int value="786688" + label="EXC_GUARD/GUARD_TYPE_MACH_PORT/kGUARD_EXC_DESTROY"/> + <int value="786689" + label="EXC_GUARD/GUARD_TYPE_MACH_PORT/kGUARD_EXC_MOD_REFS"/> + <int value="786690" + label="EXC_GUARD/GUARD_TYPE_MACH_PORT/kGUARD_EXC_SET_CONTEXT"/> + <int value="786691" + label="EXC_GUARD/GUARD_TYPE_MACH_PORT/kGUARD_EXC_UNGUARDED"/> + <int value="786692" + label="EXC_GUARD/GUARD_TYPE_MACH_PORT/kGUARD_EXC_INCORRECT_GUARD"/> + <int value="786944" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_CLOSE"/> + <int value="786945" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_DUP"/> + <int value="786946" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_NOCLOEXEC"/> + <int value="786947" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_SOCKET_IPC"/> + <int value="786948" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_FILEPORT"/> + <int value="786949" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_MISMATCH"/> + <int value="786950" label="EXC_GUARD/GUARD_TYPE_FD/kGUARD_EXC_WRITE"/> + <int value="851968" label="EXC_CORPSE_NOTIFY/0"/> <int value="1129345912" label="kMachExceptionSimulated"/> </enum> @@ -89659,9 +89637,6 @@ <int value="1345" label="ProgressElementWithNoneAppearance"/> <int value="1346" label="ProgressElementWithProgressBarAppearance"/> <int value="1347" label="PointerEventAddListenerCount"/> - <int value="1348" label="EventCancelBubbleAffected"/> - <int value="1349" label="EventCancelBubbleWasChangedToTrue"/> - <int value="1350" label="EventCancelBubbleWasChangedToFalse"/> <int value="1351" label="CSSValueAppearanceNone"/> <int value="1352" label="CSSValueAppearanceNotNone"/> <int value="1353" label="CSSValueAppearanceOthers"/> @@ -100977,6 +100952,20 @@ <int value="8" label="Other"/> </enum> +<enum name="PaymentRequestCanMakePaymentEffectOnShow" type="int"> + <int value="0" + label="CanMakePayment() returned false and show() was not called"/> + <int value="1" label="CanMakePayment() returned false and show() was called"/> + <int value="2" + label="CanMakePayment() returned true and show() was not called"/> + <int value="3" label="CanMakePayment() returned true and show() was called"/> +</enum> + +<enum name="PaymentRequestFlowCompletionStatus" type="int"> + <int value="0" label="Completed"/> + <int value="1" label="Aborted"/> +</enum> + <enum name="PaymentRequestPaymentMethods" type="int"> <int value="0" label="Autofill credit cards"/> <int value="1" label="Android Pay"/> @@ -101279,6 +101268,10 @@ <int value="9" label="DEPRECATED_XML_PROTO_MISMATCH"/> </enum> +<enum name="PersistentAllocatorErrors" type="int"> + <int value="1" label="Allocator memory is corrupt (set only once)"/> +</enum> + <enum name="PersistentHistogramsInitResult" type="int"> <int value="0" label="Local-Memory Success"/> <int value="1" label="Local-Memory Failure"/> @@ -116309,6 +116302,63 @@ <affected-histogram name="Permissions.Requested.CrossOrigin"/> </histogram_suffixes> +<histogram_suffixes name="PersistentMemoryAllocs" separator="." + ordering="prefix,2"> + <suffix name="BrowserMetrics" label="For browser process metrics."/> + <suffix name="FieldTrialAllocator" label="For field-trial allocator."/> + <suffix name="GpuMetrics" label="For GPU process metrics."/> + <suffix name="PpapiBrokerMetrics" + label="For "PPAPI broker" process metrics."/> + <suffix name="PpapiPluginMetrics" + label="For "PPAPI plugin" process metrics."/> + <suffix name="RendererMetrics" label="For renderer process metrics."/> + <suffix name="SandboxHelperMetrics" + label="For "sandbox helper" process metrics."/> + <suffix name="SetupMetrics" label="For setup metrics."/> + <suffix name="UtilityMetrics" + label="For "utility" process metrics."/> + <suffix name="ZygoteMetrics" label="For "zygote" process metrics."/> + <affected-histogram name="UMA.PersistentAllocator.Allocs"/> +</histogram_suffixes> + +<histogram_suffixes name="PersistentMemoryErrors" separator="." + ordering="prefix,2"> + <suffix name="BrowserMetrics" label="For browser process metrics."/> + <suffix name="FieldTrialAllocator" label="For field-trial allocator."/> + <suffix name="GpuMetrics" label="For GPU process metrics."/> + <suffix name="PpapiBrokerMetrics" + label="For "PPAPI broker" process metrics."/> + <suffix name="PpapiPluginMetrics" + label="For "PPAPI plugin" process metrics."/> + <suffix name="RendererMetrics" label="For renderer process metrics."/> + <suffix name="SandboxHelperMetrics" + label="For "sandbox helper" process metrics."/> + <suffix name="SetupMetrics" label="For setup metrics."/> + <suffix name="UtilityMetrics" + label="For "utility" process metrics."/> + <suffix name="ZygoteMetrics" label="For "zygote" process metrics."/> + <affected-histogram name="UMA.PersistentAllocator.Errors"/> +</histogram_suffixes> + +<histogram_suffixes name="PersistentMemoryUsedPct" separator="." + ordering="prefix,2"> + <suffix name="BrowserMetrics" label="For browser process metrics."/> + <suffix name="FieldTrialAllocator" label="For field-trial allocator."/> + <suffix name="GpuMetrics" label="For GPU process metrics."/> + <suffix name="PpapiBrokerMetrics" + label="For "PPAPI broker" process metrics."/> + <suffix name="PpapiPluginMetrics" + label="For "PPAPI plugin" process metrics."/> + <suffix name="RendererMetrics" label="For renderer process metrics."/> + <suffix name="SandboxHelperMetrics" + label="For "sandbox helper" process metrics."/> + <suffix name="SetupMetrics" label="For setup metrics."/> + <suffix name="UtilityMetrics" + label="For "utility" process metrics."/> + <suffix name="ZygoteMetrics" label="For "zygote" process metrics."/> + <affected-histogram name="UMA.PersistentAllocator.UsedPct"/> +</histogram_suffixes> + <histogram_suffixes name="PhysicalWebDebugActions" separator="."> <suffix name="ChromeStart" label="when Chrome first starts up"/> <suffix name="LaunchFromDiagnostics"
diff --git a/tools/win/ShowGlobals/.gitignore b/tools/win/ShowGlobals/.gitignore new file mode 100644 index 0000000..499cde1 --- /dev/null +++ b/tools/win/ShowGlobals/.gitignore
@@ -0,0 +1,4 @@ +Release/ +Debug/ +ipch/ +x64/ \ No newline at end of file
diff --git a/ui/app_list/search_box_model.cc b/ui/app_list/search_box_model.cc index 4691883..a0c210e 100644 --- a/ui/app_list/search_box_model.cc +++ b/ui/app_list/search_box_model.cc
@@ -6,7 +6,7 @@ #include <utility> -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "ui/app_list/search_box_model_observer.h" namespace app_list {
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index 22cbb98..6f380138 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc
@@ -8,7 +8,7 @@ #include "base/command_line.h" #include "base/macros.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/profiler/scoped_tracker.h" #include "base/strings/string_util.h" #include "build/build_config.h"
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 236560d..1250b4d 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -80,6 +80,7 @@ context_factory_private_(context_factory_private), root_layer_(NULL), widget_(gfx::kNullAcceleratedWidget), + committed_frame_number_(0), widget_valid_(false), compositor_frame_sink_requested_(false), frame_sink_id_(frame_sink_id), @@ -106,7 +107,7 @@ settings.layers_always_allowed_lcd_text = true; // Use occlusion to allow more overlapping windows to take less memory. settings.use_occlusion_for_tile_prioritization = true; - settings.renderer_settings.refresh_rate = + refresh_rate_ = settings.renderer_settings.refresh_rate = context_factory_->DoesCreateTestContexts() ? kTestRefreshRate : kDefaultRefreshRate; settings.main_frame_before_activation_enabled = false; @@ -389,6 +390,9 @@ void Compositor::SetAuthoritativeVSyncInterval( const base::TimeDelta& interval) { + DCHECK_GT(interval.InMillisecondsF(), 0); + refresh_rate_ = + base::Time::kMillisecondsPerSecond / interval.InMillisecondsF(); if (context_factory_private_) context_factory_private_->SetAuthoritativeVSyncInterval(this, interval); vsync_manager_->SetAuthoritativeVSyncInterval(interval); @@ -400,6 +404,9 @@ // TODO(brianderson): We should not be receiving 0 intervals. interval = cc::BeginFrameArgs::DefaultInterval(); } + DCHECK_GT(interval.InMillisecondsF(), 0); + refresh_rate_ = + base::Time::kMillisecondsPerSecond / interval.InMillisecondsF(); if (context_factory_private_) { context_factory_private_->SetDisplayVSyncParameters(this, timebase, @@ -506,6 +513,7 @@ } void Compositor::DidReceiveCompositorFrameAck() { + ++committed_frame_number_; for (auto& observer : observer_list_) observer.OnCompositingEnded(this); }
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 25bad57a..92696ad 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -380,6 +380,8 @@ } const cc::FrameSinkId& frame_sink_id() const { return frame_sink_id_; } + int committed_frame_number() const { return committed_frame_number_; } + float refresh_rate() const { return refresh_rate_; } private: friend class base::RefCounted<Compositor>; @@ -403,6 +405,12 @@ base::ObserverList<CompositorAnimationObserver> animation_observer_list_; gfx::AcceleratedWidget widget_; + // A sequence number of a current compositor frame for use with metrics. + int committed_frame_number_; + + // current VSYNC refresh rate per second. + float refresh_rate_; + // A map from child id to parent id. std::unordered_set<cc::FrameSinkId, cc::FrameSinkIdHash> child_frame_sinks_; bool widget_valid_;
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index be6b6e52..e5baec7 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -1082,6 +1082,16 @@ return compositor ? compositor->layer_animator_collection() : NULL; } +int Layer::GetFrameNumber() const { + const Compositor* compositor = GetCompositor(); + return compositor ? compositor->committed_frame_number() : 0; +} + +float Layer::GetRefreshRate() const { + const Compositor* compositor = GetCompositor(); + return compositor ? compositor->refresh_rate() : 60.0; +} + cc::Layer* Layer::GetCcLayer() const { return cc_layer_; }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index cfb301df..e1525b5 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -421,6 +421,8 @@ cc::Layer* GetCcLayer() const override; LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() override; LayerAnimatorCollection* GetLayerAnimatorCollection() override; + int GetFrameNumber() const override; + float GetRefreshRate() const override; // Creates a corresponding composited layer for |type_|. void CreateCcLayer();
diff --git a/ui/compositor/layer_animation_delegate.h b/ui/compositor/layer_animation_delegate.h index b1db0b3..1473fa1 100644 --- a/ui/compositor/layer_animation_delegate.h +++ b/ui/compositor/layer_animation_delegate.h
@@ -41,6 +41,8 @@ virtual cc::Layer* GetCcLayer() const = 0; virtual LayerAnimatorCollection* GetLayerAnimatorCollection() = 0; virtual LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() = 0; + virtual int GetFrameNumber() const = 0; + virtual float GetRefreshRate() const = 0; protected: virtual ~LayerAnimationDelegate() {}
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc index b446b7ad..7ba0993 100644 --- a/ui/compositor/layer_animation_element.cc +++ b/ui/compositor/layer_animation_element.cc
@@ -447,8 +447,8 @@ // LayerAnimationElement ------------------------------------------------------- -LayerAnimationElement::LayerAnimationElement( - AnimatableProperties properties, base::TimeDelta duration) +LayerAnimationElement::LayerAnimationElement(AnimatableProperties properties, + base::TimeDelta duration) : first_frame_(true), properties_(properties), duration_(GetEffectiveDuration(duration)), @@ -456,11 +456,12 @@ animation_id_(cc::AnimationIdProvider::NextAnimationId()), animation_group_id_(0), last_progressed_fraction_(0.0), - weak_ptr_factory_(this) { -} + animation_metrics_reporter_(nullptr), + start_frame_number_(0), + weak_ptr_factory_(this) {} LayerAnimationElement::LayerAnimationElement( - const LayerAnimationElement &element) + const LayerAnimationElement& element) : first_frame_(element.first_frame_), properties_(element.properties_), duration_(element.duration_), @@ -468,8 +469,9 @@ animation_id_(cc::AnimationIdProvider::NextAnimationId()), animation_group_id_(element.animation_group_id_), last_progressed_fraction_(element.last_progressed_fraction_), - weak_ptr_factory_(this) { -} + animation_metrics_reporter_(nullptr), + start_frame_number_(0), + weak_ptr_factory_(this) {} LayerAnimationElement::~LayerAnimationElement() { } @@ -481,6 +483,8 @@ animation_group_id_ = animation_group_id; last_progressed_fraction_ = 0.0; OnStart(delegate); + if (delegate) + start_frame_number_ = delegate->GetFrameNumber(); RequestEffectiveStart(delegate); first_frame_ = false; } @@ -534,10 +538,29 @@ } bool LayerAnimationElement::ProgressToEnd(LayerAnimationDelegate* delegate) { - if (first_frame_) + const int frame_number = delegate ? delegate->GetFrameNumber() : 0; + if (first_frame_) { OnStart(delegate); + start_frame_number_ = frame_number; + } base::WeakPtr<LayerAnimationElement> alive(weak_ptr_factory_.GetWeakPtr()); bool need_draw = OnProgress(1.0, delegate); + + int end_frame_number = frame_number; + if (animation_metrics_reporter_ && end_frame_number > start_frame_number_ && + !duration_.is_zero()) { + base::TimeDelta elapsed = base::TimeTicks::Now() - effective_start_time_; + if (elapsed >= duration_) { + int smoothness = 100; + const float kFrameInterval = + base::Time::kMillisecondsPerSecond / delegate->GetRefreshRate(); + const float actual_duration = + (end_frame_number - start_frame_number_) * kFrameInterval; + if (duration_.InMillisecondsF() - actual_duration >= kFrameInterval) + smoothness = 100 * (actual_duration / duration_.InMillisecondsF()); + animation_metrics_reporter_->Report(smoothness); + } + } if (!alive) return need_draw; last_progressed_fraction_ = 1.0;
diff --git a/ui/compositor/layer_animation_element.h b/ui/compositor/layer_animation_element.h index f847e42..664468e 100644 --- a/ui/compositor/layer_animation_element.h +++ b/ui/compositor/layer_animation_element.h
@@ -25,6 +25,12 @@ class InterpolatedTransform; class LayerAnimationDelegate; +class AnimationMetricsReporter { + public: + virtual ~AnimationMetricsReporter() {} + virtual void Report(int value) = 0; +}; + // LayerAnimationElements represent one segment of an animation between two // keyframes. They know how to update a LayerAnimationDelegate given a value // between 0 and 1 (0 for initial, and 1 for final). @@ -182,6 +188,10 @@ gfx::Tween::Type tween_type() const { return tween_type_; } void set_tween_type(gfx::Tween::Type tween_type) { tween_type_ = tween_type; } + void set_animation_metrics_reporter(AnimationMetricsReporter* reporter) { + animation_metrics_reporter_ = reporter; + } + // Each LayerAnimationElement has a unique animation_id. Elements belonging // to sequences that are supposed to start together have the same // animation_group_id. @@ -228,6 +238,11 @@ double last_progressed_fraction_; + // To obtain metrics of animation performance tag animation elements and + // keep track of sequential compositor frame number. + AnimationMetricsReporter* animation_metrics_reporter_; + int start_frame_number_; + base::WeakPtrFactory<LayerAnimationElement> weak_ptr_factory_; DISALLOW_ASSIGN(LayerAnimationElement);
diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc index 773cbb4..d1739e7 100644 --- a/ui/compositor/layer_animation_sequence.cc +++ b/ui/compositor/layer_animation_sequence.cc
@@ -22,8 +22,8 @@ waiting_for_group_start_(false), animation_group_id_(0), last_progressed_fraction_(0.0), - weak_ptr_factory_(this) { -} + animation_metrics_reporter_(nullptr), + weak_ptr_factory_(this) {} LayerAnimationSequence::LayerAnimationSequence( std::unique_ptr<LayerAnimationElement> element) @@ -33,6 +33,7 @@ waiting_for_group_start_(false), animation_group_id_(0), last_progressed_fraction_(0.0), + animation_metrics_reporter_(nullptr), weak_ptr_factory_(this) { AddElement(std::move(element)); } @@ -186,6 +187,7 @@ void LayerAnimationSequence::AddElement( std::unique_ptr<LayerAnimationElement> element) { properties_ |= element->properties(); + element->set_animation_metrics_reporter(animation_metrics_reporter_); elements_.push_back(std::move(element)); } @@ -243,6 +245,13 @@ } } +void LayerAnimationSequence::SetAnimationMetricsReporter( + AnimationMetricsReporter* reporter) { + animation_metrics_reporter_ = reporter; + for (auto& element : elements_) + element->set_animation_metrics_reporter(animation_metrics_reporter_); +} + size_t LayerAnimationSequence::size() const { return elements_.size(); }
diff --git a/ui/compositor/layer_animation_sequence.h b/ui/compositor/layer_animation_sequence.h index c48e91a..2a414f3 100644 --- a/ui/compositor/layer_animation_sequence.h +++ b/ui/compositor/layer_animation_sequence.h
@@ -127,6 +127,9 @@ // Called when the animator is destroyed. void OnAnimatorDestroyed(); + // Sets |animation_metrics_reporter_| and passes it to all |elements_|. + void SetAnimationMetricsReporter(AnimationMetricsReporter* reporter); + // The last_progressed_fraction of the element most recently progressed by // by this sequence. Returns 0.0 if no elements have been progressed. double last_progressed_fraction() const { return last_progressed_fraction_; } @@ -191,6 +194,9 @@ // element. double last_progressed_fraction_; + // Used to tag animation elements to obtain metrics of animation performance. + AnimationMetricsReporter* animation_metrics_reporter_; + base::WeakPtrFactory<LayerAnimationSequence> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(LayerAnimationSequence);
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc index 141e7dd..df00ff9 100644 --- a/ui/compositor/layer_animator.cc +++ b/ui/compositor/layer_animator.cc
@@ -53,7 +53,8 @@ tween_type_(gfx::Tween::LINEAR), is_started_(false), disable_timer_for_test_(false), - adding_animations_(false) { + adding_animations_(false), + animation_metrics_reporter_(nullptr) { animation_player_ = cc::AnimationPlayer::Create(cc::AnimationIdProvider::NextPlayerId()); } @@ -195,6 +196,8 @@ void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) { scoped_refptr<LayerAnimator> retain(this); + if (animation_metrics_reporter_) + animation->SetAnimationMetricsReporter(animation_metrics_reporter_); OnScheduled(animation); if (!StartSequenceImmediately(animation)) { // Attempt to preempt a running animation.
diff --git a/ui/compositor/layer_animator.h b/ui/compositor/layer_animator.h index f730adc..e027dda 100644 --- a/ui/compositor/layer_animator.h +++ b/ui/compositor/layer_animator.h
@@ -362,6 +362,10 @@ void AttachLayerToAnimationPlayer(int layer_id); void DetachLayerFromAnimationPlayer(); + void set_animation_metrics_reporter(AnimationMetricsReporter* reporter) { + animation_metrics_reporter_ = reporter; + } + // This is the queue of animations to run. AnimationQueue animation_queue_; @@ -401,6 +405,9 @@ // with preemption strategies that discard previous animations. bool adding_animations_; + // Helper to output UMA performance metrics. + AnimationMetricsReporter* animation_metrics_reporter_; + // Observers are notified when layer animations end, are scheduled or are // aborted. base::ObserverList<LayerAnimationObserver> observers_;
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 9150bf5..dce61833 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -2228,6 +2228,52 @@ EXPECT_TRUE(animation_observer.shutdown()); } +// A simple AnimationMetricsReporter class that remembers smoothness metric +// when animation completes. +class TestMetricsReporter : public ui::AnimationMetricsReporter { + public: + TestMetricsReporter() {} + ~TestMetricsReporter() override {} + + bool report_called() { return report_called_; } + int value() const { return value_; } + + protected: + void Report(int value) override { + value_ = value; + report_called_ = true; + } + + private: + bool report_called_ = false; + int value_ = -1; + + DISALLOW_COPY_AND_ASSIGN(TestMetricsReporter); +}; + +// Starts an animation and tests that incrementing compositor frame count can +// be used to report animation smoothness metrics. +TEST_F(LayerWithRealCompositorTest, ReportMetrics) { + std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR)); + GetCompositor()->SetRootLayer(root.get()); + LayerAnimator* animator = root->GetAnimator(); + std::unique_ptr<ui::LayerAnimationElement> animation_element = + ui::LayerAnimationElement::CreateColorElement( + SK_ColorRED, base::TimeDelta::FromMilliseconds(100)); + ui::LayerAnimationSequence* animation_sequence = + new ui::LayerAnimationSequence(std::move(animation_element)); + TestMetricsReporter reporter; + animation_sequence->SetAnimationMetricsReporter(&reporter); + animator->StartAnimation(animation_sequence); + while (!reporter.report_called()) + WaitForSwap(); + ResetCompositor(); + // Even though most of the time 100% smooth animations are expected, on the + // test bots this cannot be guaranteed. Therefore simply check that some + // value was reported. + EXPECT_GT(reporter.value(), 0); +} + TEST(LayerDebugInfoTest, LayerNameDoesNotClobber) { Layer layer(LAYER_NOT_DRAWN); layer.set_name("foo");
diff --git a/ui/compositor/scoped_layer_animation_settings.cc b/ui/compositor/scoped_layer_animation_settings.cc index 5688d3c..71db455a 100644 --- a/ui/compositor/scoped_layer_animation_settings.cc +++ b/ui/compositor/scoped_layer_animation_settings.cc
@@ -33,6 +33,7 @@ } ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() { + animator_->set_animation_metrics_reporter(nullptr); animator_->is_transition_duration_locked_ = old_is_transition_duration_locked_; animator_->SetTransitionDuration(old_transition_duration_); @@ -52,6 +53,11 @@ animator_->AddObserver(observer); } +void ScopedLayerAnimationSettings::SetAnimationMetricsReporter( + AnimationMetricsReporter* reporter) { + animator_->set_animation_metrics_reporter(reporter); +} + void ScopedLayerAnimationSettings::SetTransitionDuration( base::TimeDelta duration) { animator_->SetTransitionDuration(duration);
diff --git a/ui/compositor/scoped_layer_animation_settings.h b/ui/compositor/scoped_layer_animation_settings.h index f8fc459e..ddc6d68 100644 --- a/ui/compositor/scoped_layer_animation_settings.h +++ b/ui/compositor/scoped_layer_animation_settings.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/time/time.h" #include "ui/compositor/compositor_export.h" +#include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animator.h" #include "ui/gfx/animation/tween.h" @@ -28,6 +29,7 @@ void AddObserver(ImplicitAnimationObserver* observer); + void SetAnimationMetricsReporter(AnimationMetricsReporter* reporter); void SetTransitionDuration(base::TimeDelta duration); base::TimeDelta GetTransitionDuration() const;
diff --git a/ui/compositor/test/test_layer_animation_delegate.cc b/ui/compositor/test/test_layer_animation_delegate.cc index 350370d..ee6f426 100644 --- a/ui/compositor/test/test_layer_animation_delegate.cc +++ b/ui/compositor/test/test_layer_animation_delegate.cc
@@ -115,6 +115,15 @@ return &threaded_delegate_; } +int TestLayerAnimationDelegate::GetFrameNumber() const { + return 0; +} + +float TestLayerAnimationDelegate::GetRefreshRate() const { + return 60.0; +} + + void TestLayerAnimationDelegate::CreateCcLayer() { cc_layer_ = cc::Layer::Create(); }
diff --git a/ui/compositor/test/test_layer_animation_delegate.h b/ui/compositor/test/test_layer_animation_delegate.h index ea1a91d..a6575f5 100644 --- a/ui/compositor/test/test_layer_animation_delegate.h +++ b/ui/compositor/test/test_layer_animation_delegate.h
@@ -52,6 +52,8 @@ LayerAnimatorCollection* GetLayerAnimatorCollection() override; cc::Layer* GetCcLayer() const override; LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() override; + int GetFrameNumber() const override; + float GetRefreshRate() const override; private: void CreateCcLayer();
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index dc9160e..ed78526 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -18,7 +18,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h"
diff --git a/ui/gfx/blit.cc b/ui/gfx/blit.cc index 614f6c9..e402367 100644 --- a/ui/gfx/blit.cc +++ b/ui/gfx/blit.cc
@@ -14,24 +14,6 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" -#if defined(USE_CAIRO) -#if defined(OS_OPENBSD) -#include <cairo.h> -#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) -#include <cairo/cairo.h> -#endif -#endif - -#if defined(OS_MACOSX) -#if defined(OS_IOS) -#include <CoreGraphics/CoreGraphics.h> -#else -#include <ApplicationServices/ApplicationServices.h> -#endif - -#include "base/mac/scoped_cftyperef.h" -#endif - namespace gfx { namespace {
diff --git a/ui/views/view.cc b/ui/views/view.cc index 83d2700c..cf93f92c 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -219,7 +219,7 @@ const bool did_reparent_any_layers = view->UpdateParentLayers(); Widget* widget = GetWidget(); if (did_reparent_any_layers && widget) - widget->UpdateRootLayers(); + widget->LayerTreeChanged(); ReorderLayers(); @@ -565,14 +565,14 @@ Widget* widget = GetWidget(); if (widget) - widget->UpdateRootLayers(); + widget->LayerTreeChanged(); } std::unique_ptr<ui::Layer> View::RecreateLayer() { std::unique_ptr<ui::Layer> old_layer = LayerOwner::RecreateLayer(); Widget* widget = GetWidget(); if (widget) - widget->UpdateRootLayers(); + widget->LayerTreeChanged(); return old_layer; } @@ -1941,7 +1941,7 @@ // removed. view->OrphanLayers(); if (widget) - widget->UpdateRootLayers(); + widget->LayerTreeChanged(); view->PropagateRemoveNotifications(this, new_parent); view->parent_ = nullptr; @@ -2235,7 +2235,7 @@ Widget* widget = GetWidget(); if (widget) - widget->UpdateRootLayers(); + widget->LayerTreeChanged(); // Before having its own Layer, this View may have painted in to a Layer owned // by an ancestor View. Scheduling a paint on the parent View will erase this
diff --git a/ui/views/view.h b/ui/views/view.h index a916376..19118be1 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -116,7 +116,7 @@ public ui::EventTarget, public ui::EventHandler { public: - typedef std::vector<View*> Views; + using Views = std::vector<View*>; enum class FocusBehavior { // Use when the View is never focusable. Default.
diff --git a/ui/views/view_unittest_aura.cc b/ui/views/view_unittest_aura.cc index 351c662a..231afc3 100644 --- a/ui/views/view_unittest_aura.cc +++ b/ui/views/view_unittest_aura.cc
@@ -43,7 +43,18 @@ } // namespace -typedef ViewsTestBase ViewAuraTest; +class ViewAuraTest : public ViewsTestBase { + public: + ViewAuraTest() {} + ~ViewAuraTest() override {} + + const View::Views& GetViewsWithLayers(Widget* widget) { + return widget->GetViewsWithLayers(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ViewAuraTest); +}; // Test that wm::RecreateLayers() recreates the layers for all child windows and // all child views and that the z-order of the recreated layers matches that of @@ -119,11 +130,11 @@ // Verify the value of Widget::GetRootLayers(). It should only include layers // from layer-backed Views descended from the Widget's root View. - std::vector<ui::Layer*> old_w1_root_sublayers = w1->GetRootLayers(); - ASSERT_EQ(3u, old_w1_root_sublayers.size()); - EXPECT_EQ(v1_layer, old_w1_root_sublayers[0]); - EXPECT_EQ(v4_layer, old_w1_root_sublayers[1]); - EXPECT_EQ(v7_layer, old_w1_root_sublayers[2]); + View::Views old_w1_views_with_layers = GetViewsWithLayers(w1); + ASSERT_EQ(3u, old_w1_views_with_layers.size()); + EXPECT_EQ(v1, old_w1_views_with_layers[0]); + EXPECT_EQ(v4, old_w1_views_with_layers[1]); + EXPECT_EQ(v7, old_w1_views_with_layers[2]); { std::unique_ptr<ui::LayerTreeOwner> cloned_owner( @@ -174,12 +185,12 @@ ASSERT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_new_layer)); EXPECT_NE(v7_layer, v7_new_layer); - // Ensure Widget::GetRootLayers() is correctly updated. - std::vector<ui::Layer*> new_w1_root_sublayers = w1->GetRootLayers(); - ASSERT_EQ(3u, new_w1_root_sublayers.size()); - EXPECT_EQ(v1_new_layer, new_w1_root_sublayers[0]); - EXPECT_EQ(v4_new_layer, new_w1_root_sublayers[1]); - EXPECT_EQ(v7_new_layer, new_w1_root_sublayers[2]); + // Ensure Widget::GetViewsWithLayers() is correctly updated. + View::Views new_w1_views_with_layers = GetViewsWithLayers(w1); + ASSERT_EQ(3u, new_w1_views_with_layers.size()); + EXPECT_EQ(v1, new_w1_views_with_layers[0]); + EXPECT_EQ(v4, new_w1_views_with_layers[1]); + EXPECT_EQ(v7, new_w1_views_with_layers[2]); } w1->CloseNow(); }
diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.cc b/ui/views/widget/desktop_aura/desktop_capture_client.cc index 5ce64e9d..6c1d0b8 100644 --- a/ui/views/widget/desktop_aura/desktop_capture_client.cc +++ b/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -12,12 +12,20 @@ namespace views { // static -DesktopCaptureClient::CaptureClients* -DesktopCaptureClient::capture_clients_ = NULL; +DesktopCaptureClient::CaptureClients* DesktopCaptureClient::capture_clients_ = + nullptr; + +// static +aura::Window* DesktopCaptureClient::GetCaptureWindowGlobal() { + for (auto* client : *capture_clients_) { + if (client->capture_window_) + return client->capture_window_; + } + return nullptr; +} DesktopCaptureClient::DesktopCaptureClient(aura::Window* root) - : root_(root), - capture_window_(NULL) { + : root_(root), capture_window_(nullptr) { if (!capture_clients_) capture_clients_ = new CaptureClients; capture_clients_->insert(this); @@ -25,7 +33,7 @@ } DesktopCaptureClient::~DesktopCaptureClient() { - aura::client::SetCaptureClient(root_, NULL); + aura::client::SetCaptureClient(root_, nullptr); capture_clients_->erase(this); } @@ -82,7 +90,7 @@ void DesktopCaptureClient::ReleaseCapture(aura::Window* window) { if (capture_window_ != window) return; - SetCapture(NULL); + SetCapture(nullptr); } aura::Window* DesktopCaptureClient::GetCaptureWindow() { @@ -90,12 +98,7 @@ } aura::Window* DesktopCaptureClient::GetGlobalCaptureWindow() { - for (CaptureClients::iterator i = capture_clients_->begin(); - i != capture_clients_->end(); ++i) { - if ((*i)->capture_window_) - return (*i)->capture_window_; - } - return NULL; + return GetCaptureWindowGlobal(); } void DesktopCaptureClient::AddObserver(
diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.h b/ui/views/widget/desktop_aura/desktop_capture_client.h index f297127..497e896f 100644 --- a/ui/views/widget/desktop_aura/desktop_capture_client.h +++ b/ui/views/widget/desktop_aura/desktop_capture_client.h
@@ -37,6 +37,9 @@ explicit DesktopCaptureClient(aura::Window* root); ~DesktopCaptureClient() override; + // Exactly the same as GetGlobalCaptureWindow() but static. + static aura::Window* GetCaptureWindowGlobal(); + // Overridden from aura::client::CaptureClient: void SetCapture(aura::Window* window) override; void ReleaseCapture(aura::Window* window) override;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index f442ef1..bc0324c1 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -985,9 +985,8 @@ bool DesktopNativeWidgetAura::ShouldDescendIntoChildForEventHandling( aura::Window* child, const gfx::Point& location) { - views::WidgetDelegate* widget_delegate = GetWidget()->widget_delegate(); - return !widget_delegate || - widget_delegate->ShouldDescendIntoChildForEventHandling(child, location); + return native_widget_delegate_->ShouldDescendIntoChildForEventHandling( + content_window_->layer(), child, child->layer(), location); } bool DesktopNativeWidgetAura::CanFocus() {
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 75bccedd..8082fb5a 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc
@@ -819,36 +819,8 @@ bool NativeWidgetAura::ShouldDescendIntoChildForEventHandling( aura::Window* child, const gfx::Point& location) { - views::WidgetDelegate* widget_delegate = GetWidget()->widget_delegate(); - if (widget_delegate && - !widget_delegate->ShouldDescendIntoChildForEventHandling(child, location)) - return false; - - // Don't descend into |child| if there is a view with a Layer that contains - // the point and is stacked above |child|s layer. - typedef std::vector<ui::Layer*> Layers; - const Layers& root_layers(delegate_->GetRootLayers()); - if (root_layers.empty()) - return true; - - Layers::const_iterator child_layer_iter( - std::find(window_->layer()->children().begin(), - window_->layer()->children().end(), child->layer())); - if (child_layer_iter == window_->layer()->children().end()) - return true; - - for (std::vector<ui::Layer*>::const_reverse_iterator i = root_layers.rbegin(); - i != root_layers.rend(); ++i) { - ui::Layer* layer = *i; - if (layer->visible() && layer->bounds().Contains(location)) { - Layers::const_iterator root_layer_iter( - std::find(window_->layer()->children().begin(), - window_->layer()->children().end(), layer)); - if (root_layer_iter > child_layer_iter) - return false; - } - } - return true; + return delegate_->ShouldDescendIntoChildForEventHandling( + window_->layer(), child, child->layer(), location); } bool NativeWidgetAura::CanFocus() {
diff --git a/ui/views/widget/native_widget_aura_unittest.cc b/ui/views/widget/native_widget_aura_unittest.cc index 4d06907e..3a59c59 100644 --- a/ui/views/widget/native_widget_aura_unittest.cc +++ b/ui/views/widget/native_widget_aura_unittest.cc
@@ -517,6 +517,54 @@ parent->Close(); } +// Verifies views with layers are targeted for events properly. +TEST_F(NativeWidgetAuraTest, + ShouldDescendIntoChildForEventHandlingChecksVisibleBounds) { + // Create two widgets: |parent| and |child|. |child| is a child of |parent|. + View* parent_root_view = new View; + Widget parent; + Widget::InitParams parent_params(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + parent_params.context = root_window(); + parent.Init(parent_params); + parent.SetContentsView(parent_root_view); + parent.SetBounds(gfx::Rect(0, 0, 400, 400)); + parent.Show(); + + Widget child; + Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); + child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + child_params.parent = parent.GetNativeWindow(); + child.Init(child_params); + child.SetBounds(gfx::Rect(0, 0, 200, 200)); + child.Show(); + + // Point is over |child|. + EXPECT_EQ( + child.GetNativeWindow(), + parent.GetNativeWindow()->GetEventHandlerForPoint(gfx::Point(50, 50))); + + View* parent_root_view_child = new View; + parent_root_view->AddChildView(parent_root_view_child); + parent_root_view_child->SetBounds(0, 0, 10, 10); + + // Create a View whose layer extends outside the bounds of its parent. Event + // targetting should only consider the visible bounds. + View* parent_root_view_child_child = new View; + parent_root_view_child->AddChildView(parent_root_view_child_child); + parent_root_view_child_child->SetBounds(0, 0, 100, 100); + parent_root_view_child_child->SetPaintToLayer(); + parent_root_view_child_child->layer()->parent()->StackAtTop( + parent_root_view_child_child->layer()); + + // 20,20 is over |parent_root_view_child_child|'s layer, but not the visible + // bounds of |parent_root_view_child_child|, so |child| should be the event + // target. + EXPECT_EQ( + child.GetNativeWindow(), + parent.GetNativeWindow()->GetEventHandlerForPoint(gfx::Point(20, 20))); +} + // Verifies that widget->FlashFrame() sets aura::client::kDrawAttentionKey, // and activating the window clears it. TEST_F(NativeWidgetAuraTest, FlashFrame) {
diff --git a/ui/views/widget/native_widget_delegate.h b/ui/views/widget/native_widget_delegate.h index 963f48d2..8f2e56a 100644 --- a/ui/views/widget/native_widget_delegate.h +++ b/ui/views/widget/native_widget_delegate.h
@@ -5,9 +5,8 @@ #ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_DELEGATE_H_ #define UI_VIEWS_WIDGET_NATIVE_WIDGET_DELEGATE_H_ -#include <vector> - #include "ui/events/event_constants.h" +#include "ui/gfx/native_widget_types.h" #include "ui/views/views_export.h" namespace gfx { @@ -128,9 +127,6 @@ // Runs the specified native command. Returns true if the command is handled. virtual bool ExecuteCommand(int command_id) = 0; - // Returns the child Layers of the Widgets layer that were created by Views. - virtual const std::vector<ui::Layer*>& GetRootLayers() = 0; - // Returns true if window has a hit-test mask. virtual bool HasHitTestMask() const = 0; @@ -147,6 +143,15 @@ // not set the initial focus, or false if the caller should set the initial // focus (if any). virtual bool SetInitialFocus(ui::WindowShowState show_state) = 0; + + // Returns true if event handling should descend into |child|. |root_layer| is + // the layer associated with the root Window and |child_layer| the layer + // associated with |child|. |location| is in terms of the Window. + virtual bool ShouldDescendIntoChildForEventHandling( + ui::Layer* root_layer, + gfx::NativeView child, + ui::Layer* child_layer, + const gfx::Point& location) = 0; }; } // namespace internal
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 8b062753..00081416 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -9,6 +9,7 @@ #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" +#include "ui/aura/window.h" #include "ui/base/cursor/cursor.h" #include "ui/base/default_style.h" #include "ui/base/default_theme_provider.h" @@ -46,12 +47,12 @@ // If |view| has a layer the layer is added to |layers|. Else this recurses // through the children. This is used to build a list of the layers created by // views that are direct children of the Widgets layer. -void BuildRootLayers(View* view, std::vector<ui::Layer*>* layers) { +void BuildViewsWithLayers(View* view, View::Views* views) { if (view->layer()) { - layers->push_back(view->layer()); + views->push_back(view); } else { for (int i = 0; i < view->child_count(); ++i) - BuildRootLayers(view->child_at(i), layers); + BuildViewsWithLayers(view->child_at(i), views); } } @@ -163,10 +164,9 @@ ignore_capture_loss_(false), last_mouse_event_was_move_(false), auto_release_capture_(true), - root_layers_dirty_(false), + views_with_layers_dirty_(false), movement_disabled_(false), - observer_manager_(this) { -} + observer_manager_(this) {} Widget::~Widget() { DestroyRootView(); @@ -914,11 +914,11 @@ native_widget_->ReorderNativeViews(); } -void Widget::UpdateRootLayers() { +void Widget::LayerTreeChanged() { // Calculate the layers requires traversing the tree, and since nearly any // mutation of the tree can trigger this call we delay until absolutely // necessary. - root_layers_dirty_ = true; + views_with_layers_dirty_ = true; } const NativeWidget* Widget::native_widget() const { @@ -1276,15 +1276,6 @@ return widget_delegate_->ExecuteWindowsCommand(command_id); } -const std::vector<ui::Layer*>& Widget::GetRootLayers() { - if (root_layers_dirty_) { - root_layers_dirty_ = false; - root_layers_.clear(); - BuildRootLayers(GetRootView(), &root_layers_); - } - return root_layers_; -} - bool Widget::HasHitTestMask() const { return widget_delegate_->WidgetHasHitTestMask(); } @@ -1323,6 +1314,55 @@ return !!focus_manager->GetFocusedView(); } +bool Widget::ShouldDescendIntoChildForEventHandling( + ui::Layer* root_layer, + gfx::NativeView child, + ui::Layer* child_layer, + const gfx::Point& location) { + if (widget_delegate_ && + !widget_delegate_->ShouldDescendIntoChildForEventHandling(child, + location)) { + return false; + } + + const View::Views& views_with_layers = GetViewsWithLayers(); + if (views_with_layers.empty()) + return true; + + // Don't descend into |child| if there is a view with a Layer that contains + // the point and is stacked above |child_layer|. + auto child_layer_iter = std::find(root_layer->children().begin(), + root_layer->children().end(), child_layer); + if (child_layer_iter == root_layer->children().end()) + return true; + + for (auto iter = views_with_layers.rbegin(); iter != views_with_layers.rend(); + ++iter) { + ui::Layer* layer = (*iter)->layer(); + DCHECK(layer); + if (layer->visible() && layer->bounds().Contains(location)) { + auto root_layer_iter = std::find(root_layer->children().begin(), + root_layer->children().end(), layer); + if (child_layer_iter > root_layer_iter) { + // |child| is on top of the remaining layers, no need to continue. + return true; + } + + // Event targeting uses the visible bounds of the View, which may differ + // from the bounds of the layer. Verify the view hosting the layer + // actually contains |location|. Use GetVisibleBounds(), which is + // effectively what event targetting uses. + View* view = *iter; + gfx::Rect vis_bounds = view->GetVisibleBounds(); + gfx::Point point_in_view = location; + View::ConvertPointToTarget(GetRootView(), view, &point_in_view); + if (vis_bounds.Contains(point_in_view)) + return false; + } + } + return true; +} + //////////////////////////////////////////////////////////////////////////////// // Widget, ui::EventSource implementation: ui::EventProcessor* Widget::GetEventProcessor() { @@ -1492,6 +1532,15 @@ return false; } +const View::Views& Widget::GetViewsWithLayers() { + if (views_with_layers_dirty_) { + views_with_layers_dirty_ = false; + views_with_layers_.clear(); + BuildViewsWithLayers(GetRootView(), &views_with_layers_); + } + return views_with_layers_; +} + namespace internal { ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 2c5ba165..a9861ec2 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -715,9 +715,9 @@ // reordering if there are no views with an associated NativeView. void ReorderNativeViews(); - // Schedules an update to the root layers. The actual processing occurs when - // GetRootLayers() is invoked. - void UpdateRootLayers(); + // Called by a View when the status of it's layer or one of the views + // descendants layer status changes. + void LayerTreeChanged(); const NativeWidget* native_widget() const; NativeWidget* native_widget(); @@ -816,12 +816,16 @@ void OnScrollEvent(ui::ScrollEvent* event) override; void OnGestureEvent(ui::GestureEvent* event) override; bool ExecuteCommand(int command_id) override; - const std::vector<ui::Layer*>& GetRootLayers() override; bool HasHitTestMask() const override; void GetHitTestMask(gfx::Path* mask) const override; Widget* AsWidget() override; const Widget* AsWidget() const override; bool SetInitialFocus(ui::WindowShowState show_state) override; + bool ShouldDescendIntoChildForEventHandling( + ui::Layer* root_layer, + gfx::NativeView child, + ui::Layer* child_layer, + const gfx::Point& location) override; // Overridden from ui::EventSource: ui::EventProcessor* GetEventProcessor() override; @@ -855,6 +859,7 @@ friend class ComboboxTest; friend class CustomButtonTest; friend class TextfieldTest; + friend class ViewAuraTest; // Persists the window's restored position and "show" state using the // window delegate. @@ -876,6 +881,10 @@ bool GetSavedWindowPlacement(gfx::Rect* bounds, ui::WindowShowState* show_state); + // Returns the Views whose layers are parented directly to the Widget's + // layer. + const View::Views& GetViewsWithLayers(); + internal::NativeWidgetPrivate* native_widget_; base::ObserverList<WidgetObserver> observers_; @@ -967,11 +976,11 @@ // true. bool auto_release_capture_; - // See description in GetRootLayers(). - std::vector<ui::Layer*> root_layers_; + // See description in GetViewsWithLayers(). + View::Views views_with_layers_; - // Is |root_layers_| out of date? - bool root_layers_dirty_; + // Does |views_with_layers_| need updating? + bool views_with_layers_dirty_; // True when window movement via mouse interaction with the frame should be // disabled.