diff --git a/DEPS b/DEPS index cf46198..538af75 100644 --- a/DEPS +++ b/DEPS
@@ -86,7 +86,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': '3d70ca9cc194d2e946ca7baf0ed5dec30b2149c7', + 'angle_revision': '3f286cd1b6e29605a159ee0bd20c76929d4d5a9f', # 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. @@ -308,7 +308,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0844d0e4444ced82d770668c12906a14636ce024', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '276e0454b797cc2124a3aa20bda093f97fad3d90', # DevTools node modules. Used on Linux buildbots only. 'src/third_party/devtools-node-modules': { @@ -465,7 +465,7 @@ Var('chromium_git') + '/webm/libwebm.git' + '@' + '4956b2dec65352af32dc71bab553acb631c64177', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '8fa02df3c0591754958a50cc2896aafae319f3bc', # from r1675 + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '12c904a97c81c3ef4cab0fc8fb1f0485b4ec4e8c', # from r1678 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -621,7 +621,7 @@ Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '12192b948daa2d83269ab46cbf03d65e9f2a48a3', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'e4919fa03c74bd561dcabf3e61668fa3c7e54353', 'src/third_party/webrtc': Var('webrtc_git') + '/src.git' + '@' + '2707fb2782e7a47d0f53cf8e561bef0bc00fad66', # commit position 20628
diff --git a/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom index d368fe9a..3db509c 100644 --- a/ash/public/interfaces/wallpaper.mojom +++ b/ash/public/interfaces/wallpaper.mojom
@@ -4,8 +4,12 @@ module ash.mojom; +import "ash/public/interfaces/user_info.mojom"; +import "components/signin/public/interfaces/account_id.mojom"; +import "mojo/common/file_path.mojom"; import "mojo/common/time.mojom"; import "skia/public/interfaces/bitmap.mojom"; +import "url/mojo/url.mojom"; // These values match wallpaper::WallpaperLayout. enum WallpaperLayout { @@ -26,6 +30,9 @@ DEVICE, }; +// TODO(crbug.com/776464): Remove this after WallpaperManager is removed. +// WallpaperInfo will be an internal concept within WallpaperController. +// // This corresponds to wallpaper::WallpaperInfo. struct WallpaperInfo { string location; @@ -34,25 +41,118 @@ mojo.common.mojom.Time date; }; +// User info needed to set wallpapers. Clients must specify the user because +// it's not always the same with the active user, e.g., when showing wallpapers +// for different user pods at login screen, or setting wallpapers selectively +// for primary user and active user during a multi-profile session. +struct WallpaperUserInfo { + // The user's account id. + signin.mojom.AccountId account_id; + + // The user type. Matches user_manager::UserType. + UserType type; + + // True if the user's non-cryptohome data (wallpaper, avatar etc.) is + // ephemeral. See |UserManager::IsCurrentUserNonCryptohomeDataEphemeral| for + // more details. + bool is_ephemeral; + + // True if the user has gaia account. + bool has_gaia_account; +}; + // Used by Chrome to set the wallpaper displayed by ash. interface WallpaperController { - // Calling this method triggers an initial notification of the wallpaper - // state. Observers are automatically removed as their connections are closed. - AddObserver(associated WallpaperObserver observer); + // Sets the client interface. + SetClient(WallpaperControllerClient client); - // Set the wallpaper picker interface, to let ash trigger Chrome's picker. - SetWallpaperPicker(WallpaperPicker picker); + // Sets wallpaper from policy or from a local file. Saves the custom wallpaper + // to file, posts task to generate thumbnail and updates local state. + // |user_info|: The user's information related to wallpaper. + // |wallpaper_files_id|: The unique id of each wallpaper file. + // |file_name|: The name of the wallpaper file. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |type|: The type of the wallpaper, e.g., default, policy etc. + // |image|: The wallpaper image. + // |show_wallpaper|: If false, don't show the new wallpaper now but only + // update cache. + SetCustomWallpaper(WallpaperUserInfo user_info, + string wallpaper_files_id, + string file_name, + WallpaperLayout layout, + WallpaperType type, + skia.mojom.Bitmap image, + bool show_wallpaper); + // Sets wallpaper from the wallpaper picker selection, i.e., the wallpaper + // type is ONLINE. + // |user_info|: The user's information related to wallpaper. + // |image|: The wallpaper image. + // |url|: The url corresponding to this wallpaper. Used as a placeholder for + // the location in WallpaperInfo. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |show_wallpaper|: If false, don't show the new wallpaper now but only + // update cache. + SetOnlineWallpaper(WallpaperUserInfo user_info, + skia.mojom.Bitmap image, + string url, + WallpaperLayout layout, + bool show_wallpaper); + + // Sets the user's wallpaper to be the default wallpaper. Note: different user + // types may have different default wallpapers. If |show_wallpaper| is false, + // don't show the default wallpaper now. + SetDefaultWallpaper(WallpaperUserInfo user_info, bool show_wallpaper); + + // Sets a customized default wallpaper to be used wherever a default wallpaper + // is needed. Note: it doesn't change the default wallpaper for guest and + // child accounts. + // |wallpaper_url|: The url corresponding to this wallpaper. + // |file_path|: The path of the wallpaper file. + // |resized_directory|: The directory where resized versions are stored. Must + // be writable. + SetCustomizedDefaultWallpaper(url.mojom.Url wallpaper_url, + mojo.common.mojom.FilePath file_path, + mojo.common.mojom.FilePath resized_directory); + + // Shows the user's wallpaper, which is determined in the following order: + // 1) Use device policy wallpaper if it exists AND we are at the login screen. + // 2) Use user policy wallpaper if it exists. + // 3) Use the wallpaper set by the user (either by |SetOnlineWallpaper| or + // |SetCustomWallpaper|), if any. + // 4) Use the default wallpaper of this user. + ShowUserWallpaper(WallpaperUserInfo user_info); + + // Used by the gaia-signin UI. Signin wallpaper is considered either as the + // device policy wallpaper or the default wallpaper. + ShowSigninWallpaper(); + + // Removes all of the user's saved wallpapers and related info. + RemoveUserWallpaper(WallpaperUserInfo user_info); + + // TODO(crbug.com/776464): This is only used by WallpaperManager. Remove this + // after WallpaperManager is removed. + // // Set the wallpaper bitmap and info used for the ash desktop background. // A null or empty |wallpaper| bitmap is treated as a no-op. // TODO(crbug.com/655875): Optimize ash wallpaper transport; avoid sending // large bitmaps over Mojo; use shared memory like BitmapUploader, etc. SetWallpaper(skia.mojom.Bitmap? wallpaper, WallpaperInfo info); + // Calling this method triggers an initial notification of the wallpaper + // state. Observers are automatically removed as their connections are closed. + AddObserver(associated WallpaperObserver observer); + // Runs to get wallpaper prominent colors. GetWallpaperColors() => (array<uint32> prominent_colors); }; +// Used by ash to control a Chrome client. +interface WallpaperControllerClient { + // Opens the wallpaper picker window. + OpenWallpaperPicker(); +}; + // Used to listen for wallpaper state changed. interface WallpaperObserver { // Called when the colors extracted from the current wallpaper change. May @@ -61,9 +161,3 @@ // Colors are ordered and are referenced in wallpaper::ColorProfileType. OnWallpaperColorsChanged(array<uint32> prominent_colors); }; - -// Used by ash to trigger Chrome's wallpaper picker functionality. -interface WallpaperPicker { - // Open the wallpaper picker window. - Open(); -};
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc index 82dce6e9..f32eb0e4 100644 --- a/ash/shelf/shelf_context_menu_model_unittest.cc +++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -41,28 +41,28 @@ DISALLOW_COPY_AND_ASSIGN(ShelfContextMenuModelTest); }; -// A test wallpaper picker class that counts the number of times it is opened. -class TestWallpaperPicker : public mojom::WallpaperPicker { +// A test wallpaper controller client class. +class TestWallpaperControllerClient : public mojom::WallpaperControllerClient { public: - TestWallpaperPicker() : binding_(this) {} - ~TestWallpaperPicker() override = default; + TestWallpaperControllerClient() : binding_(this) {} + ~TestWallpaperControllerClient() override = default; size_t open_count() const { return open_count_; } - mojom::WallpaperPickerPtr CreateInterfacePtr() { - mojom::WallpaperPickerPtr ptr; + mojom::WallpaperControllerClientPtr CreateInterfacePtr() { + mojom::WallpaperControllerClientPtr ptr; binding_.Bind(mojo::MakeRequest(&ptr)); return ptr; } - // mojom::WallpaperPicker: - void Open() override { open_count_++; } + // mojom::WallpaperControllerClient: + void OpenWallpaperPicker() override { open_count_++; } private: size_t open_count_ = 0; - mojo::Binding<mojom::WallpaperPicker> binding_; + mojo::Binding<mojom::WallpaperControllerClient> binding_; - DISALLOW_COPY_AND_ASSIGN(TestWallpaperPicker); + DISALLOW_COPY_AND_ASSIGN(TestWallpaperControllerClient); }; // A test shelf item delegate that records the commands sent for execution. @@ -141,13 +141,12 @@ ShelfContextMenuModel menu3(MenuItemList(), nullptr, primary_id); submenu = menu3.GetSubmenuModelAt(1); EXPECT_TRUE(submenu->IsItemCheckedAt(0)); - TestWallpaperPicker picker; - Shell::Get()->wallpaper_controller()->SetWallpaperPicker( - picker.CreateInterfacePtr()); - EXPECT_EQ(0u, picker.open_count()); + TestWallpaperControllerClient client; + Shell::Get()->wallpaper_controller()->SetClient(client.CreateInterfacePtr()); + EXPECT_EQ(0u, client.open_count()); menu3.ActivatedAt(2); - RunAllPendingInMessageLoop(); - EXPECT_EQ(1u, picker.open_count()); + Shell::Get()->wallpaper_controller()->FlushForTesting(); + EXPECT_EQ(1u, client.open_count()); } // Tests the prepending of custom items in a shelf context menu.
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 65ce741..4d5e2160 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -368,9 +368,9 @@ } void WallpaperController::OpenSetWallpaperPage() { - if (wallpaper_picker_ && + if (wallpaper_controller_client_ && Shell::Get()->wallpaper_delegate()->CanOpenSetWallpaperPage()) { - wallpaper_picker_->Open(); + wallpaper_controller_client_->OpenWallpaperPicker(); } } @@ -387,26 +387,73 @@ switches::kAshDisableLoginDimAndBlur); } -void WallpaperController::AddObserver( - mojom::WallpaperObserverAssociatedPtrInfo observer) { - mojom::WallpaperObserverAssociatedPtr observer_ptr; - observer_ptr.Bind(std::move(observer)); - observer_ptr->OnWallpaperColorsChanged(prominent_colors_); - mojo_observers_.AddPtr(std::move(observer_ptr)); +void WallpaperController::SetClient( + mojom::WallpaperControllerClientPtr client) { + wallpaper_controller_client_ = std::move(client); } -void WallpaperController::SetWallpaperPicker(mojom::WallpaperPickerPtr picker) { - wallpaper_picker_ = std::move(picker); +void WallpaperController::SetCustomWallpaper( + mojom::WallpaperUserInfoPtr user_info, + const std::string& wallpaper_files_id, + const std::string& file_name, + wallpaper::WallpaperLayout layout, + wallpaper::WallpaperType type, + const SkBitmap& image, + bool show_wallpaper) { + NOTIMPLEMENTED(); +} + +void WallpaperController::SetOnlineWallpaper( + mojom::WallpaperUserInfoPtr user_info, + const SkBitmap& image, + const std::string& url, + wallpaper::WallpaperLayout layout, + bool show_wallpaper) { + NOTIMPLEMENTED(); +} + +void WallpaperController::SetDefaultWallpaper( + mojom::WallpaperUserInfoPtr user_info, + bool show_wallpaper) { + NOTIMPLEMENTED(); +} + +void WallpaperController::SetCustomizedDefaultWallpaper( + const GURL& wallpaper_url, + const base::FilePath& file_path, + const base::FilePath& resized_directory) { + NOTIMPLEMENTED(); +} + +void WallpaperController::ShowUserWallpaper( + mojom::WallpaperUserInfoPtr user_info) { + NOTIMPLEMENTED(); +} + +void WallpaperController::ShowSigninWallpaper() { + NOTIMPLEMENTED(); +} + +void WallpaperController::RemoveUserWallpaper( + mojom::WallpaperUserInfoPtr user_info) { + NOTIMPLEMENTED(); } void WallpaperController::SetWallpaper(const SkBitmap& wallpaper, const wallpaper::WallpaperInfo& info) { if (wallpaper.isNull()) return; - SetWallpaperImage(gfx::ImageSkia::CreateFrom1xBitmap(wallpaper), info); } +void WallpaperController::AddObserver( + mojom::WallpaperObserverAssociatedPtrInfo observer) { + mojom::WallpaperObserverAssociatedPtr observer_ptr; + observer_ptr.Bind(std::move(observer)); + observer_ptr->OnWallpaperColorsChanged(prominent_colors_); + mojo_observers_.AddPtr(std::move(observer_ptr)); +} + void WallpaperController::GetWallpaperColors( GetWallpaperColorsCallback callback) { std::move(callback).Run(prominent_colors_); @@ -425,6 +472,10 @@ SetProminentColors(colors); } +void WallpaperController::FlushForTesting() { + wallpaper_controller_client_.FlushForTesting(); +} + void WallpaperController::InstallDesktopController(aura::Window* root_window) { WallpaperWidgetController* component = nullptr; int container_id = GetWallpaperContainerId(locked_);
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index e5c24c1..80ecc31 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -138,10 +138,31 @@ bool IsWallpaperBlurred() const { return is_wallpaper_blurred_; } // mojom::WallpaperController overrides: - void AddObserver(mojom::WallpaperObserverAssociatedPtrInfo observer) override; - void SetWallpaperPicker(mojom::WallpaperPickerPtr picker) override; + void SetClient(mojom::WallpaperControllerClientPtr client) override; + void SetCustomWallpaper(mojom::WallpaperUserInfoPtr user_info, + const std::string& wallpaper_files_id, + const std::string& file_name, + wallpaper::WallpaperLayout layout, + wallpaper::WallpaperType type, + const SkBitmap& image, + bool show_wallpaper) override; + void SetOnlineWallpaper(mojom::WallpaperUserInfoPtr user_info, + const SkBitmap& image, + const std::string& url, + wallpaper::WallpaperLayout layout, + bool show_wallpaper) override; + void SetDefaultWallpaper(mojom::WallpaperUserInfoPtr user_info, + bool show_wallpaper) override; + void SetCustomizedDefaultWallpaper( + const GURL& wallpaper_url, + const base::FilePath& file_path, + const base::FilePath& resized_directory) override; + void ShowUserWallpaper(mojom::WallpaperUserInfoPtr user_info) override; + void ShowSigninWallpaper() override; + void RemoveUserWallpaper(mojom::WallpaperUserInfoPtr user_info) override; void SetWallpaper(const SkBitmap& wallpaper, const wallpaper::WallpaperInfo& wallpaper_info) override; + void AddObserver(mojom::WallpaperObserverAssociatedPtrInfo observer) override; void GetWallpaperColors(GetWallpaperColorsCallback callback) override; // WallpaperResizerObserver: @@ -150,6 +171,9 @@ // WallpaperColorCalculatorObserver: void OnColorCalculationComplete() override; + // Flushes the mojo message pipe to chrome. + void FlushForTesting(); + private: FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest, BasicReparenting); FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest, @@ -208,8 +232,8 @@ WallpaperMode wallpaper_mode_; - // Wallpaper picker interface in chrome browser, used to open the picker. - mojom::WallpaperPickerPtr wallpaper_picker_; + // Client interface in chrome browser. + mojom::WallpaperControllerClientPtr wallpaper_controller_client_; // Bindings for the WallpaperController interface. mojo::BindingSet<mojom::WallpaperController> bindings_;
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 7896441..402ec30 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -624,6 +624,7 @@ "paint/paint_shader_unittest.cc", "paint/scoped_image_flags_unittest.cc", "paint/solid_color_analyzer_unittest.cc", + "paint/transfer_cache_unittest.cc", "raster/playback_image_provider_unittest.cc", "raster/raster_buffer_provider_unittest.cc", "raster/raster_source_unittest.cc",
diff --git a/cc/DEPS b/cc/DEPS index 3a09aa6..c919fc61f 100644 --- a/cc/DEPS +++ b/cc/DEPS
@@ -7,6 +7,7 @@ "+gpu/command_buffer/client/gles2_interface_stub.h", # for tests "+gpu/command_buffer/client/gpu_memory_buffer_manager.h", "+gpu/command_buffer/common/capabilities.h", + "+gpu/command_buffer/common/discardable_handle.h", "+gpu/command_buffer/common/gpu_memory_allocation.h", "+gpu/command_buffer/common/mailbox.h", "+gpu/command_buffer/common/mailbox_holder.h", @@ -50,4 +51,10 @@ "+gpu/ipc", "+gpu/skia_bindings", ], + "transfer_cache_unittest\.cc" : [ + "+gpu/command_buffer/client", + "+gpu/command_buffer/common", + "+gpu/command_buffer/service", + "+gpu/ipc", + ], }
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index fde9a89..c604daed 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -53,6 +53,8 @@ "paint_text_blob_builder.h", "paint_typeface.cc", "paint_typeface.h", + "raw_memory_transfer_cache_entry.cc", + "raw_memory_transfer_cache_entry.h", "record_paint_canvas.cc", "record_paint_canvas.h", "scoped_image_flags.cc", @@ -63,6 +65,8 @@ "skia_paint_image_generator.h", "solid_color_analyzer.cc", "solid_color_analyzer.h", + "transfer_cache_entry.cc", + "transfer_cache_entry.h", ] defines = [ "CC_PAINT_IMPLEMENTATION=1" ]
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc index 660b17b..607174e 100644 --- a/cc/paint/paint_flags.cc +++ b/cc/paint/paint_flags.cc
@@ -5,6 +5,7 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_op_buffer.h" +#include "third_party/skia/include/core/SkFlattenableSerialization.h" namespace { @@ -128,6 +129,64 @@ return PaintOp::IsValidPaintFlagsSkBlendMode(getBlendMode()); } +static bool AreFlattenablesEqual(SkFlattenable* left, SkFlattenable* right) { + sk_sp<SkData> left_data(SkValidatingSerializeFlattenable(left)); + sk_sp<SkData> right_data(SkValidatingSerializeFlattenable(right)); + if (left_data->size() != right_data->size()) + return false; + if (!left_data->equals(right_data.get())) + return false; + return true; +} + +bool PaintFlags::operator==(const PaintFlags& other) const { + // Can't just ToSkPaint and operator== here as SkPaint does pointer + // comparisons on all the ref'd skia objects on the SkPaint, which + // is not true after serialization. + if (getTextSize() != other.getTextSize()) + return false; + if (getColor() != other.getColor()) + return false; + if (getStrokeWidth() != other.getStrokeWidth()) + return false; + if (getStrokeMiter() != other.getStrokeMiter()) + return false; + if (getBlendMode() != other.getBlendMode()) + return false; + if (getStrokeCap() != other.getStrokeCap()) + return false; + if (getStrokeJoin() != other.getStrokeJoin()) + return false; + if (getStyle() != other.getStyle()) + return false; + if (getTextEncoding() != other.getTextEncoding()) + return false; + if (getHinting() != other.getHinting()) + return false; + if (getFilterQuality() != other.getFilterQuality()) + return false; + + // TODO(enne): compare typeface too + if (!AreFlattenablesEqual(getPathEffect().get(), other.getPathEffect().get())) + return false; + if (!AreFlattenablesEqual(getMaskFilter().get(), other.getMaskFilter().get())) + return false; + if (!AreFlattenablesEqual(getColorFilter().get(), + other.getColorFilter().get())) + return false; + if (!AreFlattenablesEqual(getLooper().get(), other.getLooper().get())) + return false; + if (!AreFlattenablesEqual(getImageFilter().get(), + other.getImageFilter().get())) + return false; + + if (!getShader() != !other.getShader()) + return false; + if (getShader() && *getShader() != *other.getShader()) + return false; + return true; +} + bool PaintFlags::HasDiscardableImages() const { if (!shader_) return false;
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h index 5b03d52..5e2da8f 100644 --- a/cc/paint/paint_flags.h +++ b/cc/paint/paint_flags.h
@@ -218,6 +218,8 @@ SkPaint ToSkPaint() const; bool IsValid() const; + bool operator==(const PaintFlags& other) const; + bool operator!=(const PaintFlags& other) const { return !(*this == other); } bool HasDiscardableImages() const;
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc index db04151..25ca3a3 100644 --- a/cc/paint/paint_image.cc +++ b/cc/paint/paint_image.cc
@@ -31,15 +31,29 @@ PaintImage& PaintImage::operator=(PaintImage&& other) = default; bool PaintImage::operator==(const PaintImage& other) const { - return sk_image_ == other.sk_image_ && paint_record_ == other.paint_record_ && - paint_record_rect_ == other.paint_record_rect_ && - paint_record_content_id_ == other.paint_record_content_id_ && - paint_image_generator_ == other.paint_image_generator_ && - id_ == other.id_ && animation_type_ == other.animation_type_ && - completion_state_ == other.completion_state_ && - subset_rect_ == other.subset_rect_ && - frame_index_ == other.frame_index_ && - is_multipart_ == other.is_multipart_; + if (sk_image_ != other.sk_image_) + return false; + if (paint_record_ != other.paint_record_) + return false; + if (paint_record_rect_ != other.paint_record_rect_) + return false; + if (paint_record_content_id_ != other.paint_record_content_id_) + return false; + if (paint_image_generator_ != other.paint_image_generator_) + return false; + if (id_ != other.id_) + return false; + if (animation_type_ != other.animation_type_) + return false; + if (completion_state_ != other.completion_state_) + return false; + if (subset_rect_ != other.subset_rect_) + return false; + if (frame_index_ != other.frame_index_) + return false; + if (is_multipart_ != other.is_multipart_) + return false; + return true; } // static
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index 21df1d9..5bc445b 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -106,6 +106,7 @@ PaintImage& operator=(PaintImage&& other); bool operator==(const PaintImage& other) const; + bool operator!=(const PaintImage& other) const { return !(*this == other); } // Returns the smallest size that is at least as big as the requested_size // such that we can decode to exactly that scale. If the requested size is
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index c0004b2..6f75cc7 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -16,6 +16,7 @@ #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRegion.h" +#include "third_party/skia/include/core/SkWriteBuffer.h" namespace cc { namespace { @@ -157,6 +158,11 @@ TYPES(M)}; #undef M +using EqualsFunction = bool (*)(const PaintOp* left, const PaintOp* right); +#define M(T) &T::AreEqual, +static const EqualsFunction g_equals_operator[kNumOpTypes] = {TYPES(M)}; +#undef M + // Most state ops (matrix, clip, save, restore) have a trivial destructor. // TODO(enne): evaluate if we need the nullptr optimization or if // we even need to differentiate trivial destructors here. @@ -1205,6 +1211,366 @@ canvas->translate(op->dx, op->dy); } +static bool AreSkMatricesEqual(const SkMatrix& left, const SkMatrix& right) { + // Compare the 3x3 matrix values. + if (left != right) + return false; + + // If a serialized matrix says it is identity, then the original must have + // those values, as the serialization process clobbers the matrix values. + if (left.isIdentity()) { + if (SkMatrix::I() != left) + return false; + if (SkMatrix::I() != right) + return false; + } + + if (left.getType() != right.getType()) + return false; + + return true; +} + +bool AnnotateOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const AnnotateOp*>(base_left); + auto* right = static_cast<const AnnotateOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->annotation_type != right->annotation_type) + return false; + if (left->rect != right->rect) + return false; + if (!left->data != !right->data) + return false; + if (left->data) { + if (left->data->size() != right->data->size()) + return false; + if (0 != + memcmp(left->data->data(), right->data->data(), right->data->size())) + return false; + } + return true; +} + +bool ClipPathOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const ClipPathOp*>(base_left); + auto* right = static_cast<const ClipPathOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->path != right->path) + return false; + if (left->op != right->op) + return false; + if (left->antialias != right->antialias) + return false; + return true; +} + +bool ClipRectOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const ClipRectOp*>(base_left); + auto* right = static_cast<const ClipRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->rect != right->rect) + return false; + if (left->op != right->op) + return false; + if (left->antialias != right->antialias) + return false; + return true; +} + +bool ClipRRectOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const ClipRRectOp*>(base_left); + auto* right = static_cast<const ClipRRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->rrect != right->rrect) + return false; + if (left->op != right->op) + return false; + if (left->antialias != right->antialias) + return false; + return true; +} + +bool ConcatOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const ConcatOp*>(base_left); + auto* right = static_cast<const ConcatOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + return AreSkMatricesEqual(left->matrix, right->matrix); +} + +bool DrawColorOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawColorOp*>(base_left); + auto* right = static_cast<const DrawColorOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + return left->color == right->color; +} + +bool DrawDRRectOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawDRRectOp*>(base_left); + auto* right = static_cast<const DrawDRRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->outer != right->outer) + return false; + if (left->inner != right->inner) + return false; + return true; +} + +bool DrawImageOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawImageOp*>(base_left); + auto* right = static_cast<const DrawImageOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + // TODO(enne): Test PaintImage equality once implemented + if (left->left != right->left) + return false; + if (left->top != right->top) + return false; + return true; +} + +bool DrawImageRectOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawImageRectOp*>(base_left); + auto* right = static_cast<const DrawImageRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + // TODO(enne): Test PaintImage equality once implemented + if (left->src != right->src) + return false; + if (left->dst != right->dst) + return false; + return true; +} + +bool DrawIRectOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawIRectOp*>(base_left); + auto* right = static_cast<const DrawIRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->rect != right->rect) + return false; + return true; +} + +bool DrawLineOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const DrawLineOp*>(base_left); + auto* right = static_cast<const DrawLineOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->x0 != right->x0) + return false; + if (left->y0 != right->y0) + return false; + if (left->x1 != right->x1) + return false; + if (left->y1 != right->y1) + return false; + return true; +} + +bool DrawOvalOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const DrawOvalOp*>(base_left); + auto* right = static_cast<const DrawOvalOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->oval != right->oval) + return false; + return true; +} + +bool DrawPathOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const DrawPathOp*>(base_left); + auto* right = static_cast<const DrawPathOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->path != right->path) + return false; + return true; +} + +bool DrawRecordOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawRecordOp*>(base_left); + auto* right = static_cast<const DrawRecordOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (!left->record != !right->record) + return false; + if (*left->record != *right->record) + return false; + return true; +} + +bool DrawRectOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const DrawRectOp*>(base_left); + auto* right = static_cast<const DrawRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->rect != right->rect) + return false; + return true; +} + +bool DrawRRectOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawRRectOp*>(base_left); + auto* right = static_cast<const DrawRRectOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->rrect != right->rrect) + return false; + return true; +} + +bool DrawTextBlobOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const DrawTextBlobOp*>(base_left); + auto* right = static_cast<const DrawTextBlobOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->x != right->x) + return false; + if (left->y != right->y) + return false; + + DCHECK(*left->blob); + DCHECK(*right->blob); + + SkBinaryWriteBuffer left_flattened; + left->blob->ToSkTextBlob()->flatten(left_flattened); + std::vector<char> left_mem(left_flattened.bytesWritten()); + left_flattened.writeToMemory(left_mem.data()); + + SkBinaryWriteBuffer right_flattened; + right->blob->ToSkTextBlob()->flatten(right_flattened); + std::vector<char> right_mem(right_flattened.bytesWritten()); + right_flattened.writeToMemory(right_mem.data()); + + if (left_mem.size() != right_mem.size()) + return false; + if (left_mem != right_mem) + return false; + return true; +} + +bool NoopOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + return true; +} + +bool RestoreOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + return true; +} + +bool RotateOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const RotateOp*>(base_left); + auto* right = static_cast<const RotateOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->degrees != right->degrees) + return false; + return true; +} + +bool SaveOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + return true; +} + +bool SaveLayerOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const SaveLayerOp*>(base_left); + auto* right = static_cast<const SaveLayerOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->flags != right->flags) + return false; + if (left->bounds != right->bounds) + return false; + return true; +} + +bool SaveLayerAlphaOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const SaveLayerAlphaOp*>(base_left); + auto* right = static_cast<const SaveLayerAlphaOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->bounds != right->bounds) + return false; + if (left->alpha != right->alpha) + return false; + if (left->preserve_lcd_text_requests != right->preserve_lcd_text_requests) + return false; + return true; +} + +bool ScaleOp::AreEqual(const PaintOp* base_left, const PaintOp* base_right) { + auto* left = static_cast<const ScaleOp*>(base_left); + auto* right = static_cast<const ScaleOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->sx != right->sx) + return false; + if (left->sy != right->sy) + return false; + return true; +} + +bool SetMatrixOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const SetMatrixOp*>(base_left); + auto* right = static_cast<const SetMatrixOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (!AreSkMatricesEqual(left->matrix, right->matrix)) + return false; + return true; +} + +bool TranslateOp::AreEqual(const PaintOp* base_left, + const PaintOp* base_right) { + auto* left = static_cast<const TranslateOp*>(base_left); + auto* right = static_cast<const TranslateOp*>(base_right); + DCHECK(left->IsValid()); + DCHECK(right->IsValid()); + if (left->dx != right->dx) + return false; + if (left->dy != right->dy) + return false; + return true; +} + bool PaintOp::IsDrawOp() const { return g_is_draw_op[type]; } @@ -1213,6 +1579,12 @@ return g_has_paint_flags[type]; } +bool PaintOp::operator==(const PaintOp& other) const { + if (GetType() != other.GetType()) + return false; + return g_equals_operator[type](this, &other); +} + void PaintOp::Raster(SkCanvas* canvas, const PlaybackParams& params) const { g_raster_functions[type](this, canvas, params); } @@ -1827,4 +2199,29 @@ } } +bool PaintOpBuffer::operator==(const PaintOpBuffer& other) const { + if (op_count_ != other.op_count_) + return false; + if (num_slow_paths_ != other.num_slow_paths_) + return false; + if (subrecord_bytes_used_ != other.subrecord_bytes_used_) + return false; + if (has_non_aa_paint_ != other.has_non_aa_paint_) + return false; + if (has_discardable_images_ != other.has_discardable_images_) + return false; + + auto left_iter = Iterator(this); + auto right_iter = Iterator(&other); + + for (; left_iter != left_iter.end(); ++left_iter, ++right_iter) { + if (**left_iter != **right_iter) + return false; + } + + DCHECK(left_iter == left_iter.end()); + DCHECK(right_iter == right_iter.end()); + return true; +} + } // namespace cc
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index 93861eb..d0aa90d 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -110,7 +110,9 @@ void Raster(SkCanvas* canvas, const PlaybackParams& params) const; bool IsDrawOp() const; bool IsPaintOpWithFlags() const; - bool IsValid() const; + + bool operator==(const PaintOp& other) const; + bool operator!=(const PaintOp& other) const { return !(*this == other); } struct CC_PAINT_EXPORT SerializeOptions { SerializeOptions(); @@ -246,6 +248,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return rect.isFinite(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); PaintCanvas::AnnotationType annotation_type; @@ -265,6 +268,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return IsValidSkClipOp(op) && IsValidPath(path); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); int CountSlowPaths() const; bool HasNonAAPaint() const { return !antialias; } HAS_SERIALIZATION_FUNCTIONS(); @@ -286,6 +290,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return IsValidSkClipOp(op) && rect.isFinite(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkRect rect; @@ -302,6 +307,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return IsValidSkClipOp(op) && rrect.isValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasNonAAPaint() const { return !antialias; } HAS_SERIALIZATION_FUNCTIONS(); @@ -318,6 +324,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; @@ -333,6 +340,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return IsValidDrawColorSkBlendMode(mode); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkColor color; @@ -354,6 +362,7 @@ bool IsValid() const { return flags.IsValid() && outer.isValid() && inner.isValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkRRect outer; @@ -377,6 +386,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasDiscardableImages() const; bool HasNonAAPaint() const { return false; } HAS_SERIALIZATION_FUNCTIONS(); @@ -406,6 +416,7 @@ bool IsValid() const { return flags.IsValid() && src.isFinite() && dst.isFinite(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasDiscardableImages() const; HAS_SERIALIZATION_FUNCTIONS(); @@ -429,6 +440,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasNonAAPaint() const { return false; } HAS_SERIALIZATION_FUNCTIONS(); @@ -453,6 +465,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); int CountSlowPaths() const; @@ -477,6 +490,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid() && oval.isFinite(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkRect oval; @@ -496,6 +510,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid() && IsValidPath(path); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); int CountSlowPaths() const; HAS_SERIALIZATION_FUNCTIONS(); @@ -515,6 +530,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); size_t AdditionalBytesUsed() const; bool HasDiscardableImages() const; int CountSlowPaths() const; @@ -535,6 +551,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid() && rect.isFinite(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkRect rect; @@ -554,6 +571,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid() && rrect.isValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkRRect rrect; @@ -576,6 +594,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid(); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); scoped_refptr<PaintTextBlob> blob; @@ -594,6 +613,7 @@ SkCanvas* canvas, const PlaybackParams& params) {} bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); }; @@ -605,6 +625,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); }; @@ -616,6 +637,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkScalar degrees; @@ -629,6 +651,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); }; @@ -643,6 +666,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return flags.IsValid() && IsValidOrUnsetRect(bounds); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); bool HasNonAAPaint() const { return false; } HAS_SERIALIZATION_FUNCTIONS(); @@ -666,6 +690,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return IsValidOrUnsetRect(bounds); } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkRect bounds; @@ -681,6 +706,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkScalar sx; @@ -705,6 +731,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; @@ -718,6 +745,7 @@ SkCanvas* canvas, const PlaybackParams& params); bool IsValid() const { return true; } + static bool AreEqual(const PaintOp* left, const PaintOp* right); HAS_SERIALIZATION_FUNCTIONS(); SkScalar dx; @@ -772,6 +800,11 @@ bool HasNonAAPaint() const { return has_non_aa_paint_; } bool HasDiscardableImages() const { return has_discardable_images_; } + bool operator==(const PaintOpBuffer& other) const; + bool operator!=(const PaintOpBuffer& other) const { + return !(*this == other); + } + // Resize the PaintOpBuffer to exactly fit the current amount of used space. void ShrinkToFit();
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index fa5bc1f..27691439 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -13,6 +13,7 @@ #include "cc/paint/paint_op_reader.h" #include "cc/paint/paint_op_writer.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/paint_op_helper.h" #include "cc/test/skia_common.h" #include "cc/test/test_skcanvas.h" #include "testing/gtest/include/gtest/gtest.h" @@ -46,80 +47,6 @@ class PaintOpSerializationTestUtils { public: - static void ExpectFlattenableEqual(SkFlattenable* expected, - SkFlattenable* actual) { - sk_sp<SkData> expected_data(SkValidatingSerializeFlattenable(expected)); - sk_sp<SkData> actual_data(SkValidatingSerializeFlattenable(actual)); - ASSERT_EQ(expected_data->size(), actual_data->size()); - EXPECT_TRUE(expected_data->equals(actual_data.get())); - } - - static void ExpectPaintShadersEqual(const PaintShader* one, - const PaintShader* two) { - if (!one) { - EXPECT_FALSE(two); - return; - } - - ASSERT_TRUE(one); - ASSERT_TRUE(two); - - EXPECT_EQ(one->shader_type_, two->shader_type_); - EXPECT_EQ(one->flags_, two->flags_); - EXPECT_EQ(one->end_radius_, two->end_radius_); - EXPECT_EQ(one->start_radius_, two->start_radius_); - EXPECT_EQ(one->tx_, two->tx_); - EXPECT_EQ(one->ty_, two->ty_); - EXPECT_EQ(one->fallback_color_, two->fallback_color_); - EXPECT_EQ(one->scaling_behavior_, two->scaling_behavior_); - if (one->local_matrix_) { - EXPECT_TRUE(two->local_matrix_.has_value()); - EXPECT_TRUE(*one->local_matrix_ == *two->local_matrix_); - } else { - EXPECT_FALSE(two->local_matrix_.has_value()); - } - EXPECT_EQ(one->center_, two->center_); - EXPECT_EQ(one->tile_, two->tile_); - EXPECT_EQ(one->start_point_, two->start_point_); - EXPECT_EQ(one->end_point_, two->end_point_); - EXPECT_EQ(one->start_degrees_, two->start_degrees_); - EXPECT_EQ(one->end_degrees_, two->end_degrees_); - EXPECT_THAT(one->colors_, testing::ElementsAreArray(two->colors_)); - EXPECT_THAT(one->positions_, testing::ElementsAreArray(two->positions_)); - } - - static void ExpectPaintFlagsEqual(const PaintFlags& expected, - const PaintFlags& actual) { - // Can't just ToSkPaint and operator== here as SkPaint does pointer - // comparisons on all the ref'd skia objects on the SkPaint, which - // is not true after serialization. - EXPECT_EQ(expected.getTextSize(), actual.getTextSize()); - EXPECT_EQ(expected.getColor(), actual.getColor()); - EXPECT_EQ(expected.getStrokeWidth(), actual.getStrokeWidth()); - EXPECT_EQ(expected.getStrokeMiter(), actual.getStrokeMiter()); - EXPECT_EQ(expected.getBlendMode(), actual.getBlendMode()); - EXPECT_EQ(expected.getStrokeCap(), actual.getStrokeCap()); - EXPECT_EQ(expected.getStrokeJoin(), actual.getStrokeJoin()); - EXPECT_EQ(expected.getStyle(), actual.getStyle()); - EXPECT_EQ(expected.getTextEncoding(), actual.getTextEncoding()); - EXPECT_EQ(expected.getHinting(), actual.getHinting()); - EXPECT_EQ(expected.getFilterQuality(), actual.getFilterQuality()); - - // TODO(enne): compare typeface too - ExpectFlattenableEqual(expected.getPathEffect().get(), - actual.getPathEffect().get()); - ExpectFlattenableEqual(expected.getMaskFilter().get(), - actual.getMaskFilter().get()); - ExpectFlattenableEqual(expected.getColorFilter().get(), - actual.getColorFilter().get()); - ExpectFlattenableEqual(expected.getLooper().get(), - actual.getLooper().get()); - ExpectFlattenableEqual(expected.getImageFilter().get(), - actual.getImageFilter().get()); - - ExpectPaintShadersEqual(expected.getShader(), actual.getShader()); - } - static void FillArbitraryShaderValues(PaintShader* shader, bool use_matrix) { shader->shader_type_ = PaintShader::Type::kTwoPointConicalGradient; shader->flags_ = 12345; @@ -190,8 +117,7 @@ ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer); SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter); EXPECT_EQ(save_op->bounds, rect_); - PaintOpSerializationTestUtils::ExpectPaintFlagsEqual(save_op->flags, - flags_); + EXPECT_EQ(save_op->flags, flags_); ++iter; ASSERT_EQ(iter->GetType(), PaintOpType::Save); @@ -237,7 +163,6 @@ // Original should be empty, and safe to destruct. EXPECT_EQ(original.size(), 0u); EXPECT_EQ(original.bytes_used(), sizeof(PaintOpBuffer)); - EXPECT_EQ(PaintOpBuffer::Iterator(&original), false); } TEST_F(PaintOpAppendTest, MoveThenDestructOperatorEq) { @@ -264,6 +189,7 @@ // Should be possible to reappend to the original and get the same result. PushOps(&original); VerifyOps(&original); + EXPECT_EQ(original, destination); } TEST_F(PaintOpAppendTest, MoveThenReappendOperatorEq) { @@ -276,6 +202,7 @@ // Should be possible to reappend to the original and get the same result. PushOps(&original); VerifyOps(&original); + EXPECT_EQ(original, destination); } // Verify that a SaveLayerAlpha / Draw / Restore can be optimized to just @@ -1628,242 +1555,6 @@ ValidateOps<TranslateOp>(buffer); } -void CompareFlags(const PaintFlags& original, const PaintFlags& written) { - PaintOpSerializationTestUtils::ExpectPaintFlagsEqual(original, written); -} - -void CompareImages(const PaintImage& original, const PaintImage& written) {} - -void CompareMatrices(const SkMatrix& original, const SkMatrix& written) { - // Compare the 3x3 matrix values. - EXPECT_EQ(original, written); - - // If a serialized matrix says it is identity, then the original must have - // those values, as the serialization process clobbers the matrix values. - if (original.isIdentity()) { - EXPECT_EQ(SkMatrix::I(), original); - EXPECT_EQ(SkMatrix::I(), written); - } - - EXPECT_EQ(original.getType(), written.getType()); -} - -void CompareAnnotateOp(const AnnotateOp* original, const AnnotateOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->annotation_type, written->annotation_type); - EXPECT_EQ(original->rect, written->rect); - EXPECT_EQ(!!original->data, !!written->data); - if (original->data) { - EXPECT_EQ(original->data->size(), written->data->size()); - EXPECT_EQ(0, memcmp(original->data->data(), written->data->data(), - written->data->size())); - } -} - -void CompareClipPathOp(const ClipPathOp* original, const ClipPathOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_TRUE(original->path == written->path); - EXPECT_EQ(original->op, written->op); - EXPECT_EQ(original->antialias, written->antialias); -} - -void CompareClipRectOp(const ClipRectOp* original, const ClipRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->rect, written->rect); - EXPECT_EQ(original->op, written->op); - EXPECT_EQ(original->antialias, written->antialias); -} - -void CompareClipRRectOp(const ClipRRectOp* original, - const ClipRRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->rrect, written->rrect); - EXPECT_EQ(original->op, written->op); - EXPECT_EQ(original->antialias, written->antialias); -} - -void CompareConcatOp(const ConcatOp* original, const ConcatOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareMatrices(original->matrix, written->matrix); -} - -void CompareDrawColorOp(const DrawColorOp* original, - const DrawColorOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->color, written->color); -} - -void CompareDrawDRRectOp(const DrawDRRectOp* original, - const DrawDRRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->outer, written->outer); - EXPECT_EQ(original->inner, written->inner); -} - -void CompareDrawImageOp(const DrawImageOp* original, - const DrawImageOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - CompareImages(original->image, written->image); - EXPECT_EQ(original->left, written->left); - EXPECT_EQ(original->top, written->top); -} - -void CompareDrawImageRectOp(const DrawImageRectOp* original, - const DrawImageRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - CompareImages(original->image, written->image); - EXPECT_EQ(original->src, written->src); - EXPECT_EQ(original->dst, written->dst); -} - -void CompareDrawIRectOp(const DrawIRectOp* original, - const DrawIRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->rect, written->rect); -} - -void CompareDrawLineOp(const DrawLineOp* original, const DrawLineOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->x0, written->x0); - EXPECT_EQ(original->y0, written->y0); - EXPECT_EQ(original->x1, written->x1); - EXPECT_EQ(original->y1, written->y1); -} - -void CompareDrawOvalOp(const DrawOvalOp* original, const DrawOvalOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->oval, written->oval); -} - -void CompareDrawPathOp(const DrawPathOp* original, const DrawPathOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_TRUE(original->path == written->path); -} - -void CompareDrawRectOp(const DrawRectOp* original, const DrawRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->rect, written->rect); -} - -void CompareDrawRRectOp(const DrawRRectOp* original, - const DrawRRectOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->rrect, written->rrect); -} - -void CompareDrawTextBlobOp(const DrawTextBlobOp* original, - const DrawTextBlobOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->x, written->x); - EXPECT_EQ(original->y, written->y); - - ASSERT_TRUE(*original->blob); - ASSERT_TRUE(*written->blob); - - SkBinaryWriteBuffer original_flattened; - original->blob->ToSkTextBlob()->flatten(original_flattened); - std::vector<char> original_mem(original_flattened.bytesWritten()); - original_flattened.writeToMemory(original_mem.data()); - - SkBinaryWriteBuffer written_flattened; - written->blob->ToSkTextBlob()->flatten(written_flattened); - std::vector<char> written_mem(written_flattened.bytesWritten()); - written_flattened.writeToMemory(written_mem.data()); - - ASSERT_EQ(original_mem.size(), written_mem.size()); - EXPECT_EQ(original_mem, written_mem); -} - -void CompareNoopOp(const NoopOp* original, const NoopOp* written) { - // Nothing to compare. - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); -} - -void CompareRestoreOp(const RestoreOp* original, const RestoreOp* written) { - // Nothing to compare. - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); -} - -void CompareRotateOp(const RotateOp* original, const RotateOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->degrees, written->degrees); -} - -void CompareSaveOp(const SaveOp* original, const SaveOp* written) { - // Nothing to compare. - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); -} - -void CompareSaveLayerOp(const SaveLayerOp* original, - const SaveLayerOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareFlags(original->flags, written->flags); - EXPECT_EQ(original->bounds, written->bounds); -} - -void CompareSaveLayerAlphaOp(const SaveLayerAlphaOp* original, - const SaveLayerAlphaOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->bounds, written->bounds); - EXPECT_EQ(original->alpha, written->alpha); - EXPECT_EQ(original->preserve_lcd_text_requests, - written->preserve_lcd_text_requests); -} - -void CompareScaleOp(const ScaleOp* original, const ScaleOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->sx, written->sx); - EXPECT_EQ(original->sy, written->sy); -} - -void CompareSetMatrixOp(const SetMatrixOp* original, - const SetMatrixOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - CompareMatrices(original->matrix, written->matrix); -} - -void CompareTranslateOp(const TranslateOp* original, - const TranslateOp* written) { - EXPECT_TRUE(original->IsValid()); - EXPECT_TRUE(written->IsValid()); - EXPECT_EQ(original->dx, written->dx); - EXPECT_EQ(original->dy, written->dy); -} - class PaintOpSerializationTest : public ::testing::TestWithParam<uint8_t> { public: PaintOpType GetParamType() const { @@ -1953,119 +1644,6 @@ } } - static void ExpectOpsEqual(const PaintOp* original, const PaintOp* written) { - ASSERT_TRUE(original); - ASSERT_TRUE(written); - ASSERT_EQ(original->GetType(), written->GetType()); - EXPECT_EQ(original->skip, written->skip); - - switch (original->GetType()) { - case PaintOpType::Annotate: - CompareAnnotateOp(static_cast<const AnnotateOp*>(original), - static_cast<const AnnotateOp*>(written)); - break; - case PaintOpType::ClipPath: - CompareClipPathOp(static_cast<const ClipPathOp*>(original), - static_cast<const ClipPathOp*>(written)); - break; - case PaintOpType::ClipRect: - CompareClipRectOp(static_cast<const ClipRectOp*>(original), - static_cast<const ClipRectOp*>(written)); - break; - case PaintOpType::ClipRRect: - CompareClipRRectOp(static_cast<const ClipRRectOp*>(original), - static_cast<const ClipRRectOp*>(written)); - break; - case PaintOpType::Concat: - CompareConcatOp(static_cast<const ConcatOp*>(original), - static_cast<const ConcatOp*>(written)); - break; - case PaintOpType::DrawColor: - CompareDrawColorOp(static_cast<const DrawColorOp*>(original), - static_cast<const DrawColorOp*>(written)); - break; - case PaintOpType::DrawDRRect: - CompareDrawDRRectOp(static_cast<const DrawDRRectOp*>(original), - static_cast<const DrawDRRectOp*>(written)); - break; - case PaintOpType::DrawImage: - CompareDrawImageOp(static_cast<const DrawImageOp*>(original), - static_cast<const DrawImageOp*>(written)); - break; - case PaintOpType::DrawImageRect: - CompareDrawImageRectOp(static_cast<const DrawImageRectOp*>(original), - static_cast<const DrawImageRectOp*>(written)); - break; - case PaintOpType::DrawIRect: - CompareDrawIRectOp(static_cast<const DrawIRectOp*>(original), - static_cast<const DrawIRectOp*>(written)); - break; - case PaintOpType::DrawLine: - CompareDrawLineOp(static_cast<const DrawLineOp*>(original), - static_cast<const DrawLineOp*>(written)); - break; - case PaintOpType::DrawOval: - CompareDrawOvalOp(static_cast<const DrawOvalOp*>(original), - static_cast<const DrawOvalOp*>(written)); - break; - case PaintOpType::DrawPath: - CompareDrawPathOp(static_cast<const DrawPathOp*>(original), - static_cast<const DrawPathOp*>(written)); - break; - case PaintOpType::DrawRecord: - // Not supported. - break; - case PaintOpType::DrawRect: - CompareDrawRectOp(static_cast<const DrawRectOp*>(original), - static_cast<const DrawRectOp*>(written)); - break; - case PaintOpType::DrawRRect: - CompareDrawRRectOp(static_cast<const DrawRRectOp*>(original), - static_cast<const DrawRRectOp*>(written)); - break; - case PaintOpType::DrawTextBlob: - CompareDrawTextBlobOp(static_cast<const DrawTextBlobOp*>(original), - static_cast<const DrawTextBlobOp*>(written)); - break; - case PaintOpType::Noop: - CompareNoopOp(static_cast<const NoopOp*>(original), - static_cast<const NoopOp*>(written)); - break; - case PaintOpType::Restore: - CompareRestoreOp(static_cast<const RestoreOp*>(original), - static_cast<const RestoreOp*>(written)); - break; - case PaintOpType::Rotate: - CompareRotateOp(static_cast<const RotateOp*>(original), - static_cast<const RotateOp*>(written)); - break; - case PaintOpType::Save: - CompareSaveOp(static_cast<const SaveOp*>(original), - static_cast<const SaveOp*>(written)); - break; - case PaintOpType::SaveLayer: - CompareSaveLayerOp(static_cast<const SaveLayerOp*>(original), - static_cast<const SaveLayerOp*>(written)); - break; - case PaintOpType::SaveLayerAlpha: - CompareSaveLayerAlphaOp(static_cast<const SaveLayerAlphaOp*>(original), - static_cast<const SaveLayerAlphaOp*>(written)); - break; - case PaintOpType::Scale: - CompareScaleOp(static_cast<const ScaleOp*>(original), - static_cast<const ScaleOp*>(written)); - break; - case PaintOpType::SetMatrix: - CompareSetMatrixOp(static_cast<const SetMatrixOp*>(original), - static_cast<const SetMatrixOp*>(written)); - break; - case PaintOpType::Translate: - CompareTranslateOp(static_cast<const TranslateOp*>(original), - static_cast<const TranslateOp*>(written)); - break; - } - } - void ResizeOutputBuffer() { // An arbitrary deserialization buffer size that should fit all the ops // in the buffer_. @@ -2118,7 +1696,7 @@ DeserializerIterator(output_.get(), serializer.TotalBytesWritten())) { SCOPED_TRACE(base::StringPrintf( "%s #%zu", PaintOpTypeToString(GetParamType()).c_str(), i)); - ExpectOpsEqual(*iter, base_written); + EXPECT_EQ(**iter, *base_written); ++iter; ++i; } @@ -2296,7 +1874,7 @@ // Root buffer. ASSERT_EQ(op->GetType(), (*serialized_iter)->GetType()) << PaintOpTypeToString(op->GetType()); - PaintOpSerializationTest::ExpectOpsEqual(op, *serialized_iter); + EXPECT_EQ(*op, **serialized_iter); ++serialized_iter; continue; } @@ -2384,7 +1962,7 @@ if (i == 6) { // Buffer. - PaintOpSerializationTest::ExpectOpsEqual(op, buffer.GetFirstOp()); + EXPECT_EQ(*op, *buffer.GetFirstOp()); continue; } @@ -2431,7 +2009,7 @@ // Nested buffer. ASSERT_EQ(op->GetType(), (*serialized_iter)->GetType()) << PaintOpTypeToString(op->GetType()); - PaintOpSerializationTest::ExpectOpsEqual(op, *serialized_iter); + EXPECT_EQ(*op, **serialized_iter); ++serialized_iter; continue; } @@ -2481,7 +2059,7 @@ // Root buffer. ASSERT_EQ(op->GetType(), (*serialized_iter)->GetType()) << PaintOpTypeToString(op->GetType()); - PaintOpSerializationTest::ExpectOpsEqual(op, *serialized_iter); + EXPECT_EQ(*op, **serialized_iter); ++serialized_iter; continue; }
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc index 0904ad0..e5610e620 100644 --- a/cc/paint/paint_shader.cc +++ b/cc/paint/paint_shader.cc
@@ -394,4 +394,53 @@ return false; } +bool PaintShader::operator==(const PaintShader& other) const { + if (shader_type_ != other.shader_type_) + return false; + if (flags_ != other.flags_) + return false; + if (end_radius_ != other.end_radius_) + return false; + if (start_radius_ != other.start_radius_) + return false; + if (tx_ != other.tx_) + return false; + if (ty_ != other.ty_) + return false; + if (fallback_color_ != other.fallback_color_) + return false; + if (scaling_behavior_ != other.scaling_behavior_) + return false; + if (local_matrix_) { + if (!other.local_matrix_.has_value()) + return false; + if (*local_matrix_ != *other.local_matrix_) + return false; + } else { + if (other.local_matrix_.has_value()) + return false; + } + if (center_ != other.center_) + return false; + if (tile_ != other.tile_) + return false; + if (start_point_ != other.start_point_) + return false; + if (end_point_ != other.end_point_) + return false; + if (start_degrees_ != other.start_degrees_) + return false; + if (end_degrees_ != other.end_degrees_) + return false; + + // TODO(enne): add comparison of records once those are serialized. + // TODO(enne): add comparison of images once those are serialized. + + if (colors_ != other.colors_) + return false; + if (positions_ != other.positions_) + return false; + return true; +} + } // namespace cc
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h index 0c76dde..6c72074 100644 --- a/cc/paint/paint_shader.h +++ b/cc/paint/paint_shader.h
@@ -126,6 +126,9 @@ // shader is correct is hard. bool IsValid() const; + bool operator==(const PaintShader& other) const; + bool operator!=(const PaintShader& other) const { return !(*this == other); } + private: friend class PaintFlags; friend class PaintOpReader;
diff --git a/cc/paint/raw_memory_transfer_cache_entry.cc b/cc/paint/raw_memory_transfer_cache_entry.cc new file mode 100644 index 0000000..302cf0d --- /dev/null +++ b/cc/paint/raw_memory_transfer_cache_entry.cc
@@ -0,0 +1,52 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/raw_memory_transfer_cache_entry.h" + +namespace cc { + +ClientRawMemoryTransferCacheEntry::ClientRawMemoryTransferCacheEntry( + std::vector<uint8_t> data) + : data_(std::move(data)) {} +ClientRawMemoryTransferCacheEntry::~ClientRawMemoryTransferCacheEntry() = + default; + +TransferCacheEntryType ClientRawMemoryTransferCacheEntry::Type() const { + return TransferCacheEntryType::kRawMemory; +} + +size_t ClientRawMemoryTransferCacheEntry::SerializedSize() const { + return data_.size(); +} + +bool ClientRawMemoryTransferCacheEntry::Serialize(size_t size, + uint8_t* data) const { + if (size != data_.size()) + return false; + + memcpy(data, data_.data(), size); + return true; +} + +ServiceRawMemoryTransferCacheEntry::ServiceRawMemoryTransferCacheEntry() = + default; +ServiceRawMemoryTransferCacheEntry::~ServiceRawMemoryTransferCacheEntry() = + default; + +TransferCacheEntryType ServiceRawMemoryTransferCacheEntry::Type() const { + return TransferCacheEntryType::kRawMemory; +} + +size_t ServiceRawMemoryTransferCacheEntry::Size() const { + return data_.size(); +} + +bool ServiceRawMemoryTransferCacheEntry::Deserialize(size_t size, + uint8_t* data) { + data_.resize(size); + memcpy(data_.data(), data, size); + return true; +} + +} // namespace cc
diff --git a/cc/paint/raw_memory_transfer_cache_entry.h b/cc/paint/raw_memory_transfer_cache_entry.h new file mode 100644 index 0000000..6180332 --- /dev/null +++ b/cc/paint/raw_memory_transfer_cache_entry.h
@@ -0,0 +1,46 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_RAW_MEMORY_TRANSFER_CACHE_ENTRY_H_ +#define CC_PAINT_RAW_MEMORY_TRANSFER_CACHE_ENTRY_H_ + +#include <vector> + +#include "cc/paint/transfer_cache_entry.h" + +namespace cc { + +// Client/ServiceRawMemoryTransferCacheEntry implement a transfer cache entry +// backed by raw memory, with no conversion during serialization or +// deserialization. +class CC_PAINT_EXPORT ClientRawMemoryTransferCacheEntry + : public ClientTransferCacheEntry { + public: + explicit ClientRawMemoryTransferCacheEntry(std::vector<uint8_t> data); + ~ClientRawMemoryTransferCacheEntry() override; + TransferCacheEntryType Type() const override; + size_t SerializedSize() const override; + bool Serialize(size_t size, uint8_t* data) const override; + + private: + std::vector<uint8_t> data_; +}; + +class CC_PAINT_EXPORT ServiceRawMemoryTransferCacheEntry + : public ServiceTransferCacheEntry { + public: + ServiceRawMemoryTransferCacheEntry(); + ~ServiceRawMemoryTransferCacheEntry() override; + TransferCacheEntryType Type() const override; + size_t Size() const override; + bool Deserialize(size_t size, uint8_t* data) override; + const std::vector<uint8_t>& data() { return data_; } + + private: + std::vector<uint8_t> data_; +}; + +} // namespace cc + +#endif // CC_PAINT_RAW_MEMORY_TRANSFER_CACHE_ENTRY_H_
diff --git a/cc/paint/transfer_cache_entry.cc b/cc/paint/transfer_cache_entry.cc new file mode 100644 index 0000000..c68a905 --- /dev/null +++ b/cc/paint/transfer_cache_entry.cc
@@ -0,0 +1,34 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/transfer_cache_entry.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "cc/paint/raw_memory_transfer_cache_entry.h" + +namespace cc { + +std::unique_ptr<ServiceTransferCacheEntry> ServiceTransferCacheEntry::Create( + TransferCacheEntryType type) { + switch (type) { + case TransferCacheEntryType::kRawMemory: + return base::MakeUnique<ServiceRawMemoryTransferCacheEntry>(); + } + + NOTREACHED(); + return nullptr; +} + +bool ServiceTransferCacheEntry::SafeConvertToType( + uint32_t raw_type, + TransferCacheEntryType* type) { + if (raw_type > static_cast<uint32_t>(TransferCacheEntryType::kLast)) + return false; + + *type = static_cast<TransferCacheEntryType>(raw_type); + return true; +} + +} // namespace cc
diff --git a/cc/paint/transfer_cache_entry.h b/cc/paint/transfer_cache_entry.h new file mode 100644 index 0000000..ca281a2 --- /dev/null +++ b/cc/paint/transfer_cache_entry.h
@@ -0,0 +1,57 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_TRANSFER_CACHE_ENTRY_H_ +#define CC_PAINT_TRANSFER_CACHE_ENTRY_H_ + +#include <memory> + +#include "cc/paint/paint_export.h" + +namespace cc { + +// To add a new transfer cache entry type: +// - Add a type name to the TransferCacheEntryType enum. +// - Implement a ClientTransferCacheEntry and ServiceTransferCacheEntry for +// your new type. +// - Update ServiceTransferCacheEntry::Create and ServiceTransferCacheEntry:: +// DeduceType in transfer_cache_entry.cc. +enum class TransferCacheEntryType : uint32_t { + kRawMemory, + // Add new entries above this line, make sure to update kLast. + kLast = kRawMemory, +}; + +// An interface used on the client to serialize a transfer cache entry +// into raw bytes that can be sent to the service. +class CC_PAINT_EXPORT ClientTransferCacheEntry { + public: + virtual ~ClientTransferCacheEntry() {} + virtual TransferCacheEntryType Type() const = 0; + virtual size_t SerializedSize() const = 0; + virtual bool Serialize(size_t size, uint8_t* data) const = 0; +}; + +// An interface which receives the raw data sent by the client and +// deserializes it into the appropriate service-side object. +class CC_PAINT_EXPORT ServiceTransferCacheEntry { + public: + static std::unique_ptr<ServiceTransferCacheEntry> Create( + TransferCacheEntryType type); + + // Checks that |raw_type| represents a valid TransferCacheEntryType and + // populates |type|. If |raw_type| is not valid, the function returns false + // and |type| is not modified. + static bool SafeConvertToType(uint32_t raw_type, + TransferCacheEntryType* type); + + virtual ~ServiceTransferCacheEntry() {} + virtual TransferCacheEntryType Type() const = 0; + virtual size_t Size() const = 0; + virtual bool Deserialize(size_t size, uint8_t* data) = 0; +}; + +}; // namespace cc + +#endif // CC_PAINT_TRANSFER_CACHE_ENTRY_H_
diff --git a/cc/paint/transfer_cache_unittest.cc b/cc/paint/transfer_cache_unittest.cc new file mode 100644 index 0000000..20833e8 --- /dev/null +++ b/cc/paint/transfer_cache_unittest.cc
@@ -0,0 +1,212 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#include "base/threading/thread_task_runner_handle.h" +#include "cc/paint/raw_memory_transfer_cache_entry.h" +#include "cc/paint/transfer_cache_entry.h" +#include "cc/test/test_in_process_context_provider.h" +#include "gpu/command_buffer/client/client_transfer_cache.h" +#include "gpu/command_buffer/client/gles2_cmd_helper.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/client/shared_memory_limits.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/service_transfer_cache.h" +#include "gpu/ipc/gl_in_process_context.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_implementation.h" + +namespace cc { +namespace { + +class TransferCacheTest : public testing::Test { + public: + TransferCacheTest() + : testing::Test(), test_client_entry_(std::vector<uint8_t>(100)) {} + void SetUp() override { + bool is_offscreen = true; + gpu::gles2::ContextCreationAttribHelper attribs; + attribs.alpha_size = -1; + attribs.depth_size = 24; + attribs.stencil_size = 8; + attribs.samples = 0; + attribs.sample_buffers = 0; + attribs.fail_if_major_perf_caveat = false; + attribs.bind_generates_resource = false; + + context_ = gpu::GLInProcessContext::CreateWithoutInit(); + auto result = context_->Initialize( + nullptr, nullptr, is_offscreen, gpu::kNullSurfaceHandle, nullptr, + attribs, gpu::SharedMemoryLimits(), &gpu_memory_buffer_manager_, + &image_factory_, base::ThreadTaskRunnerHandle::Get()); + + ASSERT_EQ(result, gpu::ContextResult::kSuccess); + } + + void TearDown() override { context_.reset(); } + + gpu::ClientTransferCache* ClientTransferCache() { + return &client_transfer_cache_; + } + + gpu::ServiceTransferCache* ServiceTransferCache() { + return context_->ContextGroupForTesting()->transfer_cache(); + } + + gpu::gles2::GLES2Implementation* Gl() { + return context_->GetImplementation(); + } + + gpu::CommandBuffer* CommandBuffer() { + return context_->GetImplementation()->helper()->command_buffer(); + } + + const ClientRawMemoryTransferCacheEntry& test_client_entry() const { + return test_client_entry_; + } + + private: + gpu::ClientTransferCache client_transfer_cache_; + viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; + TestImageFactory image_factory_; + std::unique_ptr<gpu::GLInProcessContext> context_; + gl::DisableNullDrawGLBindings enable_pixel_output_; + ClientRawMemoryTransferCacheEntry test_client_entry_; +}; + +TEST_F(TransferCacheTest, Basic) { + auto* client_cache = ClientTransferCache(); + auto* service_cache = ServiceTransferCache(); + auto* gl = Gl(); + auto* command_buffer = CommandBuffer(); + + // Create an entry and validate client-side state. + gpu::TransferCacheEntryId id = + client_cache->CreateCacheEntry(gl, command_buffer, test_client_entry()); + EXPECT_FALSE(id.is_null()); + gpu::ClientDiscardableHandle handle = + client_cache->DiscardableManagerForTesting()->GetHandle(id); + EXPECT_TRUE(handle.IsLockedForTesting()); + gl->Finish(); + + // Validate service-side state. + EXPECT_NE(nullptr, service_cache->GetEntry(id)); + + // Unlock on client side and flush to service. Validate handle state. + client_cache->UnlockTransferCacheEntry(gl, id); + gl->Finish(); + EXPECT_FALSE(handle.IsLockedForTesting()); + + // Re-lock on client side and validate state. Nop need to flush as lock is + // local. + EXPECT_TRUE(client_cache->LockTransferCacheEntry(id)); + EXPECT_TRUE(handle.IsLockedForTesting()); + + // Delete on client side, flush, and validate that deletion reaches service. + client_cache->DeleteTransferCacheEntry(gl, id); + gl->Finish(); + EXPECT_TRUE(handle.IsDeletedForTesting()); + EXPECT_EQ(nullptr, service_cache->GetEntry(id)); +} + +TEST_F(TransferCacheTest, Eviction) { + auto* client_cache = ClientTransferCache(); + auto* service_cache = ServiceTransferCache(); + auto* gl = Gl(); + auto* command_buffer = CommandBuffer(); + + // Create an entry and validate client-side state. + gpu::TransferCacheEntryId id = + client_cache->CreateCacheEntry(gl, command_buffer, test_client_entry()); + EXPECT_FALSE(id.is_null()); + gpu::ClientDiscardableHandle handle = + client_cache->DiscardableManagerForTesting()->GetHandle(id); + EXPECT_TRUE(handle.IsLockedForTesting()); + gl->Finish(); + + // Validate service-side state. + EXPECT_NE(nullptr, service_cache->GetEntry(id)); + + // Unlock on client side and flush to service. Validate handle state. + client_cache->UnlockTransferCacheEntry(gl, id); + gl->Finish(); + EXPECT_FALSE(handle.IsLockedForTesting()); + + // Evict on the service side. + service_cache->SetCacheSizeLimitForTesting(0); + EXPECT_TRUE(handle.IsDeletedForTesting()); + EXPECT_EQ(nullptr, service_cache->GetEntry(id)); + + // Try to re-lock on the client side. This should fail. + EXPECT_FALSE(client_cache->LockTransferCacheEntry(id)); + EXPECT_FALSE(handle.IsLockedForTesting()); +} + +TEST_F(TransferCacheTest, RawMemoryTransfer) { + auto* client_cache = ClientTransferCache(); + auto* service_cache = ServiceTransferCache(); + auto* gl = Gl(); + auto* command_buffer = CommandBuffer(); + + // Create an entry with some initialized data. + std::vector<uint8_t> data; + data.resize(100); + for (size_t i = 0; i < data.size(); ++i) { + data[i] = i; + } + + // Add the entry to the transfer cache + ClientRawMemoryTransferCacheEntry client_entry(data); + gpu::TransferCacheEntryId id = + client_cache->CreateCacheEntry(gl, command_buffer, client_entry); + EXPECT_FALSE(id.is_null()); + gpu::ClientDiscardableHandle handle = + client_cache->DiscardableManagerForTesting()->GetHandle(id); + EXPECT_TRUE(handle.IsLockedForTesting()); + gl->Finish(); + + // Validate service-side data matches. + ServiceTransferCacheEntry* service_entry = service_cache->GetEntry(id); + EXPECT_EQ(service_entry->Type(), client_entry.Type()); + const std::vector<uint8_t> service_data = + static_cast<ServiceRawMemoryTransferCacheEntry*>(service_entry)->data(); + EXPECT_EQ(data, service_data); +} + +// A TransferCacheEntry that intentionally constructs on invalid +// TransferCacheEntryType. +class InvalidIdTransferCacheEntry : public ClientTransferCacheEntry { + public: + ~InvalidIdTransferCacheEntry() override = default; + TransferCacheEntryType Type() const override { + return static_cast<TransferCacheEntryType>( + static_cast<uint32_t>(TransferCacheEntryType::kLast) + 1); + } + size_t SerializedSize() const override { return sizeof(uint32_t); } + bool Serialize(size_t size, uint8_t* data) const override { return true; } +}; + +TEST_F(TransferCacheTest, InvalidTypeFails) { + auto* client_cache = ClientTransferCache(); + auto* service_cache = ServiceTransferCache(); + auto* gl = Gl(); + auto* command_buffer = CommandBuffer(); + + // Add the entry to the transfer cache + gpu::TransferCacheEntryId id = client_cache->CreateCacheEntry( + gl, command_buffer, InvalidIdTransferCacheEntry()); + EXPECT_FALSE(id.is_null()); + gpu::ClientDiscardableHandle handle = + client_cache->DiscardableManagerForTesting()->GetHandle(id); + EXPECT_TRUE(handle.IsLockedForTesting()); + gl->Finish(); + + // Nothing should be created service side, as the type was invalid. + EXPECT_EQ(nullptr, service_cache->GetEntry(id)); +} + +} // namespace +} // namespace cc
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc index 2bbb56b..6303503 100644 --- a/cc/resources/layer_tree_resource_provider.cc +++ b/cc/resources/layer_tree_resource_provider.cc
@@ -60,7 +60,10 @@ LayerTreeResourceProvider::~LayerTreeResourceProvider() { for (auto& pair : imported_resources_) { ImportedResource& imported = pair.second; - imported.release_callback->Run(gpu::SyncToken(), true /* is_lost */); + // If the resource is exported we can't report when it can be used again + // once this class is destroyed, so consider the resource lost. + bool is_lost = imported.exported_count || imported.returned_lost; + imported.release_callback->Run(imported.returned_sync_token, is_lost); } }
diff --git a/cc/resources/layer_tree_resource_provider_unittest.cc b/cc/resources/layer_tree_resource_provider_unittest.cc index 6e976423..2075837 100644 --- a/cc/resources/layer_tree_resource_provider_unittest.cc +++ b/cc/resources/layer_tree_resource_provider_unittest.cc
@@ -103,15 +103,15 @@ provider().RemoveImportedResource(id); } -TEST_P(LayerTreeResourceProviderTest, TransferableResourceLostOnShutdown) { +TEST_P(LayerTreeResourceProviderTest, TransferableResourceNotLostOnShutdown) { MockReleaseCallback release; viz::TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15); provider().ImportResource( tran, viz::SingleReleaseCallback::Create(base::Bind( &MockReleaseCallback::Released, base::Unretained(&release)))); - // On shutdown the TransferableResource is lost. - EXPECT_CALL(release, Released(_, true)); + // On shutdown the TransferableResource is not lost if not exported. + EXPECT_CALL(release, Released(_, false)); Shutdown(); }
diff --git a/cc/test/paint_op_helper.h b/cc/test/paint_op_helper.h index 5a0810d4..fcd95176b 100644 --- a/cc/test/paint_op_helper.h +++ b/cc/test/paint_op_helper.h
@@ -19,7 +19,7 @@ // implementation should be limited ot the header. class PaintOpHelper { public: - static std::string ToString(PaintOp* base_op) { + static std::string ToString(const PaintOp* base_op) { std::ostringstream str; str << std::boolalpha; switch (base_op->GetType()) { @@ -378,4 +378,8 @@ } // namespace cc +inline ::std::ostream& operator<<(::std::ostream& os, const cc::PaintOp& op) { + return os << cc::PaintOpHelper::ToString(&op); +} + #endif // CC_TEST_PAINT_OP_HELPER_H_
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index ebf6130..41df90c7 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -312,6 +312,7 @@ java_files += chrome_vr_java_sources deps += [ "//device/vr:java", + "//third_party/gvr-android-keyboard:kb_java", "//third_party/gvr-android-sdk:gvr_common_java", ] }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/BuildConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/BuildConstants.java new file mode 100644 index 0000000..c91b06f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/BuildConstants.java
@@ -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. + +package org.chromium.chrome.browser.vr_shell.keyboard; + +/** + * Miscellaneous build-related constants. + */ +public class BuildConstants { + /** + * The version number of the keyboard API. A local copy of this class should + * be built into both the client and the SDK. Then at SDK load time, the + * version numbers can be compared to make sure the client and SDK have + * compatible APIs. + */ + public static final long API_VERSION = 1; +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java new file mode 100644 index 0000000..a7358ff --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java
@@ -0,0 +1,160 @@ +// 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.vr_shell.keyboard; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.os.IBinder; +import android.os.RemoteException; + +import com.google.vr.keyboard.IGvrKeyboardLoader; + +import org.chromium.base.ContextUtils; +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** Loads the GVR keyboard SDK dynamically using the Keyboard Service. */ +@JNINamespace("vr_shell") +public class GvrKeyboardLoaderClient { + private static final String TAG = "ChromeGvrKbClient"; + private static final boolean DEBUG_LOGS = false; + + private static final String KEYBOARD_PACKAGE = "com.google.android.vr.inputmethod"; + private static final String LOADER_NAME = "com.google.vr.keyboard.GvrKeyboardLoader"; + + private static IGvrKeyboardLoader sLoader = null; + private static ClassLoader sRemoteClassLoader = null; + + @CalledByNative + public static long loadKeyboardSDK() { + if (DEBUG_LOGS) Log.i(TAG, "loadKeyboardSDK"); + IGvrKeyboardLoader loader = getLoader(); + if (loader == null) { + if (DEBUG_LOGS) Log.i(TAG, "Couldn't find GVR keyboard SDK."); + return 0; + } + try { + long handle = loader.loadGvrKeyboard(BuildConstants.API_VERSION); + return handle; + } catch (RemoteException e) { + if (DEBUG_LOGS) Log.i(TAG, "Couldn't load GVR keyboard SDK."); + return 0; + } + } + + @CalledByNative + public static void closeKeyboardSDK(long handle) { + if (DEBUG_LOGS) Log.i(TAG, "loadKeyboardSDK"); + IGvrKeyboardLoader loader = getLoader(); + if (loader != null) { + try { + loader.closeGvrKeyboard(handle); + } catch (RemoteException e) { + Log.e(TAG, "Couldn't close GVR keyboard library", e); + } + } + } + + private static IGvrKeyboardLoader getLoader() { + if (sLoader == null) { + ClassLoader remoteClassLoader = (ClassLoader) getRemoteClassLoader(); + if (remoteClassLoader != null) { + IBinder binder = newBinder(remoteClassLoader, LOADER_NAME); + sLoader = IGvrKeyboardLoader.Stub.asInterface(binder); + } + } + return sLoader; + } + + private static Context getRemoteContext(Context context) { + try { + // The flags Context.CONTEXT_INCLUDE_CODE and Context.CONTEXT_IGNORE_SECURITY are + // needed to be able to load classes via the classloader of the returned context. + return context.createPackageContext(KEYBOARD_PACKAGE, + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + } catch (NameNotFoundException e) { + Log.e(TAG, "Couldn't find remote context", e); + } + return null; + } + + @CalledByNative + public static Context getContextWrapper() { + Context context = ContextUtils.getApplicationContext(); + return new KeyboardContextWrapper(getRemoteContext(context), context); + } + + @CalledByNative + public static Object getRemoteClassLoader() { + Context context = ContextUtils.getApplicationContext(); + if (sRemoteClassLoader == null) { + Context remoteContext = getRemoteContext(context); + if (remoteContext != null) { + sRemoteClassLoader = remoteContext.getClassLoader(); + } + } + return sRemoteClassLoader; + } + + private static IBinder newBinder(ClassLoader classLoader, String className) { + try { + Class<?> clazz = classLoader.loadClass(className); + return (IBinder) clazz.getConstructor().newInstance(); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Unable to find dynamic class " + className); + } catch (InstantiationException e) { + throw new IllegalStateException("Unable to instantiate the remote class " + className); + } catch (IllegalAccessException e) { + throw new IllegalStateException( + "Unable to call the default constructor of " + className); + } catch (Exception e) { + throw new IllegalStateException("Reflection error in " + className); + } + } + + private static class KeyboardContextWrapper extends ContextWrapper { + private final Context mKeyboardContext; + + private KeyboardContextWrapper(Context keyboardContext, Context baseContext) { + super(baseContext); + this.mKeyboardContext = keyboardContext; + } + + @Override + public Object getSystemService(String name) { + // As the LAYOUT_INFLATER_SERVICE uses assets from the Context, it should point to the + // keyboard Context. + if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) { + return mKeyboardContext.getSystemService(name); + } else { + return super.getSystemService(name); + } + } + + @Override + public Resources getResources() { + return mKeyboardContext.getResources(); + } + + @Override + public AssetManager getAssets() { + return mKeyboardContext.getAssets(); + } + + @Override + public Context getApplicationContext() { + return this; + } + + @Override + public ClassLoader getClassLoader() { + return mKeyboardContext.getClassLoader(); + } + } +}
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 5184586..bb96d92 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1402,6 +1402,8 @@ "java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java", "java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java", "java/src/org/chromium/chrome/browser/vr_shell/OnDispatchTouchEventCallback.java", + "java/src/org/chromium/chrome/browser/vr_shell/keyboard/BuildConstants.java", + "java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java", ] chrome_test_java_sources = [
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index eb74828..e47e1f6 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -599,6 +599,9 @@ <message name="IDS_SETTINGS_CREDIT_CARD_NONE" desc="Placeholder that is shown when there are no credit cards in the list of saved credit cards."> Saved cards will appear here </message> + <message name="IDS_SETTINGS_CREDIT_CARD_DISABLED" desc="Placeholder that is shown when credit card autofill has been disabled by policy."> + Saved cards are disabled by your administrator + </message> <message name="IDS_SETTINGS_PASSWORDS_NONE" desc="Placeholder that is shown when there are no passwords in the list of saved passwords."> Saved passwords will appear here </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1aeed0b1..12e5aeac 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2176,6 +2176,9 @@ {"vr-browsing", flag_descriptions::kVrBrowsingName, flag_descriptions::kVrBrowsingDescription, kOsAndroid, FEATURE_VALUE_TYPE(features::kVrBrowsing)}, + {"vr-browser-keyboard", flag_descriptions::kVrBrowserKeyboardName, + flag_descriptions::kVrBrowserKeyboardDescription, kOsAndroid, + FEATURE_VALUE_TYPE(features::kVrBrowserKeyboard)}, {"vr-browsing-experimental-features", flag_descriptions::kVrBrowsingExperimentalFeaturesName, flag_descriptions::kVrBrowsingExperimentalFeaturesDescription, kOsAndroid, @@ -2196,6 +2199,11 @@ flag_descriptions::kWebVrAutopresentFromIntentDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kWebVrAutopresentFromIntent)}, #endif // OS_ANDROID +#if BUILDFLAG(ENABLE_OPENVR) + {"openvr", flag_descriptions::kOpenVRName, + flag_descriptions::kOpenVRDescription, kOsWin, + FEATURE_VALUE_TYPE(features::kOpenVR)}, +#endif // ENABLE_OPENVR #endif // ENABLE_VR #if defined(OS_CHROMEOS) {"disable-accelerated-mjpeg-decode", @@ -3572,9 +3580,9 @@ FEATURE_VALUE_TYPE(features::kClipboardContentSetting)}, #if defined(OS_CHROMEOS) - {"native-samba", flag_descriptions::kNativeSambaName, - flag_descriptions::kNativeSambaDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kNativeSamba)}, + {"native-smb", flag_descriptions::kNativeSmbName, + flag_descriptions::kNativeSmbDescription, kOsCrOS, + FEATURE_VALUE_TYPE(features::kNativeSmb)}, #endif // defined(OS_CHROMEOS) {"enable-modern-media-controls",
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn index 816920a..4e51490 100644 --- a/chrome/browser/android/vr_shell/BUILD.gn +++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -20,6 +20,7 @@ "autocomplete_controller.cc", "autocomplete_controller.h", "gl_browser_interface.h", + "gvr_keyboard_shim.cc", "gvr_util.cc", "gvr_util.h", "mailbox_to_surface_bridge.cc", @@ -75,7 +76,10 @@ "android", ] - configs += [ "//third_party/gvr-android-sdk:libgvr_config" ] + configs += [ + "//third_party/gvr-android-keyboard:kb_config", + "//third_party/gvr-android-sdk:libgvr_config", + ] } generate_jni("vr_shell_jni_headers") { @@ -85,6 +89,7 @@ "//chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrCoreInfo.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java", + "//chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java", ] jni_package = "vr_shell" }
diff --git a/chrome/browser/android/vr_shell/DEPS b/chrome/browser/android/vr_shell/DEPS index 1a4cc31..59f29a44 100644 --- a/chrome/browser/android/vr_shell/DEPS +++ b/chrome/browser/android/vr_shell/DEPS
@@ -2,5 +2,6 @@ "+cc/base", "+cc/layers", "+device/vr", + "+third_party/gvr-android-keyboard/src", "+third_party/gvr-android-sdk/src", ]
diff --git a/chrome/browser/android/vr_shell/gvr_keyboard_shim.cc b/chrome/browser/android/vr_shell/gvr_keyboard_shim.cc new file mode 100644 index 0000000..cdc68151 --- /dev/null +++ b/chrome/browser/android/vr_shell/gvr_keyboard_shim.cc
@@ -0,0 +1,246 @@ +// 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 "third_party/gvr-android-keyboard/src/libraries/headers/vr/gvr/capi/include/gvr_keyboard.h" + +#include <android/native_window_jni.h> +#include <dlfcn.h> +#include <jni.h> +#include <cmath> + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/logging.h" +#include "jni/GvrKeyboardLoaderClient_jni.h" + +// Run CALL macro for every function defined in the API. +#define FOR_EACH_API_FN \ + CALL(gvr_keyboard_initialize) \ + CALL(gvr_keyboard_create) \ + CALL(gvr_keyboard_get_input_mode) \ + CALL(gvr_keyboard_set_input_mode) \ + CALL(gvr_keyboard_get_recommended_world_from_keyboard_matrix) \ + CALL(gvr_keyboard_set_world_from_keyboard_matrix) \ + CALL(gvr_keyboard_show) \ + CALL(gvr_keyboard_update_button_state) \ + CALL(gvr_keyboard_update_controller_ray) \ + CALL(gvr_keyboard_get_text) \ + CALL(gvr_keyboard_set_text) \ + CALL(gvr_keyboard_get_selection_indices) \ + CALL(gvr_keyboard_set_selection_indices) \ + CALL(gvr_keyboard_get_composing_indices) \ + CALL(gvr_keyboard_set_composing_indices) \ + CALL(gvr_keyboard_set_frame_time) \ + CALL(gvr_keyboard_set_eye_from_world_matrix) \ + CALL(gvr_keyboard_set_projection_matrix) \ + CALL(gvr_keyboard_set_viewport) \ + CALL(gvr_keyboard_advance_frame) \ + CALL(gvr_keyboard_render) \ + CALL(gvr_keyboard_hide) \ + CALL(gvr_keyboard_destroy) + +namespace { + +// Declare implementation function pointers. +#define CALL(fn) decltype(&fn) impl_##fn = nullptr; +FOR_EACH_API_FN +#undef CALL + +template <typename Fn> +bool LoadFunction(void* handle, const char* function_name, Fn* fn_out) { + void* fn = dlsym(handle, function_name); + if (!fn) { + LOG(ERROR) << "Failed to load " << function_name + << " from GVR keyboard library: " << dlerror(); + return false; + } + *fn_out = reinterpret_cast<Fn>(fn); + return true; +} + +static void* sdk_handle = nullptr; + +void CloseSdk() { + if (!sdk_handle) + return; + + JNIEnv* env = base::android::AttachCurrentThread(); + CHECK(env); + + vr_shell::Java_GvrKeyboardLoaderClient_closeKeyboardSDK( + env, reinterpret_cast<jlong>(sdk_handle)); + +// Null all the function pointers. +#define CALL(fn) impl_##fn = nullptr; + FOR_EACH_API_FN +#undef CALL + + sdk_handle = nullptr; +} + +bool LoadSdk(void* closure, gvr_keyboard_callback callback) { + if (sdk_handle) + return true; + + JNIEnv* env = base::android::AttachCurrentThread(); + CHECK(env); + + base::android::ScopedJavaLocalRef<jobject> context_wrapper = + vr_shell::Java_GvrKeyboardLoaderClient_getContextWrapper(env); + + base::android::ScopedJavaLocalRef<jobject> remote_class_loader = + vr_shell::Java_GvrKeyboardLoaderClient_getRemoteClassLoader(env); + + sdk_handle = reinterpret_cast<void*>( + vr_shell::Java_GvrKeyboardLoaderClient_loadKeyboardSDK(env)); + + if (!sdk_handle) { + LOG(ERROR) << "Failed to load GVR keyboard SDK."; + return false; + } + + // Load all function pointers from the SDK. + bool success = true; +#define CALL(fn) success &= LoadFunction(sdk_handle, #fn, &impl_##fn); + FOR_EACH_API_FN +#undef CALL + + if (!success) { + CloseSdk(); + return false; + } + + gvr_keyboard_initialize(env, context_wrapper.obj(), + remote_class_loader.obj()); + + return success; +} + +} // namespace + +void gvr_keyboard_initialize(JNIEnv* env, + jobject app_context, + jobject class_loader) { + impl_gvr_keyboard_initialize(env, app_context, class_loader); +} + +gvr_keyboard_context* gvr_keyboard_create(void* closure, + gvr_keyboard_callback callback) { + if (!LoadSdk(closure, callback)) { + return nullptr; + } + return impl_gvr_keyboard_create(closure, callback); +} + +void gvr_keyboard_destroy(gvr_keyboard_context** context) { + impl_gvr_keyboard_destroy(context); + CloseSdk(); +} + +int32_t gvr_keyboard_get_input_mode(gvr_keyboard_context* context) { + return impl_gvr_keyboard_get_input_mode(context); +} + +void gvr_keyboard_set_input_mode(gvr_keyboard_context* context, + int32_t input_mode) { + impl_gvr_keyboard_set_input_mode(context, input_mode); +} + +void gvr_keyboard_get_recommended_world_from_keyboard_matrix( + float distance_from_eye, + gvr_mat4f* matrix) { + impl_gvr_keyboard_get_recommended_world_from_keyboard_matrix( + distance_from_eye, matrix); +} + +void gvr_keyboard_set_world_from_keyboard_matrix(gvr_keyboard_context* context, + const gvr_mat4f* matrix) { + impl_gvr_keyboard_set_world_from_keyboard_matrix(context, matrix); +} + +void gvr_keyboard_show(gvr_keyboard_context* context) { + impl_gvr_keyboard_show(context); +} + +void gvr_keyboard_update_button_state(gvr_keyboard_context* context, + int32_t button_index, + bool pressed) { + impl_gvr_keyboard_update_button_state(context, button_index, pressed); +} + +bool gvr_keyboard_update_controller_ray(gvr_keyboard_context* context, + const gvr_vec3f* start, + const gvr_vec3f* end, + gvr_vec3f* hit) { + return impl_gvr_keyboard_update_controller_ray(context, start, end, hit); +} + +char* gvr_keyboard_get_text(gvr_keyboard_context* context) { + return impl_gvr_keyboard_get_text(context); +} + +void gvr_keyboard_set_text(gvr_keyboard_context* context, const char* text) { + return impl_gvr_keyboard_set_text(context, text); +} + +void gvr_keyboard_get_selection_indices(gvr_keyboard_context* context, + size_t* start, + size_t* end) { + impl_gvr_keyboard_get_selection_indices(context, start, end); +} + +void gvr_keyboard_set_selection_indices(gvr_keyboard_context* context, + size_t start, + size_t end) { + impl_gvr_keyboard_set_selection_indices(context, start, end); +} + +void gvr_keyboard_get_composing_indices(gvr_keyboard_context* context, + size_t* start, + size_t* end) { + impl_gvr_keyboard_get_composing_indices(context, start, end); +} + +void gvr_keyboard_set_composing_indices(gvr_keyboard_context* context, + size_t start, + size_t end) { + impl_gvr_keyboard_set_composing_indices(context, start, end); +} + +void gvr_keyboard_set_frame_time(gvr_keyboard_context* context, + const gvr_clock_time_point* time) { + impl_gvr_keyboard_set_frame_time(context, time); +} + +void gvr_keyboard_set_eye_from_world_matrix(gvr_keyboard_context* context, + int32_t eye_type, + const gvr_mat4f* matrix) { + impl_gvr_keyboard_set_eye_from_world_matrix(context, eye_type, matrix); +} + +void gvr_keyboard_set_projection_matrix(gvr_keyboard_context* context, + int32_t eye_type, + const gvr_mat4f* projection) { + impl_gvr_keyboard_set_projection_matrix(context, eye_type, projection); +} + +void gvr_keyboard_set_viewport(gvr_keyboard_context* context, + int32_t eye_type, + const gvr_recti* viewport) { + impl_gvr_keyboard_set_viewport(context, eye_type, viewport); +} + +void gvr_keyboard_advance_frame(gvr_keyboard_context* context) { + impl_gvr_keyboard_advance_frame(context); +} + +void gvr_keyboard_render(gvr_keyboard_context* context, int32_t eye_type) { + impl_gvr_keyboard_render(context, eye_type); +} + +void gvr_keyboard_hide(gvr_keyboard_context* context) { + impl_gvr_keyboard_hide(context); +} + +#undef FOR_EACH_API_FN
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc index 1572c5e..4d10ce9 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.cc +++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -101,6 +101,46 @@ static constexpr float kRedrawSceneAngleDeltaDegrees = 1.0; +static gvr_keyboard_context* keyboard_context; + +// TODO(ymalik,crbug.com/780318): This callback is temporary until we have an +// editable input field. +void OnKeyboardEvent(void*, int32_t event) { + switch (event) { + case GVR_KEYBOARD_ERROR_UNKNOWN: + LOG(ERROR) << "Unknown GVR keyboard error."; + break; + case GVR_KEYBOARD_ERROR_SERVICE_NOT_CONNECTED: + LOG(ERROR) << "GVR keyboard service not connected."; + break; + case GVR_KEYBOARD_ERROR_NO_LOCALES_FOUND: + LOG(ERROR) << "No GVR keyboard locales found."; + break; + case GVR_KEYBOARD_ERROR_SDK_LOAD_FAILED: + LOG(ERROR) << "GVR keyboard sdk load failed."; + break; + case GVR_KEYBOARD_SHOWN: + DVLOG(1) << "GVR keyboard shown."; + break; + case GVR_KEYBOARD_HIDDEN: + DVLOG(1) << "GVR keyboard hidden."; + break; + case GVR_KEYBOARD_TEXT_UPDATED: { + char* text = gvr_keyboard_get_text(keyboard_context); + DVLOG(1) << "GVR keyboard text updated: " << text; + free(reinterpret_cast<void*>(text)); + } break; + case GVR_KEYBOARD_TEXT_COMMITTED: { + char* text = gvr_keyboard_get_text(keyboard_context); + DVLOG(1) << "GVR keyboard text updated: " << text; + free(reinterpret_cast<void*>(text)); + gvr_keyboard_set_text(keyboard_context, ""); + } break; + default: + NOTREACHED(); + } +} + gfx::Transform PerspectiveMatrixFromView(const gvr::Rectf& fov, float z_near, float z_far) { @@ -196,6 +236,9 @@ VrShellGl::~VrShellGl() { ClosePresentationBindings(); + if (keyboard_enabled_) { + gvr_keyboard_destroy(&gvr_keyboard_); + } } void VrShellGl::Initialize() { @@ -465,6 +508,7 @@ void VrShellGl::InitializeRenderer() { gvr_api_->InitializeGl(); + CreateKeyboard(); gfx::Transform head_pose; device::GvrDelegate::GetGvrPoseWithNeckModel(gvr_api_.get(), &head_pose); webvr_head_pose_.assign(kPoseRingBufferSize, head_pose); @@ -614,6 +658,7 @@ controller_model.opacity = controller_->GetOpacity(); controller_model.laser_direction = controller_direction; controller_model.laser_origin = laser_origin; + controller_model_ = controller_model; vr::ReticleModel reticle_model; ui_->input_manager()->HandleInput(current_time, controller_model, @@ -645,6 +690,18 @@ if (controller_->ButtonUpHappened( gvr::ControllerButton::GVR_CONTROLLER_BUTTON_APP)) { + // TODO(ymalik,crbug.com/780318): We temporarily show and hide the keyboard + // when the app button is pressed. This behavior is behind a runtime enabled + // feature and should go away as soon as we have editable input fields. + show_keyboard_ = keyboard_enabled_ && !show_keyboard_; + if (keyboard_enabled_) { + if (show_keyboard_) { + gvr_keyboard_show(gvr_keyboard_); + } else { + gvr_keyboard_hide(gvr_keyboard_); + } + } + // A gesture is a movement of the controller while holding the App button. // If the angle of the movement is within a threshold, the action is // considered a regular click @@ -892,6 +949,10 @@ // screen showing in WebVR mode that must also fill the screen. ui_->ui_renderer()->Draw(render_info_primary_); + // Draw keyboard. TODO(ymalik,crbug.com/780135): Keyboard should be a UI + // element and this special rendering logic should move out of here. + DrawKeyboard(); + content_frame_available_ = false; acquired_frame_.Unbind(); @@ -970,6 +1031,77 @@ } } +void VrShellGl::CreateKeyboard() { + if (gvr_keyboard_) + return; + + keyboard_enabled_ = + base::FeatureList::IsEnabled(features::kVrBrowserKeyboard); + if (!keyboard_enabled_) + return; + + gvr_keyboard_ = gvr_keyboard_create(nullptr, OnKeyboardEvent); + if (!gvr_keyboard_) { + keyboard_enabled_ = false; + return; + } + keyboard_context = gvr_keyboard_; + + gvr_mat4f matrix; + gvr_keyboard_get_recommended_world_from_keyboard_matrix(2.0f, &matrix); + gvr_keyboard_set_world_from_keyboard_matrix(gvr_keyboard_, &matrix); +} + +void VrShellGl::DrawKeyboard() { + if (!keyboard_enabled_) + return; + + // Note that according to the keyboard API, these functions must be called + // every frame after the keyboard is created to process events, regardless of + // keyboard visibility. + gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); + gvr_keyboard_set_frame_time(gvr_keyboard_, &target_time); + gvr_keyboard_advance_frame(gvr_keyboard_); + + if (!show_keyboard_) + return; + + bool pressed = controller_->ButtonUpHappened( + gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK); + gvr_keyboard_update_button_state( + gvr_keyboard_, gvr::ControllerButton::GVR_CONTROLLER_BUTTON_CLICK, + pressed); + + gvr_vec3f start; + start.x = controller_model_.laser_origin.x(); + start.y = controller_model_.laser_origin.y(); + start.z = controller_model_.laser_origin.z(); + gvr_vec3f end; + end.x = start.x + controller_model_.laser_direction.x(); + end.y = start.y + controller_model_.laser_direction.y(); + end.z = start.z + controller_model_.laser_direction.z(); + gvr_vec3f hit_point; + gvr_keyboard_update_controller_ray(gvr_keyboard_, &start, &end, &hit_point); + for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { + vr::CameraModel& eye_info = (eye == GVR_LEFT_EYE) + ? render_info_primary_.left_eye_model + : render_info_primary_.right_eye_model; + gvr::Mat4f view_matrix; + TransformToGvrMat(eye_info.view_matrix, &view_matrix); + gvr_keyboard_set_eye_from_world_matrix(gvr_keyboard_, eye, &view_matrix); + + gvr::Mat4f proj_matrix; + TransformToGvrMat(eye_info.proj_matrix, &proj_matrix); + gvr_keyboard_set_projection_matrix(gvr_keyboard_, eye, &proj_matrix); + + gfx::Rect viewport_rect = eye_info.viewport; + const gvr::Recti viewport = {viewport_rect.x(), viewport_rect.right(), + viewport_rect.y(), viewport_rect.bottom()}; + gvr_keyboard_set_viewport(gvr_keyboard_, eye, &viewport); + gvr_keyboard_render(gvr_keyboard_, eye); + } +} + void VrShellGl::DrawFrameSubmitWhenReady( int16_t frame_index, const gfx::Transform& head_pose,
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h index 3c2f21a..1f6fa1e 100644 --- a/chrome/browser/android/vr_shell/vr_shell_gl.h +++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -24,6 +24,7 @@ #include "chrome/browser/vr/ui_renderer.h" #include "device/vr/vr_service.mojom.h" #include "mojo/public/cpp/bindings/binding.h" +#include "third_party/gvr-android-keyboard/src/libraries/headers/vr/gvr/capi/include/gvr_keyboard.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h" #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h" #include "ui/gfx/geometry/quaternion.h" @@ -85,6 +86,8 @@ void OnTriggerEvent(); void OnPause(); void OnResume(); + void DrawKeyboard(); + void CreateKeyboard(); base::WeakPtr<vr::BrowserUiInterface> GetBrowserUiWeakPtr(); @@ -221,6 +224,7 @@ bool is_exiting_ = false; std::unique_ptr<VrController> controller_; + gvr_keyboard_context* gvr_keyboard_ = nullptr; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -264,6 +268,10 @@ bool skips_redraw_when_not_dirty_; gfx::Transform last_used_head_pose_; + bool keyboard_enabled_ = false; + bool show_keyboard_ = false; + vr::ControllerModel controller_model_; + base::WeakPtrFactory<VrShellGl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(VrShellGl);
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 3d404fe..1a02535 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -109,6 +109,7 @@ #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" +#include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_features.h" @@ -807,6 +808,8 @@ MagnificationManager::Initialize(); } + // TODO(crbug.com/776464): Remove WallpaperManager after everything is + // migrated to WallpaperController. WallpaperManager::SetPathIds(chrome::DIR_USER_DATA, chrome::DIR_CHROMEOS_WALLPAPERS, chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS); @@ -840,6 +843,9 @@ tablet_mode_client_ = std::make_unique<TabletModeClient>(); tablet_mode_client_->Init(); + wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>(); + wallpaper_controller_client_->Init(); + if (lock_screen_apps::StateController::IsEnabled()) { lock_screen_apps_state_controller_ = base::MakeUnique<lock_screen_apps::StateController>(); @@ -1165,6 +1171,8 @@ g_browser_process->platform_part()->user_manager()->Shutdown(); WallpaperManager::Shutdown(); + wallpaper_controller_client_.reset(); + // Let the DeviceDisablingManager unregister itself as an observer of the // CrosSettings singleton before it is destroyed. g_browser_process->platform_part()->ShutdownDeviceDisablingManager();
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h index 937d48f..df74642f 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -17,6 +17,7 @@ class NightLightClient; class NotificationPlatformBridge; class TabletModeClient; +class WallpaperControllerClient; namespace lock_screen_apps { class StateController; @@ -115,6 +116,7 @@ lock_screen_apps_state_controller_; std::unique_ptr<NightLightClient> night_light_client_; + std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_; // TODO(estade): Remove this when Chrome OS uses native notifications by // default (as it will be instantiated elsewhere). For now it's necessary to
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index ebef2b89..34b0add 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -200,7 +200,7 @@ // purpose, but it has two caveats: // 1. username_hash() is defined only after user has logged in. // 2. If cryptohome identifier changes, username_hash() will also change, -// and we may loose user => wallpaper files mapping at that point. +// and we may lose user => wallpaper files mapping at that point. // So this function gives WallpaperManager independent hashing method to break // this dependency. // @@ -743,15 +743,16 @@ base::FilePath WallpaperManager::GetCustomWallpaperPath( const char* sub_dir, const wallpaper::WallpaperFilesId& wallpaper_files_id, - const std::string& file) { + const std::string& file_name) { base::FilePath custom_wallpaper_path = GetCustomWallpaperDir(sub_dir); - return custom_wallpaper_path.Append(wallpaper_files_id.id()).Append(file); + return custom_wallpaper_path.Append(wallpaper_files_id.id()) + .Append(file_name); } void WallpaperManager::SetCustomWallpaper( const AccountId& account_id, const wallpaper::WallpaperFilesId& wallpaper_files_id, - const std::string& file, + const std::string& file_name, wallpaper::WallpaperLayout layout, wallpaper::WallpaperType type, const gfx::ImageSkia& image, @@ -774,7 +775,7 @@ } base::FilePath wallpaper_path = GetCustomWallpaperPath( - kOriginalWallpaperSubDir, wallpaper_files_id, file); + kOriginalWallpaperSubDir, wallpaper_files_id, file_name); const user_manager::User* user = user_manager::UserManager::Get()->FindUser(account_id); @@ -802,7 +803,7 @@ } std::string relative_path = - base::FilePath(wallpaper_files_id.id()).Append(file).value(); + base::FilePath(wallpaper_files_id.id()).Append(file_name).value(); // User's custom wallpaper path is determined by relative path and the // appropriate wallpaper resolution in GetCustomWallpaperInternal. WallpaperInfo info = {relative_path, layout, type, @@ -851,7 +852,7 @@ void WallpaperManager::SetCustomizedDefaultWallpaper( const GURL& wallpaper_url, - const base::FilePath& downloaded_file, + const base::FilePath& file_path, const base::FilePath& resized_directory) { // Should fail if this ever happens in tests. DCHECK(wallpaper_url.is_valid()); @@ -862,10 +863,10 @@ } return; } - std::string downloaded_file_name = downloaded_file.BaseName().value(); + std::string downloaded_file_name = file_path.BaseName().value(); std::unique_ptr<CustomizedWallpaperRescaledFiles> rescaled_files( new CustomizedWallpaperRescaledFiles( - downloaded_file, + file_path, resized_directory.Append(downloaded_file_name + kSmallWallpaperSuffix), resized_directory.Append(downloaded_file_name + @@ -874,7 +875,7 @@ base::Closure check_file_exists = rescaled_files->CreateCheckerClosure(); base::Closure on_checked_closure = base::Bind(&WallpaperManager::SetCustomizedDefaultWallpaperAfterCheck, - weak_factory_.GetWeakPtr(), wallpaper_url, downloaded_file, + weak_factory_.GetWeakPtr(), wallpaper_url, file_path, base::Passed(std::move(rescaled_files))); if (!task_runner_->PostTaskAndReply(FROM_HERE, check_file_exists, on_checked_closure)) { @@ -1234,7 +1235,7 @@ observers_.RemoveObserver(observer); } -void WallpaperManager::Open() { +void WallpaperManager::OpenWallpaperPicker() { if (wallpaper_manager_util::ShouldUseAndroidWallpapersApp( ProfileHelper::Get()->GetProfileByUser( user_manager::UserManager::Get()->GetActiveUser())) && @@ -1329,8 +1330,7 @@ // WallpaperManager, private: -------------------------------------------------- WallpaperManager::WallpaperManager() - : binding_(this), - activation_client_observer_(this), + : activation_client_observer_(this), window_observer_(this), weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -1349,19 +1349,6 @@ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); user_manager::UserManager::Get()->AddObserver(this); - - content::ServiceManagerConnection* connection = - content::ServiceManagerConnection::GetForProcess(); - if (connection && connection->GetConnector()) { - // Connect to the wallpaper controller interface in the ash service. - ash::mojom::WallpaperControllerPtr wallpaper_controller_ptr; - connection->GetConnector()->BindInterface(ash::mojom::kServiceName, - &wallpaper_controller_ptr); - // Register this object as the wallpaper picker. - ash::mojom::WallpaperPickerPtr picker; - binding_.Bind(mojo::MakeRequest(&picker)); - wallpaper_controller_ptr->SetWallpaperPicker(std::move(picker)); - } } // static @@ -2025,7 +2012,7 @@ void WallpaperManager::SetCustomizedDefaultWallpaperAfterCheck( const GURL& wallpaper_url, - const base::FilePath& downloaded_file, + const base::FilePath& file_path, std::unique_ptr<CustomizedWallpaperRescaledFiles> rescaled_files) { PrefService* pref_service = g_browser_process->local_state(); @@ -2037,7 +2024,7 @@ // Either resized images do not exist or cached version is incorrect. // Need to start resize again. user_image_loader::StartWithFilePath( - task_runner_, downloaded_file, ImageDecoder::ROBUST_JPEG_CODEC, + task_runner_, file_path, ImageDecoder::ROBUST_JPEG_CODEC, 0, // Do not crop. base::Bind(&WallpaperManager::OnCustomizedDefaultWallpaperDecoded, weak_factory_.GetWeakPtr(), wallpaper_url,
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h index c70894a..6bbb4a7 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
@@ -12,7 +12,6 @@ #include <string> #include <vector> -#include "ash/public/interfaces/wallpaper.mojom.h" #include "base/containers/circular_deque.h" #include "base/files/file_path.h" #include "base/macros.h" @@ -33,7 +32,6 @@ #include "components/wallpaper/wallpaper_info.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "mojo/public/cpp/bindings/binding.h" #include "ui/aura/window_observer.h" #include "ui/gfx/image/image_skia.h" #include "ui/wm/public/activation_change_observer.h" @@ -96,8 +94,7 @@ // A dictionary pref that maps usernames to wallpaper info. extern const char kUsersWallpaperInfo[]; -class WallpaperManager : public ash::mojom::WallpaperPicker, - public content::NotificationObserver, +class WallpaperManager : public content::NotificationObserver, public user_manager::UserManager::Observer, public wm::ActivationChangeObserver, public aura::WindowObserver { @@ -240,26 +237,39 @@ gfx::ImageSkia* output_skia); // Returns custom wallpaper path. Append |sub_dir|, |wallpaper_files_id| and - // |file| to custom wallpaper directory. + // |file_name| to custom wallpaper directory. static base::FilePath GetCustomWallpaperPath( const char* sub_dir, const wallpaper::WallpaperFilesId& wallpaper_files_id, - const std::string& file); + const std::string& file_name); // Sets wallpaper from policy or from a local file. Saves the custom wallpaper - // to file, posts task to generate thumbnail and updates local state. If - // |show_wallpaper| is false, don't show the new wallpaper now but only update - // cache. + // to file, posts task to generate thumbnail and updates local state. + // |account_id|: The user's account id. + // |wallpaper_files_id|: The unique id of each wallpaper file. + // |file_name|: The name of the wallpaper file. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |type|: The type of the wallpaper, e.g., default, policy etc. + // |image|: The wallpaper image. + // |show_wallpaper|: If false, don't show the new wallpaper now but only + // update cache. void SetCustomWallpaper(const AccountId& account_id, const wallpaper::WallpaperFilesId& wallpaper_files_id, - const std::string& file, + const std::string& file_name, wallpaper::WallpaperLayout layout, wallpaper::WallpaperType type, const gfx::ImageSkia& image, bool show_wallpaper); - // Sets wallpaper from the wallpaper picker selection. If |show_wallpaper| - // is false, don't show the new wallpaper now but only update cache. + // Sets wallpaper from the wallpaper picker selection, i.e., the wallpaper + // type is ONLINE. + // |account_id|: The user's account id. + // |image|: The wallpaper image. + // |url|: The url corresponding to this wallpaper. Used as a placeholder for + // the location in WallpaperInfo. + // |layout|: The layout of the wallpaper, used for wallpaper resizing. + // |show_wallpaper|: If false, don't show the new wallpaper now but only + // update cache. void SetOnlineWallpaper(const AccountId& account_id, const gfx::ImageSkia& image, const std::string& url, @@ -271,10 +281,15 @@ // false, don't show the default wallpaper now. void SetDefaultWallpaper(const AccountId& account_id, bool show_wallpaper); - // Called from CustomizationDocument. |resized_directory| is the directory - // where resized versions are stored and it must be writable. + // Sets a customized default wallpaper to be used wherever a default wallpaper + // is needed. Note: it doesn't change the default wallpaper for guest and + // child accounts. + // |wallpaper_url|: The url corresponding to this wallpaper. + // |file_path|: The path of the wallpaper file. + // |resized_directory|: The directory where resized versions are stored. Must + // be writable. void SetCustomizedDefaultWallpaper(const GURL& wallpaper_url, - const base::FilePath& downloaded_file, + const base::FilePath& file_path, const base::FilePath& resized_directory); // Shows |account_id|'s wallpaper, which is determined in the following order: @@ -357,8 +372,8 @@ // Removes given observer from the list. void RemoveObserver(Observer* observer); - // ash::mojom::WallpaperPicker: - void Open() override; + // Opens the wallpaper picker window. + void OpenWallpaperPicker(); // content::NotificationObserver: void Observe(int type, @@ -549,7 +564,7 @@ // This is called after we check that supplied default wallpaper files exist. void SetCustomizedDefaultWallpaperAfterCheck( const GURL& wallpaper_url, - const base::FilePath& downloaded_file, + const base::FilePath& file_path, std::unique_ptr<CustomizedWallpaperRescaledFiles> rescaled_files); // Starts rescaling of customized wallpaper. @@ -656,8 +671,6 @@ const base::FilePath& customized_default_wallpaper_file_large, std::unique_ptr<gfx::ImageSkia> large_wallpaper_image); - mojo::Binding<ash::mojom::WallpaperPicker> binding_; - std::unique_ptr<CrosSettings::ObserverSubscription> show_user_name_on_signin_subscription_;
diff --git a/chrome/browser/chromeos/ui/low_disk_notification.cc b/chrome/browser/chromeos/ui/low_disk_notification.cc index 349e090..4fef6d9 100644 --- a/chrome/browser/chromeos/ui/low_disk_notification.cc +++ b/chrome/browser/chromeos/ui/low_disk_notification.cc
@@ -13,6 +13,7 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/grit/generated_resources.h" @@ -23,7 +24,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/chromeos/resources/grit/ui_chromeos_resources.h" -#include "ui/message_center/message_center.h" #include "ui/message_center/notification.h" #include "ui/message_center/notification_types.h" #include "ui/message_center/notifier_id.h" @@ -37,31 +37,12 @@ constexpr base::TimeDelta kNotificationInterval = base::TimeDelta::FromMinutes(2); -class LowDiskNotificationDelegate - : public message_center::NotificationDelegate { - public: - LowDiskNotificationDelegate() {} - - // message_center::NotificationDelegate - void ButtonClick(int button_index) override { - chrome::ShowSettingsSubPageForProfile( - ProfileManager::GetActiveUserProfile(), kStoragePage); - } - - private: - ~LowDiskNotificationDelegate() override {} - - DISALLOW_COPY_AND_ASSIGN(LowDiskNotificationDelegate); -}; - } // namespace namespace chromeos { LowDiskNotification::LowDiskNotification() - : message_center_(g_browser_process->message_center()), - notification_interval_(kNotificationInterval), - weak_ptr_factory_(this) { + : notification_interval_(kNotificationInterval), weak_ptr_factory_(this) { DCHECK(DBusThreadManager::Get()->GetCryptohomeClient()); DBusThreadManager::Get()->GetCryptohomeClient()->AddObserver(this); } @@ -88,14 +69,16 @@ if (severity != last_notification_severity_ || (severity == HIGH && now - last_notification_time_ > notification_interval_)) { - message_center_->AddNotification(CreateNotification(severity)); + Profile* profile = ProfileManager::GetLastUsedProfile(); + NotificationDisplayService::GetForProfile(profile)->Display( + NotificationCommon::TRANSIENT, *CreateNotification(severity, profile)); last_notification_time_ = now; last_notification_severity_ = severity; } } std::unique_ptr<message_center::Notification> -LowDiskNotification::CreateNotification(Severity severity) { +LowDiskNotification::CreateNotification(Severity severity, Profile* profile) { base::string16 title; base::string16 message; gfx::Image icon; @@ -128,12 +111,17 @@ message_center::NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierDisk); + auto on_click = base::Bind( + [](Profile* profile, int button_index) { + chrome::ShowSettingsSubPageForProfile(profile, kStoragePage); + }, + profile); std::unique_ptr<message_center::Notification> notification = ash::system_notifier::CreateSystemNotification( message_center::NOTIFICATION_TYPE_SIMPLE, kLowDiskId, title, message, icon, base::string16(), GURL(), notifier_id, optional_fields, - new LowDiskNotificationDelegate(), kNotificationStorageFullIcon, - warning_level); + new message_center::HandleNotificationButtonClickDelegate(on_click), + kNotificationStorageFullIcon, warning_level); return notification; } @@ -147,11 +135,6 @@ return Severity::NONE; } -void LowDiskNotification::SetMessageCenterForTest( - message_center::MessageCenter* message_center) { - message_center_ = message_center; -} - void LowDiskNotification::SetNotificationIntervalForTest( base::TimeDelta notification_interval) { notification_interval_ = notification_interval;
diff --git a/chrome/browser/chromeos/ui/low_disk_notification.h b/chrome/browser/chromeos/ui/low_disk_notification.h index 2e4a663..e8bc265 100644 --- a/chrome/browser/chromeos/ui/low_disk_notification.h +++ b/chrome/browser/chromeos/ui/low_disk_notification.h
@@ -15,9 +15,10 @@ #include "base/time/time.h" #include "chromeos/dbus/cryptohome_client.h" +class Profile; + namespace message_center { class Notification; -class MessageCenter; } namespace chromeos { @@ -50,22 +51,19 @@ // Creates a notification for the specified severity. If the severity does // not match a known value MEDIUM is used by default. std::unique_ptr<message_center::Notification> CreateNotification( - Severity severity); + Severity severity, + Profile* profile); // Gets the severity of the low disk status based on the amount of free space // left on the disk. Severity GetSeverity(uint64_t free_disk_bytes); - // Sets the MessageCenter instance to use. Should only be used in tests. - void SetMessageCenterForTest(message_center::MessageCenter* message_center); - // Sets the minimum time to wait between notifications of the same severity. // Should only be used in tests. void SetNotificationIntervalForTest(base::TimeDelta interval); base::Time last_notification_time_; Severity last_notification_severity_ = NONE; - message_center::MessageCenter* message_center_; base::TimeDelta notification_interval_; base::ThreadChecker thread_checker_; base::WeakPtrFactory<LowDiskNotification> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc b/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc index ab009f4..ddb8e23 100644 --- a/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc +++ b/chrome/browser/chromeos/ui/low_disk_notification_unittest.cc
@@ -8,17 +8,17 @@ #include <utility> -#include "base/test/scoped_task_environment.h" -#include "base/threading/platform_thread.h" #include "base/time/time.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/testing_profile_manager.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cryptohome_client.h" -#include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/message_center/fake_message_center.h" -#include "ui/message_center/message_center.h" +#include "ui/message_center/notification.h" namespace { @@ -30,39 +30,44 @@ namespace chromeos { -class LowDiskNotificationTest : public testing::Test, - public message_center::FakeMessageCenter { +class LowDiskNotificationTest : public BrowserWithTestWindowTest { public: LowDiskNotificationTest() {} + ~LowDiskNotificationTest() override {} void SetUp() override { DBusThreadManager::GetSetterForTesting()->SetCryptohomeClient( std::unique_ptr<CryptohomeClient>(new FakeCryptohomeClient)); - message_center::MessageCenter::Initialize(); + + BrowserWithTestWindowTest::SetUp(); + + tester_ = std::make_unique<NotificationDisplayServiceTester>( + profile_manager()->profile_manager()->GetLastUsedProfile()); + tester_->SetNotificationAddedClosure(base::Bind( + &LowDiskNotificationTest::OnNotificationAdded, base::Unretained(this))); low_disk_notification_.reset(new LowDiskNotification()); - low_disk_notification_->SetMessageCenterForTest(this); - low_disk_notification_->SetNotificationIntervalForTest( - base::TimeDelta::FromMilliseconds(10)); notification_count_ = 0; } void TearDown() override { low_disk_notification_.reset(); - last_notification_.reset(); - message_center::MessageCenter::Shutdown(); - DBusThreadManager::Shutdown(); + BrowserWithTestWindowTest::TearDown(); } - void AddNotification( - std::unique_ptr<message_center::Notification> notification) override { - last_notification_ = std::move(notification); - notification_count_++; + base::Optional<message_center::Notification> GetNotification() { + return tester_->GetNotification("low_disk"); } + void SetNotificationThrottlingInterval(int ms) { + low_disk_notification_->SetNotificationIntervalForTest( + base::TimeDelta::FromMilliseconds(ms)); + } + + void OnNotificationAdded() { notification_count_++; } + protected: - base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<NotificationDisplayServiceTester> tester_; std::unique_ptr<LowDiskNotification> low_disk_notification_; - std::unique_ptr<message_center::Notification> last_notification_; int notification_count_; }; @@ -70,8 +75,9 @@ base::string16 expected_title = l10n_util::GetStringUTF16(IDS_LOW_DISK_NOTIFICATION_TITLE); low_disk_notification_->LowDiskSpace(kMediumNotification); - EXPECT_NE(nullptr, last_notification_); - EXPECT_EQ(expected_title, last_notification_->title()); + auto notification = GetNotification(); + ASSERT_TRUE(notification); + EXPECT_EQ(expected_title, notification->title()); EXPECT_EQ(1, notification_count_); } @@ -80,28 +86,29 @@ l10n_util::GetStringUTF16(IDS_CRITICALLY_LOW_DISK_NOTIFICATION_TITLE); low_disk_notification_->LowDiskSpace(kMediumNotification); low_disk_notification_->LowDiskSpace(kHighNotification); - EXPECT_NE(nullptr, last_notification_); - EXPECT_EQ(expected_title, last_notification_->title()); + auto notification = GetNotification(); + ASSERT_TRUE(notification); + EXPECT_EQ(expected_title, notification->title()); EXPECT_EQ(2, notification_count_); } TEST_F(LowDiskNotificationTest, NotificationsAreThrottled) { + SetNotificationThrottlingInterval(10000000); low_disk_notification_->LowDiskSpace(kHighNotification); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5)); low_disk_notification_->LowDiskSpace(kHighNotification); EXPECT_EQ(1, notification_count_); } TEST_F(LowDiskNotificationTest, HighNotificationsAreShownAfterThrottling) { + SetNotificationThrottlingInterval(-1); low_disk_notification_->LowDiskSpace(kHighNotification); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(15)); low_disk_notification_->LowDiskSpace(kHighNotification); EXPECT_EQ(2, notification_count_); } TEST_F(LowDiskNotificationTest, MediumNotificationsAreNotShownAfterThrottling) { + SetNotificationThrottlingInterval(-1); low_disk_notification_->LowDiskSpace(kMediumNotification); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(15)); low_disk_notification_->LowDiskSpace(kMediumNotification); EXPECT_EQ(1, notification_count_); }
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 8d9ef79d..04b2a93 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2554,9 +2554,9 @@ const char kMultideviceDescription[] = "Enables UI for controlling multidevice features."; -const char kNativeSambaName[] = "Native Samba Client"; -const char kNativeSambaDescription[] = - "If enabled, allows connections to a Samba share via Files app"; +const char kNativeSmbName[] = "Native Smb Client"; +const char kNativeSmbDescription[] = + "If enabled, allows connections to an smb filesystem via Files app"; const char kNetworkPortalNotificationName[] = "Notifications about captive portals"; @@ -2718,6 +2718,10 @@ const char kVrBrowsingDescription[] = "Browsing within a VR headset if available for this device."; +const char kVrBrowserKeyboardName[] = "Chrome VR virtual keyboard."; +const char kVrBrowserKeyboardDescription[] = + "Enable a virtual keyboard for Chrome VR."; + const char kVrBrowsingExperimentalFeaturesName[] = "VR browsing experimental features"; const char kVrBrowsingExperimentalFeaturesDescription[] = @@ -2744,6 +2748,12 @@ #endif // OS_ANDROID +#if BUILDFLAG(ENABLE_OPENVR) +const char kOpenVRName[] = "OpenVR hardware support"; +const char kOpenVRDescription[] = + "If enabled, Chrome will use OpenVR devices for VR."; +#endif // ENABLE_OPENVR + #endif // ENABLE_VR #if BUILDFLAG(ENABLE_NACL)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 1850a7b0..71e93370 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1583,8 +1583,8 @@ extern const char kMultideviceName[]; extern const char kMultideviceDescription[]; -extern const char kNativeSambaName[]; -extern const char kNativeSambaDescription[]; +extern const char kNativeSmbName[]; +extern const char kNativeSmbDescription[]; extern const char kNetworkPortalNotificationName[]; extern const char kNetworkPortalNotificationDescription[]; @@ -1679,6 +1679,9 @@ extern const char kVrBrowsingName[]; extern const char kVrBrowsingDescription[]; +extern const char kVrBrowserKeyboardName[]; +extern const char kVrBrowserKeyboardDescription[]; + extern const char kVrBrowsingExperimentalFeaturesName[]; extern const char kVrBrowsingExperimentalFeaturesDescription[]; @@ -1696,6 +1699,11 @@ #endif // OS_ANDROID +#if BUILDFLAG(ENABLE_OPENVR) +extern const char kOpenVRName[]; +extern const char kOpenVRDescription[]; +#endif // ENABLE_OPENVR + #endif // ENABLE_VR #if BUILDFLAG(ENABLE_NACL)
diff --git a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc index 0401a8c..fdf8e36 100644 --- a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc +++ b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.cc
@@ -114,4 +114,16 @@ } } +void WiredDisplayDeviceCountMetrics::RecordDeviceCounts( + size_t available_device_count, + size_t known_device_count) { + // Record just the available device count, because for wired displays, all + // the known displays are available. + UMA_HISTOGRAM_COUNTS_100(kHistogramWiredDisplayDeviceCount, + available_device_count); +} + +const char WiredDisplayDeviceCountMetrics::kHistogramWiredDisplayDeviceCount[] = + "MediaRouter.WiredDisplay.AvailableDevicesCount"; + } // namespace media_router
diff --git a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h index c89845a..05ed917 100644 --- a/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h +++ b/chrome/browser/media/router/discovery/media_sink_discovery_metrics.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/gtest_prod_util.h" #include "base/time/clock.h" #include "base/time/time.h" @@ -111,6 +112,21 @@ const base::TimeDelta& duration); }; +// Metrics for wired display (local screen) sink counts. +class WiredDisplayDeviceCountMetrics : public DeviceCountMetrics { + protected: + // |known_device_count| is not recorded, since it should be the same as + // |available_device_count|. + void RecordDeviceCounts(size_t available_device_count, + size_t known_device_count) override; + + private: + FRIEND_TEST_ALL_PREFIXES(WiredDisplayDeviceCountMetricsTest, + RecordWiredDisplaySinkCount); + + static const char kHistogramWiredDisplayDeviceCount[]; +}; + } // namespace media_router #endif // CHROME_BROWSER_MEDIA_ROUTER_DISCOVERY_MEDIA_SINK_DISCOVERY_METRICS_H_
diff --git a/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc b/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc index 63e2d3c..83b4d34 100644 --- a/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc +++ b/chrome/browser/media/router/discovery/media_sink_discovery_metrics_unittest.cc
@@ -148,4 +148,27 @@ delta.InMilliseconds(), 1); } +TEST(WiredDisplayDeviceCountMetricsTest, RecordWiredDisplaySinkCount) { + base::HistogramTester tester; + WiredDisplayDeviceCountMetrics metrics; + tester.ExpectTotalCount( + WiredDisplayDeviceCountMetrics::kHistogramWiredDisplayDeviceCount, 0); + + // Only the first argument, the available sink count, is recorded. + metrics.RecordDeviceCounts(1, 1); + metrics.RecordDeviceCounts(200, 200); + metrics.RecordDeviceCounts(0, 0); + metrics.RecordDeviceCounts(25, 30); + metrics.RecordDeviceCounts(1, 0); + + tester.ExpectTotalCount( + WiredDisplayDeviceCountMetrics::kHistogramWiredDisplayDeviceCount, 5); + EXPECT_THAT( + tester.GetAllSamples( + WiredDisplayDeviceCountMetrics::kHistogramWiredDisplayDeviceCount), + ElementsAre( + Bucket(0, 1), Bucket(1, 2), Bucket(25, 1), + Bucket(100, 1))); // Counts over 100 are all put in the 100 bucket. +} + } // namespace media_router
diff --git a/chrome/browser/media/router/media_router_metrics.cc b/chrome/browser/media/router/media_router_metrics.cc index 7d729b0..714082d 100644 --- a/chrome/browser/media/router/media_router_metrics.cc +++ b/chrome/browser/media/router/media_router_metrics.cc
@@ -108,12 +108,14 @@ UMA_HISTOGRAM_SPARSE_SLOWLY(kHistogramMediaRouterCastingSource, source); } +// static void MediaRouterMetrics::RecordMediaRouterFileFormat( const media::container_names::MediaContainerName format) { UMA_HISTOGRAM_ENUMERATION(kHistogramMediaRouterFileFormat, format, media::container_names::CONTAINER_MAX); } +// static void MediaRouterMetrics::RecordMediaRouterFileSize(int64_t size) { UMA_HISTOGRAM_MEMORY_LARGE_MB(kHistogramMediaRouterFileSize, size); }
diff --git a/chrome/browser/media/router/mojo/wired_display_media_route_provider.cc b/chrome/browser/media/router/mojo/wired_display_media_route_provider.cc index eb639460..8fad64c 100644 --- a/chrome/browser/media/router/mojo/wired_display_media_route_provider.cc +++ b/chrome/browser/media/router/mojo/wired_display_media_route_provider.cc
@@ -263,8 +263,9 @@ media_router_->OnRoutesUpdated(kProviderId, route_list, route_query, {}); } -void WiredDisplayMediaRouteProvider::NotifySinkObservers() const { +void WiredDisplayMediaRouteProvider::NotifySinkObservers() { std::vector<MediaSinkInternal> sinks = GetSinks(); + device_count_metrics_.RecordDeviceCountsIfNeeded(sinks.size(), sinks.size()); for (const auto& sink_query : sink_queries_) media_router_->OnSinksReceived(kProviderId, sink_query, sinks, {}); }
diff --git a/chrome/browser/media/router/mojo/wired_display_media_route_provider.h b/chrome/browser/media/router/mojo/wired_display_media_route_provider.h index 6d3ef46..ca0c61d9 100644 --- a/chrome/browser/media/router/mojo/wired_display_media_route_provider.h +++ b/chrome/browser/media/router/mojo/wired_display_media_route_provider.h
@@ -7,6 +7,7 @@ #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "chrome/browser/media/router/discovery/media_sink_discovery_metrics.h" #include "chrome/common/media_router/mojo/media_router.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/display/display_observer.h" @@ -102,7 +103,7 @@ void NotifyRouteObservers() const; // Sends the current list of sinks to each query in |sink_queries_|. - void NotifySinkObservers() const; + void NotifySinkObservers(); // Returns a list of available sinks. A display can be a sink if it is // secondary and does not mirror a primary display. @@ -125,6 +126,9 @@ // A set of MediaSource IDs associated with queries for MediaSink updates. base::flat_set<std::string> sink_queries_; + + // Used for recording UMA metrics for the number of sinks available. + WiredDisplayDeviceCountMetrics device_count_metrics_; }; } // namespace media_router
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider.cc b/chrome/browser/ntp_snippets/download_suggestions_provider.cc index 9b1649e..3537bdb 100644 --- a/chrome/browser/ntp_snippets/download_suggestions_provider.cc +++ b/chrome/browser/ntp_snippets/download_suggestions_provider.cc
@@ -722,7 +722,6 @@ bool notify, const std::vector<offline_pages::OfflinePageItem>& all_download_offline_pages) { - DCHECK(!offline_page_model_ || offline_page_model_->is_loaded()); std::set<std::string> old_dismissed_ids = ReadOfflinePageDismissedIDsFromPrefs();
diff --git a/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc b/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc index 1e7acffb..f94ed87b 100644 --- a/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc +++ b/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc
@@ -364,8 +364,6 @@ } void OfflinePageEvaluationBridge::NotifyIfDoneLoading() const { - if (!offline_page_model_->is_loaded()) - return; JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env); if (obj.is_null())
diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc index 941b8c83..51238b71 100644 --- a/chrome/browser/offline_pages/android/offline_page_bridge.cc +++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc
@@ -740,8 +740,6 @@ } void OfflinePageBridge::NotifyIfDoneLoading() const { - if (!offline_page_model_->is_loaded()) - return; JNIEnv* env = base::android::AttachCurrentThread(); Java_OfflinePageBridge_offlinePageModelLoaded(env, java_ref_); }
diff --git a/chrome/browser/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/offline_pages/recent_tab_helper_unittest.cc index c0216ef0..be8169f 100644 --- a/chrome/browser/offline_pages/recent_tab_helper_unittest.cc +++ b/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
@@ -293,14 +293,12 @@ recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); // Move the snapshot controller's time forward so it gets past timeouts. FastForwardSnapshotController(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(0U, page_added_count()); ASSERT_EQ(0U, GetAllPages().size()); // Tab is hidden with a fully loaded page. A snapshot save should happen. recent_tab_helper()->WasHidden(); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(1U, page_added_count()); ASSERT_EQ(1U, GetAllPages().size()); EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url); @@ -314,7 +312,6 @@ NavigateAndCommit(kTestPageUrl); recent_tab_helper()->WasHidden(); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(0U, page_added_count()); ASSERT_EQ(0U, GetAllPages().size()); @@ -340,7 +337,6 @@ recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), 123L, ""); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); // No page should be captured. EXPECT_EQ(0U, page_added_count()); ASSERT_EQ(0U, GetAllPages().size()); @@ -358,7 +354,6 @@ FastForwardSnapshotController(); recent_tab_helper()->WasHidden(); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(0U, page_added_count()); ASSERT_EQ(0U, GetAllPages().size()); @@ -382,7 +377,6 @@ FastForwardSnapshotController(); recent_tab_helper()->WasHidden(); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(0U, page_added_count()); ASSERT_EQ(0U, GetAllPages().size()); @@ -400,7 +394,6 @@ // Upon the next hide a last_n snapshot should be saved. recent_tab_helper()->WasHidden(); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(2U, page_added_count()); ASSERT_EQ(2U, GetAllPages().size()); } @@ -412,7 +405,6 @@ // Set page loading state to the 1st snapshot-able stage. No capture so far. recent_tab_helper()->DocumentAvailableInMainFrame(); FastForwardSnapshotController(); - EXPECT_TRUE(model()->is_loaded()); EXPECT_EQ(0U, page_added_count()); // Tab is hidden and a snapshot should be saved. @@ -642,7 +634,6 @@ recent_tab_helper()->ObserveAndDownloadCurrentPage(NewDownloadClientId(), 123L, ""); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); } @@ -656,7 +647,6 @@ FastForwardSnapshotController(); recent_tab_helper()->WasHidden(); RunUntilIdle(); - EXPECT_TRUE(model()->is_loaded()); // No page should be captured. ASSERT_EQ(0U, GetAllPages().size()); @@ -676,7 +666,6 @@ const ClientId client_id = NewDownloadClientId(); recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id, 153L, ""); FastForwardSnapshotController(); - EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); // Minimally load the page. First capture should occur. @@ -707,7 +696,6 @@ NavigateAndCommit(kTestPageUrl); recent_tab_helper()->DocumentAvailableInMainFrame(); FastForwardSnapshotController(); - EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); const ClientId client_id = NewDownloadClientId(); @@ -732,7 +720,6 @@ NavigateAndCommit(kTestPageUrl); recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); FastForwardSnapshotController(); - EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); const ClientId client_id = NewDownloadClientId(); @@ -752,7 +739,6 @@ NavigateAndCommit(kTestPageUrl); recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); FastForwardSnapshotController(); - EXPECT_TRUE(model()->is_loaded()); ASSERT_EQ(0U, GetAllPages().size()); const ClientId client_id = NewDownloadClientId();
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.css b/chrome/browser/resources/media_router/elements/route_controls/route_controls.css index 5c3c658..0fcf48a 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.css +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.css
@@ -16,13 +16,6 @@ right: 20px; } -.ellipsis { - padding: 0 1%; - text-overflow: ellipsis; - white-space: nowrap; - width: 90%; -} - :host-context([dir='rtl']) #play-pause-volume-hangouts-controls { transform: scaleX(-1); } @@ -48,7 +41,7 @@ #route-description { margin: 15px 8px 3px 8px; - overflow: hidden; + width: 90%; } #route-time-controls {
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.html b/chrome/browser/resources/media_router/elements/route_controls/route_controls.html index 64e37d0..f6184a8 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.html +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.html
@@ -8,9 +8,14 @@ <link rel="import" type="css" href="route_controls.css"> <template> <div id="media-controls"> + <!-- + TODO(crbug.com/786208): Remove the div below and always render the + description in the details element. And, possibly combine details and + controls elements. + --> <div class="ellipsis" id="route-description" - title="[[displayedDescription_]]"> - [[displayedDescription_]] + title="[[routeDescription_]]"> + [[routeDescription_]] </div> <div class="ellipsis" id="route-title" title="[[routeStatus.title]]"> [[routeStatus.title]]
diff --git a/chrome/browser/resources/media_router/elements/route_controls/route_controls.js b/chrome/browser/resources/media_router/elements/route_controls/route_controls.js index c11e97e..ce15e1e 100644 --- a/chrome/browser/resources/media_router/elements/route_controls/route_controls.js +++ b/chrome/browser/resources/media_router/elements/route_controls/route_controls.js
@@ -21,11 +21,11 @@ }, /** - * The media description to display. Uses route description if none is - * provided by the route status object. + * The route description to display. Uses the media route description if + * none is provided by the media route status object. * @private {string} */ - displayedDescription_: { + routeDescription_: { type: String, value: '', }, @@ -357,7 +357,7 @@ this.displayedVolume_ = Math.round(newRouteStatus.volume * 100) / 100; } if (newRouteStatus.description !== '') { - this.displayedDescription_ = newRouteStatus.description; + this.routeDescription_ = newRouteStatus.description; } if (!this.initialLoadTime_) { this.initialLoadTime_ = Date.now(); @@ -386,8 +386,7 @@ this.stopIncrementingCurrentTime_(); } if (route && this.routeStatus.description === '') { - this.displayedDescription_ = - loadTimeData.getStringF('castingActivityStatus', route.description); + this.routeDescription_ = route.description; } },
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.css b/chrome/browser/resources/media_router/elements/route_details/route_details.css index 742647d..92f8b1a 100644 --- a/chrome/browser/resources/media_router/elements/route_details/route_details.css +++ b/chrome/browser/resources/media_router/elements/route_details/route_details.css
@@ -17,12 +17,10 @@ text-align: end; } -#route-information { +#route-description { -webkit-padding-end: var(--dialog-padding-end); -webkit-padding-start: 44px; - background-color: white; font-size: 1.2em; line-height: 1.5em; margin-top: 16px; - overflow: hidden; }
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.html b/chrome/browser/resources/media_router/elements/route_details/route_details.html index 6bc2093..8d91b1be 100644 --- a/chrome/browser/resources/media_router/elements/route_details/route_details.html +++ b/chrome/browser/resources/media_router/elements/route_details/route_details.html
@@ -7,9 +7,9 @@ <link rel="import" type="css" href="../../media_router_common.css"> <link rel="import" type="css" href="route_details.css"> <template> - <div id="route-information" - hidden$="[[!shouldShowRouteInfoOnly_(controllerType_)]]"> - <span>[[activityStatus_]]</span> + <div class="ellipsis" id="route-description" title="[[routeDescription_]]" + hidden$="[[!shouldShowRouteDescription_(controllerType_)]]"> + [[routeDescription_]] </div> <template is="dom-if" if="[[shouldAttemptLoadingExtensionView_(route)]]"> <extension-view-wrapper id="extension-view-wrapper" route="[[route]]"
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.js b/chrome/browser/resources/media_router/elements/route_details/route_details.js index b260d81..8724cd2 100644 --- a/chrome/browser/resources/media_router/elements/route_details/route_details.js +++ b/chrome/browser/resources/media_router/elements/route_details/route_details.js
@@ -9,10 +9,10 @@ properties: { /** - * The text for the current casting activity status. + * Description of the current casting activity, e.g. "Casting YouTube". * @private {string|undefined} */ - activityStatus_: { + routeDescription_: { type: String, }, @@ -191,15 +191,12 @@ }, /** - * Updates |activityStatus_| for the default view. + * Updates |routeDescription_| for the default view. * * @private */ - updateActivityStatus_: function() { - this.activityStatus_ = this.route ? - loadTimeData.getStringF( - 'castingActivityStatus', this.route.description) : - ''; + updateRouteDescription_: function() { + this.routeDescription_ = this.route ? this.route.description : ''; }, /** @@ -231,7 +228,7 @@ */ onRouteChange_: function(newRoute) { if (this.controllerType_ !== media_router.ControllerType.WEBUI) { - this.updateActivityStatus_(); + this.updateRouteDescription_(); } }, @@ -260,7 +257,7 @@ * the extensionview or the WebUI route controller. * @private */ - shouldShowRouteInfoOnly_: function(controllerType) { + shouldShowRouteDescription_: function(controllerType) { return controllerType === media_router.ControllerType.NONE; },
diff --git a/chrome/browser/resources/media_router/media_router_common.css b/chrome/browser/resources/media_router/media_router_common.css index dd22f1cc..d944684 100644 --- a/chrome/browser/resources/media_router/media_router_common.css +++ b/chrome/browser/resources/media_router/media_router_common.css
@@ -19,3 +19,14 @@ [hidden] { display: none !important; } + +.ellipsis { + padding: 0 1%; + text-overflow: ellipsis; + white-space: nowrap; +} + +#route-description { + background-color: white; + overflow: hidden; +}
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js index 03ebf64..d5a0022 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -120,12 +120,10 @@ proxyExpanded_: Boolean, }, - /** - * Listener function for chrome.networkingPrivate.onNetworksChanged event. - * @type {?function(!Array<string>)} - * @private - */ - networksChangedListener_: null, + listeners: { + 'network-list-changed': 'checkNetworkExists_', + 'networks-changed': 'updateNetworkDetails_', + }, /** @private {boolean} */ didSetFocus_: false, @@ -133,6 +131,8 @@ /** * Set to true to once the initial properties have been received. This * prevents setProperties from being called when setting default properties. + * This will also be set to false if the network no longer exists in the + * list of networks (e.g. it goes out of range). * @private {boolean} */ networkPropertiesReceived_: false, @@ -152,19 +152,9 @@ * @protected */ currentRouteChanged: function(route, oldRoute) { - if (route != settings.routes.NETWORK_DETAIL) { - if (this.networksChangedListener_) { - this.networkingPrivate.onNetworksChanged.removeListener( - this.networksChangedListener_); - this.networksChangedListener_ = null; - } + if (route != settings.routes.NETWORK_DETAIL) return; - } - if (!this.networksChangedListener_) { - this.networksChangedListener_ = this.onNetworksChangedEvent_.bind(this); - this.networkingPrivate.onNetworksChanged.addListener( - this.networksChangedListener_); - } + var queryParams = settings.getQueryParameters(); this.guid = queryParams.get('guid') || ''; if (!this.guid) { @@ -263,11 +253,20 @@ }, /** - * networkingPrivate.onNetworksChanged event callback. - * @param {!Array<string>} networkIds The list of changed network GUIDs. + * @param {{detail: !Array<string>}} event * @private */ - onNetworksChangedEvent_: function(networkIds) { + checkNetworkExists_: function(event) { + var networkIds = event.detail; + this.networkPropertiesReceived_ = networkIds.indexOf(this.guid) != -1; + }, + + /** + * @param {{detail: !Array<string>}} event + * @private + */ + updateNetworkDetails_: function(event) { + var networkIds = event.detail; if (networkIds.indexOf(this.guid) != -1) this.getNetworkDetails_(); }, @@ -541,6 +540,8 @@ enableConnect_: function(networkProperties, defaultNetwork, globalPolicy) { if (!this.showConnect_(networkProperties, globalPolicy)) return false; + if (!this.networkPropertiesReceived_) + return false; if ((networkProperties.Type == CrOnc.Type.CELLULAR) && (CrOnc.isSimLocked(networkProperties) || this.get('Cellular.Scanning', networkProperties))) {
diff --git a/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js b/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js index 5ec39d7..b1dc5e6 100644 --- a/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
@@ -54,44 +54,17 @@ enableForget_: Boolean, }, + listeners: {'network-list-changed': 'refreshNetworks_'}, + /** @private {string} */ selectedGuid_: '', - /** - * Listener function for chrome.networkingPrivate.onNetworksChanged event. - * @type {function(!Array<string>)} - * @private - */ - networksChangedListener_: function() {}, - - /** @override */ - attached: function() { - this.networksChangedListener_ = this.onNetworksChangedEvent_.bind(this); - this.networkingPrivate.onNetworksChanged.addListener( - this.networksChangedListener_); - }, - - /** @override */ - detached: function() { - this.networkingPrivate.onNetworksChanged.removeListener( - this.networksChangedListener_); - }, - /** @private */ networkTypeChanged_: function() { this.refreshNetworks_(); }, /** - * networkingPrivate.onNetworksChanged event callback. - * @param {!Array<string>} networkIds The list of changed network GUIDs. - * @private - */ - onNetworksChangedEvent_: function(networkIds) { - this.refreshNetworks_(); - }, - - /** * Requests the list of network states from Chrome. Updates networkStates * once the results are returned from Chrome. * @private
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.html b/chrome/browser/resources/settings/internet_page/internet_page.html index ba794ee..fdee5441 100644 --- a/chrome/browser/resources/settings/internet_page/internet_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -84,7 +84,7 @@ </template> </neon-animatable> - <template is="dom-if" route-path="/networkDetail" no-search> + <template is="dom-if" route-path="/networkDetail" no-search restamp> <settings-subpage page-title="$i18n{internetDetailPageTitle}"> <settings-internet-detail-page prefs="{{prefs}}" default-network="[[defaultNetwork]]" @@ -94,7 +94,7 @@ </settings-subpage> </template> - <template is="dom-if" route-path="/knownNetworks" no-search> + <template is="dom-if" route-path="/knownNetworks" no-search restamp> <settings-subpage page-title="$i18n{internetKnownNetworksPageTitle}"> <settings-internet-known-networks-page network-type="[[knownNetworksType_]]" @@ -103,7 +103,7 @@ </settings-subpage> </template> - <template is="dom-if" route-path="/networks" no-search> + <template is="dom-if" route-path="/networks" no-search restamp> <settings-subpage page-title="[[getNetworksPageTitle_(subpageType_)]]" show-spinner="[[showSpinner_]]"> <settings-internet-subpage
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.js b/chrome/browser/resources/settings/internet_page/internet_page.js index 7ea0e3c9..ad0c6fb 100644 --- a/chrome/browser/resources/settings/internet_page/internet_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -112,6 +112,13 @@ }, // chrome.networkingPrivate listeners + /** @private {?function(!Array<string>)} */ + networkListChangedListener_: null, + + /** @private {?function(!Array<string>)} */ + networksChangedListener_: null, + + // chrome.management listeners /** @private {Function} */ onExtensionAddedListener_: null, @@ -123,6 +130,16 @@ /** @override */ attached: function() { + this.networkListChangedListener_ = this.networkListChangedListener_ || + this.onNetworkListChanged_.bind(this); + this.networkingPrivate.onNetworkListChanged.addListener( + this.networkListChangedListener_); + + this.networksChangedListener_ = + this.networksChangedListener_ || this.onNetworksChanged_.bind(this); + this.networkingPrivate.onNetworksChanged.addListener( + this.networksChangedListener_); + this.onExtensionAddedListener_ = this.onExtensionAddedListener_ || this.onExtensionAdded_.bind(this); chrome.management.onInstalled.addListener(this.onExtensionAddedListener_); @@ -146,6 +163,11 @@ /** @override */ detached: function() { + this.networkingPrivate.onNetworkListChanged.removeListener( + assert(this.networkListChangedListener_)); + this.networkingPrivate.onNetworksChanged.removeListener( + assert(this.networksChangedListener_)); + chrome.management.onInstalled.removeListener( assert(this.onExtensionAddedListener_)); chrome.management.onEnabled.removeListener( @@ -393,6 +415,45 @@ }, /** + * This event is triggered when the list of networks changes. + * |networkIds| contains the ids for all visible or configured networks. + * networkingPrivate.onNetworkListChanged event callback. + * @param {!Array<string>} networkIds + * @private + */ + onNetworkListChanged_: function(networkIds) { + var event = new CustomEvent('network-list-changed', {detail: networkIds}); + this.maybeDispatchEvent_('network-summary', event); + this.maybeDispatchEvent_('settings-internet-detail-page', event); + this.maybeDispatchEvent_('settings-internet-known-networks-page', event); + this.maybeDispatchEvent_('settings-internet-subpage', event); + }, + + /** + * This event is triggered when interesting properties of a network change. + * |networkIds| contains the ids for networks whose properties have changed. + * networkingPrivate.onNetworksChanged event callback. + * @param {!Array<string>} networkIds + * @private + */ + onNetworksChanged_: function(networkIds) { + var event = new CustomEvent('networks-changed', {detail: networkIds}); + this.maybeDispatchEvent_('network-summary', event); + this.maybeDispatchEvent_('settings-internet-detail-page', event); + }, + + /** + * @param {!Event} event + * @private + */ + maybeDispatchEvent_: function(identifier, event) { + var element = this.$$(identifier); + if (!element) + return; + element.dispatchEvent(event); + }, + + /** * chrome.management.onInstalled or onEnabled event. * @param {!chrome.management.ExtensionInfo} extension * @private
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chrome/browser/resources/settings/internet_page/internet_subpage.js index 0434b0e..af364579 100644 --- a/chrome/browser/resources/settings/internet_page/internet_subpage.js +++ b/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -84,31 +84,16 @@ }, }, + listeners: {'network-list-changed': 'getNetworkStateList_'}, + observers: ['deviceStateChanged_(networkingPrivate, deviceState)'], /** @private {number|null} */ scanIntervalId_: null, - /** - * Listener function for chrome.networkingPrivate.onNetworkListChanged event. - * @type {?function(!Array<string>)} - * @private - */ - networkListChangedListener_: null, - - /** override */ - attached: function() { - this.networkListChangedListener_ = this.networkListChangedListener_ || - this.onNetworkListChangedEvent_.bind(this); - this.networkingPrivate.onNetworkListChanged.addListener( - this.networkListChangedListener_); - }, - /** override */ detached: function() { this.stopScanning_(); - this.networkingPrivate.onNetworkListChanged.removeListener( - assert(this.networkListChangedListener_)); }, /** @@ -195,14 +180,6 @@ this.scanIntervalId_ = null; }, - /** - * networkingPrivate.onNetworkListChanged event callback. - * @private - */ - onNetworkListChangedEvent_: function() { - this.getNetworkStateList_(); - }, - /** @private */ getNetworkStateList_: function() { if (!this.deviceState)
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.js b/chrome/browser/resources/settings/internet_page/network_summary.js index a1c6dea..a755721b 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary.js +++ b/chrome/browser/resources/settings/internet_page/network_summary.js
@@ -91,11 +91,10 @@ }, }, - /** - * Listener function for chrome.networkingPrivate.onNetworkListChanged event. - * @private {?function(!Array<string>)} - */ - networkListChangedListener_: null, + listeners: { + 'network-list-changed': 'getNetworkLists_', + 'networks-changed': 'updateActiveNetworks_', + }, /** * Listener function for chrome.networkingPrivate.onDeviceStateListChanged @@ -105,12 +104,6 @@ deviceStateListChangedListener_: null, /** - * Listener function for chrome.networkingPrivate.onNetworksChanged event. - * @private {?function(!Array<string>)} - */ - networksChangedListener_: null, - - /** * Set of GUIDs identifying active networks, one for each type. * @private {?Set<string>} */ @@ -120,41 +113,17 @@ attached: function() { this.getNetworkLists_(); - this.networkListChangedListener_ = this.networkListChangedListener_ || - this.onNetworkListChangedEvent_.bind(this); - this.networkingPrivate.onNetworkListChanged.addListener( - this.networkListChangedListener_); - this.deviceStateListChangedListener_ = this.deviceStateListChangedListener_ || this.onDeviceStateListChangedEvent_.bind(this); this.networkingPrivate.onDeviceStateListChanged.addListener( this.deviceStateListChangedListener_); - - this.networksChangedListener_ = this.networksChangedListener_ || - this.onNetworksChangedEvent_.bind(this); - this.networkingPrivate.onNetworksChanged.addListener( - this.networksChangedListener_); }, /** @override */ detached: function() { - this.networkingPrivate.onNetworkListChanged.removeListener( - assert(this.networkListChangedListener_)); - this.networkingPrivate.onDeviceStateListChanged.removeListener( assert(this.deviceStateListChangedListener_)); - - this.networkingPrivate.onNetworksChanged.removeListener( - assert(this.networksChangedListener_)); - }, - - /** - * networkingPrivate.onNetworkListChanged event callback. - * @private - */ - onNetworkListChangedEvent_: function() { - this.getNetworkLists_(); }, /** @@ -166,13 +135,13 @@ }, /** - * networkingPrivate.onNetworksChanged event callback. - * @param {!Array<string>} networkIds The list of changed network GUIDs. + * @param {{detail: !Array<string>}} event * @private */ - onNetworksChangedEvent_: function(networkIds) { + updateActiveNetworks_: function(event) { if (!this.activeNetworkIds_) return; // Initial list of networks not received yet. + var networkIds = event.detail; networkIds.forEach(function(id) { if (this.activeNetworkIds_.has(id)) { this.networkingPrivate.getState(
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html index f6e65e7..4da90c01 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> +<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> @@ -57,6 +58,11 @@ text-overflow: ellipsis; white-space: nowrap; } + + cr-policy-indicator { + padding-right: 20px; + width: 20px; + } </style> <settings-toggle-button id="autofillToggle" class="first primary-toggle" @@ -133,51 +139,62 @@ <h2 class="start">$i18n{creditCards}</h2> <paper-button id="addCreditCard" class="secondary-button header-aligned-button" - on-tap="onAddCreditCardTap_"> + on-tap="onAddCreditCardTap_" + hidden$="[[isDisabled_(prefs.autofill.credit_card_enabled)]]"> $i18n{add} </paper-button> </div> <div class="list-frame"> - <div id="creditCardsHeading" class="list-item column-header" - hidden$="[[!hasSome_(creditCards)]]"> - <div class="type-column">$i18n{creditCardType}</div> - <div class="expiration-column">$i18n{creditCardExpiration}</div> - </div> - <div id="creditCardList" class="vertical-list list-with-header"> - <template is="dom-repeat" items="[[creditCards]]"> - <div class="list-item"> - <div class="type-column"> - <span id="creditCardLabel">[[item.metadata.summaryLabel]]</span> - <span class="payments-label" hidden$="[[item.metadata.isLocal]]"> - <span hidden$="[[item.metadata.isCached]]"> - $i18n{googlePayments} + <template is="dom-if" + if="[[!isDisabled_(prefs.autofill.credit_card_enabled)]]"> + <div id="creditCardsHeading" class="list-item column-header" + hidden$="[[!hasSome_(creditCards)]]"> + <div class="type-column">$i18n{creditCardType}</div> + <div class="expiration-column">$i18n{creditCardExpiration}</div> + </div> + <div id="creditCardList" class="vertical-list list-with-header"> + <template is="dom-repeat" items="[[creditCards]]"> + <div class="list-item"> + <div class="type-column"> + <span id="creditCardLabel">[[item.metadata.summaryLabel]]</span> + <span class="payments-label" + hidden$="[[item.metadata.isLocal]]"> + <span hidden$="[[item.metadata.isCached]]"> + $i18n{googlePayments} + </span> + <span hidden$="[[!item.metadata.isCached]]"> + $i18n{googlePaymentsCached} + </span> </span> - <span hidden$="[[!item.metadata.isCached]]"> - $i18n{googlePaymentsCached} - </span> - </span> + </div> + <div class="expiration-column"> + <div id="creditCardExpiration" + class="expiration-date">[[expiration_(item)]]</div> + <template is="dom-if" if="[[showDots_(item.metadata)]]"> + <button is="paper-icon-button-light" id="creditCardMenu" + class="icon-more-vert" title="$i18n{moreActions}" + on-tap="onCreditCardMenuTap_"> + </button> + </template> + <template is="dom-if" if="[[!showDots_(item.metadata)]]"> + <button is="paper-icon-button-light" id="remoteCreditCardLink" + class="icon-external" + on-tap="onRemoteEditCreditCardTap_" actionable></button> + </template> + </div> </div> - <div class="expiration-column"> - <div id="creditCardExpiration" - class="expiration-date">[[expiration_(item)]]</div> - <template is="dom-if" if="[[showDots_(item.metadata)]]"> - <button is="paper-icon-button-light" id="creditCardMenu" - class="icon-more-vert" title="$i18n{moreActions}" - on-tap="onCreditCardMenuTap_"> - </button> - </template> - <template is="dom-if" if="[[!showDots_(item.metadata)]]"> - <button is="paper-icon-button-light" id="remoteCreditCardLink" - class="icon-external" - on-tap="onRemoteEditCreditCardTap_" actionable></button> - </template> - </div> - </div> - </template> - </div> - <div id="noCreditCardsLabel" class="list-item" - hidden$="[[hasSome_(creditCards)]]"> - $i18n{noCreditCardsFound} + </template> + </div> + <div id="noCreditCardsLabel" class="list-item" + hidden$="[[hasSome_(creditCards)]]"> + $i18n{noCreditCardsFound} + </div> + </template> + <div id="CreditCardsDisabledLabel" class="list-item" + hidden$="[[!isDisabled_(prefs.autofill.credit_card_enabled)]]"> + <cr-policy-indicator indicator-type="userPolicy" + icon-aria-label="$i18n{noCreditCardsPolicy}"></cr-policy-indicator> + $i18n{noCreditCardsPolicy} </div> </div> <dialog is="cr-action-menu" id="creditCardSharedMenu">
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js index ffad7d4..7c8197d1 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
@@ -435,6 +435,17 @@ }, /** + * Returns true if the pref has been explicitly disabled. + * @param {Object} pref + * @return {boolean} + * @private + */ + isDisabled_: function(pref) { + return !!(pref.value === false); + }, + + + /** * Listens for the save-address event, and calls the private API. * @param {!Event} event * @private
diff --git a/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp b/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp index fbc1a37..952595b 100644 --- a/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
@@ -88,6 +88,7 @@ '<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', 'site_settings_behavior', + '../android_apps_page/compiled_resources2.gyp:android_apps_browser_proxy', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.js b/chrome/browser/resources/settings/site_settings/protocol_handlers.js index cc6075b..7da371a9a 100644 --- a/chrome/browser/resources/settings/site_settings/protocol_handlers.js +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.js
@@ -18,18 +18,6 @@ }; /** - * Type definition of AndroidAppsInfo entry. |playStoreEnabled| indicates that - * Play Store is enabled. |settingsAppAvailable| indicates that Android settings - * app is registered in the system. - * @typedef {{ - * playStoreEnabled: boolean, - * settingsAppAvailable: boolean, - * }} - * @see chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc - */ -var AndroidAppsInfo; - -/** * @typedef {{host: string, * protocol: string, * spec: string}}
diff --git a/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc b/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc index 511e35e2..cf00513 100644 --- a/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc +++ b/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc
@@ -287,7 +287,7 @@ UMA_HISTOGRAM_SPARSE_SLOWLY("SBClientDownload.PPAPIDownloadRequest.Result", static_cast<int>(response)); UMA_HISTOGRAM_TIMES("SBClientDownload.PPAPIDownloadRequest.RequestDuration", - start_time_ - base::TimeTicks::Now()); + base::TimeTicks::Now() - start_time_); if (!callback_.is_null()) base::ResetAndReturn(&callback_).Run(response); fetcher_.reset();
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc index 00c8205..fc63b07 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -53,7 +53,7 @@ server->InjectEntity( syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics( - kDefaultCardID, specifics)); + kDefaultCardID, specifics, 12345, 12345)); } } // namespace
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3066185..5116496 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1274,6 +1274,8 @@ "ash/volume_controller.h", "ash/vpn_list_forwarder.cc", "ash/vpn_list_forwarder.h", + "ash/wallpaper_controller_client.cc", + "ash/wallpaper_controller_client.h", "browser_commands_chromeos.cc", "browser_commands_chromeos.h", "extensions/extension_installed_notification.cc", @@ -1704,6 +1706,7 @@ "cocoa/chrome_command_dispatcher_delegate.mm", "cocoa/chrome_style.cc", "cocoa/chrome_style.h", + "cocoa/color_chooser_mac.h", "cocoa/color_chooser_mac.mm", "cocoa/confirm_quit.h", "cocoa/confirm_quit_panel_controller.h", @@ -3724,6 +3727,8 @@ sources += [ "ash/fake_tablet_mode_controller.cc", "ash/fake_tablet_mode_controller.h", + "ash/test_wallpaper_controller.cc", + "ash/test_wallpaper_controller.h", ] deps += [ "//ash/public/cpp:ash_public_cpp" ] }
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.cc b/chrome/browser/ui/ash/test_wallpaper_controller.cc new file mode 100644 index 0000000..2323147 --- /dev/null +++ b/chrome/browser/ui/ash/test_wallpaper_controller.cc
@@ -0,0 +1,84 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/test_wallpaper_controller.h" + +TestWallpaperController::TestWallpaperController() : binding_(this) {} + +TestWallpaperController::~TestWallpaperController() = default; + +ash::mojom::WallpaperControllerPtr +TestWallpaperController::CreateInterfacePtr() { + ash::mojom::WallpaperControllerPtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; +} + +void TestWallpaperController::SetClient( + ash::mojom::WallpaperControllerClientPtr client) { + was_client_set_ = true; +} + +void TestWallpaperController::SetCustomWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info, + const std::string& wallpaper_files_id, + const std::string& file_name, + wallpaper::WallpaperLayout layout, + wallpaper::WallpaperType type, + const SkBitmap& image, + bool show_wallpaper) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::SetOnlineWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info, + const SkBitmap& image, + const std::string& url, + wallpaper::WallpaperLayout layout, + bool show_wallpaper) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::SetDefaultWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info, + bool show_wallpaper) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::SetCustomizedDefaultWallpaper( + const GURL& wallpaper_url, + const base::FilePath& file_path, + const base::FilePath& resized_directory) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::ShowUserWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::ShowSigninWallpaper() { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::RemoveUserWallpaper( + ash::mojom::WallpaperUserInfoPtr user_info) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::SetWallpaper( + const SkBitmap& wallpaper, + const wallpaper::WallpaperInfo& wallpaper_info) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::AddObserver( + ash::mojom::WallpaperObserverAssociatedPtrInfo observer) { + NOTIMPLEMENTED(); +} + +void TestWallpaperController::GetWallpaperColors( + GetWallpaperColorsCallback callback) { + NOTIMPLEMENTED(); +} \ No newline at end of file
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.h b/chrome/browser/ui/ash/test_wallpaper_controller.h new file mode 100644 index 0000000..6b3f8fa4 --- /dev/null +++ b/chrome/browser/ui/ash/test_wallpaper_controller.h
@@ -0,0 +1,63 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_TEST_WALLPAPER_CONTROLLER_H_ +#define CHROME_BROWSER_UI_ASH_TEST_WALLPAPER_CONTROLLER_H_ + +#include "ash/public/interfaces/wallpaper.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" + +// Simulates WallpaperController in ash. +// TODO(crbug.com/776464): Maybe create an enum to represent each function to +// avoid having lots of counters and getters. +class TestWallpaperController : ash::mojom::WallpaperController { + public: + TestWallpaperController(); + + ~TestWallpaperController() override; + + bool was_client_set() const { return was_client_set_; } + + // Returns a mojo interface pointer bound to this object. + ash::mojom::WallpaperControllerPtr CreateInterfacePtr(); + + // ash::mojom::WallpaperController: + void SetClient(ash::mojom::WallpaperControllerClientPtr client) override; + void SetCustomWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, + const std::string& wallpaper_files_id, + const std::string& file_name, + wallpaper::WallpaperLayout layout, + wallpaper::WallpaperType type, + const SkBitmap& image, + bool show_wallpaper) override; + void SetOnlineWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, + const SkBitmap& image, + const std::string& url, + wallpaper::WallpaperLayout layout, + bool show_wallpaper) override; + void SetDefaultWallpaper(ash::mojom::WallpaperUserInfoPtr user_info, + bool show_wallpaper) override; + void SetCustomizedDefaultWallpaper( + const GURL& wallpaper_url, + const base::FilePath& file_path, + const base::FilePath& resized_directory) override; + void ShowUserWallpaper(ash::mojom::WallpaperUserInfoPtr user_info) override; + void ShowSigninWallpaper() override; + void RemoveUserWallpaper(ash::mojom::WallpaperUserInfoPtr user_info) override; + void SetWallpaper(const SkBitmap& wallpaper, + const wallpaper::WallpaperInfo& wallpaper_info) override; + void AddObserver( + ash::mojom::WallpaperObserverAssociatedPtrInfo observer) override; + void GetWallpaperColors(GetWallpaperColorsCallback callback) override; + + private: + mojo::Binding<ash::mojom::WallpaperController> binding_; + + bool was_client_set_ = false; + + DISALLOW_COPY_AND_ASSIGN(TestWallpaperController); +}; + +#endif // CHROME_BROWSER_UI_ASH_TEST_WALLPAPER_CONTROLLER_H_ \ No newline at end of file
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc new file mode 100644 index 0000000..9fe8f0e --- /dev/null +++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -0,0 +1,152 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/wallpaper_controller_client.h" + +#include "ash/public/interfaces/constants.mojom.h" +#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" +#include "components/wallpaper/wallpaper_files_id.h" +#include "content/public/common/service_manager_connection.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace { + +WallpaperControllerClient* g_instance = nullptr; + +// Creates a mojom::WallpaperUserInfo for the account id. Returns nullptr if +// user manager cannot find the user. +ash::mojom::WallpaperUserInfoPtr AccountIdToWallpaperUserInfo( + const AccountId& account_id) { + const user_manager::User* user = + user_manager::UserManager::Get()->FindUser(account_id); + if (!user) + return nullptr; + + ash::mojom::WallpaperUserInfoPtr wallpaper_user_info = + ash::mojom::WallpaperUserInfo::New(); + wallpaper_user_info->account_id = account_id; + wallpaper_user_info->type = user->GetType(); + wallpaper_user_info->is_ephemeral = + user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( + account_id); + wallpaper_user_info->has_gaia_account = user->HasGaiaAccount(); + + return wallpaper_user_info; +} + +} // namespace + +WallpaperControllerClient::WallpaperControllerClient() : binding_(this) { + DCHECK(!g_instance); + g_instance = this; +} + +WallpaperControllerClient::~WallpaperControllerClient() { + DCHECK_EQ(this, g_instance); + g_instance = nullptr; +} + +void WallpaperControllerClient::Init() { + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &wallpaper_controller_); + BindAndSetClient(); +} + +void WallpaperControllerClient::InitForTesting( + ash::mojom::WallpaperControllerPtr controller) { + wallpaper_controller_ = std::move(controller); + BindAndSetClient(); +} + +// static +WallpaperControllerClient* WallpaperControllerClient::Get() { + return g_instance; +} + +void WallpaperControllerClient::SetCustomWallpaper( + const AccountId& account_id, + const wallpaper::WallpaperFilesId& wallpaper_files_id, + const std::string& file_name, + wallpaper::WallpaperLayout layout, + wallpaper::WallpaperType type, + const gfx::ImageSkia& image, + bool show_wallpaper) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); + if (!user_info) + return; + wallpaper_controller_->SetCustomWallpaper( + std::move(user_info), wallpaper_files_id.id(), file_name, layout, type, + *image.bitmap(), show_wallpaper); +} + +void WallpaperControllerClient::SetOnlineWallpaper( + const AccountId& account_id, + const gfx::ImageSkia& image, + const std::string& url, + wallpaper::WallpaperLayout layout, + bool show_wallpaper) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); + if (!user_info) + return; + wallpaper_controller_->SetOnlineWallpaper( + std::move(user_info), *image.bitmap(), url, layout, show_wallpaper); +} + +void WallpaperControllerClient::SetDefaultWallpaper(const AccountId& account_id, + bool show_wallpaper) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); + if (!user_info) + return; + wallpaper_controller_->SetDefaultWallpaper(std::move(user_info), + show_wallpaper); +} + +void WallpaperControllerClient::SetCustomizedDefaultWallpaper( + const GURL& wallpaper_url, + const base::FilePath& file_path, + const base::FilePath& resized_directory) { + wallpaper_controller_->SetCustomizedDefaultWallpaper(wallpaper_url, file_path, + resized_directory); +} + +void WallpaperControllerClient::ShowUserWallpaper(const AccountId& account_id) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); + if (!user_info) + return; + wallpaper_controller_->ShowUserWallpaper(std::move(user_info)); +} + +void WallpaperControllerClient::ShowSigninWallpaper() { + wallpaper_controller_->ShowSigninWallpaper(); +} + +void WallpaperControllerClient::RemoveUserWallpaper( + const AccountId& account_id) { + ash::mojom::WallpaperUserInfoPtr user_info = + AccountIdToWallpaperUserInfo(account_id); + if (!user_info) + return; + wallpaper_controller_->RemoveUserWallpaper(std::move(user_info)); +} + +void WallpaperControllerClient::OpenWallpaperPicker() { + // TODO(crbug.com/776464): Inline the implementation after WallpaperManager + // is removed. + chromeos::WallpaperManager::Get()->OpenWallpaperPicker(); +} + +void WallpaperControllerClient::FlushForTesting() { + wallpaper_controller_.FlushForTesting(); +} + +void WallpaperControllerClient::BindAndSetClient() { + ash::mojom::WallpaperControllerClientPtr client; + binding_.Bind(mojo::MakeRequest(&client)); + wallpaper_controller_->SetClient(std::move(client)); +}
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h new file mode 100644 index 0000000..f9a0af2 --- /dev/null +++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -0,0 +1,73 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_WALLPAPER_CONTROLLER_CLIENT_H_ +#define CHROME_BROWSER_UI_ASH_WALLPAPER_CONTROLLER_CLIENT_H_ + +#include "ash/public/interfaces/wallpaper.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace wallpaper { +class WallpaperFilesId; +enum WallpaperLayout; +enum WallpaperType; +} // namespace wallpaper + +// Handles method calls sent from ash to chrome. Also sends messages from chrome +// to ash. +class WallpaperControllerClient : public ash::mojom::WallpaperControllerClient { + public: + WallpaperControllerClient(); + ~WallpaperControllerClient() override; + + // Initializes and connects to ash. + void Init(); + + // Tests can provide a mock mojo interface for the ash controller. + void InitForTesting(ash::mojom::WallpaperControllerPtr controller); + + static WallpaperControllerClient* Get(); + + // Wrappers around the ash::mojom::WallpaperController interface. + void SetCustomWallpaper(const AccountId& account_id, + const wallpaper::WallpaperFilesId& wallpaper_files_id, + const std::string& file_name, + wallpaper::WallpaperLayout layout, + wallpaper::WallpaperType type, + const gfx::ImageSkia& image, + bool show_wallpaper); + void SetOnlineWallpaper(const AccountId& account_id, + const gfx::ImageSkia& image, + const std::string& url, + wallpaper::WallpaperLayout layout, + bool show_wallpaper); + void SetDefaultWallpaper(const AccountId& account_id, bool show_wallpaper); + void SetCustomizedDefaultWallpaper(const GURL& wallpaper_url, + const base::FilePath& file_path, + const base::FilePath& resized_directory); + void ShowUserWallpaper(const AccountId& account_id); + void ShowSigninWallpaper(); + void RemoveUserWallpaper(const AccountId& account_id); + + // ash::mojom::WallpaperControllerClient: + void OpenWallpaperPicker() override; + + // Flushes the mojo pipe to ash. + void FlushForTesting(); + + private: + // Binds this object to its mojo interface and sets it as the ash client. + void BindAndSetClient(); + + // WallpaperController interface in ash. + ash::mojom::WallpaperControllerPtr wallpaper_controller_; + + // Binds to the client interface. + mojo::Binding<ash::mojom::WallpaperControllerClient> binding_; + + DISALLOW_COPY_AND_ASSIGN(WallpaperControllerClient); +}; + +#endif // CHROME_BROWSER_UI_ASH_WALLPAPER_CONTROLLER_CLIENT_H_ \ No newline at end of file
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc b/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc new file mode 100644 index 0000000..4c990ae3 --- /dev/null +++ b/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/wallpaper_controller_client.h" + +#include "base/test/scoped_task_environment.h" +#include "chrome/browser/ui/ash/test_wallpaper_controller.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class WallpaperControllerClientTest : public testing::Test { + public: + WallpaperControllerClientTest() = default; + ~WallpaperControllerClientTest() override = default; + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + + DISALLOW_COPY_AND_ASSIGN(WallpaperControllerClientTest); +}; + +TEST_F(WallpaperControllerClientTest, Construction) { + WallpaperControllerClient client; + TestWallpaperController controller; + client.InitForTesting(controller.CreateInterfacePtr()); + client.FlushForTesting(); + + // Singleton was initialized. + EXPECT_EQ(&client, WallpaperControllerClient::Get()); + + // Object was set as client. + EXPECT_TRUE(controller.was_client_set()); +} + +} // namespace \ No newline at end of file
diff --git a/chrome/browser/ui/browser_navigator_params.cc b/chrome/browser/ui/browser_navigator_params.cc index f4bf1e1..43e9569 100644 --- a/chrome/browser/ui/browser_navigator_params.cc +++ b/chrome/browser/ui/browser_navigator_params.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "build/build_config.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/page_navigator.h" @@ -21,102 +20,26 @@ #if defined(OS_ANDROID) NavigateParams::NavigateParams(WebContents* a_target_contents) - : frame_tree_node_id(-1), - uses_post(false), - target_contents(a_target_contents), - source_contents(nullptr), - disposition(WindowOpenDisposition::CURRENT_TAB), - opener(nullptr), - trusted_source(false), - transition(ui::PAGE_TRANSITION_LINK), - is_renderer_initiated(false), - tabstrip_index(-1), - tabstrip_add_types(TabStripModel::ADD_ACTIVE), - window_action(NO_ACTION), - user_gesture(true), - path_behavior(RESPECT), - ref_behavior(IGNORE_REF), - initiating_profile(nullptr), - should_replace_current_entry(false), - created_with_opener(false), - started_from_context_menu(false) {} + : target_contents(a_target_contents) {} #else NavigateParams::NavigateParams(Browser* a_browser, const GURL& a_url, ui::PageTransition a_transition) - : url(a_url), - frame_tree_node_id(-1), - uses_post(false), - target_contents(NULL), - source_contents(NULL), - disposition(WindowOpenDisposition::CURRENT_TAB), - opener(nullptr), - trusted_source(false), - transition(a_transition), - is_renderer_initiated(false), - tabstrip_index(-1), - tabstrip_add_types(TabStripModel::ADD_ACTIVE), - window_action(NO_ACTION), - user_gesture(true), - path_behavior(RESPECT), - ref_behavior(IGNORE_REF), - browser(a_browser), - initiating_profile(NULL), - should_replace_current_entry(false), - created_with_opener(false), - started_from_context_menu(false) {} + : url(a_url), transition(a_transition), browser(a_browser) {} NavigateParams::NavigateParams(Browser* a_browser, WebContents* a_target_contents) - : frame_tree_node_id(-1), - uses_post(false), - target_contents(a_target_contents), - source_contents(NULL), - disposition(WindowOpenDisposition::CURRENT_TAB), - opener(nullptr), - trusted_source(false), - transition(ui::PAGE_TRANSITION_LINK), - is_renderer_initiated(false), - tabstrip_index(-1), - tabstrip_add_types(TabStripModel::ADD_ACTIVE), - window_action(NO_ACTION), - user_gesture(true), - path_behavior(RESPECT), - ref_behavior(IGNORE_REF), - browser(a_browser), - initiating_profile(NULL), - should_replace_current_entry(false), - created_with_opener(false), - started_from_context_menu(false) {} + : target_contents(a_target_contents), browser(a_browser) {} #endif // !defined(OS_ANDROID) NavigateParams::NavigateParams(Profile* a_profile, const GURL& a_url, ui::PageTransition a_transition) : url(a_url), - frame_tree_node_id(-1), - uses_post(false), - target_contents(NULL), - source_contents(NULL), disposition(WindowOpenDisposition::NEW_FOREGROUND_TAB), - opener(nullptr), - trusted_source(false), transition(a_transition), - is_renderer_initiated(false), - tabstrip_index(-1), - tabstrip_add_types(TabStripModel::ADD_ACTIVE), window_action(SHOW_WINDOW), - user_gesture(true), - path_behavior(RESPECT), - ref_behavior(IGNORE_REF), -#if !defined(OS_ANDROID) - browser(NULL), -#endif - initiating_profile(a_profile), - should_replace_current_entry(false), - created_with_opener(false), - started_from_context_menu(false) { -} + initiating_profile(a_profile) {} NavigateParams::NavigateParams(const NavigateParams& other) = default;
diff --git a/chrome/browser/ui/browser_navigator_params.h b/chrome/browser/ui/browser_navigator_params.h index 007e8d52..d79db8e 100644 --- a/chrome/browser/ui/browser_navigator_params.h +++ b/chrome/browser/ui/browser_navigator_params.h
@@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/site_instance.h" #include "content/public/common/referrer.h" @@ -77,14 +78,14 @@ std::string frame_name; // The browser-global ID of the frame to navigate, or -1 for the main frame. - int frame_tree_node_id; + int frame_tree_node_id = -1; // Any redirect URLs that occurred for this navigation before |url|. // Usually empty. std::vector<GURL> redirect_chain; // Indicates whether this navigation will be sent using POST. - bool uses_post; + bool uses_post = false; // The post data when the navigation uses POST. scoped_refptr<content::ResourceRequestBody> post_data; @@ -106,7 +107,7 @@ // a new WebContents, this field will remain NULL and the // WebContents deleted if the WebContents it created is // not added to a TabStripModel before Navigate() returns. - content::WebContents* target_contents; + content::WebContents* target_contents = nullptr; // [in] The WebContents that initiated the Navigate() request if such // context is necessary. Default is NULL, i.e. no context. @@ -115,7 +116,7 @@ // Navigate(). However, if the originating page is from a different // profile (e.g. an OFF_THE_RECORD page originating from a non-OTR // window), then |source_contents| is reset to NULL. - content::WebContents* source_contents; + content::WebContents* source_contents = nullptr; // The disposition requested by the navigation source. Default is // CURRENT_TAB. What follows is a set of coercions that happen to this value @@ -132,34 +133,30 @@ // If disposition is one of NEW_WINDOW, NEW_POPUP, NEW_FOREGROUND_TAB or // SINGLETON_TAB, then TabStripModel::ADD_ACTIVE is automatically added to // |tabstrip_add_types|. - WindowOpenDisposition disposition; + WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB; // Allows setting the opener for the case when new WebContents are created // (i.e. when |disposition| asks for a new tab or window). - content::RenderFrameHost* opener; + content::RenderFrameHost* opener = nullptr; - // Sets browser->is_trusted_source. Default is false. - bool trusted_source; + // Sets browser->is_trusted_source. + bool trusted_source = false; - // The transition type of the navigation. Default is - // ui::PAGE_TRANSITION_LINK when target_contents is specified in the - // constructor. - ui::PageTransition transition; + // The transition type of the navigation. + ui::PageTransition transition = ui::PAGE_TRANSITION_LINK; - // Whether this navigation was initiated by the renderer process. Default is - // false. - bool is_renderer_initiated; + // Whether this navigation was initiated by the renderer process. + bool is_renderer_initiated = false; // The index the caller would like the tab to be positioned at in the // TabStrip. The actual index will be determined by the TabHandler in - // accordance with |add_types|. Defaults to -1 (allows the TabHandler to - // decide). - int tabstrip_index; + // accordance with |add_types|. The default allows the TabHandler to decide. + int tabstrip_index = -1; // A bitmask of values defined in TabStripModel::AddTabTypes. Helps // determine where to insert a new tab and whether or not it should be - // selected, among other properties. Default is ADD_ACTIVE. - int tabstrip_add_types; + // selected, among other properties. + int tabstrip_add_types = TabStripModel::ADD_ACTIVE; // If non-empty, the new tab is an app tab. std::string extension_app_id; @@ -184,11 +181,10 @@ // Default is NO_ACTION (don't show or activate the window). // If disposition is NEW_WINDOW or NEW_POPUP, and |window_action| is set to // NO_ACTION, |window_action| will be set to SHOW_WINDOW. - WindowAction window_action; + WindowAction window_action = NO_ACTION; // If false then the navigation was not initiated by a user gesture. - // Default is true. - bool user_gesture; + bool user_gesture = true; // What to do with the path component of the URL for singleton navigations. enum PathBehavior { @@ -199,8 +195,7 @@ // Ignore path when finding existing tab, don't navigate tab. IGNORE_AND_STAY_PUT, }; - // Default is RESPECT. - PathBehavior path_behavior; + PathBehavior path_behavior = RESPECT; // What to do with the ref component of the URL for singleton navigations. enum RefBehavior { @@ -209,8 +204,7 @@ // Two URLs with differing refs are different. RESPECT_REF, }; - // Default is IGNORE. - RefBehavior ref_behavior; + RefBehavior ref_behavior = IGNORE_REF; #if !defined(OS_ANDROID) // [in] Specifies a Browser object where the navigation could occur or the @@ -225,22 +219,22 @@ // Navigate(), the caller is responsible for showing it so that its // window can assume responsibility for the Browser's lifetime (Browser // objects are deleted when the user closes a visible browser window). - Browser* browser; + Browser* browser = nullptr; #endif // The profile that is initiating the navigation. If there is a non-NULL // browser passed in via |browser|, it's profile will be used instead. - Profile* initiating_profile; + Profile* initiating_profile = nullptr; // Indicates whether this navigation should replace the current // navigation entry. - bool should_replace_current_entry; + bool should_replace_current_entry = false; // Indicates whether |target_contents| is being created with a window.opener. - bool created_with_opener; + bool created_with_opener = false; // Whether or not the related navigation was started in the context menu. - bool started_from_context_menu; + bool started_from_context_menu = false; // SiteInstance of the frame that initiated the navigation or null if we // don't know it. This should be assigned from the OpenURLParams of the
diff --git a/chrome/browser/ui/cocoa/color_chooser_mac.h b/chrome/browser/ui/cocoa/color_chooser_mac.h new file mode 100644 index 0000000..511000dc --- /dev/null +++ b/chrome/browser/ui/cocoa/color_chooser_mac.h
@@ -0,0 +1,71 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_COCOA_COLOR_CHOOSER_MAC_H_ +#define CHROME_BROWSER_UI_COCOA_COLOR_CHOOSER_MAC_H_ + +#import <Cocoa/Cocoa.h> + +#import "base/mac/scoped_nsobject.h" +#include "content/public/browser/color_chooser.h" +#include "content/public/browser/web_contents.h" + +class ColorChooserMac; + +// A Listener class to act as a event target for NSColorPanel and send +// the results to the C++ class, ColorChooserMac. +@interface ColorPanelCocoa : NSObject<NSWindowDelegate> { + @protected + // We don't call DidChooseColor if the change wasn't caused by the user + // interacting with the panel. + BOOL nonUserChange_; + @private + ColorChooserMac* chooser_; // weak, owns this +} + +- (id)initWithChooser:(ColorChooserMac*)chooser; + +// Called from NSColorPanel. +- (void)didChooseColor:(NSColorPanel*)panel; + +// Sets color to the NSColorPanel as a non user change. +- (void)setColor:(NSColor*)color; + +@end + +class ColorChooserMac : public content::ColorChooser { + public: + // Returns a ColorChooserMac instance owned by the ColorChooserMac class - + // call End() when done to free it. Each call to Open() returns a new + // instance after freeing the previous one (i.e. it does not reuse the + // previous instance even if it still exists). + static ColorChooserMac* Open(content::WebContents* web_contents, + SkColor initial_color); + + // Called from ColorPanelCocoa. + void DidChooseColorInColorPanel(SkColor color); + void DidCloseColorPabel(); + + // Set the color programmatically. + void SetSelectedColor(SkColor color) override; + + // Call when done with the ColorChooserMac. + void End() override; + + private: + ColorChooserMac(content::WebContents* tab, SkColor initial_color); + + ~ColorChooserMac() override; + + static ColorChooserMac* current_color_chooser_; + + // The web contents invoking the color chooser. No ownership because it will + // outlive this class. + content::WebContents* web_contents_; + base::scoped_nsobject<ColorPanelCocoa> panel_; + + DISALLOW_COPY_AND_ASSIGN(ColorChooserMac); +}; + +#endif // CHROME_BROWSER_UI_COCOA_COLOR_CHOOSER_MAC_H_
diff --git a/chrome/browser/ui/cocoa/color_chooser_mac.mm b/chrome/browser/ui/cocoa/color_chooser_mac.mm index ed5a26b5..fee82a6 100644 --- a/chrome/browser/ui/cocoa/color_chooser_mac.mm +++ b/chrome/browser/ui/cocoa/color_chooser_mac.mm
@@ -2,61 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import <Cocoa/Cocoa.h> +#import "chrome/browser/ui/cocoa/color_chooser_mac.h" #include "base/logging.h" -#import "base/mac/scoped_nsobject.h" #include "chrome/browser/ui/browser_dialogs.h" -#include "content/public/browser/color_chooser.h" -#include "content/public/browser/web_contents.h" #include "skia/ext/skia_utils_mac.h" -class ColorChooserMac; - -// A Listener class to act as a event target for NSColorPanel and send -// the results to the C++ class, ColorChooserMac. -@interface ColorPanelCocoa : NSObject<NSWindowDelegate> { - @private - // We don't call DidChooseColor if the change wasn't caused by the user - // interacting with the panel. - BOOL nonUserChange_; - ColorChooserMac* chooser_; // weak, owns this -} - -- (id)initWithChooser:(ColorChooserMac*)chooser; - -// Called from NSColorPanel. -- (void)didChooseColor:(NSColorPanel*)panel; - -// Sets color to the NSColorPanel as a non user change. -- (void)setColor:(NSColor*)color; - -@end - -class ColorChooserMac : public content::ColorChooser { - public: - static ColorChooserMac* Open(content::WebContents* web_contents, - SkColor initial_color); - - ColorChooserMac(content::WebContents* tab, SkColor initial_color); - ~ColorChooserMac() override; - - // Called from ColorPanelCocoa. - void DidChooseColorInColorPanel(SkColor color); - void DidCloseColorPabel(); - - void End() override; - void SetSelectedColor(SkColor color) override; - - private: - static ColorChooserMac* current_color_chooser_; - - // The web contents invoking the color chooser. No ownership because it will - // outlive this class. - content::WebContents* web_contents_; - base::scoped_nsobject<ColorPanelCocoa> panel_; -}; - ColorChooserMac* ColorChooserMac::current_color_chooser_ = NULL; // static @@ -104,6 +55,11 @@ [panel_ setColor:skia::SkColorToDeviceNSColor(color)]; } +@interface NSColorPanel (Private) +// Private method returning the NSColorPanel's target. +- (id)__target; +@end + @implementation ColorPanelCocoa - (id)initWithChooser:(ColorChooserMac*)chooser { @@ -120,10 +76,18 @@ - (void)dealloc { NSColorPanel* panel = [NSColorPanel sharedColorPanel]; - if ([panel delegate] == self) { + + // On macOS 10.13 the NSColorPanel delegate can apparently get reset to nil + // with the target left unchanged. Use the private __target method to see if + // the ColorPanelCocoa is still the target. + BOOL respondsToPrivateTargetMethod = + [panel respondsToSelector:@selector(__target)]; + + if ([panel delegate] == self || + (respondsToPrivateTargetMethod && [panel __target] == self)) { [panel setDelegate:nil]; [panel setTarget:nil]; - [panel setAction:nil]; + [panel setAction:nullptr]; } [super dealloc];
diff --git a/chrome/browser/ui/cocoa/color_panel_cocoa_unittest.mm b/chrome/browser/ui/cocoa/color_panel_cocoa_unittest.mm new file mode 100644 index 0000000..1985d80 --- /dev/null +++ b/chrome/browser/ui/cocoa/color_panel_cocoa_unittest.mm
@@ -0,0 +1,104 @@ +// 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 "chrome/browser/ui/cocoa/color_chooser_mac.h" + +#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" +#include "skia/ext/skia_utils_mac.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" + +@interface NSColorPanel (Private) +// Private method returning the NSColorPanel's target. +- (id)__target; +@end + +namespace { + +class ColorPanelCocoaTest : public CocoaTest { + void SetUp() override { + // Create the color panel and call Init() again to update its initial + // window list to include it. The NSColorPanel cannot be dealloced, so + // without this step the tests will fail complaining that not all windows + // were closed. + [[NSColorPanel sharedColorPanel] makeKeyAndOrderFront:nil]; + Init(); + } +}; + +TEST_F(ColorPanelCocoaTest, ClearTargetAndDelegateOnEnd) { + NSColorPanel* nscolor_panel = [NSColorPanel sharedColorPanel]; + EXPECT_TRUE([nscolor_panel respondsToSelector:@selector(__target)]); + + // Create a ColorPanelCocoa. + ColorChooserMac* color_chooser_mac = + ColorChooserMac::Open(nullptr, SK_ColorBLACK); + + // Confirm the NSColorPanel's configuration by the ColorChooserMac's + // ColorPanelCocoa. + EXPECT_TRUE([nscolor_panel delegate]); + EXPECT_TRUE([nscolor_panel __target]); + + // Release the ColorPanelCocoa and confirm it's no longer the NSColorPanel's + // target or delegate. + color_chooser_mac->End(); + + EXPECT_EQ([nscolor_panel delegate], nil); + EXPECT_EQ([nscolor_panel __target], nil); +} + +TEST_F(ColorPanelCocoaTest, ClearTargetOnEnd) { + NSColorPanel* nscolor_panel = [NSColorPanel sharedColorPanel]; + EXPECT_TRUE([nscolor_panel respondsToSelector:@selector(__target)]); + + // Create a ColorPanelCocoa. + ColorChooserMac* color_chooser_mac = + ColorChooserMac::Open(nullptr, SK_ColorBLACK); + + // Confirm the NSColorPanel's configuration by the ColorChooserMac's + // ColorPanelCocoa. + EXPECT_TRUE([nscolor_panel delegate]); + EXPECT_TRUE([nscolor_panel __target]); + + // Clear the delegate and release the ColorPanelCocoa. + [nscolor_panel setDelegate:nil]; + + // Release the ColorPanelCocoa. + color_chooser_mac->End(); + + // Confirm the ColorPanelCocoa is no longer the NSColorPanel's target or + // delegate. Previously the ColorPanelCocoa would not clear the target if + // the delegate had already been cleared. + EXPECT_EQ([nscolor_panel delegate], nil); + EXPECT_EQ([nscolor_panel __target], nil); +} + +TEST_F(ColorPanelCocoaTest, SetColor) { + // Set the NSColor panel up with an intial color. + NSColor* blue_color = [NSColor blueColor]; + NSColorPanel* nscolor_panel = [NSColorPanel sharedColorPanel]; + [nscolor_panel setColor:blue_color]; + EXPECT_TRUE([[nscolor_panel color] isEqual:blue_color]); + + // Create a ColorChooserMac and confirm the NSColorPanel gets its initial + // color. + SkColor initial_color = SK_ColorBLACK; + ColorChooserMac* color_chooser_mac = + ColorChooserMac::Open(nullptr, SK_ColorBLACK); + + EXPECT_NSEQ([nscolor_panel color], + skia::SkColorToDeviceNSColor(initial_color)); + + // Confirm that -[ColorPanelCocoa setColor:] sets the NSColorPanel's color. + SkColor test_color = SK_ColorRED; + color_chooser_mac->SetSelectedColor(test_color); + + EXPECT_NSEQ([nscolor_panel color], skia::SkColorToDeviceNSColor(test_color)); + + // Clean up. + color_chooser_mac->End(); +} + +} // namespace
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.cc b/chrome/browser/ui/webui/settings/appearance_handler.cc index dae38e4..3209963 100644 --- a/chrome/browser/ui/webui/settings/appearance_handler.cc +++ b/chrome/browser/ui/webui/settings/appearance_handler.cc
@@ -14,6 +14,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" +#include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chromeos/login/login_state.h" #endif @@ -114,7 +115,7 @@ const base::ListValue* /*args*/) { if (!chromeos::WallpaperManager::Get()->IsPolicyControlled( user_manager::UserManager::Get()->GetActiveUser()->GetAccountId())) { - chromeos::WallpaperManager::Get()->Open(); + WallpaperControllerClient::Get()->OpenWallpaperPicker(); } } #endif
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 06433a4..476949f 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -35,8 +35,10 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/ash_switches.h" +#include "ash/public/interfaces/voice_interaction_controller.mojom.h" #include "ash/strings/grit/ash_strings.h" #include "base/sys_info.h" +#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" @@ -1169,6 +1171,7 @@ {"editPasswordPasswordLabel", IDS_SETTINGS_PASSWORDS_PASSWORD}, {"noAddressesFound", IDS_SETTINGS_ADDRESS_NONE}, {"noCreditCardsFound", IDS_SETTINGS_CREDIT_CARD_NONE}, + {"noCreditCardsPolicy", IDS_SETTINGS_CREDIT_CARD_DISABLED}, {"noPasswordsFound", IDS_SETTINGS_PASSWORDS_NONE}, {"noExceptionsFound", IDS_SETTINGS_PASSWORDS_EXCEPTIONS_NONE}, {"import", IDS_PASSWORD_MANAGER_IMPORT_BUTTON}, @@ -1593,17 +1596,15 @@ void AddSearchStrings(content::WebUIDataSource* html_source, Profile* profile) { #if defined(OS_CHROMEOS) - const bool is_user_primary = - chromeos::ProfileHelper::Get()->GetUserByProfile(profile) == - user_manager::UserManager::Get()->GetPrimaryUser(); + const bool is_assistant_allowed = + arc::IsAssistantAllowedForProfile(profile) == + ash::mojom::AssistantAllowedState::ALLOWED; #endif LocalizedString localized_strings[] = { #if defined(OS_CHROMEOS) - {"searchPageTitle", !profile->IsSupervised() && is_user_primary && - chromeos::switches::IsVoiceInteractionEnabled() - ? IDS_SETTINGS_SEARCH_AND_ASSISTANT - : IDS_SETTINGS_SEARCH}, + {"searchPageTitle", is_assistant_allowed ? IDS_SETTINGS_SEARCH_AND_ASSISTANT + : IDS_SETTINGS_SEARCH}, #else {"searchPageTitle", IDS_SETTINGS_SEARCH}, #endif @@ -1641,9 +1642,7 @@ base::ASCIIToUTF16(chrome::kOmniboxLearnMoreURL)); html_source->AddString("searchExplanation", search_explanation_text); #if defined(OS_CHROMEOS) - html_source->AddBoolean( - "enableVoiceInteraction", - chromeos::switches::IsVoiceInteractionEnabled() && is_user_primary); + html_source->AddBoolean("enableVoiceInteraction", is_assistant_allowed); #endif }
diff --git a/chrome/browser/vr/service/vr_device_manager.cc b/chrome/browser/vr/service/vr_device_manager.cc index 45b77fc..3948672 100644 --- a/chrome/browser/vr/service/vr_device_manager.cc +++ b/chrome/browser/vr/service/vr_device_manager.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" #include "build/build_config.h" +#include "chrome/common/chrome_features.h" #include "device/vr/features/features.h" #if defined(OS_ANDROID) @@ -35,7 +36,8 @@ #endif #if BUILDFLAG(ENABLE_OPENVR) - providers.emplace_back(std::make_unique<device::OpenVRDeviceProvider>()); + if (base::FeatureList::IsEnabled(features::kOpenVR)) + providers.emplace_back(std::make_unique<device::OpenVRDeviceProvider>()); #endif new VRDeviceManager(std::move(providers)); }
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 0bafcbc..f864568 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -227,6 +227,10 @@ #endif // BUILDFLAG(ENABLE_VR) || defined(OS_ANDROID) #if BUILDFLAG(ENABLE_VR) +// Enables the virtual keyboard for Chrome VR. +const base::Feature kVrBrowserKeyboard{"VrBrowserKeyboard", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls features related to VR browsing that are under development. const base::Feature kVrBrowsingExperimentalFeatures{ "VrBrowsingExperimentalFeatures", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -234,6 +238,12 @@ // Controls experimental rendering features for VR browsing. const base::Feature kVrBrowsingExperimentalRendering{ "VrBrowsingExperimentalRendering", base::FEATURE_DISABLED_BY_DEFAULT}; + +#if BUILDFLAG(ENABLE_OPENVR) +// Controls OpenVR support. +const base::Feature kOpenVR{"OpenVR", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif // ENABLE_OPENVR + #endif // BUILDFLAG(ENABLE_VR) #if defined(OS_WIN) @@ -485,8 +495,7 @@ #if defined(OS_CHROMEOS) // Enables or disables the ability to add a Samba Share to the Files app -const base::Feature kNativeSamba{"NativeSamba", - base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNativeSmb{"NativeSmb", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_CHROMEOS) // Enables or disables the ability to use the sound content setting to mute a
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 98866ad..2d4341d 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -118,9 +118,15 @@ extern const base::Feature kVrBrowsing; #endif #if BUILDFLAG(ENABLE_VR) +extern const base::Feature kVrBrowserKeyboard; extern const base::Feature kVrBrowsingExperimentalFeatures; extern const base::Feature kVrBrowsingExperimentalRendering; -#endif + +#if BUILDFLAG(ENABLE_OPENVR) +extern const base::Feature kOpenVR; +#endif // ENABLE_OPENVR + +#endif // ENABLE_VR #if defined(OS_MACOSX) extern const base::Feature kFullscreenToolbarReveal; @@ -253,7 +259,7 @@ #endif #if defined(OS_CHROMEOS) -extern const base::Feature kNativeSamba; +extern const base::Feature kNativeSmb; #endif extern const base::Feature kSoundContentSetting;
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js b/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js index 5427d468..f3fb248 100644 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js +++ b/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js
@@ -7,7 +7,7 @@ chrome.browserAction.setBadgeText({text: ''}); chrome.notifications.create({ type: 'basic', - iconUrl: 'drink_water.png', + iconUrl: 'stay_hydrated.png', title: 'Time to Hydrate', message: 'Everyday I\'m Guzzlin\'!', buttons: [
diff --git a/chrome/common/media_router/media_route.h b/chrome/common/media_router/media_route.h index 15b2e4d..f89789a0 100644 --- a/chrome/common/media_router/media_route.h +++ b/chrome/common/media_router/media_route.h
@@ -32,7 +32,7 @@ // |media_route_id|: ID of the route. // |media_source|: Description of source of the route. // |media_sink|: The sink that is receiving the media. - // |description|: Description of the route to be displayed. + // |description|: Human readable description of the casting activity. // |is_local|: true if the route was created from this browser. // |custom_controller_path|: custom controller path if it is given by route // provider. empty otherwise. @@ -126,8 +126,8 @@ // The ID of sink being routed to. MediaSink::Id media_sink_id_; - // The description of the media route activity, for example - // "Playing Foo Bar Music All Access." + // Human readable description of the casting activity. Examples: + // "Mirroring tab (www.example.com)", "Casting media", "Casting YouTube" std::string description_; // |true| if the route is created locally (versus discovered by a media route
diff --git a/chrome/common/media_router/media_status.h b/chrome/common/media_router/media_status.h index dc1d988..cac78a8 100644 --- a/chrome/common/media_router/media_status.h +++ b/chrome/common/media_router/media_status.h
@@ -36,6 +36,8 @@ // Text describing the media, or a secondary title. For example, in a // MediaStatus representing a YouTube Cast session, this could be "YouTube". + // + // DEPRECATED. TODO(crbug.com/786208): Remove this when no longer used. std::string description; // If this is true, the media can be played and paused.
diff --git a/chrome/common/media_router/mojo/media_router.mojom b/chrome/common/media_router/mojo/media_router.mojom index fd07ad3..97e4a434 100644 --- a/chrome/common/media_router/mojo/media_router.mojom +++ b/chrome/common/media_router/mojo/media_router.mojom
@@ -30,6 +30,11 @@ // The human-readable name, e.g. "Janet's Chromecast". string name; // Optional description of the sink. + // + // DEPRECATED. This is currently used in the Media Router UX to relay a + // Hangouts meeting name. It should not be used for other purposes. + // TODO(crbug.com/786208): Remove this at a future date when Hangouts names + // are no longer required. string? description; // Optional domain of the sink if this sink is associated with an identity. string? domain; @@ -93,7 +98,11 @@ string? media_source; // The ID of sink that is rendering the media content. string media_sink_id; - // Human readable description of this route, e.g. "Tab casting". + // Human readable description of the casting activity. Examples: + // "Mirroring tab (www.example.com)", "Casting media", "Casting YouTube" + // + // TODO(crbug.com/786208): Localize this properly by passing it in a way that + // permits use of template strings and placeholders. string description; // Specifies that the route is requested locally. bool is_local;
diff --git a/chrome/common/media_router/mojo/media_status.mojom b/chrome/common/media_router/mojo/media_status.mojom index b70fc812..09b6684 100644 --- a/chrome/common/media_router/mojo/media_status.mojom +++ b/chrome/common/media_router/mojo/media_status.mojom
@@ -16,12 +16,19 @@ BUFFERING }; - // The main title of the media. For example, in a MediaStatus representing - // a YouTube Cast session, this could be the title of the video. + // The title of the currently playing media. For example, in a MediaStatus + // representing a YouTube Cast route, this is the title of the video. + // For a tab mirroring or media remoting route, it's the page title. + // For a Presentation API route, it is the presentation page title. string title; // Text describing the media, or a secondary title. For example, in a // MediaStatus representing a YouTube Cast session, this could be "YouTube". + // + // DEPRECATED. This is used to override MediaRoute.description (defined in + // media_router.mojom) in the Media Router UX. We will be using + // MediaRoute.description exclusively once all MRPs have been updated. + // TODO(crbug.com/786208): Remove this when that is done. string description; // If this is true, the media can be played and paused through its
diff --git a/chrome/installer/linux/rpm/dist_package_provides.json b/chrome/installer/linux/rpm/dist_package_provides.json index 1fa6a5b..7866294 100644 --- a/chrome/installer/linux/rpm/dist_package_provides.json +++ b/chrome/installer/linux/rpm/dist_package_provides.json
@@ -483,6 +483,252 @@ "libstdc++.so.6(GLIBCXX_3.4.9)(64bit)", "libxcb.so.1()(64bit)" ], + "Fedora 27": [ + "ld-linux-x86-64.so.2()(64bit)", + "ld-linux-x86-64.so.2(GLIBC_2.2.5)(64bit)", + "ld-linux-x86-64.so.2(GLIBC_2.3)(64bit)", + "ld-linux-x86-64.so.2(GLIBC_2.4)(64bit)", + "libX11-xcb.so.1()(64bit)", + "libX11.so.6()(64bit)", + "libXcomposite.so.1()(64bit)", + "libXcursor.so.1()(64bit)", + "libXdamage.so.1()(64bit)", + "libXext.so.6()(64bit)", + "libXfixes.so.3()(64bit)", + "libXi.so.6()(64bit)", + "libXrandr.so.2()(64bit)", + "libXrender.so.1()(64bit)", + "libXss.so.1()(64bit)", + "libXtst.so.6()(64bit)", + "libasound.so.2()(64bit)", + "libasound.so.2(ALSA_0.9)(64bit)", + "libasound.so.2(ALSA_0.9.0)(64bit)", + "libasound.so.2(ALSA_0.9.0rc4)(64bit)", + "libasound.so.2(ALSA_0.9.0rc8)(64bit)", + "libasound.so.2(ALSA_0.9.3)(64bit)", + "libasound.so.2(ALSA_0.9.5)(64bit)", + "libasound.so.2(ALSA_0.9.7)(64bit)", + "libatk-1.0.so.0()(64bit)", + "libatk-bridge-2.0.so.0()(64bit)", + "libc.so.6()(64bit)", + "libc.so.6(GLIBC_2.10)(64bit)", + "libc.so.6(GLIBC_2.11)(64bit)", + "libc.so.6(GLIBC_2.12)(64bit)", + "libc.so.6(GLIBC_2.13)(64bit)", + "libc.so.6(GLIBC_2.14)(64bit)", + "libc.so.6(GLIBC_2.15)(64bit)", + "libc.so.6(GLIBC_2.16)(64bit)", + "libc.so.6(GLIBC_2.17)(64bit)", + "libc.so.6(GLIBC_2.18)(64bit)", + "libc.so.6(GLIBC_2.2.5)(64bit)", + "libc.so.6(GLIBC_2.2.6)(64bit)", + "libc.so.6(GLIBC_2.22)(64bit)", + "libc.so.6(GLIBC_2.23)(64bit)", + "libc.so.6(GLIBC_2.24)(64bit)", + "libc.so.6(GLIBC_2.25)(64bit)", + "libc.so.6(GLIBC_2.26)(64bit)", + "libc.so.6(GLIBC_2.3)(64bit)", + "libc.so.6(GLIBC_2.3.2)(64bit)", + "libc.so.6(GLIBC_2.3.3)(64bit)", + "libc.so.6(GLIBC_2.3.4)(64bit)", + "libc.so.6(GLIBC_2.4)(64bit)", + "libc.so.6(GLIBC_2.5)(64bit)", + "libc.so.6(GLIBC_2.6)(64bit)", + "libc.so.6(GLIBC_2.7)(64bit)", + "libc.so.6(GLIBC_2.8)(64bit)", + "libc.so.6(GLIBC_2.9)(64bit)", + "libcairo.so()(64bit)", + "libcairo.so.2()(64bit)", + "libcups.so.2()(64bit)", + "libdbus-1.so.3()(64bit)", + "libdbus-1.so.3(LIBDBUS_1_3)(64bit)", + "libdbus-1.so.3(LIBDBUS_PRIVATE_1.12.0)(64bit)", + "libdl.so.2()(64bit)", + "libdl.so.2(GLIBC_2.2.5)(64bit)", + "libdl.so.2(GLIBC_2.3.3)(64bit)", + "libdl.so.2(GLIBC_2.3.4)(64bit)", + "libexpat.so.1()(64bit)", + "libfontconfig.so.1()(64bit)", + "libgcc_s.so.1()(64bit)", + "libgcc_s.so.1(GCC_3.0)(64bit)", + "libgcc_s.so.1(GCC_3.3)(64bit)", + "libgcc_s.so.1(GCC_3.3.1)(64bit)", + "libgcc_s.so.1(GCC_3.4)(64bit)", + "libgcc_s.so.1(GCC_3.4.2)(64bit)", + "libgcc_s.so.1(GCC_3.4.4)(64bit)", + "libgcc_s.so.1(GCC_4.0.0)(64bit)", + "libgcc_s.so.1(GCC_4.2.0)(64bit)", + "libgcc_s.so.1(GCC_4.3.0)(64bit)", + "libgcc_s.so.1(GCC_4.7.0)(64bit)", + "libgcc_s.so.1(GCC_4.8.0)(64bit)", + "libgcc_s.so.1(GCC_7.0.0)(64bit)", + "libgconf-2.so.4()(64bit)", + "libgdk-3.so.0()(64bit)", + "libgdk_pixbuf-2.0.so.0()(64bit)", + "libgio-2.0.so.0()(64bit)", + "libglib-2.0.so.0()(64bit)", + "libgmodule-2.0.so.0()(64bit)", + "libgobject-2.0.so.0()(64bit)", + "libgtk-3.so.0()(64bit)", + "libm.so.6()(64bit)", + "libm.so.6(GLIBC_2.15)(64bit)", + "libm.so.6(GLIBC_2.18)(64bit)", + "libm.so.6(GLIBC_2.2.5)(64bit)", + "libm.so.6(GLIBC_2.23)(64bit)", + "libm.so.6(GLIBC_2.24)(64bit)", + "libm.so.6(GLIBC_2.25)(64bit)", + "libm.so.6(GLIBC_2.26)(64bit)", + "libm.so.6(GLIBC_2.4)(64bit)", + "libnspr4.so()(64bit)", + "libnss3.so()(64bit)", + "libnss3.so(NSS_3.10)(64bit)", + "libnss3.so(NSS_3.10.2)(64bit)", + "libnss3.so(NSS_3.11)(64bit)", + "libnss3.so(NSS_3.11.1)(64bit)", + "libnss3.so(NSS_3.11.2)(64bit)", + "libnss3.so(NSS_3.11.7)(64bit)", + "libnss3.so(NSS_3.11.9)(64bit)", + "libnss3.so(NSS_3.12)(64bit)", + "libnss3.so(NSS_3.12.1)(64bit)", + "libnss3.so(NSS_3.12.10)(64bit)", + "libnss3.so(NSS_3.12.3)(64bit)", + "libnss3.so(NSS_3.12.4)(64bit)", + "libnss3.so(NSS_3.12.5)(64bit)", + "libnss3.so(NSS_3.12.6)(64bit)", + "libnss3.so(NSS_3.12.7)(64bit)", + "libnss3.so(NSS_3.12.9)(64bit)", + "libnss3.so(NSS_3.13)(64bit)", + "libnss3.so(NSS_3.13.2)(64bit)", + "libnss3.so(NSS_3.14)(64bit)", + "libnss3.so(NSS_3.14.1)(64bit)", + "libnss3.so(NSS_3.14.3)(64bit)", + "libnss3.so(NSS_3.15)(64bit)", + "libnss3.so(NSS_3.15.4)(64bit)", + "libnss3.so(NSS_3.16.1)(64bit)", + "libnss3.so(NSS_3.16.2)(64bit)", + "libnss3.so(NSS_3.18)(64bit)", + "libnss3.so(NSS_3.19)(64bit)", + "libnss3.so(NSS_3.19.1)(64bit)", + "libnss3.so(NSS_3.2)(64bit)", + "libnss3.so(NSS_3.2.1)(64bit)", + "libnss3.so(NSS_3.21)(64bit)", + "libnss3.so(NSS_3.22)(64bit)", + "libnss3.so(NSS_3.3)(64bit)", + "libnss3.so(NSS_3.3.1)(64bit)", + "libnss3.so(NSS_3.30)(64bit)", + "libnss3.so(NSS_3.31)(64bit)", + "libnss3.so(NSS_3.33)(64bit)", + "libnss3.so(NSS_3.4)(64bit)", + "libnss3.so(NSS_3.5)(64bit)", + "libnss3.so(NSS_3.6)(64bit)", + "libnss3.so(NSS_3.7)(64bit)", + "libnss3.so(NSS_3.7.1)(64bit)", + "libnss3.so(NSS_3.8)(64bit)", + "libnss3.so(NSS_3.9)(64bit)", + "libnss3.so(NSS_3.9.2)(64bit)", + "libnss3.so(NSS_3.9.3)(64bit)", + "libnssutil3.so()(64bit)", + "libnssutil3.so(NSSUTIL_3.12)(64bit)", + "libnssutil3.so(NSSUTIL_3.12.3)(64bit)", + "libnssutil3.so(NSSUTIL_3.12.5)(64bit)", + "libnssutil3.so(NSSUTIL_3.12.7)(64bit)", + "libnssutil3.so(NSSUTIL_3.13)(64bit)", + "libnssutil3.so(NSSUTIL_3.14)(64bit)", + "libnssutil3.so(NSSUTIL_3.15)(64bit)", + "libnssutil3.so(NSSUTIL_3.17.1)(64bit)", + "libnssutil3.so(NSSUTIL_3.21)(64bit)", + "libnssutil3.so(NSSUTIL_3.24)(64bit)", + "libnssutil3.so(NSSUTIL_3.25)(64bit)", + "libnssutil3.so(NSSUTIL_3.31)(64bit)", + "libnssutil3.so(NSSUTIL_3.33)(64bit)", + "libpango-1.0.so.0()(64bit)", + "libpangocairo-1.0.so.0()(64bit)", + "libpthread.so.0()(64bit)", + "libpthread.so.0(GLIBC_2.11)(64bit)", + "libpthread.so.0(GLIBC_2.12)(64bit)", + "libpthread.so.0(GLIBC_2.18)(64bit)", + "libpthread.so.0(GLIBC_2.2.5)(64bit)", + "libpthread.so.0(GLIBC_2.2.6)(64bit)", + "libpthread.so.0(GLIBC_2.3.2)(64bit)", + "libpthread.so.0(GLIBC_2.3.3)(64bit)", + "libpthread.so.0(GLIBC_2.3.4)(64bit)", + "libpthread.so.0(GLIBC_2.4)(64bit)", + "librt.so.1()(64bit)", + "librt.so.1(GLIBC_2.2.5)(64bit)", + "librt.so.1(GLIBC_2.3.3)(64bit)", + "librt.so.1(GLIBC_2.3.4)(64bit)", + "librt.so.1(GLIBC_2.4)(64bit)", + "librt.so.1(GLIBC_2.7)(64bit)", + "libsmime3.so()(64bit)", + "libsmime3.so(NSS_3.10)(64bit)", + "libsmime3.so(NSS_3.12.10)(64bit)", + "libsmime3.so(NSS_3.12.2)(64bit)", + "libsmime3.so(NSS_3.13)(64bit)", + "libsmime3.so(NSS_3.15)(64bit)", + "libsmime3.so(NSS_3.16)(64bit)", + "libsmime3.so(NSS_3.18)(64bit)", + "libsmime3.so(NSS_3.2)(64bit)", + "libsmime3.so(NSS_3.2.1)(64bit)", + "libsmime3.so(NSS_3.3)(64bit)", + "libsmime3.so(NSS_3.4)(64bit)", + "libsmime3.so(NSS_3.4.1)(64bit)", + "libsmime3.so(NSS_3.6)(64bit)", + "libsmime3.so(NSS_3.7)(64bit)", + "libsmime3.so(NSS_3.7.2)(64bit)", + "libsmime3.so(NSS_3.8)(64bit)", + "libsmime3.so(NSS_3.9)(64bit)", + "libsmime3.so(NSS_3.9.3)(64bit)", + "libstdc++.so.5()(64bit)", + "libstdc++.so.5(CXXABI_1.2)(64bit)", + "libstdc++.so.5(CXXABI_1.2.1)(64bit)", + "libstdc++.so.5(CXXABI_1.2.2)(64bit)", + "libstdc++.so.5(GLIBCPP_3.2)(64bit)", + "libstdc++.so.5(GLIBCPP_3.2.1)(64bit)", + "libstdc++.so.5(GLIBCPP_3.2.2)(64bit)", + "libstdc++.so.5(GLIBCPP_3.2.3)(64bit)", + "libstdc++.so.5(GLIBCPP_3.2.4)(64bit)", + "libstdc++.so.6()(64bit)", + "libstdc++.so.6(CXXABI_1.3)(64bit)", + "libstdc++.so.6(CXXABI_1.3.1)(64bit)", + "libstdc++.so.6(CXXABI_1.3.10)(64bit)", + "libstdc++.so.6(CXXABI_1.3.11)(64bit)", + "libstdc++.so.6(CXXABI_1.3.2)(64bit)", + "libstdc++.so.6(CXXABI_1.3.3)(64bit)", + "libstdc++.so.6(CXXABI_1.3.4)(64bit)", + "libstdc++.so.6(CXXABI_1.3.5)(64bit)", + "libstdc++.so.6(CXXABI_1.3.6)(64bit)", + "libstdc++.so.6(CXXABI_1.3.7)(64bit)", + "libstdc++.so.6(CXXABI_1.3.8)(64bit)", + "libstdc++.so.6(CXXABI_1.3.9)(64bit)", + "libstdc++.so.6(CXXABI_FLOAT128)(64bit)", + "libstdc++.so.6(CXXABI_TM_1)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.1)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.10)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.11)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.12)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.13)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.14)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.15)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.16)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.17)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.18)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.19)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.2)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.20)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.21)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.22)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.23)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.24)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.3)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.4)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.5)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.6)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.7)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.8)(64bit)", + "libstdc++.so.6(GLIBCXX_3.4.9)(64bit)", + "libxcb.so.1()(64bit)" + ], "openSUSE Leap 42.2": [ "ld-linux-x86-64.so.2()(64bit)", "ld-linux-x86-64.so.2(GLIBC_2.2.5)(64bit)",
diff --git a/chrome/installer/linux/rpm/update_package_provides.py b/chrome/installer/linux/rpm/update_package_provides.py index 88d9ae6..feacf8da 100755 --- a/chrome/installer/linux/rpm/update_package_provides.py +++ b/chrome/installer/linux/rpm/update_package_provides.py
@@ -58,7 +58,7 @@ "libxcb.so", ] -SUPPORTED_FEDORA_RELEASES = ['25', '26'] +SUPPORTED_FEDORA_RELEASES = ['25', '26', '27'] SUPPORTED_OPENSUSE_LEAP_RELEASES = ['42.2', '42.3'] COMMON_NS = "http://linux.duke.edu/metadata/common"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4823dd6..fd0f8c56 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2990,6 +2990,7 @@ "../browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc", "../browser/ui/ash/session_controller_client_unittest.cc", "../browser/ui/ash/tablet_mode_client_unittest.cc", + "../browser/ui/ash/wallpaper_controller_client_unittest.cc", "../browser/ui/ash/window_positioner_unittest.cc", "../browser/ui/window_sizer/window_sizer_ash_unittest.cc", ] @@ -3720,6 +3721,7 @@ "../browser/ui/cocoa/bubble_view_unittest.mm", "../browser/ui/cocoa/chrome_browser_window_unittest.mm", "../browser/ui/cocoa/clickhold_button_cell_unittest.mm", + "../browser/ui/cocoa/color_panel_cocoa_unittest.mm", "../browser/ui/cocoa/confirm_bubble_controller_unittest.mm", "../browser/ui/cocoa/confirm_quit_panel_controller_unittest.mm", "../browser/ui/cocoa/constrained_window/constrained_window_alert_unittest.mm",
diff --git a/chrome/test/data/webui/media_router/route_controls_tests.js b/chrome/test/data/webui/media_router/route_controls_tests.js index b0ca648..c681514 100644 --- a/chrome/test/data/webui/media_router/route_controls_tests.js +++ b/chrome/test/data/webui/media_router/route_controls_tests.js
@@ -82,17 +82,11 @@ test('initial text setting', function() { // Set |route|. controls.onRouteUpdated_(fakeRouteOne); - assertElementText( - loadTimeData.getStringF( - 'castingActivityStatus', fakeRouteOne.description), - 'route-description'); + assertElementText(fakeRouteOne.description, 'route-description'); // Set |route| to a different route. controls.onRouteUpdated_(fakeRouteTwo); - assertElementText( - loadTimeData.getStringF( - 'castingActivityStatus', fakeRouteTwo.description), - 'route-description'); + assertElementText(fakeRouteTwo.description, 'route-description'); }); // Tests that the route title and status are shown when RouteStatus is
diff --git a/chrome/test/data/webui/media_router/route_details_tests.js b/chrome/test/data/webui/media_router/route_details_tests.js index a07cbb6..9ccd085 100644 --- a/chrome/test/data/webui/media_router/route_details_tests.js +++ b/chrome/test/data/webui/media_router/route_details_tests.js
@@ -45,9 +45,17 @@ details.$$('#' + elementId).querySelector('span').innerText); }; + // Checks whether |expected| and the text in the element in the + // |elementId| element are equal. + var checkElementText = function(expected, elementId) { + assertEquals( + expected, + details.$$('#' + elementId).innerText); + }; + // Checks the default route view is shown. var checkDefaultViewIsShown = function() { - assertFalse(details.$$('#route-information').hasAttribute('hidden')); + assertFalse(details.$$('#route-description').hasAttribute('hidden')); assertTrue( !details.$$('extension-view-wrapper') || details.$$('extension-view-wrapper').hasAttribute('hidden')); @@ -67,7 +75,7 @@ // Checks the custom controller is shown. var checkCustomControllerIsShown = function() { - assertTrue(details.$$('#route-information').hasAttribute('hidden')); + assertTrue(details.$$('#route-description').hasAttribute('hidden')); assertFalse( details.$$('extension-view-wrapper').hasAttribute('hidden')); }; @@ -182,7 +190,7 @@ checkSpanText( loadTimeData.getString('startCastingButtonText').toUpperCase(), 'start-casting-to-route-button'); - checkSpanText('', 'route-information'); + checkElementText('', 'route-description'); }); // Tests when |route| is undefined or set. @@ -194,16 +202,14 @@ // Set |route|. details.route = fakeRouteOne; assertEquals(fakeRouteOne, details.route); - checkSpanText(loadTimeData.getStringF('castingActivityStatus', - fakeRouteOne.description), 'route-information'); + checkElementText(fakeRouteOne.description, 'route-description'); checkDefaultViewIsShown(); checkStartCastButtonIsNotShown(); // Set |route| to a different route. details.route = fakeRouteTwo; assertEquals(fakeRouteTwo, details.route); - checkSpanText(loadTimeData.getStringF('castingActivityStatus', - fakeRouteTwo.description), 'route-information'); + checkElementText(fakeRouteTwo.description, 'route-description'); checkDefaultViewIsShown(); checkStartCastButtonIsShown(); });
diff --git a/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js b/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js index 2ee6103d..cbbdee0 100644 --- a/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js +++ b/chrome/test/data/webui/settings/passwords_and_forms_browsertest.js
@@ -75,21 +75,26 @@ CrSettingsPrefs.deferInitialization = true; var prefs = document.createElement('settings-prefs'); prefs.initialize(new settings.FakeSettingsPrivate([ - { - key: 'autofill.enabled', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: autofill, - }, - { - key: 'credentials_enable_service', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: passwords, - }, - { - key: 'credentials_enable_autosignin', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: true, - }, + { + key: 'autofill.enabled', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: autofill, + }, + { + key: 'autofill.credit_card_enabled', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: true, + }, + { + key: 'credentials_enable_service', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: passwords, + }, + { + key: 'credentials_enable_autosignin', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: true, + }, ])); CrSettingsPrefs.initialized.then(function() {
diff --git a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js index 95aa556..9b2ee5b 100644 --- a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js +++ b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js
@@ -116,10 +116,11 @@ * Creates the autofill section for the given lists. * @param {!Array<!chrome.passwordsPrivate.PasswordUiEntry>} passwordList * @param {!Array<!chrome.passwordsPrivate.ExceptionEntry>} exceptionList + * @param {!Object} pref_value * @return {!Object} * @private */ - createAutofillSection_: function(addresses, creditCards) { + createAutofillSection_: function(addresses, creditCards, pref_value) { // Override the AutofillManagerImpl for testing. this.autofillManager = new TestAutofillManager(); this.autofillManager.data.addresses = addresses; @@ -127,8 +128,10 @@ AutofillManagerImpl.instance_ = this.autofillManager; var section = document.createElement('settings-autofill-section'); + section.prefs = {autofill: {credit_card_enabled: pref_value}}; document.body.appendChild(section); Polymer.dom.flush(); + return section; }, @@ -168,7 +171,7 @@ test('testAutofillExtensionIndicator', function() { // Initializing with fake prefs var section = document.createElement('settings-autofill-section'); - section.prefs = {autofill: {enabled: {}}}; + section.prefs = {autofill: {enabled: {}, credit_card_enabled: {}}}; document.body.appendChild(section); assertFalse(!!section.$$('#autofillExtensionIndicator')); @@ -196,14 +199,22 @@ }); test('verifyCreditCardCount', function() { - var section = self.createAutofillSection_([], []); + var section = self.createAutofillSection_([], [], {}); - var creditCardList = section.$.creditCardList; + var creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); assertEquals(0, creditCardList.querySelectorAll('.list-item').length); - assertFalse(section.$.noCreditCardsLabel.hidden); - assertTrue(section.$.creditCardsHeading.hidden); + assertFalse(section.$$('#noCreditCardsLabel').hidden); + assertTrue(section.$$('#creditCardsHeading').hidden); + assertTrue(section.$$('#CreditCardsDisabledLabel').hidden); + }); + + test('verifyCreditCardsDisabled', function() { + var section = self.createAutofillSection_([], [], {value: false}); + + assertEquals(0, section.querySelectorAll('#creditCardList').length); + assertFalse(section.$$('#CreditCardsDisabledLabel').hidden); }); test('verifyCreditCardCount', function() { @@ -216,21 +227,21 @@ FakeDataMaker.creditCardEntry(), ]; - var section = self.createAutofillSection_([], creditCards); - - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], creditCards, {}); + var creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); assertEquals(creditCards.length, creditCardList.querySelectorAll('.list-item').length); - assertTrue(section.$.noCreditCardsLabel.hidden); - assertFalse(section.$.creditCardsHeading.hidden); + assertTrue(section.$$('#noCreditCardsLabel').hidden); + assertFalse(section.$$('#creditCardsHeading').hidden); + assertTrue(section.$$('#CreditCardsDisabledLabel').hidden); }); test('verifyCreditCardFields', function() { var creditCard = FakeDataMaker.creditCardEntry(); - var section = self.createAutofillSection_([], [creditCard]); - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], [creditCard], {}); + var creditCardList = section.$$('#creditCardList'); var row = creditCardList.children[0]; assertTrue(!!row); @@ -243,8 +254,8 @@ test('verifyCreditCardRowButtonIsDropdownWhenLocal', function() { var creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isLocal = true; - var section = self.createAutofillSection_([], [creditCard]); - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], [creditCard], {}); + var creditCardList = section.$$('#creditCardList'); var row = creditCardList.children[0]; assertTrue(!!row); var menuButton = row.querySelector('#creditCardMenu'); @@ -256,8 +267,8 @@ test('verifyCreditCardRowButtonIsOutlinkWhenRemote', function() { var creditCard = FakeDataMaker.creditCardEntry(); creditCard.metadata.isLocal = false; - var section = self.createAutofillSection_([], [creditCard]); - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], [creditCard], {}); + var creditCardList = section.$$('#creditCardList'); var row = creditCardList.children[0]; assertTrue(!!row); var menuButton = row.querySelector('#creditCardMenu'); @@ -431,8 +442,8 @@ creditCard.metadata.isLocal = true; creditCard.metadata.isCached = undefined; - var section = self.createAutofillSection_([], [creditCard]); - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], [creditCard], {}); + var creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); assertEquals(1, creditCardList.querySelectorAll('.list-item').length); var row = creditCardList.children[0]; @@ -462,8 +473,8 @@ creditCard.metadata.isLocal = false; creditCard.metadata.isCached = true; - var section = self.createAutofillSection_([], [creditCard]); - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], [creditCard], {}); + var creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); assertEquals(1, creditCardList.querySelectorAll('.list-item').length); var row = creditCardList.children[0]; @@ -493,8 +504,8 @@ creditCard.metadata.isLocal = false; creditCard.metadata.isCached = false; - var section = self.createAutofillSection_([], [creditCard]); - var creditCardList = section.$.creditCardList; + var section = self.createAutofillSection_([], [creditCard], {}); + var creditCardList = section.$$('#creditCardList'); assertTrue(!!creditCardList); assertEquals(1, creditCardList.querySelectorAll('.list-item').length); var row = creditCardList.children[0]; @@ -523,7 +534,7 @@ }); test('verifyNoAddresses', function() { - var section = self.createAutofillSection_([], []); + var section = self.createAutofillSection_([], [], {}); var addressList = section.$.addressList; assertTrue(!!addressList); @@ -542,7 +553,7 @@ FakeDataMaker.addressEntry(), ]; - var section = self.createAutofillSection_(addresses, []); + var section = self.createAutofillSection_(addresses, [], {}); var addressList = section.$.addressList; assertTrue(!!addressList); @@ -554,7 +565,7 @@ test('verifyAddressFields', function() { var address = FakeDataMaker.addressEntry(); - var section = self.createAutofillSection_([address], []); + var section = self.createAutofillSection_([address], [], {}); var addressList = section.$.addressList; var row = addressList.children[0]; assertTrue(!!row); @@ -576,7 +587,7 @@ test('verifyAddressRowButtonIsDropdownWhenLocal', function() { var address = FakeDataMaker.addressEntry(); address.metadata.isLocal = true; - var section = self.createAutofillSection_([address], []); + var section = self.createAutofillSection_([address], [], {}); var addressList = section.$.addressList; var row = addressList.children[0]; assertTrue(!!row); @@ -589,7 +600,7 @@ test('verifyAddressRowButtonIsOutlinkWhenRemote', function() { var address = FakeDataMaker.addressEntry(); address.metadata.isLocal = false; - var section = self.createAutofillSection_([address], []); + var section = self.createAutofillSection_([address], [], {}); var addressList = section.$.addressList; var row = addressList.children[0]; assertTrue(!!row);
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc index f16732a..02cba55 100644 --- a/chromeos/network/network_state_handler.cc +++ b/chromeos/network/network_state_handler.cc
@@ -6,7 +6,9 @@ #include <stddef.h> +#include <limits> #include <memory> +#include <utility> #include "base/bind.h" #include "base/command_line.h" @@ -308,10 +310,11 @@ } const NetworkState* NetworkStateHandler::ConnectedNetworkByType( - const NetworkTypePattern& type) const { - const NetworkState* connected_network = nullptr; + const NetworkTypePattern& type) { + if (!network_list_sorted_) + SortNetworkList(); // Sort to ensure visible networks are listed first. - // Active networks are always listed first by Shill so no need to sort. + const NetworkState* connected_network = nullptr; for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) { const NetworkState* network = (*iter)->AsNetworkState(); DCHECK(network); @@ -428,7 +431,7 @@ } std::string NetworkStateHandler::FormattedHardwareAddressForType( - const NetworkTypePattern& type) const { + const NetworkTypePattern& type) { const NetworkState* network = ConnectedNetworkByType(type); if (network && network->type() == kTypeTether) { // If this is a Tether network, get the MAC address corresponding to that @@ -515,7 +518,7 @@ size_t limit, NetworkStateList* list) { DCHECK(list); - DCHECK(limit != 0); + DCHECK_NE(0U, limit); if (!IsTechnologyEnabled(NetworkTypePattern::Tether())) return; @@ -1301,9 +1304,7 @@ cellular.push_back(std::move(*iter)); continue; } - // Ethernet networks are always considered active. - if (network->IsConnectingOrConnected() || - NetworkTypePattern::Ethernet().MatchesType(network->type())) { + if (network->IsConnectingOrConnected()) { active.push_back(std::move(*iter)); continue; }
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h index 3027a78..fe8a2d3 100644 --- a/chromeos/network/network_state_handler.h +++ b/chromeos/network/network_state_handler.h
@@ -161,8 +161,7 @@ const NetworkState* DefaultNetwork() const; // Returns the primary connected network of matching |type|, otherwise NULL. - const NetworkState* ConnectedNetworkByType( - const NetworkTypePattern& type) const; + const NetworkState* ConnectedNetworkByType(const NetworkTypePattern& type); // Like ConnectedNetworkByType() but returns a connecting network or NULL. const NetworkState* ConnectingNetworkByType( @@ -175,8 +174,7 @@ // Returns the aa:bb formatted hardware (MAC) address for the first connected // network matching |type|, or an empty string if none is connected. - std::string FormattedHardwareAddressForType( - const NetworkTypePattern& type) const; + std::string FormattedHardwareAddressForType(const NetworkTypePattern& type); // Convenience method to call GetNetworkListByType(visible=true). void GetVisibleNetworkListByType(const NetworkTypePattern& type,
diff --git a/components/flags_ui/resources/flags.css b/components/flags_ui/resources/flags.css index 400875b..e119df0 100644 --- a/components/flags_ui/resources/flags.css +++ b/components/flags_ui/resources/flags.css
@@ -363,7 +363,10 @@ /* Bottom padding should be greater than evaluated height of needs-restart */ padding-bottom: 200px; position: relative; + /* iOS does not show unsupported experiments. */ +<if expr="not is_ios"> width: 200%; +</if> } .tabs li:nth-child(2) .tab-content {
diff --git a/components/flags_ui/resources/flags.html b/components/flags_ui/resources/flags.html index 3f7761e..36dda60 100644 --- a/components/flags_ui/resources/flags.html +++ b/components/flags_ui/resources/flags.html
@@ -2,16 +2,18 @@ <html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1.0"> <if expr="not is_ios"> -<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> </if> + <link rel="stylesheet" href="flags.css"> <if expr="is_ios"> -<link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> -<!-- TODO(crbug.com/487000): Remove this once injected by web. --> -<script src="chrome://resources/js/ios/web_ui.js"></script> + <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=1"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> + <!-- TODO(crbug.com/487000): Remove this once injected by web. --> + <script src="chrome://resources/js/ios/web_ui.js"></script> </if> <script src="chrome://resources/js/util.js"></script>
diff --git a/components/history/core/browser/typed_url_model_type_controller.cc b/components/history/core/browser/typed_url_model_type_controller.cc index 18398bb..b158782 100644 --- a/components/history/core/browser/typed_url_model_type_controller.cc +++ b/components/history/core/browser/typed_url_model_type_controller.cc
@@ -25,8 +25,8 @@ // the tasks we want to run. class RunTaskOnHistoryThread : public HistoryDBTask { public: - explicit RunTaskOnHistoryThread(const ModelTypeController::BridgeTask& task) - : task_(task) {} + explicit RunTaskOnHistoryThread(ModelTypeController::BridgeTask task) + : task_(std::move(task)) {} bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) override { // Invoke the task, then free it immediately so we don't keep a reference @@ -34,13 +34,9 @@ // main thread - we want to release references as soon as possible to avoid // keeping them around too long during shutdown. TypedURLSyncBridge* bridge = backend->GetTypedURLSyncBridge(); - if (!bridge) { - NOTREACHED(); - return true; - } + DCHECK(bridge); - task_.Run(bridge); - task_.Reset(); + std::move(task_).Run(bridge); return true; } @@ -73,7 +69,7 @@ } void TypedURLModelTypeController::PostBridgeTask(const base::Location& location, - const BridgeTask& task) { + BridgeTask task) { history::HistoryService* history = sync_client()->GetHistoryService(); if (!history) { // History must be disabled - don't start. @@ -81,8 +77,9 @@ return; } - history->ScheduleDBTask(std::make_unique<RunTaskOnHistoryThread>(task), - &task_tracker_); + history->ScheduleDBTask( + std::make_unique<RunTaskOnHistoryThread>(std::move(task)), + &task_tracker_); } void TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged() {
diff --git a/components/history/core/browser/typed_url_model_type_controller.h b/components/history/core/browser/typed_url_model_type_controller.h index 0ef777d..d528d40 100644 --- a/components/history/core/browser/typed_url_model_type_controller.h +++ b/components/history/core/browser/typed_url_model_type_controller.h
@@ -23,8 +23,7 @@ private: // syncer::ModelTypeController implementation. - void PostBridgeTask(const base::Location& location, - const BridgeTask& task) override; + void PostBridgeTask(const base::Location& location, BridgeTask task) override; void OnSavingBrowserHistoryDisabledChanged();
diff --git a/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc b/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc index 92bf0d2..53151cf 100644 --- a/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc +++ b/components/ntp_snippets/offline_pages/offline_pages_test_utils.cc
@@ -21,10 +21,7 @@ namespace ntp_snippets { namespace test { -FakeOfflinePageModel::FakeOfflinePageModel() { - // This is to match StubOfflinePageModel behavior. - is_loaded_ = true; -} +FakeOfflinePageModel::FakeOfflinePageModel() = default; FakeOfflinePageModel::~FakeOfflinePageModel() = default; @@ -65,14 +62,6 @@ return &items_; } -bool FakeOfflinePageModel::is_loaded() const { - return is_loaded_; -} - -void FakeOfflinePageModel::set_is_loaded(bool value) { - is_loaded_ = value; -} - OfflinePageItem CreateDummyOfflinePageItem( int id, const offline_pages::ClientId& client_id) {
diff --git a/components/ntp_snippets/offline_pages/offline_pages_test_utils.h b/components/ntp_snippets/offline_pages/offline_pages_test_utils.h index bbd1ed7..56657af0 100644 --- a/components/ntp_snippets/offline_pages/offline_pages_test_utils.h +++ b/components/ntp_snippets/offline_pages/offline_pages_test_utils.h
@@ -30,12 +30,8 @@ const std::vector<offline_pages::OfflinePageItem>& items(); std::vector<offline_pages::OfflinePageItem>* mutable_items(); - bool is_loaded() const override; - void set_is_loaded(bool value); - private: std::vector<offline_pages::OfflinePageItem> items_; - bool is_loaded_; DISALLOW_COPY_AND_ASSIGN(FakeOfflinePageModel); };
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.cc b/components/offline_pages/core/model/offline_page_model_taskified.cc index bbb612f0..7299e279 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -254,13 +254,6 @@ return archive_manager_->GetPersistentArchivesDir(); } -bool OfflinePageModelTaskified::is_loaded() const { - NOTIMPLEMENTED(); - // TODO(romax): Remove the method after switch. No longer needed with - // DB.Execute pattern. - return false; -} - ClientPolicyController* OfflinePageModelTaskified::GetPolicyController() { return policy_controller_.get(); }
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.h b/components/offline_pages/core/model/offline_page_model_taskified.h index 747070b4..d924c06 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.h +++ b/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -109,8 +109,6 @@ ClientPolicyController* GetPolicyController() override; - bool is_loaded() const override; - OfflineEventLogger* GetLogger() override; // Methods for testing only:
diff --git a/components/offline_pages/core/offline_page_model.h b/components/offline_pages/core/offline_page_model.h index 2b8dfbe..63f999d 100644 --- a/components/offline_pages/core/offline_page_model.h +++ b/components/offline_pages/core/offline_page_model.h
@@ -201,9 +201,6 @@ virtual const base::FilePath& GetArchiveDirectory( const std::string& name_space) const = 0; - // TODO(dougarnett): Remove this and its uses. - virtual bool is_loaded() const = 0; - // Returns the logger. Ownership is retained by the model. virtual OfflineEventLogger* GetLogger() = 0; };
diff --git a/components/offline_pages/core/offline_page_model_impl.cc b/components/offline_pages/core/offline_page_model_impl.cc index 1932493..a5c7bfd1 100644 --- a/components/offline_pages/core/offline_page_model_impl.cc +++ b/components/offline_pages/core/offline_page_model_impl.cc
@@ -709,10 +709,6 @@ return storage_manager_.get(); } -bool OfflinePageModelImpl::is_loaded() const { - return is_loaded_; -} - OfflineEventLogger* OfflinePageModelImpl::GetLogger() { return &offline_event_logger_; }
diff --git a/components/offline_pages/core/offline_page_model_impl.h b/components/offline_pages/core/offline_page_model_impl.h index a00f407..7941c179 100644 --- a/components/offline_pages/core/offline_page_model_impl.h +++ b/components/offline_pages/core/offline_page_model_impl.h
@@ -115,8 +115,6 @@ OfflinePageStorageManager* GetStorageManager(); - bool is_loaded() const override; - OfflineEventLogger* GetLogger() override; void set_skip_clearing_original_url_for_testing() { @@ -130,6 +128,7 @@ private: FRIEND_TEST_ALL_PREFIXES(OfflinePageModelImplTest, MarkPageForDeletion); + FRIEND_TEST_ALL_PREFIXES(OfflinePageModelImplTest, StoreLoadFailurePersists); typedef std::vector<std::unique_ptr<OfflinePageArchiver>> PendingArchivers;
diff --git a/components/offline_pages/core/offline_page_model_impl_unittest.cc b/components/offline_pages/core/offline_page_model_impl_unittest.cc index 906c176c..30fc4a0 100644 --- a/components/offline_pages/core/offline_page_model_impl_unittest.cc +++ b/components/offline_pages/core/offline_page_model_impl_unittest.cc
@@ -1468,7 +1468,7 @@ // Model will 'load' but the store underneath it is not functional and // will silently fail all sql operations. - EXPECT_TRUE(model()->is_loaded()); + EXPECT_TRUE(model()->is_loaded_); EXPECT_EQ(StoreState::FAILED_LOADING, GetStore()->state()); EXPECT_EQ(0UL, offline_pages.size());
diff --git a/components/offline_pages/core/stub_offline_page_model.cc b/components/offline_pages/core/stub_offline_page_model.cc index 67e51ab..b640a6f 100644 --- a/components/offline_pages/core/stub_offline_page_model.cc +++ b/components/offline_pages/core/stub_offline_page_model.cc
@@ -63,9 +63,6 @@ ClientPolicyController* StubOfflinePageModel::GetPolicyController() { return &policy_controller_; } -bool StubOfflinePageModel::is_loaded() const { - return true; -} OfflineEventLogger* StubOfflinePageModel::GetLogger() { return nullptr; }
diff --git a/components/offline_pages/core/stub_offline_page_model.h b/components/offline_pages/core/stub_offline_page_model.h index edd496c..5ebf05e6 100644 --- a/components/offline_pages/core/stub_offline_page_model.h +++ b/components/offline_pages/core/stub_offline_page_model.h
@@ -65,7 +65,6 @@ const base::FilePath& GetArchiveDirectory( const std::string& name_space) const override; ClientPolicyController* GetPolicyController() override; - bool is_loaded() const override; OfflineEventLogger* GetLogger() override; private:
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index 2800707..0d97840 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -895,6 +895,11 @@ "engine_impl/js_mutation_event_observer_unittest.cc", "engine_impl/js_sync_encryption_handler_observer_unittest.cc", "engine_impl/js_sync_manager_observer_unittest.cc", + "engine_impl/loopback_server/loopback_server_unittest.cc", + "engine_impl/loopback_server/persistent_bookmark_entity_unittest.cc", + "engine_impl/loopback_server/persistent_permanent_entity_unittest.cc", + "engine_impl/loopback_server/persistent_tombstone_entity_unittest.cc", + "engine_impl/loopback_server/persistent_unique_client_entity_unittest.cc", "engine_impl/model_type_registry_unittest.cc", "engine_impl/model_type_worker_unittest.cc", "engine_impl/net/sync_server_connection_manager_unittest.cc", @@ -997,10 +1002,6 @@ sources -= [ "engine/net/http_bridge_unittest.cc" ] } - if (is_win) { - sources += [ "engine_impl/loopback_server/loopback_server_unittest.cc" ] - } - if (!is_ios) { sources += [ "driver/sync_policy_handler_unittest.cc" ] deps += [
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc index c08dfba..83be1bc9 100644 --- a/components/sync/driver/model_type_controller.cc +++ b/components/sync/driver/model_type_controller.cc
@@ -52,11 +52,10 @@ return arg; } -void RunBridgeTask(const BridgeProvider& bridge_provider, - const BridgeTask& task) { - if (base::WeakPtr<ModelTypeSyncBridge> bridge = bridge_provider.Run()) { - task.Run(bridge.get()); - } +void RunBridgeTask(BridgeProvider bridge_provider, BridgeTask task) { + base::WeakPtr<ModelTypeSyncBridge> bridge = std::move(bridge_provider).Run(); + if (bridge.get()) + std::move(task).Run(bridge.get()); } } // namespace @@ -263,10 +262,11 @@ } void ModelTypeController::PostBridgeTask(const base::Location& location, - const BridgeTask& task) { + BridgeTask task) { DCHECK(model_thread_); model_thread_->PostTask( - location, base::Bind(&RunBridgeTask, GetBridgeProvider(), task)); + location, base::Bind(&RunBridgeTask, base::Passed(GetBridgeProvider()), + base::Passed(std::move(task)))); } } // namespace syncer
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h index 02cfb77..ae9007d 100644 --- a/components/sync/driver/model_type_controller.h +++ b/components/sync/driver/model_type_controller.h
@@ -27,8 +27,9 @@ // DataTypeController implementation for Unified Sync and Storage model types. class ModelTypeController : public DataTypeController { public: - using BridgeProvider = base::Callback<base::WeakPtr<ModelTypeSyncBridge>()>; - using BridgeTask = base::Callback<void(ModelTypeSyncBridge*)>; + using BridgeProvider = + base::OnceCallback<base::WeakPtr<ModelTypeSyncBridge>()>; + using BridgeTask = base::OnceCallback<void(ModelTypeSyncBridge*)>; ModelTypeController( ModelType type, @@ -76,8 +77,7 @@ // Post the given task that requires the bridge object to run to the model // thread, where the bridge lives. - virtual void PostBridgeTask(const base::Location& location, - const BridgeTask& task); + virtual void PostBridgeTask(const base::Location& location, BridgeTask task); // The sync client, which provides access to this type's ModelTypeSyncBridge. SyncClient* const sync_client_;
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc index 756a6fc..5d049175 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.cc +++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -255,6 +255,9 @@ *server_status = HttpResponse::SYNC_SERVER_ERROR; *response_code = net::ERR_FAILED; *response = string(); + UMA_HISTOGRAM_ENUMERATION( + "Sync.Local.RequestTypeOnError", message.message_contents(), + sync_pb::ClientToServerMessage_Contents_Contents_MAX); return; } @@ -289,9 +292,8 @@ } bool send_encryption_keys_based_on_nigori = false; - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); - ++it) { - const LoopbackServerEntity& entity = *it->second; + for (const auto& kv : entities_) { + const LoopbackServerEntity& entity = *kv.second; if (sieve->ClientWantsItem(entity)) { sync_pb::SyncEntity* response_entity = response->add_entries(); entity.SerializeAsProto(response_entity); @@ -306,9 +308,8 @@ if (send_encryption_keys_based_on_nigori || get_updates.need_encryption_key()) { - for (vector<string>::iterator it = keystore_keys_.begin(); - it != keystore_keys_.end(); ++it) { - response->add_encryption_keys(*it); + for (const string& key : keystore_keys_) { + response->add_encryption_keys(key); } } @@ -329,7 +330,9 @@ syncer::ModelType type = GetModelType(client_entity); if (client_entity.deleted()) { entity = PersistentTombstoneEntity::CreateFromEntity(client_entity); - DeleteChildren(client_entity.id_string()); + if (entity) { + DeleteChildren(client_entity.id_string()); + } } else if (type == syncer::NIGORI) { // NIGORI is the only permanent item type that should be updated by the // client. @@ -351,6 +354,9 @@ entity = PersistentUniqueClientEntity::CreateFromEntity(client_entity); } + if (!entity) + return string(); + const std::string id = entity->GetId(); SaveEntity(std::move(entity)); BuildEntryResponseForSuccessfulCommit(id, entry_response); @@ -398,11 +404,11 @@ return IsChild(entity.GetParentId(), potential_parent_id); } -void LoopbackServer::DeleteChildren(const string& id) { +void LoopbackServer::DeleteChildren(const string& parent_id) { std::vector<sync_pb::SyncEntity> tombstones; - // Find all the children of id. + // Find all the children of |parent_id|. for (auto& entity : entities_) { - if (IsChild(entity.first, id)) { + if (IsChild(entity.first, parent_id)) { sync_pb::SyncEntity proto; entity.second->SerializeAsProto(&proto); tombstones.emplace_back(proto); @@ -423,12 +429,10 @@ ModelTypeSet committed_model_types; // TODO(pvalenzuela): Add validation of CommitMessage.entries. - ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it; - for (it = commit.entries().begin(); it != commit.entries().end(); ++it) { + for (const sync_pb::SyncEntity& client_entity : commit.entries()) { sync_pb::CommitResponse_EntryResponse* entry_response = response->add_entryresponse(); - sync_pb::SyncEntity client_entity = *it; string parent_id = client_entity.parent_id_string(); if (client_to_server_ids.find(parent_id) != client_to_server_ids.end()) { parent_id = client_to_server_ids[parent_id]; @@ -474,9 +478,8 @@ ModelType model_type) { DCHECK(thread_checker_.CalledOnValidThread()); std::vector<sync_pb::SyncEntity> sync_entities; - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); - ++it) { - const LoopbackServerEntity& entity = *it->second; + for (const auto& kv : entities_) { + const LoopbackServerEntity& entity = *kv.second; if (!(entity.IsDeleted() || entity.IsPermanent()) && entity.GetModelType() == model_type) { sync_pb::SyncEntity sync_entity; @@ -500,9 +503,8 @@ std::make_unique<base::ListValue>()); } - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); - ++it) { - const LoopbackServerEntity& entity = *it->second; + for (const auto& kv : entities_) { + const LoopbackServerEntity& entity = *kv.second; if (entity.IsDeleted() || entity.IsPermanent()) { // Tombstones are ignored as they don't represent current data. Folders // are also ignored as current verification infrastructure does not @@ -586,10 +588,14 @@ for (int i = 0; i < proto.keystore_keys_size(); ++i) keystore_keys_.push_back(proto.keystore_keys(i)); for (int i = 0; i < proto.entities_size(); ++i) { - entities_[proto.entities(i).entity().id_string()] = + std::unique_ptr<LoopbackServerEntity> entity = LoopbackServerEntity::CreateEntityFromProto(proto.entities(i)); + // Silently drop entities that cannot be successfully deserialized. + if (entity) + entities_[proto.entities(i).entity().id_string()] = std::move(entity); } + // Report success regardless of if some entities were dropped. return true; } @@ -615,8 +621,7 @@ if (base::ReadFileToString(filename, &serialized)) { sync_pb::LoopbackServerProto proto; if (serialized.length() > 0 && proto.ParseFromString(serialized)) { - DeSerializeState(proto); - return true; + return DeSerializeState(proto); } else { LOG(ERROR) << "Loopback sync can not parse the persistent state file."; return false;
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.h b/components/sync/engine_impl/loopback_server/loopback_server.h index 0f5d5d06..cecc8f2 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.h +++ b/components/sync/engine_impl/loopback_server/loopback_server.h
@@ -113,8 +113,8 @@ bool IsChild(const std::string& id, const std::string& potential_parent_id); // Creates and saves tombstones for all children of the entity with the given - // |id|. A tombstone is not created for the entity itself. - void DeleteChildren(const std::string& id); + // |parent_id|. A tombstone is not created for the entity itself. + void DeleteChildren(const std::string& parent_id); // Updates the |entity| to a new version and increments the version counter // that the server uses to assign versions.
diff --git a/components/sync/engine_impl/loopback_server/loopback_server_entity.cc b/components/sync/engine_impl/loopback_server/loopback_server_entity.cc index 340b7f4..428ec8b 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server_entity.cc +++ b/components/sync/engine_impl/loopback_server/loopback_server_entity.cc
@@ -60,7 +60,7 @@ case sync_pb::LoopbackServerEntity_Type_UNKNOWN: NOTREACHED() << "Unknown type encountered"; } - return std::unique_ptr<LoopbackServerEntity>(); + return nullptr; } const std::string& LoopbackServerEntity::GetId() const {
diff --git a/components/sync/engine_impl/loopback_server/loopback_server_entity.h b/components/sync/engine_impl/loopback_server/loopback_server_entity.h index 2ad2547..c60bc71 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server_entity.h +++ b/components/sync/engine_impl/loopback_server/loopback_server_entity.h
@@ -61,11 +61,11 @@ virtual void SerializeAsLoopbackServerEntity( sync_pb::LoopbackServerEntity* entity) const; - protected: // Extracts the ModelType from |id|. If |id| is malformed or does not contain // a valid ModelType, UNSPECIFIED is returned. static syncer::ModelType GetModelTypeFromId(const std::string& id); + protected: LoopbackServerEntity(const std::string& id, const syncer::ModelType& model_type, int64_t version,
diff --git a/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc b/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc index 99b4ba5d..298e7da 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc +++ b/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc
@@ -13,9 +13,61 @@ #include "testing/gtest/include/gtest/gtest.h" using sync_pb::ClientToServerMessage; +using sync_pb::ClientToServerResponse; +using sync_pb::EntitySpecifics; +using sync_pb::SyncEnums; +using sync_pb::SyncEntity; namespace syncer { +namespace { + +const char kUrl1[] = "http://www.one.com"; +const char kUrl2[] = "http://www.two.com"; +const char kUrl3[] = "http://www.three.com"; +const char kBookmarkBar[] = "bookmark_bar"; + +SyncEntity NewBookmarkEntity(const std::string& url, + const std::string& parent_id) { + SyncEntity entity; + entity.mutable_specifics()->mutable_bookmark()->set_url(url); + entity.set_parent_id_string(parent_id); + return entity; +} + +SyncEntity UpdatedBookmarkEntity(const std::string& url, + const std::string& id, + const std::string& parent_id, + int version) { + SyncEntity entity; + entity.mutable_specifics()->mutable_bookmark()->set_url(url); + entity.set_id_string(id); + entity.set_parent_id_string(parent_id); + entity.set_version(version); + return entity; +} + +SyncEntity DeletedBookmarkEntity(const std::string& id, int version) { + SyncEntity entity; + entity.mutable_specifics()->mutable_bookmark(); + entity.set_id_string(id); + entity.set_deleted(true); + entity.set_version(version); + return entity; +} + +std::map<std::string, SyncEntity> ResponseToMap( + const ClientToServerResponse& response) { + EXPECT_TRUE(response.has_get_updates()); + std::map<std::string, SyncEntity> results; + for (const SyncEntity& entity : response.get_updates().entries()) { + results[entity.id_string()] = entity; + } + return results; +} + +} // namespace + class LoopbackServerTest : public testing::Test { public: void SetUp() override { @@ -24,31 +76,61 @@ std::make_unique<LoopbackConnectionManager>(&signal_, persistent_file_); } - static bool CallPostAndProcessHeaders( - ServerConnectionManager* scm, - SyncCycle* cycle, - const sync_pb::ClientToServerMessage& msg, - sync_pb::ClientToServerResponse* response) { + static bool CallPostAndProcessHeaders(ServerConnectionManager* scm, + SyncCycle* cycle, + const ClientToServerMessage& msg, + ClientToServerResponse* response) { return SyncerProtoUtil::PostAndProcessHeaders(scm, cycle, msg, response); } protected: - ClientToServerMessage CreateCommitMessage() { - ClientToServerMessage msg; - SyncerProtoUtil::SetProtocolVersion(&msg); - msg.set_share("required"); - msg.set_message_contents(ClientToServerMessage::COMMIT); - msg.set_invalidator_client_id("client_id"); - auto* commit = msg.mutable_commit(); + ClientToServerResponse GetUpdatesForType(int field_number) { + ClientToServerMessage request; + SyncerProtoUtil::SetProtocolVersion(&request); + request.set_share("required"); + request.set_message_contents(ClientToServerMessage::GET_UPDATES); + request.mutable_get_updates()->add_from_progress_marker()->set_data_type_id( + field_number); + + ClientToServerResponse response; + EXPECT_TRUE( + CallPostAndProcessHeaders(lcm_.get(), nullptr, request, &response)); + EXPECT_EQ(SyncEnums::SUCCESS, response.error_code()); + return response; + } + + ClientToServerMessage SingleEntryCommit( + const std::vector<SyncEntity>& entity_vector) { + ClientToServerMessage request; + SyncerProtoUtil::SetProtocolVersion(&request); + request.set_share("required"); + request.set_message_contents(ClientToServerMessage::COMMIT); + request.set_invalidator_client_id("client_id"); + auto* commit = request.mutable_commit(); commit->set_cache_guid("cache_guid"); - auto* entry = commit->add_entries(); - // Not quite well formed but enough to fool the server. - entry->set_parent_id_string("bookmark_bar"); - entry->set_id_string("id_string"); - entry->set_version(0); - entry->set_name("google"); - entry->mutable_specifics()->mutable_bookmark()->set_url("http://google.de"); - return msg; + for (const SyncEntity& entity : entity_vector) { + *commit->add_entries() = entity; + } + return request; + } + + std::string CommitVerifySuccess(const SyncEntity& entity) { + ClientToServerMessage request = SingleEntryCommit({entity}); + ClientToServerResponse response; + EXPECT_TRUE( + CallPostAndProcessHeaders(lcm_.get(), nullptr, request, &response)); + EXPECT_EQ(SyncEnums::SUCCESS, response.error_code()); + EXPECT_TRUE(response.has_commit()); + return response.commit().entryresponse(0).id_string(); + } + + void CommitVerifyFailure(const SyncEntity& entity) { + ClientToServerMessage request = SingleEntryCommit({entity}); + ClientToServerResponse response; + EXPECT_FALSE( + CallPostAndProcessHeaders(lcm_.get(), nullptr, request, &response)); + EXPECT_NE(SyncEnums::SUCCESS, response.error_code()); + EXPECT_FALSE(response.has_commit()); } CancelationSignal signal_; @@ -63,25 +145,16 @@ msg.set_store_birthday("not_your_birthday"); msg.set_message_contents(ClientToServerMessage::GET_UPDATES); msg.mutable_get_updates()->add_from_progress_marker()->set_data_type_id( - sync_pb::EntitySpecifics::kBookmarkFieldNumber); - sync_pb::ClientToServerResponse response; + EntitySpecifics::kBookmarkFieldNumber); + ClientToServerResponse response; - EXPECT_TRUE(CallPostAndProcessHeaders(lcm_.get(), NULL, msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::NOT_MY_BIRTHDAY, response.error_code()); + EXPECT_TRUE(CallPostAndProcessHeaders(lcm_.get(), nullptr, msg, &response)); + EXPECT_EQ(SyncEnums::NOT_MY_BIRTHDAY, response.error_code()); } TEST_F(LoopbackServerTest, GetUpdateCommand) { - ClientToServerMessage msg; - SyncerProtoUtil::SetProtocolVersion(&msg); - msg.set_share("required"); - msg.set_message_contents(ClientToServerMessage::GET_UPDATES); - msg.mutable_get_updates()->add_from_progress_marker()->set_data_type_id( - sync_pb::EntitySpecifics::kBookmarkFieldNumber); - sync_pb::ClientToServerResponse response; - - EXPECT_TRUE(CallPostAndProcessHeaders(lcm_.get(), NULL, msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); - ASSERT_TRUE(response.has_get_updates()); + ClientToServerResponse response = + GetUpdatesForType(EntitySpecifics::kBookmarkFieldNumber); // Expect to see the three top-level folders in this update already. EXPECT_EQ(3, response.get_updates().entries_size()); } @@ -91,31 +164,58 @@ SyncerProtoUtil::SetProtocolVersion(&msg); msg.set_share("required"); msg.set_message_contents(ClientToServerMessage::CLEAR_SERVER_DATA); - sync_pb::ClientToServerResponse response; + ClientToServerResponse response; - EXPECT_TRUE(CallPostAndProcessHeaders(lcm_.get(), NULL, msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); + EXPECT_TRUE(CallPostAndProcessHeaders(lcm_.get(), nullptr, msg, &response)); + EXPECT_EQ(SyncEnums::SUCCESS, response.error_code()); EXPECT_TRUE(response.has_clear_server_data()); } TEST_F(LoopbackServerTest, CommitCommand) { - ClientToServerMessage msg = CreateCommitMessage(); - sync_pb::ClientToServerResponse response; + CommitVerifySuccess(NewBookmarkEntity(kUrl1, kBookmarkBar)); +} - EXPECT_TRUE(CallPostAndProcessHeaders(lcm_.get(), NULL, msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); - EXPECT_TRUE(response.has_commit()); +TEST_F(LoopbackServerTest, CommitFailureNoTag) { + // Non-bookmarks and non-commit only types must have a + // client_defined_unique_tag, which we don't set. + SyncEntity entity; + entity.mutable_specifics()->mutable_preference(); + CommitVerifyFailure(entity); +} + +TEST_F(LoopbackServerTest, CommitBookmarkTombstoneSuccess) { + std::string id1 = CommitVerifySuccess(NewBookmarkEntity(kUrl1, kBookmarkBar)); + std::string id2 = CommitVerifySuccess(NewBookmarkEntity(kUrl2, id1)); + std::string id3 = CommitVerifySuccess(NewBookmarkEntity(kUrl3, kBookmarkBar)); + + // Because 2 is a child of 1, deleting 1 will also delete 2. + CommitVerifySuccess(DeletedBookmarkEntity(id1, 10)); + + std::map<std::string, SyncEntity> bookmarks = + ResponseToMap(GetUpdatesForType(EntitySpecifics::kBookmarkFieldNumber)); + EXPECT_TRUE(bookmarks[id1].deleted()); + EXPECT_TRUE(bookmarks[id2].deleted()); + EXPECT_FALSE(bookmarks[id3].deleted()); +} + +TEST_F(LoopbackServerTest, CommitBookmarkTombstoneFailure) { + std::string id1 = CommitVerifySuccess(NewBookmarkEntity(kUrl1, kBookmarkBar)); + std::string id2 = CommitVerifySuccess(NewBookmarkEntity(kUrl2, "9" + id1)); + + // This write is going to fail, the id is supposed to encode the model type as + // as prefix, by adding 9 we're creating a fake model type. + SyncEntity entity = DeletedBookmarkEntity("9" + id1, 1); + CommitVerifyFailure(entity); + + std::map<std::string, SyncEntity> bookmarks = + ResponseToMap(GetUpdatesForType(EntitySpecifics::kBookmarkFieldNumber)); + EXPECT_FALSE(bookmarks[id1].deleted()); + // This is the point of this test, making sure the child doesn't get deleted. + EXPECT_FALSE(bookmarks[id2].deleted()); } TEST_F(LoopbackServerTest, LoadSavedState) { - ClientToServerMessage commit_msg = CreateCommitMessage(); - - sync_pb::ClientToServerResponse response; - - EXPECT_TRUE( - CallPostAndProcessHeaders(lcm_.get(), NULL, commit_msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); - EXPECT_TRUE(response.has_commit()); + std::string id = CommitVerifySuccess(NewBookmarkEntity(kUrl1, kBookmarkBar)); CancelationSignal signal; LoopbackConnectionManager second_user(&signal, persistent_file_); @@ -126,59 +226,31 @@ get_updates_msg.set_message_contents(ClientToServerMessage::GET_UPDATES); get_updates_msg.mutable_get_updates() ->add_from_progress_marker() - ->set_data_type_id(sync_pb::EntitySpecifics::kBookmarkFieldNumber); + ->set_data_type_id(EntitySpecifics::kBookmarkFieldNumber); - EXPECT_TRUE(CallPostAndProcessHeaders(&second_user, NULL, get_updates_msg, + ClientToServerResponse response; + EXPECT_TRUE(CallPostAndProcessHeaders(&second_user, nullptr, get_updates_msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); + EXPECT_EQ(SyncEnums::SUCCESS, response.error_code()); ASSERT_TRUE(response.has_get_updates()); // Expect to see the three top-level folders and the newly added bookmark! EXPECT_EQ(4, response.get_updates().entries_size()); + EXPECT_EQ(1U, ResponseToMap(response).count(id)); } TEST_F(LoopbackServerTest, CommitCommandUpdate) { - ClientToServerMessage commit_msg_1 = CreateCommitMessage(); - sync_pb::ClientToServerResponse response; + std::string id = CommitVerifySuccess(NewBookmarkEntity(kUrl1, kBookmarkBar)); + EXPECT_EQ(1U, ResponseToMap( + GetUpdatesForType(EntitySpecifics::kBookmarkFieldNumber)) + .count(id)); + CommitVerifySuccess(UpdatedBookmarkEntity(kUrl2, id, "other_bookmarks", 1)); - EXPECT_TRUE( - CallPostAndProcessHeaders(lcm_.get(), NULL, commit_msg_1, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); - EXPECT_TRUE(response.has_commit()); - const std::string server_id = response.commit().entryresponse(0).id_string(); - - ClientToServerMessage get_updates_msg; - SyncerProtoUtil::SetProtocolVersion(&get_updates_msg); - get_updates_msg.set_share("required"); - get_updates_msg.set_message_contents(ClientToServerMessage::GET_UPDATES); - get_updates_msg.mutable_get_updates() - ->add_from_progress_marker() - ->set_data_type_id(sync_pb::EntitySpecifics::kBookmarkFieldNumber); - - EXPECT_TRUE( - CallPostAndProcessHeaders(lcm_.get(), NULL, get_updates_msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); - ASSERT_TRUE(response.has_get_updates()); - // Expect to see the three top-level folders and the newly added bookmark! - EXPECT_EQ(4, response.get_updates().entries_size()); - - ClientToServerMessage commit_msg_2 = CreateCommitMessage(); - auto* entry = commit_msg_2.mutable_commit()->mutable_entries()->Mutable(0); - entry->set_id_string(server_id); - entry->set_version(1); - entry->set_parent_id_string("other_bookmarks"); - entry->mutable_specifics()->mutable_bookmark()->set_url("http://google.bg"); - - EXPECT_TRUE( - CallPostAndProcessHeaders(lcm_.get(), NULL, commit_msg_2, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); - EXPECT_TRUE(response.has_commit()); - - EXPECT_TRUE( - CallPostAndProcessHeaders(lcm_.get(), NULL, get_updates_msg, &response)); - EXPECT_EQ(sync_pb::SyncEnums::SUCCESS, response.error_code()); + ClientToServerResponse response = + GetUpdatesForType(EntitySpecifics::kBookmarkFieldNumber); ASSERT_TRUE(response.has_get_updates()); // Expect to see no fifth bookmark! EXPECT_EQ(4, response.get_updates().entries_size()); + EXPECT_EQ(kUrl2, ResponseToMap(response)[id].specifics().bookmark().url()); } } // namespace syncer
diff --git a/components/sync/engine_impl/loopback_server/persistent_bookmark_entity.cc b/components/sync/engine_impl/loopback_server/persistent_bookmark_entity.cc index b20ea8d..7d156bab 100644 --- a/components/sync/engine_impl/loopback_server/persistent_bookmark_entity.cc +++ b/components/sync/engine_impl/loopback_server/persistent_bookmark_entity.cc
@@ -5,6 +5,7 @@ #include "components/sync/engine_impl/loopback_server/persistent_bookmark_entity.h" #include "base/guid.h" +#include "base/memory/ptr_util.h" using std::string; @@ -26,16 +27,17 @@ const sync_pb::SyncEntity& client_entity, const string& parent_id, const string& client_guid) { - DLOG_IF(WARNING, client_entity.version() == 0) - << "Possible roaming store corruption. Should self heal."; - DCHECK(IsBookmark(client_entity)) << "The given entity must be a bookmark."; + if (!IsBookmark(client_entity)) { + DLOG(WARNING) << "The given entity must be a bookmark."; + return nullptr; + } const string id = LoopbackServerEntity::CreateId(syncer::BOOKMARKS, base::GenerateGUID()); const string originator_cache_guid = client_guid; const string originator_client_item_id = client_entity.id_string(); - return std::unique_ptr<LoopbackServerEntity>(new PersistentBookmarkEntity( + return base::WrapUnique(new PersistentBookmarkEntity( id, 0, client_entity.name(), originator_cache_guid, originator_client_item_id, client_entity.unique_position(), client_entity.specifics(), client_entity.folder(), parent_id, @@ -48,9 +50,14 @@ const sync_pb::SyncEntity& client_entity, const LoopbackServerEntity& current_server_entity, const string& parent_id) { - DCHECK(client_entity.version() != 0) << "Existing entities must not have a " - << "version = 0."; - DCHECK(IsBookmark(client_entity)) << "The given entity must be a bookmark."; + if (client_entity.version() == 0) { + DLOG(WARNING) << "Existing entities must not have a version = 0."; + return nullptr; + } + if (!IsBookmark(client_entity)) { + DLOG(WARNING) << "The given entity must be a bookmark."; + return nullptr; + } const PersistentBookmarkEntity& current_bookmark_entity = static_cast<const PersistentBookmarkEntity&>(current_server_entity); @@ -59,7 +66,9 @@ const string originator_client_item_id = current_bookmark_entity.originator_client_item_id_; - return std::unique_ptr<LoopbackServerEntity>(new PersistentBookmarkEntity( + // Using a version of 0 is okay here as it'll be updated before this entity is + // actually saved. + return base::WrapUnique(new PersistentBookmarkEntity( client_entity.id_string(), 0, client_entity.name(), originator_cache_guid, originator_client_item_id, client_entity.unique_position(), client_entity.specifics(), client_entity.folder(), parent_id, @@ -70,9 +79,12 @@ std::unique_ptr<LoopbackServerEntity> PersistentBookmarkEntity::CreateFromEntity( const sync_pb::SyncEntity& client_entity) { - DCHECK(IsBookmark(client_entity)) << "The given entity must be a bookmark."; + if (!IsBookmark(client_entity)) { + DLOG(WARNING) << "The given entity must be a bookmark."; + return nullptr; + } - return std::unique_ptr<LoopbackServerEntity>(new PersistentBookmarkEntity( + return base::WrapUnique(new PersistentBookmarkEntity( client_entity.id_string(), client_entity.version(), client_entity.name(), client_entity.originator_cache_guid(), client_entity.originator_client_item_id(),
diff --git a/components/sync/engine_impl/loopback_server/persistent_bookmark_entity_unittest.cc b/components/sync/engine_impl/loopback_server/persistent_bookmark_entity_unittest.cc new file mode 100644 index 0000000..e2a9e23 --- /dev/null +++ b/components/sync/engine_impl/loopback_server/persistent_bookmark_entity_unittest.cc
@@ -0,0 +1,61 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync/engine_impl/loopback_server/persistent_bookmark_entity.h" + +#include "components/sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +TEST(PersistentBookmarkEntityTest, CreateNew) { + sync_pb::SyncEntity entity; + entity.mutable_specifics()->mutable_preference(); + EXPECT_FALSE( + PersistentBookmarkEntity::CreateNew(entity, "parent_id", "client_guid")); + + entity.clear_specifics(); + entity.mutable_specifics()->mutable_bookmark(); + EXPECT_TRUE( + PersistentBookmarkEntity::CreateNew(entity, "parent_id", "client_guid")); +} + +TEST(PersistentBookmarkEntityTest, CreateUpdatedVersion) { + sync_pb::SyncEntity client_entity; + client_entity.mutable_specifics()->mutable_bookmark(); + auto server_entity = + PersistentBookmarkEntity::CreateFromEntity(client_entity); + ASSERT_TRUE(server_entity); + + // Fails with since there's no version + ASSERT_FALSE(PersistentBookmarkEntity::CreateUpdatedVersion( + client_entity, *server_entity, "parent_id")); + + // And now succeeds that we have a version. + client_entity.set_version(1); + ASSERT_TRUE(PersistentBookmarkEntity::CreateUpdatedVersion( + client_entity, *server_entity, "parent_id")); + + // But fails when not actually a bookmark. + client_entity.clear_specifics(); + client_entity.mutable_specifics()->mutable_preference(); + ASSERT_FALSE(PersistentBookmarkEntity::CreateUpdatedVersion( + client_entity, *server_entity, "parent_id")); +} + +TEST(PersistentBookmarkEntityTest, CreateFromEntity) { + sync_pb::SyncEntity entity; + entity.mutable_specifics()->mutable_preference(); + EXPECT_FALSE(PersistentBookmarkEntity::CreateFromEntity(entity)); + + entity.clear_specifics(); + entity.mutable_specifics()->mutable_bookmark(); + EXPECT_TRUE(PersistentBookmarkEntity::CreateFromEntity(entity)); +} + +} // namespace + +} // namespace syncer
diff --git a/components/sync/engine_impl/loopback_server/persistent_permanent_entity.cc b/components/sync/engine_impl/loopback_server/persistent_permanent_entity.cc index a0203868..54716b2 100644 --- a/components/sync/engine_impl/loopback_server/persistent_permanent_entity.cc +++ b/components/sync/engine_impl/loopback_server/persistent_permanent_entity.cc
@@ -12,9 +12,11 @@ using syncer::ModelType; namespace { + // The parent tag for children of the root entity. Entities with this parent are // referred to as top level enities. static const char kRootParentTag[] = "0"; + } // namespace namespace syncer { @@ -27,38 +29,52 @@ const string& server_tag, const string& name, const string& parent_server_tag) { - DCHECK(model_type != syncer::UNSPECIFIED) << "The entity's ModelType is " - << "invalid."; - DCHECK(!server_tag.empty()) - << "A PersistentPermanentEntity must have a server tag."; - DCHECK(!name.empty()) << "The entity must have a non-empty name."; - DCHECK(!parent_server_tag.empty()) - << "A PersistentPermanentEntity must have a parent " - << "server tag."; - DCHECK(parent_server_tag != kRootParentTag) - << "Top-level entities should not " - << "be created with this factory."; + if (model_type == syncer::UNSPECIFIED) { + DLOG(WARNING) << "The entity's ModelType is invalid."; + return nullptr; + } + if (server_tag.empty()) { + DLOG(WARNING) << "A PersistentPermanentEntity must have a server tag."; + return nullptr; + } + if (name.empty()) { + DLOG(WARNING) << "The entity must have a non-empty name."; + return nullptr; + } + if (parent_server_tag.empty()) { + DLOG(WARNING) + << "A PersistentPermanentEntity must have a parent server tag."; + return nullptr; + } + if (parent_server_tag == kRootParentTag) { + DLOG(WARNING) + << "Top-level entities should not be created with this factory."; + return nullptr; + } string id = LoopbackServerEntity::CreateId(model_type, server_tag); string parent_id = LoopbackServerEntity::CreateId(model_type, parent_server_tag); sync_pb::EntitySpecifics entity_specifics; AddDefaultFieldValue(model_type, &entity_specifics); - return std::unique_ptr<LoopbackServerEntity>(new PersistentPermanentEntity( + return base::WrapUnique(new PersistentPermanentEntity( id, 0, model_type, name, parent_id, server_tag, entity_specifics)); } // static std::unique_ptr<LoopbackServerEntity> PersistentPermanentEntity::CreateTopLevel( const ModelType& model_type) { - DCHECK(model_type != syncer::UNSPECIFIED) << "The entity's ModelType is " - << "invalid."; + if (model_type == syncer::UNSPECIFIED) { + DLOG(WARNING) << "The entity's ModelType is invalid."; + return nullptr; + } + string server_tag = syncer::ModelTypeToRootTag(model_type); string name = syncer::ModelTypeToString(model_type); string id = LoopbackServerEntity::GetTopLevelId(model_type); sync_pb::EntitySpecifics entity_specifics; AddDefaultFieldValue(model_type, &entity_specifics); - return std::unique_ptr<LoopbackServerEntity>(new PersistentPermanentEntity( + return base::WrapUnique(new PersistentPermanentEntity( id, 0, model_type, name, kRootParentTag, server_tag, entity_specifics)); } @@ -68,10 +84,12 @@ const sync_pb::SyncEntity& client_entity, const LoopbackServerEntity& current_server_entity) { ModelType model_type = current_server_entity.GetModelType(); - DCHECK(model_type == syncer::NIGORI) << "This factory only supports NIGORI " - << "entities."; + if (model_type != syncer::NIGORI) { + DLOG(WARNING) << "This factory only supports NIGORI entities."; + return nullptr; + } - return base::WrapUnique<LoopbackServerEntity>(new PersistentPermanentEntity( + return base::WrapUnique(new PersistentPermanentEntity( current_server_entity.GetId(), current_server_entity.GetVersion(), model_type, current_server_entity.GetName(), current_server_entity.GetParentId(),
diff --git a/components/sync/engine_impl/loopback_server/persistent_permanent_entity_unittest.cc b/components/sync/engine_impl/loopback_server/persistent_permanent_entity_unittest.cc new file mode 100644 index 0000000..24f0329 --- /dev/null +++ b/components/sync/engine_impl/loopback_server/persistent_permanent_entity_unittest.cc
@@ -0,0 +1,53 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync/engine_impl/loopback_server/persistent_permanent_entity.h" + +#include "components/sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +TEST(PersistentPermanentEntityTest, CreateNew) { + ASSERT_FALSE(PersistentPermanentEntity::CreateNew( + UNSPECIFIED, "server_tag", "name", "parent_server_tag")); + ASSERT_FALSE(PersistentPermanentEntity::CreateNew(PREFERENCES, "", "name", + "parent_server_tag")); + ASSERT_FALSE(PersistentPermanentEntity::CreateNew(PREFERENCES, "server_tag", + "", "parent_server_tag")); + ASSERT_FALSE(PersistentPermanentEntity::CreateNew(PREFERENCES, "server_tag", + "name", "")); + ASSERT_FALSE(PersistentPermanentEntity::CreateNew(PREFERENCES, "server_tag", + "name", "0")); + ASSERT_TRUE(PersistentPermanentEntity::CreateNew( + PREFERENCES, "server_tag", "name", "parent_server_tag")); +} + +TEST(PersistentPermanentEntityTest, CreateTopLevel) { + ASSERT_FALSE(PersistentPermanentEntity::CreateTopLevel(UNSPECIFIED)); + ASSERT_TRUE(PersistentPermanentEntity::CreateTopLevel(PREFERENCES)); +} + +TEST(PersistentPermanentEntityTest, CreateUpdatedNigoriEntity) { + sync_pb::SyncEntity client_entity; + client_entity.mutable_specifics()->mutable_nigori(); + + auto preferences_server_entity = PersistentPermanentEntity::CreateNew( + PREFERENCES, "server_tag", "name", "parent_server_tag"); + ASSERT_TRUE(preferences_server_entity); + ASSERT_FALSE(PersistentPermanentEntity::CreateUpdatedNigoriEntity( + client_entity, *preferences_server_entity)); + + auto nigori_server_entity = PersistentPermanentEntity::CreateNew( + NIGORI, "server_tag", "name", "parent_server_tag"); + ASSERT_TRUE(nigori_server_entity); + ASSERT_TRUE(PersistentPermanentEntity::CreateUpdatedNigoriEntity( + client_entity, *nigori_server_entity)); +} + +} // namespace + +} // namespace syncer
diff --git a/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.cc b/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.cc index 1571e81a..931983e 100644 --- a/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.cc +++ b/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.cc
@@ -4,6 +4,8 @@ #include "components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h" +#include "base/memory/ptr_util.h" + using std::string; using syncer::ModelType; @@ -15,22 +17,31 @@ // static std::unique_ptr<LoopbackServerEntity> PersistentTombstoneEntity::CreateFromEntity(const sync_pb::SyncEntity& entity) { - const ModelType model_type = GetModelTypeFromId(entity.id_string()); - DCHECK_NE(model_type, syncer::UNSPECIFIED) - << "Invalid ID was given: " << entity.id_string(); - return std::unique_ptr<LoopbackServerEntity>(new PersistentTombstoneEntity( - entity.id_string(), entity.version(), model_type, - entity.client_defined_unique_tag())); + return CreateNewInternal(entity.id_string(), entity.version(), + entity.client_defined_unique_tag()); } // static std::unique_ptr<LoopbackServerEntity> PersistentTombstoneEntity::CreateNew( const std::string& id, const std::string& client_defined_unique_tag) { - const ModelType model_type = GetModelTypeFromId(id); - DCHECK_NE(model_type, syncer::UNSPECIFIED) << "Invalid ID was given: " << id; - return std::unique_ptr<LoopbackServerEntity>(new PersistentTombstoneEntity( - id, 0, model_type, client_defined_unique_tag)); + return CreateNewInternal(id, 0, client_defined_unique_tag); +} + +// static +std::unique_ptr<LoopbackServerEntity> +PersistentTombstoneEntity::CreateNewInternal( + const std::string& id, + int64_t version, + const std::string& client_defined_unique_tag) { + const ModelType model_type = LoopbackServerEntity::GetModelTypeFromId(id); + if (model_type == syncer::UNSPECIFIED) { + DLOG(WARNING) << "Invalid ID was given: " << id; + return nullptr; + } + + return base::WrapUnique(new PersistentTombstoneEntity( + id, version, model_type, client_defined_unique_tag)); } PersistentTombstoneEntity::PersistentTombstoneEntity(
diff --git a/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h b/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h index 0531666..985fc69 100644 --- a/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h +++ b/components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h
@@ -36,6 +36,11 @@ const override; private: + static std::unique_ptr<LoopbackServerEntity> CreateNewInternal( + const std::string& id, + int64_t version, + const std::string& client_defined_unique_tag); + PersistentTombstoneEntity(const std::string& id, int64_t version, const syncer::ModelType& model_type,
diff --git a/components/sync/engine_impl/loopback_server/persistent_tombstone_entity_unittest.cc b/components/sync/engine_impl/loopback_server/persistent_tombstone_entity_unittest.cc new file mode 100644 index 0000000..3617ac3 --- /dev/null +++ b/components/sync/engine_impl/loopback_server/persistent_tombstone_entity_unittest.cc
@@ -0,0 +1,31 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync/engine_impl/loopback_server/persistent_tombstone_entity.h" + +#include "components/sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +TEST(PersistentTombstoneEntityTest, CreateFromEntity) { + sync_pb::SyncEntity entity; + *entity.mutable_id_string() = "invalid_id"; + ASSERT_FALSE(PersistentTombstoneEntity::CreateFromEntity(entity)); + *entity.mutable_id_string() = "37702_id"; + ASSERT_TRUE(PersistentTombstoneEntity::CreateFromEntity(entity)); +} + +TEST(PersistentTombstoneEntityTest, CreateNew) { + ASSERT_FALSE(PersistentTombstoneEntity::CreateNew( + "invalid_id", "client_defined_unique_tag")); + ASSERT_TRUE(PersistentTombstoneEntity::CreateNew( + "37702_id", "client_defined_unique_tag")); +} + +} // namespace + +} // namespace syncer
diff --git a/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.cc b/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.cc index 445f288b..eaca76a 100644 --- a/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.cc +++ b/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.cc
@@ -5,6 +5,7 @@ #include "components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h" #include "base/guid.h" +#include "base/memory/ptr_util.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "components/sync/base/hash_util.h" @@ -38,10 +39,13 @@ PersistentUniqueClientEntity::CreateFromEntity( const sync_pb::SyncEntity& client_entity) { ModelType model_type = GetModelTypeFromSpecifics(client_entity.specifics()); - DCHECK_NE(client_entity.has_client_defined_unique_tag(), - syncer::CommitOnlyTypes().Has(model_type)) - << "A UniqueClientEntity should have a client-defined unique tag iff it " - "is not a CommitOnly type."; + if (client_entity.has_client_defined_unique_tag() == + syncer::CommitOnlyTypes().Has(model_type)) { + DLOG(WARNING) << "A UniqueClientEntity should have a client-defined unique " + "tag iff it is not a CommitOnly type."; + return nullptr; + } + // Without model type specific logic for each CommitOnly type, we cannot infer // a reasonable tag from the specifics. We need uniqueness for how the server // holds onto all objects, so simply make a new tag from a random number. @@ -49,7 +53,7 @@ ? client_entity.client_defined_unique_tag() : base::Uint64ToString(base::RandUint64()); string id = LoopbackServerEntity::CreateId(model_type, effective_tag); - return std::unique_ptr<LoopbackServerEntity>(new PersistentUniqueClientEntity( + return base::WrapUnique(new PersistentUniqueClientEntity( id, model_type, client_entity.version(), client_entity.name(), client_entity.client_defined_unique_tag(), client_entity.specifics(), client_entity.ctime(), client_entity.mtime())); @@ -59,14 +63,16 @@ std::unique_ptr<LoopbackServerEntity> PersistentUniqueClientEntity::CreateFromEntitySpecifics( const string& name, - const sync_pb::EntitySpecifics& entity_specifics) { + const sync_pb::EntitySpecifics& entity_specifics, + int64_t creation_time, + int64_t last_modified_time) { ModelType model_type = GetModelTypeFromSpecifics(entity_specifics); string client_defined_unique_tag = GenerateSyncableHash(model_type, name); string id = LoopbackServerEntity::CreateId(model_type, client_defined_unique_tag); - return std::unique_ptr<LoopbackServerEntity>(new PersistentUniqueClientEntity( + return base::WrapUnique(new PersistentUniqueClientEntity( id, model_type, 0, name, client_defined_unique_tag, entity_specifics, - 1337, 1337)); + creation_time, last_modified_time)); } bool PersistentUniqueClientEntity::RequiresParentId() const {
diff --git a/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h b/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h index 746f0bd..7909356 100644 --- a/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h +++ b/components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h
@@ -46,7 +46,9 @@ // FakeServer injection API. static std::unique_ptr<LoopbackServerEntity> CreateFromEntitySpecifics( const std::string& name, - const sync_pb::EntitySpecifics& entity_specifics); + const sync_pb::EntitySpecifics& entity_specifics, + int64_t creation_time, + int64_t last_modified_time); // LoopbackServerEntity implementation. bool RequiresParentId() const override;
diff --git a/components/sync/engine_impl/loopback_server/persistent_unique_client_entity_unittest.cc b/components/sync/engine_impl/loopback_server/persistent_unique_client_entity_unittest.cc new file mode 100644 index 0000000..6bedb58 --- /dev/null +++ b/components/sync/engine_impl/loopback_server/persistent_unique_client_entity_unittest.cc
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync/engine_impl/loopback_server/persistent_unique_client_entity.h" + +#include "components/sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +TEST(PersistentUniqueClientEntityTest, CreateFromEntity) { + sync_pb::SyncEntity entity; + entity.mutable_specifics()->mutable_preference(); + // Normal types need a client_defined_unique_tag. + ASSERT_FALSE(PersistentUniqueClientEntity::CreateFromEntity(entity)); + + *entity.mutable_client_defined_unique_tag() = "tag"; + ASSERT_TRUE(PersistentUniqueClientEntity::CreateFromEntity(entity)); + + entity.clear_specifics(); + entity.mutable_specifics()->mutable_user_event(); + // CommitOnly type should never have a client_defined_unique_tag. + ASSERT_FALSE(PersistentUniqueClientEntity::CreateFromEntity(entity)); + + entity.clear_client_defined_unique_tag(); + ASSERT_TRUE(PersistentUniqueClientEntity::CreateFromEntity(entity)); +} + +TEST(PersistentUniqueClientEntityTest, CreateFromEntitySpecifics) { + sync_pb::EntitySpecifics specifics; + specifics.mutable_preference(); + ASSERT_TRUE(PersistentUniqueClientEntity::CreateFromEntitySpecifics( + "name", specifics, 0, 0)); +} + +} // namespace + +} // namespace syncer
diff --git a/components/sync/test/fake_server/android/fake_server_helper_android.cc b/components/sync/test/fake_server/android/fake_server_helper_android.cc index 140c997c..5b6af3b 100644 --- a/components/sync/test/fake_server/android/fake_server_helper_android.cc +++ b/components/sync/test/fake_server/android/fake_server_helper_android.cc
@@ -145,7 +145,8 @@ fake_server_ptr->InjectEntity( syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics( - base::android::ConvertJavaStringToUTF8(env, name), entity_specifics)); + base::android::ConvertJavaStringToUTF8(env, name), entity_specifics, + 12345, 12345)); } void FakeServerHelperAndroid::ModifyEntitySpecifics(
diff --git a/components/sync/test/fake_server/fake_server_entity.cc b/components/sync/test/fake_server/fake_server_entity.cc deleted file mode 100644 index def68fcc..0000000 --- a/components/sync/test/fake_server/fake_server_entity.cc +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/sync/test/fake_server/fake_server_entity.h" - -#include <limits> -#include <memory> -#include <vector> - -#include "base/guid.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "net/base/net_errors.h" -#include "net/http/http_status_code.h" - -using std::string; -using std::vector; -using syncer::ModelType; - -// The separator used when formatting IDs. -// -// We chose the underscore character because it doesn't conflict with the -// special characters used by base/base64.h's encoding, which is also used in -// the construction of some IDs. -const char kIdSeparator[] = "_"; - -namespace fake_server { - -FakeServerEntity::~FakeServerEntity() {} - -int64_t FakeServerEntity::GetVersion() const { - return version_; -} - -void FakeServerEntity::SetVersion(int64_t version) { - version_ = version; -} - -const std::string& FakeServerEntity::GetName() const { - return name_; -} - -void FakeServerEntity::SetName(const std::string& name) { - name_ = name; -} - -void FakeServerEntity::SetSpecifics( - const sync_pb::EntitySpecifics& updated_specifics) { - specifics_ = updated_specifics; -} - -bool FakeServerEntity::IsDeleted() const { - return false; -} - -bool FakeServerEntity::IsFolder() const { - return false; -} - -bool FakeServerEntity::IsPermanent() const { - return false; -} - -// static -string FakeServerEntity::CreateId(const ModelType& model_type, - const string& inner_id) { - int field_number = GetSpecificsFieldNumberFromModelType(model_type); - return base::StringPrintf("%d%s%s", field_number, kIdSeparator, - inner_id.c_str()); -} - -// static -std::string FakeServerEntity::GetTopLevelId(const ModelType& model_type) { - return FakeServerEntity::CreateId(model_type, - syncer::ModelTypeToRootTag(model_type)); -} - -// static -ModelType FakeServerEntity::GetModelTypeFromId(const string& id) { - vector<base::StringPiece> tokens = base::SplitStringPiece( - id, kIdSeparator, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - - int field_number; - if (tokens.size() != 2 || !base::StringToInt(tokens[0], &field_number)) { - return syncer::UNSPECIFIED; - } - - return syncer::GetModelTypeFromSpecificsFieldNumber(field_number); -} - -FakeServerEntity::FakeServerEntity(const string& id, - const string& client_defined_unique_tag, - const ModelType& model_type, - int64_t version, - const string& name) - : id_(id), - client_defined_unique_tag_(client_defined_unique_tag), - model_type_(model_type), - version_(version), - name_(name) { - // There shouldn't be a unique_tag if the type is bookmarks. - DCHECK(model_type != syncer::BOOKMARKS || client_defined_unique_tag.empty()); -} - -void FakeServerEntity::SerializeBaseProtoFields( - sync_pb::SyncEntity* sync_entity) const { - sync_pb::EntitySpecifics* specifics = sync_entity->mutable_specifics(); - specifics->CopyFrom(specifics_); - - // FakeServerEntity fields - sync_entity->set_id_string(id_); - if (!client_defined_unique_tag_.empty()) - sync_entity->set_client_defined_unique_tag(client_defined_unique_tag_); - sync_entity->set_version(version_); - sync_entity->set_name(name_); - - // Data via accessors - sync_entity->set_deleted(IsDeleted()); - sync_entity->set_folder(IsFolder()); - - if (RequiresParentId()) - sync_entity->set_parent_id_string(GetParentId()); -} - -} // namespace fake_server
diff --git a/components/viz/service/display_embedder/display_provider.h b/components/viz/service/display_embedder/display_provider.h index d490bf2..be728d87 100644 --- a/components/viz/service/display_embedder/display_provider.h +++ b/components/viz/service/display_embedder/display_provider.h
@@ -11,10 +11,10 @@ namespace viz { -class BeginFrameSource; class Display; class FrameSinkId; class RendererSettings; +class SyntheticBeginFrameSource; // Handles creating Display and related classes for FrameSinkManagerImpl. class DisplayProvider { @@ -27,7 +27,7 @@ const FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, const RendererSettings& renderer_settings, - std::unique_ptr<BeginFrameSource>* begin_frame_source) = 0; + std::unique_ptr<SyntheticBeginFrameSource>* out_begin_frame_source) = 0; }; } // namespace viz
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc index 6954d86..8fd3cfea 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.cc +++ b/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -61,7 +61,7 @@ const FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, const RendererSettings& renderer_settings, - std::unique_ptr<BeginFrameSource>* begin_frame_source) { + std::unique_ptr<SyntheticBeginFrameSource>* out_begin_frame_source) { auto synthetic_begin_frame_source = base::MakeUnique<DelayBasedBeginFrameSource>( base::MakeUnique<DelayBasedTimeSource>(task_runner_.get()), @@ -102,7 +102,7 @@ max_frames_pending); // The ownership of the BeginFrameSource is transfered to the caller. - *begin_frame_source = std::move(synthetic_begin_frame_source); + *out_begin_frame_source = std::move(synthetic_begin_frame_source); return base::MakeUnique<Display>( ServerSharedBitmapManager::current(), gpu_memory_buffer_manager_.get(),
diff --git a/components/viz/service/display_embedder/gpu_display_provider.h b/components/viz/service/display_embedder/gpu_display_provider.h index ebc0382a..54a6bafc 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.h +++ b/components/viz/service/display_embedder/gpu_display_provider.h
@@ -39,7 +39,8 @@ const FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, const RendererSettings& renderer_settings, - std::unique_ptr<BeginFrameSource>* begin_frame_source) override; + std::unique_ptr<SyntheticBeginFrameSource>* out_begin_frame_source) + override; private: const uint32_t restart_id_;
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc index aed0c069..eb7ed9c 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -112,7 +112,7 @@ DCHECK_EQ(0u, compositor_frame_sinks_.count(frame_sink_id)); DCHECK(display_provider_); - std::unique_ptr<BeginFrameSource> begin_frame_source; + std::unique_ptr<SyntheticBeginFrameSource> begin_frame_source; auto display = display_provider_->CreateDisplay( frame_sink_id, surface_handle, renderer_settings, &begin_frame_source);
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc index a8a85be..7072e33af 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -16,7 +16,7 @@ FrameSinkManagerImpl* frame_sink_manager, const FrameSinkId& frame_sink_id, std::unique_ptr<Display> display, - std::unique_ptr<BeginFrameSource> begin_frame_source, + std::unique_ptr<SyntheticBeginFrameSource> synthetic_begin_frame_source, mojom::CompositorFrameSinkAssociatedRequest request, mojom::CompositorFrameSinkClientPtr client, mojom::DisplayPrivateAssociatedRequest display_private_request) @@ -29,23 +29,23 @@ frame_sink_id, true /* is_root */, true /* needs_sync_points */)), - display_begin_frame_source_(std::move(begin_frame_source)), + synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)), display_(std::move(display)), hit_test_aggregator_(frame_sink_manager->hit_test_manager(), this) { - DCHECK(display_begin_frame_source_); + DCHECK(synthetic_begin_frame_source_); DCHECK(display_); compositor_frame_sink_binding_.set_connection_error_handler( base::Bind(&RootCompositorFrameSinkImpl::OnClientConnectionLost, base::Unretained(this))); frame_sink_manager->RegisterBeginFrameSource( - display_begin_frame_source_.get(), frame_sink_id); + synthetic_begin_frame_source_.get(), frame_sink_id); display_->Initialize(this, frame_sink_manager->surface_manager()); } RootCompositorFrameSinkImpl::~RootCompositorFrameSinkImpl() { support_->frame_sink_manager()->UnregisterBeginFrameSource( - display_begin_frame_source_.get()); + synthetic_begin_frame_source_.get()); } void RootCompositorFrameSinkImpl::SetDisplayVisible(bool visible) { @@ -62,6 +62,12 @@ display_->SetOutputIsSecure(secure); } +void RootCompositorFrameSinkImpl::SetAuthoritativeVSyncInterval( + base::TimeDelta interval) { + if (synthetic_begin_frame_source_) + synthetic_begin_frame_source_->SetAuthoritativeVSyncInterval(interval); +} + void RootCompositorFrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) { support_->SetNeedsBeginFrame(needs_begin_frame); } @@ -71,7 +77,7 @@ CompositorFrame frame, mojom::HitTestRegionListPtr hit_test_region_list, uint64_t submit_time) { - // Update |display_| when size or local surface id changes. + // Update display when size or local surface id changes. if (support_->local_surface_id() != local_surface_id) { display_->Resize(frame.size_in_pixels()); display_->SetLocalSurfaceId(local_surface_id, frame.device_scale_factor());
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h index a4c97797d..14e0bfe 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -19,9 +19,9 @@ namespace viz { -class BeginFrameSource; class Display; class FrameSinkManagerImpl; +class SyntheticBeginFrameSource; // The viz portion of a root CompositorFrameSink. Holds the Binding/InterfacePtr // for the mojom::CompositorFrameSink interface and owns the Display. @@ -34,18 +34,21 @@ FrameSinkManagerImpl* frame_sink_manager, const FrameSinkId& frame_sink_id, std::unique_ptr<Display> display, - std::unique_ptr<BeginFrameSource> begin_frame_source, + std::unique_ptr<SyntheticBeginFrameSource> begin_frame_source, mojom::CompositorFrameSinkAssociatedRequest request, mojom::CompositorFrameSinkClientPtr client, mojom::DisplayPrivateAssociatedRequest display_private_request); ~RootCompositorFrameSinkImpl() override; + CompositorFrameSinkSupport* support() const { return support_.get(); } + // mojom::DisplayPrivate: void SetDisplayVisible(bool visible) override; void SetDisplayColorSpace(const gfx::ColorSpace& blending_color_space, const gfx::ColorSpace& device_color_space) override; void SetOutputIsSecure(bool secure) override; + void SetAuthoritativeVSyncInterval(base::TimeDelta interval) override; // mojom::CompositorFrameSink: void SetNeedsBeginFrame(bool needs_begin_frame) override; @@ -55,8 +58,6 @@ uint64_t submit_time) override; void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override; - CompositorFrameSinkSupport* support() const { return support_.get(); } - // HitTestAggregatorDelegate: void OnAggregatedHitTestRegionListUpdated( mojo::ScopedSharedBufferHandle active_handle, @@ -86,7 +87,7 @@ // RootCompositorFrameSinkImpl holds a Display and its BeginFrameSource if // it was created with a non-null gpu::SurfaceHandle. - std::unique_ptr<BeginFrameSource> display_begin_frame_source_; + std::unique_ptr<SyntheticBeginFrameSource> synthetic_begin_frame_source_; std::unique_ptr<Display> display_; HitTestAggregator hit_test_aggregator_;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index b8b30ca0..245bd83 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1452,10 +1452,11 @@ // so this cannot happen any earlier than now. InitializeMojo(); -#if defined(USE_AURA) +#if BUILDFLAG(ENABLE_MUS) if (IsUsingMus()) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kIsRunningInMash); + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kMus, + IsMusHostingViz() ? switches::kMusHostVizValue : std::string()); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableSurfaceSynchronization); }
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index 6121053..0d9d89e7 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -213,8 +213,10 @@ void VizProcessTransportFactory::SetAuthoritativeVSyncInterval( ui::Compositor* compositor, base::TimeDelta interval) { - // TODO(crbug.com/772524): Deal with vsync later. - NOTIMPLEMENTED(); + auto iter = compositor_data_map_.find(compositor); + if (iter == compositor_data_map_.end() || !iter->second.display_private) + return; + iter->second.display_private->SetAuthoritativeVSyncInterval(interval); } void VizProcessTransportFactory::SetDisplayVSyncParameters(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index e6d0d5c0..97870689 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -100,6 +100,7 @@ #include "content/browser/media/midi_host.h" #include "content/browser/memory/memory_coordinator_impl.h" #include "content/browser/mime_registry_impl.h" +#include "content/browser/mus_util.h" #include "content/browser/net/reporting_service_proxy.h" #include "content/browser/notifications/notification_message_filter.h" #include "content/browser/notifications/platform_notification_context_impl.h" @@ -2609,7 +2610,6 @@ switches::kIgnoreAutoplayRestrictionsForTests, switches::kIPCConnectionTimeout, switches::kIsolateOrigins, - switches::kIsRunningInMash, switches::kJavaScriptFlags, switches::kLoggingLevel, switches::kMainFrameResizesAreOrientationChanges, @@ -2707,6 +2707,9 @@ switches::kIpcDumpDirectory, switches::kIpcFuzzerTestcase, #endif +#if BUILDFLAG(ENABLE_MUS) + switches::kMus, +#endif }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, arraysize(kSwitchNames)); @@ -2747,8 +2750,7 @@ // optimizes the common case to avoid wasted work. // Note: There is no ImageTransportFactory with Mash or Viz. // TODO(danakj): Get this info somewhere for viz mode. - if (!browser_cmd.HasSwitch(switches::kIsRunningInMash) && - !browser_cmd.HasSwitch(switches::kEnableViz) && + if (!IsUsingMus() && !browser_cmd.HasSwitch(switches::kEnableViz) && ImageTransportFactory::GetInstance()->IsGpuCompositingDisabled()) renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing); #endif
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index ef93281..e2eea32083 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -92,9 +92,13 @@ #endif -static bool IsRunningInMash() { +static bool IsRunningWithMus() { +#if BUILDFLAG(ENABLE_MUS) const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - return cmdline->HasSwitch(switches::kIsRunningInMash); + return cmdline->HasSwitch(switches::kMus); +#else + return false; +#endif } namespace content { @@ -127,7 +131,7 @@ // allocator. if (!command_line.HasSwitch(switches::kSingleProcess)) { discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (IsRunningInMash()) { + if (IsRunningWithMus()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr);
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java index 198ac82..ae671034 100644 --- a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java +++ b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
@@ -159,7 +159,7 @@ */ public SelectionPopupController( Context context, WindowAndroid window, WebContents webContents, View view) { - this(context, window, webContents, view, /* initialNative = */ true); + this(context, window, webContents, view, /* initializeNative = */ true); } /** @@ -173,7 +173,7 @@ public static SelectionPopupController createForTesting( Context context, WindowAndroid window, WebContents webContents, View view) { return new SelectionPopupController( - context, window, webContents, view, /* initialNative = */ false); + context, window, webContents, view, /* initializeNative = */ false); } private SelectionPopupController(Context context, WindowAndroid window, WebContents webContents, @@ -1265,7 +1265,7 @@ if (!(result.startAdjust == 0 && result.endAdjust == 0)) { // This call will cause showSelectionMenu again. mWebContents.adjustSelectionByCharacterOffset( - result.startAdjust, result.endAdjust, /* show_selection_menu = */ true); + result.startAdjust, result.endAdjust, /* showSelectionMenu = */ true); return; }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index 879d64e6..462f0c6 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -1744,4 +1744,27 @@ + " document.getElementById('div').firstChild, " + " 'composition', 1).endOffset")); } + + @Test + @SmallTest + @Feature({"TextInput"}) + public void testAutocorrectAttribute() throws Exception { + // Autocorrect should be on for a text field that doesn't have an autocorrect attribute. + mRule.focusElement("input_text"); + Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT, + mRule.getConnectionFactory().getOutAttrs().inputType + & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT); + + // Autocorrect should be on for a text field that has autocorrect="on" set. + mRule.focusElement("autocorrect_on"); + Assert.assertEquals(EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT, + mRule.getConnectionFactory().getOutAttrs().inputType + & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT); + + // Autocorrect should be off for a text field that has autocorrect="off" set. + mRule.focusElement("autocorrect_off"); + Assert.assertEquals(0, + mRule.getConnectionFactory().getOutAttrs().inputType + & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT); + } }
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index c3fd709f..cfa357b2 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -589,9 +589,6 @@ // --isolate-origins=https://www.foo.com,https://www.bar.com const char kIsolateOrigins[] = "isolate-origins"; -// Chrome is running in Mash. -const char kIsRunningInMash[] = "is-running-in-mash"; - // Disable latest shipping ECMAScript 6 features. const char kDisableJavaScriptHarmonyShipping[] = "disable-javascript-harmony-shipping";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 5b2199e..5f27e8c 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -171,7 +171,6 @@ CONTENT_EXPORT extern const char kInProcessGPU[]; CONTENT_EXPORT extern const char kIPCConnectionTimeout[]; CONTENT_EXPORT extern const char kIsolateOrigins[]; -CONTENT_EXPORT extern const char kIsRunningInMash[]; CONTENT_EXPORT extern const char kJavaScriptFlags[]; CONTENT_EXPORT extern const char kJavaScriptHarmony[]; CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 0365a284..f7ea97f0 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -144,7 +144,7 @@ int browser_plugin_instance_id, const viz::SurfaceInfo& surface_info, const viz::SurfaceSequence& sequence) { - if (!attached() || IsRunningInMash()) + if (!attached() || IsRunningWithMus()) return; if (!enable_surface_synchronization_) { @@ -296,7 +296,7 @@ sent_resize_params_ = pending_resize_params_; #if defined(USE_AURA) - if (IsRunningInMash() && mus_embedded_frame_) { + if (IsRunningWithMus() && mus_embedded_frame_) { mus_embedded_frame_->SetWindowBounds(local_surface_id_, FrameRectInPixels()); } @@ -362,7 +362,7 @@ void BrowserPlugin::OnSetMusEmbedToken( int instance_id, const base::UnguessableToken& embed_token) { - DCHECK(IsRunningInMash()); + DCHECK(IsRunningWithMus()); if (!attached_) { pending_embed_token_ = embed_token; } else {
diff --git a/content/renderer/mash_util.cc b/content/renderer/mash_util.cc index 23c58773..4c3b525d 100644 --- a/content/renderer/mash_util.cc +++ b/content/renderer/mash_util.cc
@@ -5,13 +5,17 @@ #include "content/renderer/mash_util.h" #include "base/command_line.h" -#include "content/public/common/content_switches.h" +#include "ui/base/ui_base_switches.h" namespace content { -bool IsRunningInMash() { +bool IsRunningWithMus() { +#if BUILDFLAG(ENABLE_MUS) const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - return cmdline->HasSwitch(switches::kIsRunningInMash); + return cmdline->HasSwitch(switches::kMus); +#else + return false; +#endif } } // namespace content
diff --git a/content/renderer/mash_util.h b/content/renderer/mash_util.h index 9091cce..3933b73 100644 --- a/content/renderer/mash_util.h +++ b/content/renderer/mash_util.h
@@ -7,7 +7,7 @@ namespace content { -bool IsRunningInMash(); +bool IsRunningWithMus(); } // namespace content
diff --git a/content/renderer/media/gpu/rtc_video_encoder.cc b/content/renderer/media/gpu/rtc_video_encoder.cc index aebe2d24..8a2a2d3 100644 --- a/content/renderer/media/gpu/rtc_video_encoder.cc +++ b/content/renderer/media/gpu/rtc_video_encoder.cc
@@ -22,7 +22,6 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "build/build_config.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h" @@ -523,11 +522,7 @@ } pending_timestamps_.pop_front(); } -#if !defined(OS_ANDROID) - // No capture timestamps available on Android at present. So generate rtp - // timestamps below. DCHECK(rtp_timestamp.has_value()); -#endif } if (!rtp_timestamp.has_value()) { failed_timestamp_match_ = true;
diff --git a/content/renderer/media/gpu/rtc_video_encoder_unittest.cc b/content/renderer/media/gpu/rtc_video_encoder_unittest.cc index 336705c..31bccb0 100644 --- a/content/renderer/media/gpu/rtc_video_encoder_unittest.cc +++ b/content/renderer/media/gpu/rtc_video_encoder_unittest.cc
@@ -292,15 +292,7 @@ rtc_encoder_->Encode(rtc_frame, nullptr, &frame_types)); } -// We cannot run this test on Android because AndroidVideoEncodeAccelerator does -// not preserve timestamps. -#if defined(OS_ANDROID) -#define MAYBE_PreserveTimestamps DISABLED_PreserveTimestamps -#else -#define MAYBE_PreserveTimestamps PreserveTimestamps -#endif // defined(OS_ANDROID) - -TEST_F(RTCVideoEncoderTest, MAYBE_PreserveTimestamps) { +TEST_F(RTCVideoEncoderTest, PreserveTimestamps) { const webrtc::VideoCodecType codec_type = webrtc::kVideoCodecVP8; CreateEncoder(codec_type); webrtc::VideoCodec codec = GetDefaultCodec();
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc index 84353df..596740f 100644 --- a/content/renderer/mus/renderer_window_tree_client.cc +++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -30,7 +30,7 @@ // static void RendererWindowTreeClient::CreateIfNecessary(int routing_id) { - if (!IsRunningInMash() || Get(routing_id)) + if (!IsRunningWithMus() || Get(routing_id)) return; RendererWindowTreeClient* connection = new RendererWindowTreeClient(routing_id);
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 132ce35..3d2f6dc 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -230,7 +230,7 @@ pending_resize_params_.screen_info = render_widget_->screen_info(); #if defined(USE_AURA) - if (IsRunningInMash()) { + if (IsRunningWithMus()) { RendererWindowTreeClient* renderer_window_tree_client = RendererWindowTreeClient::Get(render_widget_->routing_id()); // It's possible a MusEmbeddedFrame has already been scheduled for creation @@ -400,7 +400,7 @@ void RenderFrameProxy::OnViewChanged(const viz::FrameSinkId& frame_sink_id) { // In mash the FrameSinkId comes from RendererWindowTreeClient. - if (!IsRunningInMash()) + if (!IsRunningWithMus()) frame_sink_id_ = frame_sink_id; // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 4bfd1f3..b76a020 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -690,7 +690,7 @@ gpu_ = ui::Gpu::Create( GetConnector(), - IsRunningInMash() ? ui::mojom::kServiceName : mojom::kBrowserServiceName, + IsRunningWithMus() ? ui::mojom::kServiceName : mojom::kBrowserServiceName, GetIOTaskRunner()); viz::mojom::SharedBitmapAllocationNotifierPtr @@ -799,7 +799,7 @@ // Register exported services: #if defined(USE_AURA) - if (IsRunningInMash()) { + if (IsRunningWithMus()) { CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection()); } #endif @@ -952,7 +952,7 @@ categorized_worker_pool_->Start(num_raster_threads); discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (IsRunningInMash()) { + if (IsRunningWithMus()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr); @@ -2043,7 +2043,7 @@ } #if defined(USE_AURA) - if (IsRunningInMash()) { + if (IsRunningWithMus()) { if (!RendererWindowTreeClient::Get(routing_id)) { callback.Run(nullptr); return;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 6704d26b..d8bb604 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -403,7 +403,7 @@ } #if defined(USE_AURA) RendererWindowTreeClient::CreateIfNecessary(routing_id_); - if (IsRunningInMash()) + if (IsRunningWithMus()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_); #endif } @@ -2085,7 +2085,7 @@ is_hidden_ = hidden; #if defined(USE_AURA) - if (IsRunningInMash()) + if (IsRunningWithMus()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden); #endif
diff --git a/content/test/data/android/input/input_forms.html b/content/test/data/android/input/input_forms.html index 97a049ce..3005f0e 100644 --- a/content/test/data/android/input/input_forms.html +++ b/content/test/data/android/input/input_forms.html
@@ -23,6 +23,10 @@ <input id="input_text1" type="text" size="10" size="10"><br> <input id="input_radio" type="radio" style="width:50px;height:50px"><br> </form> + <form> + <input id="autocorrect_off" type="input" autocorrect="off"> + <input id="autocorrect_on" type="input" autocorrect="on"> + </form> <!-- We may trigger different sets of events for CONTENTEDITABLE and INPUT / TEXTAREA --> <div id="contenteditable_event" contenteditable><b>ab</b>cd<i>ef<b>gh</b></i></div>
diff --git a/content/test/data/gpu/pixel_webgl_premultiplied_alpha_false.html b/content/test/data/gpu/pixel_webgl_premultiplied_alpha_false.html new file mode 100644 index 0000000..b2c0ff9 --- /dev/null +++ b/content/test/data/gpu/pixel_webgl_premultiplied_alpha_false.html
@@ -0,0 +1,57 @@ +<!DOCTYPE HTML> + +<html> +<head> +<title>WebGL PremultipliedAlpha False Test</title> +<style type="text/css"> +.nomargin { + margin: 0px auto; +} +</style> + +<script> +function sendResult(status, detail) { + console.log(detail); + if (window.domAutomationController) { + window.domAutomationController.send(status); + } else { + console.log(status); + } +} + +var numFramesBeforeEnd = 15; + +function main() { + var canvas = document.getElementById("c"); + var gl = canvas.getContext( + 'webgl', { antialias: false, premultipliedAlpha: false }); + if (!gl) { + sendResult("FAILURE", "WebGL context not supported"); + return; + } + + // Clear the left half of the canvas to transparent red, assuming + // non-premultiplied alpha. + gl.scissor(0, 0, 150, 150); + gl.enable(gl.SCISSOR_TEST); + gl.clearColor(1.0, 0.0, 0.0, 0.4); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.disable(gl.SCISSOR_TEST); + window.requestAnimationFrame(waitForFinish); +} + +function waitForFinish() +{ + if (--numFramesBeforeEnd == 0) { + sendResult("SUCCESS", "Test complete"); + } else { + window.requestAnimationFrame(waitForFinish); + } +} +</script> +</head> +<body onload="main()"> +<canvas id="c" width="300" height="150" class="nomargin" style="position:absolute; top:0px; left:0px; background-color: #008000;"></canvas> +</div> +</body> +</html>
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 0a6cc28..195f1b8 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -227,6 +227,18 @@ 'swarming': True, 'os_type': 'linux', }, + 'Android Release (Nexus 5X)': { + 'swarming_dimensions': [ + { + 'device_type': 'bullhead', + 'device_os': 'M', + 'os': 'Android' + }, + ], + 'build_config': 'android-chromium', + 'swarming': True, + 'os_type': 'android', + }, } }
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 9af8ee1..057fd8b 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -150,6 +150,57 @@ revision=7), PixelTestPage( + 'pixel_webgl_premultiplied_alpha_false.html', + base_name + '_WebGL_PremultipliedAlpha_False', + test_rect=[0, 0, 150, 150], + revision=0, # This is not used. + expected_colors=[ + # TODO(kbr): if this works, then factor it out so it applies + # to all pixel tests that use programmatic expectations. + { + "comment": "scale factor overrides", + "scale_factor_overrides": [ + { + "device_type": "Nexus 5", + "scale_factor": 1.105 + }, + { + "device_type": "Nexus 5X", + "scale_factor": 1.105 + }, + { + "device_type": "Nexus 6", + "scale_factor": 1.47436 + }, + { + "device_type": "Nexus 6P", + "scale_factor": 1.472 + }, + { + "device_type": "Nexus 9", + "scale_factor": 1.566 + }, + { + "comment": "NVIDIA Shield", + "device_type": "sb_na_wf", + "scale_factor": 1.226 + } + ] + }, + { + 'comment': 'brown', + 'location': [1, 1], + 'size': [148, 148], + # This is the color on an NVIDIA based MacBook Pro if the + # sRGB profile's applied correctly. + 'color': [102, 77, 0], + # This is the color if it isn't. + # 'color': [101, 76, 12], + 'tolerance': 3 + }, + ]), + + PixelTestPage( 'pixel_webgl2_blitframebuffer_result_displayed.html', base_name + '_WebGL2_BlitFramebuffer_Result_Displayed', test_rect=[0, 0, 200, 200],
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 721a2607..42803406 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -616,6 +616,9 @@ bug=609883) self.Fail('conformance/extensions/webgl-compressed-texture-atc.html', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=609883) + # This test is skipped because it is crashing the GPU process. + self.Skip('conformance/glsl/bugs/init-array-with-loop.html', + ['android', ('qualcomm', 'Adreno (TM) 418')], bug=784817) self.Fail('conformance/glsl/bugs/sampler-struct-function-arg.html', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=609883) # This test is skipped because it is crashing the GPU process.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt index b429206..d770d70b 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt +++ b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
@@ -1,3 +1,3 @@ # AUTOGENERATED FILE - DO NOT EDIT # SEE roll_webgl_conformance.py -Current webgl revision 12192b948daa2d83269ab46cbf03d65e9f2a48a3 +Current webgl revision e4919fa03c74bd561dcabf3e61668fa3c7e54353
diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc index c04b614..76e59305 100644 --- a/device/bluetooth/bluetooth_adapter_win.cc +++ b/device/bluetooth/bluetooth_adapter_win.cc
@@ -282,8 +282,9 @@ // (primary services of BLE device) are the same. However, in BLE tests, // we may simulate characteristic, descriptor and secondary GATT service // after device has been initialized. - if (force_update_device_for_test_) + if (force_update_device_for_test_) { device_win->Update(*device_state); + } } } }
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc index 19fc5cd..b9cd97e 100644 --- a/device/bluetooth/bluetooth_device_unittest.cc +++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -82,13 +82,7 @@ service_uuids.push_back(duplicate_service_uuid_.canonical_value()); SimulateGattServicesDiscovered(device_, service_uuids); base::RunLoop().RunUntilIdle(); -#if defined(OS_WIN) - // TODO(crbug.com/507419): Check connection once CreateGattConnection is - // implemented on Windows. - EXPECT_FALSE(device_->IsGattServicesDiscoveryComplete()); -#else EXPECT_TRUE(device_->IsGattServicesDiscoveryComplete()); -#endif // defined(OS_WIN) } protected: @@ -1388,11 +1382,39 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, observer.gatt_services_discovered_count()); - EXPECT_EQ(2, observer.gatt_service_added_count()); } #endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_MACOSX) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_MACOSX) +TEST_F(BluetoothTest, GattServicesDiscovered_Success) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + StartLowEnergyDiscoverySession(); + TestBluetoothAdapterObserver observer(adapter_); + BluetoothDevice* device = SimulateLowEnergyDevice(3); + device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED), + GetConnectErrorCallback(Call::NOT_EXPECTED)); + ResetEventCounts(); + SimulateGattConnection(device); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, gatt_discovery_attempts_); + EXPECT_EQ(0, observer.gatt_services_discovered_count()); + + SimulateGattServicesDiscovered( + device, + std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate})); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(device->IsGattServicesDiscoveryComplete()); + EXPECT_EQ(1, observer.gatt_services_discovered_count()); + EXPECT_EQ(2u, device->GetGattServices().size()); +} +#endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_MACOSX) + +#if defined(OS_ANDROID) || defined(OS_WIN) // macOS: Not applicable: This can never happen because when // the device gets destroyed the CBPeripheralDelegate is also destroyed // and no more events are dispatched. @@ -1421,9 +1443,9 @@ std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate})); base::RunLoop().RunUntilIdle(); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) // macOS: Not applicable: This can never happen because when // the device gets destroyed the CBPeripheralDelegate is also destroyed // and no more events are dispatched. @@ -1450,11 +1472,12 @@ SimulateGattServicesDiscoveryError(nullptr /* use remembered device */); base::RunLoop().RunUntilIdle(); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) #if defined(OS_ANDROID) || defined(OS_MACOSX) +// Windows does not support disconnection. TEST_F(BluetoothTest, GattServicesDiscovered_AfterDisconnection) { - // Tests that we don't crash there was an error discovering services after + // Tests that we don't crash if there was an error discovering services after // the device disconnects. if (!PlatformSupportsLowEnergy()) { LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; @@ -1484,6 +1507,7 @@ #endif // defined(OS_ANDROID) || defined(OS_MACOSX) #if defined(OS_ANDROID) || defined(OS_MACOSX) +// Windows does not support disconnecting. TEST_F(BluetoothTest, GattServicesDiscoveredError_AfterDisconnection) { // Tests that we don't crash if services are discovered after // the device disconnects. @@ -1509,7 +1533,7 @@ EXPECT_FALSE(device->IsGattServicesDiscoveryComplete()); EXPECT_EQ(0u, device->GetGattServices().size()); } -#endif // defined(OS_ANDROID) || defined(OS_MACOSX) +#endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_MACOSX) #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_MACOSX) TEST_F(BluetoothTest, GetGattServices_and_GetGattService) {
diff --git a/device/bluetooth/bluetooth_device_win.cc b/device/bluetooth/bluetooth_device_win.cc index 35ceee7..7c1502d07 100644 --- a/device/bluetooth/bluetooth_device_win.cc +++ b/device/bluetooth/bluetooth_device_win.cc
@@ -277,6 +277,21 @@ UpdateServices(device_state); } +void BluetoothDeviceWin::GattServiceDiscoveryComplete( + BluetoothRemoteGattServiceWin* service) { + DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(BluetoothDeviceWin::IsGattServiceDiscovered( + service->GetUUID(), service->GetAttributeHandle())); + + discovery_completed_included_services_.insert( + {service->GetUUID(), service->GetAttributeHandle()}); + if (discovery_completed_included_services_.size() != gatt_services_.size()) + return; + + SetGattServicesDiscoveryComplete(true); + adapter_->NotifyGattServicesDiscovered(this); +} + void BluetoothDeviceWin::CreateGattConnectionImpl() { // Windows implementation does not use the default CreateGattConnection // implementation. @@ -310,7 +325,7 @@ UpdateGattServices(device_state.service_record_states); } -bool BluetoothDeviceWin::IsGattServiceDiscovered(BluetoothUUID& uuid, +bool BluetoothDeviceWin::IsGattServiceDiscovered(const BluetoothUUID& uuid, uint16_t attribute_handle) { for (const auto& gatt_service : gatt_services_) { uint16_t it_att_handle = @@ -382,8 +397,6 @@ adapter_->NotifyGattServiceAdded(primary_service); } } - - adapter_->NotifyGattServicesDiscovered(this); } } // namespace device
diff --git a/device/bluetooth/bluetooth_device_win.h b/device/bluetooth/bluetooth_device_win.h index ce853e8..6934d6e0 100644 --- a/device/bluetooth/bluetooth_device_win.h +++ b/device/bluetooth/bluetooth_device_win.h
@@ -25,10 +25,13 @@ namespace device { class BluetoothAdapterWin; +class BluetoothRemoteGattServiceWin; class BluetoothServiceRecordWin; class BluetoothSocketThread; -class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWin : public BluetoothDevice { +class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWin + : public BluetoothDevice, + public BluetoothAdapter::Observer { public: explicit BluetoothDeviceWin( BluetoothAdapterWin* adapter, @@ -100,6 +103,10 @@ // |device_state|. void Update(const BluetoothTaskManagerWin::DeviceState& device_state); + // Notify |service| discovery complete, |service| is a remote GATT service of + // this device. + void GattServiceDiscoveryComplete(BluetoothRemoteGattServiceWin* service); + protected: // BluetoothDevice override void CreateGattConnectionImpl() override; @@ -117,7 +124,8 @@ // Checks if GATT service with |uuid| and |attribute_handle| has already been // discovered. - bool IsGattServiceDiscovered(BluetoothUUID& uuid, uint16_t attribute_handle); + bool IsGattServiceDiscovered(const BluetoothUUID& uuid, + uint16_t attribute_handle); // Checks if |service| still exist on device according to newly discovered // |service_state|. @@ -162,6 +170,11 @@ // The service records retrieved from SDP. std::vector<std::unique_ptr<BluetoothServiceRecordWin>> service_record_list_; + // The element of the set is the uuid / attribute handle pair of the + // BluetoothRemoteGattServiceWin instance. + std::set<std::pair<BluetoothUUID, uint16_t>> + discovery_completed_included_services_; + DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceWin); };
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc index a8e356a..44b90a52 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
@@ -2155,6 +2155,23 @@ } #endif // defined(OS_ANDROID) || defined(OS_MACOSX) +#if defined(OS_MACOSX) || defined(OS_WIN) +// TODO(786473) Android should report that services are discovered when a +// characteristic is added, but currently does not. +TEST_F(BluetoothRemoteGattCharacteristicTest, GattCharacteristicAdded) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); + TestBluetoothAdapterObserver observer(adapter_); + + SimulateGattCharacteristic(service_, kTestUUIDDeviceName, 0); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, observer.gatt_services_discovered_count()); +} +#endif // defined(OS_MACOSX) || defined(OS_WIN) + #if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) // Tests Characteristic Value changes during a Notify Session. TEST_F(BluetoothRemoteGattCharacteristicTest, GattCharacteristicValueChanged) {
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc index e451732..8453c17 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
@@ -27,6 +27,7 @@ characteristic_added_notified_(false), characteristic_value_read_or_write_in_progress_(false), gatt_event_handle_(nullptr), + discovery_pending_count_(0), weak_ptr_factory_(this) { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(parent_service_); @@ -205,6 +206,7 @@ void BluetoothRemoteGattCharacteristicWin::Update() { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); + ++discovery_pending_count_; task_manager_->PostGetGattIncludedDescriptors( parent_service_->GetServicePath(), characteristic_info_.get(), base::Bind(&BluetoothRemoteGattCharacteristicWin:: @@ -251,6 +253,10 @@ characteristic_added_notified_ = true; parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); } + + // Report discovery complete. + if (--discovery_pending_count_ == 0) + parent_service_->GattCharacteristicDiscoveryComplete(this); } void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors(
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h index dd29121..8936119 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -130,6 +130,10 @@ // GATT event handle returned by GattEventRegistrationCallback. PVOID gatt_event_handle_; + // Counts the number of asynchronous operations that are discovering + // descriptors. + int discovery_pending_count_; + base::WeakPtrFactory<BluetoothRemoteGattCharacteristicWin> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicWin); };
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc b/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc index 4b4db43..c70448c 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc
@@ -21,7 +21,7 @@ #if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) class BluetoothRemoteGattServiceTest : public BluetoothTest {}; -#endif +#endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) // Android is excluded because it fires a single discovery event per device. #if defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.cc b/device/bluetooth/bluetooth_remote_gatt_service_win.cc index 954c1e6..7f4e3381 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_win.cc +++ b/device/bluetooth/bluetooth_remote_gatt_service_win.cc
@@ -31,6 +31,7 @@ parent_service_(parent_service), ui_task_runner_(ui_task_runner), discovery_complete_notified_(false), + discovery_pending_count_(0), weak_ptr_factory_(this) { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(!service_path_.empty()); @@ -113,6 +114,7 @@ void BluetoothRemoteGattServiceWin::Update() { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); + ++discovery_pending_count_; task_manager_->PostGetGattIncludedCharacteristics( service_path_, service_uuid_, service_attribute_handle_, base::Bind(&BluetoothRemoteGattServiceWin::OnGetIncludedCharacteristics, @@ -125,9 +127,14 @@ HRESULT hr) { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); - UpdateIncludedCharacteristics(characteristics.get(), num); + if (--discovery_pending_count_ != 0) + return; + + // Report discovery complete. SetDiscoveryComplete(true); + UpdateIncludedCharacteristics(characteristics.get(), num); NotifyGattDiscoveryCompleteForServiceIfNecessary(); + device_->GattServiceDiscoveryComplete(this); } void BluetoothRemoteGattServiceWin::UpdateIncludedCharacteristics(
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.h b/device/bluetooth/bluetooth_remote_gatt_service_win.h index 16983494..ac5cbae6 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_win.h +++ b/device/bluetooth/bluetooth_remote_gatt_service_win.h
@@ -115,6 +115,10 @@ // avoid duplicate notification. bool discovery_complete_notified_; + // Counts the number of asynchronous operations that are discovering + // characteristics. + int discovery_pending_count_; + base::WeakPtrFactory<BluetoothRemoteGattServiceWin> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceWin); };
diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc index 9f80fc1..e38da91 100644 --- a/device/bluetooth/test/bluetooth_test_win.cc +++ b/device/bluetooth/test/bluetooth_test_win.cc
@@ -196,8 +196,11 @@ void BluetoothTestWin::SimulateGattServicesDiscovered( BluetoothDevice* device, const std::vector<std::string>& uuids) { + std::string address = + device ? device->GetAddress() : remembered_device_address_; + win::BLEDevice* simulated_device = - fake_bt_le_wrapper_->GetSimulatedBLEDevice(device->GetAddress()); + fake_bt_le_wrapper_->GetSimulatedBLEDevice(address); CHECK(simulated_device); for (auto uuid : uuids) { @@ -206,6 +209,11 @@ } FinishPendingTasks(); + + // We still need to discover characteristics. Wait for the appropriate method + // to be posted and then finish the pending tasks. + base::RunLoop().RunUntilIdle(); + FinishPendingTasks(); } void BluetoothTestWin::SimulateGattServiceRemoved( @@ -363,6 +371,11 @@ FinishPendingTasks(); } +void BluetoothTestWin::RememberDeviceForSubsequentAction( + BluetoothDevice* device) { + remembered_device_address_ = device->GetAddress(); +} + void BluetoothTestWin::DeleteDevice(BluetoothDevice* device) { CHECK(device); fake_bt_le_wrapper_->RemoveSimulatedBLEDevice(device->GetAddress()); @@ -506,6 +519,11 @@ void BluetoothTestWin::ForceRefreshDevice() { adapter_win_->force_update_device_for_test_ = true; FinishPendingTasks(); + adapter_win_->force_update_device_for_test_ = false; + + // The characteristics still need to be discovered. + base::RunLoop().RunUntilIdle(); + FinishPendingTasks(); } void BluetoothTestWin::FinishPendingTasks() {
diff --git a/device/bluetooth/test/bluetooth_test_win.h b/device/bluetooth/test/bluetooth_test_win.h index 9649d0f..c420229 100644 --- a/device/bluetooth/test/bluetooth_test_win.h +++ b/device/bluetooth/test/bluetooth_test_win.h
@@ -56,6 +56,7 @@ void SimulateGattCharacteristicWriteError( BluetoothRemoteGattCharacteristic* characteristic, BluetoothRemoteGattService::GattErrorCode error_code) override; + void RememberDeviceForSubsequentAction(BluetoothDevice* device) override; void DeleteDevice(BluetoothDevice* device) override; void SimulateGattDescriptor(BluetoothRemoteGattCharacteristic* characteristic, const std::string& uuid) override; @@ -83,6 +84,9 @@ win::BluetoothClassicWrapperFake* fake_bt_classic_wrapper_; win::BluetoothLowEnergyWrapperFake* fake_bt_le_wrapper_; + // This is used for retaining access to a single deleted device. + std::string remembered_device_address_; + void AdapterInitCallback(); win::GattService* GetSimulatedService(win::BLEDevice* device, BluetoothRemoteGattService* service);
diff --git a/device/geolocation/BUILD.gn b/device/geolocation/BUILD.gn index 3d70cc0..c3f47f0 100644 --- a/device/geolocation/BUILD.gn +++ b/device/geolocation/BUILD.gn
@@ -74,8 +74,6 @@ sources -= [ "network_location_provider.cc", "network_location_provider.h", - "network_location_request.cc", - "network_location_request.h", ] deps += [ ":geolocation_jni_headers" ] }
diff --git a/device/geolocation/network_location_request.h b/device/geolocation/network_location_request.h index 07fe536..10ae8e01 100644 --- a/device/geolocation/network_location_request.h +++ b/device/geolocation/network_location_request.h
@@ -28,10 +28,11 @@ // Takes wifi data and sends it to a server to get a position fix. // It performs formatting of the request and interpretation of the response. -class NetworkLocationRequest : private net::URLFetcherDelegate { +class DEVICE_GEOLOCATION_EXPORT NetworkLocationRequest + : private net::URLFetcherDelegate { public: // ID passed to URLFetcher::Create(). Used for testing. - DEVICE_GEOLOCATION_EXPORT static int url_fetcher_id_for_tests; + static int url_fetcher_id_for_tests; // Called when a new geo position is available. The second argument indicates // whether there was a server error or not. It is true when there was a
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn index 38663e3..7f61975 100644 --- a/device/vr/BUILD.gn +++ b/device/vr/BUILD.gn
@@ -70,6 +70,7 @@ if (enable_openvr) { deps += [ "//device/gamepad", + "//device/gamepad/public/cpp:shared_with_blink", "//third_party/openvr:openvr", ] sources += [
diff --git a/device/vr/features/features.gni b/device/vr/features/features.gni index 2e3c76a7..5698cd8 100644 --- a/device/vr/features/features.gni +++ b/device/vr/features/features.gni
@@ -9,13 +9,12 @@ # support arm and arm64. enable_gvr_services = is_android && !is_chromecast && (current_cpu == "arm" || current_cpu == "arm64") - enable_openvr = false + enable_openvr = is_win } declare_args() { - # Enable VR device support whenever VR device SDK(s) are supported and - # on Windows for testing. - enable_vr = enable_gvr_services || enable_openvr || is_win + # Enable VR device support whenever VR device SDK(s) are supported. + enable_vr = enable_gvr_services || enable_openvr # Whether to include VR extras like test APKs in non-VR-specific targets include_vr_data = false
diff --git a/device/vr/openvr/openvr_device_provider.cc b/device/vr/openvr/openvr_device_provider.cc index baed53a..8ba4aee 100644 --- a/device/vr/openvr/openvr_device_provider.cc +++ b/device/vr/openvr/openvr_device_provider.cc
@@ -14,14 +14,24 @@ OpenVRDeviceProvider::OpenVRDeviceProvider() : initialized_(false), vr_system_(nullptr) {} -OpenVRDeviceProvider::~OpenVRDeviceProvider() {} +OpenVRDeviceProvider::~OpenVRDeviceProvider() { + device::GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory( + device::GAMEPAD_SOURCE_OPENVR); + device_ = nullptr; + vr::VR_Shutdown(); +} void OpenVRDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) { if (initialized_) { - VRDevice* device = new OpenVRDevice(vr_system_); - devices->push_back(device); - GamepadDataFetcherManager::GetInstance()->AddFactory( - new OpenVRGamepadDataFetcher::Factory(device->GetId(), vr_system_)); + if (!device_) { + device_ = std::make_unique<OpenVRDevice>(vr_system_); + GamepadDataFetcherManager::GetInstance()->AddFactory( + new OpenVRGamepadDataFetcher::Factory(device_->GetId(), vr_system_)); + } + + if (device_) { + devices->push_back(device_.get()); + } } }
diff --git a/device/vr/openvr/openvr_device_provider.h b/device/vr/openvr/openvr_device_provider.h index 7dc42db4..4e5fa3fd 100644 --- a/device/vr/openvr/openvr_device_provider.h +++ b/device/vr/openvr/openvr_device_provider.h
@@ -18,6 +18,8 @@ namespace device { +class OpenVRDevice; + class DEVICE_VR_EXPORT OpenVRDeviceProvider : public VRDeviceProvider { public: OpenVRDeviceProvider(); @@ -29,6 +31,7 @@ private: bool initialized_; vr::IVRSystem* vr_system_; + std::unique_ptr<OpenVRDevice> device_; DISALLOW_COPY_AND_ASSIGN(OpenVRDeviceProvider); };
diff --git a/device/vr/openvr/openvr_render_loop.cc b/device/vr/openvr/openvr_render_loop.cc index 1d0051a..788962d 100644 --- a/device/vr/openvr/openvr_render_loop.cc +++ b/device/vr/openvr/openvr_render_loop.cc
@@ -20,7 +20,9 @@ DCHECK(main_thread_task_runner_); } -OpenVRRenderLoop::~OpenVRRenderLoop() {} +OpenVRRenderLoop::~OpenVRRenderLoop() { + Stop(); +} void OpenVRRenderLoop::SubmitFrame(int16_t frame_index, const gpu::MailboxHolder& mailbox) { @@ -78,6 +80,11 @@ #endif } +void OpenVRRenderLoop::CleanUp() { + submit_client_ = nullptr; + binding_.Close(); +} + void OpenVRRenderLoop::UpdateLayerBounds(int16_t frame_id, const gfx::RectF& left_bounds, const gfx::RectF& right_bounds,
diff --git a/device/vr/openvr/openvr_render_loop.h b/device/vr/openvr/openvr_render_loop.h index 676bc824..8719c53 100644 --- a/device/vr/openvr/openvr_render_loop.h +++ b/device/vr/openvr/openvr_render_loop.h
@@ -45,6 +45,7 @@ private: // base::Thread overrides: void Init() override; + void CleanUp() override; mojom::VRPosePtr GetPose();
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index a0537d0..92da9bf 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -377,6 +377,7 @@ "//base", "//base/test:test_support", "//base/third_party/dynamic_annotations", + "//cc/paint", "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/common:gles2_utils",
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index 4d36aea..6b2d4bf 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -399,6 +399,12 @@ #define glBeginRasterCHROMIUM GLES2_GET_FUN(BeginRasterCHROMIUM) #define glRasterCHROMIUM GLES2_GET_FUN(RasterCHROMIUM) #define glEndRasterCHROMIUM GLES2_GET_FUN(EndRasterCHROMIUM) +#define glCreateTransferCacheEntryCHROMIUM \ + GLES2_GET_FUN(CreateTransferCacheEntryCHROMIUM) +#define glDeleteTransferCacheEntryCHROMIUM \ + GLES2_GET_FUN(DeleteTransferCacheEntryCHROMIUM) +#define glUnlockTransferCacheEntryCHROMIUM \ + GLES2_GET_FUN(UnlockTransferCacheEntryCHROMIUM) #define glTexStorage2DImageCHROMIUM GLES2_GET_FUN(TexStorage2DImageCHROMIUM) #define glSetColorSpaceMetadataCHROMIUM \ GLES2_GET_FUN(SetColorSpaceMetadataCHROMIUM)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index ebfe95e..b3f0866 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4635,6 +4635,30 @@ 'extension': 'CHROMIUM_raster_transport', 'extension_flag': 'chromium_raster_transport', }, + "CreateTransferCacheEntryCHROMIUM": { + 'type': 'Custom', + 'cmd_args': 'GLuint64 handle_id, GLuint handle_shm_id, ' + 'GLuint handle_shm_offset, GLuint type, ' + 'GLuint data_shm_id, GLuint data_shm_offset, ' + 'GLuint data_size', + 'impl_func': False, + 'client_test': False, + 'extension': True, + }, + "DeleteTransferCacheEntryCHROMIUM": { + 'decoder_func': 'DoDeleteTransferCacheEntryCHROMIUM', + 'cmd_args': 'GLuint64 handle_id', + 'impl_func': True, + 'client_test': False, + 'extension': True, + }, + "UnlockTransferCacheEntryCHROMIUM": { + 'decoder_func': 'DoUnlockTransferCacheEntryCHROMIUM', + 'cmd_args': 'GLuint64 handle_id', + 'impl_func': True, + 'client_test': False, + 'extension': True, + }, 'TexStorage2DImageCHROMIUM': { 'decoder_func': 'DoTexStorage2DImageCHROMIUM', 'unit_test': False,
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn index 50c937df..12beb1a 100644 --- a/gpu/command_buffer/client/BUILD.gn +++ b/gpu/command_buffer/client/BUILD.gn
@@ -46,6 +46,8 @@ "client_discardable_manager.h", "client_discardable_texture_manager.cc", "client_discardable_texture_manager.h", + "client_transfer_cache.cc", + "client_transfer_cache.h", "cmd_buffer_helper.cc", "cmd_buffer_helper.h", "fenced_allocator.cc", @@ -70,11 +72,16 @@ "//gpu/command_buffer/common:gles2_utils", ] deps = [ + ":gles2_interface", "//gpu/command_buffer/common:common_sources", "//gpu/ipc/common:surface_handle_type", "//ui/gfx:memory_buffer", "//ui/gfx/geometry", ] + + if (!is_nacl) { + deps += [ "//cc/paint" ] + } } source_set("gles2_cmd_helper_sources") {
diff --git a/gpu/command_buffer/client/client_transfer_cache.cc b/gpu/command_buffer/client/client_transfer_cache.cc new file mode 100644 index 0000000..a929e87 --- /dev/null +++ b/gpu/command_buffer/client/client_transfer_cache.cc
@@ -0,0 +1,44 @@ +// Copyright (c) 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 "gpu/command_buffer/client/client_transfer_cache.h" + +namespace gpu { + +ClientTransferCache::ClientTransferCache() = default; +ClientTransferCache::~ClientTransferCache() = default; + +TransferCacheEntryId ClientTransferCache::CreateCacheEntry( + gles2::GLES2Interface* gl, + CommandBuffer* command_buffer, + const cc::ClientTransferCacheEntry& entry) { + TransferCacheEntryId id = discardable_manager_.CreateHandle(command_buffer); + ClientDiscardableHandle handle = discardable_manager_.GetHandle(id); + gl->CreateTransferCacheEntryCHROMIUM(id.GetUnsafeValue(), handle.shm_id(), + handle.byte_offset(), entry); + return id; +} + +bool ClientTransferCache::LockTransferCacheEntry(TransferCacheEntryId id) { + if (discardable_manager_.LockHandle(id)) + return true; + + // Could not lock. Entry is already deleted service side, just free the + // handle. + discardable_manager_.FreeHandle(id); + return false; +} + +void ClientTransferCache::UnlockTransferCacheEntry(gles2::GLES2Interface* gl, + TransferCacheEntryId id) { + gl->UnlockTransferCacheEntryCHROMIUM(id.GetUnsafeValue()); +} + +void ClientTransferCache::DeleteTransferCacheEntry(gles2::GLES2Interface* gl, + TransferCacheEntryId id) { + discardable_manager_.FreeHandle(id); + gl->DeleteTransferCacheEntryCHROMIUM(id.GetUnsafeValue()); +} + +} // namespace gpu
diff --git a/gpu/command_buffer/client/client_transfer_cache.h b/gpu/command_buffer/client/client_transfer_cache.h new file mode 100644 index 0000000..d5c9c35 --- /dev/null +++ b/gpu/command_buffer/client/client_transfer_cache.h
@@ -0,0 +1,57 @@ +// Copyright (c) 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 GPU_COMMAND_BUFFER_CLIENT_CLIENT_TRANSFER_CACHE_H_ +#define GPU_COMMAND_BUFFER_CLIENT_CLIENT_TRANSFER_CACHE_H_ + +#include "cc/paint/transfer_cache_entry.h" +#include "gpu/command_buffer/client/client_discardable_manager.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/common/transfer_cache_entry_id.h" + +namespace gpu { + +// ClientTransferCache allows for ClientTransferCacheEntries to be inserted +// into the cache, which will send them to the ServiceTransferCache, making +// them available for consumption in the GPU process. Typical usage is: +// 1) Insert a new entry via CreateCacheEntry. It starts locked. +// 2) Use the new entry's ID in one or more commands. +// 3) Unlock the entry via UnlockTransferCacheEntry after dependent commands +// have been issued. +// +// If an entry is needed again: +// 4) Attempt to lock the entry via LockTransferCacheEntry. +// 4a) If this fails, DeleteTransferCacheEntry then go to (1) +// 4b) If this succeeds, go to (2). +// +// If an entry is no longer needed: +// 5) DeleteTransferCacheEntry +// +class GPU_EXPORT ClientTransferCache { + public: + ClientTransferCache(); + ~ClientTransferCache(); + + TransferCacheEntryId CreateCacheEntry( + gles2::GLES2Interface* gl, + CommandBuffer* command_buffer, + const cc::ClientTransferCacheEntry& entry); + bool LockTransferCacheEntry(TransferCacheEntryId id); + void UnlockTransferCacheEntry(gles2::GLES2Interface* gl, + TransferCacheEntryId id); + void DeleteTransferCacheEntry(gles2::GLES2Interface* gl, + TransferCacheEntryId id); + + // Test only functions + ClientDiscardableManager* DiscardableManagerForTesting() { + return &discardable_manager_; + } + + private: + ClientDiscardableManager discardable_manager_; +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_CLIENT_TRANSFER_CACHE_H_
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index f9ae81f4..e155246 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1794,6 +1794,20 @@ void GL_APIENTRY GLES2EndRasterCHROMIUM() { gles2::GetGLContext()->EndRasterCHROMIUM(); } +void GL_APIENTRY GLES2CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) { + gles2::GetGLContext()->CreateTransferCacheEntryCHROMIUM( + handle_id, handle_shm_id, handle_shm_offset, entry); +} +void GL_APIENTRY GLES2DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) { + gles2::GetGLContext()->DeleteTransferCacheEntryCHROMIUM(handle_id); +} +void GL_APIENTRY GLES2UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) { + gles2::GetGLContext()->UnlockTransferCacheEntryCHROMIUM(handle_id); +} void GL_APIENTRY GLES2TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage, @@ -3159,6 +3173,21 @@ reinterpret_cast<GLES2FunctionPointer>(glEndRasterCHROMIUM), }, { + "glCreateTransferCacheEntryCHROMIUM", + reinterpret_cast<GLES2FunctionPointer>( + glCreateTransferCacheEntryCHROMIUM), + }, + { + "glDeleteTransferCacheEntryCHROMIUM", + reinterpret_cast<GLES2FunctionPointer>( + glDeleteTransferCacheEntryCHROMIUM), + }, + { + "glUnlockTransferCacheEntryCHROMIUM", + reinterpret_cast<GLES2FunctionPointer>( + glUnlockTransferCacheEntryCHROMIUM), + }, + { "glTexStorage2DImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(glTexStorage2DImageCHROMIUM), },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 5f7cab6..1423350 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -3298,6 +3298,37 @@ } } +void CreateTransferCacheEntryCHROMIUM(GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + GLuint type, + GLuint data_shm_id, + GLuint data_shm_offset, + GLuint data_size) { + gles2::cmds::CreateTransferCacheEntryCHROMIUM* c = + GetCmdSpace<gles2::cmds::CreateTransferCacheEntryCHROMIUM>(); + if (c) { + c->Init(handle_id, handle_shm_id, handle_shm_offset, type, data_shm_id, + data_shm_offset, data_size); + } +} + +void DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) { + gles2::cmds::DeleteTransferCacheEntryCHROMIUM* c = + GetCmdSpace<gles2::cmds::DeleteTransferCacheEntryCHROMIUM>(); + if (c) { + c->Init(handle_id); + } +} + +void UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) { + gles2::cmds::UnlockTransferCacheEntryCHROMIUM* c = + GetCmdSpace<gles2::cmds::UnlockTransferCacheEntryCHROMIUM>(); + if (c) { + c->Init(handle_id); + } +} + void TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index b13547cf..6c4aeb7 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -52,6 +52,7 @@ #if !defined(OS_NACL) #include "cc/paint/display_item_list.h" // nogncheck #include "cc/paint/paint_op_buffer_serializer.h" +#include "cc/paint/transfer_cache_entry.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/skia_util.h" #endif @@ -7108,6 +7109,28 @@ return true; } +void GLES2Implementation::CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) { +#if defined(OS_NACL) + NOTREACHED(); +#else + ScopedMappedMemoryPtr mapped_alloc(entry.SerializedSize(), helper_, + mapped_memory_.get()); + DCHECK(mapped_alloc.valid()); + bool succeeded = entry.Serialize( + mapped_alloc.size(), reinterpret_cast<uint8_t*>(mapped_alloc.address())); + DCHECK(succeeded); + + helper_->CreateTransferCacheEntryCHROMIUM( + handle_id, handle_shm_id, handle_shm_offset, + static_cast<uint32_t>(entry.Type()), mapped_alloc.shm_id(), + mapped_alloc.offset(), mapped_alloc.size()); +#endif +} + void GLES2Implementation::UpdateCachedExtensionsIfNeeded() { if (cached_extension_string_) { return;
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index e5a124280..b5d99a0 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1259,6 +1259,16 @@ void EndRasterCHROMIUM() override; +void CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) override; + +void DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) override; + +void UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) override; + void TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage,
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 6f7a6bd8..f7e26d4 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3574,6 +3574,24 @@ CheckGLError(); } +void GLES2Implementation::DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() + << "] glDeleteTransferCacheEntryCHROMIUM(" << handle_id + << ")"); + helper_->DeleteTransferCacheEntryCHROMIUM(handle_id); + CheckGLError(); +} + +void GLES2Implementation::UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() + << "] glUnlockTransferCacheEntryCHROMIUM(" << handle_id + << ")"); + helper_->UnlockTransferCacheEntryCHROMIUM(handle_id); + CheckGLError(); +} + void GLES2Implementation::TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage,
diff --git a/gpu/command_buffer/client/gles2_interface.h b/gpu/command_buffer/client/gles2_interface.h index 030ecdf..86a385f8 100644 --- a/gpu/command_buffer/client/gles2_interface.h +++ b/gpu/command_buffer/client/gles2_interface.h
@@ -10,6 +10,7 @@ #include "base/compiler_specific.h" namespace cc { +class ClientTransferCacheEntry; class DisplayItemList; }
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 4ea3d63..c332e63a 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -936,6 +936,13 @@ GLfloat post_translate_y, GLfloat post_scale) = 0; virtual void EndRasterCHROMIUM() = 0; +virtual void CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) = 0; +virtual void DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) = 0; +virtual void UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) = 0; virtual void TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 9bb6c57..0d59364 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -909,6 +909,13 @@ GLfloat post_translate_y, GLfloat post_scale) override; void EndRasterCHROMIUM() override; +void CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) override; +void DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) override; +void UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) override; void TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index bbcc356..1214bc2 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1220,6 +1220,15 @@ GLfloat /* post_translate_y */, GLfloat /* post_scale */) {} void GLES2InterfaceStub::EndRasterCHROMIUM() {} +void GLES2InterfaceStub::CreateTransferCacheEntryCHROMIUM( + GLuint64 /* handle_id */, + GLuint /* handle_shm_id */, + GLuint /* handle_shm_offset */, + const cc::ClientTransferCacheEntry& /* entry */) {} +void GLES2InterfaceStub::DeleteTransferCacheEntryCHROMIUM( + GLuint64 /* handle_id */) {} +void GLES2InterfaceStub::UnlockTransferCacheEntryCHROMIUM( + GLuint64 /* handle_id */) {} void GLES2InterfaceStub::TexStorage2DImageCHROMIUM(GLenum /* target */, GLenum /* internalFormat */, GLenum /* bufferUsage */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 5665f233..f0ef8bd 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -909,6 +909,13 @@ GLfloat post_translate_y, GLfloat post_scale) override; void EndRasterCHROMIUM() override; +void CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) override; +void DeleteTransferCacheEntryCHROMIUM(GLuint64 handle_id) override; +void UnlockTransferCacheEntryCHROMIUM(GLuint64 handle_id) override; void TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 338a0db8..32730225 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2603,6 +2603,31 @@ gl_->EndRasterCHROMIUM(); } +void GLES2TraceImplementation::CreateTransferCacheEntryCHROMIUM( + GLuint64 handle_id, + GLuint handle_shm_id, + GLuint handle_shm_offset, + const cc::ClientTransferCacheEntry& entry) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", + "GLES2Trace::CreateTransferCacheEntryCHROMIUM"); + gl_->CreateTransferCacheEntryCHROMIUM(handle_id, handle_shm_id, + handle_shm_offset, entry); +} + +void GLES2TraceImplementation::DeleteTransferCacheEntryCHROMIUM( + GLuint64 handle_id) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", + "GLES2Trace::DeleteTransferCacheEntryCHROMIUM"); + gl_->DeleteTransferCacheEntryCHROMIUM(handle_id); +} + +void GLES2TraceImplementation::UnlockTransferCacheEntryCHROMIUM( + GLuint64 handle_id) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", + "GLES2Trace::UnlockTransferCacheEntryCHROMIUM"); + gl_->UnlockTransferCacheEntryCHROMIUM(handle_id); +} + void GLES2TraceImplementation::TexStorage2DImageCHROMIUM(GLenum target, GLenum internalFormat, GLenum bufferUsage,
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 4e65c80..255dad7c 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -381,6 +381,9 @@ GL_APICALL void GL_APIENTRY glBeginRasterCHROMIUM (GLuint texture_id, GLuint sk_color, GLuint msaa_sample_count, GLboolean can_use_lcd_text, GLboolean use_distance_field_text, GLint pixel_config); GL_APICALL void GL_APIENTRY glRasterCHROMIUM (const cc::DisplayItemList* list, GLint translate_x, GLint translate_y, GLint clip_x, GLint clip_y, GLint clip_w, GLint clip_h, GLfloat post_translate_x, GLfloat post_translate_y, GLfloat post_scale); GL_APICALL void GL_APIENTRY glEndRasterCHROMIUM (void); +GL_APICALL void GL_APIENTRY glCreateTransferCacheEntryCHROMIUM (GLuint64 handle_id, GLuint handle_shm_id, GLuint handle_shm_offset, const cc::ClientTransferCacheEntry& entry); +GL_APICALL void GL_APIENTRY glDeleteTransferCacheEntryCHROMIUM (GLuint64 handle_id); +GL_APICALL void GL_APIENTRY glUnlockTransferCacheEntryCHROMIUM (GLuint64 handle_id); // Extension CHROMIUM_texture_storage_image GL_APICALL void GL_APIENTRY glTexStorage2DImageCHROMIUM (GLenumTextureBindTarget target, GLenumTextureInternalFormatStorage internalFormat, GLenumClientBufferUsage bufferUsage, GLsizei width, GLsizei height);
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn index b7b3dc6..1f177b2b 100644 --- a/gpu/command_buffer/common/BUILD.gn +++ b/gpu/command_buffer/common/BUILD.gn
@@ -62,6 +62,7 @@ "texture_in_use_response.h", "thread_local.h", "time.h", + "transfer_cache_entry_id.h", ] configs += [ "//gpu:gpu_implementation" ]
diff --git a/gpu/command_buffer/common/discardable_handle.cc b/gpu/command_buffer/common/discardable_handle.cc index 6b759c1..7401471 100644 --- a/gpu/command_buffer/common/discardable_handle.cc +++ b/gpu/command_buffer/common/discardable_handle.cc
@@ -50,6 +50,10 @@ return kHandleDeleted == base::subtle::NoBarrier_Load(AsAtomic()); } +scoped_refptr<Buffer> DiscardableHandleBase::BufferForTesting() const { + return buffer_; +} + volatile base::subtle::Atomic32* DiscardableHandleBase::AsAtomic() const { return reinterpret_cast<volatile base::subtle::Atomic32*>( buffer_->GetDataAddress(byte_offset_, sizeof(base::subtle::Atomic32))); @@ -125,6 +129,11 @@ // No barrier is needed as all GPU process access happens on a single thread, // and communication of dependent data between the GPU process and the // renderer process happens across the command buffer and includes barriers. + + // This check notifies a non-malicious caller that they've issued unbalanced + // lock/unlock calls. + DLOG_IF(ERROR, kHandleLockedStart > base::subtle::NoBarrier_Load(AsAtomic())); + base::subtle::NoBarrier_AtomicIncrement(AsAtomic(), -1); }
diff --git a/gpu/command_buffer/common/discardable_handle.h b/gpu/command_buffer/common/discardable_handle.h index 1e9ea51..18cf0e8 100644 --- a/gpu/command_buffer/common/discardable_handle.h +++ b/gpu/command_buffer/common/discardable_handle.h
@@ -43,7 +43,7 @@ // Test only functions. bool IsLockedForTesting() const; bool IsDeletedForTesting() const; - scoped_refptr<Buffer> BufferForTesting() const { return buffer_; } + scoped_refptr<Buffer> BufferForTesting() const; protected: DiscardableHandleBase(scoped_refptr<Buffer> buffer,
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index c994825..46de934 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -16185,6 +16185,183 @@ static_assert(offsetof(EndRasterCHROMIUM, header) == 0, "offset of EndRasterCHROMIUM header should be 0"); +struct CreateTransferCacheEntryCHROMIUM { + typedef CreateTransferCacheEntryCHROMIUM ValueType; + static const CommandId kCmdId = kCreateTransferCacheEntryCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLuint64 _handle_id, + GLuint _handle_shm_id, + GLuint _handle_shm_offset, + GLuint _type, + GLuint _data_shm_id, + GLuint _data_shm_offset, + GLuint _data_size) { + SetHeader(); + GLES2Util::MapUint64ToTwoUint32(static_cast<uint64_t>(_handle_id), + &handle_id_0, &handle_id_1); + handle_shm_id = _handle_shm_id; + handle_shm_offset = _handle_shm_offset; + type = _type; + data_shm_id = _data_shm_id; + data_shm_offset = _data_shm_offset; + data_size = _data_size; + } + + void* Set(void* cmd, + GLuint64 _handle_id, + GLuint _handle_shm_id, + GLuint _handle_shm_offset, + GLuint _type, + GLuint _data_shm_id, + GLuint _data_shm_offset, + GLuint _data_size) { + static_cast<ValueType*>(cmd)->Init(_handle_id, _handle_shm_id, + _handle_shm_offset, _type, _data_shm_id, + _data_shm_offset, _data_size); + return NextCmdAddress<ValueType>(cmd); + } + + GLuint64 handle_id() const volatile { + return static_cast<GLuint64>( + GLES2Util::MapTwoUint32ToUint64(handle_id_0, handle_id_1)); + } + + gpu::CommandHeader header; + uint32_t handle_id_0; + uint32_t handle_id_1; + uint32_t handle_shm_id; + uint32_t handle_shm_offset; + uint32_t type; + uint32_t data_shm_id; + uint32_t data_shm_offset; + uint32_t data_size; +}; + +static_assert(sizeof(CreateTransferCacheEntryCHROMIUM) == 36, + "size of CreateTransferCacheEntryCHROMIUM should be 36"); +static_assert(offsetof(CreateTransferCacheEntryCHROMIUM, header) == 0, + "offset of CreateTransferCacheEntryCHROMIUM header should be 0"); +static_assert( + offsetof(CreateTransferCacheEntryCHROMIUM, handle_id_0) == 4, + "offset of CreateTransferCacheEntryCHROMIUM handle_id_0 should be 4"); +static_assert( + offsetof(CreateTransferCacheEntryCHROMIUM, handle_id_1) == 8, + "offset of CreateTransferCacheEntryCHROMIUM handle_id_1 should be 8"); +static_assert( + offsetof(CreateTransferCacheEntryCHROMIUM, handle_shm_id) == 12, + "offset of CreateTransferCacheEntryCHROMIUM handle_shm_id should be 12"); +static_assert(offsetof(CreateTransferCacheEntryCHROMIUM, handle_shm_offset) == + 16, + "offset of CreateTransferCacheEntryCHROMIUM handle_shm_offset " + "should be 16"); +static_assert(offsetof(CreateTransferCacheEntryCHROMIUM, type) == 20, + "offset of CreateTransferCacheEntryCHROMIUM type should be 20"); +static_assert( + offsetof(CreateTransferCacheEntryCHROMIUM, data_shm_id) == 24, + "offset of CreateTransferCacheEntryCHROMIUM data_shm_id should be 24"); +static_assert( + offsetof(CreateTransferCacheEntryCHROMIUM, data_shm_offset) == 28, + "offset of CreateTransferCacheEntryCHROMIUM data_shm_offset should be 28"); +static_assert( + offsetof(CreateTransferCacheEntryCHROMIUM, data_size) == 32, + "offset of CreateTransferCacheEntryCHROMIUM data_size should be 32"); + +struct DeleteTransferCacheEntryCHROMIUM { + typedef DeleteTransferCacheEntryCHROMIUM ValueType; + static const CommandId kCmdId = kDeleteTransferCacheEntryCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLuint64 _handle_id) { + SetHeader(); + GLES2Util::MapUint64ToTwoUint32(static_cast<uint64_t>(_handle_id), + &handle_id_0, &handle_id_1); + } + + void* Set(void* cmd, GLuint64 _handle_id) { + static_cast<ValueType*>(cmd)->Init(_handle_id); + return NextCmdAddress<ValueType>(cmd); + } + + GLuint64 handle_id() const volatile { + return static_cast<GLuint64>( + GLES2Util::MapTwoUint32ToUint64(handle_id_0, handle_id_1)); + } + + gpu::CommandHeader header; + uint32_t handle_id_0; + uint32_t handle_id_1; +}; + +static_assert(sizeof(DeleteTransferCacheEntryCHROMIUM) == 12, + "size of DeleteTransferCacheEntryCHROMIUM should be 12"); +static_assert(offsetof(DeleteTransferCacheEntryCHROMIUM, header) == 0, + "offset of DeleteTransferCacheEntryCHROMIUM header should be 0"); +static_assert( + offsetof(DeleteTransferCacheEntryCHROMIUM, handle_id_0) == 4, + "offset of DeleteTransferCacheEntryCHROMIUM handle_id_0 should be 4"); +static_assert( + offsetof(DeleteTransferCacheEntryCHROMIUM, handle_id_1) == 8, + "offset of DeleteTransferCacheEntryCHROMIUM handle_id_1 should be 8"); + +struct UnlockTransferCacheEntryCHROMIUM { + typedef UnlockTransferCacheEntryCHROMIUM ValueType; + static const CommandId kCmdId = kUnlockTransferCacheEntryCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLuint64 _handle_id) { + SetHeader(); + GLES2Util::MapUint64ToTwoUint32(static_cast<uint64_t>(_handle_id), + &handle_id_0, &handle_id_1); + } + + void* Set(void* cmd, GLuint64 _handle_id) { + static_cast<ValueType*>(cmd)->Init(_handle_id); + return NextCmdAddress<ValueType>(cmd); + } + + GLuint64 handle_id() const volatile { + return static_cast<GLuint64>( + GLES2Util::MapTwoUint32ToUint64(handle_id_0, handle_id_1)); + } + + gpu::CommandHeader header; + uint32_t handle_id_0; + uint32_t handle_id_1; +}; + +static_assert(sizeof(UnlockTransferCacheEntryCHROMIUM) == 12, + "size of UnlockTransferCacheEntryCHROMIUM should be 12"); +static_assert(offsetof(UnlockTransferCacheEntryCHROMIUM, header) == 0, + "offset of UnlockTransferCacheEntryCHROMIUM header should be 0"); +static_assert( + offsetof(UnlockTransferCacheEntryCHROMIUM, handle_id_0) == 4, + "offset of UnlockTransferCacheEntryCHROMIUM handle_id_0 should be 4"); +static_assert( + offsetof(UnlockTransferCacheEntryCHROMIUM, handle_id_1) == 8, + "offset of UnlockTransferCacheEntryCHROMIUM handle_id_1 should be 8"); + struct TexStorage2DImageCHROMIUM { typedef TexStorage2DImageCHROMIUM ValueType; static const CommandId kCmdId = kTexStorage2DImageCHROMIUM;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 62b6b80..491e549d 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -5390,6 +5390,51 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, CreateTransferCacheEntryCHROMIUM) { + cmds::CreateTransferCacheEntryCHROMIUM& cmd = + *GetBufferAs<cmds::CreateTransferCacheEntryCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint64>(11), + static_cast<GLuint>(12), static_cast<GLuint>(13), + static_cast<GLuint>(14), static_cast<GLuint>(15), + static_cast<GLuint>(16), static_cast<GLuint>(17)); + EXPECT_EQ( + static_cast<uint32_t>(cmds::CreateTransferCacheEntryCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint64>(11), cmd.handle_id()); + EXPECT_EQ(static_cast<GLuint>(12), cmd.handle_shm_id); + EXPECT_EQ(static_cast<GLuint>(13), cmd.handle_shm_offset); + EXPECT_EQ(static_cast<GLuint>(14), cmd.type); + EXPECT_EQ(static_cast<GLuint>(15), cmd.data_shm_id); + EXPECT_EQ(static_cast<GLuint>(16), cmd.data_shm_offset); + EXPECT_EQ(static_cast<GLuint>(17), cmd.data_size); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, DeleteTransferCacheEntryCHROMIUM) { + cmds::DeleteTransferCacheEntryCHROMIUM& cmd = + *GetBufferAs<cmds::DeleteTransferCacheEntryCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint64>(11)); + EXPECT_EQ( + static_cast<uint32_t>(cmds::DeleteTransferCacheEntryCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint64>(11), cmd.handle_id()); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, UnlockTransferCacheEntryCHROMIUM) { + cmds::UnlockTransferCacheEntryCHROMIUM& cmd = + *GetBufferAs<cmds::UnlockTransferCacheEntryCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint64>(11)); + EXPECT_EQ( + static_cast<uint32_t>(cmds::UnlockTransferCacheEntryCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint64>(11), cmd.handle_id()); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, TexStorage2DImageCHROMIUM) { cmds::TexStorage2DImageCHROMIUM& cmd = *GetBufferAs<cmds::TexStorage2DImageCHROMIUM>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 524c5ef..c9cc3ac 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -340,9 +340,12 @@ OP(BeginRasterCHROMIUM) /* 581 */ \ OP(RasterCHROMIUM) /* 582 */ \ OP(EndRasterCHROMIUM) /* 583 */ \ - OP(TexStorage2DImageCHROMIUM) /* 584 */ \ - OP(SetColorSpaceMetadataCHROMIUM) /* 585 */ \ - OP(WindowRectanglesEXTImmediate) /* 586 */ + OP(CreateTransferCacheEntryCHROMIUM) /* 584 */ \ + OP(DeleteTransferCacheEntryCHROMIUM) /* 585 */ \ + OP(UnlockTransferCacheEntryCHROMIUM) /* 586 */ \ + OP(TexStorage2DImageCHROMIUM) /* 587 */ \ + OP(SetColorSpaceMetadataCHROMIUM) /* 588 */ \ + OP(WindowRectanglesEXTImmediate) /* 589 */ enum CommandId { kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/common/transfer_cache_entry_id.h b/gpu/command_buffer/common/transfer_cache_entry_id.h new file mode 100644 index 0000000..d1f17ad --- /dev/null +++ b/gpu/command_buffer/common/transfer_cache_entry_id.h
@@ -0,0 +1,14 @@ +// Copyright (c) 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 GPU_COMMAND_BUFFER_COMMON_TRANSFER_CACHE_ENTRY_ID_H_ +#define GPU_COMMAND_BUFFER_COMMON_TRANSFER_CACHE_ENTRY_ID_H_ + +#include "gpu/command_buffer/common/discardable_handle.h" + +namespace gpu { +using TransferCacheEntryId = ClientDiscardableHandle::Id; +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_COMMON_TRANSFER_CACHE_ENTRY_ID_H_
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 5c3ddb7..d5a0ee5d 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -126,6 +126,8 @@ "sequence_id.h", "service_discardable_manager.cc", "service_discardable_manager.h", + "service_transfer_cache.cc", + "service_transfer_cache.h", "service_utils.cc", "service_utils.h", "shader_manager.cc",
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 537205f..63bd30f 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc
@@ -22,6 +22,7 @@ #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/sampler_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" +#include "gpu/command_buffer/service/service_transfer_cache.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" @@ -115,7 +116,8 @@ passthrough_resources_(new PassthroughResources), progress_reporter_(progress_reporter), gpu_feature_info_(gpu_feature_info), - discardable_manager_(discardable_manager) { + discardable_manager_(discardable_manager), + transfer_cache_(new ServiceTransferCache) { DCHECK(discardable_manager); DCHECK(feature_info_); DCHECK(mailbox_manager_);
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index d467f8b..74127fc 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h
@@ -30,6 +30,7 @@ struct GpuPreferences; class TransferBufferManager; class ServiceDiscardableManager; +class ServiceTransferCache; namespace gles2 { @@ -203,6 +204,8 @@ return discardable_manager_; } + ServiceTransferCache* transfer_cache() const { return transfer_cache_.get(); } + uint32_t GetMemRepresented() const; // Loses all the context associated with this group. @@ -320,6 +323,14 @@ ServiceDiscardableManager* discardable_manager_; + // ServiceTransferCache uses Ids based on transfer buffer shm_id+offset, which + // are guaranteed to be unique within the scope of the TransferBufferManager + // which generates them. Because of this, |transfer_cache_| must have the same + // scope as |transfer_buffer_manager_|. In the future, we could add a channel + // Id to allow a single ServiceTransferCache to be shared among multiple + // ContextGroups. + std::unique_ptr<ServiceTransferCache> transfer_cache_; + DISALLOW_COPY_AND_ASSIGN(ContextGroup); };
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 381451c..ef324530 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -27,6 +27,7 @@ #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "cc/paint/paint_op_buffer.h" +#include "cc/paint/transfer_cache_entry.h" #include "gpu/command_buffer/common/debug_marker_manager.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -62,6 +63,7 @@ #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/sampler_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" +#include "gpu/command_buffer/service/service_transfer_cache.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/command_buffer/service/texture_manager.h" @@ -1971,6 +1973,9 @@ GLint pixel_config); void DoEndRasterCHROMIUM(); + void DoUnlockTransferCacheEntryCHROMIUM(GLuint64 id); + void DoDeleteTransferCacheEntryCHROMIUM(GLuint64 id); + void DoWindowRectanglesEXT(GLenum mode, GLsizei n, const volatile GLint* box); // Returns false if textures were replaced. @@ -20405,6 +20410,66 @@ state_.UpdateWindowRectangles(); } +error::Error GLES2DecoderImpl::HandleCreateTransferCacheEntryCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::CreateTransferCacheEntryCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::CreateTransferCacheEntryCHROMIUM*>( + cmd_data); + TransferCacheEntryId handle_id = + TransferCacheEntryId::FromUnsafeValue(c.handle_id()); + GLuint handle_shm_id = c.handle_shm_id; + GLuint handle_shm_offset = c.handle_shm_offset; + GLuint data_shm_id = c.data_shm_id; + GLuint data_shm_offset = c.data_shm_offset; + GLuint data_size = c.data_size; + + // Validate the type we are about to create. + cc::TransferCacheEntryType type; + if (!cc::ServiceTransferCacheEntry::SafeConvertToType(c.type, &type)) + return error::kInvalidArguments; + + uint8_t* data_memory = + GetSharedMemoryAs<uint8_t*>(data_shm_id, data_shm_offset, data_size); + if (!data_memory) + return error::kInvalidArguments; + + scoped_refptr<gpu::Buffer> handle_buffer = + GetSharedMemoryBuffer(handle_shm_id); + if (!DiscardableHandleBase::ValidateParameters(handle_buffer.get(), + handle_shm_offset)) + return error::kInvalidArguments; + ServiceDiscardableHandle handle(std::move(handle_buffer), handle_shm_offset, + handle_shm_id); + + if (!GetContextGroup()->transfer_cache()->CreateLockedEntry( + handle_id, handle, type, data_memory, data_size)) + return error::kInvalidArguments; + + return error::kNoError; +} + +void GLES2DecoderImpl::DoUnlockTransferCacheEntryCHROMIUM( + GLuint64 raw_handle_id) { + TransferCacheEntryId handle_id = + TransferCacheEntryId::FromUnsafeValue(raw_handle_id); + if (!GetContextGroup()->transfer_cache()->UnlockEntry(handle_id)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glUnlockTransferCacheEntryCHROMIUM", + "Attempt to unlock an invalid ID"); + } +} + +void GLES2DecoderImpl::DoDeleteTransferCacheEntryCHROMIUM( + GLuint64 raw_handle_id) { + TransferCacheEntryId handle_id = + TransferCacheEntryId::FromUnsafeValue(raw_handle_id); + if (!GetContextGroup()->transfer_cache()->DeleteEntry(handle_id)) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteTransferCacheEntryCHROMIUM", + "Attempt to delete an invalid ID"); + } +} + // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file // instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 6113fa0..a833ffb 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -5207,6 +5207,30 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleDeleteTransferCacheEntryCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::DeleteTransferCacheEntryCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::DeleteTransferCacheEntryCHROMIUM*>( + cmd_data); + GLuint64 handle_id = c.handle_id(); + DoDeleteTransferCacheEntryCHROMIUM(handle_id); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleUnlockTransferCacheEntryCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::UnlockTransferCacheEntryCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::UnlockTransferCacheEntryCHROMIUM*>( + cmd_data); + GLuint64 handle_id = c.handle_id(); + DoUnlockTransferCacheEntryCHROMIUM(handle_id); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleTexStorage2DImageCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index 0d4b68c..fe776e1f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -1012,6 +1012,8 @@ GLboolean use_distance_field_text, GLint pixel_config); error::Error DoEndRasterCHROMIUM(); +error::Error DoUnlockTransferCacheEntryCHROMIUM(GLuint64 id); +error::Error DoDeleteTransferCacheEntryCHROMIUM(GLuint64 id); error::Error DoWindowRectanglesEXT(GLenum mode, GLsizei n, const volatile GLint* box);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index b262e42..aea3e05b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -4620,6 +4620,18 @@ return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::DoUnlockTransferCacheEntryCHROMIUM( + GLuint64 handle_id) { + NOTIMPLEMENTED(); + return error::kNoError; +} + +error::Error GLES2DecoderPassthroughImpl::DoDeleteTransferCacheEntryCHROMIUM( + GLuint64 handle_id) { + NOTIMPLEMENTED(); + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::DoWindowRectanglesEXT( GLenum mode, GLsizei n,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc index 02f20d9b8..6e2b183 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -2802,5 +2802,13 @@ return error::kNoError; } +error::Error +GLES2DecoderPassthroughImpl::HandleCreateTransferCacheEntryCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + NOTIMPLEMENTED(); + return error::kNoError; +} + } // namespace gles2 } // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc index 2e9add33..8acaa4c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -4592,6 +4592,38 @@ return error::kNoError; } +error::Error +GLES2DecoderPassthroughImpl::HandleDeleteTransferCacheEntryCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::DeleteTransferCacheEntryCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::DeleteTransferCacheEntryCHROMIUM*>( + cmd_data); + GLuint64 handle_id = c.handle_id(); + error::Error error = DoDeleteTransferCacheEntryCHROMIUM(handle_id); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + +error::Error +GLES2DecoderPassthroughImpl::HandleUnlockTransferCacheEntryCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::UnlockTransferCacheEntryCHROMIUM& c = + *static_cast< + const volatile gles2::cmds::UnlockTransferCacheEntryCHROMIUM*>( + cmd_data); + GLuint64 handle_id = c.handle_id(); + error::Error error = DoUnlockTransferCacheEntryCHROMIUM(handle_id); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + error::Error GLES2DecoderPassthroughImpl::HandleTexStorage2DImageCHROMIUM( uint32_t immediate_data_size, const volatile void* cmd_data) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h index 671309d..7ab35ba 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h
@@ -42,4 +42,22 @@ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } + +TEST_P(GLES2DecoderTest4, DeleteTransferCacheEntryCHROMIUMValidArgs) { + EXPECT_CALL(*gl_, DeleteTransferCacheEntryCHROMIUM(1)); + SpecializedSetup<cmds::DeleteTransferCacheEntryCHROMIUM, 0>(true); + cmds::DeleteTransferCacheEntryCHROMIUM cmd; + cmd.Init(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest4, UnlockTransferCacheEntryCHROMIUMValidArgs) { + EXPECT_CALL(*gl_, UnlockTransferCacheEntryCHROMIUM(1)); + SpecializedSetup<cmds::UnlockTransferCacheEntryCHROMIUM, 0>(true); + cmds::UnlockTransferCacheEntryCHROMIUM cmd; + cmd.Init(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_4_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/service_transfer_cache.cc b/gpu/command_buffer/service/service_transfer_cache.cc new file mode 100644 index 0000000..404a783 --- /dev/null +++ b/gpu/command_buffer/service/service_transfer_cache.cc
@@ -0,0 +1,107 @@ +// Copyright (c) 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 "gpu/command_buffer/service/service_transfer_cache.h" + +#include "base/sys_info.h" +#include "cc/paint/raw_memory_transfer_cache_entry.h" + +namespace gpu { +namespace { +size_t CacheSizeLimit() { + if (base::SysInfo::IsLowEndDevice()) { + return 4 * 1024 * 1024; + } else { + return 128 * 1024 * 1024; + } +} + +} // namespace + +ServiceTransferCache::CacheEntryInternal::CacheEntryInternal( + ServiceDiscardableHandle handle, + std::unique_ptr<cc::ServiceTransferCacheEntry> entry) + : handle(handle), entry(std::move(entry)) {} + +ServiceTransferCache::CacheEntryInternal::~CacheEntryInternal() = default; + +ServiceTransferCache::CacheEntryInternal::CacheEntryInternal( + CacheEntryInternal&& other) = default; + +ServiceTransferCache::CacheEntryInternal& +ServiceTransferCache::CacheEntryInternal::operator=( + CacheEntryInternal&& other) = default; + +ServiceTransferCache::ServiceTransferCache() + : entries_(EntryCache::NO_AUTO_EVICT), + cache_size_limit_(CacheSizeLimit()) {} + +ServiceTransferCache::~ServiceTransferCache() = default; + +bool ServiceTransferCache::CreateLockedEntry(TransferCacheEntryId id, + ServiceDiscardableHandle handle, + cc::TransferCacheEntryType type, + uint8_t* data_memory, + size_t data_size) { + auto found = entries_.Peek(id); + if (found != entries_.end()) { + return false; + } + + std::unique_ptr<cc::ServiceTransferCacheEntry> entry = + cc::ServiceTransferCacheEntry::Create(type); + if (!entry) + return false; + + entry->Deserialize(data_size, data_memory); + total_size_ += entry->Size(); + entries_.Put(id, CacheEntryInternal(handle, std::move(entry))); + EnforceLimits(); + return true; +} + +bool ServiceTransferCache::UnlockEntry(TransferCacheEntryId id) { + auto found = entries_.Peek(id); + if (found == entries_.end()) + return false; + + found->second.handle.Unlock(); + return true; +} + +bool ServiceTransferCache::DeleteEntry(TransferCacheEntryId id) { + auto found = entries_.Peek(id); + if (found == entries_.end()) + return false; + + found->second.handle.ForceDelete(); + total_size_ -= found->second.entry->Size(); + entries_.Erase(found); + return true; +} + +cc::ServiceTransferCacheEntry* ServiceTransferCache::GetEntry( + TransferCacheEntryId id) { + auto found = entries_.Get(id); + if (found == entries_.end()) + return nullptr; + return found->second.entry.get(); +} + +void ServiceTransferCache::EnforceLimits() { + for (auto it = entries_.rbegin(); it != entries_.rend();) { + if (total_size_ <= cache_size_limit_) { + return; + } + if (!it->second.handle.Delete()) { + ++it; + continue; + } + + total_size_ -= it->second.entry->Size(); + it = entries_.Erase(it); + } +} + +} // namespace gpu
diff --git a/gpu/command_buffer/service/service_transfer_cache.h b/gpu/command_buffer/service/service_transfer_cache.h new file mode 100644 index 0000000..00a1f92 --- /dev/null +++ b/gpu/command_buffer/service/service_transfer_cache.h
@@ -0,0 +1,74 @@ +// Copyright (c) 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 GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_ +#define GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_ + +#include <vector> + +#include "base/containers/mru_cache.h" +#include "cc/paint/transfer_cache_entry.h" +#include "gpu/command_buffer/common/discardable_handle.h" +#include "gpu/command_buffer/common/transfer_cache_entry_id.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/gpu_export.h" + +namespace gpu { + +// ServiceTransferCache is a GPU process interface for retreiving cached entries +// from the transfer cache. These entries are populated by client calls to the +// ClientTransferCache. +// +// In addition to access, the ServiceTransferCache is also responsible for +// unlocking and deleting entries when no longer needed, as well as enforcing +// cache limits. If the cache exceeds its specified limits, unlocked transfer +// cache entries may be deleted. +class GPU_EXPORT ServiceTransferCache { + public: + ServiceTransferCache(); + ~ServiceTransferCache(); + + bool CreateLockedEntry(TransferCacheEntryId id, + ServiceDiscardableHandle handle, + cc::TransferCacheEntryType type, + uint8_t* data_memory, + size_t data_size); + bool UnlockEntry(TransferCacheEntryId id); + bool DeleteEntry(TransferCacheEntryId id); + cc::ServiceTransferCacheEntry* GetEntry(TransferCacheEntryId id); + + // Test-only functions: + void SetCacheSizeLimitForTesting(size_t cache_size_limit) { + cache_size_limit_ = cache_size_limit; + EnforceLimits(); + } + + private: + void EnforceLimits(); + + struct CacheEntryInternal { + CacheEntryInternal(ServiceDiscardableHandle handle, + std::unique_ptr<cc::ServiceTransferCacheEntry> entry); + CacheEntryInternal(CacheEntryInternal&& other); + CacheEntryInternal& operator=(CacheEntryInternal&& other); + ~CacheEntryInternal(); + ServiceDiscardableHandle handle; + std::unique_ptr<cc::ServiceTransferCacheEntry> entry; + }; + using EntryCache = base::MRUCache<TransferCacheEntryId, CacheEntryInternal>; + EntryCache entries_; + + // Total size of all |entries_|. The same as summing + // GpuDiscardableEntry::size for each entry. + size_t total_size_ = 0; + + // The limit above which the cache will start evicting resources. + size_t cache_size_limit_ = 0; + + DISALLOW_COPY_AND_ASSIGN(ServiceTransferCache); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 5473aa6..4835014 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -77,8 +77,13 @@ { "id": 20, "description": "Disable EXT_draw_buffers on GeForce GT 650M on Mac OS X due to driver bugs", + "cr_bugs": [180397, 779991], "os": { - "type": "macosx" + "type": "macosx", + "version": { + "op": "<", + "value": "10.12" + } }, "vendor_id": "0x10de", "device_id": ["0x0fd5"],
diff --git a/gpu/ipc/gl_in_process_context.cc b/gpu/ipc/gl_in_process_context.cc index 39b4faa4..c162b3c 100644 --- a/gpu/ipc/gl_in_process_context.cc +++ b/gpu/ipc/gl_in_process_context.cc
@@ -74,6 +74,7 @@ const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& callback) override; void SetLock(base::Lock* lock) override; + gpu::gles2::ContextGroup* ContextGroupForTesting() const override; private: void OnSignalSyncPoint(const base::Closure& callback); @@ -133,6 +134,11 @@ NOTREACHED(); } +gpu::gles2::ContextGroup* GLInProcessContextImpl::ContextGroupForTesting() + const { + return command_buffer_->ContextGroupForTesting(); +} + gpu::ContextResult GLInProcessContextImpl::Initialize( scoped_refptr<gpu::InProcessCommandBuffer::Service> service, scoped_refptr<gl::GLSurface> surface,
diff --git a/gpu/ipc/gl_in_process_context.h b/gpu/ipc/gl_in_process_context.h index 8de4def..7a30b85a 100644 --- a/gpu/ipc/gl_in_process_context.h +++ b/gpu/ipc/gl_in_process_context.h
@@ -71,6 +71,9 @@ virtual void SetUpdateVSyncParametersCallback( const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& callback) = 0; + + // Test only functions. + virtual gpu::gles2::ContextGroup* ContextGroupForTesting() const = 0; }; } // namespace gpu
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h index 166e4804e..58c4738 100644 --- a/gpu/ipc/in_process_command_buffer.h +++ b/gpu/ipc/in_process_command_buffer.h
@@ -32,6 +32,7 @@ #include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" +#include "gpu/command_buffer/service/service_transfer_cache.h" #include "gpu/config/gpu_feature_info.h" #include "gpu/gpu_export.h" #include "gpu/ipc/service/image_transport_surface_delegate.h" @@ -195,6 +196,10 @@ static void InitializeDefaultServiceForTesting( const GpuFeatureInfo& gpu_feature_info); + gpu::gles2::ContextGroup* ContextGroupForTesting() const { + return context_group_.get(); + } + // The serializer interface to the GPU service (i.e. thread). class Service { public: @@ -229,6 +234,7 @@ ServiceDiscardableManager* discardable_manager() { return &discardable_manager_; } + ServiceTransferCache* transfer_cache() { return &transfer_cache_; } gles2::ShaderTranslatorCache* shader_translator_cache() { return &shader_translator_cache_; } @@ -248,6 +254,7 @@ GpuProcessActivityFlags activity_flags_; gles2::ImageManager image_manager_; ServiceDiscardableManager discardable_manager_; + ServiceTransferCache transfer_cache_; gles2::ShaderTranslatorCache shader_translator_cache_; gles2::FramebufferCompletenessCache framebuffer_completeness_cache_; };
diff --git a/ios/build/bots/chromium.mac/ios-simulator-eg.json b/ios/build/bots/chromium.mac/ios-simulator-eg.json deleted file mode 100644 index 077ef21e..0000000 --- a/ios/build/bots/chromium.mac/ios-simulator-eg.json +++ /dev/null
@@ -1,176 +0,0 @@ -{ - "comments": [ - "EarlGrey Tests for 64-bit iOS 11.0 simulators." - ], - "xcode version": "9.0", - "gn_args": [ - "goma_dir=\"$(goma_dir)\"", - "is_component_build=false", - "is_debug=true", - "target_cpu=\"x64\"", - "target_os=\"ios\"", - "use_goma=true" - ], - "configuration": "Debug", - "sdk": "iphonesimulator11.0", - "tests": [ - { - "app": "ios_chrome_integration_egtests", - "test args": [ - "--enable-features=CredentialManager" - ], - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_payments_egtests", - "test args": [ - "--enable-features=WebPayments" - ], - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_reading_list_egtests", - "test args": [ - "--enable-reading-list" - ], - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_settings_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_smoke_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_ui_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_bookmarks_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_web_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_showcase_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_web_shell_egtests", - "device type": "iPhone 6s", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_integration_egtests", - "test args": [ - "--enable-features=CredentialManager" - ], - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_payments_egtests", - "test args": [ - "--enable-features=WebPayments" - ], - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_reading_list_egtests", - "test args": [ - "--enable-reading-list" - ], - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_settings_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_smoke_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_ui_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_bookmarks_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_chrome_web_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_showcase_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - }, - { - "app": "ios_web_shell_egtests", - "device type": "iPad Air 2", - "os": "11.0", - "xcode version": "9.0", - "xctest": true - } - ] -}
diff --git a/ios/chrome/test/app/sync_test_util.mm b/ios/chrome/test/app/sync_test_util.mm index bf9a2b2..69f2e21 100644 --- a/ios/chrome/test/app/sync_test_util.mm +++ b/ios/chrome/test/app/sync_test_util.mm
@@ -178,7 +178,7 @@ std::unique_ptr<syncer::LoopbackServerEntity> entity = syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics( - guid, entity_specifics); + guid, entity_specifics, 12345, 12345); gSyncFakeServer->InjectEntity(std::move(entity)); } @@ -268,7 +268,7 @@ std::unique_ptr<syncer::LoopbackServerEntity> entity = syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics( - url, entitySpecifics); + url, entitySpecifics, 12345, 12345); gSyncFakeServer->InjectEntity(std::move(entity)); }
diff --git a/media/gpu/android/android_video_encode_accelerator.cc b/media/gpu/android/android_video_encode_accelerator.cc index a334169..684ffea 100644 --- a/media/gpu/android/android_video_encode_accelerator.cc +++ b/media/gpu/android/android_video_encode_accelerator.cc
@@ -356,16 +356,30 @@ frame->coded_size().height()); RETURN_ON_FAILURE(converted, "Failed to I420ToNV12!", kPlatformFailureError); - input_timestamp_ += base::TimeDelta::FromMicroseconds( + // MediaCodec encoder assumes the presentation timestamps to be monotonically + // increasing at initialized framerate. But in Chromium, the video capture + // may be paused for a while or drop some frames, so the timestamp in input + // frames won't be continious. Here we cache the timestamps of input frames, + // mapping to the generated |presentation_timestamp_|, and will read them out + // after encoding. Then encoder can work happily always and we can preserve + // the timestamps in captured frames for other purpose. + presentation_timestamp_ += base::TimeDelta::FromMicroseconds( base::Time::kMicrosecondsPerSecond / INITIAL_FRAMERATE); + DCHECK(frame_timestamp_map_.find(presentation_timestamp_) == + frame_timestamp_map_.end()); + frame_timestamp_map_[presentation_timestamp_] = frame->timestamp(); + status = media_codec_->QueueInputBuffer(input_buf_index, nullptr, queued_size, - input_timestamp_); + presentation_timestamp_); UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime", base::Time::Now() - std::get<2>(input)); RETURN_ON_FAILURE(status == MEDIA_CODEC_OK, "Failed to QueueInputBuffer: " << status, kPlatformFailureError); ++num_buffers_at_codec_; + DCHECK(static_cast<int32_t>(frame_timestamp_map_.size()) == + num_buffers_at_codec_); + pending_frames_.pop(); } @@ -380,9 +394,10 @@ size_t size = 0; bool key_frame = false; - MediaCodecStatus status = - media_codec_->DequeueOutputBuffer(NoWaitTimeOut(), &buf_index, &offset, - &size, nullptr, nullptr, &key_frame); + base::TimeDelta presentaion_timestamp; + MediaCodecStatus status = media_codec_->DequeueOutputBuffer( + NoWaitTimeOut(), &buf_index, &offset, &size, &presentaion_timestamp, + nullptr, &key_frame); switch (status) { case MEDIA_CODEC_TRY_AGAIN_LATER: return; @@ -407,6 +422,11 @@ break; } + const auto it = frame_timestamp_map_.find(presentaion_timestamp); + DCHECK(it != frame_timestamp_map_.end()); + const base::TimeDelta frame_timestamp = it->second; + frame_timestamp_map_.erase(it); + BitstreamBuffer bitstream_buffer = available_bitstream_buffers_.back(); available_bitstream_buffers_.pop_back(); std::unique_ptr<SharedMemoryRegion> shm( @@ -427,7 +447,7 @@ FROM_HERE, base::Bind(&VideoEncodeAccelerator::Client::BitstreamBufferReady, client_ptr_factory_->GetWeakPtr(), bitstream_buffer.id(), size, - key_frame, base::TimeDelta())); + key_frame, frame_timestamp)); } } // namespace media
diff --git a/media/gpu/android/android_video_encode_accelerator.h b/media/gpu/android/android_video_encode_accelerator.h index b9624217..91ad14b 100644 --- a/media/gpu/android/android_video_encode_accelerator.h +++ b/media/gpu/android/android_video_encode_accelerator.h
@@ -9,6 +9,7 @@ #include <stdint.h> #include <list> +#include <map> #include <memory> #include <tuple> #include <vector> @@ -96,7 +97,11 @@ int32_t num_buffers_at_codec_; // A monotonically-growing value. - base::TimeDelta input_timestamp_; + base::TimeDelta presentation_timestamp_; + + std::map<base::TimeDelta /* presentation_timestamp */, + base::TimeDelta /* frame_timestamp */> + frame_timestamp_map_; // Resolution of input stream. Set once in initialization and not allowed to // change after.
diff --git a/net/cert/internal/ocsp.cc b/net/cert/internal/ocsp.cc index 606cb35b..49c34ddd 100644 --- a/net/cert/internal/ocsp.cc +++ b/net/cert/internal/ocsp.cc
@@ -934,7 +934,7 @@ // the OCSPRequest} GURL CreateOCSPGetURL(const ParsedCertificate* cert, const ParsedCertificate* issuer, - const GURL& ocsp_responder_url) { + base::StringPiece ocsp_responder_url) { std::vector<uint8_t> ocsp_request_der; if (!CreateOCSPRequest(cert, issuer, &ocsp_request_der)) { // Unexpected (means BoringSSL failed an operation). @@ -956,24 +956,9 @@ base::ReplaceSubstringsAfterOffset(&b64_encoded, 0, "/", "%2F"); base::ReplaceSubstringsAfterOffset(&b64_encoded, 0, "=", "%3D"); - // RFC 2560 and RFC 5019 are vague on what is intended for URL concatenation. - // - // * If the path doesn't end in a slash, is one implicitly added? - // * Is a straight up string concatenation expected, or only a concatenation - // to the path? - // - // This code contenates the data to the path portion of the URL, and leaves - // the other URL components unmodified. - // - // TODO(eroman): Confirm whether OCSP responders use query parameters. - std::string path = ocsp_responder_url.path(); - if (!base::StringPiece(path).ends_with("/")) - path += "/"; - path += b64_encoded; - - GURL::Replacements replacements; - replacements.SetPath(path.data(), url::Component(0, path.size())); - return ocsp_responder_url.ReplaceComponents(replacements); + // No attempt is made to collapse double slashes for URLs that end in slash, + // since the spec doesn't do that. + return GURL(std::string(ocsp_responder_url) + "/" + b64_encoded); } } // namespace net
diff --git a/net/cert/internal/ocsp.h b/net/cert/internal/ocsp.h index e4c7182..ffba90e5 100644 --- a/net/cert/internal/ocsp.h +++ b/net/cert/internal/ocsp.h
@@ -314,7 +314,7 @@ // Creates a URL to issue a GET request for OCSP information for |cert|. NET_EXPORT GURL CreateOCSPGetURL(const ParsedCertificate* cert, const ParsedCertificate* issuer, - const GURL& ocsp_responder_url); + base::StringPiece ocsp_responder_url); } // namespace net
diff --git a/net/cert/internal/ocsp_unittest.cc b/net/cert/internal/ocsp_unittest.cc index dff4ea1..436dd22 100644 --- a/net/cert/internal/ocsp_unittest.cc +++ b/net/cert/internal/ocsp_unittest.cc
@@ -297,23 +297,15 @@ #endif } -struct GetURLTestParams { - const char* responder_url; - int index_start_data; - int index_end_data; +base::StringPiece kGetURLTestParams[] = { + "http://www.example.com/", "http://www.example.com/path/", + "http://www.example.com/path", + "http://www.example.com/path?query" + "http://user:pass@www.example.com/path?query", }; -const GetURLTestParams kGetURLTestParams[] = { - {"http://www.example.com/", 23, -1}, - {"http://www.example.com/path/", 28, -1}, - {"http://www.example.com/path", 28, -1}, - // The data will be appended to the path (before the ?query). - {"http://www.example.com/path?query", 28, -7}, - {"http://user:pass@www.example.com/path?query", 38, -7}, -}; - -class CreateOCSPGetURLTest : public ::testing::TestWithParam<GetURLTestParams> { -}; +class CreateOCSPGetURLTest + : public ::testing::TestWithParam<base::StringPiece> {}; INSTANTIATE_TEST_CASE_P(, CreateOCSPGetURLTest, @@ -340,20 +332,13 @@ scoped_refptr<ParsedCertificate> issuer = ParseCertificate(ca_data); ASSERT_TRUE(issuer); - // Try using a URL that doesn't end with a slash. - GURL url = CreateOCSPGetURL(cert.get(), issuer.get(), - GURL(GetParam().responder_url)); + GURL url = CreateOCSPGetURL(cert.get(), issuer.get(), GetParam()); // Try to extract the encoded data and compare against |request_data|. // // A known answer output test would be better as this just reverses the logic // from the implementaiton file. - int begin_index = GetParam().index_start_data; - int end_index = GetParam().index_end_data; - if (end_index < 0) - end_index += url.spec().size(); - - std::string b64 = url.spec().substr(begin_index, end_index - begin_index + 1); + std::string b64 = url.spec().substr(GetParam().size() + 1); // Hex un-escape the data. base::ReplaceSubstringsAfterOffset(&b64, 0, "%2B", "+");
diff --git a/net/cert/internal/revocation_checker.cc b/net/cert/internal/revocation_checker.cc index 83c4ebf..a8333e2 100644 --- a/net/cert/internal/revocation_checker.cc +++ b/net/cert/internal/revocation_checker.cc
@@ -76,9 +76,9 @@ for (const auto& ocsp_uri : cert->ocsp_uris()) { // Only consider http:// URLs (https:// could create a circular // dependency). - GURL responder_url(ocsp_uri); - if (!responder_url.is_valid() || - !responder_url.SchemeIs(url::kHttpScheme)) { + GURL parsed_ocsp_url(ocsp_uri); + if (!parsed_ocsp_url.is_valid() || + !parsed_ocsp_url.SchemeIs(url::kHttpScheme)) { continue; } @@ -94,9 +94,10 @@ // TODO(eroman): Duplication of work if there are multiple URLs to try. // TODO(eroman): Are there cases where we would need to POST instead? - GURL get_url = CreateOCSPGetURL(cert, issuer_cert, responder_url); + GURL get_url = CreateOCSPGetURL(cert, issuer_cert, ocsp_uri); if (!get_url.is_valid()) { - // A failure here is unexpected, but could happen from BoringSSL. + // A failure here could mean an unexpected failure from BoringSSL, or a + // problem concatenating the URL. continue; }
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn index 206197c..11cff3d 100644 --- a/services/device/BUILD.gn +++ b/services/device/BUILD.gn
@@ -33,6 +33,7 @@ "//device/sensors/public/interfaces", "//services/device/fingerprint", "//services/device/generic_sensor", + "//services/device/geolocation", "//services/device/power_monitor", "//services/device/public/cpp:device_features", "//services/device/public/interfaces", @@ -81,6 +82,7 @@ "generic_sensor/platform_sensor_fusion_unittest.cc", "generic_sensor/platform_sensor_provider_unittest_android.cc", "generic_sensor/relative_orientation_euler_angles_fusion_algorithm_using_accelerometer_unittest.cc", + "geolocation/public_ip_address_location_notifier_unittest.cc", "power_monitor/power_monitor_message_broadcaster_unittest.cc", "public/cpp/power_monitor/power_monitor_broadcast_source_unittest.cc", "vibration/vibration_manager_impl_unittest.cc", @@ -92,8 +94,13 @@ "//base", "//base/test:test_support", "//device/base/synchronization", + "//device/geolocation/public/cpp", + "//device/geolocation/public/interfaces", "//mojo/public/cpp/bindings", + "//net", + "//net:test_support", "//services/device/generic_sensor", + "//services/device/geolocation", "//services/device/power_monitor", "//services/device/public/cpp:device_features", "//services/device/public/cpp/power_monitor", @@ -206,6 +213,8 @@ "//base", "//base/test:test_support", "//mojo/public/cpp/bindings", + "//net", + "//net:test_support", "//services/device/public/interfaces:constants", "//services/service_manager/public/cpp", "//services/service_manager/public/cpp:service_test_support",
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn new file mode 100644 index 0000000..55b04e6 --- /dev/null +++ b/services/device/geolocation/BUILD.gn
@@ -0,0 +1,20 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/features.gni") + +source_set("geolocation") { + visibility = [ "//services/device:*" ] + + sources = [ + "public_ip_address_location_notifier.cc", + "public_ip_address_location_notifier.h", + ] + + deps = [ + "//base", + "//device/geolocation", + "//net", + ] +}
diff --git a/services/device/geolocation/DEPS b/services/device/geolocation/DEPS new file mode 100644 index 0000000..8fa9d48 --- /dev/null +++ b/services/device/geolocation/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+net", +]
diff --git a/services/device/geolocation/public_ip_address_location_notifier.cc b/services/device/geolocation/public_ip_address_location_notifier.cc new file mode 100644 index 0000000..cf18163 --- /dev/null +++ b/services/device/geolocation/public_ip_address_location_notifier.cc
@@ -0,0 +1,143 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/device/geolocation/public_ip_address_location_notifier.h" + +#include "device/geolocation/wifi_data.h" +#include "net/traffic_annotation/network_traffic_annotation.h" + +namespace device { + +namespace { +// Time to wait before issuing a network geolocation request in response to +// network change notification. Network changes tend to occur in clusters. +constexpr base::TimeDelta kNetworkChangeReactionDelay = + base::TimeDelta::FromMinutes(5); +} // namespace + +PublicIpAddressLocationNotifier::PublicIpAddressLocationNotifier( + GeolocationProvider::RequestContextProducer request_context_producer, + const std::string& api_key) + : network_changed_since_last_request_(true), + api_key_(api_key), + request_context_producer_(request_context_producer), + network_traffic_annotation_tag_(nullptr), + weak_ptr_factory_(this) { + // Subscribe to notifications of changes in network configuration. + net::NetworkChangeNotifier::AddNetworkChangeObserver(this); +} + +PublicIpAddressLocationNotifier::~PublicIpAddressLocationNotifier() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); +} + +void PublicIpAddressLocationNotifier::QueryNextPosition( + base::Time time_of_prev_position, + const net::PartialNetworkTrafficAnnotationTag& tag, + QueryNextPositionCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + network_traffic_annotation_tag_.reset( + new net::PartialNetworkTrafficAnnotationTag(tag)); + // If a network location request is in flight, wait. + if (network_location_request_) { + callbacks_.push_back(std::move(callback)); + return; + } + + // If a network change has occured since we last made a request, start a + // request and wait. + if (network_changed_since_last_request_) { + callbacks_.push_back(std::move(callback)); + MakeNetworkLocationRequest(); + return; + } + + if (latest_geoposition_.has_value() && + latest_geoposition_->timestamp > time_of_prev_position) { + std::move(callback).Run(*latest_geoposition_); + return; + } + + // The cached geoposition is not new enough for this client, and + // there hasn't been a recent network change, so add the client + // to the list of clients waiting for a network change. + callbacks_.push_back(std::move(callback)); +} + +void PublicIpAddressLocationNotifier::OnNetworkChanged( + net::NetworkChangeNotifier::ConnectionType type) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Post a cancelable task to react to this network change after a reasonable + // delay, so that we only react once if multiple network changes occur in a + // short span of time. + react_to_network_change_closure_.Reset( + base::Bind(&PublicIpAddressLocationNotifier::ReactToNetworkChange, + base::Unretained(this))); + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, react_to_network_change_closure_.callback(), + kNetworkChangeReactionDelay); +} + +void PublicIpAddressLocationNotifier::ReactToNetworkChange() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + network_changed_since_last_request_ = true; + + // Invalidate the cached recent position. + latest_geoposition_.reset(); + + // If any clients are waiting, start a request. + // (This will cancel any previous request, which is OK.) + if (!callbacks_.empty()) + MakeNetworkLocationRequest(); +} + +void PublicIpAddressLocationNotifier::MakeNetworkLocationRequest() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + network_changed_since_last_request_ = false; + // Obtain URL request context using provided producer callback, then continue + // request in MakeNetworkLocationRequestWithRequestContext. + request_context_producer_.Run(base::BindOnce( + &PublicIpAddressLocationNotifier::MakeNetworkLocationRequestWithContext, + weak_ptr_factory_.GetWeakPtr())); +} + +void PublicIpAddressLocationNotifier::MakeNetworkLocationRequestWithContext( + scoped_refptr<net::URLRequestContextGetter> context_getter) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!context_getter) + return; + + network_location_request_ = std::make_unique<NetworkLocationRequest>( + std::move(context_getter), api_key_, + base::BindRepeating( + &PublicIpAddressLocationNotifier::OnNetworkLocationResponse, + weak_ptr_factory_.GetWeakPtr())); + + DCHECK(network_traffic_annotation_tag_); + network_location_request_->MakeRequest(WifiData(), base::Time::Now(), + *network_traffic_annotation_tag_); +} + +void PublicIpAddressLocationNotifier::OnNetworkLocationResponse( + const mojom::Geoposition& position, + const bool server_error, + const WifiData& /* wifi_data */) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (server_error) { + network_changed_since_last_request_ = true; + DCHECK(!latest_geoposition_.has_value()); + } else { + latest_geoposition_ = base::make_optional(position); + } + // Notify all clients. + for (QueryNextPositionCallback& callback : callbacks_) + std::move(callback).Run(position); + callbacks_.clear(); + network_location_request_.reset(); +} + +} // namespace device
diff --git a/services/device/geolocation/public_ip_address_location_notifier.h b/services/device/geolocation/public_ip_address_location_notifier.h new file mode 100644 index 0000000..0f4e84b --- /dev/null +++ b/services/device/geolocation/public_ip_address_location_notifier.h
@@ -0,0 +1,123 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_LOCATION_NOTIFIER_H_ +#define SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_LOCATION_NOTIFIER_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/callback_list.h" +#include "base/cancelable_callback.h" +#include "base/macros.h" +#include "base/optional.h" +#include "base/time/time.h" +#include "device/geolocation/geolocation_provider.h" +#include "device/geolocation/network_location_request.h" +#include "device/geolocation/public/interfaces/geoposition.mojom.h" +#include "net/base/network_change_notifier.h" +#include "net/traffic_annotation/network_traffic_annotation.h" + +namespace device { + +class NetworkLocationRequest; +struct WifiData; + +// Provides subscribers with updates of the device's approximate geographic +// location inferred from its publicly-visible IP address. +// Sequencing: +// * Must be created, used, and destroyed on the same sequence. +class PublicIpAddressLocationNotifier + : public net::NetworkChangeNotifier::NetworkChangeObserver { + public: + // Creates a notifier that uses the specified Google |api_key| and a URL + // request context produced by |request_context_producer| for network location + // requests. + PublicIpAddressLocationNotifier( + GeolocationProvider::RequestContextProducer request_context_producer, + const std::string& api_key); + ~PublicIpAddressLocationNotifier() override; + + using QueryNextPositionCallback = + base::OnceCallback<void(const mojom::Geoposition&)>; + + // Requests a callback with the next Geoposition obtained later than + // |time_of_prev_position|. + // Specifically: + // * If a position has been obtained subsequent to |time_of_prev_position|, + // returns it. + // * Otherwise, returns an updated position once a network change has + // occurred. + // * Note that it is possible for |callback| to never be called if no network + // change ever occurs after |time_of_prev_position|. + void QueryNextPosition(base::Time time_of_prev_position, + const net::PartialNetworkTrafficAnnotationTag& tag, + QueryNextPositionCallback callback); + + private: + // Sequence checker for all methods. + SEQUENCE_CHECKER(sequence_checker_); + + // NetworkChangeNotifier::NetworkChangeObserver: + // Network change notifications tend to come in a cluster in a short time, so + // this just sets a task to run ReactToNetworkChange after a short time. + void OnNetworkChanged( + net::NetworkChangeNotifier::ConnectionType type) override; + + // Actually react to a network change, starting a network geolocation request + // if any clients are waiting. + void ReactToNetworkChange(); + + // Begins a network location request, by first obtaining a + // URLRequestContextGetter, then continuing in + // MakeNetworkLocationRequestWithContext. + void MakeNetworkLocationRequest(); + + // Creates network_location_request_ and starts the network request, which + // will invoke OnNetworkLocationResponse when done. + void MakeNetworkLocationRequestWithContext( + scoped_refptr<net::URLRequestContextGetter> context_getter); + + // Completion callback for network_location_request_. + void OnNetworkLocationResponse(const mojom::Geoposition& position, + bool server_error, + const WifiData& wifi_data); + + // Cancelable closure to absorb overlapping delayed calls to + // ReactToNetworkChange. + base::CancelableClosure react_to_network_change_closure_; + + // Whether we have been notified of a network change since the last network + // location request was sent. + bool network_changed_since_last_request_; + + // The geoposition as of the latest network change, if it has been obtained. + base::Optional<mojom::Geoposition> latest_geoposition_; + + // Google API key for network geolocation requests. + const std::string api_key_; + + // Callback to produce a URL request context for network geolocation requests. + const GeolocationProvider::RequestContextProducer request_context_producer_; + + // Used to make calls to the Maps geolocate API. + // Empty unless a call is currently in progress. + std::unique_ptr<NetworkLocationRequest> network_location_request_; + + // Clients waiting for an updated geoposition. + std::vector<QueryNextPositionCallback> callbacks_; + + // The most recent PartialNetworkTrafficAnnotationTag provided by a client. + std::unique_ptr<const net::PartialNetworkTrafficAnnotationTag> + network_traffic_annotation_tag_; + + // Weak references to |this| for posted tasks. + base::WeakPtrFactory<PublicIpAddressLocationNotifier> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PublicIpAddressLocationNotifier); +}; + +} // namespace device + +#endif // SERVICES_DEVICE_GEOLOCATION_PUBLIC_IP_ADDRESS_LOCATION_NOTIFIER_H_
diff --git a/services/device/geolocation/public_ip_address_location_notifier_unittest.cc b/services/device/geolocation/public_ip_address_location_notifier_unittest.cc new file mode 100644 index 0000000..90a0dda --- /dev/null +++ b/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
@@ -0,0 +1,312 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/device/geolocation/public_ip_address_location_notifier.h" + +#include "base/bind.h" +#include "base/strings/stringprintf.h" +#include "base/test/test_mock_time_task_runner.h" +#include "device/geolocation/public/cpp/geoposition.h" +#include "device/geolocation/public/interfaces/geoposition.mojom.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +// Simple request context producer that immediately produces a +// TestURLRequestContextGetter. +void TestRequestContextProducer( + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, + base::OnceCallback<void(scoped_refptr<net::URLRequestContextGetter>)> + response_callback) { + std::move(response_callback) + .Run(base::MakeRefCounted<net::TestURLRequestContextGetter>( + network_task_runner)); +} + +class PublicIpAddressLocationNotifierTest : public testing::Test { + protected: + // Helps test a single call to + // PublicIpAddressLocationNotifier::QueryNextPositionAfterTimestamp. + class TestPositionQuery { + public: + // Provides a callback suitable to pass to QueryNextPositionAfterTimestamp. + PublicIpAddressLocationNotifier::QueryNextPositionCallback MakeCallback() { + return base::BindOnce(&TestPositionQuery::OnQueryNextPositionResponse, + base::Unretained(this)); + } + + // Optional. Wait until the callback from MakeCallback() is called. + void Wait() { loop_.Run(); } + + const base::Optional<mojom::Geoposition>& position() const { + return position_; + } + + private: + void OnQueryNextPositionResponse(const mojom::Geoposition& position) { + position_ = position; + loop_.Quit(); + } + + base::RunLoop loop_; + base::Optional<mojom::Geoposition> position_; + }; + + PublicIpAddressLocationNotifierTest() + : mock_time_task_runner_( + base::MakeRefCounted<base::TestMockTimeTaskRunner>( + base::TestMockTimeTaskRunner::Type::kBoundToThread)), + mock_time_scoped_context_(mock_time_task_runner_.get()), + network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), + notifier_( + base::Bind(&TestRequestContextProducer, mock_time_task_runner_), + std::string() /* api_key */) {} + + // Returns the current TestURLFetcher (if any) and advances the test fetcher + // id for disambiguation from subsequent tests. + net::TestURLFetcher* GetTestUrlFetcher() { + net::TestURLFetcher* const fetcher = url_fetcher_factory_.GetFetcherByID( + NetworkLocationRequest::url_fetcher_id_for_tests); + if (fetcher) + ++NetworkLocationRequest::url_fetcher_id_for_tests; + return fetcher; + } + + // Gives a valid JSON reponse to the specified URLFetcher. + // For disambiguation purposes, the specified |latitude| is included in the + // response. + void RespondToFetchWithLatitude(net::TestURLFetcher* const fetcher, + const float latitude) { + // Issue a valid response including the specified latitude. + fetcher->set_url(fetcher->GetOriginalURL()); + fetcher->set_status(net::URLRequestStatus()); + fetcher->set_response_code(200); + const char kNetworkResponseFormatString[] = + R"({ + "accuracy": 100.0, + "location": { + "lat": %f, + "lng": 90.0 + } + })"; + fetcher->SetResponseString( + base::StringPrintf(kNetworkResponseFormatString, latitude)); + fetcher->delegate()->OnURLFetchComplete(fetcher); + } + + void RespondToFetchWithServerError(net::TestURLFetcher* const fetcher) { + fetcher->set_url(fetcher->GetOriginalURL()); + fetcher->set_status(net::URLRequestStatus()); + fetcher->set_response_code(500); + fetcher->delegate()->OnURLFetchComplete(fetcher); + } + + // Expects a non-empty and valid Geoposition, including the specified + // |latitude|. + void ExpectValidPosition(const base::Optional<mojom::Geoposition>& position, + const float latitude) { + ASSERT_TRUE(position); + EXPECT_TRUE(ValidateGeoposition(*position)); + EXPECT_FLOAT_EQ(position->latitude, latitude); + } + + void ExpectError(const base::Optional<mojom::Geoposition>& position) { + ASSERT_TRUE(position); + EXPECT_THAT(position->error_code, + mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE); + } + // Use a TaskRunner on which we can fast-forward time. + const scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner_; + const base::TestMockTimeTaskRunner::ScopedContext mock_time_scoped_context_; + + // notifier_ requires a NetworkChangeNotifier to exist. + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; + + // Intercept URL fetchers. + net::TestURLFetcherFactory url_fetcher_factory_; + + // The object under test. + PublicIpAddressLocationNotifier notifier_; +}; + +// Tests that a single initial query makes a URL fetch and returns a position. +TEST_F(PublicIpAddressLocationNotifierTest, SingleQueryReturns) { + // Make query. + TestPositionQuery query; + notifier_.QueryNextPosition(base::Time::Now(), + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query.MakeCallback()); + // Expect a URL fetch & send a valid response. + net::TestURLFetcher* const fetcher = GetTestUrlFetcher(); + EXPECT_THAT(fetcher, testing::NotNull()); + RespondToFetchWithLatitude(fetcher, 1.0f); + // Expect the query to return. + ExpectValidPosition(query.position(), 1.0f); +} + +// Tests that a second query asking for an older timestamp gets a cached result. +TEST_F(PublicIpAddressLocationNotifierTest, OlderQueryReturnsCached) { + const auto time = base::Time::Now(); + + // Initial query. + TestPositionQuery query_1; + notifier_.QueryNextPosition(time, PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_1.MakeCallback()); + net::TestURLFetcher* const fetcher = GetTestUrlFetcher(); + EXPECT_THAT(fetcher, testing::NotNull()); + RespondToFetchWithLatitude(fetcher, 1.0f); + ExpectValidPosition(query_1.position(), 1.0f); + + // Second query for an earlier time. + TestPositionQuery query_2; + notifier_.QueryNextPosition(time - base::TimeDelta::FromMinutes(5), + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_2.MakeCallback()); + // Expect a cached result, so no new network request. + EXPECT_THAT(GetTestUrlFetcher(), testing::IsNull()); + // Expect the same result as query_1. + ExpectValidPosition(query_2.position(), 1.0f); +} + +// Tests that a subsequent query seeking a newer geoposition does not return, +// until a network change occurs. +TEST_F(PublicIpAddressLocationNotifierTest, + SubsequentQueryWaitsForNetworkChange) { + // Initial query. + TestPositionQuery query_1; + notifier_.QueryNextPosition(base::Time::Now(), + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_1.MakeCallback()); + net::TestURLFetcher* const fetcher = GetTestUrlFetcher(); + EXPECT_THAT(fetcher, testing::NotNull()); + RespondToFetchWithLatitude(fetcher, 1.0f); + ExpectValidPosition(query_1.position(), 1.0f); + + // Second query seeking a position newer than the result of query_1. + TestPositionQuery query_2; + notifier_.QueryNextPosition(query_1.position()->timestamp, + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_2.MakeCallback()); + // Expect no network request or callback. + EXPECT_THAT(GetTestUrlFetcher(), testing::IsNull()); + EXPECT_FALSE(query_2.position().has_value()); + + // Fake a network change notification. + net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + // Wait for the notifier to complete its delayed reaction. + mock_time_task_runner_->FastForwardUntilNoTasksRemain(); + + // Now expect a network request and query_2 to return. + net::TestURLFetcher* const fetcher_2 = GetTestUrlFetcher(); + EXPECT_THAT(fetcher_2, testing::NotNull()); + RespondToFetchWithLatitude(fetcher_2, 2.0f); + ExpectValidPosition(query_2.position(), 2.0f); +} + +// Tests that multiple network changes in a short time result in only one +// network request. +TEST_F(PublicIpAddressLocationNotifierTest, + ConsecutiveNetworkChangesRequestsOnlyOnce) { + // Initial query. + TestPositionQuery query_1; + notifier_.QueryNextPosition(base::Time::Now(), + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_1.MakeCallback()); + net::TestURLFetcher* const fetcher = GetTestUrlFetcher(); + EXPECT_THAT(fetcher, testing::NotNull()); + RespondToFetchWithLatitude(fetcher, 1.0f); + ExpectValidPosition(query_1.position(), 1.0f); + + // Second query seeking a position newer than the result of query_1. + TestPositionQuery query_2; + notifier_.QueryNextPosition(query_1.position()->timestamp, + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_2.MakeCallback()); + // Expect no network request or callback since network has not changed. + EXPECT_THAT(GetTestUrlFetcher(), testing::IsNull()); + EXPECT_FALSE(query_2.position().has_value()); + + // Fake several consecutive network changes notification. + for (int i = 0; i < 10; ++i) { + net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + mock_time_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5)); + } + // Expect still no network request or callback. + EXPECT_THAT(GetTestUrlFetcher(), testing::IsNull()); + EXPECT_FALSE(query_2.position().has_value()); + + // Wait longer. + mock_time_task_runner_->FastForwardUntilNoTasksRemain(); + + // Now expect a network request & query_2 to return. + net::TestURLFetcher* const fetcher_2 = GetTestUrlFetcher(); + EXPECT_THAT(fetcher_2, testing::NotNull()); + RespondToFetchWithLatitude(fetcher_2, 2.0f); + ExpectValidPosition(query_2.position(), 2.0f); +} + +// Tests multiple waiting queries. +TEST_F(PublicIpAddressLocationNotifierTest, MutipleWaitingQueries) { + // Initial query. + TestPositionQuery query_1; + notifier_.QueryNextPosition(base::Time::Now(), + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_1.MakeCallback()); + net::TestURLFetcher* const fetcher = GetTestUrlFetcher(); + EXPECT_THAT(fetcher, testing::NotNull()); + RespondToFetchWithLatitude(fetcher, 1.0f); + ExpectValidPosition(query_1.position(), 1.0f); + + // Multiple queries seeking positions newer than the result of query_1. + TestPositionQuery query_2; + notifier_.QueryNextPosition(query_1.position()->timestamp, + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_2.MakeCallback()); + TestPositionQuery query_3; + notifier_.QueryNextPosition(query_1.position()->timestamp, + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query_3.MakeCallback()); + + // Expect no network requests or callback since network has not changed. + EXPECT_THAT(GetTestUrlFetcher(), testing::IsNull()); + EXPECT_FALSE(query_2.position().has_value()); + EXPECT_FALSE(query_3.position().has_value()); + + // Fake a network change notification. + net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + // Wait for the notifier to complete its delayed reaction. + mock_time_task_runner_->FastForwardUntilNoTasksRemain(); + + // Now expect a network request & fake a valid response. + net::TestURLFetcher* const fetcher_2 = GetTestUrlFetcher(); + EXPECT_THAT(fetcher_2, testing::NotNull()); + RespondToFetchWithLatitude(fetcher_2, 2.0f); + // Expect all queries to now return. + ExpectValidPosition(query_2.position(), 2.0f); + ExpectValidPosition(query_3.position(), 2.0f); +} + +// Tests that server error is propogated to the client. +TEST_F(PublicIpAddressLocationNotifierTest, ServerError) { + // Make query. + TestPositionQuery query; + notifier_.QueryNextPosition(base::Time::Now(), + PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, + query.MakeCallback()); + // Expect a URL fetch & send a valid response. + net::TestURLFetcher* const fetcher = GetTestUrlFetcher(); + EXPECT_THAT(fetcher, testing::NotNull()); + RespondToFetchWithServerError(fetcher); + // Expect the query to return. + ExpectError(query.position()); +} + +} // namespace device
diff --git a/services/service_manager/sandbox/mac/renderer_v2.sb b/services/service_manager/sandbox/mac/renderer_v2.sb index da0d278a..ed2bbbb 100644 --- a/services/service_manager/sandbox/mac/renderer_v2.sb +++ b/services/service_manager/sandbox/mac/renderer_v2.sb
@@ -142,6 +142,8 @@ (allow mach-lookup (global-name "com.apple.distributed_notifications@Uv3") (global-name "com.apple.fonts") + ; crbug.com/756145, crbug.com/786615 + (global-name "com.apple.FontObjectsServer") (global-name "com.apple.logd") (global-name "com.apple.lsd.mapdb") (global-name "com.apple.system.logger") @@ -154,10 +156,6 @@ (if (< os-version 1012) (allow mach-lookup (global-name "com.apple.FontServer"))) -; crbug.com/756145 -(if (= os-version 1011) - (allow mach-lookup (global-name "com.apple.FontObjectsServer"))) - ; sysctl (if (= os-version 1009) (allow sysctl-read)
diff --git a/services/viz/privileged/interfaces/compositing/display_private.mojom b/services/viz/privileged/interfaces/compositing/display_private.mojom index 3bd6bbc..75dbde6 100644 --- a/services/viz/privileged/interfaces/compositing/display_private.mojom +++ b/services/viz/privileged/interfaces/compositing/display_private.mojom
@@ -4,6 +4,7 @@ module viz.mojom; +import "mojo/common/time.mojom"; import "ui/gfx/mojo/color_space.mojom"; // See ui/compositor/compositor.h: ContextFactoryPrivate. @@ -14,4 +15,9 @@ SetDisplayColorSpace(gfx.mojom.ColorSpace blending_color_space, gfx.mojom.ColorSpace device_color_space); SetOutputIsSecure(bool secure); + + // Locks the BeginFrame vsync interval for this display to |interval| and + // ignores vsync interval information from other sources. This will do nothing + // if the display is using an external BeginFrame source. + SetAuthoritativeVSyncInterval(mojo.common.mojom.TimeDelta interval); };
diff --git a/testing/buildbot/chromium.gpu.json b/testing/buildbot/chromium.gpu.json index 663e54e..a01eb11 100644 --- a/testing/buildbot/chromium.gpu.json +++ b/testing/buildbot/chromium.gpu.json
@@ -1,6 +1,381 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "Android Release (Nexus 5X)": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "angle_unittests", + "use_xvfb": false + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "gl_unittests", + "use_xvfb": false + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "0", + "--expected-device-id", + "0" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--os-type", + "android", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "android", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=android-chromium", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "M", + "device_type": "bullhead", + "os": "Android" + } + ], + "shards": 6 + } + } + ] + }, "GPU Linux Builder": {}, "GPU Linux Builder (dbg)": {}, "GPU Mac Builder": {},
diff --git a/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter b/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter index d879992b..b9107278 100644 --- a/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.mash.browser_tests.filter
@@ -1,234 +1,27 @@ # These tests fail when running browser_tests --mash # http://crbug.com/678687 -# Uncategorized timeouts, crashes and failures. +# Unknown failure. -BrowserTabRestoreTest.* --GalleryBrowserTest.* --GalleryBrowserTestInGuestMode.* --GoodiesDisplayerBrowserTest.* --HostedAppNonClientFrameViewAshTest.* --IdentityGetProfileUserInfoFunctionTest.* --IdentityOldProfilesGetAccountsFunctionTest.* --ImageDecoderBrowserTest.* --ImageLoaderJsTest.* --ImageWriterPrivateApiTest.* --ImmersiveModeBrowserViewTest.* --ImmersiveModeControllerAshHostedAppBrowserTest.* --IncognitoProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.* --InfoBarsTest.* + +# Extensive use of ash::WindowState. +-AcceleratorCommandsBrowserTest.* -InitiallyMaximized/AcceleratorCommandsFullscreenBrowserTest.* -InitiallyMaximized/AcceleratorCommandsPlatformAppFullscreenBrowserTest.* -InitiallyRestored/AcceleratorCommandsFullscreenBrowserTest.* -InitiallyRestored/AcceleratorCommandsPlatformAppFullscreenBrowserTest.* --InProcessAccessibilityBrowserTest.* --InputMethodEngineBrowserTest/InputMethodEngineBrowserTest.* --InputMethodEngineComponentExtensionBrowserTest/InputMethodEngineBrowserTest.* --InputMethodEngineIncognitoBrowserTest/InputMethodEngineBrowserTest.* --InspectUITest.* --InstallableManagerBrowserTest.* --InstantThemeTest.* --InterstitialUITest.* --InvalidationsWebUITest.* --JavaScript/ExtensionBindingsApiTest.* --JavaScriptBindings/ExternallyConnectableMessagingTest.* --JavaScriptBindings/MessagingApiTest.* --KeyboardEndToEndTest.* --KeyboardOperations/FileManagerBrowserTest.* --KeyboardOverlayUIBrowserTest.* -# Works, but flaky timeouts. http://crbug.* --KioskAppManagerTest.* --KioskAppSettingsWebUITest.* --KioskCrashRestoreTest.* --KioskEnterpriseTest.* --KioskHiddenWebUITest.* --KioskTest.* --KioskUpdateTest.* --KioskVirtualKeyboardTest.* --LauncherPlatformAppBrowserTest.* --LazyBackgroundPageApiTest.* --LoadImageBrowserTest.* --LocalFileSystemExtensionApiTest.* --LocalNTPDoodleTest.* --LocalNTPOneGoogleBarSmokeTest.* --LocalNTPTest.* --LockScreenNoteTakingTest.* --LoginFeedbackTest.* --LoginPromptBrowserTest.* --LoginScreenDefaultPolicyInSessionBrowsertest.* --LoginScreenDefaultPolicyLoginScreenBrowsertest.* --LoginScreenLocalePolicyTest.* --LoginScreenPolicyTest.* --LoginUIKeyboardTest.* --LoginUIKeyboardTestWithUsersAndOwner.* --LoginUtilsTest.* --LoginWebDialogTest.* --LogWebUIUrlTest.* --MagnificationManagerTest.* --ManagedWithoutPermission/ManagedWithoutPermissionPlatformKeysTest.* --ManagedWithPermission/ManagedWithPermissionPlatformKeysTest.* --MaterialBookmarksCommandManagerTest.* --MaterialBookmarksDNDManagerTest.* --MaterialBookmarksFolderNodeTest.* --MaterialBookmarksPolicyTest.* --MaterialHistoryListTest.* --MaterialHistorySyncedTabsTest.* --MaterialHistoryToolbarTest.* --MaybeSetMetadata/SafeBrowsingServiceMetadataTest.* --MaybeSetMetadata/V4SafeBrowsingServiceMetadataTest.* --MdSettingsUITest.* --MediaEngagementAutoplayBrowserTest.* --MediaEngagementBrowserTest.* --MediaFileValidatorTest.* --MediaRouterElementsBrowserTest.* --MediaStreamDevicesControllerBrowserTestInstance/MediaStreamDevicesControllerBrowserTest.* --MediaStreamDevicesControllerTest.* --MergeSessionTest.* --MimeHandlerViewTests/MimeHandlerViewTest.* --Minimal/MemlogBrowserTest.* --Mojo/ECKEncryptedMediaTest.* --MSE_ClearKey/EncryptedMediaTest.* --MSE_ExternalClearKey_Mojo/EncryptedMediaTest.* --MSE_ExternalClearKey/EncryptedMediaTest.* --MultiAuthEnrollmentScreenTest.* --MultiProfileFileManagerBrowserTest.* --Native/ExtensionBindingsApiTest.* --NativeBindings/ExternallyConnectableMessagingTest.* --NativeBindings/MessagingApiTest.* --NativeWindowTrackerTest.* --NavigatingExtensionPopupBrowserTest.* --NavigationConsumingTest.* --NetInternalsTest.* --NetworkConfigViewTest.* --NetworkingConfigDelegateChromeosTest.* --NetworkingConfigTest.* --NetworkingPrivateApiTest.* --NetworkingPrivateChromeOSApiTest.* --NetworkPortalDetectorImplBrowserTest.* --NoSessionRestoreTest.* --NoStatePrefetchBrowserTest/NoStatePrefetchBrowserTest.* --NtpExtensionBubbleViewBrowserTest.* --NTPTilesTest.* --OAuth2Test.* --OnStartupSettingsBrowserTest.* --OpenAudioFiles/FileManagerBrowserTest.* --OpenFileDialog/FileManagerBrowserTest.* --OutOfProcessPPAPIPrivateTest.* --OutOfProcessPPAPITest.* --PageLoadMetricsBrowserTest.* --PatchTest.* --PaymentManifestParserTest.* --PaymentMethodViewControllerTest.* --PaymentRequestCanMakePaymentMetricsTest.* --PaymentRequestCanMakePaymentQueryTest.* --PaymentRequestContactInfoEditorTest.* --PaymentRequestCreditCardEditorTest.* --PaymentRequestDebitTest.* --PaymentRequestEmptyUpdateTest.* --PaymentRequestIframeTest.* --PaymentRequestJourneyLoggerNoSupportedPaymentMethodTest.* --PaymentRequestNoUpdateWithTest.* --PaymentRequestOrderSummaryViewControllerTest.* --PaymentRequestSettingsLinkTest.* --PaymentRequestShippingAddressEditorTest.* --PaymentSheetViewControllerContactDetailsTest.* --PaymentSheetViewControllerNoShippingTest.* --PDFExtensionClipboardTest.* --PDFExtensionLinkClickTest.* --PDFExtensionTest.* --PDFTestFiles/PDFExtensionTest.* --Pepper/ECKEncryptedMediaTest.* --PepperContentSettingsSpecialCasesTest.* --PlatformAppBrowserTest.* --PlatformAppNavigationRedirectorBrowserTest.* --PluginPowerSaverBrowserTest.* --PolicyDisplayRotationDefault/DisplayRotationBootTest.* --PolicyDisplayRotationDefault/DisplayRotationDefaultTest.* --PolicyPrefsTest.* --PolicyProvidedTrustRootsPublicSessionTest.* --PolicyTest.* --PolicyToolUITest.* --PolicyUITest.* --PPAPIBrokerInfoBarTest.* --PPAPIFileChooserTestWithSBService.* --PPAPINaClGLibcTest.* --PPAPINaClPNaClNonSfiTest.* --PredictorBrowserTest.* --PreferencesTest.* --PrefHashBrowserTestChangedAtomicInstance/PrefHashBrowserTestChangedAtomic.* --PrefHashBrowserTestClearedAtomicInstance/PrefHashBrowserTestClearedAtomic.* --PrefHashBrowserTestUnchangedCustomInstance/PrefHashBrowserTestUnchangedCustom.* --PrefHashBrowserTestUnchangedDefaultInstance/PrefHashBrowserTestUnchangedDefault.* --PrefsTabHelperBrowserTest.* --PreinstalledSigninExtensionsDeviceCloudPolicyBrowserTest.* --PrerenderBrowserTest.* --PrintBrowserTest.* --PrintPreviewBrowserTest.* --PrintPreviewDestinationSearchTest.* --PrintPreviewDialogControllerBrowserTest.* --PrintPreviewUIBrowserTest.* --ProcessesApiTest.* --ProcessManagementTest.* --ProcessManagerBrowserTest.* --ProcessMemoryMetricsEmitterTest.* --ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.* --ProfilingBrowserTest.* --Providers/FileManagerBrowserTest.* --ProvisionedEnrollmentScreenTest.* --ProxySettingsApiTest.* --PushMessagingBrowserTest.* --RequestFileSystemDialogTest.* --ResetFirstAfterBootTest.* --SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.* --SaveCardBubbleControllerImplTest.* --SessionRestoreTest.* --SessionRestoreTestChromeOS.* --SettingsA11yManagePasswords.* --SettingsAccessibilityTest.* --ShelfAppBrowserTest.* --ShelfAppBrowserTestNoDefaultBrowser.* --ShutdownPolicyInSessionTest.* --SigninExtensionsDeviceCloudPolicyBrowserTest.* --SigninProfileAppsPolicyPerChannelTest.* --SigninProfileAppsPolicyTest.* --SimpleWebViewDialogTest.* --SitePerProcess/TaskManagerOOPIFBrowserTest.* --SmartSessionRestoreTest.* --SortWindowsByZIndexBrowserTest.* --StartupMetricsTest.* --SupervisedUserCreationTest.* --SystemTrayTrayCastMediaRouterChromeOSTest.* --SystemUse24HourClockPolicyTest.* --TabCaptureApiPixelTest.* --TabManagerTest.* --TabRestoreTest.* --TaskManagerUtilityProcessBrowserTest.* --TrayAccessibilityLoginScreenTest.* --TrayAccessibilityTestInstance/TrayAccessibilityTest.* --UserAddingScreenTest.* --UserTypeInstantiation/AccessibilityManagerUserTypeTest.* --VirtualKeyboardAppWindowTest.* --VirtualKeyboardStateTest.* --VirtualKeyboardWebContentTest.* --VolumeControllerSoundsTest.* --WallpaperManagerPolicyTest.* --WebstoreInlineInstallerTest.* --WebViewScrollBubbling/WebViewGuestScrollTouchTest.* --WebViewTests/WebViewFocusTest.* --WebViewTests/WebViewSizeTest.* --WebViewTests/WebViewTest.* -# Fails (assertion in JS side of code). --WindowOpenApiTest.* --WizardControllerKioskFlowTest.* --WizardControllerTest.* --ZoomBubbleBrowserTest.* - -# Extensive use of ash::WindowState. --AcceleratorCommandsBrowserTest.* # ChromeVoxPanel directly calls into ash to set panel height. -AccessibilityFeatureaApiTestInstantiatePermission/AccessibilityFeaturesApiTest.* -AccessibilityManagerTest.* -ChromeOSInfoPrivateTest.* +-PolicyPrefsTest.* +-PolicyProvidedTrustRootsPublicSessionTest.* +-PolicyTest.* +-UserTypeInstantiation/AccessibilityManagerUserTypeTest.* +-VolumeControllerSoundsTest.* +-WizardControllerKioskFlowTest.* +-WizardControllerTest.* # Crashes in net::URLRequestContext::CreateRequest. -AffiliationCheck/EnterpriseDeviceAttributesTest.* @@ -237,6 +30,10 @@ -ExistingUserControllerActiveDirectoryTest.* -ExistingUserControllerPublicSessionTest.* -ExistingUserControllerUntrustedTest.* +-PreinstalledSigninExtensionsDeviceCloudPolicyBrowserTest.* +-SigninExtensionsDeviceCloudPolicyBrowserTest.* +-SigninProfileAppsPolicyPerChannelTest.* +-SigninProfileAppsPolicyTest.* # Uses ash::Shell::GetRootWindowForNewWindows to choose a display for the app list. # More generally, app list needs to move into ash. @@ -262,54 +59,65 @@ # profile_destroyer.cc(57) Check failed: hosts.empty() || profile->IsOffTheRecord() || profile->HasOffTheRecordProfile() || content::RenderProcessHost::run_renderer_in_process(). Profile still has 1 hosts -BluetoothPairingUITest.* -DemoAppLauncherTest.* +-LoginWebDialogTest.* # Direct access to ash window frames, tablet mode, overview mode, etc. -BrowserNonClientFrameViewAshBackButtonTest.* -BrowserNonClientFrameViewAshTest.* +-HostedAppNonClientFrameViewAshTest.* +-ImmersiveModeControllerAshHostedAppBrowserTest.* # Incorrect window bounds. Probably WindowSizerAsh problem. -BrowserTestTabbedOrApp/BrowserTestParam.* +-TabRestoreTest.* # Timeout waiting for notification. -CaptivePortalAuthenticationIgnoresProxy/NetworkPortalDetectorImplBrowserTestIgnoreProxy.* # ash::Shell access from ChromeViewsDelegate::CreateDefaultNonClientFrameView() -# from chromeos::CaptivePortalWindowProxy::Show(). +# e.g. from chromeos::CaptivePortalWindowProxy::Show(). -CaptivePortalWindowCtorDtorTest.* -CaptivePortalWindowTest.* +-SimpleWebViewDialogTest.* # Need pixel copy support. http://crbug.com/754864 -CastStreamingApiTestWithPixelOutput.* +-TabCaptureApiPixelTest.* # RefCounted check failed: CalledOnValidSequence() from SchedulerWorkerDelegate::OnMainExit -CheckSystemTokenAvailability/EnterprisePlatformKeysTest.* # aura::CrashInFlightChange::ChangeFailed() when searching PDF. -ChromeFindRequestManagerTest.* +-PDFExtensionTest.* # Need screenshot support. http://crbug.com/754899 -ChromeScreenshotGrabberBrowserTest.* # ChromeBrowserMainExtraPartsAsh: Check failed: views::MusClient::Exists(). -ChromeMainTest.* +-ProfilingBrowserTest.* # Null immersive_fullscreen_controller_. -ChromeNativeAppWindowViewsAuraAshBrowserTest.* +# Flaky. SessionRestoreStatsCollector::Observe failure. crbug.com/785298 # session_restore_stats_collector.cc(210) Check failed: 0u < loading_tab_count_ (0 vs. 0) -ContinueWhereILeftOffTest.* -DeviceIDTest.* +-SessionRestoreTest.* +-SessionRestoreTestChromeOS.* +-SAMLPolicyTest.TransferCookiesAffiliated +-SmartSessionRestoreTest.* # ash::Shell access in test for wallpaper images. -CustomizationWallpaperDownloaderBrowserTest.* +-WallpaperManagerPolicyTest.* # Flaky: private_api_file_system.cc(811) Check failed: external_backend->CanHandleType(file_system_url.type()). -DefaultTaskDialog/FileManagerBrowserTest.* -QuickView/FileManagerBrowserTest.* -# Need virtual keyboard support. --DefaultKeyboardExtensionBrowserTest.* - # ash::Shell access for LogoutConfirmationController -DeviceLocalAccountTest.* @@ -318,7 +126,11 @@ # WindowPortMus check failed in fullscreen test: # window_mus_type() == WindowMusType::TOP_LEVEL_IN_WM || window_mus_type() == WindowMusType::EMBED_IN_OWNER. +# http://crbug.com/786544 -ExtensionInstallUIBrowserTest.* +-ImmersiveModeBrowserViewTest.* +-WebstoreInlineInstallerTest.* +-ZoomBubbleBrowserTest.* # ozone_platform.cc(61) Check failed: instance_. OzonePlatform is not initialized -ExtensionWebstoreGetWebGLStatusTest.* @@ -332,13 +144,128 @@ # ash::Shell::display_manager() to update displays. -ForceMaximizeOnFirstRunTest.* -ForceMaximizePolicyFalseTest.* +-PolicyDisplayRotationDefault/DisplayRotationBootTest.* +-PolicyDisplayRotationDefault/DisplayRotationDefaultTest.* -# Flaky. SessionRestoreStatsCollector::Observe failure. crbug.com/785298 --SAMLPolicyTest.TransferCookiesAffiliated +# Failures JS-side. +-GalleryBrowserTest.* +-GalleryBrowserTestInGuestMode.* + +# IME accesses ash::Shell for root window. +-InputMethodEngineBrowserTest/InputMethodEngineBrowserTest.* +-InputMethodEngineComponentExtensionBrowserTest/InputMethodEngineBrowserTest.* +-InputMethodEngineIncognitoBrowserTest/InputMethodEngineBrowserTest.* + +# KeyboardOverlayUI uses ash::Shell. +-KeyboardOverlayUIBrowserTest.* + +# Kiosk mode has a variety of failures: +# termination_observer_->terminated() is false. +# Value of: login_display_host == NULL || login_display_host->GetNativeWindow()->layer()->GetTargetOpacity() == 0.0f +# Check failed: !browser_client || browser_client->IsShuttingDown() || did_respond() || ignore_all_did_respond_for_testing_do_not_use. app.window.create +# chromeos::KioskExternalUpdateNotification::CreateAndShowNotificationView() uses ash::Shell. +-KioskAppManagerTest.* +-KioskAppSettingsWebUITest.* +-KioskCrashRestoreTest.* +-KioskEnterpriseTest.* +-KioskHiddenWebUITest.* +-KioskTest.* +-KioskUpdateTest.* + +# Window state lookup failures for minimized, active, etc. +-LauncherPlatformAppBrowserTest.* + +# JS failure: hasAccessToCurrentWindow: FAIL (no message) +-LockScreenNoteTakingTest.* + +# desktop_window_tree_host_mus.cc(796) Check failed: !window->GetRootWindow() || this->window() == window->GetRootWindow(). +-LoginFeedbackTest.* + +# Missing magnification manager and ChromeVoxPanel crashes. +-LoginScreenDefaultPolicyInSessionBrowsertest.* +-LoginScreenDefaultPolicyLoginScreenBrowsertest.* + +# Test shutdown crashes. +-LoginScreenLocalePolicyTest.* +-LoginScreenPolicyTest.* + +# Crashes in pre-login phase, probably MagnificationManager not created. +-MagnificationManagerTest.* + +# OutputProtection problems: +# interface_endpoint_client.cc(32) Check failed: !is_valid. The callback passed to OutputProtection::QueryStatus() was never run. +# binder_registry.h(89) Failed to locate a binder for interface: display::mojom::OutputProtection +-Mojo/ECKEncryptedMediaTest.* +-OutOfProcessPPAPITest.* +-Pepper/ECKEncryptedMediaTest.* + +# ash::FocusRingController::SetVisible() from LoginDisplayHostWebUI. +-MultiAuthEnrollmentScreenTest.* +-ProvisionedEnrollmentScreenTest.* + +# VPN item not in system tray. +-NetworkingConfigDelegateChromeosTest.* + +# Timeout device_event_log_impl.cc(156) Network: network_portal_detector_impl.cc:486 Portal detection timeout: name= id= +-NetworkingConfigTest.* +-NetworkPortalDetectorImplBrowserTest.* + +# Crash in autofill::SaveCardBubbleViews::ShouldShowCloseButton(). +-SaveCardBubbleControllerImplTest.* + +# ash::Shell access in test. +-ShelfAppBrowserTest.* +-ShelfAppBrowserTestNoDefaultBrowser.* + +# ash::Shell access in test. +-ShutdownPolicyInSessionTest.* + +# Function under test uses ash::Shell for window list. +-SortWindowsByZIndexBrowserTest.* + +# Timeout. +-StartupMetricsTest.* + +# ash::Shell access in test for StatusAreaWidget. +-SupervisedUserCreationTest.* +# Crash. Database is locked. +-SyncAwareCounterTest.* + +# ash::Shell access in test. +-SystemTrayTrayCastMediaRouterChromeOSTest.* + +# ash::Shell access in test. +-SystemUse24HourClockPolicyTest.* # Flaky shutdown crashes in ~MusClient http://crbug.com/786234 and AtExit # crashes in ~WebContentsTaskProvider http://crbug.com/786230 -AppBackgroundPageApiTest.* -DefaultIsolation/TaskManagerOOPIFBrowserTest.* +-PrerenderBrowserTest.* +-SitePerProcess/TaskManagerOOPIFBrowserTest.* -TaskManagerBrowserTest.* -TaskManagerMemoryCoordinatorBrowserTest.* +-TaskManagerUtilityProcessBrowserTest.* + +# ash::Shell access in test. +-TrayAccessibilityLoginScreenTest.* +-TrayAccessibilityTestInstance/TrayAccessibilityTest.* + +# chromeos::UserAddingScreenImpl::Cancel() uses ash::Shell to enable system tray. +-UserAddingScreenTest.* + +# Virtual keyboard not supported. +-DefaultKeyboardExtensionBrowserTest.* +-KeyboardEndToEndTest.* +-KioskVirtualKeyboardTest.* +-VirtualKeyboardAppWindowTest.* +-VirtualKeyboardStateTest.* +-VirtualKeyboardWebContentTest.* + +# Also fails in --mus. http://crbug.com/755318. +-WebViewScrollBubbling/WebViewGuestScrollTouchTest.* + +# Also fails in --mus. http://crbug.com/755328 +-WebViewTests/WebViewFocusTest.* +-WebViewTests/WebViewSizeTest.* +-WebViewTests/WebViewTest.*
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 93741c5..dab495a 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -197,7 +197,7 @@ deps = [ "//v8:parser_fuzzer", ] - dict = "dicts/generated/v8_script_parser_fuzzer.dict" + dict = "dicts/generated/javascript.dict" seed_corpus = "//v8/test/mjsunit/regress/" libfuzzer_options = [ "only_ascii=1" ] } @@ -505,3 +505,17 @@ ] include_dirs = [ "$root_build_dir/$target_gen_dir" ] } + +fuzzer_test("v8_fully_instrumented_fuzzer") { + sources = [ + "v8_fuzzer.cc", + ] + deps = [ + "//base", + "//v8:v8", + "//v8:v8_libplatform", + ] + dict = "dicts/generated/javascript.dict" + seed_corpus = "//v8/test/mjsunit/" + libfuzzer_options = [ "only_ascii=1" ] +}
diff --git a/testing/libfuzzer/fuzzers/dicts/generated/v8_script_parser_fuzzer.dict b/testing/libfuzzer/fuzzers/dicts/generated/javascript.dict similarity index 100% rename from testing/libfuzzer/fuzzers/dicts/generated/v8_script_parser_fuzzer.dict rename to testing/libfuzzer/fuzzers/dicts/generated/javascript.dict
diff --git a/testing/libfuzzer/fuzzers/v8_fuzzer.cc b/testing/libfuzzer/fuzzers/v8_fuzzer.cc new file mode 100644 index 0000000..82995bbb --- /dev/null +++ b/testing/libfuzzer/fuzzers/v8_fuzzer.cc
@@ -0,0 +1,200 @@ +// 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 <chrono> +#include <functional> +#include <iostream> +#include <mutex> +#include <thread> + +#include "base/logging.h" +#include "v8/include/libplatform/libplatform.h" +#include "v8/include/v8.h" + +using v8::MaybeLocal; +using std::ref; +using std::chrono::time_point; +using std::chrono::steady_clock; +using std::chrono::seconds; +using std::chrono::duration_cast; + +static const seconds kSleepSeconds(1); + +// Because of the sleep we do, the actual max will be: +// kSleepSeconds + kMaxExecutionSeconds. +// TODO(metzman): Determine if having such a short timeout causes too much +// indeterminism. +static const seconds kMaxExecutionSeconds(15); + +// Inspired by/copied from d8 code, this allocator will return nullptr when +// an allocation request is made that puts currently_allocated_ over +// kAllocationLimit (1 GB). Should handle the current allocations done by V8. +class MockArrayBufferAllocator : public v8::ArrayBuffer::Allocator { + std::unique_ptr<Allocator> allocator_ = + std::unique_ptr<Allocator>(NewDefaultAllocator()); + + const size_t kAllocationLimit = 1000 * 1024 * 1024; + // TODO(metzman): Determine if this approach where we keep track of state + // between runs is a good idea. Maybe we should simply prevent allocations + // over a certain size regardless of previous allocations. + size_t currently_allocated_; + std::mutex mtx_; + + public: + MockArrayBufferAllocator() + : v8::ArrayBuffer::Allocator(), currently_allocated_(0) {} + void SetProtection(void* data, + size_t length, + Protection protection) override { + allocator_->SetProtection(data, length, protection); + } + + void* Allocate(size_t length) override { + void* data = AllocateUninitialized(length); + return data == nullptr ? data : memset(data, 0, length); + } + + void* AllocateUninitialized(size_t length) override { + mtx_.lock(); + if (length + currently_allocated_ > kAllocationLimit) { + mtx_.unlock(); + return nullptr; + } + currently_allocated_ += length; + mtx_.unlock(); + return malloc(length); + } + + void Free(void* ptr, size_t length) override { + mtx_.lock(); + currently_allocated_ -= length; + // We need to free before we unlock, otherwise currently_allocated_ will + // be innacurate. + free(ptr); + mtx_.unlock(); + } + + void Free(void* data, size_t length, AllocationMode mode) override { + switch (mode) { + case AllocationMode::kNormal: { + mtx_.lock(); + currently_allocated_ -= length; + Free(data, length); + mtx_.unlock(); + return; + } + case AllocationMode::kReservation: { + mtx_.lock(); + currently_allocated_ -= length; + allocator_->Free(data, length, mode); + mtx_.unlock(); + return; + } + default: + NOTREACHED(); + } + } + + void* Reserve(size_t length) override { + mtx_.lock(); + if (length + currently_allocated_ > kAllocationLimit) { + mtx_.unlock(); + return nullptr; + } + currently_allocated_ += length; + mtx_.unlock(); + return allocator_->Reserve(length); + } +}; + +void terminate_execution(v8::Isolate* isolate, + std::mutex& mtx, + bool& is_running, + time_point<steady_clock>& start_time) { + while (true) { + std::this_thread::sleep_for(kSleepSeconds); + mtx.lock(); + if (is_running) { + if (duration_cast<seconds>(steady_clock::now() - start_time) > + kMaxExecutionSeconds) { + isolate->TerminateExecution(); + is_running = false; + std::cout << "Terminated" << std::endl; + fflush(0); + } + } + mtx.unlock(); + } +} + +struct Environment { + Environment() { + v8::Platform* platform = v8::platform::CreateDefaultPlatform( + 0, v8::platform::IdleTaskSupport::kDisabled, + v8::platform::InProcessStackDumping::kDisabled, nullptr); + + v8::V8::InitializePlatform(platform); + v8::V8::Initialize(); + v8::Isolate::CreateParams create_params; + + create_params.array_buffer_allocator = &mock_arraybuffer_allocator; + isolate = v8::Isolate::New(create_params); + terminator_thread = std::thread(terminate_execution, isolate, ref(mtx), + ref(is_running), ref(start_time)); + } + MockArrayBufferAllocator mock_arraybuffer_allocator; + std::mutex mtx; + std::thread terminator_thread; + v8::Isolate* isolate; + time_point<steady_clock> start_time; + bool is_running; +}; + +extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { + v8::V8::InitializeICUDefaultLocation((*argv)[0]); + v8::V8::InitializeExternalStartupData((*argv)[0]); + v8::V8::SetFlagsFromCommandLine(argc, *argv, true); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 1) + return 0; + + static Environment* env = new Environment(); + + v8::Isolate::Scope isolate_scope(env->isolate); + v8::HandleScope handle_scope(env->isolate); + v8::Local<v8::Context> context = v8::Context::New(env->isolate); + v8::Context::Scope context_scope(context); + + std::string source_string = + std::string(reinterpret_cast<const char*>(data), size); + + MaybeLocal<v8::String> source_v8_string = v8::String::NewFromUtf8( + env->isolate, source_string.c_str(), v8::NewStringType::kNormal); + + if (source_v8_string.IsEmpty()) + return 0; + + v8::TryCatch try_catch(env->isolate); + MaybeLocal<v8::Script> script = + v8::Script::Compile(context, source_v8_string.ToLocalChecked()); + + if (script.IsEmpty()) + return 0; + + auto local_script = script.ToLocalChecked(); + env->mtx.lock(); + env->start_time = steady_clock::now(); + env->is_running = true; + env->mtx.unlock(); + + ALLOW_UNUSED_LOCAL(local_script->Run(context)); + + env->mtx.lock(); + env->is_running = false; + env->mtx.unlock(); + return 0; +}
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls index 1c97cd0a..06c6fbb 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls +++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -73,21 +73,7 @@ crbug.com/417782 paint/invalidation/svg/absolute-sized-document-no-scrollbars.svg [ Failure ] crbug.com/417782 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] crbug.com/417782 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-background-image-fixed-centered.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-background-image-generated.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-background-image-non-fixed.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-frameset.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-media-query.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-no-layout-change1.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-no-layout-change2.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-percent-html.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-percent-width-height.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-positioned-bottom.html [ Failure ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-positioned-percent-top.html [ Failure ] crbug.com/417782 paint/invalidation/window-resize/window-resize-vertical-writing-mode.html [ Crash ] -crbug.com/417782 paint/invalidation/window-resize/window-resize-viewport-percent.html [ Failure ] crbug.com/417782 plugins/webview-plugin-nested-iframe-scroll.html [ Failure ] crbug.com/417782 plugins/webview-plugin-scroll.html [ Failure ] crbug.com/417782 printing/quirks-percentage-height-body.html [ Failure ] @@ -99,10 +85,6 @@ crbug.com/417782 svg/custom/mask-with-default-value.svg [ Failure ] crbug.com/417782 [ Mac ] svg/custom/masking-clipping-hidpi.svg [ Failure ] crbug.com/417782 transforms/selection-bounds-in-transformed-view.html [ Failure ] -crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/browser-controls-background-iframe.html [ Failure ] -crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-scroller.html [ Failure ] -crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe.html [ Failure ] -crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/browser-controls-gradient-background.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-hidden.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-shown.html [ Failure ] crbug.com/417782 [ Linux ] virtual/android/fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/harness/results.html b/third_party/WebKit/LayoutTests/fast/harness/results.html index 92c6549..de7bc98 100644 --- a/third_party/WebKit/LayoutTests/fast/harness/results.html +++ b/third_party/WebKit/LayoutTests/fast/harness/results.html
@@ -317,7 +317,8 @@ </div> <div id="report_header" style="margin-top:8px"> - <span class="fix-width">Tests shown</span><span id="report_title" style="font-weight:bold"></span> + <span class="fix-width">Tests shown</span><span id="report_count"></span> + <span id="report_title" style="font-weight:bold"></span> in format: <select id="report_format" onchange="Query.generateReport()"> <option value="plain" selected>Plain text</option> @@ -825,6 +826,7 @@ }; window.setTimeout( _ => { traversal.traverse(filter, report.print); + document.querySelector("#report_count").innerText = traversal.html.length; this.completeReportPromise(traversal); this.currentRAF = window.requestAnimationFrame(callback); }, 0); @@ -1002,9 +1004,8 @@ showNextExpectation: function(backward) { let nextExpectation; - let openDetails = document.querySelector(".details.open"); - let openExpectation = openDetails && GUI.getExpectation(openDetails); let activeExpectation = GUI.activeExpectation(); + let openExpectation = GUI.openExpectation(); if (openExpectation) GUI.hideResults(openExpectation); if (openExpectation && openExpectation == activeExpectation) { @@ -1024,12 +1025,13 @@ } }, + openExpectation: function() { + let openDetails = document.querySelector(".details.open"); + return openDetails && GUI.getExpectation(openDetails); + }, + activeExpectation: function() { - let result = GUI.closest(document.activeElement, "expect"); - if (result) - return result; - result = GUI.closest(document.activeElement, "result-frame"); - return result ? result.previousElementSibling : null; + return GUI.getExpectation(document.activeElement) || GUI.openExpectation(); }, initEvents: function() { @@ -1123,7 +1125,6 @@ printSummary: function (fullResults) { if (fullResults.builder_name) document.querySelector("#builder_name").innerText = fullResults.builder_name; - document.querySelector("#summary_total").innerText = fullResults.num_passes + fullResults.num_regressions; document.querySelector("#summary_passed").innerText = fullResults.num_passes; document.querySelector("#summary_regressions").innerText = fullResults.num_regressions; let failures = fullResults["num_failures_by_type"]; @@ -1141,10 +1142,12 @@ "count_unexpected_pass": 0, "count_unexpected_fail": 0, "count_testexpectations": 0, - "count_flaky": 0 + "count_flaky": 0, + "count_all": 0, }; var t = new Traversal(fullResults.tests); t.traverse( test => { + counts.count_all++; if (Filters.unexpectedPass(test)) counts.count_unexpected_pass++; if (Filters.unexpectedFailure(test)) @@ -1156,11 +1159,16 @@ }); for (let p in counts) document.querySelector("#" + p).innerText = counts[p]; - document.querySelector("#count_all").innerText = fullResults.num_passes + fullResults.num_regressions; + + document.querySelector("#summary_total").innerText = counts.count_all; }, getExpectation: function(el) { - return GUI.closest(el, "expect"); + let result = GUI.closest(el, "expect"); + if (result) + return result; + result = GUI.closest(document.activeElement, "result-frame"); + return result ? result.previousElementSibling : null; }, isFlag: function(el) { @@ -1376,6 +1384,11 @@ if (ev.target.tagName == "A") { this.selectAnchor(ev.target); ev.preventDefault(); + if (this.animationIntervalId) { + // Restart animation to show the clicked view for one second. + this.setAnimation(false); + window.setTimeout(_ => this.setAnimation(true), 1000); + } } });
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt new file mode 100644 index 0000000..be93e98 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-composited-expected.txt
@@ -0,0 +1,133 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 500], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 600], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt new file mode 100644 index 0000000..e66b6e9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-fixed-centered-expected.txt
@@ -0,0 +1,177 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 500], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 500], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 600], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-generated-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-generated-expected.txt new file mode 100644 index 0000000..e66b6e9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-generated-expected.txt
@@ -0,0 +1,177 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 500], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 500], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 600], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 400, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "background" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-non-fixed-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-non-fixed-expected.txt new file mode 100644 index 0000000..f3bc507e --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-background-image-non-fixed-expected.txt
@@ -0,0 +1,177 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt new file mode 100644 index 0000000..d949e6c --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt
@@ -0,0 +1,311 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "rect": [0, 0, 600, 500], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "rect": [0, 0, 6, 500], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "rect": [0, 250, 6, 30], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "rect": [0, 125, 6, 30], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "reason": "geometry" + }, + { + "object": "RootInlineBox", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "rect": [0, 0, 600, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "rect": [0, 0, 6, 250], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "rect": [0, 125, 6, 30], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "reason": "geometry" + }, + { + "object": "RootInlineBox", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "rect": [0, 0, 400, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "rect": [0, 0, 6, 600], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "rect": [0, 300, 6, 30], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "rect": [0, 125, 6, 30], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "reason": "geometry" + }, + { + "object": "RootInlineBox", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "rect": [0, 0, 800, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "rect": [0, 0, 6, 600], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "rect": [0, 300, 6, 30], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV class='container'", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow DIV class='parent'", + "reason": "geometry" + }, + { + "object": "RootInlineBox", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (relative positioned) DIV class='child'", + "reason": "geometry" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-frameset-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-frameset-expected.txt new file mode 100644 index 0000000..9fc2106 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-frameset-expected.txt
@@ -0,0 +1,501 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutFrameSet FRAMESET", + "rect": [0, 0, 600, 500], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutFrame FRAME", + "rect": [153, 0, 294, 500], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [153, 250, 294, 250], + "reason": "incremental" + }, + { + "object": "LayoutFrame FRAME", + "rect": [453, 0, 147, 500], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [0, 0, 147, 500], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [453, 250, 147, 250], + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "rect": [0, 250, 147, 250], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutFrameSet FRAMESET", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutFrameSet FRAMESET", + "rect": [0, 0, 600, 250], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [153, 0, 294, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [153, 0, 294, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutFrame FRAME", + "rect": [103, 0, 194, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [103, 0, 194, 250], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [453, 0, 147, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [453, 0, 147, 250], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [0, 0, 147, 250], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [303, 0, 97, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [303, 0, 97, 250], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [97, 0, 50, 250], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutFrameSet FRAMESET", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow HTML", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow BODY", + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow HTML", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow BODY", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutFrameSet FRAMESET", + "rect": [0, 0, 400, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutFrame FRAME", + "rect": [103, 0, 194, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [103, 250, 194, 350], + "reason": "incremental" + }, + { + "object": "LayoutFrame FRAME", + "rect": [303, 0, 97, 600], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [0, 0, 97, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [303, 250, 97, 350], + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "rect": [0, 250, 97, 350], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutFrameSet FRAMESET", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutFrameSet FRAMESET", + "rect": [0, 0, 800, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutFrame FRAME", + "rect": [203, 0, 394, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [203, 0, 394, 600], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [603, 0, 197, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [603, 0, 197, 600], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [0, 0, 197, 600], + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "rect": [103, 0, 194, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [103, 0, 194, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [97, 0, 100, 600], + "reason": "incremental" + }, + { + "object": "LayoutFrame FRAME", + "rect": [303, 0, 97, 600], + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "rect": [303, 0, 97, 600], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutFrameSet FRAMESET", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutFrame FRAME", + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutView #document", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow HTML", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow BODY", + "reason": "geometry" + }, + { + "object": "LayoutView #document", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow HTML", + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow BODY", + "reason": "geometry" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-media-query-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-media-query-expected.txt new file mode 100644 index 0000000..eab3dc6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-media-query-expected.txt
@@ -0,0 +1,177 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-no-layout-change1-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-no-layout-change1-expected.txt new file mode 100644 index 0000000..23e9f8d --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-no-layout-change1-expected.txt
@@ -0,0 +1,133 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2016], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-no-layout-change2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-no-layout-change2-expected.txt new file mode 100644 index 0000000..1f2c5ba --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-no-layout-change2-expected.txt
@@ -0,0 +1,133 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2008], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2008], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2008], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [2008, 2008], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-percent-html-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-percent-html-expected.txt new file mode 100644 index 0000000..94e61e08 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-percent-html-expected.txt
@@ -0,0 +1,213 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [0, 62, 300, 63], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [200, 0, 100, 63], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [0, 62, 200, 88], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [200, 0, 200, 150], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-percent-width-height-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-percent-width-height-expected.txt new file mode 100644 index 0000000..3e23106 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-percent-width-height-expected.txt
@@ -0,0 +1,213 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 125, 300, 125], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [200, 0, 100, 125], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 125, 200, 175], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [200, 0, 200, 300], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-positioned-bottom-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-positioned-bottom-expected.txt new file mode 100644 index 0000000..ccdff59 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-positioned-bottom-expected.txt
@@ -0,0 +1,205 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 460, 20, 20], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 210, 20, 20], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 560, 20, 20], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 210, 20, 20], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-positioned-percent-top-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-positioned-percent-top-expected.txt new file mode 100644 index 0000000..a50abaa --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-positioned-percent-top-expected.txt
@@ -0,0 +1,205 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 250, 20, 20], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 125, 20, 20], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 300, 20, 20], + "reason": "geometry" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "rect": [0, 125, 20, 20], + "reason": "geometry" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow (positioned) DIV", + "reason": "geometry" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-viewport-percent-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-viewport-percent-expected.txt new file mode 100644 index 0000000..58eb3a2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/paint/invalidation/window-resize/window-resize-viewport-percent-expected.txt
@@ -0,0 +1,205 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [600, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [600, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [600, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 600, 250], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [0, 25, 50, 25], + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [25, 0, 25, 50], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 250], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 200, 250], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 250], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 250], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 600, 250], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [400, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [400, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 250, 400, 350], + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [0, 25, 60, 35], + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [25, 0, 35, 60], + "reason": "incremental" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "incremental" + } + ] +} +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [400, 0, 400, 600], + "reason": "incremental" + } + ] + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [0, 0, 800, 600], + "reason": "background on scrolling contents layer" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "background on scrolling contents layer" + }, + { + "object": "LayoutView #document", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.11/paint/invalidation/background/change-text-content-and-background-color-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.11/paint/invalidation/background/change-text-content-and-background-color-expected.txt new file mode 100644 index 0000000..45eb1d1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/mac-mac10.11/paint/invalidation/background/change-text-content-and-background-color-expected.txt
@@ -0,0 +1,60 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutTextControl (positioned) INPUT id='input'", + "rect": [8, 8, 244, 67], + "reason": "style change" + }, + { + "object": "LayoutBlockFlow DIV", + "rect": [30, 30, 200, 23], + "reason": "geometry" + }, + { + "object": "LayoutText #text", + "rect": [30, 30, 44, 23], + "reason": "full" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutTextControl (positioned) INPUT id='input'", + "reason": "style change" + }, + { + "object": "LayoutBlockFlow DIV", + "reason": "geometry" + }, + { + "object": "RootInlineBox", + "reason": "geometry" + }, + { + "object": "LayoutText #text", + "reason": "full" + }, + { + "object": "InlineTextBox 'NEW'", + "reason": "full" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt index e792836..08ce6de 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/root-layer-scrolls/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt
@@ -18,7 +18,7 @@ "paintInvalidations": [ { "object": "LayoutText #text", - "rect": [230, 123, 542, 394], + "rect": [230, 123, 499, 394], "reason": "geometry" } ]
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-expected.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-expected.html deleted file mode 100644 index 1547d19..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-expected.html +++ /dev/null
@@ -1,7 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<style> - html { - background-color: grey; - } -</style>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-expected.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-expected.html deleted file mode 100644 index 1547d19..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-expected.html +++ /dev/null
@@ -1,7 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<style> - html { - background-color: grey; - } -</style>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-scroller-expected.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-scroller-expected.html deleted file mode 100644 index 1547d19..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-scroller-expected.html +++ /dev/null
@@ -1,7 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<style> - html { - background-color: grey; - } -</style>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-scroller.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-scroller.html deleted file mode 100644 index 5bbf20e..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe-scroller.html +++ /dev/null
@@ -1,57 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should be grey. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - var iframe = document.getElementById("iframe"); - document.rootScroller = iframe; - iframe.contentDocument.rootScroller = iframe.contentDocument.getElementById("scroller"); - }); -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #iframe { - position: absolute; - width: 100%; - height: 100%; - border: 0; - } -</style> - -<iframe id="iframe" srcdoc=" - <style> - html,body { - height: 100vh; - width: 100%; - margin:0; - background-color: maroon; - } - #scroller { - position: absolute; - width: 100%; - height: 100%; - background-color: grey; - overflow: auto; - } - </style> - <div id='scroller'></div>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe.html deleted file mode 100644 index 60fb3c9..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-iframe.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should be grey. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - document.rootScroller = document.getElementById("scroller"); - }); -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #scroller { - position: absolute; - width: 100%; - height: 100%; - border: 0; - } -</style> - -<iframe id="scroller" srcdoc="<style>html {background-color: grey;}</style>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-modified-expected.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-modified-expected.html deleted file mode 100644 index 1547d19..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-modified-expected.html +++ /dev/null
@@ -1,7 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<style> - html { - background-color: grey; - } -</style>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-modified.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-modified.html deleted file mode 100644 index f0e929e..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background-modified.html +++ /dev/null
@@ -1,51 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should be grey. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - testRunner.waitUntilDone(); - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - document.rootScroller = document.getElementById("scroller"); - requestAnimationFrame(function() { - document.rootScroller.style.backgroundColor = "grey"; - requestAnimationFrame(function() { - testRunner.notifyDone(); - }); - }); - }); -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #scroller { - width: 100%; - height: 100%; - overflow: auto; - } - #content { - width: 10px; - height: 20px; - } -</style> - -<div id="scroller"> - <div id="content"></div> -</div>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background.html deleted file mode 100644 index 4d2d336..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-background.html +++ /dev/null
@@ -1,46 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should be grey. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - document.rootScroller = document.getElementById("scroller"); - }); -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #scroller { - position: absolute; - width: 100%; - height: 100%; - overflow: auto; - background-color: grey; - } - #content { - width: 10px; - height: 20px; - } -</style> - -<div id="scroller"> - <div id="content"></div> -</div>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-expected.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-expected.html deleted file mode 100644 index 14a1bcf..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-expected.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html { - height: 100%; - background: linear-gradient(green, blue); - } -</style>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-scroller.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-scroller.html deleted file mode 100644 index aabc873..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe-scroller.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should be a green-blue gradient that starts - // repeating 100px from the bottom. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - var iframe = document.getElementById("iframe"); - document.rootScroller = iframe; - iframe.contentDocument.rootScroller = iframe.contentDocument.getElementById("scroller"); - }); -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #iframe { - position: absolute; - width: 100%; - height: 100%; - border: 0; - } -</style> - -<iframe id="iframe" srcdoc=" - <style> - html,body { - height: 100vh; - width: 100%; - margin:0; - background-color: maroon; - } - #scroller { - position: absolute; - width: 100%; - height: 100%; - background: linear-gradient(green, blue); - overflow: auto; - } - </style> - <div id='scroller'></div>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe.html deleted file mode 100644 index c6dff42..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background-iframe.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should be a green-blue gradient that starts - // repeating 100px from the bottom. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - document.rootScroller = document.getElementById("scroller"); - }); -</script> -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #scroller { - width: 100%; - height: 100%; - border: 0; - } -</style> - -<iframe id="scroller" srcdoc="<style>html {height: 100%; background: linear-gradient(green, blue);}</style>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background.html deleted file mode 100644 index c8bbcd62..0000000 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/browser-controls-gradient-background.html +++ /dev/null
@@ -1,49 +0,0 @@ -<!DOCTYPE html> -<meta name="viewport" content="width=device-width, user-scalable=no" /> -<script> - // Set the browser control height but set them to be hidden so that the - // viewport is taller than the root scroller. This test passes if the root - // scroller's background is painted into the enitre height of the viewport. - // That is, the full viewport should have a red-orange gradient that repeats - // near the bottom. - // NOTE: It is important that this test be run with the Android viewport - // flags turned on. - if (window.internals) { - window.internals.setBrowserControlsState(100, 0, false); - } - - addEventListener("load", function() { - document.rootScroller = document.getElementById("scroller"); - }); -</script> -<style> - -<style> - ::-webkit-scrollbar { - width: 0px; - height: 0px; - } - html, body { - height: 100%; - width: 100%; - margin: 0; - } - body { - background-color: red; - } - #scroller { - position: absolute; - width: 100%; - height: 100%; - overflow: auto; - background: linear-gradient(green, blue); - } - #content { - width: 10px; - height: 20px; - } -</style> - -<div id="scroller"> - <div id="content"></div> -</div>
diff --git a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-shown-expected.html b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-shown-expected.html index 61139bd..a15d286 100644 --- a/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-shown-expected.html +++ b/third_party/WebKit/LayoutTests/virtual/android/fast/rootscroller/nested-rootscroller-browser-controls-bounds-shown-expected.html
@@ -7,7 +7,7 @@ margin: 0; } body { - background-color: white; + background-color: red; } #bottom { position: fixed;
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index ccdd620..e60bc29 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -1959,12 +1959,6 @@ !background_style->HasBackground()) background_style = body_style; - // If the page set a rootScroller, we should use its background for painting - // the document background. - Node& root_scroller = GetRootScrollerController().EffectiveRootScroller(); - if (this != &root_scroller) - background_style = ToElement(root_scroller).EnsureComputedStyle(); - Color background_color = background_style->VisitedDependentColor(CSSPropertyBackgroundColor); FillLayer background_layers = background_style->BackgroundLayers();
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index a1119fa..82ae0c4 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1322,12 +1322,13 @@ } // Reset m_layoutSchedulingEnabled to its previous value. CheckDoesNotNeedLayout(); - Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean); + DocumentLifecycle::Scope lifecycle_scope(Lifecycle(), + DocumentLifecycle::kLayoutClean); frame_timing_requests_dirty_ = true; - // FIXME: Could find the common ancestor layer of all dirty subtrees and - // mark from there. crbug.com/462719 + // FIXME: Could find the common ancestor layer of all dirty subtrees and mark + // from there. crbug.com/462719 GetLayoutViewItem().EnclosingLayer()->UpdateLayerPositionsAfterLayout(); TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp index f2efec94..a76c66c 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
@@ -85,7 +85,6 @@ } void RootScrollerController::DidUpdateLayout() { - DCHECK(document_->Lifecycle().GetState() == DocumentLifecycle::kLayoutClean); RecomputeEffectiveRootScroller(); } @@ -134,14 +133,6 @@ ApplyRootScrollerProperties(*old_effective_root_scroller); ApplyRootScrollerProperties(*effective_root_scroller_); - // Document (i.e. LayoutView) gets its background style from the rootScroller - // so we need to recalc its style. Ensure that we get back to a LayoutClean - // state after. - document_->SetNeedsStyleRecalc(kLocalStyleChange, - StyleChangeReasonForTracing::Create( - StyleChangeReason::kStyleInvalidator)); - document_->UpdateStyleAndLayout(); - if (Page* page = document_->GetPage()) page->GlobalRootScrollerController().DidChangeRootScroller(); }
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h index f998581..1989f67a 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
@@ -66,7 +66,7 @@ // This class needs to be informed of changes in layout so that it can // determine if the current root scroller is still valid or if it must be - // replaced by the default root scroller. Must be called from LayoutClean. + // replaced by the default root scroller. void DidUpdateLayout(); // This class needs to be informed when the FrameView of its Document changes
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp index 82db51f..564350a9 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerTest.cpp
@@ -1170,49 +1170,6 @@ &MainFrameView()->GetRootFrameViewport()->LayoutViewport()); } -// Ensure that background style is propagated to the layout view. -TEST_P(RootScrollerTest, PropagateBackgroundToLayoutView) { - Initialize(); - - WebURL base_url = URLTestHelpers::ToKURL("http://www.test.com/"); - FrameTestHelpers::LoadHTMLString(GetWebView()->MainFrameImpl(), - "<!DOCTYPE html>" - "<style>" - " body, html {" - " width: 100%;" - " height: 100%;" - " margin: 0px;" - " background-color: #ff0000;" - " }" - " #container {" - " width: 100%;" - " height: 100%;" - " overflow: auto;" - " background-color: #0000ff;" - " }" - "</style>" - "<div id='container'>" - " <div style='height:1000px'>test</div>" - "</div>", - base_url); - MainFrameView()->UpdateAllLifecyclePhases(); - - Document* document = MainFrame()->GetDocument(); - ASSERT_EQ(Color(255, 0, 0), - document->GetLayoutView()->Style()->VisitedDependentColor( - CSSPropertyBackgroundColor)); - - Element* container = MainFrame()->GetDocument()->getElementById("container"); - document->setRootScroller(container, ASSERT_NO_EXCEPTION); - - document->setRootScroller(container); - MainFrameView()->UpdateAllLifecyclePhases(); - - EXPECT_EQ(Color(0, 0, 255), - document->GetLayoutView()->Style()->VisitedDependentColor( - CSSPropertyBackgroundColor)); -} - class RootScrollerHitTest : public RootScrollerTest { public: void CheckHitTestAtBottomOfScreen() {
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index 1d963dd..aa85912 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -1408,6 +1408,13 @@ bool DrawingBuffer::ShouldUseChromiumImage() { return RuntimeEnabledFeatures::WebGLImageChromiumEnabled() && chromium_image_usage_ == kAllowChromiumImage && +#if defined(OS_MACOSX) + // Core Animation assumes that the incoming alpha channel is + // premultiplied into the color channels. Fall back to + // regular compositing if the user wants the alpha channel + // interpreted as separate. + premultiplied_alpha_ && +#endif Platform::Current()->GetGpuMemoryBufferManager(); }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h index 8eab17d..4def4f1b 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h
@@ -431,7 +431,7 @@ client, false /* discardFramebufferSupported */, true /* wantAlphaChannel */, - false /* premultipliedAlpha */, + true /* premultipliedAlpha */, preserve, kWebGL1, false /* wantDepth */,
diff --git a/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1 b/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1 index 22db5e09..d430b7a4 100644 --- a/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1 +++ b/third_party/instrumented_libraries/binaries/msan-chained-origins-trusty.tgz.sha1
@@ -1 +1 @@ -0dcb36e70349be00195414cee70ff0d780e3b461 \ No newline at end of file +ef790d476bc67356798ee0c2948a2eedf05dbfa1 \ No newline at end of file
diff --git a/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1 b/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1 index baca72e..06356e5 100644 --- a/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1 +++ b/third_party/instrumented_libraries/binaries/msan-no-origins-trusty.tgz.sha1
@@ -1 +1 @@ -66e243aeaafa32567781733747d569c9e1fe461d \ No newline at end of file +1ccd6518a2b15e53ba8d84d33e705639da9bc753 \ No newline at end of file
diff --git a/third_party/tcmalloc/README.chromium b/third_party/tcmalloc/README.chromium index 1ff6d67..486b6d3 100644 --- a/third_party/tcmalloc/README.chromium +++ b/third_party/tcmalloc/README.chromium
@@ -110,3 +110,4 @@ - Changed kint64min to not depend on undefined behavior. - Fix potential missing nul character in symbol names produced by addr2line-pdb. - Remove superfluous size_t value >= 0 check. +- Make kFooType in tcmalloc.cc truly const.
diff --git a/third_party/tcmalloc/chromium/src/tcmalloc.cc b/third_party/tcmalloc/chromium/src/tcmalloc.cc index 4ea7cdc..bbd47e5 100644 --- a/third_party/tcmalloc/chromium/src/tcmalloc.cc +++ b/third_party/tcmalloc/chromium/src/tcmalloc.cc
@@ -818,13 +818,13 @@ } virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) { - static const char* kCentralCacheType = "tcmalloc.central"; - static const char* kTransferCacheType = "tcmalloc.transfer"; - static const char* kThreadCacheType = "tcmalloc.thread"; - static const char* kPageHeapType = "tcmalloc.page"; - static const char* kPageHeapUnmappedType = "tcmalloc.page_unmapped"; - static const char* kLargeSpanType = "tcmalloc.large"; - static const char* kLargeUnmappedSpanType = "tcmalloc.large_unmapped"; + static const char kCentralCacheType[] = "tcmalloc.central"; + static const char kTransferCacheType[] = "tcmalloc.transfer"; + static const char kThreadCacheType[] = "tcmalloc.thread"; + static const char kPageHeapType[] = "tcmalloc.page"; + static const char kPageHeapUnmappedType[] = "tcmalloc.page_unmapped"; + static const char kLargeSpanType[] = "tcmalloc.large"; + static const char kLargeUnmappedSpanType[] = "tcmalloc.large_unmapped"; v->clear();
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index bbb713d..bca4398 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -27,7 +27,7 @@ # Do NOT CHANGE this if you don't know what you're doing -- see # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md # Reverting problematic clang rolls is safe, though. -CLANG_REVISION = '318369' +CLANG_REVISION = '317263' use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0') in ('1', 'YES')) @@ -35,7 +35,7 @@ CLANG_REVISION = 'HEAD' # This is incremented when pushing a new build of Clang at the same revision. -CLANG_SUB_REVISION=1 +CLANG_SUB_REVISION=4 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index 2bf2d060..e95450a 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -103,28 +103,28 @@ "structures": [12010], }, "chrome/browser/resources/quota_internals_resources.grd": { - "includes": [12050], + "includes": [12110], }, "chrome/browser/resources/settings/settings_resources_vulcanized.grd": { - "includes": [12070], + "includes": [12130], }, "chrome/browser/resources/settings/settings_resources.grd": { - "structures": [12080], + "structures": [12140], }, "chrome/browser/resources/sync_file_system_internals_resources.grd": { - "includes": [12580], + "includes": [12640], }, "chrome/browser/resources/task_scheduler_internals/resources.grd": { - "includes": [12610], + "includes": [12670], }, "chrome/browser/resources/translate_internals_resources.grd": { - "includes": [12620], + "includes": [12680], }, "chrome/browser/resources/vr_shell_resources.grd": { - "includes": [12630], + "includes": [12690], }, "chrome/browser/resources/webapks_ui_resources.grd": { - "includes": [12640], + "includes": [12700], }, # END chrome/browser section.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index c7f21ca..b644fa72 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -24249,7 +24249,6 @@ <int value="-2062373123" label="WebPaymentsModifiers:enabled"/> <int value="-2059771509" label="NTPTilesLowerResolutionFavicons:disabled"/> <int value="-2058656447" label="ContextualSearchUrlActions:enabled"/> - <int value="-2054501930" label="NativeSamba:enabled"/> <int value="-2053860791" label="XGEOVisibleNetworks:enabled"/> <int value="-2048732429" label="enable-alternative-services"/> <int value="-2048679945" label="NTPOfflinePageDownloadSuggestions:disabled"/> @@ -24297,7 +24296,6 @@ <int value="-1960567385" label="KeepPrefetchedContentSuggestions:enabled"/> <int value="-1957328398" label="MacSystemShareMenu:disabled"/> <int value="-1956349722" label="disable-smooth-scrolling"/> - <int value="-1949100957" label="NativeSamba:disabled"/> <int value="-1948540128" label="disable-webrtc-hw-encoding (deprecated)"/> <int value="-1946595906" label="enable-push-api-background-mode"/> <int value="-1946522787" label="VrCustomTabBrowsing:disabled"/> @@ -24555,6 +24553,7 @@ <int value="-1302904242" label="enable-navigation-tracing"/> <int value="-1294050129" label="ContentFullscreen:disabled"/> <int value="-1289678848" label="SystemDownloadManager:enabled"/> + <int value="-1288130734" label="OpenVR:disabled"/> <int value="-1285021473" label="save-page-as-mhtml"/> <int value="-1284637134" label="pull-to-refresh"/> <int value="-1276912933" label="enable-quick-unlock-pin"/> @@ -24565,6 +24564,7 @@ <int value="-1262152606" label="disable-lock-screen-apps"/> <int value="-1261263046" label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:disabled"/> + <int value="-1259901957" label="VrBrowserKeyboard:disabled"/> <int value="-1254070521" label="enable-slimming-paint-invalidation"/> <int value="-1251411236" label="disable-new-md-input-view"/> <int value="-1248478422" label="enable-zip-archiver-packer"/> @@ -24708,6 +24708,7 @@ <int value="-876148583" label="ArcBootCompletedBroadcast:disabled"/> <int value="-867087281" label="enable-virtual-keyboard"/> <int value="-866993841" label="OfflinePagesCTV2:disabled"/> + <int value="-865390600" label="NativeSmb:enabled"/> <int value="-864266073" label="cros-regions-mode"/> <int value="-864234985" label="UseDdljsonApi:enabled"/> <int value="-864205629" label="enable-offline-load-stale-cache"/> @@ -24726,6 +24727,7 @@ <int value="-835672415" label="PointerEventV1SpecCapturing:disabled"/> <int value="-834661509" label="ModalPermissionPrompts:disabled"/> <int value="-832561975" label="enable-picture-in-picture"/> + <int value="-828070439" label="NativeSmb:disabled"/> <int value="-825942229" label="tab-management-experiment-type-elderberry"/> <int value="-823165021" label="MaterialDesignUserMenu:enabled"/> <int value="-820041355" label="enable-transition-compositing"/> @@ -25588,6 +25590,7 @@ <int value="1612871297" label="WebPayments:disabled"/> <int value="1612974229" label="allow-insecure-localhost"/> <int value="1617187093" label="enable-improved-a2hs"/> + <int value="1621298798" label="VrBrowserKeyboard:enabled"/> <int value="1622131033" label="ozone-test-single-overlay-support"/> <int value="1626824478" label="ExperimentalAppBanners:disabled"/> <int value="1630988998" label="VrBrowsingExperimentalRendering:disabled"/> @@ -25703,6 +25706,7 @@ <int value="1928407249" label="NewPhotoPicker:enabled"/> <int value="1930901873" label="disable-sync-app-list"/> <int value="1931309368" label="fill-on-account-select:disabled"/> + <int value="1932732886" label="OpenVR:enabled"/> <int value="1936810062" label="WebVrVsyncAlign:enabled"/> <int value="1939413645" label="enable-invalid-cert-collection"/> <int value="1942911276" label="enable-grouped-history"/> @@ -39339,6 +39343,15 @@ <int value="1" label="The user clicked the promo to sign in"/> </enum> +<enum name="SyncRequestType"> + <summary>Maps to values in sync_pb::ClientToServerMessage_Contents.</summary> + <int value="1" label="COMMIT"/> + <int value="2" label="GET_UPDATES"/> + <int value="3" label="AUTHENTICATE"/> + <int value="4" label="DEPRECATED_4"/> + <int value="5" label="CLEAR_SERVER_DATA"/> +</enum> + <enum name="SyncSimpleConflictResolutions"> <summary> Sync simple conflict resolutions. The codes are listed in
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index d1b352f..bb06ebee 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -35733,6 +35733,15 @@ </summary> </histogram> +<histogram name="MediaRouter.WiredDisplay.AvailableDevicesCount"> + <owner>takumif@chromium.org</owner> + <summary> + The number of Media Sinks available for Casting a Presentation API URL to + local screens. Recorded at most once an hour, when the Wired Display Media + Route Provider reports an update on the sink count. + </summary> +</histogram> + <histogram name="MemCache.WriteResult" enum="MemCacheWriteResult"> <owner>jkarlin@chromium.org</owner> <summary>The outcome of Entry::WriteData in the memory cache.</summary> @@ -84869,6 +84878,13 @@ <summary>Tracks the size of the local sync backend database file.</summary> </histogram> +<histogram name="Sync.Local.RequestTypeOnError" enum="SyncRequestType"> + <owner>skym@chromium.org</owner> + <summary> + Tracks the types of requests that caused errors inside of the local server. + </summary> +</histogram> + <histogram name="Sync.Local.RoamingProfileUnavailable" enum="BooleanError"> <owner>pastarmovj@chromium.org</owner> <summary>
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc index 54314e9e..ddecf81 100644 --- a/ui/base/ui_base_switches.cc +++ b/ui/base/ui_base_switches.cc
@@ -129,8 +129,11 @@ #if BUILDFLAG(ENABLE_MUS) // Used to enable the mus service (aka the UI service). This makes mus run in -// process. +// process. It is also used to notify the clients that the UI service is being +// used. If the value of this flag is set to kMusHostVizValue, then that means +// the UI service is hosting the viz service. const char kMus[] = "mus"; +const char kMusHostVizValue[] = "viz"; #endif } // namespace switches
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h index d3d90c18..76bb09a 100644 --- a/ui/base/ui_base_switches.h +++ b/ui/base/ui_base_switches.h
@@ -59,6 +59,7 @@ #if BUILDFLAG(ENABLE_MUS) UI_BASE_EXPORT extern const char kMus[]; +UI_BASE_EXPORT extern const char kMusHostVizValue[]; #endif } // namespace switches