diff --git a/DEPS b/DEPS index 16761847..c2f8dac 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '2ac96dc82c45b4425c288dedbf3d35d70ac36928', + 'skia_revision': 'df669811b16e317b307b335822c4c7c881c1d163', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '71062f39efd675ed137cea600d55f666499f1c56', + 'v8_revision': '64735758443e0a81a2f8a67338a5203fd725c2f3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -60,7 +60,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '3b9e1eab3544111f3f1ff8fc652d6548acb608ba', + 'swiftshader_revision': '9282c6d71f730ff604469951a1f6615baa57c056', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '3d3b6d368d4aea08015591e995ac3d50c7ea77f4', + 'catapult_revision': '677b02eacd6fe0d32040649858b5248d7dc402da', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -199,7 +199,7 @@ Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '331fe3a462b2e1f5c9baa1a710312a1b5888e404', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '9ffa3b5a09e9d86be4ec4cdf6c151a503fa1c0e0', 'src/third_party/webdriver/pylib': Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 80b4e43..6cf9d7a 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -205,7 +205,7 @@ Shell::DeleteInstance(); // Suspend the tear down until all resources are returned via - // MojoCompositorFrameSinkClient::ReclaimResources() + // CompositorFrameSinkClient::ReclaimResources() RunAllPendingInMessageLoop(); ash_test_environment_->TearDown();
diff --git a/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java b/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java index f57dba2..ab66bfee 100644 --- a/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java +++ b/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java
@@ -159,6 +159,35 @@ } } + /** Caches a set of boolean histogram samples. */ + public static class BooleanHistogramSample extends CachedHistogram { + private final List<Boolean> mSamples = new ArrayList<Boolean>(); + + public BooleanHistogramSample(String histogramName) { + super(histogramName); + } + + public void record(boolean sample) { + if (LibraryLoader.isInitialized()) { + recordWithNative(sample); + } else { + mSamples.add(sample); + } + } + + private void recordWithNative(boolean sample) { + RecordHistogram.recordBooleanHistogram(mHistogramName, sample); + } + + @Override + protected void commitAndClear() { + for (Boolean sample : mSamples) { + recordWithNative(sample); + } + mSamples.clear(); + } + } + /** * Calls out to native code to commit any cached histograms and events. * Should be called once the native library has been loaded.
diff --git a/base/win/com_init_util.cc b/base/win/com_init_util.cc index 53a6d73d..a3093fa 100644 --- a/base/win/com_init_util.cc +++ b/base/win/com_init_util.cc
@@ -17,6 +17,7 @@ // Derived from combase.dll. struct OleTlsData { enum ApartmentFlags { + LOGICAL_THREAD_REGISTERED = 0x2, STA = 0x80, MTA = 0x140, }; @@ -30,9 +31,13 @@ // to work between x86 and x64 builds. }; -ComApartmentType GetComApartmentTypeForThread() { +OleTlsData* GetOleTlsData() { TEB* teb = NtCurrentTeb(); - OleTlsData* ole_tls_data = reinterpret_cast<OleTlsData*>(teb->ReservedForOle); + return reinterpret_cast<OleTlsData*>(teb->ReservedForOle); +} + +ComApartmentType GetComApartmentTypeForThread() { + OleTlsData* ole_tls_data = GetOleTlsData(); if (!ole_tls_data) return ComApartmentType::NONE; @@ -50,7 +55,18 @@ } // namespace void AssertComInitialized() { - DCHECK_NE(ComApartmentType::NONE, GetComApartmentTypeForThread()); + if (GetComApartmentTypeForThread() != ComApartmentType::NONE) + return; + + // COM worker threads don't always set up the apartment, but they do perform + // some thread registration, so we allow those. + OleTlsData* ole_tls_data = GetOleTlsData(); + if (ole_tls_data && (ole_tls_data->apartment_flags & + OleTlsData::ApartmentFlags::LOGICAL_THREAD_REGISTERED)) { + return; + } + + NOTREACHED(); } void AssertComApartmentType(ComApartmentType apartment_type) {
diff --git a/cc/ipc/BUILD.gn b/cc/ipc/BUILD.gn index 13e4325..59fb1ec4 100644 --- a/cc/ipc/BUILD.gn +++ b/cc/ipc/BUILD.gn
@@ -42,6 +42,7 @@ "begin_frame_args.mojom", "compositor_frame.mojom", "compositor_frame_metadata.mojom", + "compositor_frame_sink.mojom", "copy_output_request.mojom", "copy_output_result.mojom", "filter_operation.mojom", @@ -49,7 +50,6 @@ "frame_sink_id.mojom", "frame_sink_manager.mojom", "local_surface_id.mojom", - "mojo_compositor_frame_sink.mojom", "quads.mojom", "render_pass.mojom", "returned_resource.mojom",
diff --git a/cc/ipc/mojo_compositor_frame_sink.mojom b/cc/ipc/compositor_frame_sink.mojom similarity index 91% rename from cc/ipc/mojo_compositor_frame_sink.mojom rename to cc/ipc/compositor_frame_sink.mojom index cc547e7..45e904a3 100644 --- a/cc/ipc/mojo_compositor_frame_sink.mojom +++ b/cc/ipc/compositor_frame_sink.mojom
@@ -14,12 +14,12 @@ import "cc/ipc/surface_sequence.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; -// A MojoCompositorFrameSink is an interface for receiving CompositorFrame +// A CompositorFrameSink is an interface for receiving CompositorFrame // structs. A CompositorFrame contains the complete output meant for display. // Each time a client has a graphical update, and receives an OnBeginFrame, it // is responsible for creating a CompositorFrame to update its portion of the // screen. -interface MojoCompositorFrameSink { +interface CompositorFrameSink { // Lets the display compositor know that the client wishes to receive the next // BeginFrame event. SetNeedsBeginFrame(bool needs_begin_frame); @@ -40,7 +40,7 @@ DidNotProduceFrame(cc.mojom.BeginFrameAck ack); }; -interface MojoCompositorFrameSinkClient { +interface CompositorFrameSinkClient { // Notification that the previous CompositorFrame given to // SubmitCompositorFrame() has been processed and that another frame // can be submitted. This provides backpressure from the display compositor @@ -57,10 +57,10 @@ ReclaimResources(ReturnedResourceArray resources); }; -// MojoCompositorFrameSinkPrivate is used by the display compositor host to +// CompositorFrameSinkPrivate is used by the display compositor host to // perform privilieged operations on a CompositorFrameSink such as // CopyOutputRequests. -interface MojoCompositorFrameSinkPrivate { +interface CompositorFrameSinkPrivate { // Claims this FrameSinkId will embed |surface_id| so it should own the // temporary reference to |surface_id|. ClaimTemporaryReference(SurfaceId surface_id);
diff --git a/cc/ipc/frame_sink_manager.mojom b/cc/ipc/frame_sink_manager.mojom index 584d614f..323451b2 100644 --- a/cc/ipc/frame_sink_manager.mojom +++ b/cc/ipc/frame_sink_manager.mojom
@@ -6,7 +6,7 @@ import "cc/ipc/frame_sink_id.mojom"; import "cc/ipc/local_surface_id.mojom"; -import "cc/ipc/mojo_compositor_frame_sink.mojom"; +import "cc/ipc/compositor_frame_sink.mojom"; import "cc/ipc/surface_id.mojom"; import "cc/ipc/surface_info.mojom"; import "gpu/ipc/common/surface_handle.mojom"; @@ -29,15 +29,15 @@ // The FrameSinkManager interface is a privileged interface that allows the // frame sink manager host (browser or window server) to create // CompositorFrameSinks. Clients acquire a CompositorFrameSink connection -// through the frame sink manager host. Clients request a -// MojoCompositorFrameSink interface, and implement a -// MojoCompositorFrameSinkClient interface. The frame sink manager host -// holds one or more display CompositorFrameSinks that are tied to a valid -// |surface_handle| and cc::Display. All other CompositorFrameSinks must be -// parented by another CompositorFrameSink. FrameSinkIds are fixed for a given -// client and are determined ahead of time. Thus, a client will typically simply -// request a CompositorFrameSink from the frame sink manager host which will -// forward the request to the frame sink manager. +// through the frame sink manager host. Clients request a CompositorFrameSink +// interface, and implement a CompositorFrameSinkClient interface. The frame +// sink manager host holds one or more display CompositorFrameSinks that are +// tied to a valid |surface_handle| and cc::Display. All other +// CompositorFrameSinks must be parented by another CompositorFrameSink. +// FrameSinkIds are fixed for a given client and are determined ahead of time. +// Thus, a client will typically simply request a CompositorFrameSink from the +// frame sink manager host which will forward the request to the frame sink +// manager. interface FrameSinkManager { // Create a CompositorFrameSink for a privileged client (e.g. WindowServer). // This is only used by privileged clients. The client can call methods that @@ -45,9 +45,9 @@ CreateRootCompositorFrameSink( cc.mojom.FrameSinkId frame_sink_id, gpu.mojom.SurfaceHandle widget, - associated cc.mojom.MojoCompositorFrameSink& compositor_frame_sink, - cc.mojom.MojoCompositorFrameSinkPrivate& compositor_frame_sink_private, - cc.mojom.MojoCompositorFrameSinkClient compositor_frame_sink_client, + associated cc.mojom.CompositorFrameSink& compositor_frame_sink, + cc.mojom.CompositorFrameSinkPrivate& compositor_frame_sink_private, + cc.mojom.CompositorFrameSinkClient compositor_frame_sink_client, associated DisplayPrivate& display_private); // CreateCompositorFrameSink is used by unprivileged clients. This @@ -55,9 +55,9 @@ // CompositorFrameSink in order to appear on screen. CreateCompositorFrameSink( cc.mojom.FrameSinkId frame_sink_id, - cc.mojom.MojoCompositorFrameSink& compositor_frame_sink, - cc.mojom.MojoCompositorFrameSinkPrivate& compositor_frame_sink_private, - cc.mojom.MojoCompositorFrameSinkClient compositor_frame_sink_client); + cc.mojom.CompositorFrameSink& compositor_frame_sink, + cc.mojom.CompositorFrameSinkPrivate& compositor_frame_sink_private, + cc.mojom.CompositorFrameSinkClient compositor_frame_sink_client); // Set up a BeginFrame relationship between two FrameSinkIds. In this case, // the child inherits the BeginFrameSource from the parent if it doesn't
diff --git a/cc/paint/draw_image.cc b/cc/paint/draw_image.cc index 6ffb3ae8..c0505d9 100644 --- a/cc/paint/draw_image.cc +++ b/cc/paint/draw_image.cc
@@ -46,4 +46,12 @@ DrawImage::~DrawImage() = default; +bool DrawImage::operator==(const DrawImage& other) const { + return paint_image_ == other.paint_image_ && src_rect_ == other.src_rect_ && + filter_quality_ == other.filter_quality_ && matrix_ == other.matrix_ && + scale_ == other.scale_ && + matrix_is_decomposable_ == other.matrix_is_decomposable_ && + target_color_space_ == other.target_color_space_; +} + } // namespace cc
diff --git a/cc/paint/draw_image.h b/cc/paint/draw_image.h index fe84f06..8f202b1 100644 --- a/cc/paint/draw_image.h +++ b/cc/paint/draw_image.h
@@ -30,6 +30,8 @@ DrawImage(const DrawImage& other); ~DrawImage(); + bool operator==(const DrawImage& other) const; + const PaintImage& paint_image() const { return paint_image_; } const sk_sp<SkImage>& image() const { return paint_image_.sk_image(); } const SkSize& scale() const { return scale_; }
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index a1744055..0127799 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -938,8 +938,12 @@ void SurfaceAggregator::SetOutputColorSpace( const gfx::ColorSpace& blending_color_space, const gfx::ColorSpace& output_color_space) { - blending_color_space_ = blending_color_space; - output_color_space_ = output_color_space; + blending_color_space_ = blending_color_space.IsValid() + ? blending_color_space + : gfx::ColorSpace::CreateSRGB(); + output_color_space_ = output_color_space.IsValid() + ? output_color_space + : gfx::ColorSpace::CreateSRGB(); } } // namespace cc
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h index 015e5f4..9e7ce6f 100644 --- a/cc/surfaces/surface_aggregator.h +++ b/cc/surfaces/surface_aggregator.h
@@ -153,11 +153,11 @@ // The color space for the root render pass. If this is different from // |blending_color_space_|, then a final render pass to convert between - // the two will be added. - gfx::ColorSpace output_color_space_; + // the two will be added. This space must always be valid. + gfx::ColorSpace output_color_space_ = gfx::ColorSpace::CreateSRGB(); // The color space in which blending is done, used for all non-root render - // passes. - gfx::ColorSpace blending_color_space_; + // passes. This space must always be valid. + gfx::ColorSpace blending_color_space_ = gfx::ColorSpace::CreateSRGB(); // The id for the final color conversion render pass. RenderPassId color_conversion_render_pass_id_ = 0;
diff --git a/cc/test/fake_layer_tree_host_impl_client.cc b/cc/test/fake_layer_tree_host_impl_client.cc index 3b7adfc..b37a5e6 100644 --- a/cc/test/fake_layer_tree_host_impl_client.cc +++ b/cc/test/fake_layer_tree_host_impl_client.cc
@@ -18,4 +18,12 @@ did_request_impl_side_invalidation_ = true; } +void FakeLayerTreeHostImplClient::NotifyReadyToActivate() { + ready_to_activate_ = true; +} + +void FakeLayerTreeHostImplClient::NotifyReadyToDraw() { + ready_to_draw_ = true; +} + } // namespace cc
diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index 78b2ed8..9ed611b 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -17,8 +17,8 @@ void SetBeginFrameSource(BeginFrameSource* source) override {} void DidReceiveCompositorFrameAckOnImplThread() override {} void OnCanDrawStateChanged(bool can_draw) override {} - void NotifyReadyToActivate() override {} - void NotifyReadyToDraw() override {} + void NotifyReadyToActivate() override; + void NotifyReadyToDraw() override; void SetNeedsRedrawOnImplThread() override {} void SetNeedsOneBeginImplFrameOnImplThread() override {} void SetNeedsCommitOnImplThread() override {} @@ -46,8 +46,16 @@ return did_request_impl_side_invalidation_; } + void reset_ready_to_activate() { ready_to_activate_ = false; } + bool ready_to_activate() const { return ready_to_activate_; } + + void reset_ready_to_draw() { ready_to_draw_ = false; } + bool ready_to_draw() const { return ready_to_draw_; } + private: bool did_request_impl_side_invalidation_ = false; + bool ready_to_activate_ = false; + bool ready_to_draw_ = false; }; } // namespace cc
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 2bd8d5b..14666f6 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -230,6 +230,7 @@ block_impl_side_invalidation_ = block; if (!block_impl_side_invalidation_ && impl_side_invalidation_was_blocked_) { RequestImplSideInvalidation(); + impl_side_invalidation_was_blocked_ = false; } } @@ -281,6 +282,7 @@ } void RequestImplSideInvalidation() override { + test_hooks_->DidReceiveImplSideInvalidationRequest(this); if (block_impl_side_invalidation_) { impl_side_invalidation_was_blocked_ = true; return;
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h index a59f6aa..a143805 100644 --- a/cc/test/test_hooks.h +++ b/cc/test/test_hooks.h
@@ -66,6 +66,8 @@ virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl, base::TimeTicks monotonic_time) {} virtual void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) {} + virtual void DidReceiveImplSideInvalidationRequest( + LayerTreeHostImpl* host_impl) {} virtual void DidRequestImplSideInvalidation(LayerTreeHostImpl* host_impl) {} // Asynchronous compositor thread hooks.
diff --git a/cc/tiles/checker_image_tracker.cc b/cc/tiles/checker_image_tracker.cc index 1e562cd..c9e4228 100644 --- a/cc/tiles/checker_image_tracker.cc +++ b/cc/tiles/checker_image_tracker.cc
@@ -39,6 +39,14 @@ } // namespace +// static +const int CheckerImageTracker::kNoDecodeAllowedPriority = -1; + +CheckerImageTracker::ImageDecodeRequest::ImageDecodeRequest( + PaintImage paint_image, + DecodeType type) + : paint_image(std::move(paint_image)), type(type) {} + CheckerImageTracker::CheckerImageTracker(ImageController* image_controller, CheckerImageTrackerClient* client, bool enable_checker_imaging) @@ -49,6 +57,23 @@ CheckerImageTracker::~CheckerImageTracker() = default; +void CheckerImageTracker::SetNoDecodesAllowed() { + decode_priority_allowed_ = kNoDecodeAllowedPriority; +} + +void CheckerImageTracker::SetMaxDecodePriorityAllowed(DecodeType decode_type) { + DCHECK_GT(decode_type, kNoDecodeAllowedPriority); + DCHECK_GE(decode_type, decode_priority_allowed_); + DCHECK_LE(decode_type, DecodeType::kLast); + + if (decode_priority_allowed_ == decode_type) + return; + decode_priority_allowed_ = decode_type; + + // This will start the next decode if applicable. + ScheduleNextImageDecode(); +} + void CheckerImageTracker::ScheduleImageDecodeQueue( ImageDecodeQueue image_decode_queue) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), @@ -58,6 +83,15 @@ // be checkered. DCHECK(image_decode_queue.empty() || enable_checker_imaging_); +#if DCHECK_IS_ON() + // The decodes in the queue should be prioritized correctly. + DecodeType type = DecodeType::kRaster; + for (const auto& image_request : image_decode_queue) { + DCHECK_GE(image_request.type, type); + type = image_request.type; + } +#endif + image_decode_queue_ = std::move(image_decode_queue); ScheduleNextImageDecode(); } @@ -250,9 +284,17 @@ if (outstanding_image_decode_.has_value()) return; + if (image_decode_queue_.empty()) + return; + + // If scheduling decodes for this priority is not allowed right now, don't + // schedule them. We will come back here when the allowed priority changes. + if (image_decode_queue_.front().type > decode_priority_allowed_) + return; + DrawImage draw_image; while (!image_decode_queue_.empty()) { - auto candidate = std::move(image_decode_queue_.front()); + auto candidate = std::move(image_decode_queue_.front().paint_image); image_decode_queue_.erase(image_decode_queue_.begin()); // Once an image has been decoded, it can still be present in the decode
diff --git a/cc/tiles/checker_image_tracker.h b/cc/tiles/checker_image_tracker.h index 64560fb..8053743 100644 --- a/cc/tiles/checker_image_tracker.h +++ b/cc/tiles/checker_image_tracker.h
@@ -33,6 +33,24 @@ // sync tree until the previous tree is activated. class CC_EXPORT CheckerImageTracker { public: + // The priority type for a decode. Note we use int to specify a decreasing + // order of priority with higher values. + enum DecodeType : int { + // Priority for images on tiles being rasterized (visible or pre-paint). + kRaster = 0, + // Lowest priority for images on tiles in pre-decode region. These are tiles + // which are beyond the pre-paint region, but have their images decoded. + kPreDecode = 1, + + kLast = kPreDecode + }; + + struct CC_EXPORT ImageDecodeRequest { + ImageDecodeRequest(PaintImage paint_image, DecodeType type); + PaintImage paint_image; + DecodeType type; + }; + CheckerImageTracker(ImageController* image_controller, CheckerImageTrackerClient* client, bool enable_checker_imaging); @@ -42,9 +60,16 @@ // service and it should be be skipped during raster. bool ShouldCheckerImage(const DrawImage& image, WhichTree tree); - using ImageDecodeQueue = std::vector<PaintImage>; + // Provides a prioritized queue of images to decode. + using ImageDecodeQueue = std::vector<ImageDecodeRequest>; void ScheduleImageDecodeQueue(ImageDecodeQueue image_decode_queue); + // Disables scheduling any decode work by the tracker. + void SetNoDecodesAllowed(); + + // The max decode priority type that is allowed to run. + void SetMaxDecodePriorityAllowed(DecodeType decode_type); + // Returns the set of images to invalidate on the sync tree. const PaintImageIdFlatSet& TakeImagesToInvalidateOnSyncTree(); @@ -70,7 +95,16 @@ return !image_id_to_decode_.empty(); } + int decode_priority_allowed_for_testing() const { + return decode_priority_allowed_; + } + bool no_decodes_allowed_for_testing() const { + return decode_priority_allowed_ == kNoDecodeAllowedPriority; + } + private: + static const int kNoDecodeAllowedPriority; + enum class DecodePolicy { // The image can be decoded asynchronously from raster. When set, the image // is always skipped during rasterization of content that includes this @@ -134,6 +168,9 @@ // dependent on these images. ImageDecodeQueue image_decode_queue_; + // The max decode type that is allowed to run, if decodes are allowed to run. + int decode_priority_allowed_ = kNoDecodeAllowedPriority; + // The currently outstanding image decode that has been scheduled with the // decode service. There can be only one outstanding decode at a time. base::Optional<PaintImage> outstanding_image_decode_;
diff --git a/cc/tiles/checker_image_tracker_unittest.cc b/cc/tiles/checker_image_tracker_unittest.cc index aee6773b..16b6ebd 100644 --- a/cc/tiles/checker_image_tracker_unittest.cc +++ b/cc/tiles/checker_image_tracker_unittest.cc
@@ -85,6 +85,8 @@ void SetUpTracker(bool checker_images_enabled) { checker_image_tracker_ = base::MakeUnique<CheckerImageTracker>( &image_controller_, this, checker_images_enabled); + checker_image_tracker_->SetMaxDecodePriorityAllowed( + CheckerImageTracker::DecodeType::kPreDecode); } void TearDown() override { checker_image_tracker_.reset(); } @@ -122,7 +124,8 @@ CheckerImageTracker::ImageDecodeQueue decode_queue; for (const auto& image : images) { if (checker_image_tracker_->ShouldCheckerImage(image, tree)) - decode_queue.push_back(image.paint_image()); + decode_queue.push_back(CheckerImageTracker::ImageDecodeRequest( + image.paint_image(), CheckerImageTracker::DecodeType::kRaster)); } return decode_queue; } @@ -170,8 +173,8 @@ BuildImageDecodeQueue(draw_images, WhichTree::PENDING_TREE); ASSERT_EQ(2u, image_decode_queue.size()); - EXPECT_EQ(checkerable_image.paint_image(), image_decode_queue[0]); - EXPECT_EQ(checkerable_image.paint_image(), image_decode_queue[1]); + EXPECT_EQ(checkerable_image.paint_image(), image_decode_queue[0].paint_image); + EXPECT_EQ(checkerable_image.paint_image(), image_decode_queue[1].paint_image); checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue); EXPECT_EQ(image_controller_.num_of_locked_images(), 1); @@ -416,7 +419,7 @@ CheckerImageTracker::ImageDecodeQueue image_decode_queue = BuildImageDecodeQueue(draw_images, WhichTree::PENDING_TREE); EXPECT_EQ(image_decode_queue.size(), 1U); - EXPECT_EQ(image_decode_queue[0], static_image.paint_image()); + EXPECT_EQ(image_decode_queue[0].paint_image, static_image.paint_image()); // Change the partial image to complete and try again. It should sstill not // be checkered. @@ -488,5 +491,45 @@ multi_part_image, WhichTree::PENDING_TREE)); } +TEST_F(CheckerImageTrackerTest, RespectsDecodePriority) { + SetUpTracker(true); + + DrawImage image1 = CreateImage(ImageType::CHECKERABLE); + DrawImage image2 = CreateImage(ImageType::CHECKERABLE); + DrawImage image3 = CreateImage(ImageType::CHECKERABLE); + DrawImage image4 = CreateImage(ImageType::CHECKERABLE); + CheckerImageTracker::ImageDecodeQueue image_decode_queue = + BuildImageDecodeQueue({image1, image2, image3, image4}, + WhichTree::PENDING_TREE); + + // Mark the last 2 images as pre-decode. + EXPECT_EQ(image_decode_queue.size(), 4u); + image_decode_queue[2].type = CheckerImageTracker::DecodeType::kPreDecode; + image_decode_queue[3].type = CheckerImageTracker::DecodeType::kPreDecode; + + // No decodes allowed. Nothing should be scheduled. + EXPECT_EQ(image_controller_.decoded_images().size(), 0u); + checker_image_tracker_->SetNoDecodesAllowed(); + checker_image_tracker_->ScheduleImageDecodeQueue(image_decode_queue); + EXPECT_EQ(image_controller_.decoded_images().size(), 0u); + + // Raster decodes allowed. Only those should be scheduled. + checker_image_tracker_->SetMaxDecodePriorityAllowed( + CheckerImageTracker::DecodeType::kRaster); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(image_controller_.decoded_images().size(), 2u); + EXPECT_EQ(image_controller_.decoded_images()[0], image1); + EXPECT_EQ(image_controller_.decoded_images()[1], image2); + + // All decodes allowed. The complete queue should be flushed. + checker_image_tracker_->SetMaxDecodePriorityAllowed( + CheckerImageTracker::DecodeType::kPreDecode); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(image_controller_.decoded_images()[0], image1); + EXPECT_EQ(image_controller_.decoded_images()[1], image2); + EXPECT_EQ(image_controller_.decoded_images()[2], image3); + EXPECT_EQ(image_controller_.decoded_images()[3], image4); +} + } // namespace } // namespace cc
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index 7597883e..2e78129 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc
@@ -497,6 +497,12 @@ signals_.reset(); global_state_ = state; + // Ensure that we don't schedule any decode work for checkered images until + // the raster work for visible tiles is complete. This is done in + // CheckAndIssueSignals when the ready to activate/draw signals are dispatched + // to the client. + checker_image_tracker_.SetNoDecodesAllowed(); + // We need to call CheckForCompletedTasks() once in-between each call // to ScheduleTasks() to prevent canceled tasks from being scheduled. if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { @@ -513,7 +519,7 @@ prioritized_work.tiles_to_raster.front().tile()->required_for_draw()); // Schedule tile tasks. - ScheduleTasks(prioritized_work); + ScheduleTasks(std::move(prioritized_work)); TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, "state", BasicStateAsValue()); @@ -709,6 +715,7 @@ AddCheckeredImagesToDecodeQueue( prioritized_tile, raster_color_space, + CheckerImageTracker::DecodeType::kRaster, &work_to_schedule.checker_image_decode_queue); continue; } @@ -767,6 +774,7 @@ prioritized_tile.should_decode_checkered_images_for_tile()) { AddCheckeredImagesToDecodeQueue( prioritized_tile, raster_color_space, + CheckerImageTracker::DecodeType::kRaster, &work_to_schedule.checker_image_decode_queue); } } else { @@ -809,6 +817,7 @@ tile->raster_task_scheduled_with_checker_images()) { AddCheckeredImagesToDecodeQueue( prioritized_tile, raster_color_space, + CheckerImageTracker::DecodeType::kRaster, &work_to_schedule.checker_image_decode_queue); } } @@ -878,6 +887,7 @@ void TileManager::AddCheckeredImagesToDecodeQueue( const PrioritizedTile& prioritized_tile, const gfx::ColorSpace& raster_color_space, + CheckerImageTracker::DecodeType decode_type, CheckerImageTracker::ImageDecodeQueue* image_decode_queue) { Tile* tile = prioritized_tile.tile(); std::vector<DrawImage> images_in_tile; @@ -887,13 +897,14 @@ WhichTree tree = tile->tiling()->tree(); for (auto& draw_image : images_in_tile) { - if (checker_image_tracker_.ShouldCheckerImage(draw_image, tree)) - image_decode_queue->push_back(draw_image.paint_image()); + if (checker_image_tracker_.ShouldCheckerImage(draw_image, tree)) { + image_decode_queue->push_back(CheckerImageTracker::ImageDecodeRequest( + draw_image.paint_image(), decode_type)); + } } } -void TileManager::ScheduleTasks( - const PrioritizedWorkToSchedule& work_to_schedule) { +void TileManager::ScheduleTasks(PrioritizedWorkToSchedule work_to_schedule) { const std::vector<PrioritizedTile>& tiles_that_need_to_be_rasterized = work_to_schedule.tiles_to_raster; TRACE_EVENT1("cc", "TileManager::ScheduleTasks", "count", @@ -973,16 +984,23 @@ work_to_schedule.tiles_to_process_for_images; std::vector<DrawImage> new_locked_images; for (const PrioritizedTile& prioritized_tile : tiles_to_process_for_images) { - Tile* tile = prioritized_tile.tile(); + std::vector<DrawImage> sync_decoded_images; + std::vector<PaintImage> checkered_images; + PartitionImagesForCheckering(prioritized_tile, raster_color_space, + &sync_decoded_images, &checkered_images); - // TODO(khushalsagar): Send these images to the ImageDecodeService, through - // the CheckerImageTracker as well. See crbug.com/691087. - std::vector<DrawImage> images; - prioritized_tile.raster_source()->GetDiscardableImagesInRect( - tile->enclosing_layer_rect(), tile->raster_transform().scale(), - raster_color_space, &images); - new_locked_images.insert(new_locked_images.end(), images.begin(), - images.end()); + // Add the sync decoded images to |new_locked_images| so they can be added + // to the task graph. + new_locked_images.insert(new_locked_images.end(), + sync_decoded_images.begin(), + sync_decoded_images.end()); + + // For checkered-images, send them to the decode service. + for (auto& image : checkered_images) { + work_to_schedule.checker_image_decode_queue.push_back( + CheckerImageTracker::ImageDecodeRequest( + std::move(image), CheckerImageTracker::DecodeType::kPreDecode)); + } } // TODO(vmpstr): SOON is misleading here, but these images can come from @@ -1107,8 +1125,11 @@ // or are occluded on the pending tree. While we still need to continue // skipping images for these tiles, we don't need to decode them since // they will not be required on the next active tree. - if (prioritized_tile.should_decode_checkered_images_for_tile()) - checker_image_decode_queue->push_back(image); + if (prioritized_tile.should_decode_checkered_images_for_tile()) { + checker_image_decode_queue->push_back( + CheckerImageTracker::ImageDecodeRequest( + image, CheckerImageTracker::DecodeType::kRaster)); + } } } @@ -1307,6 +1328,19 @@ client_->NotifyAllTileTasksCompleted(); } } + + // Allow decodes for rasterized tiles if all required for draw/activate tiles + // are done. And pre-decode tiles once all tile tasks are done. + // Note that the order is important here, since all signals could have become + // true and in that case we want to allow the most decodes. + if (signals_.did_notify_all_tile_tasks_completed) { + checker_image_tracker_.SetMaxDecodePriorityAllowed( + CheckerImageTracker::DecodeType::kPreDecode); + } else if (signals_.did_notify_ready_to_activate && + signals_.did_notify_ready_to_draw) { + checker_image_tracker_.SetMaxDecodePriorityAllowed( + CheckerImageTracker::DecodeType::kRaster); + } } void TileManager::CheckIfMoreTilesNeedToBePrepared() { @@ -1326,7 +1360,7 @@ // |tiles_that_need_to_be_rasterized| will be empty when we reach a // steady memory state. Keep scheduling tasks until we reach this state. if (!work_to_schedule.tiles_to_raster.empty()) { - ScheduleTasks(work_to_schedule); + ScheduleTasks(std::move(work_to_schedule)); return; }
diff --git a/cc/tiles/tile_manager.h b/cc/tiles/tile_manager.h index 86c66c4..1b08ae0e 100644 --- a/cc/tiles/tile_manager.h +++ b/cc/tiles/tile_manager.h
@@ -104,6 +104,26 @@ // should no longer have any memory assigned to them. Tile objects are "owned" // by layers; they automatically register with the manager when they are // created, and unregister from the manager when they are deleted. +// +// The TileManager coordinates scheduling of prioritized raster and decode work +// across 2 different subsystems, namely the TaskGraphRunner used primarily for +// raster work and images which must be decoded before rasterization of a tile +// can proceed, and the CheckerImageTracker used for images decoded +// asynchronously from raster using the |image_worker_task_runner|. The order in +// which work is scheduled across these systems is as follows: +// +// 1) RequiredForActivation/Draw Tiles: These are the highest priority tiles +// which block scheduling of any decode work for checkered-images. +// +// 2) Pre-paint Tiles: These are offscreen tiles which fall within the +// pre-raster distance. The work for these tiles continues in parallel with the +// decode work for checkered images from visible/pre-paint tiles. +// +// 3) Pre-decode Tiles: These are offscreen tiles which are outside the +// pre-raster distance but have their images pre-decoded and locked. Finishing +// work for these tiles on the TaskGraph blocks starting decode work for +// checker-imaged pre-decode tiles. + class CC_EXPORT TileManager : CheckerImageTrackerClient { public: TileManager(TileManagerClient* client, @@ -332,7 +352,7 @@ scoped_refptr<TileTask> CreateTaskSetFinishedTask( void (TileManager::*callback)()); PrioritizedWorkToSchedule AssignGpuMemoryToTiles(); - void ScheduleTasks(const PrioritizedWorkToSchedule& work_to_schedule); + void ScheduleTasks(PrioritizedWorkToSchedule work_to_schedule); void PartitionImagesForCheckering(const PrioritizedTile& prioritized_tile, const gfx::ColorSpace& raster_color_space, @@ -341,6 +361,7 @@ void AddCheckeredImagesToDecodeQueue( const PrioritizedTile& prioritized_tile, const gfx::ColorSpace& raster_color_space, + CheckerImageTracker::DecodeType decode_type, CheckerImageTracker::ImageDecodeQueue* image_decode_queue); std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index cf2fbae..d497d963f 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc
@@ -2533,6 +2533,11 @@ gfx::Rect(rect_to_raster)); // Eventually rect. host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + // Finish all raster and dispatch completion callback so that the decode work + // for checkered images can be scheduled. + static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); + // Run decode tasks to trigger completion of any pending decodes. FlushDecodeTasks(); @@ -2573,7 +2578,6 @@ TEST_F(CheckerImagingTileManagerTest, TileManagerCleanupClearsCheckerImagedDecodes) { const gfx::Size layer_bounds(512, 512); - SetupDefaultTrees(layer_bounds); std::unique_ptr<FakeRecordingSource> recording_source = FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); @@ -2584,28 +2588,24 @@ scoped_refptr<RasterSource> raster_source = RasterSource::CreateFromRecordingSource(recording_source.get(), false); - std::unique_ptr<PictureLayerImpl> layer_impl = PictureLayerImpl::Create( - host_impl()->active_tree(), 1, Layer::LayerMaskType::NOT_MASK); - layer_impl->set_contributes_to_drawn_render_surface(true); - PictureLayerTilingSet* tiling_set = layer_impl->picture_layer_tiling_set(); - - PictureLayerTiling* tiling = - tiling_set->AddTiling(gfx::AxisTransform2d(), raster_source); - tiling->set_resolution(HIGH_RESOLUTION); - tiling->CreateAllTilesForTesting(); - tiling->SetTilePriorityRectsForTesting( - gfx::Rect(layer_bounds), // Visible rect. - gfx::Rect(layer_bounds), // Skewport rect. - gfx::Rect(layer_bounds), // Soon rect. - gfx::Rect(layer_bounds)); // Eventually rect. + SetupPendingTree(raster_source, gfx::Size(100, 100), + Region(gfx::Rect(0, 0, 500, 500))); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + // Finish all raster and dispatch completion callback so that the decode work + // for checkered images can be scheduled. + static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); FlushDecodeTasks(); + EXPECT_TRUE(host_impl() ->tile_manager() ->checker_image_tracker() .has_locked_decodes_for_testing()); + + host_impl()->pending_tree()->ReleaseTileResources(); CleanUpTileManager(); + EXPECT_FALSE(host_impl() ->tile_manager() ->checker_image_tracker() @@ -2614,6 +2614,75 @@ host_impl()->tile_manager()->TakeImagesToInvalidateOnSyncTree().empty()); } +TEST_F(CheckerImagingTileManagerTest, + TileManagerCorrectlyPrioritizesCheckerImagedDecodes) { + gfx::Size layer_bounds(500, 500); + + std::unique_ptr<FakeRecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); + recording_source->set_fill_with_nonsolid_color(true); + sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(512, 512)); + recording_source->add_draw_image(image, gfx::Point(0, 0)); + recording_source->Rerecord(); + scoped_refptr<RasterSource> raster_source = + RasterSource::CreateFromRecordingSource(recording_source.get(), false); + + // Required for activation tiles block checker-imaged decodes. + SetupPendingTree(raster_source, gfx::Size(100, 100), + Region(gfx::Rect(0, 0, 500, 500))); + host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + EXPECT_TRUE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting()); + EXPECT_TRUE(host_impl() + ->tile_manager() + ->checker_image_tracker() + .no_decodes_allowed_for_testing()); + while (!host_impl()->client()->ready_to_activate()) { + static_cast<SynchronousTaskGraphRunner*>(task_graph_runner()) + ->RunSingleTaskForTesting(); + base::RunLoop().RunUntilIdle(); + } + EXPECT_EQ(host_impl() + ->tile_manager() + ->checker_image_tracker() + .decode_priority_allowed_for_testing(), + CheckerImageTracker::DecodeType::kRaster); + + // Finishing all tasks allows pre-decodes. + static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(host_impl() + ->tile_manager() + ->checker_image_tracker() + .decode_priority_allowed_for_testing(), + CheckerImageTracker::DecodeType::kPreDecode); + + // Required for draw tiles block checker-imaged decodes. + // Free all tile resources and perform another PrepareTiles. + ActivateTree(); + EXPECT_TRUE(host_impl()->tile_manager()->IsReadyToDraw()); + host_impl()->tile_manager()->PrepareTiles( + GlobalStateThatImpactsTilePriority()); + EXPECT_FALSE(host_impl()->tile_manager()->IsReadyToDraw()); + + host_impl()->client()->reset_ready_to_draw(); + host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + EXPECT_TRUE(host_impl()->tile_manager()->HasScheduledTileTasksForTesting()); + EXPECT_TRUE(host_impl() + ->tile_manager() + ->checker_image_tracker() + .no_decodes_allowed_for_testing()); + while (!host_impl()->client()->ready_to_draw()) { + static_cast<SynchronousTaskGraphRunner*>(task_graph_runner()) + ->RunSingleTaskForTesting(); + base::RunLoop().RunUntilIdle(); + } + EXPECT_EQ(host_impl() + ->tile_manager() + ->checker_image_tracker() + .decode_priority_allowed_for_testing(), + CheckerImageTracker::DecodeType::kRaster); +} + class CheckerImagingTileManagerMemoryTest : public CheckerImagingTileManagerTest { public: @@ -2686,6 +2755,11 @@ complete_tiling_rect); // Eventually rect. host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); + // Finish all raster work so the decode work for checkered images can be + // scheduled. + static_cast<SynchronousTaskGraphRunner*>(task_graph_runner())->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); + // Flush all decode tasks. The tiles with checkered images should be // invalidated. FlushDecodeTasks();
diff --git a/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/cc/trees/layer_tree_host_unittest_checkerimaging.cc index 692bb747..0fe9dc1 100644 --- a/cc/trees/layer_tree_host_unittest_checkerimaging.cc +++ b/cc/trees/layer_tree_host_unittest_checkerimaging.cc
@@ -46,15 +46,6 @@ LayerTreeTest::SetupTree(); } - void FlushImageDecodeTasks() { - CompletionEvent completion_event; - image_worker_task_runner()->PostTask( - FROM_HERE, - base::BindOnce([](CompletionEvent* event) { event->Signal(); }, - base::Unretained(&completion_event))); - completion_event.Wait(); - } - private: // Accessed only on the main thread. FakeContentLayerClient content_layer_client_; @@ -73,26 +64,24 @@ } } - void ReadyToCommitOnThread(LayerTreeHostImpl* host_impl) override { - if (num_of_commits_ == 1) { - // Send the blocked invalidation request before notifying that we're ready - // to commit, since the invalidation will be merged with the commit. - host_impl->BlockImplSideInvalidationRequestsForTesting(false); - } + void DidReceiveImplSideInvalidationRequest( + LayerTreeHostImpl* host_impl) override { + if (invalidation_requested_) + return; + invalidation_requested_ = true; + + // Request a commit. + host_impl->SetNeedsCommit(); } void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { switch (++num_of_commits_) { - case 1: { - // The first commit has happened. Run all tasks on the image worker to - // ensure that the decode completion triggers an impl-side invalidation - // request. - FlushImageDecodeTasks(); - - // Block notifying the scheduler of this request until we get a commit. + case 1: + // Block notifying the scheduler of this request until we've had a + // chance to make sure that the decode work was scheduled, flushed and + // the commit requested after it is received. host_impl->BlockImplSideInvalidationRequestsForTesting(true); - host_impl->SetNeedsCommit(); - } break; + break; case 2: { // Ensure that the expected tiles are invalidated on the sync tree. PictureLayerImpl* sync_layer_impl = static_cast<PictureLayerImpl*>( @@ -102,7 +91,9 @@ ->FindTilingWithResolution(TileResolution::HIGH_RESOLUTION); for (int i = 0; i < 4; i++) { + SCOPED_TRACE(i); for (int j = 0; j < 2; j++) { + SCOPED_TRACE(j); Tile* tile = sync_tiling->TileAt(i, j) ? sync_tiling->TileAt(i, j) : nullptr; @@ -110,10 +101,12 @@ // exist and have a raster task. If its the active tree, then only // the invalidated tiles have a raster task. if (i < 3) { + ASSERT_TRUE(tile); EXPECT_TRUE(tile->HasRasterTask()); } else if (host_impl->pending_tree()) { EXPECT_EQ(tile, nullptr); } else { + ASSERT_TRUE(tile); EXPECT_FALSE(tile->HasRasterTask()); } } @@ -127,7 +120,9 @@ void AfterTest() override { EXPECT_EQ(num_of_commits_, 2); } + // Use only on impl thread. int num_of_commits_ = 0; + bool invalidation_requested_ = false; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -158,10 +153,12 @@ // exist and have a raster task. If its the active tree, then only // the invalidated tiles have a raster task. if (i < 2) { + ASSERT_TRUE(tile); EXPECT_TRUE(tile->HasRasterTask()); } else if (host_impl->pending_tree()) { EXPECT_EQ(tile, nullptr); } else { + ASSERT_TRUE(tile); EXPECT_FALSE(tile->HasRasterTask()); } }
diff --git a/chrome/android/java/res/color/checkbox_tint.xml b/chrome/android/java/res/color/checkbox_tint.xml new file mode 100644 index 0000000..cc10e11 --- /dev/null +++ b/chrome/android/java/res/color/checkbox_tint.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_checked="true" android:color="@color/light_active_color" /> + <item android:color="@color/light_normal_color"/> +</selector>
diff --git a/chrome/android/java/res/layout/menu_item.xml b/chrome/android/java/res/layout/menu_item.xml index 3fe96c92..43468c0 100644 --- a/chrome/android/java/res/layout/menu_item.xml +++ b/chrome/android/java/res/layout/menu_item.xml
@@ -6,9 +6,11 @@ --> <!-- Layout for each item in the menu popup --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto" style="@style/AppMenuItem" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeightSmall" > + <TextView android:id="@+id/menu_item_text" android:textAppearance="?android:attr/textAppearanceLargePopupMenu" @@ -19,11 +21,13 @@ android:gravity="center_vertical" android:singleLine="true" android:paddingEnd="9dp" /> + <org.chromium.chrome.browser.appmenu.AppMenuItemIcon android:id="@+id/menu_item_icon" android:layout_weight="0" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="end" - android:gravity="center_vertical" /> + android:gravity="center_vertical" + chrome:chrometint="@null" /> </LinearLayout>
diff --git a/chrome/android/java/res/layout/title_button_menu_item.xml b/chrome/android/java/res/layout/title_button_menu_item.xml index f993c84..3edbfabe4 100644 --- a/chrome/android/java/res/layout/title_button_menu_item.xml +++ b/chrome/android/java/res/layout/title_button_menu_item.xml
@@ -4,6 +4,12 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> + +<!-- Represents a menu item that can display any of the following options: + * A text label + * A text label with a checkbox indicating that it is enabled or disabled + * A text label with an icon +--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:chrome="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" @@ -21,6 +27,21 @@ android:singleLine="true" android:textAppearance="?android:attr/textAppearanceLargePopupMenu" /> + <!-- Checkbox. Paddings account for built-in padding from the Android resource. --> + <org.chromium.chrome.browser.appmenu.AppMenuItemIcon + android:id="@+id/checkbox" + android:layout_width="56dp" + android:layout_height="match_parent" + android:background="?attr/listChoiceBackgroundIndicator" + android:paddingStart="12dp" + android:paddingEnd="12dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:scaleType="fitCenter" + android:src="?android:attr/listChoiceIndicatorMultiple" + chrome:chrometint="@null" /> + + <!-- Displays an icon. --> <org.chromium.chrome.browser.widget.TintedImageButton android:id="@+id/button" android:layout_width="56dp"
diff --git a/chrome/android/java/res/layout/update_menu_item.xml b/chrome/android/java/res/layout/update_menu_item.xml index 054b0010..1d126ae 100644 --- a/chrome/android/java/res/layout/update_menu_item.xml +++ b/chrome/android/java/res/layout/update_menu_item.xml
@@ -4,6 +4,7 @@ found in the LICENSE file. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto" style="@style/AppMenuItem" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -41,6 +42,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="end" - android:gravity="center_vertical" /> + android:gravity="center_vertical" + chrome:chrometint="@null" /> </LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/res/menu/custom_tabs_menu.xml b/chrome/android/java/res/menu/custom_tabs_menu.xml index 28540e0..0510bd2 100644 --- a/chrome/android/java/res/menu/custom_tabs_menu.xml +++ b/chrome/android/java/res/menu/custom_tabs_menu.xml
@@ -45,11 +45,17 @@ <item android:id="@+id/open_webapk_id" android:title="@string/menu_open_webapk" android:orderInCategory="2" /> - <item android:id="@+id/request_desktop_site_id" - android:title="@string/menu_request_desktop_site" - android:checkable="true" - android:icon="?android:attr/listChoiceIndicatorMultiple" - android:orderInCategory="2" /> + <item android:id="@+id/request_desktop_site_row_menu_id" + android:title="@null" + android:orderInCategory="2"> + <menu> + <item android:id="@+id/request_desktop_site_id" + android:title="@string/menu_request_desktop_site" /> + <item android:id="@+id/request_desktop_site_check_id" + android:title="@null" + android:checkable="true" /> + </menu> + </item> <item android:id="@+id/open_in_browser_id" android:title="" android:orderInCategory="2" />
diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml index a491b95..3b5aa0e3 100644 --- a/chrome/android/java/res/menu/main_menu.xml +++ b/chrome/android/java/res/menu/main_menu.xml
@@ -59,10 +59,16 @@ android:title="@string/menu_add_to_homescreen" /> <item android:id="@+id/open_webapk_id" android:title="@string/menu_open_webapk" /> - <item android:id="@+id/request_desktop_site_id" - android:title="@string/menu_request_desktop_site" - android:checkable="true" - android:icon="?android:attr/listChoiceIndicatorMultiple" /> + <item android:id="@+id/request_desktop_site_row_menu_id" + android:title="@null"> + <menu> + <item android:id="@+id/request_desktop_site_id" + android:title="@string/menu_request_desktop_site" /> + <item android:id="@+id/request_desktop_site_check_id" + android:title="@null" + android:checkable="true" /> + </menu> + </item> <item android:id="@+id/reader_mode_prefs_id" android:title="@string/menu_reader_mode_prefs" android:icon="@drawable/reader_mode_prefs_icon" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 90ceaec..d6093c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1947,7 +1947,7 @@ if (launchFailed) { Toast.makeText(context, R.string.open_webapk_failed, Toast.LENGTH_SHORT).show(); } - } else if (id == R.id.request_desktop_site_id) { + } else if (id == R.id.request_desktop_site_id || id == R.id.request_desktop_site_check_id) { final boolean reloadOnChange = !currentTab.isNativePage(); final boolean usingDesktopUserAgent = currentTab.getUseDesktopUserAgent(); currentTab.setUseDesktopUserAgent(!usingDesktopUserAgent, reloadOnChange);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java index c6587af..e2b5d39 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -228,26 +228,31 @@ break; } case TITLE_BUTTON_MENU_ITEM: { + assert item.hasSubMenu(); + final MenuItem titleItem = item.getSubMenu().getItem(0); + final MenuItem subItem = item.getSubMenu().getItem(1); + TitleButtonMenuItemViewHolder holder = null; if (convertView == null || !(convertView.getTag() instanceof TitleButtonMenuItemViewHolder)) { - holder = new TitleButtonMenuItemViewHolder(); convertView = mInflater.inflate(R.layout.title_button_menu_item, parent, false); + + holder = new TitleButtonMenuItemViewHolder(); holder.title = (TextView) convertView.findViewById(R.id.title); + holder.checkbox = (AppMenuItemIcon) convertView.findViewById(R.id.checkbox); holder.button = (TintedImageButton) convertView.findViewById(R.id.button); holder.button.setTag( R.id.menu_item_original_background, holder.button.getBackground()); - View animatedView = convertView; convertView.setTag(holder); convertView.setTag(R.id.menu_item_enter_anim_id, - buildStandardItemEnterAnimator(animatedView, position)); + buildStandardItemEnterAnimator(convertView, position)); convertView.setTag( R.id.menu_item_original_background, convertView.getBackground()); } else { holder = (TitleButtonMenuItemViewHolder) convertView.getTag(); } - final MenuItem titleItem = item.hasSubMenu() ? item.getSubMenu().getItem(0) : item; + holder.title.setText(titleItem.getTitle()); holder.title.setEnabled(titleItem.isEnabled()); holder.title.setFocusable(titleItem.isEnabled()); @@ -258,12 +263,22 @@ } }); - if (item.getSubMenu().getItem(1).getIcon() != null) { + if (subItem.isCheckable()) { + // Display a checkbox for the MenuItem. + holder.checkbox.setVisibility(View.VISIBLE); + holder.button.setVisibility(View.GONE); + setupCheckBox(holder.checkbox, subItem); + } else if (subItem.getIcon() != null) { + // Display an icon alongside the MenuItem. + holder.checkbox.setVisibility(View.GONE); holder.button.setVisibility(View.VISIBLE); - setupImageButton(holder.button, item.getSubMenu().getItem(1)); + setupImageButton(holder.button, subItem); } else { + // Display just the label of the MenuItem. + holder.checkbox.setVisibility(View.GONE); holder.button.setVisibility(View.GONE); } + convertView.setFocusable(false); convertView.setEnabled(false); break; @@ -277,16 +292,33 @@ return convertView; } + private void setupCheckBox(AppMenuItemIcon button, final MenuItem item) { + button.setChecked(item.isChecked()); + + // The checkbox must be tinted to make Android consistently style it across OS versions. + // http://crbug.com/571445 + button.setTint(ApiCompatibilityUtils.getColorStateList( + button.getResources(), R.color.checkbox_tint)); + + setupMenuButton(button, item); + } + private void setupImageButton(TintedImageButton button, final MenuItem item) { // Store and recover the level of image as button.setimageDrawable // resets drawable to default level. int currentLevel = item.getIcon().getLevel(); button.setImageDrawable(item.getIcon()); item.getIcon().setLevel(currentLevel); + if (item.isChecked()) { button.setTint(ApiCompatibilityUtils.getColorStateList( button.getResources(), R.color.blue_mode_tint)); } + + setupMenuButton(button, item); + } + + private void setupMenuButton(View button, final MenuItem item) { button.setEnabled(item.isEnabled()); button.setFocusable(item.isEnabled()); button.setContentDescription(item.getTitleCondensed()); @@ -497,6 +529,7 @@ static class TitleButtonMenuItemViewHolder { public TextView title; + public AppMenuItemIcon checkbox; public TintedImageButton button; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java index f3b0b10..47b3980 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuItemIcon.java
@@ -6,12 +6,14 @@ import android.content.Context; import android.util.AttributeSet; -import android.widget.ImageView; +import android.widget.Checkable; + +import org.chromium.chrome.browser.widget.TintedImageView; /** - * A menu icon that supports the checkable state. + * A TintedImageView that supports the checkable state. */ -public class AppMenuItemIcon extends ImageView { +public class AppMenuItemIcon extends TintedImageView implements Checkable { private static final int[] CHECKED_STATE_SET = new int[] {android.R.attr.state_checked}; private boolean mCheckedState; @@ -19,23 +21,14 @@ super(context, attrs); } - /** - * Sets whether the item is checked and refreshes the View if necessary. - */ - protected void setChecked(boolean state) { + @Override + public void setChecked(boolean state) { if (state == mCheckedState) return; mCheckedState = state; refreshDrawableState(); } @Override - public void setPressed(boolean state) { - // We don't want to highlight the checkbox icon since the parent item is already - // highlighted. - return; - } - - @Override public int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (mCheckedState) { @@ -43,4 +36,14 @@ } return drawableState; } + + @Override + public boolean isChecked() { + return mCheckedState; + } + + @Override + public void toggle() { + setChecked(!mCheckedState); + } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java index 52306bc..a537cfd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -178,10 +178,7 @@ && !isChromeScheme && !isFileScheme && !isContentScheme && !isIncognito; prepareAddToHomescreenMenuItem(menu, currentTab, canShowHomeScreenMenuItem); - // Hide request desktop site on all chrome:// pages except for the NTP. Check request - // desktop site if it's activated on this page. - MenuItem requestItem = menu.findItem(R.id.request_desktop_site_id); - updateRequestDesktopSiteMenuItem(requestItem, currentTab); + updateRequestDesktopSiteMenuItem(menu, currentTab); // Only display reader mode settings menu option if the current page is in reader mode. menu.findItem(R.id.reader_mode_prefs_id) @@ -367,20 +364,29 @@ } /** - * Updates the request desktop site item's visibility + * Updates the request desktop site item's state. * * @param requstMenuItem {@link MenuItem} for request desktop site. * @param currentTab Current tab being displayed. */ - protected void updateRequestDesktopSiteMenuItem( - MenuItem requstMenuItem, Tab currentTab) { + protected void updateRequestDesktopSiteMenuItem(Menu menu, Tab currentTab) { + MenuItem requestMenuRow = menu.findItem(R.id.request_desktop_site_row_menu_id); + MenuItem requestMenuLabel = menu.findItem(R.id.request_desktop_site_id); + MenuItem requestMenuCheck = menu.findItem(R.id.request_desktop_site_check_id); + + // Hide request desktop site on all chrome:// pages except for the NTP. String url = currentTab.getUrl(); boolean isChromeScheme = url.startsWith(UrlConstants.CHROME_URL_PREFIX) || url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX); - requstMenuItem.setVisible(!isChromeScheme || currentTab.isNativePage()); - requstMenuItem.setChecked(currentTab.getUseDesktopUserAgent()); - requstMenuItem.setTitleCondensed(requstMenuItem.isChecked() - ? mActivity.getString(R.string.menu_request_desktop_site_on) - : mActivity.getString(R.string.menu_request_desktop_site_off)); + requestMenuRow.setVisible(!isChromeScheme || currentTab.isNativePage()); + + // Mark the checkbox if RDS is activated on this page. + requestMenuCheck.setChecked(currentTab.getUseDesktopUserAgent()); + + // This title doesn't seem to be displayed by Android, but it is used to set up + // accessibility text in {@link AppMenuAdapter#setupMenuButton}. + requestMenuLabel.setTitleCondensed(requestMenuLabel.isChecked() + ? mActivity.getString(R.string.menu_request_desktop_site_on) + : mActivity.getString(R.string.menu_request_desktop_site_off)); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java index 56f68ac..de634b39 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionActivity.java
@@ -88,7 +88,7 @@ @Override public void openContextMenu(View view) { ContextMenuParams params = createContextMenuParams(); - mHelper = new BrowserActionsContextMenuHelper(this, params, mActions); + mHelper = new BrowserActionsContextMenuHelper(this, params, mActions, mCreatorPackageName); mHelper.displayBrowserActionsMenu(view); return; } @@ -155,4 +155,11 @@ mHelper.onContextMenuClosed(); } } + + /** + * @return the package name of the requesting app. + */ + public String getCreatorPackageName() { + return mCreatorPackageName; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java index 19a170b..871c950 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.contextmenu.ContextMenuParams; import org.chromium.chrome.browser.contextmenu.ContextMenuUi; import org.chromium.chrome.browser.contextmenu.PlatformContextMenuUi; +import org.chromium.chrome.browser.contextmenu.ShareContextMenuItem; import org.chromium.chrome.browser.contextmenu.TabularContextMenuUi; import org.chromium.ui.base.WindowAndroid.OnCloseContextMenuListener; @@ -37,19 +38,14 @@ OnAttachStateChangeListener { private static final boolean IS_NEW_UI_ENABLED = true; - // Items list that could be included in the Browser Actions context menu for type {@code LINK}. - private static final List<? extends ContextMenuItem> BROWSER_ACTIONS_LINK_GROUP = - Arrays.asList(ChromeContextMenuItem.BROWSER_ACTIONS_OPEN_IN_BACKGROUND, - ChromeContextMenuItem.BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB, - ChromeContextMenuItem.BROWSER_ACTION_SAVE_LINK_AS, - ChromeContextMenuItem.BROWSER_ACTIONS_COPY_ADDRESS, - ChromeContextMenuItem.BROWSER_ACTIONS_SHARE); - private static final List<Integer> CUSTOM_BROWSER_ACTIONS_ID_GROUP = Arrays.asList(R.id.browser_actions_custom_item_one, R.id.browser_actions_custom_item_two, R.id.browser_actions_custom_item_three, R.id.browser_actions_custom_item_four, R.id.browser_actions_custom_item_five); + // Items list that could be included in the Browser Actions context menu for type {@code LINK}. + private final List<? extends ContextMenuItem> mBrowserActionsLinkGroup; + // Map each custom item's id with its PendingIntent action. private final SparseArray<PendingIntent> mCustomItemActionMap = new SparseArray<>(); @@ -59,12 +55,12 @@ private final Callback<Integer> mItemSelectedCallback; private final Runnable mOnMenuShown; private final Runnable mOnMenuClosed; - private final Runnable mOnShareClickedRunnable; + private final Callback<Boolean> mOnShareClickedRunnable; private final List<Pair<Integer, List<ContextMenuItem>>> mItems; public BrowserActionsContextMenuHelper(BrowserActionActivity activity, ContextMenuParams params, - List<BrowserActionItem> customItems) { + List<BrowserActionItem> customItems, String sourcePackageName) { mActivity = activity; mCurrentContextMenuParams = params; mOnMenuShown = new Runnable() { @@ -85,11 +81,22 @@ onItemSelected(result); } }; - mOnShareClickedRunnable = new Runnable() { + mOnShareClickedRunnable = new Callback<Boolean>() { @Override - public void run() {} + public void onResult(Boolean isShareLink) { + mDelegate.share(true, mCurrentContextMenuParams.getLinkUrl()); + } }; - mDelegate = new BrowserActionsContextMenuItemDelegate(); + ShareContextMenuItem shareItem = new ShareContextMenuItem(R.drawable.ic_share_white_24dp, + R.string.browser_actions_share, R.id.browser_actions_share, true); + shareItem.setCreatorPackageName(sourcePackageName); + mBrowserActionsLinkGroup = + Arrays.asList(ChromeContextMenuItem.BROWSER_ACTIONS_OPEN_IN_BACKGROUND, + ChromeContextMenuItem.BROWSER_ACTIONS_OPEN_IN_INCOGNITO_TAB, + ChromeContextMenuItem.BROWSER_ACTION_SAVE_LINK_AS, + ChromeContextMenuItem.BROWSER_ACTIONS_COPY_ADDRESS, shareItem); + mDelegate = new BrowserActionsContextMenuItemDelegate(mActivity, sourcePackageName); + mItems = buildContextMenuItems(customItems); } @@ -100,7 +107,7 @@ List<BrowserActionItem> customItems) { List<Pair<Integer, List<ContextMenuItem>>> menuItems = new ArrayList<>(); List<ContextMenuItem> items = new ArrayList<>(); - items.addAll(BROWSER_ACTIONS_LINK_GROUP); + items.addAll(mBrowserActionsLinkGroup); addBrowserActionItems(items, customItems); menuItems.add(new Pair<>(R.string.contextmenu_link_title, items)); @@ -132,7 +139,7 @@ } else if (itemId == R.id.browser_actions_copy_address) { mDelegate.onSaveToClipboard(mCurrentContextMenuParams.getLinkUrl()); } else if (itemId == R.id.browser_actions_share) { - mDelegate.share(mCurrentContextMenuParams.getLinkUrl()); + mDelegate.share(false, mCurrentContextMenuParams.getLinkUrl()); } else if (mCustomItemActionMap.indexOfKey(itemId) >= 0) { mDelegate.onCustomItemSelected(mCustomItemActionMap.get(itemId)); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java index 7c2bd87ed..7d3f8ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.browseractions; +import android.app.Activity; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; @@ -25,6 +26,8 @@ import org.chromium.chrome.browser.notifications.NotificationConstants; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; +import org.chromium.chrome.browser.share.ShareHelper; +import org.chromium.chrome.browser.share.ShareParams; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.ui.widget.Toast; @@ -50,9 +53,23 @@ public static final String EXTRA_IS_SINGLE_URL = "org.chromium.chrome.browser.browseractions.is_single_url"; - private final Context mContext; + private final Activity mActivity; private final NotificationManager mNotificationManager; private final SharedPreferences mSharedPreferences; + private final String mSourcePackageName; + + /** + * Builds a {@link BrowserActionsContextMenuItemDelegate} instance. + * @param activity The activity displays the context menu. + * @param sourcePackageName The package name of the app which requests the Browser Actions. + */ + public BrowserActionsContextMenuItemDelegate(Activity activity, String sourcePackageName) { + mActivity = activity; + mNotificationManager = + (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE); + mSharedPreferences = ContextUtils.getAppSharedPreferences(); + mSourcePackageName = sourcePackageName; + } private void sendBrowserActionsNotification() { ChromeNotificationBuilder builder = createNotificationBuilder(); @@ -72,20 +89,20 @@ .setLocalOnly(true) .setAutoCancel(true) .setContentText( - mContext.getString(R.string.browser_actions_notification_text)); + mActivity.getString(R.string.browser_actions_notification_text)); int titleResId = hasBrowserActionsNotification() ? R.string.browser_actions_multi_links_open_notification_title : R.string.browser_actions_single_link_open_notification_title; - builder.setContentTitle(mContext.getString(titleResId)); + builder.setContentTitle(mActivity.getString(titleResId)); Intent intent = buildNotificationIntent(); PendingIntent notifyPendingIntent = - PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(notifyPendingIntent); return builder; } private Intent buildNotificationIntent() { - Intent intent = new Intent(mContext, ChromeLauncherActivity.class); + Intent intent = new Intent(mActivity, ChromeLauncherActivity.class); intent.setAction(ACTION_BROWSER_ACTIONS_OPEN_IN_BACKGROUND); intent.putExtra(EXTRA_IS_SINGLE_URL, !hasBrowserActionsNotification()); return intent; @@ -96,22 +113,12 @@ } /** - * Builds a {@link BrowserActionsContextMenuItemDelegate} instance. - */ - public BrowserActionsContextMenuItemDelegate() { - mContext = ContextUtils.getApplicationContext(); - mNotificationManager = - (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - mSharedPreferences = ContextUtils.getAppSharedPreferences(); - } - - /** * Called when the {@code text} should be saved to the clipboard. * @param text The text to save to the clipboard. */ public void onSaveToClipboard(String text) { ClipboardManager clipboardManager = - (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); + (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE); ClipData data = ClipData.newPlainText("url", text); clipboardManager.setPrimaryClip(data); } @@ -123,13 +130,13 @@ public void onOpenInIncognitoTab(String linkUrl) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setPackage(mContext.getPackageName()); + intent.setPackage(mActivity.getPackageName()); intent.putExtra(ChromeLauncherActivity.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, false); intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName()); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, mActivity.getPackageName()); IntentHandler.addTrustedIntentExtras(intent); IntentHandler.setTabLaunchType(intent, TabLaunchType.FROM_EXTERNAL_APP); - IntentUtils.safeStartActivity(mContext, intent); + IntentUtils.safeStartActivity(mActivity, intent); } /** @@ -138,7 +145,7 @@ */ public void onOpenInBackground(String linkUrl) { sendBrowserActionsNotification(); - Toast.makeText(mContext, R.string.browser_actions_open_in_background_toast_message, + Toast.makeText(mActivity, R.string.browser_actions_open_in_background_toast_message, Toast.LENGTH_SHORT) .show(); } @@ -163,9 +170,18 @@ /** * Called when the {@code linkUrl} should be shared. + * @param shareDirectly Whether to share directly with the previous app shared with. * @param linkUrl The url to share. */ - public void share(String linkUrl) {} + public void share(Boolean shareDirectly, String linkUrl) { + ShareParams params = new ShareParams.Builder(mActivity, linkUrl, linkUrl) + .setShareDirectly(shareDirectly) + .setSaveLastUsed(!shareDirectly) + .setSourcePackageName(mSourcePackageName) + .setIsExternalUrl(true) + .build(); + ShareHelper.share(params); + } /** * Cancel Browser Actions notification.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java index b9237c3..a5a3058 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
@@ -39,8 +39,6 @@ R.id.contextmenu_copy_link_address), SAVE_LINK_AS(R.drawable.ic_file_download_white_24dp, R.string.contextmenu_save_link, R.id.contextmenu_save_link_as), - SHARE_LINK(R.drawable.ic_share_white_24dp, R.string.contextmenu_share_link, - R.id.contextmenu_share_link), // Image Group LOAD_ORIGINAL_IMAGE(R.drawable.context_menu_load_image, @@ -53,8 +51,6 @@ R.string.contextmenu_open_image_in_new_tab, R.id.contextmenu_open_image_in_new_tab), SEARCH_BY_IMAGE(R.drawable.context_menu_search, R.string.contextmenu_search_web_for_image, R.id.contextmenu_search_by_image), - SHARE_IMAGE(R.drawable.ic_share_white_24dp, R.string.contextmenu_share_image, - R.id.contextmenu_share_image), // Message Group CALL(R.drawable.ic_phone_googblue_36dp, R.string.contextmenu_call, R.id.contextmenu_call), @@ -81,9 +77,7 @@ BROWSER_ACTION_SAVE_LINK_AS(R.drawable.ic_file_download_white_24dp, R.string.browser_actions_save_link_as, R.id.browser_actions_save_link_as), BROWSER_ACTIONS_COPY_ADDRESS(R.drawable.ic_content_copy, R.string.browser_actions_copy_address, - R.id.browser_actions_copy_address), - BROWSER_ACTIONS_SHARE(R.drawable.ic_share_white_24dp, R.string.browser_actions_share, - R.id.browser_actions_share); + R.id.browser_actions_copy_address); @DrawableRes private final int mIconId;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java index 5ffa5586..42f3af6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -43,6 +43,12 @@ */ public class ChromeContextMenuPopulator implements ContextMenuPopulator { private static final String TAG = "CCMenuPopulator"; + private static final ShareContextMenuItem SHARE_IMAGE = + new ShareContextMenuItem(R.drawable.ic_share_white_24dp, + R.string.contextmenu_share_image, R.id.contextmenu_share_image, false); + private static final ShareContextMenuItem SHARE_LINK = + new ShareContextMenuItem(R.drawable.ic_share_white_24dp, + R.string.contextmenu_share_link, R.id.contextmenu_share_link, true); /** * Defines the Groups of each Context Menu Item @@ -77,8 +83,7 @@ ChromeContextMenuItem.SEND_MESSAGE, ChromeContextMenuItem.ADD_TO_CONTACTS, ChromeContextMenuItem.COPY, ChromeContextMenuItem.LOAD_ORIGINAL_IMAGE, ChromeContextMenuItem.SAVE_LINK_AS, ChromeContextMenuItem.SAVE_IMAGE, - ChromeContextMenuItem.SHARE_IMAGE, ChromeContextMenuItem.SAVE_VIDEO, - ChromeContextMenuItem.SHARE_LINK)); + SHARE_IMAGE, ChromeContextMenuItem.SAVE_VIDEO, SHARE_LINK)); // Items that are included for normal Chrome browser mode. private static final Set<? extends ContextMenuItem> NORMAL_MODE_WHITELIST = @@ -113,13 +118,13 @@ CollectionUtil.newArrayList(ChromeContextMenuItem.OPEN_IN_OTHER_WINDOW, ChromeContextMenuItem.OPEN_IN_NEW_TAB, ChromeContextMenuItem.OPEN_IN_INCOGNITO_TAB, ChromeContextMenuItem.SAVE_LINK_AS, - ChromeContextMenuItem.COPY_LINK_ADDRESS, ChromeContextMenuItem.SHARE_LINK)); + ChromeContextMenuItem.COPY_LINK_ADDRESS, SHARE_LINK)); private static final List<? extends ContextMenuItem> IMAGE_GROUP = Collections.unmodifiableList(CollectionUtil.newArrayList( ChromeContextMenuItem.LOAD_ORIGINAL_IMAGE, ChromeContextMenuItem.OPEN_IMAGE, ChromeContextMenuItem.OPEN_IMAGE_IN_NEW_TAB, ChromeContextMenuItem.SAVE_IMAGE, - ChromeContextMenuItem.SEARCH_BY_IMAGE, ChromeContextMenuItem.SHARE_IMAGE)); + ChromeContextMenuItem.SEARCH_BY_IMAGE, SHARE_IMAGE)); private static final List<? extends ContextMenuItem> MESSAGE_GROUP = Collections.unmodifiableList(CollectionUtil.newArrayList(ChromeContextMenuItem.CALL, @@ -507,7 +512,7 @@ disabledOptions.add(ChromeContextMenuItem.SAVE_IMAGE); disabledOptions.add(ChromeContextMenuItem.OPEN_IMAGE); disabledOptions.add(ChromeContextMenuItem.SEARCH_BY_IMAGE); - disabledOptions.add(ChromeContextMenuItem.SHARE_IMAGE); + disabledOptions.add(SHARE_IMAGE); recordSaveImageContextMenuResult(true, isSrcDownloadableScheme); } else if (params.isImage() && !params.imageWasFetchedLoFi()) { disabledOptions.add(ChromeContextMenuItem.LOAD_ORIGINAL_IMAGE); @@ -533,8 +538,8 @@ if (mMode == CUSTOM_TAB_MODE) { try { - URI uri = new URI(getUrl(params)); - if (UrlUtilities.isInternalScheme(uri) || isEmptyUrl(getUrl(params))) { + URI uri = new URI(params.getUrl()); + if (UrlUtilities.isInternalScheme(uri) || isEmptyUrl(params.getUrl())) { disabledOptions.add(ChromeContextMenuItem.OPEN_IN_NEW_CHROME_TAB); disabledOptions.add(ChromeContextMenuItem.OPEN_IN_CHROME_INCOGNITO_TAB); disabledOptions.add(ChromeContextMenuItem.OPEN_IN_BROWSER_ID); @@ -630,9 +635,9 @@ } else if (itemId == R.id.contextmenu_share_link) { ContextMenuUma.record(params, ContextMenuUma.ACTION_SHARE_LINK); ShareParams linkShareParams = - new ShareParams - .Builder(helper.getActivity(), params.getLinkUrl(), - params.getTitleText()) + new ShareParams.Builder(helper.getActivity(), params.getUrl(), params.getUrl()) + .setShareDirectly(false) + .setSaveLastUsed(true) .build(); ShareHelper.share(linkShareParams); } else if (itemId == R.id.contextmenu_search_by_image) { @@ -646,13 +651,13 @@ mDelegate.onOpenInChrome(params.getLinkUrl(), params.getPageUrl()); } else if (itemId == R.id.contextmenu_open_in_new_chrome_tab) { ContextMenuUma.record(params, ContextMenuUma.ACTION_OPEN_IN_NEW_CHROME_TAB); - mDelegate.onOpenInNewChromeTabFromCCT(getUrl(params), false); + mDelegate.onOpenInNewChromeTabFromCCT(params.getUrl(), false); } else if (itemId == R.id.contextmenu_open_in_chrome_incognito_tab) { ContextMenuUma.record(params, ContextMenuUma.ACTION_OPEN_IN_CHROME_INCOGNITO_TAB); - mDelegate.onOpenInNewChromeTabFromCCT(getUrl(params), true); + mDelegate.onOpenInNewChromeTabFromCCT(params.getUrl(), true); } else if (itemId == R.id.contextmenu_open_in_browser_id) { ContextMenuUma.record(params, ContextMenuUma.ACTION_OPEN_IN_BROWSER); - mDelegate.onOpenInDefaultBrowser(getUrl(params)); + mDelegate.onOpenInDefaultBrowser(params.getUrl()); } else { assert false; } @@ -693,20 +698,6 @@ } /** - * Return the valid url of a ContextMenuParams. - * If the ContextMenuParams is an anchor and its linkUrl is not empty, returns the linkUrl. - * Otherwise returns the srcUrl. - * @param params The {@link ContextMenuParams} to check. - */ - private String getUrl(ContextMenuParams params) { - if (params.isAnchor()) { - return params.getLinkUrl(); - } else { - return params.getSrcUrl(); - } - } - - /** * Record the UMA related to save image context menu option. * @param wasFetchedLoFi The image was fectched LoFi. * @param isDownloadableScheme The image is downloadable.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java index 0c1dd75..a38c28e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.share.ShareHelper; +import org.chromium.chrome.browser.share.ShareParams; import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.WindowAndroid; @@ -83,7 +84,8 @@ * @param params The {@link ContextMenuParams} that indicate what menu items to show. */ @CalledByNative - private void showContextMenu(final ContentViewCore contentViewCore, ContextMenuParams params) { + private void showContextMenu( + final ContentViewCore contentViewCore, final ContextMenuParams params) { if (params.isFile()) return; View view = contentViewCore.getContainerView(); final WindowAndroid windowAndroid = contentViewCore.getWindowAndroid(); @@ -126,10 +128,19 @@ return; } - final TabularContextMenuUi menuUi = new TabularContextMenuUi(new Runnable() { + final TabularContextMenuUi menuUi = new TabularContextMenuUi(new Callback<Boolean>() { @Override - public void run() { - shareImageDirectly(ShareHelper.getLastShareComponentName()); + public void onResult(Boolean isShareLink) { + if (isShareLink) { + ShareParams shareParams = + new ShareParams.Builder(mActivity, params.getUrl(), params.getUrl()) + .setShareDirectly(true) + .setSaveLastUsed(false) + .build(); + ShareHelper.share(shareParams); + } else { + shareImageDirectly(ShareHelper.getLastShareComponentName(null)); + } } }); menuUi.setRenderCoordinates(contentViewCore.getRenderCoordinates());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java index f6e7d95..29ae5a2c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
@@ -152,6 +152,17 @@ return mTriggeringTouchYDp; } + /** + * @return The valid url of a ContextMenuParams. + */ + public String getUrl() { + if (isAnchor() && !TextUtils.isEmpty(getLinkUrl())) { + return getLinkUrl(); + } else { + return getSrcUrl(); + } + } + public ContextMenuParams(int mediaType, String pageUrl, String linkUrl, String linkText, String unfilteredLinkUrl, String srcUrl, String titleText, boolean imageWasFetchedLoFi, Referrer referrer, boolean canSaveMedia, int triggeringTouchXDp,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java new file mode 100644 index 0000000..c3741ea9 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java
@@ -0,0 +1,85 @@ +// 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.contextmenu; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; +import android.support.annotation.IdRes; +import android.support.annotation.StringRes; +import android.util.Pair; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.share.ShareHelper; +import org.chromium.chrome.browser.widget.TintedDrawable; + +/** + * List of all predefined Context Menu Items for share in Chrome. + */ +public class ShareContextMenuItem implements ContextMenuItem { + @DrawableRes + private final int mIconId; + @StringRes + private final int mStringId; + @IdRes + private final int mMenuId; + private final boolean mIsShareLink; + private String mCreatorPackageName; + + /** + * A representation of a Context Menu Item. Each item should have a string and an id associated + * with it. + * @param iconId The icon that appears in {@link TabularContextMenuUi} to represent each item. + * @param stringId The string that describes the action of the item. + * @param menuId The id found in ids.xml. + * @param isShareLink Whether the menu is for sharing a link. + */ + public ShareContextMenuItem(@DrawableRes int iconId, @StringRes int stringId, @IdRes int menuId, + boolean isShareLink) { + mIconId = iconId; + mStringId = stringId; + mMenuId = menuId; + mIsShareLink = isShareLink; + } + + /** + * Set the package name of the app who requests for share. If Null, it is requested by Chrome. + */ + public void setCreatorPackageName(String creatorPackageName) { + mCreatorPackageName = creatorPackageName; + } + + @Override + public String getTitle(Context context) { + return context.getString(mStringId); + } + + @Override + public Drawable getDrawable(Context context) { + return TintedDrawable.constructTintedDrawable( + context.getResources(), mIconId, R.color.light_normal_color); + } + + @Override + public int getMenuId() { + return mMenuId; + } + + /** + * Return whether this menu is for sharing a link. + */ + public boolean isShareLink() { + return mIsShareLink; + } + + /** + * Return the icon and name of the most recently shared app by certain app. + */ + public Pair<Drawable, CharSequence> getShareInfo() { + Intent shareIntent = mIsShareLink ? ShareHelper.getShareLinkAppCompatibilityIntent() + : ShareHelper.getShareImageIntent(null); + return ShareHelper.getShareableIconAndName(shareIntent, mCreatorPackageName); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java index 79365e3..0489d80 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuListAdapter.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.contextmenu; import android.app.Activity; -import android.content.Intent; import android.graphics.drawable.Drawable; import android.util.Pair; import android.view.LayoutInflater; @@ -16,8 +15,8 @@ import android.widget.Space; import android.widget.TextView; +import org.chromium.base.Callback; import org.chromium.chrome.R; -import org.chromium.chrome.browser.share.ShareHelper; import java.util.List; @@ -28,15 +27,16 @@ class TabularContextMenuListAdapter extends BaseAdapter { private final List<ContextMenuItem> mMenuItems; private final Activity mActivity; - private final Runnable mOnDirectShare; + private final Callback<Boolean> mOnDirectShare; /** * Adapter for the tabular context menu UI * @param menuItems The list of items to display in the view. * @param activity Used to inflate the layout. + * @param onDirectShare Callback to handle direct share. */ TabularContextMenuListAdapter( - List<ContextMenuItem> menuItems, Activity activity, Runnable onDirectShare) { + List<ContextMenuItem> menuItems, Activity activity, Callback<Boolean> onDirectShare) { mMenuItems = menuItems; mActivity = activity; mOnDirectShare = onDirectShare; @@ -59,7 +59,7 @@ @Override public View getView(int position, View convertView, ViewGroup parent) { - ContextMenuItem menuItem = mMenuItems.get(position); + final ContextMenuItem menuItem = mMenuItems.get(position); ViewHolderItem viewHolder; if (convertView == null) { @@ -84,10 +84,9 @@ viewHolder.mIcon.setImageDrawable(icon); viewHolder.mIcon.setVisibility(icon != null ? View.VISIBLE : View.INVISIBLE); - if (menuItem == ChromeContextMenuItem.SHARE_IMAGE) { - Intent shareIntent = ShareHelper.getShareImageIntent(null); + if (menuItem instanceof ShareContextMenuItem) { final Pair<Drawable, CharSequence> shareInfo = - ShareHelper.getShareableIconAndName(mActivity, shareIntent); + ((ShareContextMenuItem) menuItem).getShareInfo(); if (shareInfo.first != null) { viewHolder.mShareIcon.setImageDrawable(shareInfo.first); viewHolder.mShareIcon.setVisibility(View.VISIBLE); @@ -96,7 +95,7 @@ viewHolder.mShareIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - mOnDirectShare.run(); + mOnDirectShare.onResult(((ShareContextMenuItem) menuItem).isShareLink()); } }); viewHolder.mRightPadding.setVisibility(View.GONE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java index 6e11f96..f965262 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUi.java
@@ -43,11 +43,11 @@ private Callback<Integer> mCallback; private int mMenuItemHeight; private ImageView mHeaderImageView; - private Runnable mOnShareItemClicked; + private Callback<Boolean> mOnShareItemClicked; private View mPagerView; private RenderCoordinates mRenderCoordinates; - public TabularContextMenuUi(Runnable onShareItemClicked) { + public TabularContextMenuUi(Callback<Boolean> onShareItemClicked) { mOnShareItemClicked = onShareItemClicked; } @@ -172,10 +172,10 @@ } // Set the list adapter and get the height to display it appropriately in a dialog. - Runnable onDirectShare = new Runnable() { + Callback<Boolean> onDirectShare = new Callback<Boolean>() { @Override - public void run() { - mOnShareItemClicked.run(); + public void onResult(Boolean isShareLink) { + mOnShareItemClicked.onResult(isShareLink); mContextMenuDialog.dismiss(); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java index a4399c8..9b4a58d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
@@ -87,7 +87,7 @@ */ Drawable getIcon(Resources res) { if (mShouldTint) { - return TintedDrawable.constructTintedDrawable(res, mIcon); + return new TintedDrawable(res, mIcon); } else { return new BitmapDrawable(res, mIcon); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java index e13619d..d6f8879 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -82,18 +82,14 @@ MenuItem downloadItem = menu.findItem(R.id.offline_page_id); boolean addToHomeScreenVisible = true; - - // Hide request desktop site on all chrome:// pages except for the NTP. Check request - // desktop site if it's activated on this page. - MenuItem requestItem = menu.findItem(R.id.request_desktop_site_id); - updateRequestDesktopSiteMenuItem(requestItem, currentTab); + updateRequestDesktopSiteMenuItem(menu, currentTab); if (mIsMediaViewer) { // Most of the menu items don't make sense when viewing media. iconRow.setVisible(false); openInChromeItem.setVisible(false); menu.findItem(R.id.find_in_page_id).setVisible(false); - menu.findItem(R.id.request_desktop_site_id).setVisible(false); + menu.findItem(R.id.request_desktop_site_row_menu_id).setVisible(false); addToHomeScreenVisible = false; } else if (mIsPaymentRequestUI) { // Only the icon row and 'find in page' are shown for openning payment request UI
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java index 8d4fcd5..80989ec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
@@ -6,9 +6,10 @@ import android.content.ContentResolver; import android.database.Cursor; +import android.database.sqlite.SQLiteException; import android.net.Uri; -import android.util.Log; +import org.chromium.base.Log; import org.chromium.chrome.browser.UrlConstants; import java.util.NoSuchElementException; @@ -17,8 +18,7 @@ * Imports bookmarks from partner content provider using the private provider API. */ public class PartnerBookmarksProviderIterator implements PartnerBookmarksReader.BookmarkIterator { - - private static final String TAG = "PartnerBookmarksProviderIterator"; + private static final String TAG = "cr_PartnerBookmarks"; private static final String PROVIDER_AUTHORITY = "com.android.partnerbookmarks"; private static final Uri CONTENT_URI = new Uri.Builder() .scheme(UrlConstants.CONTENT_SCHEME) @@ -64,10 +64,15 @@ */ public static PartnerBookmarksProviderIterator createIfAvailable( ContentResolver contentResolver) { - Cursor cursor = contentResolver.query(BOOKMARKS_CONTENT_URI, - BOOKMARKS_PROJECTION, null, null, BOOKMARKS_SORT_ORDER); - if (cursor == null) return null; - return new PartnerBookmarksProviderIterator(cursor); + try { + Cursor cursor = contentResolver.query( + BOOKMARKS_CONTENT_URI, BOOKMARKS_PROJECTION, null, null, BOOKMARKS_SORT_ORDER); + if (cursor == null) return null; + return new PartnerBookmarksProviderIterator(cursor); + } catch (SQLiteException ex) { + Log.e(TAG, "Unable to read partner bookmark database", ex); + return null; + } } private PartnerBookmarksProviderIterator(Cursor cursor) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java index 16309af..c6284a3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -44,9 +44,8 @@ import org.chromium.base.StreamUtil; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.SuppressFBWarnings; -import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.CachedMetrics; import org.chromium.chrome.R; -import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.ui.UiUtils; import java.io.File; @@ -62,6 +61,7 @@ * A helper class that helps to start an intent to share titles and URLs. */ public class ShareHelper { + static final String EXTERNAL_APP_SHARING_PREF_FILE_NAME = "external_app_sharing"; /** Interface that receives intents for testing (to fake out actually sending them). */ public interface FakeIntentReceiver { @@ -173,6 +173,7 @@ */ static class TargetChosenReceiver extends BroadcastReceiver { private static final String EXTRA_RECEIVER_TOKEN = "receiver_token"; + private static final String EXTRA_SOURCE_PACKAGE_NAME = "source_package_name"; private static final Object LOCK = new Object(); private static String sTargetChosenReceiveAction; @@ -193,9 +194,8 @@ } @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) - static void sendChooserIntent(boolean saveLastUsed, Activity activity, - Intent sharingIntent, - @Nullable TargetChosenCallback callback) { + static void sendChooserIntent(boolean saveLastUsed, Activity activity, Intent sharingIntent, + @Nullable TargetChosenCallback callback, @Nullable String sourcePackageName) { synchronized (LOCK) { if (sTargetChosenReceiveAction == null) { sTargetChosenReceiveAction = activity.getPackageName() + "/" @@ -218,6 +218,7 @@ Intent intent = new Intent(sTargetChosenReceiveAction); intent.setPackage(activity.getPackageName()); intent.putExtra(EXTRA_RECEIVER_TOKEN, sLastRegisteredReceiver.hashCode()); + intent.putExtra(EXTRA_SOURCE_PACKAGE_NAME, sourcePackageName); final PendingIntent pendingIntent = PendingIntent.getBroadcast(activity, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT); Intent chooserIntent = Intent.createChooser(sharingIntent, @@ -242,11 +243,12 @@ } ComponentName target = intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT); + String sourcePackageName = intent.getStringExtra(EXTRA_SOURCE_PACKAGE_NAME); if (mCallback != null) { mCallback.onTargetChosen(target); } if (mSaveLastUsed && target != null) { - setLastShareComponentName(target); + setLastShareComponentName(target, sourcePackageName); } } @@ -289,7 +291,7 @@ */ public static void share(ShareParams params) { if (params.shareDirectly()) { - ComponentName component = getLastShareComponentName(); + ComponentName component = getLastShareComponentName(params.getSourcePackageName()); if (component == null) return; assert params.getCallback() == null; makeIntentAndShare(params, component); @@ -357,7 +359,7 @@ if (name == null) { if (TargetChosenReceiver.isSupported()) { TargetChosenReceiver.sendChooserIntent( - true, activity, shareIntent, null); + true, activity, shareIntent, null, null); } else { Intent chooserIntent = Intent.createChooser(shareIntent, activity.getString(R.string.share_link_chooser_title)); @@ -462,7 +464,9 @@ callback.onTargetChosen(component); callbackCalled[0] = true; } - if (params.saveLastUsed()) setLastShareComponentName(component); + if (params.saveLastUsed()) { + setLastShareComponentName(component, params.getSourcePackageName()); + } makeIntentAndShare(params, component); dialog.dismiss(); } @@ -493,20 +497,19 @@ fireIntent(params.getActivity(), intent); } else { assert TargetChosenReceiver.isSupported(); - TargetChosenReceiver.sendChooserIntent( - params.saveLastUsed(), params.getActivity(), intent, params.getCallback()); + TargetChosenReceiver.sendChooserIntent(params.saveLastUsed(), params.getActivity(), + intent, params.getCallback(), params.getSourcePackageName()); } } /** * Set the icon and the title for the menu item used for direct share. - * * @param activity Activity that is used to access the package manager. * @param item The menu item that is used for direct share */ public static void configureDirectShareMenuItem(Activity activity, MenuItem item) { Intent shareIntent = getShareLinkAppCompatibilityIntent(); - Pair<Drawable, CharSequence> directShare = getShareableIconAndName(activity, shareIntent); + Pair<Drawable, CharSequence> directShare = getShareableIconAndName(shareIntent, null); Drawable directShareIcon = directShare.first; CharSequence directShareTitle = directShare.second; @@ -518,21 +521,22 @@ } /** - * Get the icon and name of the most recently shared app within chrome. - * @param activity Activity that is used to access the package manager. + * Get the icon and name of the most recently shared app by certain app. * @param shareIntent Intent used to get list of apps support sharing. + * @param sourcePackageName The package name of the app who requests for share. If Null, it is + * requested by Chrome. * @return The Image and the String of the recently shared Icon. */ public static Pair<Drawable, CharSequence> getShareableIconAndName( - Activity activity, Intent shareIntent) { + Intent shareIntent, @Nullable String sourcePackageName) { Drawable directShareIcon = null; CharSequence directShareTitle = null; - final ComponentName component = getLastShareComponentName(); + final ComponentName component = getLastShareComponentName(sourcePackageName); boolean isComponentValid = false; if (component != null) { shareIntent.setPackage(component.getPackageName()); - PackageManager manager = activity.getPackageManager(); + PackageManager manager = ContextUtils.getApplicationContext().getPackageManager(); List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(shareIntent, 0); for (ResolveInfo info : resolveInfoList) { ActivityInfo ai = info.activityInfo; @@ -545,7 +549,7 @@ if (isComponentValid) { boolean retrieved = false; try { - final PackageManager pm = activity.getPackageManager(); + final PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); AsyncTask<Void, Void, Pair<Drawable, CharSequence>> task = new AsyncTask<Void, Void, Pair<Drawable, CharSequence>>() { @Override @@ -565,6 +569,8 @@ } }; task.execute(); + // TODO(ltian): Return nothing for the AsyncTask and have a callback to update the + // the menu. Pair<Drawable, CharSequence> result = task.get(COMPONENT_INFO_READ_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS); directShareIcon = result.first; @@ -577,41 +583,36 @@ } catch (TimeoutException te) { // Use the default null values. } - RecordHistogram.recordBooleanHistogram( - "Android.IsLastSharedAppInfoRetrieved", retrieved); + CachedMetrics.BooleanHistogramSample isLastSharedAppInfoRetrieved = + new CachedMetrics.BooleanHistogramSample( + "Android.IsLastSharedAppInfoRetrieved"); + isLastSharedAppInfoRetrieved.record(retrieved); } return new Pair<>(directShareIcon, directShareTitle); } - /* - * Stores the component selected for sharing last time share was called. + /** + * Stores the component selected for sharing last time share was called by certain app. * * This method is public since it is used in tests to avoid creating share dialog. + * @param component The {@link ComponentName} of the app selected for sharing. + * @param sourcePackageName The package name of the app who requests share. If Null, it is + * request by Chrome. */ @VisibleForTesting - public static void setLastShareComponentName(ComponentName component) { - SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); + public static void setLastShareComponentName( + ComponentName component, @Nullable String sourcePackageName) { + SharedPreferences preferences = getSharePreferences(sourcePackageName); SharedPreferences.Editor editor = preferences.edit(); - editor.putString(PACKAGE_NAME_KEY, component.getPackageName()); - editor.putString(CLASS_NAME_KEY, component.getClassName()); + editor.putString(getPackageNameKey(sourcePackageName), component.getPackageName()); + editor.putString(getClassNameKey(sourcePackageName), component.getClassName()); editor.apply(); } @VisibleForTesting public static Intent getShareLinkIntent(ShareParams params) { - String url = params.getUrl(); String text = params.getText(); - if (!TextUtils.isEmpty(url)) { - url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); - if (!TextUtils.isEmpty(text)) { - // Concatenate text and URL with a space. - text = text + " " + url; - } else { - text = url; - } - } - Intent intent = new Intent(Intent.ACTION_SEND); intent.addFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag()); intent.putExtra(Intent.EXTRA_SUBJECT, params.getTitle()); @@ -663,14 +664,31 @@ } /** - * Gets the {@link ComponentName} of the app that was used to last share. + * Gets the {@link ComponentName} of the app that was used to last share by certain app. + * @param sourcePackageName The package name of the app who requests for share. If Null, it is + * requested by Chrome. */ @Nullable - public static ComponentName getLastShareComponentName() { - SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); - String packageName = preferences.getString(PACKAGE_NAME_KEY, null); - String className = preferences.getString(CLASS_NAME_KEY, null); + public static ComponentName getLastShareComponentName(@Nullable String sourcePackageName) { + SharedPreferences preferences = getSharePreferences(sourcePackageName); + String packageName = preferences.getString(getPackageNameKey(sourcePackageName), null); + String className = preferences.getString(getClassNameKey(sourcePackageName), null); if (packageName == null || className == null) return null; return new ComponentName(packageName, className); } + + private static SharedPreferences getSharePreferences(@Nullable String sourcePackageName) { + return sourcePackageName != null + ? ContextUtils.getApplicationContext().getSharedPreferences( + EXTERNAL_APP_SHARING_PREF_FILE_NAME, Context.MODE_PRIVATE) + : ContextUtils.getAppSharedPreferences(); + } + + private static String getPackageNameKey(@Nullable String sourcePackageName) { + return (TextUtils.isEmpty(sourcePackageName) ? "" : sourcePackageName) + PACKAGE_NAME_KEY; + } + + private static String getClassNameKey(@Nullable String sourcePackageName) { + return (TextUtils.isEmpty(sourcePackageName) ? "" : sourcePackageName) + CLASS_NAME_KEY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java index 60016acd..ba55170f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java
@@ -8,8 +8,10 @@ import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.text.TextUtils; import org.chromium.chrome.browser.share.ShareHelper.TargetChosenCallback; +import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; /** * A container object for passing share parameters to {@link ShareHelper}. @@ -51,9 +53,13 @@ */ private TargetChosenCallback mCallback; + /** The package name of the app who requests for share. If Null, it is requested by Chrome */ + private final String mSourcePackageName; + private ShareParams(boolean shareDirectly, boolean saveLastUsed, Activity activity, String title, String text, String url, @Nullable Uri offlineUri, - @Nullable Uri screenshotUri, @Nullable TargetChosenCallback callback) { + @Nullable Uri screenshotUri, @Nullable TargetChosenCallback callback, + @Nullable String sourcePackageName) { mShareDirectly = shareDirectly; mSaveLastUsed = saveLastUsed; mActivity = activity; @@ -63,6 +69,7 @@ mOfflineUri = offlineUri; mScreenshotUri = screenshotUri; mCallback = callback; + mSourcePackageName = sourcePackageName; } /** @@ -132,6 +139,13 @@ return mCallback; } + /** + * @return The package name of the app who requests for share. + */ + public String getSourcePackageName() { + return mSourcePackageName; + } + /** The builder for {@link ShareParams} objects. */ public static class Builder { private boolean mShareDirectly; @@ -143,6 +157,8 @@ private Uri mOfflineUri; private Uri mScreenshotUri; private TargetChosenCallback mCallback; + private String mSourcePackageName; + private boolean mIsExternalUrl; public Builder(@NonNull Activity activity, @NonNull String title, @NonNull String url) { mActivity = activity; @@ -207,10 +223,37 @@ return this; } + /** + * Set the package name of the app who requests for share. + */ + public Builder setSourcePackageName(String sourcePackageName) { + mSourcePackageName = sourcePackageName; + return this; + } + + /** + * Set whether the params are created by the url from external app. + */ + public Builder setIsExternalUrl(boolean isExternalUrl) { + mIsExternalUrl = isExternalUrl; + return this; + } + /** @return A fully constructed {@link ShareParams} object. */ public ShareParams build() { + if (!TextUtils.isEmpty(mUrl)) { + if (!mIsExternalUrl) { + mUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(mUrl); + } + if (!TextUtils.isEmpty(mText)) { + // Concatenate text and URL with a space. + mText = mText + " " + mUrl; + } else { + mText = mUrl; + } + } return new ShareParams(mShareDirectly, mSaveLastUsed, mActivity, mTitle, mText, mUrl, - mOfflineUri, mScreenshotUri, mCallback); + mOfflineUri, mScreenshotUri, mCallback, mSourcePackageName); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java new file mode 100644 index 0000000..17518f0d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
@@ -0,0 +1,91 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.widget; + +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.ImageView; + +import org.chromium.chrome.R; + +/** + * Utility for tinting an ImageView and its Drawable. + * + * Example usage in XML: + * <ImageViewTinterInstanceOwner + * xmlns:android="http://schemas.android.com/apk/res/android" + * xmlns:chrome="http://schemas.android.com/apk/res-auto" + * chrome:chrometint="@color/light_active_color" /> + * + * The default style used by the Application will likely cause your Drawable to be automatically + * tinted. To prevent this, set the value of chrome:chrometint to "@null". + */ +public class ImageViewTinter { + /** Classes that own an ImageViewTinter must implement these functions. */ + public static interface ImageViewTinterOwner { + /** See {@link ImageViewTinter#drawableStateChanged}. */ + void drawableStateChanged(); + + /** See {@link ImageViewTinter#setTint}. */ + void setTint(ColorStateList tintList); + + /** See {@link ImageView#onDraw}. */ + void onDraw(Canvas canvas); + } + + private ImageView mImageView; + private ColorStateList mTintList; + + /** + * Constructor. Should be called with the AttributeSet and style of the ImageView so that XML + * attributes for it can be parsed. + * @param view ImageView being tinted. + * @param attrs AttributeSet that is pulled in from an XML layout. May be null. + * @param defStyle Style that is pulled in from an XML layout. + */ + public ImageViewTinter(ImageViewTinterOwner view, @Nullable AttributeSet attrs, int defStyle) { + assert view instanceof ImageView; + mImageView = (ImageView) view; + + // Parse out the attributes from the XML. + if (attrs != null) { + TypedArray a = mImageView.getContext().obtainStyledAttributes( + attrs, R.styleable.TintedImage, defStyle, 0); + setTint(a.getColorStateList(R.styleable.TintedImage_chrometint)); + a.recycle(); + } + } + + /** + * Sets the tint color for the given ImageView for all states. + * @param tintList The set of colors to use. + */ + public void setTint(ColorStateList tintList) { + if (mTintList == tintList) return; + mTintList = tintList; + updateTintColor(); + } + + /** Call when the state of the Drawable has changed. */ + public void drawableStateChanged() { + updateTintColor(); + } + + private void updateTintColor() { + if (mImageView.getDrawable() == null) { + return; + } else if (mTintList == null) { + mImageView.clearColorFilter(); + return; + } + + int tintColor = mTintList.getColorForState(mImageView.getDrawableState(), 0); + mImageView.setColorFilter(tintColor, PorterDuff.Mode.SRC_IN); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java index 15fc3180..6d28cbd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
@@ -69,13 +69,6 @@ return drawable; } - /** - * Factory method for creating a {@link TintedDrawable} with a {@link Bitmap} icon. - */ - public static TintedDrawable constructTintedDrawable(Resources res, Bitmap icon) { - return new TintedDrawable(res, icon); - } - private boolean updateTintColor() { if (mTint == null) return false; setColorFilter(mTint.getColorForState(getState(), 0), PorterDuff.Mode.SRC_IN);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java index 8d848e05..3678694 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageButton.java
@@ -6,63 +6,45 @@ import android.content.Context; import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.PorterDuff; +import android.graphics.Canvas; import android.util.AttributeSet; import android.widget.ImageButton; -import org.chromium.chrome.R; +import org.chromium.chrome.browser.widget.ImageViewTinter.ImageViewTinterOwner; /** - * Implementation of ImageButton that allows to tint the color of the image button for all - * image button states using chrome:chrometint attribute in XML. + * Implementation of ImageButton that allows tinting the Drawable for all states. + * For usage, see {@link ImageViewTinter}. */ -public class TintedImageButton extends ImageButton { - private ColorStateList mTint; +public class TintedImageButton extends ImageButton implements ImageViewTinterOwner { + private ImageViewTinter mTinter; public TintedImageButton(Context context) { - super(context); + this(context, null); } public TintedImageButton(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs, 0); + this(context, attrs, 0); } public TintedImageButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - init(context, attrs, defStyle); - } - - private void init(Context context, AttributeSet attrs, int defStyle) { - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.TintedImage, defStyle, 0); - setTintInternal(a.getColorStateList(R.styleable.TintedImage_chrometint)); - a.recycle(); + mTinter = new ImageViewTinter(this, attrs, defStyle); } @Override - protected void drawableStateChanged() { + public void drawableStateChanged() { super.drawableStateChanged(); - updateTintColor(); + mTinter.drawableStateChanged(); } - /** - * Sets the tint color for the given ImageButton for all button states. - * @param tint The set of colors to use to color the ImageButton. - */ - public void setTint(ColorStateList tint) { - if (mTint == tint) return; - setTintInternal(tint); - updateTintColor(); + @Override + public void setTint(ColorStateList tintList) { + mTinter.setTint(tintList); } - private void setTintInternal(ColorStateList tint) { - mTint = tint; - } - - private void updateTintColor() { - if (mTint == null) return; - setColorFilter(mTint.getColorForState(getDrawableState(), 0), PorterDuff.Mode.SRC_IN); + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java index 96bb9a29..02713e0b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedImageView.java
@@ -6,66 +6,45 @@ import android.content.Context; import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.PorterDuff; +import android.graphics.Canvas; import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; -import org.chromium.chrome.R; +import org.chromium.chrome.browser.widget.ImageViewTinter.ImageViewTinterOwner; /** - * Implementation of ImageView that allows to tint the color of the image view for all - * image view states using chrome:chrometint attribute in XML. + * Implementation of ImageView that allows tinting its Drawable for all states. + * For usage, see {@link ImageViewTinter}. */ -public class TintedImageView extends AppCompatImageView { - private ColorStateList mTint; +public class TintedImageView extends AppCompatImageView implements ImageViewTinterOwner { + private ImageViewTinter mTinter; public TintedImageView(Context context) { - super(context); + this(context, null); } public TintedImageView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs, 0); + this(context, attrs, 0); } public TintedImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - init(context, attrs, defStyle); - } - - private void init(Context context, AttributeSet attrs, int defStyle) { - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.TintedImage, defStyle, 0); - setTintInternal(a.getColorStateList(R.styleable.TintedImage_chrometint)); - a.recycle(); + mTinter = new ImageViewTinter(this, attrs, defStyle); } @Override - protected void drawableStateChanged() { + public void drawableStateChanged() { super.drawableStateChanged(); - updateTintColor(); + mTinter.drawableStateChanged(); } - /** - * Sets the tint color for the given ImageView for all view states. - * @param tint The set of colors to use to color the ImageView. - */ - public void setTint(ColorStateList tint) { - if (mTint == tint) return; - setTintInternal(tint); - updateTintColor(); + @Override + public void setTint(ColorStateList tintList) { + mTinter.setTint(tintList); } - private void setTintInternal(ColorStateList tint) { - mTint = tint; - } - - private void updateTintColor() { - if (mTint == null) { - clearColorFilter(); - return; - } - setColorFilter(mTint.getColorForState(getDrawableState(), 0), PorterDuff.Mode.SRC_IN); + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); } }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index a9bc2666..d2cf17f4 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -232,6 +232,7 @@ "java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuPagerAdapter.java", "java/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuViewPager.java", "java/src/org/chromium/chrome/browser/contextmenu/PlatformContextMenuUi.java", + "java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java", "java/src/org/chromium/chrome/browser/contextualsearch/BarOverlapTapSuppression.java", "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java", "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java", @@ -1231,6 +1232,7 @@ "java/src/org/chromium/chrome/browser/widget/FadingShadow.java", "java/src/org/chromium/chrome/browser/widget/FadingShadowView.java", "java/src/org/chromium/chrome/browser/widget/FloatLabelLayout.java", + "java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java", "java/src/org/chromium/chrome/browser/widget/LoadingView.java", "java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java", "java/src/org/chromium/chrome/browser/widget/NumberRollView.java", @@ -1684,6 +1686,7 @@ "javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/widget/DualControlLayoutTest.java", + "javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java", "javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java", "javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java", "javatests/src/org/chromium/chrome/browser/widget/RadioButtonLayoutTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java index 3e3a457..5739f1d4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
@@ -110,7 +110,8 @@ // Sets a test component as last shared and "shareDirectly" option is set so that the share // selector menu is not opened. The start activity is overriden, so the package and class // names do not matter. - ShareHelper.setLastShareComponentName(new ComponentName("test.package", "test.activity")); + ShareHelper.setLastShareComponentName( + new ComponentName("test.package", "test.activity"), null); // Skips the capture of screenshot and notifies with an empty file. mockActivity.setScreenshotCaptureSkippedForTesting(true); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @@ -127,7 +128,7 @@ assert false : "Test thread was interrupted while trying to wait."; } - ShareHelper.setLastShareComponentName(new ComponentName("", "")); + ShareHelper.setLastShareComponentName(new ComponentName("", ""), null); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index fd71a61..b449631 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -543,7 +543,7 @@ Assert.assertFalse(menu.findItem(R.id.share_row_menu_id).isEnabled()); Assert.assertNotNull(menu.findItem(R.id.find_in_page_id)); Assert.assertNotNull(menu.findItem(R.id.add_to_homescreen_id)); - Assert.assertNotNull(menu.findItem(R.id.request_desktop_site_id)); + Assert.assertNotNull(menu.findItem(R.id.request_desktop_site_row_menu_id)); } /** @@ -568,7 +568,7 @@ Assert.assertEquals(expectedMenuSize, actualMenuSize); Assert.assertFalse(menu.findItem(R.id.find_in_page_id).isVisible()); Assert.assertFalse(menu.findItem(R.id.add_to_homescreen_id).isVisible()); - Assert.assertFalse(menu.findItem(R.id.request_desktop_site_id).isVisible()); + Assert.assertFalse(menu.findItem(R.id.request_desktop_site_row_menu_id).isVisible()); Assert.assertFalse(menu.findItem(R.id.open_in_browser_id).isVisible()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java index 8076fae..08149a3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
@@ -21,6 +21,7 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; +import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.vr_shell.mock.MockVrDaydreamApi; import org.chromium.chrome.browser.vr_shell.util.NfcSimUtils; @@ -81,6 +82,7 @@ */ @Test @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYDREAM}) + @RetryOnFailure(message = "crbug.com/736527") @MediumTest public void test2dtoVrShellNfcSupported() { enterVrShellNfc(true /* supported */);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java index d886a0b6..d556b2d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; +import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.vr_shell.util.NfcSimUtils; import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils; @@ -57,6 +58,7 @@ @Test @MediumTest @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM) + @RetryOnFailure(message = "crbug.com/736527") public void testNfcFiresVrdisplayactivate() throws InterruptedException { mVrTestRule.loadUrlAndAwaitInitialization( VrTestRule.getHtmlTestFile("test_nfc_fires_vrdisplayactivate"),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java new file mode 100644 index 0000000..942b2f8e --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
@@ -0,0 +1,180 @@ +// 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.widget; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.rule.UiThreadTestRule; +import android.view.LayoutInflater; +import android.view.View.MeasureSpec; +import android.view.ViewGroup; +import android.widget.ImageView; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.widget.ImageViewTinter.ImageViewTinterOwner; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; + +/** + * Tests the classes that use ImageViewTinter. + * + * In an ideal world, these tests would simply use an XmlPullParser and XML that is defined inside + * this test, but Android explicitly disallows that because it pre-processes the XML files: + * https://developer.android.com/reference/android/view/LayoutInflater.html + * + * An alternative would be to have test-specific layout directories, but these don't seem to be + * able to reference the instrumented package's resources. Instead, the tests reference XML for + * actual controls used in the production app. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +public class ImageViewTinterTest { + @Rule + public UiThreadTestRule mRule = new UiThreadTestRule(); + + private Context mContext; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + mContext.setTheme(R.style.MainTheme); + } + + @Test + @SmallTest + public void testTintedImageView_attributeParsingExplicitTint() throws Exception { + // The tint is explicitly set to a blue in the XML. + int color = ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.blue_mode_tint); + TintedImageView clearStorageView = (TintedImageView) LayoutInflater.from(mContext).inflate( + R.layout.clear_storage, null, false); + Assert.assertNotNull(clearStorageView.getColorFilter()); + Assert.assertTrue(checkIfTintWasApplied(clearStorageView, color)); + } + + @Test + @SmallTest + public void testTintedImageButton_attributeParsingExplicitTint() throws Exception { + // The tint was explicitly set to a color. + int color = ApiCompatibilityUtils.getColor( + mContext.getResources(), R.color.app_menu_button_tint); + TintedImageButton colorTint = + createImageView(R.layout.icon_row_menu_footer, R.id.forward_menu_id); + Assert.assertNotNull(colorTint.getColorFilter()); + Assert.assertTrue(checkIfTintWasApplied(colorTint, color)); + } + + @Test + @SmallTest + public void testTintedImageView_attributeParsingNullTint() throws Exception { + // The tint is explicitly set to null in the XML. + int color = ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.blue_mode_tint); + TintedImageView nullTint = createImageView(R.layout.title_button_menu_item, R.id.checkbox); + Assert.assertNull(nullTint.getColorFilter()); + Assert.assertFalse(checkIfTintWasApplied(nullTint, color)); + } + + @Test + @SmallTest + public void testTintedImageButton_attributeParsingNullTint() throws Exception { + // The tint is explicitly set to null in the XML. An image resource needs to be set here + // because the layout doesn't define one by default. + int color = ApiCompatibilityUtils.getColor( + mContext.getResources(), R.color.app_menu_button_tint); + TintedImageButton nullTint = createImageView(R.layout.title_button_menu_item, R.id.button); + Assert.assertNull(nullTint.getColorFilter()); + nullTint.setImageResource(R.drawable.plus); + Assert.assertFalse(checkIfTintWasApplied(nullTint, color)); + } + + @Test + @SmallTest + public void testTintedImageView_setTint() throws Exception { + // The tint is explicitly set to null for this object in the XML. + TintedImageView nullTint = createImageView(R.layout.title_button_menu_item, R.id.checkbox); + checkSetTintWorksCorrectly(nullTint); + } + + @Test + @SmallTest + public void testTintedImageButton_setTint() throws Exception { + // The tint is explicitly set to null for this object in the XML. + TintedImageButton nullTint = createImageView(R.layout.title_button_menu_item, R.id.button); + checkSetTintWorksCorrectly(nullTint); + } + + private void checkSetTintWorksCorrectly(ImageViewTinterOwner view) { + ImageView imageView = (ImageView) view; + int color = + ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.light_active_color); + + Assert.assertNull(imageView.getColorFilter()); + if (imageView.getDrawable() == null) { + // An image resource is set here in case the layout does not define one. + imageView.setImageResource(R.drawable.plus); + } + Assert.assertFalse(checkIfTintWasApplied(view, color)); + + // Set the tint to one color. + ColorStateList colorList = ApiCompatibilityUtils.getColorStateList( + mContext.getResources(), R.color.light_active_color); + view.setTint(colorList); + Assert.assertNotNull(imageView.getColorFilter()); + Assert.assertTrue(checkIfTintWasApplied(view, color)); + + // Clear it out. + view.setTint(null); + Assert.assertNull(imageView.getColorFilter()); + Assert.assertFalse(checkIfTintWasApplied(view, color)); + + // Set it to another color. + int otherColor = + ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.google_red_700); + ColorStateList otherColorList = ApiCompatibilityUtils.getColorStateList( + mContext.getResources(), R.color.google_red_700); + view.setTint(otherColorList); + Assert.assertNotNull(imageView.getColorFilter()); + Assert.assertTrue(checkIfTintWasApplied(view, otherColor)); + } + + @SuppressWarnings("unchecked") + private <T extends ImageView> T createImageView(int layoutId, int ownerId) { + ViewGroup root = (ViewGroup) LayoutInflater.from(mContext).inflate(layoutId, null, false); + return (T) root.findViewById(ownerId); + } + + private boolean checkIfTintWasApplied( + ImageViewTinterOwner imageViewTinterOwner, int expectedColor) { + int unspecifiedSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + Assert.assertTrue(imageViewTinterOwner instanceof ImageView); + ImageView imageView = (ImageView) imageViewTinterOwner; + imageView.measure(unspecifiedSpec, unspecifiedSpec); + imageView.layout(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight()); + + // Draw the ImageView into a Canvas so we can check that the tint was applied. + Drawable drawable = imageView.getDrawable(); + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + imageViewTinterOwner.onDraw(canvas); + + // Search for any pixel that is of the expected color. + for (int x = 0; x < bitmap.getWidth(); x++) { + for (int y = 0; y < bitmap.getHeight(); y++) { + if (expectedColor == bitmap.getPixel(x, y)) return true; + } + } + return false; + } +}
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index d159361..712f8cf0 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -6120,7 +6120,7 @@ <ph name="PAGE_NUMBER">$1<ex>5</ex></ph> pages to <ph name="PRINTER_NAME">$2<ex>printer</ex></ph> </message> <message name="IDS_PRINT_JOB_NOTIFICATION_SINGLE_PAGE_MESSAGE" desc="Message of the print job notification for a single page."> - 1 page to <ph name="PRINTER_NAME">$2<ex>printer</ex></ph> + 1 page to <ph name="PRINTER_NAME">$1<ex>printer</ex></ph> </message> <message name="IDS_PRINT_JOB_NOTIFICATION_CANCEL_BUTTON" desc="Text on the button for the user to cancel the current print job."> Cancel printing
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index d2d49d2..aca859b 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4983,6 +4983,9 @@ </message> <message name="IDS_PREVIEWS_INFOBAR_TIMESTAMP_HOURS" desc="The desciption stating how old a preview version of a page is in hours. This is shown on the infobar notifying the user that a preview page has been shown."> Updated <ph name="HOURS">$1<ex>4</ex></ph>hrs ago + </message> + <message name="IDS_PREVIEWS_INFOBAR_TIMESTAMP_UPDATED_NOW" desc="The desciption stating that a preview version of a page was just updated. This is shown on the infobar notifying the user that a preview page has been shown."> + Updated just now </message> <!-- WebRTC logs --> @@ -6459,6 +6462,9 @@ <message name="IDS_CHROME_CLEANUP_LOGS_PERMISSION" desc="A checkbox label, appearing on both the Chrome Cleanup dialog and web page, asking the user for permission to send some system information to Google in order to help with detection of harmful software. The word 'settings' refers to the user's operating system settings. The word 'applications' refers to any software that is installed or runs on the user's computer."> Send information about your system and applications to Google to help detect harmful software </message> + <message name="IDS_CHROME_CLEANUP_LOGS_PERMISSION_WITH_LINK" desc="A checkbox label, appearing on both the Chrome Cleanup dialog and web page, asking the user for permission to send some system information to Google in order to help with detection of harmful software. The word 'settings' refers to the user's operating system settings. The word 'applications' refers to any software that is installed or runs on the user's computer. The translation for this string should have the same meaning as IDS_CHROME_CLEANUP_LOGS_PERMISSION"> + Send <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>information about your system and applications<ph name="END_LINK"></a></ph> to Google to help detect harmful software + </message> </if> <!-- Settings reset prompt dialog messages --> @@ -8467,6 +8473,10 @@ desc="Text for the button that activates Android App. (In sentence case.)"> Open </message> + <message name="IDS_APP_CONTEXT_MENU_INSTALL_ARC" + desc="Text for the button that installs the Android app. (In sentence case.)"> + Install + </message> </if> </if> @@ -8524,6 +8534,10 @@ desc="Text for the button that activates Android App. (In title case.)"> Open </message> + <message name="IDS_APP_CONTEXT_MENU_INSTALL_ARC" + desc="Text for the button that installs the Android app. (In title case.)"> + Install + </message> </if> </if>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index b918158..bcc5c41 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -3161,8 +3161,8 @@ <message name="IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP" desc="In Device Settings > Power, menu item for idle behavior that turns the screen off and later puts the device to sleep."> Turn off display and sleep </message> - <message name="IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_STAY_AWAKE" desc="In Device Settings > Power, menu item for idle behavior that turns the screen off but prevents the device from sleeping."> - Turn off display but stay awake + <message name="IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF" desc="In Device Settings > Power, menu item for idle behavior that turns the screen off but prevents the device from sleeping."> + Turn off display </message> <message name="IDS_SETTINGS_POWER_IDLE_DISPLAY_ON" desc="In Device Settings > Power, menu item for idle behavior that prevents the screen from turning off and prevents the device from sleeping."> Keep display on
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture.cc b/chrome/browser/android/vr_shell/textures/url_bar_texture.cc index 65a84f9..1e1a85c4 100644 --- a/chrome/browser/android/vr_shell/textures/url_bar_texture.cc +++ b/chrome/browser/android/vr_shell/textures/url_bar_texture.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/android/vr_shell/textures/url_bar_texture.h" -#include "base/i18n/rtl.h" #include "base/strings/utf_string_conversions.h" #include "cc/paint/skia_paint_canvas.h" #include "chrome/browser/android/vr_shell/color_scheme.h" @@ -353,9 +352,6 @@ gurl_, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr); - if (base::i18n::StringContainsStrongRTLChars(text)) - failure_callback_.Run(UiUnsupportedMode::kURLWithStrongRTLChars); - int pixel_font_height = texture_size.height() * kFontHeight / kHeight; gfx::FontList font_list; @@ -368,6 +364,7 @@ render_text->SetColor(SK_ColorBLACK); render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); render_text->SetElideBehavior(gfx::ELIDE_TAIL); + render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR); render_text->SetText(text); render_text->SetDisplayRect(bounds); @@ -391,6 +388,7 @@ color_scheme()); url_render_text_ = std::move(render_text); + url_text_ = text; } // This method replicates behavior in OmniboxView::UpdateTextStyle(), and
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture.h b/chrome/browser/android/vr_shell/textures/url_bar_texture.h index c848cf1..11e18d0 100644 --- a/chrome/browser/android/vr_shell/textures/url_bar_texture.h +++ b/chrome/browser/android/vr_shell/textures/url_bar_texture.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/android/vr_shell/textures/ui_texture.h" #include "chrome/browser/android/vr_shell/ui_unsupported_mode.h" #include "components/security_state/core/security_state.h" @@ -51,13 +52,16 @@ void SetBackButtonHovered(bool hovered); void SetBackButtonPressed(bool pressed); - // Public for testability. + protected: static void ApplyUrlStyling(const base::string16& formatted_url, const url::Parsed& parsed, security_state::SecurityLevel security_level, vr_shell::RenderTextWrapper* render_text, const ColorScheme& color_scheme); + std::unique_ptr<gfx::RenderText> url_render_text_; + base::string16 url_text_; + private: void Draw(SkCanvas* canvas, const gfx::Size& texture_size) override; float ToPixels(float meters) const; @@ -77,7 +81,6 @@ security_state::SecurityLevel::NONE; bool malware_ = false; - std::unique_ptr<gfx::RenderText> url_render_text_; GURL last_drawn_gurl_; bool has_back_button_ = true; bool has_security_chip_ = true;
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture_unittest.cc b/chrome/browser/android/vr_shell/textures/url_bar_texture_unittest.cc index 20df5908..01709d4511 100644 --- a/chrome/browser/android/vr_shell/textures/url_bar_texture_unittest.cc +++ b/chrome/browser/android/vr_shell/textures/url_bar_texture_unittest.cc
@@ -50,6 +50,15 @@ DrawAndLayout(surface->getCanvas(), texture_size_); } + static void TestUrlStyling(const base::string16& formatted_url, + const url::Parsed& parsed, + security_state::SecurityLevel security_level, + vr_shell::RenderTextWrapper* render_text, + const ColorScheme& color_scheme) { + ApplyUrlStyling(formatted_url, parsed, security_level, render_text, + color_scheme); + } + void SetForceFontFallbackFailure(bool force) { SetForceFontFallbackFailureForTesting(force); } @@ -71,6 +80,9 @@ // no unsupported mode was encountered. UiUnsupportedMode unsupported_mode() const { return unsupported_mode_; } + gfx::RenderText* url_render_text() { return url_render_text_.get(); } + const base::string16& url_text() { return url_text_; } + private: void OnUnsupportedFeature(UiUnsupportedMode mode) { unsupported_mode_ = mode; @@ -116,10 +128,10 @@ url, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr); EXPECT_EQ(formatted_url, base::UTF8ToUTF16(expected_string)); - UrlBarTexture::ApplyUrlStyling( + TestUrlBarTexture::TestUrlStyling( formatted_url, parsed, level, &mock_, ColorScheme::GetColorScheme(ColorScheme::kModeNormal)); - UrlBarTexture::ApplyUrlStyling( + TestUrlBarTexture::TestUrlStyling( formatted_url, parsed, level, &mock_, ColorScheme::GetColorScheme(ColorScheme::kModeIncognito)); } @@ -202,11 +214,44 @@ EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode()); } -TEST(UrlBarTextureTest, WillFailOnStrongRTLChar) { +TEST(UrlBarTextureTest, MaliciousRTLIsRenderedLTR) { TestUrlBarTexture texture; - texture.DrawURL(GURL("https://ש.com")); - EXPECT_EQ(UiUnsupportedMode::kURLWithStrongRTLChars, - texture.unsupported_mode()); + + // Construct a malicious URL that attempts to spoof the hostname. + const std::string real_host("127.0.0.1"); + const std::string spoofed_host("attack.com"); + const std::string url = + "http://" + real_host + "/ا/http://" + spoofed_host + "‬"; + + texture.DrawURL(GURL(base::UTF8ToUTF16(url))); + + // Determine the logical character ranges of the legitimate and spoofed + // hostnames in the processed URL text. + base::string16 text = texture.url_text(); + base::string16 real_16 = base::UTF8ToUTF16(real_host); + base::string16 spoofed_16 = base::UTF8ToUTF16(spoofed_host); + size_t position = text.find(real_16); + ASSERT_NE(position, base::string16::npos); + gfx::Range real_range(position, position + real_16.size()); + position = text.find(spoofed_16); + ASSERT_NE(position, base::string16::npos); + gfx::Range spoofed_range(position, position + spoofed_16.size()); + + // Extract the pixel locations at which hostnames were actually rendered. + auto real_bounds = + texture.url_render_text()->GetSubstringBoundsForTesting(real_range); + auto spoofed_bounds = + texture.url_render_text()->GetSubstringBoundsForTesting(spoofed_range); + EXPECT_EQ(real_bounds.size(), 1u); + EXPECT_GE(spoofed_bounds.size(), 1u); + + // Verify that any spoofed portion of the hostname has remained to the right + // of the legitimate hostname. This will fail if LTR directionality is not + // specified during URL rendering. + auto minimum_position = real_bounds[0].x() + real_bounds[0].width(); + for (const auto& region : spoofed_bounds) { + EXPECT_GT(region.x(), minimum_position); + } } TEST(UrlBarTexture, ElisionIsAnUnsupportedMode) {
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.cc b/chrome/browser/android/vr_shell/ui_scene_manager.cc index 84d337bd..22580916 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager.cc +++ b/chrome/browser/android/vr_shell/ui_scene_manager.cc
@@ -433,10 +433,10 @@ web_vr_mode_ = web_vr; web_vr_autopresented_ = auto_presented; web_vr_show_toast_ = show_toast; + toast_state_ = SET_FOR_WEB_VR; ConfigureScene(); ConfigureSecurityWarnings(); ConfigureTransientUrlBar(); - ConfigureIndicators(); ConfigurePresentationToast(); } @@ -498,6 +498,14 @@ scene_->SetBackgroundDistance(main_content_->translation().z() * -kBackgroundDistanceMultiplier); UpdateBackgroundColor(); + + // Configure other subsystems here as well. Ultimately, it would be nice if we + // could configure all elements through ConfigureScene(), as the exact + // conditions that control each element are getting complicated. More systems + // should move in here, such that a single method call can update the entire + // scene. The drawback is slightly more overhead for individual scene + // reconfigurations. + ConfigureIndicators(); } void UiSceneManager::UpdateBackgroundColor() { @@ -545,8 +553,7 @@ void UiSceneManager::OnGLInitialized() { scene_->OnGLInitialized(); - // Indicators don't know their position until they've rendered themselves. - ConfigureIndicators(); + ConfigureScene(); } void UiSceneManager::OnAppButtonClicked() { @@ -562,7 +569,9 @@ if (fullscreen_ == fullscreen) return; fullscreen_ = fullscreen; + toast_state_ = SET_FOR_FULLSCREEN; ConfigureScene(); + ConfigurePresentationToast(); } void UiSceneManager::ConfigureSecurityWarnings() { @@ -579,17 +588,24 @@ } void UiSceneManager::ConfigureIndicators() { - audio_capture_indicator_->set_visible(!web_vr_mode_ && audio_capturing_); - video_capture_indicator_->set_visible(!web_vr_mode_ && video_capturing_); - screen_capture_indicator_->set_visible(!web_vr_mode_ && screen_capturing_); - location_access_indicator_->set_visible(!web_vr_mode_ && location_access_); + bool allowed = !web_vr_mode_ && !fullscreen_; + audio_capture_indicator_->set_visible(allowed && audio_capturing_); + video_capture_indicator_->set_visible(allowed && video_capturing_); + screen_capture_indicator_->set_visible(allowed && screen_capturing_); + location_access_indicator_->set_visible(allowed && location_access_); + + if (!allowed) + return; // Position elements dynamically relative to each other, based on which // indicators are showing, and how big each one is. - float total_width = kIndicatorGap * (system_indicators_.size() - 1); + float total_width = 0; for (const UiElement* indicator : system_indicators_) { - if (indicator->visible()) + if (indicator->visible()) { + if (total_width > 0) + total_width += kIndicatorGap; total_width += indicator->size().x(); + } } float x_position = -total_width / 2; for (UiElement* indicator : system_indicators_) { @@ -604,14 +620,26 @@ } void UiSceneManager::ConfigurePresentationToast() { - presentation_toast_->set_visible(web_vr_show_toast_); - if (web_vr_show_toast_) { + bool toast_visible = false; + switch (toast_state_) { + case SET_FOR_WEB_VR: + toast_visible = web_vr_show_toast_; + break; + case SET_FOR_FULLSCREEN: + toast_visible = fullscreen_; + break; + case UNCHANGED: + return; + } + presentation_toast_->set_visible(toast_visible); + if (toast_visible) { presentation_toast_timer_.Start( FROM_HERE, base::TimeDelta::FromSeconds(kToastTimeoutSeconds), this, &UiSceneManager::OnPresentationToastTimer); } else { presentation_toast_timer_.Stop(); } + toast_state_ = UNCHANGED; } void UiSceneManager::OnSecurityWarningTimer() {
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.h b/chrome/browser/android/vr_shell/ui_scene_manager.h index 06ec34e6..a330af6 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager.h +++ b/chrome/browser/android/vr_shell/ui_scene_manager.h
@@ -59,6 +59,11 @@ void OnExitPromptPrimaryButtonClickedForTesting(); private: + enum ToastState { + UNCHANGED = 0, + SET_FOR_WEB_VR, + SET_FOR_FULLSCREEN, + }; void CreateScreenDimmer(); void CreateSecurityWarnings(); void CreateSystemIndicators(); @@ -127,6 +132,7 @@ bool video_capturing_ = false; bool screen_capturing_ = false; bool location_access_ = false; + ToastState toast_state_ = UNCHANGED; int next_available_id_ = 1;
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc index d3af85909..38b8241 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc +++ b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc
@@ -77,17 +77,31 @@ return element ? element->visible() : false; } + // Verify that only the elements in the set are visible. void VerifyElementsVisible(const std::string& debug_name, - const std::set<UiElementDebugId>& elements) { + const std::set<UiElementDebugId>& debug_ids) { SCOPED_TRACE(debug_name); for (const auto& element : scene_->GetUiElements()) { SCOPED_TRACE(element->debug_id()); bool should_be_visible = - elements.find(element->debug_id()) != elements.end(); + debug_ids.find(element->debug_id()) != debug_ids.end(); EXPECT_EQ(should_be_visible, element->visible()); } } + // Return false if not all elements in the set match the specified visibility + // state. Other elements are ignored. + bool VerifyVisibility(const std::set<UiElementDebugId>& debug_ids, + bool visible) { + for (const auto& element : scene_->GetUiElements()) { + if (debug_ids.find(element->debug_id()) != debug_ids.end() && + element->visible() != visible) { + return false; + } + } + return true; + } + base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<MockBrowserInterface> browser_; std::unique_ptr<UiScene> scene_; @@ -134,28 +148,32 @@ EXPECT_TRUE(IsVisible(kWebVrTransientHttpSecurityWarning)); } -// Tests toast not showing when directly entering VR though WebVR presentation. -TEST_F(UiSceneManagerTest, WebVrToastNotShowingWhenInitiallyInWebVr) { +TEST_F(UiSceneManagerTest, ToastVisibility) { + // Tests toast not showing when directly entering VR though WebVR + // presentation. MakeManager(kNotInCct, kInWebVr); EXPECT_FALSE(IsVisible(kPresentationToast)); -} -// Tests toast visibility is controlled by show_toast parameter. -TEST_F(UiSceneManagerTest, WebVrToastShowAndHide) { MakeManager(kNotInCct, kNotInWebVr); EXPECT_FALSE(IsVisible(kPresentationToast)); + manager_->SetFullscreen(true); + EXPECT_TRUE(IsVisible(kPresentationToast)); + manager_->SetWebVrMode(true, false, true); EXPECT_TRUE(IsVisible(kPresentationToast)); + manager_->SetWebVrMode(false, false, false); + EXPECT_FALSE(IsVisible(kPresentationToast)); + + manager_->SetFullscreen(false); + EXPECT_FALSE(IsVisible(kPresentationToast)); + manager_->SetWebVrMode(true, false, false); EXPECT_FALSE(IsVisible(kPresentationToast)); manager_->SetWebVrMode(false, false, true); EXPECT_TRUE(IsVisible(kPresentationToast)); - - manager_->SetWebVrMode(false, false, false); - EXPECT_FALSE(IsVisible(kPresentationToast)); } TEST_F(UiSceneManagerTest, CloseButtonVisibleInCctFullscreen) { @@ -267,7 +285,9 @@ TEST_F(UiSceneManagerTest, UiUpdatesForFullscreenChanges) { std::set<UiElementDebugId> visible_in_fullscreen = { - kContentQuad, kCloseButton, kBackplane, kCeiling, kFloor}; + kContentQuad, kCloseButton, kBackplane, + kCeiling, kFloor, kPresentationToast, + }; MakeManager(kNotInCct, kNotInWebVr); @@ -358,42 +378,37 @@ } TEST_F(UiSceneManagerTest, CaptureIndicatorsVisibility) { + const std::set<UiElementDebugId> indicators = { + kAudioCaptureIndicator, kVideoCaptureIndicator, kScreenCaptureIndicator, + kLocationAccessIndicator, + }; + MakeManager(kNotInCct, kNotInWebVr); - EXPECT_FALSE(IsVisible(kAudioCaptureIndicator)); - EXPECT_FALSE(IsVisible(kVideoCaptureIndicator)); - EXPECT_FALSE(IsVisible(kScreenCaptureIndicator)); - EXPECT_FALSE(IsVisible(kLocationAccessIndicator)); + EXPECT_TRUE(VerifyVisibility(indicators, false)); manager_->SetAudioCapturingIndicator(true); manager_->SetVideoCapturingIndicator(true); manager_->SetScreenCapturingIndicator(true); manager_->SetLocationAccessIndicator(true); + EXPECT_TRUE(VerifyVisibility(indicators, true)); - EXPECT_TRUE(IsVisible(kAudioCaptureIndicator)); - EXPECT_TRUE(IsVisible(kVideoCaptureIndicator)); - EXPECT_TRUE(IsVisible(kScreenCaptureIndicator)); - EXPECT_TRUE(IsVisible(kLocationAccessIndicator)); - + // Go into non-browser modes and make sure all indicators are hidden. manager_->SetWebVrMode(true, false, false); - EXPECT_FALSE(IsVisible(kAudioCaptureIndicator)); - EXPECT_FALSE(IsVisible(kVideoCaptureIndicator)); - EXPECT_FALSE(IsVisible(kScreenCaptureIndicator)); - EXPECT_FALSE(IsVisible(kLocationAccessIndicator)); - + EXPECT_TRUE(VerifyVisibility(indicators, false)); manager_->SetWebVrMode(false, false, false); - EXPECT_TRUE(IsVisible(kAudioCaptureIndicator)); - EXPECT_TRUE(IsVisible(kVideoCaptureIndicator)); - EXPECT_TRUE(IsVisible(kScreenCaptureIndicator)); - EXPECT_TRUE(IsVisible(kLocationAccessIndicator)); + manager_->SetFullscreen(true); + EXPECT_TRUE(VerifyVisibility(indicators, false)); + manager_->SetFullscreen(false); + // Back to browser, make sure the indicators reappear. + EXPECT_TRUE(VerifyVisibility(indicators, true)); + + // Ensure they can be turned off. manager_->SetAudioCapturingIndicator(false); manager_->SetVideoCapturingIndicator(false); manager_->SetScreenCapturingIndicator(false); manager_->SetLocationAccessIndicator(false); - - EXPECT_FALSE(IsVisible(kAudioCaptureIndicator)); - EXPECT_FALSE(IsVisible(kVideoCaptureIndicator)); - EXPECT_FALSE(IsVisible(kScreenCaptureIndicator)); - EXPECT_FALSE(IsVisible(kLocationAccessIndicator)); + EXPECT_TRUE(VerifyVisibility(indicators, false)); } + } // namespace vr_shell
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index 357898da..aeb4716 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -17,7 +17,9 @@ "spellcheck::mojom::SpellCheckHost", "spellcheck::mojom::SpellCheckPanelHost", "startup_metric_utils::mojom::StartupMetricHost", - "translate::mojom::ContentTranslateDriver", + "translate::mojom::ContentTranslateDriver" + ], + "url_keyed_metrics": [ "ukm::mojom::UkmRecorderInterface" ], "gpu": [
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc index 9640f2e..26322dc 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -319,8 +319,11 @@ AreArcAllOptInPreferencesManagedForProfile(profile_) && !IsActiveDirectoryUserForProfile(profile_)); if (!suppress_play_store_app) { - playstore_launcher_.reset( - new ArcAppLauncher(profile_, kPlayStoreAppId, true, false)); + playstore_launcher_ = base::MakeUnique<ArcAppLauncher>( + profile_, kPlayStoreAppId, + GetLaunchIntent(kPlayStorePackage, kPlayStoreActivity, + {kInitialStartParam}), + true, false); } for (auto& observer : observer_list_)
diff --git a/chrome/browser/chromeos/printing/cups_print_job_notification.cc b/chrome/browser/chromeos/printing/cups_print_job_notification.cc index f8158fe..6216b8da 100644 --- a/chrome/browser/chromeos/printing/cups_print_job_notification.cc +++ b/chrome/browser/chromeos/printing/cups_print_job_notification.cc
@@ -234,12 +234,17 @@ } void CupsPrintJobNotification::UpdateNotificationBodyMessage() { - base::string16 message = l10n_util::GetStringFUTF16( - (print_job_->total_page_number() > 1) - ? IDS_PRINT_JOB_NOTIFICATION_MESSAGE - : IDS_PRINT_JOB_NOTIFICATION_SINGLE_PAGE_MESSAGE, - base::IntToString16(print_job_->total_page_number()), - base::UTF8ToUTF16(print_job_->printer().display_name())); + base::string16 message; + if (print_job_->total_page_number() > 1) { + message = l10n_util::GetStringFUTF16( + IDS_PRINT_JOB_NOTIFICATION_MESSAGE, + base::IntToString16(print_job_->total_page_number()), + base::UTF8ToUTF16(print_job_->printer().display_name())); + } else { + message = l10n_util::GetStringFUTF16( + IDS_PRINT_JOB_NOTIFICATION_SINGLE_PAGE_MESSAGE, + base::UTF8ToUTF16(print_job_->printer().display_name())); + } notification_->set_message(message); }
diff --git a/chrome/browser/media/media_engagement_contents_observer.cc b/chrome/browser/media/media_engagement_contents_observer.cc index bb9091f..e3cf786 100644 --- a/chrome/browser/media/media_engagement_contents_observer.cc +++ b/chrome/browser/media/media_engagement_contents_observer.cc
@@ -22,10 +22,17 @@ void MediaEngagementContentsObserver::WebContentsDestroyed() { playback_timer_->Stop(); + ClearPlayerStates(); service_->contents_observers_.erase(this); delete this; } +void MediaEngagementContentsObserver::ClearPlayerStates() { + for (auto const& p : player_states_) + delete p.second; + player_states_.clear(); +} + void MediaEngagementContentsObserver::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!navigation_handle->IsInMainFrame() || @@ -37,6 +44,8 @@ DCHECK(!playback_timer_->IsRunning()); DCHECK(significant_players_.empty()); + ClearPlayerStates(); + url::Origin new_origin(navigation_handle->GetURL()); if (committed_origin_.IsSameOriginWith(new_origin)) return; @@ -60,27 +69,48 @@ UpdateTimer(); } +MediaEngagementContentsObserver::PlayerState* +MediaEngagementContentsObserver::GetPlayerState(const MediaPlayerId& id) { + auto state = player_states_.find(id); + if (state != player_states_.end()) + return state->second; + + PlayerState* new_state = new PlayerState(); + player_states_[id] = new_state; + return new_state; +} + void MediaEngagementContentsObserver::MediaStartedPlaying( const MediaPlayerInfo& media_player_info, const MediaPlayerId& media_player_id) { // TODO(mlamouri): check if: // - the playback has the minimum size requirements; - // - the playback isn't muted. if (!media_player_info.has_audio) return; - DCHECK(significant_players_.find(media_player_id) == - significant_players_.end()); - significant_players_.insert(media_player_id); + GetPlayerState(media_player_id)->playing = true; + MaybeInsertSignificantPlayer(media_player_id); + UpdateTimer(); +} + +void MediaEngagementContentsObserver::MediaMutedStateChanged( + const MediaPlayerId& id, + bool muted_state) { + GetPlayerState(id)->muted = muted_state; + + if (muted_state) + MaybeRemoveSignificantPlayer(id); + else + MaybeInsertSignificantPlayer(id); + UpdateTimer(); } void MediaEngagementContentsObserver::MediaStoppedPlaying( const MediaPlayerInfo& media_player_info, const MediaPlayerId& media_player_id) { - DCHECK(significant_players_.find(media_player_id) != - significant_players_.end()); - significant_players_.erase(media_player_id); + GetPlayerState(media_player_id)->playing = false; + MaybeRemoveSignificantPlayer(media_player_id); UpdateTimer(); } @@ -88,6 +118,12 @@ UpdateTimer(); } +bool MediaEngagementContentsObserver::IsSignificantPlayer( + const MediaPlayerId& id) { + PlayerState* state = GetPlayerState(id); + return !state->muted && state->playing; +} + void MediaEngagementContentsObserver::OnSignificantMediaPlaybackTime() { DCHECK(!significant_playback_recorded_); @@ -99,6 +135,24 @@ // TODO(mlamouri): record the playback into content settings. } +void MediaEngagementContentsObserver::MaybeInsertSignificantPlayer( + const MediaPlayerId& id) { + if (significant_players_.find(id) != significant_players_.end()) + return; + + if (IsSignificantPlayer(id)) + significant_players_.insert(id); +} + +void MediaEngagementContentsObserver::MaybeRemoveSignificantPlayer( + const MediaPlayerId& id) { + if (significant_players_.find(id) == significant_players_.end()) + return; + + if (!IsSignificantPlayer(id)) + significant_players_.erase(id); +} + bool MediaEngagementContentsObserver::AreConditionsMet() const { if (significant_players_.empty() || !is_visible_) return false;
diff --git a/chrome/browser/media/media_engagement_contents_observer.h b/chrome/browser/media/media_engagement_contents_observer.h index 94a57f7..4a5cf41 100644 --- a/chrome/browser/media/media_engagement_contents_observer.h +++ b/chrome/browser/media/media_engagement_contents_observer.h
@@ -25,6 +25,7 @@ void MediaStoppedPlaying(const MediaPlayerInfo& media_player_info, const MediaPlayerId& media_player_id) override; void DidUpdateAudioMutingState(bool muted) override; + void MediaMutedStateChanged(const MediaPlayerId& id, bool muted_state); private: // Only MediaEngagementService can create a MediaEngagementContentsObserver. @@ -55,6 +56,21 @@ // significant playback. std::set<MediaPlayerId> significant_players_; + // A structure containing all the information we have about a player's state. + struct PlayerState { + bool muted = true; + bool playing = false; // Currently playing with an audio track. + }; + std::map<MediaPlayerId, PlayerState*> player_states_; + PlayerState* GetPlayerState(const MediaPlayerId& id); + void ClearPlayerStates(); + + // Inserts/removes players from significant_players_ based on their volume, + // play state and size. + void MaybeInsertSignificantPlayer(const MediaPlayerId& id); + void MaybeRemoveSignificantPlayer(const MediaPlayerId& id); + bool IsSignificantPlayer(const MediaPlayerId& id); + bool is_visible_ = false; bool significant_playback_recorded_ = false;
diff --git a/chrome/browser/media/media_engagement_contents_observer_unittest.cc b/chrome/browser/media/media_engagement_contents_observer_unittest.cc index df49625..3719417 100644 --- a/chrome/browser/media/media_engagement_contents_observer_unittest.cc +++ b/chrome/browser/media/media_engagement_contents_observer_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/media/media_engagement_service_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,6 +29,8 @@ playback_timer_ = new base::MockTimer(true, false); contents_observer_->SetTimerForTest(base::WrapUnique(playback_timer_)); + + ASSERT_FALSE(GetStoredPlayerStatesCount()); } bool IsTimerRunning() const { return playback_timer_->IsRunning(); } @@ -40,6 +43,17 @@ return contents_observer_->significant_players_.size(); } + size_t GetStoredPlayerStatesCount() const { + return contents_observer_->player_states_.size(); + } + + void Navigate(GURL url) { + std::unique_ptr<content::NavigationHandle> test_handle = + content::NavigationHandle::CreateNavigationHandleForTesting( + url, main_rfh(), true /** committed */); + contents_observer_->DidFinishNavigation(test_handle.get()); + } + void SimulatePlaybackStarted(int id) { content::WebContentsObserver::MediaPlayerInfo player_info(true, true); SimulatePlaybackStarted(player_info, id); @@ -51,6 +65,7 @@ content::WebContentsObserver::MediaPlayerId player_id = std::make_pair(nullptr /* RenderFrameHost */, id); contents_observer_->MediaStartedPlaying(player_info, player_id); + SimulateMutedStateChange(id, false); } void SimulatePlaybackStopped(int id) { @@ -60,6 +75,12 @@ contents_observer_->MediaStoppedPlaying(player_info, player_id); } + void SimulateMutedStateChange(int id, bool muted_state) { + content::WebContentsObserver::MediaPlayerId player_id = + std::make_pair(nullptr /* RenderFrameHost */, id); + contents_observer_->MediaMutedStateChanged(player_id, muted_state); + } + void SimulateIsVisible() { contents_observer_->WasShown(); } void SimulateIsHidden() { contents_observer_->WasHidden(); } @@ -129,6 +150,22 @@ SimulatePlaybackStarted(0); EXPECT_TRUE(AreConditionsMet()); + + SimulateMutedStateChange(0, true); + EXPECT_FALSE(AreConditionsMet()); + + SimulatePlaybackStarted(1); + EXPECT_TRUE(AreConditionsMet()); +} + +TEST_F(MediaEngagementContentsObserverTest, EnsureCleanupAfterNavigation) { + EXPECT_FALSE(GetStoredPlayerStatesCount()); + + SimulateMutedStateChange(0, true); + EXPECT_TRUE(GetStoredPlayerStatesCount()); + + Navigate(GURL("https://example.com")); + EXPECT_FALSE(GetStoredPlayerStatesCount()); } TEST_F(MediaEngagementContentsObserverTest, TimerRunsDependingOnConditions) { @@ -152,6 +189,12 @@ SimulatePlaybackStarted(0); EXPECT_TRUE(IsTimerRunning()); + + SimulateMutedStateChange(0, true); + EXPECT_FALSE(IsTimerRunning()); + + SimulatePlaybackStarted(1); + EXPECT_TRUE(IsTimerRunning()); } TEST_F(MediaEngagementContentsObserverTest, TimerDoesNotRunIfEntryRecorded) {
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc index d67c1dd4..0aade3b 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
@@ -62,6 +62,7 @@ PreviewsInfoBarDelegate::Create( web_contents, previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, + false /* is_reload */, base::Bind(&AddPreviewNavigationToBlackListCallback, web_contents->GetBrowserContext(), web_contents->GetController()
diff --git a/chrome/browser/previews/previews_infobar_delegate.cc b/chrome/browser/previews/previews_infobar_delegate.cc index 3f87c2c..d1cce99 100644 --- a/chrome/browser/previews/previews_infobar_delegate.cc +++ b/chrome/browser/previews/previews_infobar_delegate.cc
@@ -122,6 +122,7 @@ previews::PreviewsType previews_type, base::Time previews_freshness, bool is_data_saver_user, + bool is_reload, const OnDismissPreviewsInfobarCallback& on_dismiss_callback) { PreviewsInfoBarTabHelper* infobar_tab_helper = PreviewsInfoBarTabHelper::FromWebContents(web_contents); @@ -136,8 +137,8 @@ return; std::unique_ptr<PreviewsInfoBarDelegate> delegate(new PreviewsInfoBarDelegate( - web_contents, previews_type, previews_freshness, is_data_saver_user, - on_dismiss_callback)); + infobar_tab_helper, previews_type, previews_freshness, is_data_saver_user, + is_reload, on_dismiss_callback)); #if defined(OS_ANDROID) std::unique_ptr<infobars::InfoBar> infobar_ptr( @@ -163,14 +164,17 @@ } PreviewsInfoBarDelegate::PreviewsInfoBarDelegate( - content::WebContents* web_contents, + PreviewsInfoBarTabHelper* infobar_tab_helper, previews::PreviewsType previews_type, base::Time previews_freshness, bool is_data_saver_user, + bool is_reload, const OnDismissPreviewsInfobarCallback& on_dismiss_callback) : ConfirmInfoBarDelegate(), + infobar_tab_helper_(infobar_tab_helper), previews_type_(previews_type), previews_freshness_(previews_freshness), + is_reload_(is_reload), infobar_dismissed_action_(INFOBAR_DISMISSED_BY_TAB_CLOSURE), message_text_(l10n_util::GetStringUTF16( is_data_saver_user ? IDS_PREVIEWS_INFOBAR_SAVED_DATA_TITLE @@ -283,6 +287,13 @@ int staleness_in_minutes = (network_time - previews_freshness_).InMinutes(); if (staleness_in_minutes < min_staleness_in_minutes) { + if (is_reload_) { + RecordStaleness(TIMESTAMP_UPDATED_NOW_SHOWN); + if (infobar_tab_helper_) + infobar_tab_helper_->set_displayed_preview_timestamp(true); + return l10n_util::GetStringUTF16( + IDS_PREVIEWS_INFOBAR_TIMESTAMP_UPDATED_NOW); + } RecordStaleness(TIMESTAMP_NOT_SHOWN_PREVIEW_NOT_STALE); return base::string16(); } @@ -292,6 +303,8 @@ } RecordStaleness(TIMESTAMP_SHOWN); + if (infobar_tab_helper_) + infobar_tab_helper_->set_displayed_preview_timestamp(true); if (staleness_in_minutes < 60) { return l10n_util::GetStringFUTF16(
diff --git a/chrome/browser/previews/previews_infobar_delegate.h b/chrome/browser/previews/previews_infobar_delegate.h index 09ccb493..ae14d8ed 100644 --- a/chrome/browser/previews/previews_infobar_delegate.h +++ b/chrome/browser/previews/previews_infobar_delegate.h
@@ -11,6 +11,8 @@ #include "components/infobars/core/confirm_infobar_delegate.h" #include "components/previews/core/previews_experiments.h" +class PreviewsInfoBarTabHelper; + namespace content { class WebContents; } @@ -43,6 +45,7 @@ TIMESTAMP_NOT_SHOWN_PREVIEW_NOT_STALE = 1, TIMESTAMP_NOT_SHOWN_STALENESS_NEGATIVE = 2, TIMESTAMP_NOT_SHOWN_STALENESS_GREATER_THAN_MAX = 3, + TIMESTAMP_UPDATED_NOW_SHOWN = 4, TIMESTAMP_INDEX_BOUNDARY }; @@ -55,6 +58,7 @@ previews::PreviewsType previews_type, base::Time previews_freshness, bool is_data_saver_user, + bool is_reload, const OnDismissPreviewsInfobarCallback& on_dismiss_callback); // ConfirmInfoBarDelegate overrides: @@ -66,10 +70,11 @@ private: PreviewsInfoBarDelegate( - content::WebContents* web_contents, + PreviewsInfoBarTabHelper* infobar_tab_helper, previews::PreviewsType previews_type, base::Time previews_freshness, bool is_data_saver_user, + bool is_reload, const OnDismissPreviewsInfobarCallback& on_dismiss_callback); // ConfirmInfoBarDelegate overrides: @@ -79,10 +84,12 @@ int GetButtons() const override; bool LinkClicked(WindowOpenDisposition disposition) override; + PreviewsInfoBarTabHelper* infobar_tab_helper_; previews::PreviewsType previews_type_; // The time at which the preview associated with this infobar was created. A // value of zero means that the creation time is unknown. const base::Time previews_freshness_; + const bool is_reload_; mutable PreviewsInfoBarAction infobar_dismissed_action_; const base::string16 message_text_;
diff --git a/chrome/browser/previews/previews_infobar_delegate_unittest.cc b/chrome/browser/previews/previews_infobar_delegate_unittest.cc index 49b3b0f..4574a03a 100644 --- a/chrome/browser/previews/previews_infobar_delegate_unittest.cc +++ b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
@@ -171,9 +171,10 @@ PreviewsInfoBarDelegate* CreateInfoBar(previews::PreviewsType type, base::Time previews_freshness, - bool is_data_saver_user) { + bool is_data_saver_user, + bool is_reload) { PreviewsInfoBarDelegate::Create( - web_contents(), type, previews_freshness, is_data_saver_user, + web_contents(), type, previews_freshness, is_data_saver_user, is_reload, base::Bind(&PreviewsInfoBarDelegateUnitTest::OnDismissPreviewsInfobar, base::Unretained(this))); @@ -207,12 +208,13 @@ void TestStalePreviews( int staleness_in_minutes, + bool is_reload, base::string16 expected_timestamp, PreviewsInfoBarDelegate::PreviewsInfoBarTimestamp expected_bucket) { PreviewsInfoBarDelegate* infobar = CreateInfoBar( previews::PreviewsType::LITE_PAGE, base::Time::Now() - base::TimeDelta::FromMinutes(staleness_in_minutes), - true /* is_data_saver_user */); + true /* is_data_saver_user */, is_reload); EXPECT_EQ(expected_timestamp, infobar->GetTimestampText()); tester_->ExpectBucketCount(kUMAPreviewsInfoBarTimestamp, expected_bucket, 1); @@ -241,13 +243,14 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestNavigationDismissal) { CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Try showing a second infobar. Another should not be shown since the page // has not navigated. PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, + false /* is_reload */, PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback()); EXPECT_EQ(1U, infobar_service()->infobar_count()); @@ -268,13 +271,14 @@ NavigateAndCommit(GURL(kTestUrl)); CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Try showing a second infobar. Another should not be shown since the page // has not navigated. PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, + false /* is_reload */, PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback()); EXPECT_EQ(1U, infobar_service()->infobar_count()); @@ -304,7 +308,7 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestUserDismissal) { ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Simulate dismissing the infobar. infobar->InfoBarDismissed(); @@ -321,7 +325,7 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestTabClosedDismissal) { CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Delete the infobar without any other infobar actions. infobar_service()->infobar_at(0)->RemoveSelf(); @@ -358,7 +362,7 @@ ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Simulate clicking the infobar link. if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB)) @@ -387,7 +391,7 @@ ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LITE_PAGE, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Simulate clicking the infobar link. if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB)) @@ -416,7 +420,7 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestShownOncePerNavigation) { ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Simulate dismissing the infobar. infobar->InfoBarDismissed(); @@ -426,6 +430,7 @@ PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, + false /* is_reload */, PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback()); // Infobar should not be shown again since a navigation hasn't happened. @@ -434,13 +439,13 @@ // Navigate and show infobar again. NavigateAndCommit(GURL(kTestUrl)); CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); } TEST_F(PreviewsInfoBarDelegateUnitTest, LoFiInfobarTest) { ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LOFI, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); tester_->ExpectUniqueSample(kUMAPreviewsInfoBarActionLoFi, PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1); @@ -462,7 +467,7 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, PreviewInfobarTest) { PreviewsInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LITE_PAGE, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); tester_->ExpectUniqueSample(kUMAPreviewsInfoBarActionLitePage, PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1); @@ -486,7 +491,7 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, OfflineInfobarNonDataSaverUserTest) { PreviewsInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::OFFLINE, base::Time(), - false /* is_data_saver_user */); + false /* is_data_saver_user */, false /* is_reload */); tester_->ExpectUniqueSample(kUMAPreviewsInfoBarActionOffline, PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1); @@ -510,7 +515,7 @@ TEST_F(PreviewsInfoBarDelegateUnitTest, OfflineInfobarDataSaverUserTest) { PreviewsInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::OFFLINE, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); tester_->ExpectUniqueSample(kUMAPreviewsInfoBarActionOffline, PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1); @@ -539,7 +544,7 @@ ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::OFFLINE, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); tester_->ExpectUniqueSample(kUMAPreviewsInfoBarActionOffline, PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1); @@ -569,7 +574,7 @@ ConfirmInfoBarDelegate* infobar = CreateInfoBar(previews::PreviewsType::LITE_PAGE, base::Time(), - true /* is_data_saver_user */); + true /* is_data_saver_user */, false /* is_reload */); // Simulate clicking the infobar link. if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB)) @@ -620,7 +625,7 @@ int staleness_in_minutes = 5; TestStalePreviews( - staleness_in_minutes, + staleness_in_minutes, false /* is_reload */, l10n_util::GetStringFUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_MINUTES, base::IntToString16(staleness_in_minutes)), PreviewsInfoBarDelegate::TIMESTAMP_SHOWN); @@ -633,7 +638,7 @@ int staleness_in_minutes = 65; TestStalePreviews( - staleness_in_minutes, + staleness_in_minutes, false /* is_reload */, l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_ONE_HOUR), PreviewsInfoBarDelegate::TIMESTAMP_SHOWN); } @@ -645,7 +650,7 @@ int staleness_in_hours = 2; TestStalePreviews( - staleness_in_hours * 60, + staleness_in_hours * 60, false /* is_reload */, l10n_util::GetStringFUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_HOURS, base::IntToString16(staleness_in_hours)), PreviewsInfoBarDelegate::TIMESTAMP_SHOWN); @@ -658,13 +663,13 @@ EnableStalePreviewsTimestamp(variation_params); TestStalePreviews( - 1, + 1, false /* is_reload */, l10n_util::GetStringFUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_MINUTES, base::IntToString16(1)), PreviewsInfoBarDelegate::TIMESTAMP_SHOWN); TestStalePreviews( - 6, base::string16(), + 6, false /* is_reload */, base::string16(), PreviewsInfoBarDelegate::TIMESTAMP_NOT_SHOWN_STALENESS_GREATER_THAN_MAX); } @@ -674,12 +679,31 @@ EnableStalePreviewsTimestamp(variation_params); TestStalePreviews( - 1, base::string16(), + 1, false /* is_reload */, base::string16(), PreviewsInfoBarDelegate::TIMESTAMP_NOT_SHOWN_PREVIEW_NOT_STALE); TestStalePreviews( - -1, base::string16(), + -1, false /* is_reload */, base::string16(), PreviewsInfoBarDelegate::TIMESTAMP_NOT_SHOWN_STALENESS_NEGATIVE); TestStalePreviews( - 1441, base::string16(), + 1441, false /* is_reload */, base::string16(), PreviewsInfoBarDelegate::TIMESTAMP_NOT_SHOWN_STALENESS_GREATER_THAN_MAX); } + +TEST_F(PreviewsInfoBarDelegateUnitTest, PreviewInfobarTimestampReloadTest) { + // Use default params. + std::map<std::string, std::string> variation_params; + EnableStalePreviewsTimestamp(variation_params); + int staleness_in_minutes = 5; + + TestStalePreviews( + staleness_in_minutes, false /* is_reload */, + l10n_util::GetStringFUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_MINUTES, + base::IntToString16(staleness_in_minutes)), + PreviewsInfoBarDelegate::TIMESTAMP_SHOWN); + + staleness_in_minutes = 1; + TestStalePreviews( + staleness_in_minutes, true /* is_reload */, + l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_UPDATED_NOW), + PreviewsInfoBarDelegate::TIMESTAMP_UPDATED_NOW_SHOWN); +}
diff --git a/chrome/browser/previews/previews_infobar_tab_helper.cc b/chrome/browser/previews/previews_infobar_tab_helper.cc index 41dd2ff..ba7aef8d 100644 --- a/chrome/browser/previews/previews_infobar_tab_helper.cc +++ b/chrome/browser/previews/previews_infobar_tab_helper.cc
@@ -58,7 +58,8 @@ content::WebContents* web_contents) : content::WebContentsObserver(web_contents), browser_context_(web_contents->GetBrowserContext()), - displayed_preview_infobar_(false) { + displayed_preview_infobar_(false), + displayed_preview_timestamp_(false) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); } @@ -68,7 +69,14 @@ if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted() || navigation_handle->IsSameDocument()) return; + // The infobar should only be told if the page was a reload if the previous + // page displayed a timestamp. + bool is_reload = + displayed_preview_timestamp_ + ? navigation_handle->GetReloadType() != content::ReloadType::NONE + : false; displayed_preview_infobar_ = false; + displayed_preview_timestamp_ = false; ClearLastNavigationAsync(); committed_data_saver_navigation_id_.reset(); @@ -105,7 +113,7 @@ web_contents()->GetBrowserContext()); PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::OFFLINE, - base::Time() /* previews_freshness */, + base::Time() /* previews_freshness */, false /* is_reload */, data_reduction_proxy_settings && data_reduction_proxy_settings->IsDataReductionProxyEnabled(), base::Bind(&AddPreviewNavigationCallback, browser_context_, @@ -123,7 +131,7 @@ headers->GetDateValue(&previews_freshness); PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LITE_PAGE, previews_freshness, - true /* is_data_saver_user */, + true /* is_data_saver_user */, is_reload, base::Bind(&AddPreviewNavigationCallback, browser_context_, navigation_handle->GetRedirectChain()[0], previews::PreviewsType::LITE_PAGE));
diff --git a/chrome/browser/previews/previews_infobar_tab_helper.h b/chrome/browser/previews/previews_infobar_tab_helper.h index 949ac7e..19a8ded 100644 --- a/chrome/browser/previews/previews_infobar_tab_helper.h +++ b/chrome/browser/previews/previews_infobar_tab_helper.h
@@ -31,6 +31,13 @@ displayed_preview_infobar_ = displayed; } + // Sets whether the timestamp on the InfoBar for a preview has been shown for + // the page. |displayed_preview_timestamp_| is reset to false on + // DidStartProvisionalLoadForFrame for the main frame. + void set_displayed_preview_timestamp(bool displayed_preview_timestamp) { + displayed_preview_timestamp_ = displayed_preview_timestamp; + } + // The data saver page identifier of the current page load. const base::Optional<data_reduction_proxy::NavigationID>& committed_data_saver_navigation_id() { @@ -56,6 +63,9 @@ // True if the InfoBar for a preview has been shown for the page. bool displayed_preview_infobar_; + // True if the InfoBar with a timestamp was shown for the page. + bool displayed_preview_timestamp_; + // The data saver page identifier of the current page load. base::Optional<data_reduction_proxy::NavigationID> committed_data_saver_navigation_id_;
diff --git a/chrome/browser/resource_coordinator/DEPS b/chrome/browser/resource_coordinator/DEPS index 57c4684..0fecc23 100644 --- a/chrome/browser/resource_coordinator/DEPS +++ b/chrome/browser/resource_coordinator/DEPS
@@ -3,4 +3,5 @@ "+ash/multi_profile_uma.h", "+ash/shell.h", "+ash/shell_port.h", + "+services/resource_coordinator/public", ]
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc index 62d5c11..7adf73b 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc +++ b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.cc
@@ -4,21 +4,72 @@ #include "chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h" +#include <utility> + +#include "components/ukm/public/interfaces/ukm_interface.mojom.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/service_manager_connection.h" +#include "content/public/common/service_names.mojom.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h" +#include "services/resource_coordinator/public/interfaces/service_callbacks.mojom.h" +#include "services/resource_coordinator/public/interfaces/service_constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY(ResourceCoordinatorWebContentsObserver); +bool ResourceCoordinatorWebContentsObserver::ukm_recorder_initialized = false; + ResourceCoordinatorWebContentsObserver::ResourceCoordinatorWebContentsObserver( content::WebContents* web_contents) : WebContentsObserver(web_contents) { + service_manager::Connector* connector = + content::ServiceManagerConnection::GetForProcess()->GetConnector(); + tab_resource_coordinator_ = base::MakeUnique<resource_coordinator::ResourceCoordinatorInterface>( - content::ServiceManagerConnection::GetForProcess()->GetConnector(), - resource_coordinator::CoordinationUnitType::kWebContents); + connector, resource_coordinator::CoordinationUnitType::kWebContents); + + connector->BindInterface(resource_coordinator::mojom::kServiceName, + mojo::MakeRequest(&service_callbacks_)); + + EnsureUkmRecorderInterface(); +} + +// TODO(matthalp) integrate into ResourceCoordinatorService once the UKM mojo +// interface can be accessed directly within GRC. GRC cannot currently use +// the UKM mojo inteface directly because of software layering issues +// (i.e. the UKM mojo interface is only reachable from the content_browser +// service which cannot be accesses by services in the services/ directory). +// Instead the ResourceCoordinatorWebContentsObserver is used as it lives +// within the content_browser service and can initialize the +// UkmRecorderInterface and pass that interface into GRC through +// resource_coordinator::mojom::ServiceCallbacks. +void ResourceCoordinatorWebContentsObserver::EnsureUkmRecorderInterface() { + if (ukm_recorder_initialized) { + return; + } + + service_callbacks_->IsUkmRecorderInterfaceInitialized(base::Bind( + &ResourceCoordinatorWebContentsObserver::MaybeSetUkmRecorderInterface, + base::Unretained(this))); +} + +void ResourceCoordinatorWebContentsObserver::MaybeSetUkmRecorderInterface( + bool ukm_recorder_already_initialized) { + if (ukm_recorder_already_initialized) { + return; + } + + ukm::mojom::UkmRecorderInterfacePtr ukm_recorder_interface; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(content::mojom::kBrowserServiceName, + mojo::MakeRequest(&ukm_recorder_interface)); + service_callbacks_->SetUkmRecorderInterface( + std::move(ukm_recorder_interface)); + ukm_recorder_initialized = true; } ResourceCoordinatorWebContentsObserver::
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h index db50288..16d9e7c7 100644 --- a/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h +++ b/chrome/browser/resource_coordinator/resource_coordinator_web_contents_observer.h
@@ -5,10 +5,13 @@ #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_RESOURCE_COORDINATOR_WEB_CONTENTS_OBSERVER_H_ #define CHROME_BROWSER_RESOURCE_COORDINATOR_RESOURCE_COORDINATOR_WEB_CONTENTS_OBSERVER_H_ +#include <memory> + #include "base/macros.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "services/resource_coordinator/public/cpp/resource_coordinator_interface.h" +#include "services/resource_coordinator/public/interfaces/service_callbacks.mojom.h" class ResourceCoordinatorWebContentsObserver : public content::WebContentsObserver, @@ -17,6 +20,7 @@ public: ~ResourceCoordinatorWebContentsObserver() override; + static bool ukm_recorder_initialized; static bool IsEnabled(); resource_coordinator::ResourceCoordinatorInterface* @@ -30,6 +34,9 @@ void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; + void EnsureUkmRecorderInterface(); + void MaybeSetUkmRecorderInterface(bool ukm_recorder_already_initialized); + private: explicit ResourceCoordinatorWebContentsObserver( content::WebContents* web_contents); @@ -40,6 +47,8 @@ std::unique_ptr<resource_coordinator::ResourceCoordinatorInterface> tab_resource_coordinator_; + resource_coordinator::mojom::ServiceCallbacksPtr service_callbacks_; + DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorWebContentsObserver); };
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js index fdaae352..60580fd 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -45,7 +45,7 @@ * Flag set to indicate whether ChromeVox uses experimental rich text support. * @type {boolean} */ -editing.useRichText = false; +editing.useRichText = true; editing.TextEditHandler.prototype = { /** @return {!AutomationNode} */ @@ -313,6 +313,11 @@ new Range(cur.start_, cur.end_), new Range(prev.start_, prev.end_), Output.EventType.NAVIGATE) .go(); + } else if (!cur.hasCollapsedSelection()) { + // This is a selection. + cvox.ChromeVox.tts.speak(cur.selectedText, cvox.QueueMode.CATEGORY_FLUSH); + cvox.ChromeVox.tts.speak(Msgs.getMsg('selected'), cvox.QueueMode.QUEUE); + this.brailleCurrentRichLine_(); } else { // Describe the current line. This accounts for previous/current // selections and picking the line edge boundary that changed (as computed @@ -360,6 +365,8 @@ */ speakTextStyle_: function(style, opt_end) { var msgs = []; + if (style.state.linked) + msgs.push(opt_end ? 'link_end' : 'link_start'); if (style.bold) msgs.push(opt_end ? 'bold_end' : 'bold_start'); if (style.italic) @@ -724,6 +731,16 @@ return this.value_.toString(); }, + /** @return {string} */ + get selectedText() { + return this.value_.toString().substring(this.startOffset, this.endOffset); + }, + + /** @return {boolean} */ + hasCollapsedSelection: function() { + return this.start_.equals(this.end_); + }, + /** * Returns true if |otherLine| surrounds the same line as |this|. Note that * the contents of the line might be different.
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs index 23bc7d14..79809daa 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs
@@ -32,6 +32,7 @@ }, assertLineData: function(doc, data) { + editing.useRichText = false; this.runWithLoadedTree(doc, function(root) { var input = root.find({role: RoleType.TEXT_FIELD}); input.addEventListener('focus', this.newCallback(function() { @@ -213,7 +214,6 @@ }); TEST_F('EditingTest', 'RichTextMoveByLine', function() { - editing.useRichText = true; var mockFeedback = this.createMockFeedback(); this.runWithLoadedTree(function() {/*! <div id="go" role="textbox" contenteditable> @@ -261,7 +261,6 @@ }); TEST_F('EditingTest', 'RichTextMoveByCharacter', function() { - editing.useRichText = true; var mockFeedback = this.createMockFeedback(); this.runWithLoadedTree(function() {/*! <div id="go" role="textbox" contenteditable>This <b>is</b> a test.</div> @@ -332,7 +331,6 @@ // Tests specifically for cursor workarounds. TEST_F('EditingTest', 'RichTextMoveByCharacterNodeWorkaround', function() { - editing.useRichText = true; var mockFeedback = this.createMockFeedback(); this.runWithLoadedTree(function() {/*! <div id="go" role="textbox" contenteditable>hello <b>world</b></div> @@ -374,7 +372,6 @@ }); TEST_F('EditingTest', 'RichTextMoveByCharacterEndOfLine', function() { - editing.useRichText = true; var mockFeedback = this.createMockFeedback(); this.runWithLoadedTree(function() {/*! <div id="go" role="textbox" contenteditable>Test</div> @@ -410,6 +407,83 @@ }); }); +TEST_F('EditingTest', 'RichTextLinkOutput', function() { + var mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree(function() {/*! + <div id="go" role="textbox" contenteditable>a <a href="#">test</a></div> + + <script> + document.getElementById('go').addEventListener('click', function() { + var sel = getSelection(); + sel.modify('move', 'forward', 'character'); + }, true); + </script> + */}, function(root) { + var input = root.find({role: RoleType.TEXT_FIELD}); + var moveByChar = input.doDefault.bind(input); + var lineText = 'a test'; + + this.listenOnce(input, 'focus', function() { + mockFeedback.call(moveByChar) + .expectSpeech(' ') + .expectBraille(lineText, { startIndex: 1, endIndex: 1 }) + .call(moveByChar) + .expectSpeech('t') + .expectSpeech('Link start') + .expectSpeech('Underline start') + .expectBraille(lineText, { startIndex: 2, endIndex: 2 }) + .call(moveByChar) + .expectSpeech('e') + .expectBraille(lineText, { startIndex: 3, endIndex: 3 }) + .call(moveByChar) + .expectSpeech('s') + .expectBraille(lineText, { startIndex: 4, endIndex: 4 }) + .call(moveByChar) + .expectSpeech('t') + .expectSpeech('Link end') + .expectSpeech('Underline end') + .expectBraille(lineText, { startIndex: 5, endIndex: 5 }) + + .replay(); + }); + input.focus(); + }); +}); + +TEST_F('EditingTest', 'RichTextExtendByCharacter', function() { + var mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree(function() {/*! + <div id="go" role="textbox" contenteditable>Te<br>st</div> + + <script> + document.getElementById('go').addEventListener('click', function() { + var sel = getSelection(); + sel.modify('extend', 'forward', 'character'); + }, true); + </script> + */}, function(root) { + var input = root.find({role: RoleType.TEXT_FIELD}); + var moveByChar = input.doDefault.bind(input); + + this.listenOnce(input, 'focus', function() { + mockFeedback.call(moveByChar) + .expectSpeech('T', 'selected') + .call(moveByChar) + .expectSpeech('e', 'added to selection') + .call(moveByChar) + .expectSpeech('selected') + .call(moveByChar) + // This gets described by the line logic in EditableLine. + .expectSpeech('s', 'selected') + .call(moveByChar) + .expectSpeech('t', 'added to selection') + + .replay(); + }); + input.focus(); + }); +}); + TEST_F('EditingTest', 'EditableLineOneStaticText', function() { this.runWithLoadedTree(function() {/*! <p contenteditable style="word-spacing:100000px">this is a test</p>
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index 6e4b026..3ef777b 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2772,6 +2772,12 @@ <message desc="Spoken when a user navigates to the end of strike through text." name="IDS_CHROMEVOX_LINE_THROUGH_END"> Strike through end </message> + <message desc="Spoken when a user navigates to the beginning of a link's text." name="IDS_CHROMEVOX_LINK_START"> + Link start + </message> + <message desc="Spoken when a user navigates to the end of a link's text." name="IDS_CHROMEVOX_LINK_END"> + Link end + </message> </messages> </release> </grit>
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html index 237ed717..9f5f5a1d 100644 --- a/chrome/browser/resources/md_extensions/manager.html +++ b/chrome/browser/resources/md_extensions/manager.html
@@ -80,8 +80,7 @@ on-cr-toolbar-menu-tap="onMenuButtonTap_" on-search-changed="onFilterChanged_"> </extensions-toolbar> - <dialog id="drawer" is="cr-drawer"> - <div class="drawer-header">$i18n{toolbarTitle}</div> + <dialog id="drawer" is="cr-drawer" title="$i18n{toolbarTitle}"> <div class="drawer-content"> <extensions-sidebar></extensions-sidebar> </div>
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/md_history/app.html index e7de3247..c36a5bd1 100644 --- a/chrome/browser/resources/md_history/app.html +++ b/chrome/browser/resources/md_history/app.html
@@ -113,8 +113,7 @@ </div> <template is="cr-lazy-render" id="drawer"> - <dialog is="cr-drawer" swipe-open> - <div class="drawer-header">$i18n{title}</div> + <dialog is="cr-drawer" title="$i18n{title}" swipe-open> <history-side-bar id="drawer-side-bar" class="drawer-content" selected-page="{{selectedPage_}}" show-footer="[[showSidebarFooter]]">
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js index f84f893c..1a2b0e6 100644 --- a/chrome/browser/resources/print_preview/native_layer.js +++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -88,9 +88,6 @@ // Bind global handlers global.setUseCloudPrint = this.onSetUseCloudPrint_.bind(this); global.reloadPrintersList = this.onReloadPrintersList_.bind(this); - global.printToCloud = this.onPrintToCloud_.bind(this); - global.fileSelectionCancelled = this.onFileSelectionCancelled_.bind(this); - global.fileSelectionCompleted = this.onFileSelectionCompleted_.bind(this); global.printPreviewFailed = this.onPrintPreviewFailed_.bind(this); global.invalidPrinterSettings = this.onInvalidPrinterSettings_.bind(this); global.onDidGetDefaultPageLayout = @@ -137,9 +134,6 @@ CLOUD_PRINT_ENABLE: 'print_preview.NativeLayer.CLOUD_PRINT_ENABLE', DESTINATIONS_RELOAD: 'print_preview.NativeLayer.DESTINATIONS_RELOAD', DISABLE_SCALING: 'print_preview.NativeLayer.DISABLE_SCALING', - FILE_SELECTION_CANCEL: 'print_preview.NativeLayer.FILE_SELECTION_CANCEL', - FILE_SELECTION_COMPLETE: - 'print_preview.NativeLayer.FILE_SELECTION_COMPLETE', MANIPULATE_SETTINGS_FOR_TEST: 'print_preview.NativeLayer.MANIPULATE_SETTINGS_FOR_TEST', PAGE_COUNT_READY: 'print_preview.NativeLayer.PAGE_COUNT_READY', @@ -149,7 +143,6 @@ 'print_preview.NativeLayer.PREVIEW_GENERATION_DONE', PREVIEW_GENERATION_FAIL: 'print_preview.NativeLayer.PREVIEW_GENERATION_FAIL', - PRINT_TO_CLOUD: 'print_preview.NativeLayer.PRINT_TO_CLOUD', SETTINGS_INVALID: 'print_preview.NativeLayer.SETTINGS_INVALID', PRINT_PRESET_OPTIONS: 'print_preview.NativeLayer.PRINT_PRESET_OPTIONS', }; @@ -420,8 +413,10 @@ * system's preview application. * @param {boolean=} opt_showSystemDialog Whether to open system dialog for * advanced settings. + * @return {!Promise} Promise that will resolve when the print request is + * finished or rejected. */ - startPrint: function( + print: function( destination, printTicketStore, cloudPrintInterface, documentInfo, opt_isOpenPdfInPreview, opt_showSystemDialog) { assert( @@ -497,7 +492,7 @@ ticket['OpenPDFInPreview'] = true; } - chrome.send('print', [JSON.stringify(ticket)]); + return cr.sendWithPromise('print', JSON.stringify(ticket)); }, /** Requests that the current pending print request be cancelled. */ @@ -511,9 +506,16 @@ chrome.send('showSystemDialog'); }, - /** Closes the print preview dialog. */ - startCloseDialog: function() { - chrome.send('closePrintPreviewDialog'); + /** + * Closes the print preview dialog. + * If |isCancel| is true, also sends a message to Print Preview Handler in + * order to update UMA statistics. + * @param {boolean} isCancel whether this was called due to the user + * closing the dialog without printing. + */ + startCloseDialog: function(isCancel) { + if (isCancel) + chrome.send('closePrintPreviewDialog'); chrome.send('dialogClose'); }, @@ -573,41 +575,6 @@ }, /** - * Called from the C++ layer. - * Take the PDF data handed to us and submit it to the cloud, closing the - * print preview dialog once the upload is successful. - * @param {string} data Data to send as the print job. - * @private - */ - onPrintToCloud_: function(data) { - var printToCloudEvent = new Event(NativeLayer.EventType.PRINT_TO_CLOUD); - printToCloudEvent.data = data; - this.eventTarget_.dispatchEvent(printToCloudEvent); - }, - - /** - * Called from PrintPreviewUI::OnFileSelectionCancelled to notify the print - * preview dialog regarding the file selection cancel event. - * @private - */ - onFileSelectionCancelled_: function() { - cr.dispatchSimpleEvent( - this.eventTarget_, NativeLayer.EventType.FILE_SELECTION_CANCEL); - }, - - /** - * Called from PrintPreviewUI::OnFileSelectionCompleted to notify the print - * preview dialog regarding the file selection completed event. - * @private - */ - onFileSelectionCompleted_: function() { - // If the file selection is completed and the dialog is not already closed - // it means that a pending print to pdf request exists. - cr.dispatchSimpleEvent( - this.eventTarget_, NativeLayer.EventType.FILE_SELECTION_COMPLETE); - }, - - /** * Display an error message when print preview fails. * Called from PrintPreviewMessageHandler::OnPrintPreviewFailed(). * @private
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index 1162a515..741a50e 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -352,18 +352,6 @@ this.onCloudPrintEnable_.bind(this)); this.tracker.add( nativeLayerEventTarget, - print_preview.NativeLayer.EventType.PRINT_TO_CLOUD, - this.onPrintToCloud_.bind(this)); - this.tracker.add( - nativeLayerEventTarget, - print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL, - this.onFileSelectionCancel_.bind(this)); - this.tracker.add( - nativeLayerEventTarget, - print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE, - this.onFileSelectionComplete_.bind(this)); - this.tracker.add( - nativeLayerEventTarget, print_preview.NativeLayer.EventType.SETTINGS_INVALID, this.onSettingsInvalid_.bind(this)); this.tracker.add( @@ -544,9 +532,8 @@ this.setIsEnabled_(false); this.printHeader_.isCancelButtonEnabled = true; var printAttemptResult = this.printIfReady_(); - if (printAttemptResult == print_preview.PrintAttemptResult_.PRINTED || - printAttemptResult == - print_preview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) { + if (printAttemptResult == + print_preview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) { if ((this.destinationStore_.selectedDestination.isLocal && !this.destinationStore_.selectedDestination.isPrivet && !this.destinationStore_.selectedDestination.isExtension && @@ -590,23 +577,54 @@ print_preview.Metrics.PrintSettingsUiBucket .PRINT_WITH_SETTINGS_COLLAPSED); } - this.nativeLayer_.startPrint( - assert(this.destinationStore_.selectedDestination), - this.printTicketStore_, this.cloudPrintInterface_, this.documentInfo_, + var destination = assert(this.destinationStore_.selectedDestination); + var whenPrintDone = this.nativeLayer_.print( + destination, this.printTicketStore_, this.cloudPrintInterface_, + this.documentInfo_, this.uiState_ == PrintPreviewUiState_.OPENING_PDF_PREVIEW, this.showSystemDialogBeforeNextPrint_); + + if (!destination.isLocal) { + // Cloud print resolves when print data is returned to submit to cloud + // print, or if setings are invalid. + whenPrintDone.then( + this.onPrintToCloud_.bind(this), + this.onSettingsInvalid_.bind(this)); + } else if (destination.isPrivet || destination.isExtension) { + // Privet and extension resolve when printing is complete or if there + // is an error printing. + whenPrintDone.then( + this.close_.bind(this, false), + this.onPrintFailed_.bind(this)); + } else if ( + destination.id == + print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) { + // Save as PDF resolves when file selection is completed or cancelled. + whenPrintDone.then( + this.onFileSelectionComplete_.bind(this), + this.onFileSelectionCancel_.bind(this)); + } else { // standard local printer + var boundHideDialog = function () { + this.nativeLayer_.startHideDialog(); + }.bind(this); + // Local printers resolve when print is started. Hide the dialog. + whenPrintDone.then(boundHideDialog, boundHideDialog); + } + this.showSystemDialogBeforeNextPrint_ = false; return print_preview.PrintAttemptResult_.PRINTED; }, /** * Closes the print preview. + * @param {boolean} isCancel Whether this was called due to the user + * closing the dialog without printing. * @private */ - close_: function() { + close_: function(isCancel) { this.exitDocument(); this.uiState_ = PrintPreviewUiState_.CLOSING; - this.nativeLayer_.startCloseDialog(); + this.nativeLayer_.startCloseDialog(isCancel); }, /** @@ -707,10 +725,10 @@ /** * Called from the native layer when ready to print to Google Cloud Print. - * @param {Event} event Contains the body to send in the HTTP request. + * @param {string} data The body to send in the HTTP request. * @private */ - onPrintToCloud_: function(event) { + onPrintToCloud_: function(data) { assert( this.uiState_ == PrintPreviewUiState_.PRINTING, 'Document ready to be sent to the cloud when not in printing ' + @@ -721,7 +739,7 @@ assert(this.destinationStore_.selectedDestination != null); this.cloudPrintInterface_.submit( this.destinationStore_.selectedDestination, this.printTicketStore_, - this.documentInfo_, event.data); + this.documentInfo_, data); }, /** @@ -762,7 +780,7 @@ this.uiState_ == PrintPreviewUiState_.PRINTING, 'Submited job to Google Cloud Print but not in printing state ' + this.uiState_); - this.close_(); + this.close_(false); }, /** @@ -857,7 +875,7 @@ * @private */ onCancelButtonClick_: function() { - this.close_(); + this.close_(true); }, /** @@ -885,7 +903,7 @@ // On non-mac with toolkit-views, ESC key is handled by C++-side instead // of JS-side. if (cr.isMac) { - this.close_(); + this.close_(true); e.preventDefault(); } return; @@ -893,7 +911,7 @@ // On Mac, Cmd-. should close the print dialog. if (cr.isMac && e.keyCode == 190 && e.metaKey) { - this.close_(); + this.close_(true); e.preventDefault(); return; } @@ -1027,8 +1045,8 @@ /** * Called when printing to a privet or extension printer fails. - * @param {number | string} httpError The HTTP error code, or -1 if not an - * HTTP error. + * @param {*} httpError The HTTP error code, or -1 or a string describing + * the error, if not an HTTP error. * @private */ onPrintFailed_: function(httpError) { @@ -1256,7 +1274,7 @@ window.open( this.cloudPrintInterface_.baseUrl + '?user=' + this.userInfo_.activeUser + '#printers'); - this.close_(); + this.close_(false); } };
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html index dd4644a..21352c7 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
@@ -62,7 +62,7 @@ <div id="pairedContainer" class="container" scrollable on-device-event="onDeviceEvent_" hidden="[[!showDevices_(bluetoothToggleState, pairedDeviceList_)]]"> - <iron-list id="pairedDevices" class="vertical-list" + <iron-list id="pairedDevices" class="vertical-list" preserve-focus items="[[pairedDeviceList_]]" selection-enabled selected-item="{{selectedPairedItem_}}" scroll-target="pairedContainer"> @@ -87,7 +87,7 @@ <div id="unpairedContainer" class="container" scrollable on-device-event="onDeviceEvent_" hidden="[[!showDevices_(bluetoothToggleState, unpairedDeviceList_)]]"> - <iron-list id="unpairedDevices" class="vertical-list" + <iron-list id="unpairedDevices" class="vertical-list" preserve-focus items="[[unpairedDeviceList_]]" selection-enabled selected-item="{{selectedUnpairedItem_}}" scroll-target="unpairedContainer">
diff --git a/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js b/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js index 902809c..5e63b92 100644 --- a/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js +++ b/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
@@ -39,7 +39,7 @@ */ settings.IdleBehavior = { DISPLAY_OFF_SLEEP: 0, - DISPLAY_OFF_STAY_AWAKE: 1, + DISPLAY_OFF: 1, DISPLAY_ON: 2, OTHER: 3, };
diff --git a/chrome/browser/resources/settings/device_page/power.js b/chrome/browser/resources/settings/device_page/power.js index 49cdeea..61532061 100644 --- a/chrome/browser/resources/settings/device_page/power.js +++ b/chrome/browser/resources/settings/device_page/power.js
@@ -31,8 +31,8 @@ idleControlled_: Boolean, /** @private {boolean} Whether the lid-closed behavior is controlled by - * policy. - */ + * policy. + */ lidClosedControlled_: Boolean, /** @private {boolean} Whether the system posesses a lid. */ @@ -155,8 +155,8 @@ name: loadTimeData.getString('powerIdleDisplayOffSleep'), }, { - value: settings.IdleBehavior.DISPLAY_OFF_STAY_AWAKE, - name: loadTimeData.getString('powerIdleDisplayOffStayAwake'), + value: settings.IdleBehavior.DISPLAY_OFF, + name: loadTimeData.getString('powerIdleDisplayOff'), }, { value: settings.IdleBehavior.DISPLAY_ON,
diff --git a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html index 7df028e..d92f226 100644 --- a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html +++ b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
@@ -48,7 +48,7 @@ </div> <div class="list-frame"> <template is="dom-if" if="[[hasWords_(words_.length)]]"> - <iron-list id="list" items="[[words_]]" + <iron-list id="list" items="[[words_]]" preserve-focus scroll-target="[[subpageScrollTarget]]"> <template> <div class="list-item">
diff --git a/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp b/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp index 5a6fa0d4..d29ed565 100644 --- a/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp
@@ -26,6 +26,7 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink', '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_scrollable_behavior', + '<(EXTERNS_GYP):settings_private', 'startup_urls_page_browser_proxy', 'startup_url_entry', ],
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html index 155ded00..e66cbb3d 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html +++ b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
@@ -32,18 +32,20 @@ </style> <div id="outer" class="layout vertical flex vertical-list"> <div id="container" class="scroll-container" scrollable> - <iron-list items="[[startupPages_]]" scroll-target="container"> + <iron-list items="[[startupPages_]]" scroll-target="container" + preserve-focus> <template> <settings-startup-url-entry model="[[item]]" tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]" last-focused="{{lastFocused_}}" - editable="[[!prefs.session.startup_urls.controlledBy]]"> + editable="[[shouldAllowUrlsEdit_( + prefs.session.startup_urls.enforcement)]]"> </settings-startup-url-entry> </template> </iron-list> </div> - <template is="dom-if" if="[[!prefs.session.startup_urls.controlledBy]]" - restamp> + <template is="dom-if" if="[[shouldAllowUrlsEdit_( + prefs.session.startup_urls.enforcement)]]" restamp> <div class="list-item" id="addPage"> <a is="action-link" class="list-button" on-tap="onAddPageTap_"> $i18n{onStartupAddNewPage}
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js index fbc43d3..38451be 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js +++ b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js
@@ -86,4 +86,14 @@ onUseCurrentPagesTap_: function() { this.browserProxy_.useCurrentPages(); }, + + /** + * @return {boolean} Whether "Add new page" and "Use current pages" are + * allowed. + * @private + */ + shouldAllowUrlsEdit_: function() { + return this.get('prefs.session.startup_urls.enforcement') != + chrome.settingsPrivate.Enforcement.ENFORCED; + }, });
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html index 21caa8d..df0d3e5 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -64,7 +64,7 @@ $i18n{editPasswordPasswordLabel} </div> </div> - <iron-list id="passwordList" + <iron-list id="passwordList" preserve-focus items="[[getFilteredPasswords_(savedPasswords, filter)]]" class="vertical-list list-with-header" scroll-target="[[subpageScrollTarget]]">
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_list.html b/chrome/browser/resources/settings/search_engines_page/search_engines_list.html index 7d71e83b..0b74c3f5 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_list.html +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
@@ -58,7 +58,7 @@ class$="scroll-container [[getHeightClass(scrollTarget)]]" scrollable$="[[isScrollable(scrollTarget)]]"> <iron-list items="[[engines]]" scroll-target="[[scrollTarget]]" - scroll-offset="[[scrollOffset]]"> + scroll-offset="[[scrollOffset]]" preserve-focus> <template> <settings-search-engine-entry engine="[[item]]" tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]"
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html index be6244af..7323258b 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.html +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
@@ -52,7 +52,7 @@ <h2>$i18n{searchEnginesExtension}</h2> </div> <iron-list id="extensions" class="extension-engines fixed-height-list" - items="[[extensions]]"> + items="[[extensions]]" preserve-focus> <template> <settings-omnibox-extension-entry engine="[[item]]" tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]"
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.html b/chrome/browser/resources/settings/settings_ui/settings_ui.html index 0616648..c1f67ff 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.html +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -32,10 +32,6 @@ overflow: hidden; /* Prevent double scroll bar bugs. */ } - .drawer-header { - outline: none; - } - .last { display: flex; justify-content: flex-end; @@ -92,8 +88,8 @@ role="none" show-menu> </cr-toolbar> - <dialog id="drawer" is="cr-drawer" on-close="onMenuClosed_"> - <div class="drawer-header" tabindex="-1">$i18n{settings}</div> + <dialog id="drawer" is="cr-drawer" on-close="onMenuClosed_" + title="$i18n{settings}"> <div class="drawer-content"> <template is="dom-if" id="drawerTemplate"> <settings-menu page-visibility="[[pageVisibility_]]"
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc index e454e1b..f62a78a6 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc +++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -10,11 +10,18 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/crx_file/id_util.h" +#include "components/sync/model/attachments/attachment_service_proxy_for_test.h" +#include "components/sync/model/fake_sync_change_processor.h" +#include "components/sync/model/sync_error_factory.h" +#include "components/sync/model/sync_error_factory_mock.h" +#include "components/sync/protocol/sync.pb.h" #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" #include "ui/app_list/app_list_item.h" #include "ui/app_list/app_list_model.h" +using namespace crx_file::id_util; + namespace { scoped_refptr<extensions::Extension> MakeApp( @@ -46,6 +53,111 @@ return next_app_id; } +constexpr char kUnset[] = "__unset__"; +constexpr char kDefault[] = "__default__"; + +// These constants are defined as functions so their values can be derived via +// function calls. The constant naming scheme is kept to maintain readability. +const std::string kInvalidOrdinalsId() { + return GenerateId("invalid_ordinals"); +} +const std::string kEmptyItemNameId() { + return GenerateId("empty_item_name"); +} +const std::string kEmptyItemNameUnsetId() { + return GenerateId("empty_item_name_unset"); +} +const std::string kEmptyParentId() { + return GenerateId("empty_parent_id"); +} +const std::string kEmptyParentUnsetId() { + return GenerateId("empty_parent_id_unset"); +} +const std::string kEmptyOrdinalsId() { + return GenerateId("empty_ordinals"); +} +const std::string kEmptyOrdinalsUnsetId() { + return GenerateId("empty_ordinals_unset"); +} +const std::string kDupeItemId() { + return GenerateId("dupe_item_id"); +} +const std::string kParentId() { + return GenerateId("parent_id"); +} + +syncer::SyncData CreateAppRemoteData(const std::string& id, + const std::string& name, + const std::string& parent_id, + const std::string& item_ordinal, + const std::string& item_pin_ordinal) { + sync_pb::EntitySpecifics specifics; + sync_pb::AppListSpecifics* app_list = specifics.mutable_app_list(); + if (id != kUnset) + app_list->set_item_id(id); + app_list->set_item_type(sync_pb::AppListSpecifics_AppListItemType_TYPE_APP); + if (name != kUnset) + app_list->set_item_name(name); + if (parent_id != kUnset) + app_list->set_parent_id(parent_id); + if (item_ordinal != kUnset) + app_list->set_item_ordinal(item_ordinal); + if (item_pin_ordinal != kUnset) + app_list->set_item_pin_ordinal(item_pin_ordinal); + + return syncer::SyncData::CreateRemoteData( + std::hash<std::string>{}(id), specifics, base::Time(), + syncer::AttachmentIdList(), + syncer::AttachmentServiceProxyForTest::Create()); +} + +syncer::SyncDataList CreateBadAppRemoteData(const std::string& id) { + syncer::SyncDataList sync_list; + // Invalid item_ordinal and item_pin_ordinal. + sync_list.push_back(CreateAppRemoteData( + id == kDefault ? kInvalidOrdinalsId() : id, "item_name", kParentId(), + "$$invalid_ordinal$$", "$$invalid_ordinal$$")); + // Empty item name. + sync_list.push_back( + CreateAppRemoteData(id == kDefault ? kEmptyItemNameId() : id, "", + kParentId(), "ordinal", "pinordinal")); + sync_list.push_back( + CreateAppRemoteData(id == kDefault ? kEmptyItemNameUnsetId() : id, kUnset, + kParentId(), "ordinal", "pinordinal")); + // Empty parent ID. + sync_list.push_back( + CreateAppRemoteData(id == kDefault ? kEmptyParentId() : id, "item_name", + "", "ordinal", "pinordinal")); + sync_list.push_back( + CreateAppRemoteData(id == kDefault ? kEmptyParentUnsetId() : id, + "item_name", kUnset, "ordinal", "pinordinal")); + // Empty item_ordinal and item_pin_ordinal. + sync_list.push_back( + CreateAppRemoteData(id == kDefault ? kEmptyOrdinalsId() : id, "item_name", + kParentId(), "", "")); + sync_list.push_back( + CreateAppRemoteData(id == kDefault ? kEmptyOrdinalsUnsetId() : id, + "item_name", kParentId(), kUnset, kUnset)); + // Duplicate item_id. + sync_list.push_back(CreateAppRemoteData(id == kDefault ? kDupeItemId() : id, + "item_name", kParentId(), "ordinal", + "pinordinal")); + sync_list.push_back(CreateAppRemoteData(id == kDefault ? kDupeItemId() : id, + "item_name_dupe", kParentId(), + "ordinal", "pinordinal")); + // Empty item_id. + sync_list.push_back(CreateAppRemoteData("", "item_name", kParentId(), + "ordinal", "pinordinal")); + sync_list.push_back(CreateAppRemoteData(kUnset, "item_name", kParentId(), + "ordinal", "pinordinal")); + // All fields empty. + sync_list.push_back(CreateAppRemoteData("", "", "", "", "")); + sync_list.push_back( + CreateAppRemoteData(kUnset, kUnset, kUnset, kUnset, kUnset)); + + return sync_list; +} + } // namespace class AppListSyncableServiceTest : public AppListTestBase { @@ -74,6 +186,16 @@ return app_list_syncable_service_->GetModel(); } + const app_list::AppListSyncableService::SyncItem* GetSyncItem( + const std::string& id) const { + return app_list_syncable_service_->GetSyncItem(id); + } + + protected: + app_list::AppListSyncableService* app_list_syncable_service() { + return app_list_syncable_service_.get(); + } + private: base::ScopedTempDir temp_dir_; std::unique_ptr<app_list::AppListSyncableService> app_list_syncable_service_; @@ -131,3 +253,163 @@ EXPECT_EQ(some_app_index, web_store_app_index + 1); EXPECT_EQ(oem_folder_index, web_store_app_index + 2); } + +TEST_F(AppListSyncableServiceTest, InitialMerge) { + const std::string kItemId1 = GenerateId("item_id1"); + const std::string kItemId2 = GenerateId("item_id2"); + + syncer::SyncDataList sync_list; + sync_list.push_back(CreateAppRemoteData(kItemId1, "item_name1", + GenerateId("parent_id1"), "ordinal", + "pinordinal")); + sync_list.push_back(CreateAppRemoteData(kItemId2, "item_name2", + GenerateId("parent_id2"), "ordinal", + "pinordinal")); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), + base::MakeUnique<syncer::SyncErrorFactoryMock>()); + content::RunAllBlockingPoolTasksUntilIdle(); + + ASSERT_TRUE(GetSyncItem(kItemId1)); + EXPECT_EQ("item_name1", GetSyncItem(kItemId1)->item_name); + EXPECT_EQ(GenerateId("parent_id1"), GetSyncItem(kItemId1)->parent_id); + EXPECT_EQ("ordinal", GetSyncItem(kItemId1)->item_ordinal.ToDebugString()); + EXPECT_EQ("pinordinal", + GetSyncItem(kItemId1)->item_pin_ordinal.ToDebugString()); + + ASSERT_TRUE(GetSyncItem(kItemId2)); + EXPECT_EQ("item_name2", GetSyncItem(kItemId2)->item_name); + EXPECT_EQ(GenerateId("parent_id2"), GetSyncItem(kItemId2)->parent_id); + EXPECT_EQ("ordinal", GetSyncItem(kItemId2)->item_ordinal.ToDebugString()); + EXPECT_EQ("pinordinal", + GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString()); +} + +TEST_F(AppListSyncableServiceTest, InitialMerge_BadData) { + const syncer::SyncDataList sync_list = CreateBadAppRemoteData(kDefault); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), + base::MakeUnique<syncer::SyncErrorFactoryMock>()); + content::RunAllBlockingPoolTasksUntilIdle(); + + // Invalid item_ordinal and item_pin_ordinal. + // Invalid item_ordinal is fixed up. + ASSERT_TRUE(GetSyncItem(kInvalidOrdinalsId())); + EXPECT_EQ("n", + GetSyncItem(kInvalidOrdinalsId())->item_ordinal.ToDebugString()); + EXPECT_EQ( + "INVALID[$$invalid_ordinal$$]", + GetSyncItem(kInvalidOrdinalsId())->item_pin_ordinal.ToDebugString()); + + // Empty item name. + ASSERT_TRUE(GetSyncItem(kEmptyItemNameId())); + EXPECT_EQ("", GetSyncItem(kEmptyItemNameId())->item_name); + EXPECT_TRUE(GetSyncItem(kEmptyItemNameUnsetId())); + EXPECT_EQ("", GetSyncItem(kEmptyItemNameUnsetId())->item_name); + + // Empty parent ID. + ASSERT_TRUE(GetSyncItem(kEmptyParentId())); + EXPECT_EQ("", GetSyncItem(kEmptyParentId())->parent_id); + EXPECT_TRUE(GetSyncItem(kEmptyParentUnsetId())); + EXPECT_EQ("", GetSyncItem(kEmptyParentUnsetId())->parent_id); + + // Empty item_ordinal and item_pin_ordinal. + // Empty item_ordinal is fixed up. + ASSERT_TRUE(GetSyncItem(kEmptyOrdinalsId())); + EXPECT_EQ("n", GetSyncItem(kEmptyOrdinalsId())->item_ordinal.ToDebugString()); + EXPECT_EQ("INVALID[]", + GetSyncItem(kEmptyOrdinalsId())->item_pin_ordinal.ToDebugString()); + ASSERT_TRUE(GetSyncItem(kEmptyOrdinalsUnsetId())); + EXPECT_EQ("n", + GetSyncItem(kEmptyOrdinalsUnsetId())->item_ordinal.ToDebugString()); + EXPECT_EQ( + "INVALID[]", + GetSyncItem(kEmptyOrdinalsUnsetId())->item_pin_ordinal.ToDebugString()); + + // Duplicate item_id overrides previous. + ASSERT_TRUE(GetSyncItem(kDupeItemId())); + EXPECT_EQ("item_name_dupe", GetSyncItem(kDupeItemId())->item_name); +} + +TEST_F(AppListSyncableServiceTest, InitialMergeAndUpdate) { + const std::string kItemId1 = GenerateId("item_id1"); + const std::string kItemId2 = GenerateId("item_id2"); + + syncer::SyncDataList sync_list; + sync_list.push_back(CreateAppRemoteData(kItemId1, "item_name1", kParentId(), + "ordinal", "pinordinal")); + sync_list.push_back(CreateAppRemoteData(kItemId2, "item_name2", kParentId(), + "ordinal", "pinordinal")); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), + base::MakeUnique<syncer::SyncErrorFactoryMock>()); + content::RunAllBlockingPoolTasksUntilIdle(); + + ASSERT_TRUE(GetSyncItem(kItemId1)); + ASSERT_TRUE(GetSyncItem(kItemId2)); + + syncer::SyncChangeList change_list; + change_list.push_back(syncer::SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, + CreateAppRemoteData(kItemId1, "item_name1x", GenerateId("parent_id1x"), + "ordinalx", "pinordinalx"))); + change_list.push_back(syncer::SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, + CreateAppRemoteData(kItemId2, "item_name2x", GenerateId("parent_id2x"), + "ordinalx", "pinordinalx"))); + + app_list_syncable_service()->ProcessSyncChanges(tracked_objects::Location(), + change_list); + content::RunAllBlockingPoolTasksUntilIdle(); + + ASSERT_TRUE(GetSyncItem(kItemId1)); + EXPECT_EQ("item_name1x", GetSyncItem(kItemId1)->item_name); + EXPECT_EQ(GenerateId("parent_id1x"), GetSyncItem(kItemId1)->parent_id); + EXPECT_EQ("ordinalx", GetSyncItem(kItemId1)->item_ordinal.ToDebugString()); + EXPECT_EQ("pinordinalx", + GetSyncItem(kItemId1)->item_pin_ordinal.ToDebugString()); + + ASSERT_TRUE(GetSyncItem(kItemId2)); + EXPECT_EQ("item_name2x", GetSyncItem(kItemId2)->item_name); + EXPECT_EQ(GenerateId("parent_id2x"), GetSyncItem(kItemId2)->parent_id); + EXPECT_EQ("ordinalx", GetSyncItem(kItemId2)->item_ordinal.ToDebugString()); + EXPECT_EQ("pinordinalx", + GetSyncItem(kItemId2)->item_pin_ordinal.ToDebugString()); +} + +TEST_F(AppListSyncableServiceTest, InitialMergeAndUpdate_BadData) { + const std::string kItemId = GenerateId("item_id"); + + syncer::SyncDataList sync_list; + sync_list.push_back(CreateAppRemoteData(kItemId, "item_name", kParentId(), + "ordinal", "pinordinal")); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + base::MakeUnique<syncer::FakeSyncChangeProcessor>(), + base::MakeUnique<syncer::SyncErrorFactoryMock>()); + content::RunAllBlockingPoolTasksUntilIdle(); + + ASSERT_TRUE(GetSyncItem(kItemId)); + + syncer::SyncChangeList change_list; + const syncer::SyncDataList update_list = CreateBadAppRemoteData(kItemId); + for (syncer::SyncDataList::const_iterator iter = update_list.begin(); + iter != update_list.end(); ++iter) { + change_list.push_back(syncer::SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, *iter)); + } + + // Validate items with bad data are processed without crashing. + app_list_syncable_service()->ProcessSyncChanges(tracked_objects::Location(), + change_list); + content::RunAllBlockingPoolTasksUntilIdle(); + + ASSERT_TRUE(GetSyncItem(kItemId)); +}
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc index 8509703..546edc92 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
@@ -11,10 +11,12 @@ ArcAppLauncher::ArcAppLauncher(content::BrowserContext* context, const std::string& app_id, + const base::Optional<std::string>& launch_intent, bool landscape_layout, bool deferred_launch_allowed) : context_(context), app_id_(app_id), + launch_intent_(launch_intent), landscape_layout_(landscape_layout), deferred_launch_allowed_(deferred_launch_allowed) { ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context_); @@ -55,8 +57,10 @@ DCHECK(prefs && prefs->GetApp(app_id_)); prefs->RemoveObserver(this); - if (!arc::LaunchApp(context_, app_id_, landscape_layout_, ui::EF_NONE)) + if (!arc::LaunchAppWithIntent(context_, app_id_, launch_intent_, + landscape_layout_, ui::EF_NONE)) { VLOG(2) << "Failed to launch app: " + app_id_ + "."; + } app_launched_ = true; }
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.h b/chrome/browser/ui/app_list/arc/arc_app_launcher.h index 3043ff0c..5ccf83e 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_launcher.h +++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.h
@@ -8,6 +8,7 @@ #include <string> #include "base/macros.h" +#include "base/optional.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" namespace content { @@ -20,6 +21,7 @@ public: ArcAppLauncher(content::BrowserContext* context, const std::string& app_id, + const base::Optional<std::string>& launch_intent, bool landscape_layout, bool deferred_launch_allowed); ~ArcAppLauncher() override; @@ -36,8 +38,12 @@ // Unowned pointer. content::BrowserContext* context_; - // ARC app id and requested layout. + // ARC app id. const std::string app_id_; + // Optional intent to launch the app. If not set then app is started default + // way. + const base::Optional<std::string> launch_intent_; + // Requested layout. const bool landscape_layout_; // If it is set to true that means app is allowed to launch in deferred mode // once it is registered, regardless it is ready or not. Otherwise app is
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index 8f2ec681..4e0b2fa0 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -1512,11 +1512,13 @@ const std::string id2 = ArcAppTest::GetAppId(app2); const std::string id3 = ArcAppTest::GetAppId(app3); - ArcAppLauncher launcher1(profile(), id1, true, false); + ArcAppLauncher launcher1(profile(), id1, base::Optional<std::string>(), true, + false); EXPECT_FALSE(launcher1.app_launched()); EXPECT_TRUE(prefs->HasObserver(&launcher1)); - ArcAppLauncher launcher3(profile(), id3, true, false); + ArcAppLauncher launcher3(profile(), id3, base::Optional<std::string>(), true, + false); EXPECT_FALSE(launcher1.app_launched()); EXPECT_TRUE(prefs->HasObserver(&launcher1)); EXPECT_FALSE(launcher3.app_launched()); @@ -1535,11 +1537,14 @@ EXPECT_FALSE(prefs->HasObserver(&launcher1)); EXPECT_TRUE(prefs->HasObserver(&launcher3)); - ArcAppLauncher launcher2(profile(), id2, true, false); + const std::string launch_intent2 = arc::GetLaunchIntent( + app2.package_name, app2.activity, std::vector<std::string>()); + ArcAppLauncher launcher2(profile(), id2, launch_intent2, true, false); EXPECT_TRUE(launcher2.app_launched()); EXPECT_FALSE(prefs->HasObserver(&launcher2)); - ASSERT_EQ(2u, app_instance()->launch_requests().size()); - EXPECT_TRUE(app_instance()->launch_requests()[1]->IsForApp(app2)); + EXPECT_EQ(1u, app_instance()->launch_requests().size()); + ASSERT_EQ(1u, app_instance()->launch_intents().size()); + EXPECT_EQ(app_instance()->launch_intents()[0], launch_intent2); } // Validates an app that have no launchable flag. @@ -1704,9 +1709,11 @@ const std::string id2 = ArcAppTest::GetAppId(app2); // Launch when app is registered and ready. - ArcAppLauncher launcher1(profile(), id1, true, false); + ArcAppLauncher launcher1(profile(), id1, base::Optional<std::string>(), true, + false); // Launch when app is registered. - ArcAppLauncher launcher2(profile(), id2, true, true); + ArcAppLauncher launcher2(profile(), id2, base::Optional<std::string>(), true, + true); EXPECT_FALSE(launcher1.app_launched()); EXPECT_FALSE(launcher2.app_launched());
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index 1952536..f3c9ed8a 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -10,6 +10,9 @@ #include "ash/shell.h" #include "base/bind.h" #include "base/json/json_writer.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/synchronization/waitable_event.h" #include "base/values.h" #include "chrome/browser/chromeos/arc/arc_migration_guide_notification.h" @@ -65,6 +68,15 @@ constexpr char kShowTalkbackSettingsIntent[] = "org.chromium.arc.intent_helper.SHOW_TALKBACK_SETTINGS"; +constexpr char kAction[] = "action"; +constexpr char kActionMain[] = "android.intent.action.MAIN"; +constexpr char kCategory[] = "category"; +constexpr char kCategoryLauncher[] = "android.intent.category.LAUNCHER"; +constexpr char kComponent[] = "component"; +constexpr char kEndSuffix[] = "end"; +constexpr char kIntentPrefix[] = "#Intent"; +constexpr char kLaunchFlags[] = "launchFlags"; + // Find a proper size and position for a given rectangle on the screen. // TODO(skuhne): This needs more consideration, but it is lacking // WindowPositioner functionality since we do not have an Aura::Window yet. @@ -103,81 +115,9 @@ ui::EF_FORWARD_MOUSE_BUTTON | ui::EF_FROM_TOUCH)) != 0; } -// A class which handles the asynchronous ARC runtime callback to figure out if -// an app can handle a certain resolution or not. -// After LaunchAndRelease() got called, the object will destroy itself once -// done. -class LaunchAppWithoutSize { - public: - LaunchAppWithoutSize(content::BrowserContext* context, - const std::string& app_id, - bool landscape_mode, - int event_flags) - : context_(context), - app_id_(app_id), - landscape_mode_(landscape_mode), - event_flags_(event_flags) {} - - // This will launch the request and after the return the creator does not - // need to delete the object anymore. - bool LaunchAndRelease() { - landscape_ = landscape_mode_ ? gfx::Rect(0, 0, kNexus7Width, kNexus7Height) - : gfx::Rect(0, 0, kNexus5Width, kNexus5Height); - if (!ash::Shell::HasInstance()) { - // Skip this if there is no Ash shell. - LaunchAppWithRect(context_, app_id_, landscape_, event_flags_); - delete this; - return true; - } - - // TODO(skuhne): Change CanHandleResolution into a call which returns - // capability flags like [PHONE/TABLET]_[LANDSCAPE/PORTRAIT] and which - // might also return the used DP->PIX conversion constant to do better - // size calculations. - bool result = CanHandleResolution( - context_, app_id_, landscape_, - base::Bind(&LaunchAppWithoutSize::Callback, base::Unretained(this))); - if (!result) - delete this; - - return result; - } - - private: - content::BrowserContext* context_; - const std::string app_id_; - const bool landscape_mode_; - gfx::Rect landscape_; - const int event_flags_; - - // The callback handler which gets called from the CanHandleResolution - // function. - void Callback(bool can_handle) { - gfx::Size target_size = - can_handle ? landscape_.size() : gfx::Size(kNexus5Width, kNexus5Height); - LaunchAppWithRect(context_, app_id_, GetTargetRect(target_size), - event_flags_); - // Now that we are done, we can delete ourselves. - delete this; - } - - DISALLOW_COPY_AND_ASSIGN(LaunchAppWithoutSize); -}; - -} // namespace - -const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei"; -const char kLegacyPlayStoreAppId[] = "gpkmicpkkebkmabiaedjognfppcchdfa"; -const char kPlayStorePackage[] = "com.android.vending"; -const char kPlayStoreActivity[] = "com.android.vending.AssetBrowserActivity"; -const char kSettingsAppId[] = "mconboelelhjpkbdhhiijkgcimoangdj"; - -bool ShouldShowInLauncher(const std::string& app_id) { - return (app_id != kSettingsAppId); -} - bool LaunchAppWithRect(content::BrowserContext* context, const std::string& app_id, + const base::Optional<std::string>& launch_intent, const gfx::Rect& target_rect, int event_flags) { ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context); @@ -215,12 +155,13 @@ extras_string); } - if (app_info->shortcut) { + if (app_info->shortcut || launch_intent.has_value()) { // Before calling LaunchIntent, check if the interface is supported. Reusing // the same |app_instance| for LaunchIntent is allowed. if (!GET_APP_INSTANCE(LaunchIntent)) return false; - app_instance->LaunchIntent(app_info->intent_uri, target_rect); + app_instance->LaunchIntent(launch_intent.value_or(app_info->intent_uri), + target_rect); } else { app_instance->LaunchApp(app_info->package_name, app_info->activity, target_rect); @@ -230,6 +171,84 @@ return true; } +// A class which handles the asynchronous ARC runtime callback to figure out if +// an app can handle a certain resolution or not. +// After LaunchAndRelease() is called, the object will destroy itself once done. +class AppLauncher { + public: + AppLauncher(content::BrowserContext* context, + const std::string& app_id, + const base::Optional<std::string>& launch_intent, + bool landscape_mode, + int event_flags) + : context_(context), + app_id_(app_id), + launch_intent_(launch_intent), + landscape_mode_(landscape_mode), + event_flags_(event_flags) {} + + // This will launch the request and after the return the creator does not + // need to delete the object anymore. + bool LaunchAndRelease() { + landscape_ = landscape_mode_ ? gfx::Rect(0, 0, kNexus7Width, kNexus7Height) + : gfx::Rect(0, 0, kNexus5Width, kNexus5Height); + if (!ash::Shell::HasInstance()) { + // Skip this if there is no Ash shell. + LaunchAppWithRect(context_, app_id_, launch_intent_, landscape_, + event_flags_); + delete this; + return true; + } + + // TODO(skuhne): Change CanHandleResolution into a call which returns + // capability flags like [PHONE/TABLET]_[LANDSCAPE/PORTRAIT] and which + // might also return the used DP->PIX conversion constant to do better + // size calculations. base::Unretained is safe because this object is + // responsible for its own deletion. + bool result = CanHandleResolution( + context_, app_id_, landscape_, + base::Bind(&AppLauncher::Callback, base::Unretained(this))); + if (!result) + delete this; + + return result; + } + + private: + content::BrowserContext* const context_; + const std::string app_id_; + const base::Optional<std::string> launch_intent_; + const bool landscape_mode_; + gfx::Rect landscape_; + const int event_flags_; + + // The callback handler which gets called from the CanHandleResolution + // function. + void Callback(bool can_handle) { + gfx::Size target_size = + can_handle ? landscape_.size() : gfx::Size(kNexus5Width, kNexus5Height); + LaunchAppWithRect(context_, app_id_, launch_intent_, + GetTargetRect(target_size), event_flags_); + // Now that we are done, we can delete ourselves. + delete this; + } + + DISALLOW_COPY_AND_ASSIGN(AppLauncher); +}; + +} // namespace + +const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei"; +const char kLegacyPlayStoreAppId[] = "gpkmicpkkebkmabiaedjognfppcchdfa"; +const char kPlayStorePackage[] = "com.android.vending"; +const char kPlayStoreActivity[] = "com.android.vending.AssetBrowserActivity"; +const char kSettingsAppId[] = "mconboelelhjpkbdhhiijkgcimoangdj"; +const char kInitialStartParam[] = "S.org.chromium.arc.start_type=initialStart"; + +bool ShouldShowInLauncher(const std::string& app_id) { + return app_id != kSettingsAppId; +} + bool LaunchAndroidSettingsApp(content::BrowserContext* context, int event_flags) { constexpr bool kUseLandscapeLayout = true; @@ -259,6 +278,18 @@ const std::string& app_id, bool landscape_layout, int event_flags) { + return LaunchAppWithIntent(context, app_id, + base::Optional<std::string>() /* launch_intent */, + landscape_layout, event_flags); +} + +bool LaunchAppWithIntent(content::BrowserContext* context, + const std::string& app_id, + const base::Optional<std::string>& launch_intent, + bool landscape_layout, + int event_flags) { + DCHECK(!launch_intent.has_value() || !launch_intent->empty()); + Profile* const profile = Profile::FromBrowserContext(context); // Even when ARC is not allowed for the profile, ARC apps may still show up @@ -325,8 +356,8 @@ prefs->SetLastLaunchTime(app_id, base::Time::Now()); return true; } - return (new LaunchAppWithoutSize(context, app_id, landscape_layout, - event_flags)) + return (new AppLauncher(context, app_id, launch_intent, landscape_layout, + event_flags)) ->LaunchAndRelease(); } @@ -456,4 +487,101 @@ return arc_prefs->IsRegistered(ArcAppShelfId::FromString(id).app_id()); } +std::string GetLaunchIntent(const std::string& package_name, + const std::string& activity, + const std::vector<std::string>& extra_params) { + std::string extra_params_extracted; + for (const auto& extra_param : extra_params) { + extra_params_extracted += extra_param; + extra_params_extracted += ";"; + } + + // Remove the |package_name| prefix, if activity starts with it. + const char* activity_compact_name = + activity.find(package_name.c_str()) == 0 + ? activity.c_str() + package_name.length() + : activity.c_str(); + + // Construct a string in format: + // #Intent;action=android.intent.action.MAIN; + // category=android.intent.category.LAUNCHER; + // launchFlags=0x10210000; + // component=package_name/activity; + // param1;param2;end + return base::StringPrintf( + "%s;%s=%s;%s=%s;%s=0x%x;%s=%s/%s;%s%s", kIntentPrefix, kAction, + kActionMain, kCategory, kCategoryLauncher, kLaunchFlags, + Intent::FLAG_ACTIVITY_NEW_TASK | + Intent::FLAG_ACTIVITY_RESET_TASK_IF_NEEDED, + kComponent, package_name.c_str(), activity_compact_name, + extra_params_extracted.c_str(), kEndSuffix); +} + +bool ParseIntent(const std::string& intent_as_string, Intent* intent) { + DCHECK(intent); + const std::vector<base::StringPiece> parts = base::SplitStringPiece( + intent_as_string, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (parts.size() < 2 || parts.front() != kIntentPrefix || + parts.back() != kEndSuffix) { + DVLOG(1) << "Failed to split intent " << intent_as_string << "."; + return false; + } + + for (size_t i = 1; i < parts.size() - 1; ++i) { + const size_t separator = parts[i].find('='); + if (separator == std::string::npos) { + intent->AddExtraParam(parts[i].as_string()); + continue; + } + const base::StringPiece key = parts[i].substr(0, separator); + const base::StringPiece value = parts[i].substr(separator + 1); + if (key == kAction) { + intent->set_action(value.as_string()); + } else if (key == kCategory) { + intent->set_category(value.as_string()); + } else if (key == kLaunchFlags) { + uint32_t launch_flags; + const bool parsed = + base::HexStringToUInt(value.as_string(), &launch_flags); + if (!parsed) { + DVLOG(1) << "Failed to parse launchFlags: " << value.as_string() << "."; + return false; + } + intent->set_launch_flags(launch_flags); + } else if (key == kComponent) { + const size_t component_separator = value.find('/'); + if (component_separator == std::string::npos) + return false; + intent->set_package_name( + value.substr(0, component_separator).as_string()); + const base::StringPiece activity_compact_name = + value.substr(component_separator + 1); + if (!activity_compact_name.empty() && activity_compact_name[0] == '.') { + std::string activity = value.substr(0, component_separator).as_string(); + activity += activity_compact_name.as_string(); + intent->set_activity(activity); + } else { + intent->set_activity(activity_compact_name.as_string()); + } + } else { + intent->AddExtraParam(parts[i].as_string()); + } + } + + return true; +} + +Intent::Intent() = default; + +Intent::~Intent() = default; + +void Intent::AddExtraParam(const std::string& extra_param) { + extra_params_.push_back(extra_param); +} + +bool Intent::HasExtraParam(const std::string& extra_param) const { + return std::find(extra_params_.begin(), extra_params_.end(), extra_param) != + extra_params_.end(); +} + } // namespace arc
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h index 9176ddd..6ea7ba27 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.h +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -6,8 +6,11 @@ #define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_UTILS_H_ #include <string> +#include <vector> #include "base/callback.h" +#include "base/macros.h" +#include "base/optional.h" #include "components/arc/common/app.mojom.h" #include "ui/gfx/geometry/rect.h" @@ -27,9 +30,56 @@ extern const char kPlayStorePackage[]; extern const char kPlayStoreActivity[]; extern const char kSettingsAppId[]; +extern const char kInitialStartParam[]; using CanHandleResolutionCallback = base::Callback<void(bool)>; +// Represents unparsed intent. +class Intent { + public: + Intent(); + ~Intent(); + + enum LaunchFlags : uint32_t { + FLAG_ACTIVITY_NEW_TASK = 0x10000000, + FLAG_RECEIVER_NO_ABORT = 0x08000000, + FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0x00200000, + FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000, + }; + + void AddExtraParam(const std::string& extra_param); + bool HasExtraParam(const std::string& extra_param) const; + + const std::string& action() const { return action_; } + void set_action(const std::string& action) { action_ = action; } + + const std::string& category() const { return category_; } + void set_category(const std::string& category) { category_ = category; } + + const std::string& package_name() const { return package_name_; } + void set_package_name(const std::string& package_name) { + package_name_ = package_name; + } + + const std::string& activity() const { return activity_; } + void set_activity(const std::string& activity) { activity_ = activity; } + + uint32_t launch_flags() const { return launch_flags_; } + void set_launch_flags(uint32_t launch_flags) { launch_flags_ = launch_flags; } + + const std::vector<std::string>& extra_params() { return extra_params_; } + + private: + std::string action_; // Extracted from action. + std::string category_; // Extracted from category. + std::string package_name_; // Extracted from component. + std::string activity_; // Extracted from component. + uint32_t launch_flags_ = 0; // Extracted from launchFlags; + std::vector<std::string> extra_params_; // Other parameters not listed above. + + DISALLOW_COPY_AND_ASSIGN(Intent); +}; + // Checks if a given app should be hidden in launcher. bool ShouldShowInLauncher(const std::string& app_id); @@ -45,20 +95,23 @@ // Launch Play Store app. bool LaunchPlayStoreWithUrl(const std::string& url); -// Launch an app with given layout and let the system decides how big and where -// to place it. -// TODO (khmel) replace bool for |landscape_layout| with enum class in order -// to prevent using another LaunchApp with different signature mistakenly. +// Launches an app with given layout and lets the system decides how big and +// where to place it. bool LaunchApp(content::BrowserContext* context, const std::string& app_id, bool landscape_layout, int event_flags); -// Launch an app and place it at the specified coordinates. -bool LaunchAppWithRect(content::BrowserContext* context, - const std::string& app_id, - const gfx::Rect& target_rect, - int event_flags); +// Launches an app with given layout and lets the system decides how big and +// where to place it. |launch_intent| may be optionally provided to customize +// an app launch. +// TODO(khmel): replace bool for |landscape_layout| with enum class in order +// to prevent using another LaunchApp with different signature mistakenly. +bool LaunchAppWithIntent(content::BrowserContext* context, + const std::string& app_id, + const base::Optional<std::string>& launch_intent, + bool landscape_layout, + int event_flags); // Sets task active. void SetTaskActive(int task_id); @@ -98,6 +151,17 @@ // Returns true if |id| represents either ARC app or ARC shelf group. bool IsArcItem(content::BrowserContext* context, const std::string& id); +// Returns intent that can be used to launch an activity specified by +// |package_name| and |activity|. |extra_params| is the list of optional +// parameters encoded to intent. +std::string GetLaunchIntent(const std::string& package_name, + const std::string& activity, + const std::vector<std::string>& extra_params); + +// Parses provided |intent_as_string|. Returns false if |intent_as_string| +// cannot be parsed. +bool ParseIntent(const std::string& intent_as_string, Intent* intent); + } // namespace arc #endif // CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_UTILS_H_
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_utils_unittest.cc new file mode 100644 index 0000000..f21394e0 --- /dev/null +++ b/chrome/browser/ui/app_list/arc/arc_app_utils_unittest.cc
@@ -0,0 +1,80 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/browser/ui/ash/launcher/arc_app_shelf_id.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +constexpr char kTestPackage[] = "com.test.app"; +constexpr char kTestActivity[] = "com.test.app.some.activity"; +constexpr char kTestShelfGroupId[] = "some_shelf_group"; +constexpr char kIntentWithShelfGroupId[] = + "#Intent;launchFlags=0x18001000;" + "component=com.test.app/com.test.app.some.activity;" + "S.org.chromium.arc.shelf_group_id=some_shelf_group;end"; + +std::string GetPlayStoreInitialLaunchIntent() { + return arc::GetLaunchIntent(arc::kPlayStorePackage, arc::kPlayStoreActivity, + {arc::kInitialStartParam}); +} + +} // namespace + +class ArcAppUtilsTest : public testing::Test { + public: + ArcAppUtilsTest() = default; + ~ArcAppUtilsTest() override = default; + + private: + DISALLOW_COPY_AND_ASSIGN(ArcAppUtilsTest); +}; + +TEST_F(ArcAppUtilsTest, LaunchIntent) { + const std::string launch_intent = GetPlayStoreInitialLaunchIntent(); + + arc::Intent intent1; + EXPECT_TRUE(arc::ParseIntent(launch_intent, &intent1)); + EXPECT_EQ(intent1.action(), "android.intent.action.MAIN"); + EXPECT_EQ(intent1.category(), "android.intent.category.LAUNCHER"); + EXPECT_EQ(intent1.package_name(), arc::kPlayStorePackage); + EXPECT_EQ(intent1.activity(), arc::kPlayStoreActivity); + EXPECT_EQ(intent1.launch_flags(), + arc::Intent::FLAG_ACTIVITY_NEW_TASK | + arc::Intent::FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + ASSERT_EQ(intent1.extra_params().size(), 1U); + EXPECT_TRUE(intent1.HasExtraParam(arc::kInitialStartParam)); + + arc::Intent intent2; + EXPECT_TRUE(arc::ParseIntent(kIntentWithShelfGroupId, &intent2)); + EXPECT_EQ(intent2.action(), ""); + EXPECT_EQ(intent2.category(), ""); + EXPECT_EQ(intent2.package_name(), kTestPackage); + EXPECT_EQ(intent2.activity(), kTestActivity); + EXPECT_EQ(intent2.launch_flags(), + arc::Intent::FLAG_ACTIVITY_NEW_TASK | + arc::Intent::FLAG_RECEIVER_NO_ABORT | + arc::Intent::FLAG_ACTIVITY_LAUNCH_ADJACENT); + ASSERT_EQ(intent2.extra_params().size(), 1U); + EXPECT_TRUE(intent2.HasExtraParam( + "S.org.chromium.arc.shelf_group_id=some_shelf_group")); +} + +TEST_F(ArcAppUtilsTest, ShelfGroupId) { + const std::string intent_with_shelf_group_id(kIntentWithShelfGroupId); + const std::string shelf_app_id = + ArcAppListPrefs::GetAppId(kTestPackage, kTestActivity); + arc::ArcAppShelfId shelf_id1 = arc::ArcAppShelfId::FromIntentAndAppId( + intent_with_shelf_group_id, shelf_app_id); + EXPECT_TRUE(shelf_id1.has_shelf_group_id()); + EXPECT_EQ(shelf_id1.shelf_group_id(), kTestShelfGroupId); + EXPECT_EQ(shelf_id1.app_id(), shelf_app_id); + + arc::ArcAppShelfId shelf_id2 = arc::ArcAppShelfId::FromIntentAndAppId( + GetPlayStoreInitialLaunchIntent(), arc::kPlayStoreAppId); + EXPECT_FALSE(shelf_id2.has_shelf_group_id()); + EXPECT_EQ(shelf_id2.app_id(), arc::kPlayStoreAppId); +}
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc index ae41736..bb74ecd2 100644 --- a/chrome/browser/ui/app_list/search/app_result.cc +++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -17,6 +17,7 @@ app_id_(app_id), controller_(controller) { set_display_type(is_recommendation ? DISPLAY_RECOMMENDATION : DISPLAY_TILE); + set_result_type(RESULT_INSTALLED_APP); } AppResult::~AppResult() {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_shelf_id.cc b/chrome/browser/ui/ash/launcher/arc_app_shelf_id.cc index 5a969db..98ef84f 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_shelf_id.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_shelf_id.cc
@@ -7,14 +7,13 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "components/crx_file/id_util.h" namespace arc { namespace { -// String representation of Intent starts with this prefix. -constexpr char kIntent[] = "#Intent"; // Prefix in intent that specifies ARC shelf group. S. means string type. constexpr char kShelfGroupIntentPrefix[] = "S.org.chromium.arc.shelf_group_id="; // Prefix to specify ARC shelf group. @@ -50,15 +49,14 @@ if (intent.empty()) return ArcAppShelfId(std::string(), app_id); - const std::string prefix(kShelfGroupIntentPrefix); - const std::vector<std::string> parts = base::SplitString( - intent, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - if (parts.empty() || parts[0] != kIntent) + Intent parsed_intent; + if (!ParseIntent(intent, &parsed_intent)) return ArcAppShelfId(std::string(), app_id); - for (const auto& part : parts) { - if (base::StartsWith(part, prefix, base::CompareCase::SENSITIVE)) - return ArcAppShelfId(part.substr(prefix.length()), app_id); + const std::string prefix(kShelfGroupIntentPrefix); + for (const auto& param : parsed_intent.extra_params()) { + if (base::StartsWith(param, prefix, base::CompareCase::SENSITIVE)) + return ArcAppShelfId(param.substr(prefix.length()), app_id); } return ArcAppShelfId(std::string(), app_id);
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc index c3677cf61..a948a632 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -69,8 +69,9 @@ // even when its AppWindow is not present. class ArcAppWindowLauncherController::AppWindowInfo { public: - explicit AppWindowInfo(const arc::ArcAppShelfId& app_shelf_id) - : app_shelf_id_(app_shelf_id) {} + explicit AppWindowInfo(const arc::ArcAppShelfId& app_shelf_id, + const std::string& launch_intent) + : app_shelf_id_(app_shelf_id), launch_intent_(launch_intent) {} ~AppWindowInfo() = default; void SetDescription(const std::string& title, @@ -119,12 +120,15 @@ ArcAppWindow* app_window() { return app_window_.get(); } + const std::string& launch_intent() { return launch_intent_; } + const std::string& title() const { return title_; } const std::vector<uint8_t>& icon_data_png() const { return icon_data_png_; } private: const arc::ArcAppShelfId app_shelf_id_; + const std::string launch_intent_; bool has_requested_orientation_lock_ = false; // If true, the orientation should be locked to the specific @@ -357,7 +361,7 @@ const arc::ArcAppShelfId arc_app_shelf_id = arc::ArcAppShelfId::FromIntentAndAppId(intent, arc_app_id); task_id_to_app_window_info_[task_id] = - base::MakeUnique<AppWindowInfo>(arc_app_shelf_id); + base::MakeUnique<AppWindowInfo>(arc_app_shelf_id, intent); // Don't create shelf icon for non-primary user. if (observed_profile_ != owner()->profile()) return; @@ -595,9 +599,13 @@ if (!opt_in_management_check_start_time_.is_null() && app_window_info->app_shelf_id().app_id() == arc::kPlayStoreAppId) { - arc::UpdatePlayStoreShowTime( - base::Time::Now() - opt_in_management_check_start_time_, - arc::policy_util::IsAccountManaged(owner()->profile())); + arc::Intent intent; + if (arc::ParseIntent(app_window_info->launch_intent(), &intent) && + intent.HasExtraParam(arc::kInitialStartParam)) { + arc::UpdatePlayStoreShowTime( + base::Time::Now() - opt_in_management_check_start_time_, + arc::policy_util::IsAccountManaged(owner()->profile())); + } opt_in_management_check_start_time_ = base::Time(); } }
diff --git a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc index c8b67abf..95e4af6 100644 --- a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
@@ -30,8 +30,9 @@ std::unique_ptr<ArcAppLauncher> playstore_launcher = base::MakeUnique<ArcAppLauncher>( ChromeLauncherController::instance()->profile(), - arc::kPlayStoreAppId, true /* landscape_layout */, - true /* deferred_launch_allowed */); + arc::kPlayStoreAppId, + base::Optional<std::string>() /* launch_intent */, + true /* landscape_layout */, true /* deferred_launch_allowed */); // ArcAppLauncher may launch Play Store in case it exists already. In this // case this instance of ArcPlaystoreShortcutLauncherItemController may be // deleted. If Play Store does not exist at this moment, then let
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_browsertest.mm index d571102..e738593 100644 --- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_browsertest.mm +++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa_browsertest.mm
@@ -154,6 +154,10 @@ l10n_util::GetStringUTF16(IDS_BLOCKED_ADS_PROMPT_EXPLANATION)); EXPECT_NSEQ([[filterController messageLabel] stringValue], label); + NSString* link = + base::SysUTF16ToNSString(l10n_util::GetStringUTF16(IDS_LEARN_MORE)); + EXPECT_NSEQ([[filterController learnMoreLink] title], link); + EXPECT_TRUE([filterController manageCheckbox]); label = base::SysUTF16ToNSString(l10n_util::GetStringUTF16(IDS_ALLOW_ADS)); EXPECT_NSEQ([[filterController manageCheckbox] title], label);
diff --git a/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.h b/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.h index cace71ab..5f332d5 100644 --- a/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.h +++ b/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.h
@@ -25,6 +25,7 @@ @interface SubresourceFilterBubbleController (ExposedForTesting) - (void)manageCheckboxChecked:(id)sender; - (id)messageLabel; +- (id)learnMoreLink; - (id)manageCheckbox; - (id)doneButton; @end
diff --git a/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.mm b/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.mm index 6f68986..19f73051 100644 --- a/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/subresource_filter/subresource_filter_bubble_controller.mm
@@ -9,10 +9,12 @@ #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h" #include "components/strings/grit/components_strings.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" +#import "ui/base/cocoa/controls/hyperlink_button_cell.h" #include "ui/base/l10n/l10n_util_mac.h" @interface SubresourceFilterBubbleController () { NSButton* manageCheckbox_; + NSButton* learnMoreLink_; } @end @@ -61,6 +63,21 @@ [self.window.contentView addSubview:messageLabel_]; [messageLabel_ release]; + // Set up the "Learn more" link. + NSString* linkText = base::SysUTF16ToNSString( + contentSettingBubbleModel_->bubble_content().learn_more_link); + learnMoreLink_ = [[NSButton alloc] initWithFrame:NSMakeRect(18, 76, 282, 28)]; + base::scoped_nsobject<HyperlinkButtonCell> cell( + [[HyperlinkButtonCell alloc] initTextCell:linkText]); + [cell setAlignment:NSNaturalTextAlignment]; + [cell setControlSize:NSSmallControlSize]; + [learnMoreLink_ setCell:cell]; + [GTMUILocalizerAndLayoutTweaker sizeToFitView:learnMoreLink_]; + [learnMoreLink_ setTarget:self]; + [learnMoreLink_ setAction:@selector(learnMoreLinkClicked:)]; + [self.window.contentView addSubview:learnMoreLink_]; + [learnMoreLink_ release]; + manageCheckbox_ = [[NSButton alloc] initWithFrame:NSMakeRect(18, 35, 282, 28)]; [manageCheckbox_ setButtonType:NSSwitchButton]; @@ -103,12 +120,22 @@ [self layoutView]; } +// Callback for clicking on the "Learn more" link. +- (void)learnMoreLinkClicked:(id)sender { + contentSettingBubbleModel_->OnCustomLinkClicked(); + [self close]; +} + // For testing. - (id)messageLabel { return messageLabel_; } +- (id)learnMoreLink { + return learnMoreLink_; +} + - (id)manageCheckbox { return manageCheckbox_; }
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index 886ae3c..e530027 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -348,17 +348,9 @@ params.SetString("gaiaUrl", eafe_url); params.SetString("gaiaPath", eafe_path); } - if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kCrosGaiaApiV1)) { params.SetString("chromeOSApiVersion", "1"); - } else if (use_easy_bootstrap_) { - // Easy bootstrap is not v2-compatible - params.SetString("chromeOSApiVersion", "1"); - } else { - // This enables GLIF MM UI for the online Gaia screen by default. - // (see https://crbug.com/709244 ). - params.SetString("chromeOSApiVersion", "2"); } frame_state_ = FRAME_STATE_LOADING;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index bbc00684..1f29ef4 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -202,15 +202,10 @@ // Timeout for searching for privet printers, in seconds. const int kPrivetTimeoutSec = 5; -// Get the print job settings dictionary from |args|. The caller takes -// ownership of the returned DictionaryValue. Returns NULL on failure. +// Get the print job settings dictionary from |json_str|. Returns NULL on +// failure. std::unique_ptr<base::DictionaryValue> GetSettingsDictionary( - const base::ListValue* args) { - std::string json_str; - if (!args->GetString(0, &json_str)) { - NOTREACHED() << "Could not read JSON argument"; - return NULL; - } + const std::string& json_str) { if (json_str.empty()) { NOTREACHED() << "Empty print job settings"; return NULL; @@ -698,8 +693,8 @@ using local_discovery::ServiceDiscoverySharedClient; scoped_refptr<ServiceDiscoverySharedClient> service_discovery = ServiceDiscoverySharedClient::GetInstance(); - DCHECK(privet_callback_id_.empty()); - privet_callback_id_ = callback_id; + DCHECK(privet_search_callback_id_.empty()); + privet_search_callback_id_ = callback_id; StartPrivetLister(service_discovery); #endif } @@ -710,8 +705,9 @@ if (PrivetPrintingEnabled() && printer_lister_) { printer_lister_->Stop(); } - ResolveJavascriptCallback(base::Value(privet_callback_id_), base::Value()); - privet_callback_id_ = ""; + ResolveJavascriptCallback(base::Value(privet_search_callback_id_), + base::Value()); + privet_search_callback_id_.clear(); #endif } @@ -789,7 +785,11 @@ void PrintPreviewHandler::HandleGetPreview(const base::ListValue* args) { DCHECK_EQ(2U, args->GetSize()); - std::unique_ptr<base::DictionaryValue> settings = GetSettingsDictionary(args); + std::string json_str; + if (!args->GetString(0, &json_str)) + return; + std::unique_ptr<base::DictionaryValue> settings = + GetSettingsDictionary(json_str); if (!settings) return; int request_id = -1; @@ -875,9 +875,19 @@ UMA_HISTOGRAM_COUNTS("PrintPreview.RegeneratePreviewRequest.BeforePrint", regenerate_preview_request_count_); - std::unique_ptr<base::DictionaryValue> settings = GetSettingsDictionary(args); + AllowJavascript(); + + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + CHECK(!callback_id.empty()); + std::string json_str; + if (!args->GetString(1, &json_str)) + RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); + + std::unique_ptr<base::DictionaryValue> settings = + GetSettingsDictionary(json_str); if (!settings) - return; + RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); ReportPrintSettingsStats(*settings); @@ -909,6 +919,8 @@ if (print_to_pdf) { UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPDF", page_count); ReportUserActionHistogram(PRINT_TO_PDF); + DCHECK(pdf_callback_id_.empty()); + pdf_callback_id_ = callback_id; PrintToPdf(); return; } @@ -930,12 +942,14 @@ !settings->GetInteger(printing::kSettingPageHeight, &height) || width <= 0 || height <= 0) { NOTREACHED(); - FireWebUIListener("print-failed", base::Value(-1)); + RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); return; } - PrintToPrivetPrinter( - printer_name, print_ticket, capabilities, gfx::Size(width, height)); + DCHECK(privet_print_callback_id_.empty()); + privet_print_callback_id_ = callback_id; + PrintToPrivetPrinter(callback_id, printer_name, print_ticket, capabilities, + gfx::Size(width, height)); return; } #endif @@ -957,7 +971,7 @@ !settings->GetInteger(printing::kSettingPageHeight, &height) || width <= 0 || height <= 0) { NOTREACHED(); - OnExtensionPrintResult(false, "FAILED"); + RejectJavascriptCallback(base::Value(callback_id), base::Value("FAILED")); return; } @@ -965,7 +979,8 @@ scoped_refptr<base::RefCountedBytes> data; if (!GetPreviewDataAndTitle(&data, &title)) { LOG(ERROR) << "Nothing to print; no preview available."; - OnExtensionPrintResult(false, "NO_DATA"); + RejectJavascriptCallback(base::Value(callback_id), + base::Value("NO_DATA")); return; } @@ -974,7 +989,7 @@ destination_id, capabilities, title, print_ticket, gfx::Size(width, height), data, base::Bind(&PrintPreviewHandler::OnExtensionPrintResult, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), callback_id)); return; } @@ -982,6 +997,7 @@ base::string16 title; if (!GetPreviewDataAndTitle(&data, &title)) { // Nothing to print, no preview available. + RejectJavascriptCallback(base::Value(callback_id), base::Value()); return; } @@ -989,7 +1005,7 @@ UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToCloudPrint", page_count); ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT); - SendCloudPrintJob(data.get()); + SendCloudPrintJob(callback_id, data.get()); return; } @@ -1004,13 +1020,6 @@ ReportUserActionHistogram(PRINT_TO_PRINTER); } - // This tries to activate the initiator as well, so do not clear the - // association with the initiator yet. - print_preview_ui()->OnHidePreviewDialog(); - - // Grab the current initiator before calling ClearInitiatorDetails() below. - // Otherwise calling GetInitiator() later will return the wrong WebContents. - // https://crbug.com/407080 WebContents* initiator = GetInitiator(); if (initiator) { // Save initiator IDs. PrintMsg_PrintForPrintPreview below should cause @@ -1023,24 +1032,24 @@ main_render_frame->GetRoutingID()); } - // Do this so the initiator can open a new print preview dialog, while the - // current print preview dialog is still handling its print job. - ClearInitiatorDetails(); - // Set ID to know whether printing is for preview. settings->SetInteger(printing::kPreviewUIID, print_preview_ui()->GetIDForPrintPreviewUI()); RenderFrameHost* rfh = preview_web_contents()->GetMainFrame(); rfh->Send(new PrintMsg_PrintForPrintPreview(rfh->GetRoutingID(), *settings)); - // For all other cases above, the preview dialog will stay open until the - // printing has finished. Then the dialog closes and PrintPreviewDone() gets - // called. In the case below, since the preview dialog will be hidden and - // not closed, we need to make this call. - if (initiator) { - auto* print_view_manager = PrintViewManager::FromWebContents(initiator); - print_view_manager->PrintPreviewDone(); - } + // Set this so when print preview sends "hidePreviewDialog" we clear the + // initiator and call PrintPreviewDone(). In the cases above, the preview + // dialog stays open until printing is finished and we do this when the + // dialog is closed. In this case, we set this so that these tasks are + // done in HandleHidePreview(). + printing_started_ = true; + + // This will ultimately try to activate the initiator as well, so do not + // clear the association with the initiator until "hidePreviewDialog" is + // received from JS. + ResolveJavascriptCallback(base::Value(callback_id), base::Value()); + #else NOTREACHED(); #endif // BUILDFLAG(ENABLE_BASIC_PRINTING) @@ -1049,6 +1058,8 @@ void PrintPreviewHandler::PrintToPdf() { if (!print_to_pdf_path_.empty()) { // User has already selected a path, no need to show the dialog again. + ResolveJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); + pdf_callback_id_.clear(); PostPrintToPdfTask(); } else if (!select_file_dialog_.get() || !select_file_dialog_->IsRunning(platform_util::GetTopLevel( @@ -1076,6 +1087,24 @@ } void PrintPreviewHandler::HandleHidePreview(const base::ListValue* /*args*/) { + if (printing_started_) { + // Printing has started, so clear the initiator so that it can open a new + // print preview dialog, while the current print preview dialog is still + // handling its print job. + WebContents* initiator = GetInitiator(); + ClearInitiatorDetails(); + + // Since the preview dialog will be hidden and not closed, we need to make + // this call. + if (initiator) { + auto* print_view_manager = PrintViewManager::FromWebContents(initiator); + print_view_manager->PrintPreviewDone(); + } + + // Since the initiator is cleared, only want to do this once. + printing_started_ = false; + } + print_preview_ui()->OnHidePreviewDialog(); } @@ -1412,15 +1441,15 @@ } } -void PrintPreviewHandler::SendCloudPrintJob(const base::RefCountedBytes* data) { +void PrintPreviewHandler::SendCloudPrintJob(const std::string& callback_id, + const base::RefCountedBytes* data) { // BASE64 encode the job data. const base::StringPiece raw_data(reinterpret_cast<const char*>(data->front()), data->size()); std::string base64_data; base::Base64Encode(raw_data, &base64_data); - base::Value data_value(base64_data); - web_ui()->CallJavascriptFunctionUnsafe("printToCloud", data_value); + ResolveJavascriptCallback(base::Value(callback_id), base::Value(base64_data)); } WebContents* PrintPreviewHandler::GetInitiator() const { @@ -1443,7 +1472,9 @@ ChromeSelectFilePolicy policy(GetInitiator()); if (!policy.CanOpenSelectFileDialog()) { policy.SelectFileDenied(); - return ClosePreviewDialog(); + RejectJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); + pdf_callback_id_.clear(); + return; } } @@ -1526,7 +1557,8 @@ sticky_settings->SaveInPrefs( Profile::FromBrowserContext(preview_web_contents()->GetBrowserContext()) ->GetPrefs()); - web_ui()->CallJavascriptFunctionUnsafe("fileSelectionCompleted"); + ResolveJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); + pdf_callback_id_.clear(); print_to_pdf_path_ = path; PostPrintToPdfTask(); } @@ -1548,7 +1580,8 @@ } void PrintPreviewHandler::FileSelectionCanceled(void* params) { - print_preview_ui()->OnFileSelectionCancelled(); + RejectJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); + pdf_callback_id_.clear(); } void PrintPreviewHandler::ClearInitiatorDetails() { @@ -1636,13 +1669,10 @@ const std::string& callback_id, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { if (!http_client) { - if (callback_id.empty()) { - // This was an attempt to print to a privet printer and has failed. - FireWebUIListener("print-failed", base::Value(-1)); - } else { // Capabilities update failed - RejectJavascriptCallback(base::Value(callback_id), base::Value()); - } + RejectJavascriptCallback(base::Value(callback_id), base::Value()); privet_http_resolution_.reset(); + if (callback_id == privet_print_callback_id_) + privet_print_callback_id_.clear(); return false; } @@ -1657,11 +1687,12 @@ } void PrintPreviewHandler::PrivetLocalPrintUpdateClient( + const std::string& callback_id, std::string print_ticket, std::string capabilities, gfx::Size page_size, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { - if (!PrivetUpdateClient("", std::move(http_client))) + if (!PrivetUpdateClient(callback_id, std::move(http_client))) return; StartPrivetLocalPrint(print_ticket, capabilities, page_size); @@ -1680,7 +1711,9 @@ base::string16 title; if (!GetPreviewDataAndTitle(&data, &title)) { - FireWebUIListener("print-failed", base::Value(-1)); + RejectJavascriptCallback(base::Value(privet_print_callback_id_), + base::Value(-1)); + privet_print_callback_id_.clear(); return; } @@ -1733,16 +1766,19 @@ privet_capabilities_operation_.reset(); } -void PrintPreviewHandler::PrintToPrivetPrinter(const std::string& device_name, +void PrintPreviewHandler::PrintToPrivetPrinter(const std::string& callback_id, + const std::string& device_name, const std::string& ticket, const std::string& capabilities, const gfx::Size& page_size) { if (!CreatePrivetHTTP( device_name, base::Bind(&PrintPreviewHandler::PrivetLocalPrintUpdateClient, - weak_factory_.GetWeakPtr(), ticket, capabilities, - page_size))) { - FireWebUIListener("print-failed", base::Value(-1)); + weak_factory_.GetWeakPtr(), callback_id, ticket, + capabilities, page_size))) { + RejectJavascriptCallback(base::Value(privet_print_callback_id_), + base::Value(-1)); + privet_print_callback_id_.clear(); } } @@ -1767,13 +1803,17 @@ void PrintPreviewHandler::OnPrivetPrintingDone( const cloud_print::PrivetLocalPrintOperation* print_operation) { - ClosePreviewDialog(); + ResolveJavascriptCallback(base::Value(privet_print_callback_id_), + base::Value()); + privet_print_callback_id_.clear(); } void PrintPreviewHandler::OnPrivetPrintingError( const cloud_print::PrivetLocalPrintOperation* print_operation, int http_code) { - FireWebUIListener("print-failed", base::Value(http_code)); + RejectJavascriptCallback(base::Value(privet_print_callback_id_), + base::Value(http_code)); + privet_print_callback_id_.clear(); } void PrintPreviewHandler::FillPrinterDescription( @@ -1834,13 +1874,14 @@ ResolveJavascriptCallback(base::Value(callback_id), capabilities); } -void PrintPreviewHandler::OnExtensionPrintResult(bool success, +void PrintPreviewHandler::OnExtensionPrintResult(const std::string& callback_id, + bool success, const std::string& status) { if (success) { - ClosePreviewDialog(); + ResolveJavascriptCallback(base::Value(callback_id), base::Value()); return; } - FireWebUIListener("print-failed", base::Value(status)); + RejectJavascriptCallback(base::Value(callback_id), base::Value(status)); } void PrintPreviewHandler::RegisterForGaiaCookieChanges() {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 80446ab..35b50cf 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -253,7 +253,8 @@ void SendCloudPrintEnabled(); // Send the PDF data to the cloud to print. - void SendCloudPrintJob(const base::RefCountedBytes* data); + void SendCloudPrintJob(const std::string& callback_id, + const base::RefCountedBytes* data); // Gets the initiator for the print preview dialog. content::WebContents* GetInitiator() const; @@ -301,6 +302,7 @@ const std::string& callback_id, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client); void PrivetLocalPrintUpdateClient( + const std::string& callback_id, std::string print_ticket, std::string capabilities, gfx::Size page_size, @@ -312,7 +314,8 @@ const std::string& capabilities, const gfx::Size& page_size); void SendPrivetCapabilitiesError(const std::string& id); - void PrintToPrivetPrinter(const std::string& printer_name, + void PrintToPrivetPrinter(const std::string& callback_id, + const std::string& printer_name, const std::string& print_ticket, const std::string& capabilities, const gfx::Size& page_size); @@ -357,10 +360,13 @@ const base::DictionaryValue& capabilities); // Called when an extension print job is completed. + // |callback_id|: The javascript callback to run. // |success|: Whether the job succeeded. // |status|: The returned print job status. Useful for reporting a specific // error. - void OnExtensionPrintResult(bool success, const std::string& status); + void OnExtensionPrintResult(const std::string& callback_id, + bool success, + const std::string& status); // Register/unregister from notifications of changes done to the GAIA // cookie. @@ -415,8 +421,18 @@ // notify the test if it was a successful save, only that it was attempted. base::Closure pdf_file_saved_closure_; +#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) // Callback ID to be used to notify UI that privet search is finished. - std::string privet_callback_id_ = ""; + std::string privet_search_callback_id_; + + // Callback ID to be used to notify UI that privet printing is finished. + std::string privet_print_callback_id_; +#endif + + // Callback ID to be used to notify UI that PDF file selection has finished. + std::string pdf_callback_id_; + + bool printing_started_ = false; // Proxy for calls to the print backend. Lazily initialized since web_ui() is // not available at construction time.
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index ee92bb87..83086734 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" #include <map> +#include <memory> #include <utility> #include <vector> @@ -624,10 +625,6 @@ ui_preview_request_id); } -void PrintPreviewUI::OnFileSelectionCancelled() { - web_ui()->CallJavascriptFunctionUnsafe("fileSelectionCancelled"); -} - void PrintPreviewUI::OnCancelPendingPreviewRequest() { g_print_preview_request_id_map.Get().Set(id_, -1); }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chrome/browser/ui/webui/print_preview/print_preview_ui.h index 360a1cd2..2abe24e 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
@@ -119,9 +119,6 @@ // controls that need the initiator for generating the preview data. void OnInitiatorClosed(); - // Notifies the Web UI renderer that file selection has been cancelled. - void OnFileSelectionCancelled(); - // Notifies the Web UI that the printer is unavailable or its settings are // invalid. void OnInvalidPrinterSettings();
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc index bcc9414..5ff31ca 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -192,7 +192,7 @@ prefs_->ClearPref(prefs::kPowerBatteryScreenOffDelayMs); prefs_->ClearPref(prefs::kPowerBatteryScreenLockDelayMs); break; - case IdleBehavior::DISPLAY_OFF_STAY_AWAKE: + case IdleBehavior::DISPLAY_OFF: // Override idle actions to keep the system awake, but use the default // screen delays. prefs_->SetInteger(prefs::kPowerAcIdleAction, @@ -305,7 +305,7 @@ idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP; } else if (idle_action == PowerPolicyController::ACTION_DO_NOTHING) { idle_behavior = (prefs_->GetInteger(prefs::kPowerAcScreenOffDelayMs) > 0 - ? IdleBehavior::DISPLAY_OFF_STAY_AWAKE + ? IdleBehavior::DISPLAY_OFF : IdleBehavior::DISPLAY_ON); }
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h index b958a2f..6839817 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -37,7 +37,7 @@ // tests. enum class IdleBehavior { DISPLAY_OFF_SLEEP = 0, - DISPLAY_OFF_STAY_AWAKE = 1, + DISPLAY_OFF = 1, DISPLAY_ON = 2, OTHER = 3, };
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_unittest.cc index 51305c08..acac9ab 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_unittest.cc
@@ -200,12 +200,12 @@ base::MakeUnique<base::Value>(PowerPolicyController::ACTION_DO_NOTHING)); prefs_.SetUserPref(prefs::kPowerAcScreenOffDelayMs, base::MakeUnique<base::Value>(10000)); - EXPECT_EQ( - CreateSettingsChangedString( - PowerHandler::IdleBehavior::DISPLAY_OFF_STAY_AWAKE, - false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND, - false /* lid_closed_controlled */, true /* has_lid */), - GetLastSettingsChangedMessage()); + EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_OFF, + false /* idle_controlled */, + PowerPolicyController::ACTION_SUSPEND, + false /* lid_closed_controlled */, + true /* has_lid */), + GetLastSettingsChangedMessage()); // Now set the delay to zero and check that the setting goes to "display on". prefs_.SetUserPref(prefs::kPowerAcScreenOffDelayMs, @@ -254,7 +254,7 @@ // Verifies that requests from WebUI to update the idle behavior update prefs // appropriately. TEST_F(PowerHandlerTest, SetIdleBehavior) { - // Request the "display on" setting and check that prefs are set + // Request the "Keep display on" setting and check that prefs are set // appropriately. test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON); EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING, @@ -268,10 +268,9 @@ EXPECT_EQ(0, GetIntPref(prefs::kPowerBatteryScreenOffDelayMs)); EXPECT_EQ(0, GetIntPref(prefs::kPowerBatteryScreenLockDelayMs)); - // "Turn the display off but stay awake" should set the idle prefs but clear - // the screen delays. - test_api_->SetIdleBehavior( - PowerHandler::IdleBehavior::DISPLAY_OFF_STAY_AWAKE); + // "Turn off display" should set the idle prefs but clear the screen + // delays. + test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF); EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING, GetIntPref(prefs::kPowerAcIdleAction)); EXPECT_EQ(-1, GetIntPref(prefs::kPowerAcScreenDimDelayMs)); @@ -283,8 +282,8 @@ EXPECT_EQ(-1, GetIntPref(prefs::kPowerBatteryScreenOffDelayMs)); EXPECT_EQ(-1, GetIntPref(prefs::kPowerBatteryScreenLockDelayMs)); - // Now switch to the "display on" setting (to set the prefs again) and check - // that the "sleep" setting clears all the prefs. + // Now switch to the "Keep display on" setting (to set the prefs again) and + // check that the "Turn off display and sleep" setting clears all the prefs. test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON); test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP); EXPECT_EQ(-1, GetIntPref(prefs::kPowerAcIdleAction));
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 9b07071..2619e76e 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
@@ -751,8 +751,7 @@ {"calculatingPower", IDS_SETTINGS_POWER_SOURCE_CALCULATING}, {"powerIdleLabel", IDS_SETTINGS_POWER_IDLE_LABEL}, {"powerIdleDisplayOffSleep", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP}, - {"powerIdleDisplayOffStayAwake", - IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_STAY_AWAKE}, + {"powerIdleDisplayOff", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF}, {"powerIdleDisplayOn", IDS_SETTINGS_POWER_IDLE_DISPLAY_ON}, {"powerIdleOther", IDS_SETTINGS_POWER_IDLE_OTHER}, {"powerLidClosedLabel", IDS_SETTINGS_POWER_LID_CLOSED_LABEL},
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index cef3a792..4523ef28 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4895,6 +4895,7 @@ "../browser/ui/app_list/arc/arc_app_test.cc", "../browser/ui/app_list/arc/arc_app_test.h", "../browser/ui/app_list/arc/arc_app_unittest.cc", + "../browser/ui/app_list/arc/arc_app_utils_unittest.cc", "../browser/ui/app_list/extension_app_model_builder_unittest.cc", "../browser/ui/app_list/profile_loader_unittest.cc", "../browser/ui/app_list/search/answer_card/answer_card_result_unittest.cc",
diff --git a/chrome/test/chromedriver/BUILD.gn b/chrome/test/chromedriver/BUILD.gn index 5dad239..ce99cba 100644 --- a/chrome/test/chromedriver/BUILD.gn +++ b/chrome/test/chromedriver/BUILD.gn
@@ -273,7 +273,7 @@ if (!use_x11) { sources -= [ "keycode_text_conversion_x.cc" ] } - if (!use_ozone) { + if (!use_ozone && !use_x11) { sources -= [ "keycode_text_conversion_ozone.cc" ] }
diff --git a/chrome/test/chromedriver/keycode_text_conversion.h b/chrome/test/chromedriver/keycode_text_conversion.h index 6885f70..5968516 100644 --- a/chrome/test/chromedriver/keycode_text_conversion.h +++ b/chrome/test/chromedriver/keycode_text_conversion.h
@@ -37,4 +37,16 @@ bool SwitchToUSKeyboardLayout(); #endif +#if defined(USE_X11) +// Use the ozone implementation when there is no X display. +bool ConvertKeyCodeToTextOzone(ui::KeyboardCode key_code, + int modifiers, + std::string* text, + std::string* error_msg); +bool ConvertCharToKeyCodeOzone(base::char16 key, + ui::KeyboardCode* key_code, + int* necessary_modifiers, + std::string* error_msg); +#endif + #endif // CHROME_TEST_CHROMEDRIVER_KEYCODE_TEXT_CONVERSION_H_
diff --git a/chrome/test/chromedriver/keycode_text_conversion_ozone.cc b/chrome/test/chromedriver/keycode_text_conversion_ozone.cc index 4ac8a00..6d07880 100644 --- a/chrome/test/chromedriver/keycode_text_conversion_ozone.cc +++ b/chrome/test/chromedriver/keycode_text_conversion_ozone.cc
@@ -14,10 +14,15 @@ #include "ui/events/ozone/layout/keyboard_layout_engine.h" #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" -bool ConvertKeyCodeToText(ui::KeyboardCode key_code, - int modifiers, - std::string* text, - std::string* error_msg) { +#if defined(USE_X11) +bool ConvertKeyCodeToTextOzone +#else +bool ConvertKeyCodeToText +#endif + (ui::KeyboardCode key_code, + int modifiers, + std::string* text, + std::string* error_msg) { ui::KeyboardLayoutEngine* keyboard_layout_engine = ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine(); ui::DomCode dom_code = ui::UsLayoutKeyboardCodeToDomCode(key_code); @@ -48,10 +53,15 @@ return true; } -bool ConvertCharToKeyCode(base::char16 key, - ui::KeyboardCode* key_code, - int* necessary_modifiers, - std::string* error_msg) { +#if defined(USE_X11) +bool ConvertCharToKeyCodeOzone +#else +bool ConvertCharToKeyCode +#endif + (base::char16 key, + ui::KeyboardCode* key_code, + int* necessary_modifiers, + std::string* error_msg) { base::string16 key_string; key_string.push_back(key); std::string key_string_utf8 = base::UTF16ToUTF8(key_string);
diff --git a/chrome/test/chromedriver/keycode_text_conversion_x.cc b/chrome/test/chromedriver/keycode_text_conversion_x.cc index 58c632b..c0b2cf6 100644 --- a/chrome/test/chromedriver/keycode_text_conversion_x.cc +++ b/chrome/test/chromedriver/keycode_text_conversion_x.cc
@@ -184,6 +184,11 @@ bool ConvertKeyCodeToText( ui::KeyboardCode key_code, int modifiers, std::string* text, std::string* error_msg) { + XDisplay* display = gfx::GetXDisplay(); + if (!display) { + return ConvertKeyCodeToTextOzone(key_code, modifiers, text, error_msg); + } + *error_msg = std::string(); int x_key_code = KeyboardCodeToXKeyCode(key_code); if (x_key_code == -1) { @@ -194,13 +199,6 @@ XEvent event; memset(&event, 0, sizeof(XEvent)); XKeyEvent* key_event = &event.xkey; - XDisplay* display = gfx::GetXDisplay(); - if (!display) { - *error_msg = - "an X display is required for keycode conversions, consider using Xvfb"; - *text = std::string(); - return false; - } key_event->display = display; key_event->keycode = x_key_code; if (modifiers & kShiftKeyModifierMask) @@ -237,6 +235,12 @@ ui::KeyboardCode* key_code, int* necessary_modifiers, std::string* error_msg) { + XDisplay* display = gfx::GetXDisplay(); + if (!display) { + return ConvertCharToKeyCodeOzone(key, key_code, necessary_modifiers, + error_msg); + } + std::string key_string(base::UTF16ToUTF8(base::string16(1, key))); bool found = false; ui::KeyboardCode test_code;
diff --git a/chrome/test/data/webui/print_preview/native_layer_stub.js b/chrome/test/data/webui/print_preview/native_layer_stub.js index 73ba1244..23e223e 100644 --- a/chrome/test/data/webui/print_preview/native_layer_stub.js +++ b/chrome/test/data/webui/print_preview/native_layer_stub.js
@@ -15,6 +15,7 @@ 'getExtensionPrinters', 'getPrivetPrinters', 'getPrinterCapabilities', + 'print', 'setupPrinter' ]); @@ -24,9 +25,6 @@ */ this.eventTarget_ = new cr.EventTarget(); - /** @private {boolean} Whether the native layer has sent a print message. */ - this.printStarted_ = false; - /** * @private {boolean} Whether the native layer has set the generate draft * parameter when requesting an updated preview. @@ -100,6 +98,12 @@ }, /** @override */ + print: function() { + this.methodCalled('print'); + return Promise.resolve(); + }, + + /** @override */ setupPrinter: function(printerId) { this.methodCalled('setupPrinter', printerId); return this.shouldRejectPrinterSetup_ ? @@ -114,7 +118,6 @@ generateDraft, requestId) { this.generateDraft_ = generateDraft; }, - startPrint: function () { this.printStarted_ = true; }, startHideDialog: function () {}, /** @return {!cr.EventTarget} The native layer event target. */ @@ -128,9 +131,6 @@ /** @return {boolean} Whether a new draft was requested for preview. */ generateDraft: function() { return this.generateDraft_; }, - /** @return {boolean} Whether a print request has been issued. */ - isPrintStarted: function() { return this.printStarted_; }, - /** * @param {!print_preview.NativeInitialSettings} settings The settings * to return as a response to |getInitialSettings|.
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js index fa0892e..9af4ebd 100644 --- a/chrome/test/data/webui/print_preview/print_preview_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -1307,9 +1307,9 @@ // Has active print button and successfully 'prints', indicating // recovery from error state. expectFalse(printButton.disabled); - expectFalse(nativeLayer.isPrintStarted()); printButton.click(); - expectTrue(nativeLayer.isPrintStarted()); + // This should result in a call to print. + return nativeLayer.whenCalled('print'); }); }); });
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index 3a083d68..1fdbe06 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -795,9 +795,9 @@ settings.IdleBehavior.DISPLAY_ON, settings.DevicePageBrowserProxyImpl.getInstance().idleBehavior_); - selectValue(idleSelect, settings.IdleBehavior.DISPLAY_OFF_STAY_AWAKE); + selectValue(idleSelect, settings.IdleBehavior.DISPLAY_OFF); expectEquals( - settings.IdleBehavior.DISPLAY_OFF_STAY_AWAKE, + settings.IdleBehavior.DISPLAY_OFF, settings.DevicePageBrowserProxyImpl.getInstance().idleBehavior_); }); @@ -834,14 +834,13 @@ expectEquals(null, powerPage.$$('#lidClosedControlledIndicator')); }).then(function() { sendPowerManagementSettings( - settings.IdleBehavior.DISPLAY_OFF_STAY_AWAKE, + settings.IdleBehavior.DISPLAY_OFF, false /* idleControlled */, settings.LidClosedBehavior.SUSPEND, false /* lidClosedControlled */, true /* hasLid */); return new Promise(function(resolve) { powerPage.async(resolve); }); }).then(function() { - expectEquals( - settings.IdleBehavior.DISPLAY_OFF_STAY_AWAKE.toString(), - idleSelect.value); + expectEquals(settings.IdleBehavior.DISPLAY_OFF.toString(), + idleSelect.value); expectFalse(idleSelect.disabled); expectEquals(null, powerPage.$$('#idleControlledIndicator')); expectEquals(
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 109693cd..e1e30b19 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -204,9 +204,6 @@ // Disables new channel switcher UI. const char kDisableNewChannelSwitcherUI[] = "disable-new-channel-switcher-ui"; -// Disables new Kiosk UI when kiosk apps are represented as user pods. -const char kDisableNewKioskUI[] = "disable-new-kiosk-ui"; - // Disables the new Korean IME in chrome://settings/languages. const char kDisableNewKoreanIme[] = "disable-new-korean-ime"; @@ -278,10 +275,6 @@ // Enables action handler apps (e.g. creating new notes) on lock screen. const char kEnableLockScreenApps[] = "enable-lock-screen-apps"; -// Enables Kiosk mode for Chrome OS. Note this switch refers to retail mode -// rather than the kiosk app mode. -const char kEnableKioskMode[] = "enable-kiosk-mode"; - // Overrides Tether with stub service. Provide integer arguments for the number // of fake networks desired, e.g. 'tether-stub=2'. const char kTetherStub[] = "tether-stub"; @@ -448,11 +441,6 @@ // If true, the non-md login and lock screens will be shown. const char kShowNonMdLogin[] = "show-non-md-login"; -// Specifies power stub behavior: -// 'cycle=2' - Cycles power states every 2 seconds. -// See FakeDBusThreadManager::ParsePowerCommandLineSwitch for full details. -const char kPowerStub[] = "power-stub"; - // Overrides network stub behavior. By default, ethernet, wifi and vpn are // enabled, and transitions occur instantaneously. Multiple options can be // comma separated (no spaces). Note: all options are in the format 'foo=x'.
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index aa1617b..d1407a85 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -66,7 +66,6 @@ CHROMEOS_EXPORT extern const char kDisableMultiDisplayLayout[]; CHROMEOS_EXPORT extern const char kDisableNetworkPortalNotification[]; CHROMEOS_EXPORT extern const char kDisableNewChannelSwitcherUI[]; -CHROMEOS_EXPORT extern const char kDisableNewKioskUI[]; CHROMEOS_EXPORT extern const char kDisableNewKoreanIme[]; CHROMEOS_EXPORT extern const char kDisableNewZIPUnpacker[]; CHROMEOS_EXPORT extern const char kDisableOfficeEditingComponentApp[]; @@ -89,7 +88,6 @@ CHROMEOS_EXPORT extern const char kEnableExtensionAssetsSharing[]; CHROMEOS_EXPORT extern const char kEnableFirstRunUITransitions[]; CHROMEOS_EXPORT extern const char kEnableLockScreenApps[]; -CHROMEOS_EXPORT extern const char kEnableKioskMode[]; CHROMEOS_EXPORT extern const char kTetherStub[]; CHROMEOS_EXPORT extern const char kDisableMdOobe[]; CHROMEOS_EXPORT extern const char kEnableNetworkPortalNotification[]; @@ -133,7 +131,6 @@ CHROMEOS_EXPORT extern const char kOobeTimerInterval[]; CHROMEOS_EXPORT extern const char kShowMdLogin[]; CHROMEOS_EXPORT extern const char kShowNonMdLogin[]; -CHROMEOS_EXPORT extern const char kPowerStub[]; CHROMEOS_EXPORT extern const char kShillStub[]; CHROMEOS_EXPORT extern const char kSmsTestMessages[]; CHROMEOS_EXPORT extern const char kStubCrosSettings[];
diff --git a/chromeos/components/tether/ble_connection_manager.cc b/chromeos/components/tether/ble_connection_manager.cc index fc9fea7d5..60516e9 100644 --- a/chromeos/components/tether/ble_connection_manager.cc +++ b/chromeos/components/tether/ble_connection_manager.cc
@@ -41,10 +41,10 @@ BleConnectionManager::ConnectionMetadata::ConnectionMetadata( const cryptauth::RemoteDevice remote_device, - std::shared_ptr<base::Timer> timer, + std::unique_ptr<base::Timer> timer, base::WeakPtr<BleConnectionManager> manager) : remote_device_(remote_device), - connection_attempt_timeout_timer_(timer), + connection_attempt_timeout_timer_(std::move(timer)), manager_(manager), weak_ptr_factory_(this) {} @@ -219,7 +219,7 @@ << remote_device.GetTruncatedDeviceIdForLogs() << "\", Reason: " << MessageTypeToString(connection_reason); - std::shared_ptr<ConnectionMetadata> connection_metadata = + ConnectionMetadata* connection_metadata = GetConnectionMetadata(remote_device); if (!connection_metadata) { connection_metadata = AddMetadataForDevice(remote_device); @@ -232,17 +232,20 @@ void BleConnectionManager::UnregisterRemoteDevice( const cryptauth::RemoteDevice& remote_device, const MessageType& connection_reason) { + ConnectionMetadata* connection_metadata = + GetConnectionMetadata(remote_device); + if (!connection_metadata) { + PA_LOG(WARNING) << "Tried to unregister device, but was not registered - " + << "Device ID: \"" + << remote_device.GetTruncatedDeviceIdForLogs() + << "\", Reason: " << MessageTypeToString(connection_reason); + return; + } + PA_LOG(INFO) << "Unregister - Device ID: \"" << remote_device.GetTruncatedDeviceIdForLogs() << "\", Reason: " << MessageTypeToString(connection_reason); - std::shared_ptr<ConnectionMetadata> connection_metadata = - GetConnectionMetadata(remote_device); - if (!connection_metadata) { - // If the device was not registered, there is nothing to do. - return; - } - connection_metadata->UnregisterConnectionReason(connection_reason); if (!connection_metadata->HasReasonForConnection()) { cryptauth::SecureChannel::Status status_before_disconnect = @@ -267,7 +270,7 @@ void BleConnectionManager::SendMessage( const cryptauth::RemoteDevice& remote_device, const std::string& message) { - std::shared_ptr<ConnectionMetadata> connection_metadata = + ConnectionMetadata* connection_metadata = GetConnectionMetadata(remote_device); if (!connection_metadata || connection_metadata->GetStatus() != @@ -288,7 +291,7 @@ bool BleConnectionManager::GetStatusForDevice( const cryptauth::RemoteDevice& remote_device, cryptauth::SecureChannel::Status* status) const { - std::shared_ptr<ConnectionMetadata> connection_metadata = + ConnectionMetadata* connection_metadata = GetConnectionMetadata(remote_device); if (!connection_metadata) { return false; @@ -309,7 +312,7 @@ void BleConnectionManager::OnReceivedAdvertisementFromDevice( const std::string& device_address, cryptauth::RemoteDevice remote_device) { - std::shared_ptr<ConnectionMetadata> connection_metadata = + ConnectionMetadata* connection_metadata = GetConnectionMetadata(remote_device); if (!connection_metadata) { // If an advertisement is received from a device that is not registered, @@ -350,7 +353,7 @@ UpdateConnectionAttempts(); } -std::shared_ptr<BleConnectionManager::ConnectionMetadata> +BleConnectionManager::ConnectionMetadata* BleConnectionManager::GetConnectionMetadata( const cryptauth::RemoteDevice& remote_device) const { const auto map_iter = device_to_metadata_map_.find(remote_device); @@ -358,26 +361,30 @@ return nullptr; } - return map_iter->second; + return map_iter->second.get(); } -std::shared_ptr<BleConnectionManager::ConnectionMetadata> +BleConnectionManager::ConnectionMetadata* BleConnectionManager::AddMetadataForDevice( const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<ConnectionMetadata> existing_data = - GetConnectionMetadata(remote_device); + ConnectionMetadata* existing_data = GetConnectionMetadata(remote_device); if (existing_data) { return existing_data; } - std::unique_ptr<base::Timer> timer = timer_factory_->CreateOneShotTimer(); - device_to_metadata_map_.insert( - std::pair<cryptauth::RemoteDevice, std::shared_ptr<ConnectionMetadata>>( - remote_device, - std::shared_ptr<ConnectionMetadata>( - new ConnectionMetadata(remote_device, std::move(timer), - weak_ptr_factory_.GetWeakPtr())))); - return device_to_metadata_map_.at(remote_device); + // Create the metadata. + std::unique_ptr<ConnectionMetadata> metadata = + base::WrapUnique(new ConnectionMetadata( + remote_device, timer_factory_->CreateOneShotTimer(), + weak_ptr_factory_.GetWeakPtr())); + ConnectionMetadata* metadata_raw_ptr = metadata.get(); + + // Add it to the map. + device_to_metadata_map_.emplace( + std::pair<cryptauth::RemoteDevice, std::unique_ptr<ConnectionMetadata>>( + remote_device, std::move(metadata))); + + return metadata_raw_ptr; } void BleConnectionManager::UpdateConnectionAttempts() { @@ -389,8 +396,7 @@ static_cast<size_t>(kMaxConcurrentAdvertisements)); for (const auto& remote_device : should_advertise_to) { - std::shared_ptr<ConnectionMetadata> associated_data = - GetConnectionMetadata(remote_device); + ConnectionMetadata* associated_data = GetConnectionMetadata(remote_device); if (associated_data->GetStatus() != cryptauth::SecureChannel::Status::CONNECTING) { // If there is no active attempt to connect to a device at the front of @@ -417,19 +423,13 @@ void BleConnectionManager::StartConnectionAttempt( const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<ConnectionMetadata> connection_metadata = + ConnectionMetadata* connection_metadata = GetConnectionMetadata(remote_device); DCHECK(connection_metadata); PA_LOG(INFO) << "Attempting connection - Device ID: \"" << remote_device.GetTruncatedDeviceIdForLogs() << "\""; - // Send a "disconnected => connecting" update to alert clients that a - // connection attempt for |remote_device| is underway. - SendSecureChannelStatusChangeEvent( - remote_device, cryptauth::SecureChannel::Status::DISCONNECTED, - cryptauth::SecureChannel::Status::CONNECTING); - bool success = ble_scanner_->RegisterScanFilterForDevice(remote_device) && ble_advertiser_->StartAdvertisingToDevice(remote_device); @@ -442,6 +442,12 @@ // case in order to route all connection failures through the same code path. connection_metadata->StartConnectionAttemptTimer( !success /* fail_immediately */); + + // Send a "disconnected => connecting" update to alert clients that a + // connection attempt for |remote_device| is underway. + SendSecureChannelStatusChangeEvent( + remote_device, cryptauth::SecureChannel::Status::DISCONNECTED, + cryptauth::SecureChannel::Status::CONNECTING); } void BleConnectionManager::StopConnectionAttemptAndMoveToEndOfQueue( @@ -476,8 +482,8 @@ } void BleConnectionManager::SendMessageReceivedEvent( - const cryptauth::RemoteDevice& remote_device, - const std::string& payload) { + cryptauth::RemoteDevice remote_device, + std::string payload) { PA_LOG(INFO) << "Message received - Device ID: \"" << remote_device.GetTruncatedDeviceIdForLogs() << "\", " << "Message: \"" << payload << "\"."; @@ -487,9 +493,9 @@ } void BleConnectionManager::SendSecureChannelStatusChangeEvent( - const cryptauth::RemoteDevice& remote_device, - const cryptauth::SecureChannel::Status& old_status, - const cryptauth::SecureChannel::Status& new_status) { + cryptauth::RemoteDevice remote_device, + cryptauth::SecureChannel::Status old_status, + cryptauth::SecureChannel::Status new_status) { PA_LOG(INFO) << "Status change - Device ID: \"" << remote_device.GetTruncatedDeviceIdForLogs() << "\": " << cryptauth::SecureChannel::StatusToString(old_status)
diff --git a/chromeos/components/tether/ble_connection_manager.h b/chromeos/components/tether/ble_connection_manager.h index aa7809d..3cb7f76 100644 --- a/chromeos/components/tether/ble_connection_manager.h +++ b/chromeos/components/tether/ble_connection_manager.h
@@ -121,12 +121,12 @@ std::unique_ptr<TimerFactory> timer_factory, cryptauth::BluetoothThrottler* bluetooth_throttler); - void SendMessageReceivedEvent(const cryptauth::RemoteDevice& remote_device, - const std::string& payload); + void SendMessageReceivedEvent(cryptauth::RemoteDevice remote_device, + std::string payload); void SendSecureChannelStatusChangeEvent( - const cryptauth::RemoteDevice& remote_device, - const cryptauth::SecureChannel::Status& old_status, - const cryptauth::SecureChannel::Status& new_status); + cryptauth::RemoteDevice remote_device, + cryptauth::SecureChannel::Status old_status, + cryptauth::SecureChannel::Status new_status); private: friend class BleConnectionManagerTest; @@ -142,7 +142,7 @@ class ConnectionMetadata : public cryptauth::SecureChannel::Observer { public: ConnectionMetadata(const cryptauth::RemoteDevice remote_device, - std::shared_ptr<base::Timer> timer, + std::unique_ptr<base::Timer> timer, base::WeakPtr<BleConnectionManager> manager); ~ConnectionMetadata(); @@ -175,17 +175,16 @@ cryptauth::RemoteDevice remote_device_; std::set<MessageType> active_connection_reasons_; - std::shared_ptr<cryptauth::SecureChannel> secure_channel_; - std::shared_ptr<base::Timer> connection_attempt_timeout_timer_; + std::unique_ptr<cryptauth::SecureChannel> secure_channel_; + std::unique_ptr<base::Timer> connection_attempt_timeout_timer_; base::WeakPtr<BleConnectionManager> manager_; base::WeakPtrFactory<ConnectionMetadata> weak_ptr_factory_; }; - - std::shared_ptr<ConnectionMetadata> GetConnectionMetadata( + ConnectionMetadata* GetConnectionMetadata( const cryptauth::RemoteDevice& remote_device) const; - std::shared_ptr<ConnectionMetadata> AddMetadataForDevice( + ConnectionMetadata* AddMetadataForDevice( const cryptauth::RemoteDevice& remote_device); void UpdateConnectionAttempts(); @@ -210,7 +209,7 @@ cryptauth::BluetoothThrottler* bluetooth_throttler_; bool has_registered_observer_; - std::map<cryptauth::RemoteDevice, std::shared_ptr<ConnectionMetadata>> + std::map<cryptauth::RemoteDevice, std::unique_ptr<ConnectionMetadata>> device_to_metadata_map_; base::ObserverList<Observer> observer_list_;
diff --git a/chromeos/components/tether/ble_connection_manager_unittest.cc b/chromeos/components/tether/ble_connection_manager_unittest.cc index 86cb008..864f625 100644 --- a/chromeos/components/tether/ble_connection_manager_unittest.cc +++ b/chromeos/components/tether/ble_connection_manager_unittest.cc
@@ -4,7 +4,6 @@ #include "chromeos/components/tether/ble_connection_manager.h" -#include "base/logging.h" #include "base/timer/mock_timer.h" #include "chromeos/components/tether/ble_constants.h" #include "chromeos/components/tether/proto/tether.pb.h" @@ -69,6 +68,8 @@ } }; +// Observer used in all tests except for ObserverUnregisters() which tracks all +// status changes and messages received. class TestObserver : public BleConnectionManager::Observer { public: TestObserver() {} @@ -100,6 +101,33 @@ std::vector<ReceivedMessage> received_messages_; }; +// Observer used in ObserverUnregisters() which unregisters a device when it +// receives a callback from the manager. The device it unregisters is the same +// one it receives the event about. +class UnregisteringObserver : public BleConnectionManager::Observer { + public: + UnregisteringObserver(BleConnectionManager* manager, + MessageType connection_reason) + : manager_(manager), connection_reason_(connection_reason) {} + + // BleConnectionManager::Observer: + void OnSecureChannelStatusChanged( + const cryptauth::RemoteDevice& remote_device, + const cryptauth::SecureChannel::Status& old_status, + const cryptauth::SecureChannel::Status& new_status) override { + manager_->UnregisterRemoteDevice(remote_device, connection_reason_); + } + + void OnMessageReceived(const cryptauth::RemoteDevice& remote_device, + const std::string& payload) override { + manager_->UnregisterRemoteDevice(remote_device, connection_reason_); + } + + private: + BleConnectionManager* manager_; + MessageType connection_reason_; +}; + class MockBleScanner : public BleScanner { public: MockBleScanner(scoped_refptr<device::BluetoothAdapter> adapter) @@ -336,8 +364,8 @@ } void VerifyNoTimeoutSet(const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<BleConnectionManager::ConnectionMetadata> - connection_metadata = manager_->GetConnectionMetadata(remote_device); + BleConnectionManager::ConnectionMetadata* connection_metadata = + manager_->GetConnectionMetadata(remote_device); EXPECT_TRUE(connection_metadata); EXPECT_FALSE( connection_metadata->connection_attempt_timeout_timer_->IsRunning()); @@ -357,8 +385,8 @@ void VerifyTimeoutSet(const cryptauth::RemoteDevice& remote_device, int64_t expected_num_millis) { - std::shared_ptr<BleConnectionManager::ConnectionMetadata> - connection_metadata = manager_->GetConnectionMetadata(remote_device); + BleConnectionManager::ConnectionMetadata* connection_metadata = + manager_->GetConnectionMetadata(remote_device); EXPECT_TRUE(connection_metadata); EXPECT_TRUE( connection_metadata->connection_attempt_timeout_timer_->IsRunning()); @@ -368,8 +396,8 @@ } void FireTimerForDevice(const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<BleConnectionManager::ConnectionMetadata> - connection_metadata = manager_->GetConnectionMetadata(remote_device); + BleConnectionManager::ConnectionMetadata* connection_metadata = + manager_->GetConnectionMetadata(remote_device); EXPECT_TRUE(connection_metadata); EXPECT_TRUE( connection_metadata->connection_attempt_timeout_timer_->IsRunning()); @@ -380,8 +408,8 @@ FakeSecureChannel* GetChannelForDevice( const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<BleConnectionManager::ConnectionMetadata> - connection_metadata = manager_->GetConnectionMetadata(remote_device); + BleConnectionManager::ConnectionMetadata* connection_metadata = + manager_->GetConnectionMetadata(remote_device); EXPECT_TRUE(connection_metadata); EXPECT_TRUE(connection_metadata->secure_channel_); return static_cast<FakeSecureChannel*>( @@ -389,14 +417,14 @@ } void VerifyDeviceRegistered(const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<BleConnectionManager::ConnectionMetadata> - connection_metadata = manager_->GetConnectionMetadata(remote_device); + BleConnectionManager::ConnectionMetadata* connection_metadata = + manager_->GetConnectionMetadata(remote_device); EXPECT_TRUE(connection_metadata); } void VerifyDeviceNotRegistered(const cryptauth::RemoteDevice& remote_device) { - std::shared_ptr<BleConnectionManager::ConnectionMetadata> - connection_metadata = manager_->GetConnectionMetadata(remote_device); + BleConnectionManager::ConnectionMetadata* connection_metadata = + manager_->GetConnectionMetadata(remote_device); EXPECT_FALSE(connection_metadata); } @@ -1216,6 +1244,70 @@ cryptauth::SecureChannel::Status::DISCONNECTED}}); } +// Regression test for crbug.com/733360. This bug caused a crash when there were +// multiple observers of BleConnectionManager. The bug was that when an event +// occurred which triggered observers to be notified (i.e., a status changed or +// message received event), sometimes one of the observers would unregister the +// device, which, in turn, caused the associated ConnectionMetadata to be +// deleted. Then, the next observer would be notified of the event after the +// deletion. Since the parameters to the observer callbacks were passed by +// reference (and the reference was held by the deleted ConnectionMetadata), +// this led to the second observer referencing deleted memory. The fix is to +// pass the parameters from the ConnectionMetadata to BleConnectionManager by +// value instead. +TEST_F(BleConnectionManagerTest, ObserverUnregisters) { + EXPECT_CALL(*mock_ble_scanner_, RegisterScanFilterForDevice(test_devices_[0])) + .Times(2); + EXPECT_CALL(*mock_ble_advertiser_, StartAdvertisingToDevice(test_devices_[0])) + .Times(2); + EXPECT_CALL(*mock_ble_scanner_, + UnregisterScanFilterForDevice(test_devices_[0])) + .Times(2); + EXPECT_CALL(*mock_ble_advertiser_, StopAdvertisingToDevice(test_devices_[0])) + .Times(2); + + FakeSecureChannel* channel = + ConnectSuccessfully(test_devices_[0], std::string(kBluetoothAddress1), + MessageType::TETHER_AVAILABILITY_REQUEST); + + // Register two separate UnregisteringObservers. When a message is received, + // the first observer will unregister the device. + UnregisteringObserver first(manager_.get(), + MessageType::TETHER_AVAILABILITY_REQUEST); + UnregisteringObserver second(manager_.get(), + MessageType::TETHER_AVAILABILITY_REQUEST); + manager_->AddObserver(&first); + manager_->AddObserver(&second); + + // Receive a message over the channel. This should invoke the observer + // callbacks. This would have caused a crash before the fix for + // crbug.com/733360. + channel->ReceiveMessage(std::string(kTetherFeature), "response1"); + VerifyReceivedMessages( + std::vector<ReceivedMessage>{{test_devices_[0], "response1"}}); + + // We expect the device to be unregistered (by the observer). + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0], cryptauth::SecureChannel::Status::AUTHENTICATED, + cryptauth::SecureChannel::Status::DISCONNECTED}}); + VerifyDeviceNotRegistered(test_devices_[0]); + + // Now, register the device again. This should cause a "disconnected => + // connecting" status change. This time, the multiple observers will respond + // to a status change event instead of a message received event. This also + // would have caused a crash before the fix for crbug.com/733360. + manager_->RegisterRemoteDevice(test_devices_[0], + MessageType::TETHER_AVAILABILITY_REQUEST); + + // We expect the device to be unregistered (by the observer). + VerifyConnectionStateChanges(std::vector<SecureChannelStatusChange>{ + {test_devices_[0], cryptauth::SecureChannel::Status::DISCONNECTED, + cryptauth::SecureChannel::Status::CONNECTING}, + {test_devices_[0], cryptauth::SecureChannel::Status::CONNECTING, + cryptauth::SecureChannel::Status::DISCONNECTED}}); + VerifyDeviceNotRegistered(test_devices_[0]); +} + } // namespace tether } // namespace cryptauth
diff --git a/components/component_updater/configurator_impl.cc b/components/component_updater/configurator_impl.cc index b695238..c4b10eb 100644 --- a/components/component_updater/configurator_impl.cc +++ b/components/component_updater/configurator_impl.cc
@@ -203,11 +203,10 @@ } std::vector<uint8_t> ConfiguratorImpl::GetRunActionKeyHash() const { - // The component id is: iddcipcljjhfegcfaaaapdilddpplalp - return std::vector<uint8_t>{0x83, 0x32, 0x8f, 0x2b, 0x99, 0x75, 0x46, 0x25, - 0x00, 0x00, 0xf3, 0x8b, 0x33, 0xff, 0xb0, 0xbf, - 0xea, 0xea, 0x19, 0xb3, 0x38, 0xfb, 0xdc, 0xb3, - 0x28, 0x90, 0x5f, 0xe2, 0xbe, 0x28, 0x89, 0x11}; + return std::vector<uint8_t>{0x97, 0xf0, 0xbe, 0xe4, 0x3f, 0x2b, 0x9e, 0xcf, + 0x2c, 0x50, 0x61, 0xdf, 0xc2, 0x6e, 0x0b, 0x4a, + 0x4f, 0x1e, 0xda, 0x71, 0x29, 0x64, 0x74, 0x70, + 0x15, 0x07, 0x18, 0xb7, 0x92, 0x04, 0xcd, 0x70}; } } // namespace component_updater
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index db7e028..e80b933a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -712,7 +712,7 @@ std::string page_id_value; if (page_id) { - char page_id_buffer[16]; + char page_id_buffer[17]; if (base::strings::SafeSPrintf(page_id_buffer, "%x", page_id.value()) > 0) { page_id_value = std::string("pid=") + page_id_buffer;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc index d2f0b5dd..faec819e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
@@ -182,12 +182,17 @@ header_value += header_value_; if (page_id) { - char page_id_buffer[16]; + // 64 bit uint fits in 16 characters when represented in hexadecimal, but + // there needs to be a trailing null termianted character in the buffer. + char page_id_buffer[17]; if (base::strings::SafeSPrintf(page_id_buffer, "%x", page_id.value()) > 0) { header_value += ", " + FormatOption(kPageIdOption, page_id_buffer); } + uint64_t page_id_tested; + DCHECK(base::HexStringToUInt64(page_id_buffer, &page_id_tested) && + page_id_tested == page_id.value()); + ALLOW_UNUSED_LOCAL(page_id_tested); } - request_headers->SetHeader(kChromeProxyHeader, header_value); }
diff --git a/components/exo/layer_tree_frame_sink_holder.h b/components/exo/layer_tree_frame_sink_holder.h index f3e7f87c..cb16cdd7 100644 --- a/components/exo/layer_tree_frame_sink_holder.h +++ b/components/exo/layer_tree_frame_sink_holder.h
@@ -19,7 +19,7 @@ namespace exo { class Surface; -// This class talks to MojoCompositorFrameSink and keeps track of references to +// This class talks to CompositorFrameSink and keeps track of references to // the contents of Buffers. It's keeped alive by references from // release_callbacks_. It's destroyed when its owning Surface is destroyed and // the last outstanding release callback is called.
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc index dc79726..983c036 100644 --- a/components/exo/surface_unittest.cc +++ b/components/exo/surface_unittest.cc
@@ -53,7 +53,7 @@ surface->Attach(nullptr); surface->Commit(); // LayerTreeFrameSinkHolder::ReclaimResources() gets called via - // MojoCompositorFrameSinkClient interface. We need to wait here for the mojo + // CompositorFrameSinkClient interface. We need to wait here for the mojo // call to finish so that the release callback finishes running before // the assertion below. RunAllPendingInMessageLoop();
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc index 00bbedf..01f15da 100644 --- a/components/previews/core/previews_features.cc +++ b/components/previews/core/previews_features.cc
@@ -17,7 +17,7 @@ // Enables the Stale Previews timestamp on Previews infobars. const base::Feature kStalePreviewsTimestamp{"StalePreviewsTimestamp", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; } // namespace features } // namespace previews
diff --git a/components/ukm/public/mojo_ukm_recorder.cc b/components/ukm/public/mojo_ukm_recorder.cc index d62b146..2e07e8c 100644 --- a/components/ukm/public/mojo_ukm_recorder.cc +++ b/components/ukm/public/mojo_ukm_recorder.cc
@@ -4,7 +4,7 @@ #include "components/ukm/public/mojo_ukm_recorder.h" -#include "base/memory/ptr_util.h" +#include <utility> namespace ukm {
diff --git a/components/ukm/public/mojo_ukm_recorder.h b/components/ukm/public/mojo_ukm_recorder.h index de959b31..2df0780 100644 --- a/components/ukm/public/mojo_ukm_recorder.h +++ b/components/ukm/public/mojo_ukm_recorder.h
@@ -6,6 +6,7 @@ #define COMPONENTS_UKM_PUBLIC_MOJO_UKM_RECORDER_H_ #include "components/ukm/public/interfaces/ukm_interface.mojom.h" +#include "components/ukm/public/ukm_export.h" #include "components/ukm/public/ukm_recorder.h" namespace ukm { @@ -24,9 +25,9 @@ * recorder.GetEntryBuilder(coordination_unit_id, "MyEvent"); * builder->AddMetric("MyMetric", metric_value); */ -class MojoUkmRecorder : public UkmRecorder { +class UKM_EXPORT MojoUkmRecorder : public UkmRecorder { public: - MojoUkmRecorder(mojom::UkmRecorderInterfacePtr interface); + explicit MojoUkmRecorder(mojom::UkmRecorderInterfacePtr interface); ~MojoUkmRecorder() override; private:
diff --git a/components/ukm/public/ukm_recorder.h b/components/ukm/public/ukm_recorder.h index bcb5a4d..76d921c0 100644 --- a/components/ukm/public/ukm_recorder.h +++ b/components/ukm/public/ukm_recorder.h
@@ -7,6 +7,8 @@ #include <stddef.h> +#include <memory> + #include "base/callback.h" #include "base/feature_list.h" #include "base/macros.h" @@ -30,6 +32,10 @@ class RenderWidgetHostLatencyTracker; } +namespace resource_coordinator { +class CoordinationUnitManager; +} + namespace translate { class TranslateRankerImpl; } @@ -85,6 +91,7 @@ friend content::RenderFrameImpl; friend content::RenderWidgetHostLatencyTracker; friend password_manager::PasswordFormMetricsRecorder; + friend resource_coordinator::CoordinationUnitManager; FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, AddEntryWithEmptyMetrics); FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, EntryBuilderAndSerialization); FRIEND_TEST_ALL_PREFIXES(UkmServiceTest,
diff --git a/components/viz/client/client_layer_tree_frame_sink.cc b/components/viz/client/client_layer_tree_frame_sink.cc index 60b27d3..421af8c 100644 --- a/components/viz/client/client_layer_tree_frame_sink.cc +++ b/components/viz/client/client_layer_tree_frame_sink.cc
@@ -19,8 +19,8 @@ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, cc::SharedBitmapManager* shared_bitmap_manager, std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source, - cc::mojom::MojoCompositorFrameSinkPtrInfo compositor_frame_sink_info, - cc::mojom::MojoCompositorFrameSinkClientRequest client_request, + cc::mojom::CompositorFrameSinkPtrInfo compositor_frame_sink_info, + cc::mojom::CompositorFrameSinkClientRequest client_request, std::unique_ptr<LocalSurfaceIdProvider> local_surface_id_provider, bool enable_surface_synchronization) : cc::LayerTreeFrameSink(std::move(context_provider), @@ -40,8 +40,8 @@ ClientLayerTreeFrameSink::ClientLayerTreeFrameSink( scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider, std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source, - cc::mojom::MojoCompositorFrameSinkPtrInfo compositor_frame_sink_info, - cc::mojom::MojoCompositorFrameSinkClientRequest client_request, + cc::mojom::CompositorFrameSinkPtrInfo compositor_frame_sink_info, + cc::mojom::CompositorFrameSinkClientRequest client_request, std::unique_ptr<LocalSurfaceIdProvider> local_surface_id_provider, bool enable_surface_synchronization) : cc::LayerTreeFrameSink(std::move(vulkan_context_provider)),
diff --git a/components/viz/client/client_layer_tree_frame_sink.h b/components/viz/client/client_layer_tree_frame_sink.h index bbc6e37..a32c772 100644 --- a/components/viz/client/client_layer_tree_frame_sink.h +++ b/components/viz/client/client_layer_tree_frame_sink.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/output/context_provider.h" #include "cc/output/layer_tree_frame_sink.h" #include "cc/scheduler/begin_frame_source.h" @@ -19,10 +19,9 @@ class LocalSurfaceIdProvider; -class ClientLayerTreeFrameSink - : public cc::LayerTreeFrameSink, - public cc::mojom::MojoCompositorFrameSinkClient, - public cc::ExternalBeginFrameSourceClient { +class ClientLayerTreeFrameSink : public cc::LayerTreeFrameSink, + public cc::mojom::CompositorFrameSinkClient, + public cc::ExternalBeginFrameSourceClient { public: ClientLayerTreeFrameSink( scoped_refptr<cc::ContextProvider> context_provider, @@ -31,8 +30,8 @@ cc::SharedBitmapManager* shared_bitmap_manager, std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source, - cc::mojom::MojoCompositorFrameSinkPtrInfo compositor_frame_sink_info, - cc::mojom::MojoCompositorFrameSinkClientRequest client_request, + cc::mojom::CompositorFrameSinkPtrInfo compositor_frame_sink_info, + cc::mojom::CompositorFrameSinkClientRequest client_request, std::unique_ptr<LocalSurfaceIdProvider> local_surface_id_provider, bool enable_surface_synchronization); @@ -40,8 +39,8 @@ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider, std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source, - cc::mojom::MojoCompositorFrameSinkPtrInfo compositor_frame_sink_info, - cc::mojom::MojoCompositorFrameSinkClientRequest client_request, + cc::mojom::CompositorFrameSinkPtrInfo compositor_frame_sink_info, + cc::mojom::CompositorFrameSinkClientRequest client_request, std::unique_ptr<LocalSurfaceIdProvider> local_surface_id_provider, bool enable_surface_synchronization); @@ -57,7 +56,7 @@ void DidNotProduceFrame(const cc::BeginFrameAck& ack) override; private: - // cc::mojom::MojoCompositorFrameSinkClient implementation: + // cc::mojom::CompositorFrameSinkClient implementation: void DidReceiveCompositorFrameAck( const cc::ReturnedResourceArray& resources) override; void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_args) override; @@ -73,10 +72,10 @@ std::unique_ptr<LocalSurfaceIdProvider> local_surface_id_provider_; std::unique_ptr<cc::ExternalBeginFrameSource> begin_frame_source_; std::unique_ptr<cc::SyntheticBeginFrameSource> synthetic_begin_frame_source_; - cc::mojom::MojoCompositorFrameSinkPtrInfo compositor_frame_sink_info_; - cc::mojom::MojoCompositorFrameSinkClientRequest client_request_; - cc::mojom::MojoCompositorFrameSinkPtr compositor_frame_sink_; - mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> client_binding_; + cc::mojom::CompositorFrameSinkPtrInfo compositor_frame_sink_info_; + cc::mojom::CompositorFrameSinkClientRequest client_request_; + cc::mojom::CompositorFrameSinkPtr compositor_frame_sink_; + mojo::Binding<cc::mojom::CompositorFrameSinkClient> client_binding_; THREAD_CHECKER(thread_checker_); const bool enable_surface_synchronization_;
diff --git a/components/viz/host/frame_sink_manager_host.cc b/components/viz/host/frame_sink_manager_host.cc index 2670068..2f3eeeb 100644 --- a/components/viz/host/frame_sink_manager_host.cc +++ b/components/viz/host/frame_sink_manager_host.cc
@@ -33,8 +33,8 @@ void FrameSinkManagerHost::CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client) { DCHECK_EQ(frame_sink_data_map_.count(frame_sink_id), 0u); FrameSinkData& data = frame_sink_data_map_[frame_sink_id]; @@ -53,7 +53,7 @@ if (data.parent.has_value()) UnregisterFrameSinkHierarchy(data.parent.value(), frame_sink_id); - // This destroys the MojoCompositorFrameSinkPrivatePtr and closes the pipe. + // This destroys the CompositorFrameSinkPrivatePtr and closes the pipe. frame_sink_data_map_.erase(iter); }
diff --git a/components/viz/host/frame_sink_manager_host.h b/components/viz/host/frame_sink_manager_host.h index 00a9999..1a18467 100644 --- a/components/viz/host/frame_sink_manager_host.h +++ b/components/viz/host/frame_sink_manager_host.h
@@ -45,8 +45,8 @@ // call DestroyCompositorFrameSink(). void CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client); + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client); // Destroys a client connection. Will call UnregisterFrameSinkHierarchy() with // the registered parent if there is one. @@ -54,7 +54,7 @@ // Registers FrameSink hierarchy. Clients can call this multiple times to // reparent without calling UnregisterFrameSinkHierarchy(). If a client uses - // MojoCompositorFrameSink, then CreateCompositorFrameSink() should be called + // CompositorFrameSink, then CreateCompositorFrameSink() should be called // before this. void RegisterFrameSinkHierarchy(const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& child_frame_sink_id); @@ -77,8 +77,9 @@ // The private interface that gives the host control over the // CompositorFrameSink connection between the client and viz. - cc::mojom::MojoCompositorFrameSinkPrivatePtr private_interface; + cc::mojom::CompositorFrameSinkPrivatePtr private_interface; + private: DISALLOW_COPY_AND_ASSIGN(FrameSinkData); };
diff --git a/components/viz/host/frame_sink_manager_host_unittests.cc b/components/viz/host/frame_sink_manager_host_unittests.cc index bb5643b..d2c939d 100644 --- a/components/viz/host/frame_sink_manager_host_unittests.cc +++ b/components/viz/host/frame_sink_manager_host_unittests.cc
@@ -26,29 +26,29 @@ closure.Run(); } -// A stub MojoCompositorFrameSinkClient that does nothing. -class StubClientCompositorFrameSink - : public cc::mojom::MojoCompositorFrameSinkClient { +// A stub CompositorFrameSinkClient that does nothing. +class StubCompositorFrameSinkClient + : public cc::mojom::CompositorFrameSinkClient { public: - StubClientCompositorFrameSink() : binding_(this) {} - ~StubClientCompositorFrameSink() override = default; + StubCompositorFrameSinkClient() : binding_(this) {} + ~StubCompositorFrameSinkClient() override = default; - cc::mojom::MojoCompositorFrameSinkClientPtr GetInterfacePtr() { - cc::mojom::MojoCompositorFrameSinkClientPtr client; + cc::mojom::CompositorFrameSinkClientPtr GetInterfacePtr() { + cc::mojom::CompositorFrameSinkClientPtr client; binding_.Bind(mojo::MakeRequest(&client)); return client; } private: - // cc::mojom::MojoCompositorFrameSinkClient: + // cc::mojom::CompositorFrameSinkClient: void DidReceiveCompositorFrameAck( const cc::ReturnedResourceArray& resources) override {} void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_args) override {} void ReclaimResources(const cc::ReturnedResourceArray& resources) override {} - mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> binding_; + mojo::Binding<cc::mojom::CompositorFrameSinkClient> binding_; - DISALLOW_COPY_AND_ASSIGN(StubClientCompositorFrameSink); + DISALLOW_COPY_AND_ASSIGN(StubCompositorFrameSinkClient); }; // A mock implementation of mojom::FrameSinkManager. @@ -68,16 +68,16 @@ void CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request) override {} void CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) override {} + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client) override {} MOCK_METHOD2(RegisterFrameSinkHierarchy, void(const cc::FrameSinkId& parent, const cc::FrameSinkId& child)); @@ -135,8 +135,8 @@ TEST_F(FrameSinkManagerHostTest, UnregisterHierarchyOnDestroy) { base::RunLoop run_loop; - cc::mojom::MojoCompositorFrameSinkPtr frame_sink; - StubClientCompositorFrameSink frame_sink_client; + cc::mojom::CompositorFrameSinkPtr frame_sink; + StubCompositorFrameSinkClient frame_sink_client; manager_host().CreateCompositorFrameSink(kFrameSinkId1, mojo::MakeRequest(&frame_sink), frame_sink_client.GetInterfacePtr());
diff --git a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc index 045cba6..d6b2771 100644 --- a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc +++ b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc
@@ -10,10 +10,10 @@ GpuCompositorFrameSinkDelegate* delegate, cc::SurfaceManager* surface_manager, const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest compositor_frame_sink_private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) + cc::mojom::CompositorFrameSinkClientPtr client) : delegate_(delegate), support_(cc::CompositorFrameSinkSupport::Create( this,
diff --git a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h index 89cb6246..40f920c 100644 --- a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h +++ b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/surfaces/compositor_frame_sink_support.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" #include "cc/surfaces/local_surface_id.h" @@ -23,26 +23,26 @@ // Server side representation of a WindowSurface. class GpuCompositorFrameSink : public NON_EXPORTED_BASE(cc::CompositorFrameSinkSupportClient), - public NON_EXPORTED_BASE(cc::mojom::MojoCompositorFrameSink), - public NON_EXPORTED_BASE(cc::mojom::MojoCompositorFrameSinkPrivate) { + public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink), + public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSinkPrivate) { public: GpuCompositorFrameSink( GpuCompositorFrameSinkDelegate* delegate, cc::SurfaceManager* surface_manager, const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client); + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client); ~GpuCompositorFrameSink() override; - // cc::mojom::MojoCompositorFrameSink: + // cc::mojom::CompositorFrameSink: void SetNeedsBeginFrame(bool needs_begin_frame) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; void DidNotProduceFrame(const cc::BeginFrameAck& begin_frame_ack) override; - // cc::mojom::MojoCompositorFrameSinkPrivate: + // cc::mojom::CompositorFrameSinkPrivate: void ClaimTemporaryReference(const cc::SurfaceId& surface_id) override; void RequestCopyOfSurface( std::unique_ptr<cc::CopyOutputRequest> request) override; @@ -65,10 +65,9 @@ bool client_connection_lost_ = false; bool private_connection_lost_ = false; - cc::mojom::MojoCompositorFrameSinkClientPtr client_; - mojo::Binding<cc::mojom::MojoCompositorFrameSink> - compositor_frame_sink_binding_; - mojo::Binding<cc::mojom::MojoCompositorFrameSinkPrivate> + cc::mojom::CompositorFrameSinkClientPtr client_; + mojo::Binding<cc::mojom::CompositorFrameSink> compositor_frame_sink_binding_; + mojo::Binding<cc::mojom::CompositorFrameSinkPrivate> compositor_frame_sink_private_binding_; DISALLOW_COPY_AND_ASSIGN(GpuCompositorFrameSink);
diff --git a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc index 2da7aa1e..57eede9 100644 --- a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc +++ b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc
@@ -15,10 +15,10 @@ const cc::FrameSinkId& frame_sink_id, std::unique_ptr<cc::Display> display, std::unique_ptr<cc::BeginFrameSource> begin_frame_source, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest compositor_frame_sink_private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request) : delegate_(delegate), support_(cc::CompositorFrameSinkSupport::Create(
diff --git a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h index 112e2443..3f03f79d 100644 --- a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h +++ b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h
@@ -5,8 +5,8 @@ #ifndef COMPONENTS_VIZ_SERVICE_FRAME_SINKS_GPU_ROOT_COMPOSITOR_FRAME_SINK_H_ #define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_GPU_ROOT_COMPOSITOR_FRAME_SINK_H_ +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/ipc/frame_sink_manager.mojom.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" #include "cc/surfaces/compositor_frame_sink_support_client.h" #include "cc/surfaces/display_client.h" #include "cc/surfaces/local_surface_id.h" @@ -28,8 +28,8 @@ class GpuRootCompositorFrameSink : public NON_EXPORTED_BASE(cc::CompositorFrameSinkSupportClient), - public NON_EXPORTED_BASE(cc::mojom::MojoCompositorFrameSink), - public NON_EXPORTED_BASE(cc::mojom::MojoCompositorFrameSinkPrivate), + public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink), + public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSinkPrivate), public NON_EXPORTED_BASE(cc::mojom::DisplayPrivate), public NON_EXPORTED_BASE(cc::DisplayClient) { public: @@ -39,9 +39,9 @@ const cc::FrameSinkId& frame_sink_id, std::unique_ptr<cc::Display> display, std::unique_ptr<cc::BeginFrameSource> begin_frame_source, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request); ~GpuRootCompositorFrameSink() override; @@ -54,13 +54,13 @@ void SetLocalSurfaceId(const cc::LocalSurfaceId& local_surface_id, float scale_factor) override; - // cc::mojom::MojoCompositorFrameSink: + // cc::mojom::CompositorFrameSink: void SetNeedsBeginFrame(bool needs_begin_frame) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; void DidNotProduceFrame(const cc::BeginFrameAck& begin_frame_ack) override; - // cc::mojom::MojoCompositorFrameSinkPrivate: + // cc::mojom::CompositorFrameSinkPrivate: void ClaimTemporaryReference(const cc::SurfaceId& surface_id) override; void RequestCopyOfSurface( std::unique_ptr<cc::CopyOutputRequest> request) override; @@ -94,10 +94,10 @@ bool client_connection_lost_ = false; bool private_connection_lost_ = false; - cc::mojom::MojoCompositorFrameSinkClientPtr client_; - mojo::AssociatedBinding<cc::mojom::MojoCompositorFrameSink> + cc::mojom::CompositorFrameSinkClientPtr client_; + mojo::AssociatedBinding<cc::mojom::CompositorFrameSink> compositor_frame_sink_binding_; - mojo::Binding<cc::mojom::MojoCompositorFrameSinkPrivate> + mojo::Binding<cc::mojom::CompositorFrameSinkPrivate> compositor_frame_sink_private_binding_; mojo::AssociatedBinding<cc::mojom::DisplayPrivate> display_private_binding_;
diff --git a/components/viz/service/frame_sinks/mojo_frame_sink_manager.cc b/components/viz/service/frame_sinks/mojo_frame_sink_manager.cc index 78ff7fa3..01eb0318 100644 --- a/components/viz/service/frame_sinks/mojo_frame_sink_manager.cc +++ b/components/viz/service/frame_sinks/mojo_frame_sink_manager.cc
@@ -49,9 +49,9 @@ void MojoFrameSinkManager::CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_NE(surface_handle, gpu::kNullSurfaceHandle); @@ -72,9 +72,9 @@ void MojoFrameSinkManager::CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_EQ(0u, compositor_frame_sinks_.count(frame_sink_id));
diff --git a/components/viz/service/frame_sinks/mojo_frame_sink_manager.h b/components/viz/service/frame_sinks/mojo_frame_sink_manager.h index d883730b..1cb0666 100644 --- a/components/viz/service/frame_sinks/mojo_frame_sink_manager.h +++ b/components/viz/service/frame_sinks/mojo_frame_sink_manager.h
@@ -53,16 +53,16 @@ void CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request) override; void CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) override; + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client) override; void RegisterFrameSinkHierarchy( const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& child_frame_sink_id) override; @@ -106,7 +106,7 @@ DisplayProvider* const display_provider_; std::unordered_map<cc::FrameSinkId, - std::unique_ptr<cc::mojom::MojoCompositorFrameSink>, + std::unique_ptr<cc::mojom::CompositorFrameSink>, cc::FrameSinkIdHash> compositor_frame_sinks_;
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc index 3a00577..2062fe0 100644 --- a/content/browser/devtools/devtools_http_handler.cc +++ b/content/browser/devtools/devtools_http_handler.cc
@@ -20,6 +20,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread.h" #include "base/values.h" #include "build/build_config.h" @@ -170,20 +171,18 @@ // Thread and ServerWrapper lifetime management ------------------------------ -void TerminateOnUI(base::Thread* thread, - ServerWrapper* server_wrapper, - DevToolsSocketFactory* socket_factory) { +void TerminateOnUI(std::unique_ptr<base::Thread> thread, + std::unique_ptr<ServerWrapper> server_wrapper, + std::unique_ptr<DevToolsSocketFactory> socket_factory) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (server_wrapper) { - DCHECK(thread); - thread->task_runner()->DeleteSoon(FROM_HERE, server_wrapper); - } - if (socket_factory) { - DCHECK(thread); - thread->task_runner()->DeleteSoon(FROM_HERE, socket_factory); - } + if (server_wrapper) + thread->task_runner()->DeleteSoon(FROM_HERE, std::move(server_wrapper)); + if (socket_factory) + thread->task_runner()->DeleteSoon(FROM_HERE, std::move(socket_factory)); if (thread) { - BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, thread); + base::PostTaskWithTraits( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + BindOnce([](std::unique_ptr<base::Thread>) {}, std::move(thread))); } } @@ -194,28 +193,33 @@ std::unique_ptr<net::IPEndPoint> ip_address) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (handler && thread && server_wrapper) { - handler->ServerStarted(thread, server_wrapper, socket_factory, - std::move(ip_address)); + handler->ServerStarted( + std::unique_ptr<base::Thread>(thread), + std::unique_ptr<ServerWrapper>(server_wrapper), + std::unique_ptr<DevToolsSocketFactory>(socket_factory), + std::move(ip_address)); } else { - TerminateOnUI(thread, server_wrapper, socket_factory); + TerminateOnUI(std::unique_ptr<base::Thread>(thread), + std::unique_ptr<ServerWrapper>(server_wrapper), + std::unique_ptr<DevToolsSocketFactory>(socket_factory)); } } void StartServerOnHandlerThread( base::WeakPtr<DevToolsHttpHandler> handler, - base::Thread* thread, - DevToolsSocketFactory* socket_factory, + std::unique_ptr<base::Thread> thread, + std::unique_ptr<DevToolsSocketFactory> socket_factory, const base::FilePath& output_directory, const base::FilePath& frontend_dir, bool bundles_resources) { DCHECK(thread->task_runner()->BelongsToCurrentThread()); - ServerWrapper* server_wrapper = nullptr; + std::unique_ptr<ServerWrapper> server_wrapper; std::unique_ptr<net::ServerSocket> server_socket = socket_factory->CreateForHttpServer(); std::unique_ptr<net::IPEndPoint> ip_address(new net::IPEndPoint); if (server_socket) { - server_wrapper = new ServerWrapper(handler, std::move(server_socket), - frontend_dir, bundles_resources); + server_wrapper.reset(new ServerWrapper(handler, std::move(server_socket), + frontend_dir, bundles_resources)); if (!output_directory.empty()) server_wrapper->WriteActivePortToUserProfile(output_directory); @@ -225,34 +229,11 @@ ip_address.reset(); LOG(ERROR) << "Cannot start http server for devtools. Stop devtools."; } - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&ServerStartedOnUI, - handler, - thread, - server_wrapper, - socket_factory, - base::Passed(&ip_address))); -} - -void StartServerOnFile( - base::WeakPtr<DevToolsHttpHandler> handler, - DevToolsSocketFactory* socket_factory, - const base::FilePath& output_directory, - const base::FilePath& frontend_dir, - bool bundles_resources) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); - std::unique_ptr<base::Thread> thread( - new base::Thread(kDevToolsHandlerThreadName)); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - if (thread->StartWithOptions(options)) { - base::MessageLoop* message_loop = thread->message_loop(); - message_loop->task_runner()->PostTask( - FROM_HERE, - base::Bind(&StartServerOnHandlerThread, handler, - base::Unretained(thread.release()), socket_factory, - output_directory, frontend_dir, bundles_resources)); - } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&ServerStartedOnUI, std::move(handler), thread.release(), + server_wrapper.release(), socket_factory.release(), + std::move(ip_address))); } // DevToolsAgentHostClientImpl ----------------------------------------------- @@ -328,7 +309,8 @@ // DevToolsHttpHandler ------------------------------------------------------- DevToolsHttpHandler::~DevToolsHttpHandler() { - TerminateOnUI(thread_, server_wrapper_, socket_factory_); + TerminateOnUI(std::move(thread_), std::move(server_wrapper_), + std::move(socket_factory_)); } static std::string PathWithoutParams(const std::string& path) { @@ -653,9 +635,9 @@ response.SetBody(json_protocol, "application/json; charset=UTF-8"); thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind(&ServerWrapper::SendResponse, - base::Unretained(server_wrapper_), connection_id, response)); + FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse, + base::Unretained(server_wrapper_.get()), + connection_id, response)); } void DevToolsHttpHandler::RespondToJsonList( @@ -695,9 +677,9 @@ DevToolsAgentHost::CreateForBrowser( thread_->task_runner(), base::Bind(&DevToolsSocketFactory::CreateForTethering, - base::Unretained(socket_factory_))); + base::Unretained(socket_factory_.get()))); connection_to_client_[connection_id].reset(new DevToolsAgentHostClientImpl( - thread_->message_loop(), server_wrapper_, connection_id, + thread_->message_loop(), server_wrapper_.get(), connection_id, browser_agent)); AcceptWebSocket(connection_id, request); return; @@ -724,7 +706,7 @@ } connection_to_client_[connection_id].reset(new DevToolsAgentHostClientImpl( - thread_->message_loop(), server_wrapper_, connection_id, agent)); + thread_->message_loop(), server_wrapper_.get(), connection_id, agent)); AcceptWebSocket(connection_id, request); } @@ -750,37 +732,37 @@ const base::FilePath& debug_frontend_dir, const std::string& product_name, const std::string& user_agent) - : thread_(nullptr), - frontend_url_(frontend_url), + : frontend_url_(frontend_url), product_name_(product_name), user_agent_(user_agent), - server_wrapper_(nullptr), delegate_(delegate), - socket_factory_(nullptr), weak_factory_(this) { bool bundles_resources = frontend_url_.empty(); if (frontend_url_.empty()) frontend_url_ = "/devtools/inspector.html"; - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&StartServerOnFile, - weak_factory_.GetWeakPtr(), - socket_factory.release(), - output_directory, - debug_frontend_dir, - bundles_resources)); + std::unique_ptr<base::Thread> thread( + new base::Thread(kDevToolsHandlerThreadName)); + base::Thread::Options options; + options.message_loop_type = base::MessageLoop::TYPE_IO; + if (thread->StartWithOptions(options)) { + thread->task_runner()->PostTask( + FROM_HERE, base::BindOnce(&StartServerOnHandlerThread, + weak_factory_.GetWeakPtr(), std::move(thread), + std::move(socket_factory), output_directory, + debug_frontend_dir, bundles_resources)); + } } void DevToolsHttpHandler::ServerStarted( - base::Thread* thread, - ServerWrapper* server_wrapper, - DevToolsSocketFactory* socket_factory, + std::unique_ptr<base::Thread> thread, + std::unique_ptr<ServerWrapper> server_wrapper, + std::unique_ptr<DevToolsSocketFactory> socket_factory, std::unique_ptr<net::IPEndPoint> ip_address) { - thread_ = thread; - server_wrapper_ = server_wrapper; - socket_factory_ = socket_factory; - server_ip_address_.swap(ip_address); + thread_ = std::move(thread); + server_wrapper_ = std::move(server_wrapper); + socket_factory_ = std::move(socket_factory); + server_ip_address_ = std::move(ip_address); } void ServerWrapper::WriteActivePortToUserProfile( @@ -824,9 +806,9 @@ response.SetBody(json_value + message, "application/json; charset=UTF-8"); thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind(&ServerWrapper::SendResponse, - base::Unretained(server_wrapper_), connection_id, response)); + FROM_HERE, base::Bind(&ServerWrapper::SendResponse, + base::Unretained(server_wrapper_.get()), + connection_id, response)); } void DevToolsHttpHandler::Send200(int connection_id, @@ -835,17 +817,18 @@ if (!thread_) return; thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind(&ServerWrapper::Send200, base::Unretained(server_wrapper_), - connection_id, data, mime_type)); + FROM_HERE, base::BindOnce(&ServerWrapper::Send200, + base::Unretained(server_wrapper_.get()), + connection_id, data, mime_type)); } void DevToolsHttpHandler::Send404(int connection_id) { if (!thread_) return; thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&ServerWrapper::Send404, - base::Unretained(server_wrapper_), connection_id)); + FROM_HERE, + base::BindOnce(&ServerWrapper::Send404, + base::Unretained(server_wrapper_.get()), connection_id)); } void DevToolsHttpHandler::Send500(int connection_id, @@ -853,9 +836,9 @@ if (!thread_) return; thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind(&ServerWrapper::Send500, base::Unretained(server_wrapper_), - connection_id, message)); + FROM_HERE, base::BindOnce(&ServerWrapper::Send500, + base::Unretained(server_wrapper_.get()), + connection_id, message)); } void DevToolsHttpHandler::AcceptWebSocket( @@ -864,9 +847,9 @@ if (!thread_) return; thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind(&ServerWrapper::AcceptWebSocket, - base::Unretained(server_wrapper_), connection_id, request)); + FROM_HERE, base::BindOnce(&ServerWrapper::AcceptWebSocket, + base::Unretained(server_wrapper_.get()), + connection_id, request)); } std::unique_ptr<base::DictionaryValue> DevToolsHttpHandler::SerializeDescriptor(
diff --git a/content/browser/devtools/devtools_http_handler.h b/content/browser/devtools/devtools_http_handler.h index 72836212..4ef44136 100644 --- a/content/browser/devtools/devtools_http_handler.h +++ b/content/browser/devtools/devtools_http_handler.h
@@ -80,9 +80,9 @@ void OnWebSocketMessage(int connection_id, const std::string& data); void OnClose(int connection_id); - void ServerStarted(base::Thread* thread, - ServerWrapper* server_wrapper, - DevToolsSocketFactory* socket_factory, + void ServerStarted(std::unique_ptr<base::Thread> thread, + std::unique_ptr<ServerWrapper> server_wrapper, + std::unique_ptr<DevToolsSocketFactory> socket_factory, std::unique_ptr<net::IPEndPoint> ip_address); void SendJson(int connection_id, @@ -109,17 +109,17 @@ const std::string& host); // The thread used by the devtools handler to run server socket. - base::Thread* thread_; + std::unique_ptr<base::Thread> thread_; std::string frontend_url_; std::string product_name_; std::string user_agent_; - ServerWrapper* server_wrapper_; + std::unique_ptr<ServerWrapper> server_wrapper_; std::unique_ptr<net::IPEndPoint> server_ip_address_; using ConnectionToClientMap = std::map<int, std::unique_ptr<DevToolsAgentHostClientImpl>>; ConnectionToClientMap connection_to_client_; DevToolsManagerDelegate* delegate_; - DevToolsSocketFactory* socket_factory_; + std::unique_ptr<DevToolsSocketFactory> socket_factory_; base::WeakPtrFactory<DevToolsHttpHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandler);
diff --git a/content/browser/devtools/devtools_http_handler_unittest.cc b/content/browser/devtools/devtools_http_handler_unittest.cc index a4ad827e..7232833 100644 --- a/content/browser/devtools/devtools_http_handler_unittest.cc +++ b/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -158,10 +158,8 @@ // Our dummy socket factory will post a quit message once the server will // become ready. run_loop.Run(); - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) RunAllPendingInMessageLoop(BrowserThread::UI); - RunAllPendingInMessageLoop(BrowserThread::FILE); - } DevToolsAgentHost::StopRemoteDebuggingServer(); // Make sure the handler actually stops. run_loop_2.Run();
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc index 9d354304..c65878e 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -425,7 +425,7 @@ } void RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { ResetCompositorFrameSinkSupport(); renderer_compositor_frame_sink_ = renderer_compositor_frame_sink; CreateCompositorFrameSinkSupport();
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h index 38840a32..a1959a6 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.h +++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -115,7 +115,7 @@ void GestureEventAck(const blink::WebGestureEvent& event, InputEventAckState ack_result) override; void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; @@ -280,7 +280,7 @@ cc::FrameSinkId parent_frame_sink_id_; bool has_frame_ = false; - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_ = + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; // The background color of the widget.
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc index d589fd2..ceb9813 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -101,10 +101,10 @@ test_frame_connector_ = new MockCrossProcessFrameConnector(); view_->SetCrossProcessFrameConnector(test_frame_connector_); - cc::mojom::MojoCompositorFrameSinkPtr sink; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtr sink; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink); - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_); renderer_compositor_frame_sink_ = base::MakeUnique<FakeRendererCompositorFrameSink>( @@ -156,8 +156,7 @@ renderer_compositor_frame_sink_; private: - cc::mojom::MojoCompositorFrameSinkClientPtr - renderer_compositor_frame_sink_ptr_; + cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrameTest); };
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc index b8ed3b2..a3f8cd8 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -443,7 +443,7 @@ } void RenderWidgetHostViewGuest::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { RenderWidgetHostViewChildFrame::DidCreateNewRendererCompositorFrameSink( renderer_compositor_frame_sink); platform_view_->DidCreateNewRendererCompositorFrameSink(
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h index 753c32ed..f11f219 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.h +++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -106,7 +106,7 @@ bool LockMouse() override; void UnlockMouse() override; void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; #if defined(OS_MACOSX)
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc index 5145d04..0453cdd2 100644 --- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -169,10 +169,10 @@ view_ = RenderWidgetHostViewGuest::Create( widget_host_, browser_plugin_guest_, (new TestRenderWidgetHostView(widget_host_))->GetWeakPtr()); - cc::mojom::MojoCompositorFrameSinkPtr sink; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtr sink; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink); - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_); renderer_compositor_frame_sink_ = base::MakeUnique<FakeRendererCompositorFrameSink>( @@ -220,8 +220,7 @@ renderer_compositor_frame_sink_; private: - cc::mojom::MojoCompositorFrameSinkClientPtr - renderer_compositor_frame_sink_ptr_; + cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest); };
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index 9be1c75..37bd5b9 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -56,12 +56,12 @@ ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac(); void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink); + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink); void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame); void OnDidNotProduceFrame(const cc::BeginFrameAck& ack); void SetHasTransparentBackground(bool transparent); - void SetDisplayColorProfile(const gfx::ICCProfile& icc_profile); + void SetDisplayColorSpace(const gfx::ColorSpace& color_space); void UpdateVSyncParameters(const base::TimeTicks& timebase, const base::TimeDelta& interval); void SetNeedsBeginFrames(bool needs_begin_frames); @@ -163,7 +163,7 @@ std::unique_ptr<ui::Layer> root_layer_; bool has_transparent_background_ = false; - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_ = + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; base::WeakPtrFactory<BrowserCompositorMac> weak_factory_;
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index f96ee5f..082550d0 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -271,7 +271,7 @@ } void BrowserCompositorMac::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { renderer_compositor_frame_sink_ = renderer_compositor_frame_sink; delegated_frame_host_->DidCreateNewRendererCompositorFrameSink( renderer_compositor_frame_sink_); @@ -306,10 +306,10 @@ } } -void BrowserCompositorMac::SetDisplayColorProfile( - const gfx::ICCProfile& icc_profile) { +void BrowserCompositorMac::SetDisplayColorSpace( + const gfx::ColorSpace& color_space) { if (recyclable_compositor_) - recyclable_compositor_->compositor()->SetDisplayColorProfile(icc_profile); + recyclable_compositor_->compositor()->SetDisplayColorSpace(color_space); } void BrowserCompositorMac::UpdateVSyncParameters(
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 820ec29..e6b8725 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -381,7 +381,7 @@ } void DelegatedFrameHost::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { ResetCompositorFrameSinkSupport(); renderer_compositor_frame_sink_ = renderer_compositor_frame_sink; CreateCompositorFrameSinkSupport();
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index 08f8b950..a418dcc7 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -119,7 +119,7 @@ // Public interface exposed to RenderWidgetHostView. void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink); + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink); void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame); void ClearDelegatedFrame(); @@ -320,7 +320,7 @@ cc::BeginFrameArgs::kInvalidFrameNumber; bool has_frame_ = false; - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_ = + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; std::unique_ptr<viz::FrameEvictor> frame_evictor_;
diff --git a/content/browser/renderer_host/frame_sink_provider_impl.cc b/content/browser/renderer_host/frame_sink_provider_impl.cc index d01ace8..3fc3f0f 100644 --- a/content/browser/renderer_host/frame_sink_provider_impl.cc +++ b/content/browser/renderer_host/frame_sink_provider_impl.cc
@@ -26,8 +26,8 @@ void FrameSinkProviderImpl::CreateForWidget( int32_t widget_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client) { RenderWidgetHostImpl* render_widget_host_impl = RenderWidgetHostImpl::FromID(process_id_, widget_id); if (!render_widget_host_impl) { @@ -35,8 +35,8 @@ << "in process " << process_id_; return; } - render_widget_host_impl->RequestMojoCompositorFrameSink(std::move(request), - std::move(client)); + render_widget_host_impl->RequestCompositorFrameSink(std::move(request), + std::move(client)); } } // namespace content
diff --git a/content/browser/renderer_host/frame_sink_provider_impl.h b/content/browser/renderer_host/frame_sink_provider_impl.h index 29b19c4..52a7b29 100644 --- a/content/browser/renderer_host/frame_sink_provider_impl.h +++ b/content/browser/renderer_host/frame_sink_provider_impl.h
@@ -10,7 +10,7 @@ namespace content { -// This class lives in the browser and provides MojoCompositorFrameSink for the +// This class lives in the browser and provides CompositorFrameSink for the // renderer. class FrameSinkProviderImpl : public mojom::FrameSinkProvider { public: @@ -21,10 +21,9 @@ void Unbind(); // mojom::FrameSinkProvider implementation. - void CreateForWidget( - int32_t widget_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) override; + void CreateForWidget(int32_t widget_id, + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client) override; private: const int32_t process_id_;
diff --git a/content/browser/renderer_host/offscreen_canvas_provider_impl.cc b/content/browser/renderer_host/offscreen_canvas_provider_impl.cc index ff84fda3..58acfb70 100644 --- a/content/browser/renderer_host/offscreen_canvas_provider_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_provider_impl.cc
@@ -48,8 +48,8 @@ void OffscreenCanvasProviderImpl::CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkClientPtr client, - cc::mojom::MojoCompositorFrameSinkRequest request) { + cc::mojom::CompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkRequest request) { // TODO(kylechar): Kill the renderer too. if (frame_sink_id.client_id() != renderer_client_id_) { DLOG(ERROR) << "Invalid client id " << frame_sink_id;
diff --git a/content/browser/renderer_host/offscreen_canvas_provider_impl.h b/content/browser/renderer_host/offscreen_canvas_provider_impl.h index 00d4afdb..4547a63e 100644 --- a/content/browser/renderer_host/offscreen_canvas_provider_impl.h +++ b/content/browser/renderer_host/offscreen_canvas_provider_impl.h
@@ -21,7 +21,7 @@ class OffscreenCanvasSurfaceImpl; -// Creates OffscreenCanvasSurfaces and MojoCompositorFrameSinks for a renderer. +// Creates OffscreenCanvasSurfaces and CompositorFrameSinks for a renderer. class CONTENT_EXPORT OffscreenCanvasProviderImpl : public blink::mojom::OffscreenCanvasProvider { public: @@ -40,8 +40,8 @@ blink::mojom::OffscreenCanvasSurfaceRequest request) override; void CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkClientPtr client, - cc::mojom::MojoCompositorFrameSinkRequest request) override; + cc::mojom::CompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkRequest request) override; private: friend class OffscreenCanvasProviderImplTest;
diff --git a/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc b/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc index 680a2cb..8e565bc 100644 --- a/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc +++ b/content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc
@@ -11,7 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/output/compositor_frame.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/compositor/test/no_transport_image_transport_factory.h" @@ -65,27 +65,27 @@ DISALLOW_COPY_AND_ASSIGN(StubOffscreenCanvasSurfaceClient); }; -// Stub MojoCompositorFrameSinkClient that does nothing. +// Stub CompositorFrameSinkClient that does nothing. class StubCompositorFrameSinkClient - : public cc::mojom::MojoCompositorFrameSinkClient { + : public cc::mojom::CompositorFrameSinkClient { public: StubCompositorFrameSinkClient() : binding_(this) {} ~StubCompositorFrameSinkClient() override {} - cc::mojom::MojoCompositorFrameSinkClientPtr GetInterfacePtr() { - cc::mojom::MojoCompositorFrameSinkClientPtr client; + cc::mojom::CompositorFrameSinkClientPtr GetInterfacePtr() { + cc::mojom::CompositorFrameSinkClientPtr client; binding_.Bind(mojo::MakeRequest(&client)); return client; } private: - // cc::mojom::MojoCompositorFrameSinkClient: + // cc::mojom::CompositorFrameSinkClient: void DidReceiveCompositorFrameAck( const cc::ReturnedResourceArray& resources) override {} void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_args) override {} void ReclaimResources(const cc::ReturnedResourceArray& resources) override {} - mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> binding_; + mojo::Binding<cc::mojom::CompositorFrameSinkClient> binding_; DISALLOW_COPY_AND_ASSIGN(StubCompositorFrameSinkClient); }; @@ -197,7 +197,7 @@ EXPECT_THAT(GetAllCanvases(), ElementsAre(kFrameSinkA)); // Mimic connection from the renderer main or worker thread to browser. - cc::mojom::MojoCompositorFrameSinkPtr compositor_frame_sink; + cc::mojom::CompositorFrameSinkPtr compositor_frame_sink; StubCompositorFrameSinkClient compositor_frame_sink_client; provider()->CreateCompositorFrameSink( kFrameSinkA, compositor_frame_sink_client.GetInterfacePtr(), @@ -274,13 +274,13 @@ EXPECT_TRUE(connection_error); } -// Check that connecting MojoCompositorFrameSink without first making a +// Check that connecting CompositorFrameSink without first making a // OffscreenCanvasSurface connection fails. TEST_F(OffscreenCanvasProviderImplTest, ClientConnectionWrongOrder) { // Mimic connection from the renderer main or worker thread. - cc::mojom::MojoCompositorFrameSinkPtr compositor_frame_sink; + cc::mojom::CompositorFrameSinkPtr compositor_frame_sink; StubCompositorFrameSinkClient compositor_frame_sink_client; - // Try to connect MojoCompositorFrameSink without first making + // Try to connect CompositorFrameSink without first making // OffscreenCanvasSurface connection. This should fail. provider()->CreateCompositorFrameSink( kFrameSinkA, compositor_frame_sink_client.GetInterfacePtr(),
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc index 94962f3eb..10b6866 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -43,8 +43,8 @@ } void OffscreenCanvasSurfaceImpl::CreateCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClientPtr client, - cc::mojom::MojoCompositorFrameSinkRequest request) { + cc::mojom::CompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkRequest request) { if (has_created_compositor_frame_sink_) { DLOG(ERROR) << "CreateCompositorFrameSink() called more than once."; return;
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.h b/content/browser/renderer_host/offscreen_canvas_surface_impl.h index 65dd8a5..f1d1eb8 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_impl.h +++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.h
@@ -44,13 +44,12 @@ return local_surface_id_; } - // Creates a MojoCompositorFrameSink connection to FrameSinkManager for an + // Creates a CompositorFrameSink connection to FrameSinkManager for an // offscreen canvas client. The corresponding private interface will be owned // here to control CompositorFrameSink lifetime. This should only ever be // called once. - void CreateCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClientPtr client, - cc::mojom::MojoCompositorFrameSinkRequest request); + void CreateCompositorFrameSink(cc::mojom::CompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkRequest request); // FrameSinkObserver implementation. void OnSurfaceCreated(const cc::SurfaceInfo& surface_info) override;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 156f863..2d02a4f 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2562,9 +2562,9 @@ monitor_updates)); } -void RenderWidgetHostImpl::RequestMojoCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { +void RenderWidgetHostImpl::RequestCompositorFrameSink( + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client) { if (compositor_frame_sink_binding_.is_bound()) compositor_frame_sink_binding_.Close(); #if defined(OS_MACOSX)
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index f5baa73..62299ad 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -25,7 +25,7 @@ #include "base/time/time.h" #include "base/timer/elapsed_timer.h" #include "build/build_config.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/resources/shared_bitmap.h" #include "cc/surfaces/frame_sink_id.h" #include "content/browser/renderer_host/event_with_latency_info.h" @@ -103,7 +103,7 @@ public InputAckHandler, public TouchEmulatorClient, public NON_EXPORTED_BASE(SyntheticGestureController::Delegate), - public NON_EXPORTED_BASE(cc::mojom::MojoCompositorFrameSink), + public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink), public IPC::Listener { public: // |routing_id| must not be MSG_ROUTING_NONE. @@ -577,9 +577,9 @@ // renderer unless it is for an immediate request. void RequestCompositionUpdates(bool immediate_request, bool monitor_updates); - void RequestMojoCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client); + void RequestCompositorFrameSink( + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client); const cc::CompositorFrameMetadata& last_frame_metadata() { return last_frame_metadata_; @@ -587,7 +587,7 @@ bool HasGestureStopped() override; - // cc::mojom::MojoCompositorFrameSink implementation. + // cc::mojom::CompositorFrameSink implementation. void SetNeedsBeginFrame(bool needs_begin_frame) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; @@ -979,9 +979,8 @@ cc::LocalSurfaceId last_local_surface_id_; RenderWidgetSurfaceProperties last_surface_properties_; - mojo::Binding<cc::mojom::MojoCompositorFrameSink> - compositor_frame_sink_binding_; - cc::mojom::MojoCompositorFrameSinkClientPtr renderer_compositor_frame_sink_; + mojo::Binding<cc::mojom::CompositorFrameSink> compositor_frame_sink_binding_; + cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_; cc::CompositorFrameMetadata last_frame_metadata_;
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index d043d31..d3a9b51d 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -566,15 +566,15 @@ host_->Init(); host_->DisableGestureDebounce(); - cc::mojom::MojoCompositorFrameSinkPtr sink; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtr sink; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink); - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_); renderer_compositor_frame_sink_ = base::MakeUnique<FakeRendererCompositorFrameSink>( std::move(sink), std::move(client_request)); - host_->RequestMojoCompositorFrameSink( + host_->RequestCompositorFrameSink( std::move(sink_request), std::move(renderer_compositor_frame_sink_ptr_)); } @@ -754,8 +754,7 @@ TestBrowserThreadBundle thread_bundle_; base::test::ScopedFeatureList feature_list_; - cc::mojom::MojoCompositorFrameSinkClientPtr - renderer_compositor_frame_sink_ptr_; + cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostTest); };
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 19a9a84..82872c6 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1174,7 +1174,7 @@ } void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { if (!delegated_frame_host_) { DCHECK(!using_browser_compositor_); // We don't expect RendererCompositorFrameSink on Android WebView.
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index eb6097f..c85662a8 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -146,7 +146,7 @@ bool LockMouse() override; void UnlockMouse() override; void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; @@ -436,7 +436,7 @@ gfx::Point prev_mousedown_point_; int left_click_count_ = 0; - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_ = + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; base::ObserverList<DestructionObserver> destruction_observers_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index a437295..9a4eece 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -887,7 +887,7 @@ #endif void RenderWidgetHostViewAura::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { renderer_compositor_frame_sink_ = renderer_compositor_frame_sink; if (delegated_frame_host_) { delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index b3af31a..e5f15fe9 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -164,7 +164,7 @@ bool LockMouse() override; void UnlockMouse() override; void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; @@ -596,7 +596,7 @@ float device_scale_factor_; - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_ = + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; // While this is a ui::EventHandler for targetting, |event_handler_| actually
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index a026c33..f915f1d6 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -418,10 +418,10 @@ ~FakeRenderWidgetHostViewAura() override {} void CreateNewRendererCompositorFrameSink() { - cc::mojom::MojoCompositorFrameSinkPtr sink; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtr sink; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink); - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&renderer_compositor_frame_sink_ptr_); renderer_compositor_frame_sink_ = base::MakeUnique<FakeRendererCompositorFrameSink>( @@ -496,8 +496,7 @@ private: FakeDelegatedFrameHostClientAura* delegated_frame_host_client_; - cc::mojom::MojoCompositorFrameSinkClientPtr - renderer_compositor_frame_sink_ptr_; + cc::mojom::CompositorFrameSinkClientPtr renderer_compositor_frame_sink_ptr_; DISALLOW_COPY_AND_ASSIGN(FakeRenderWidgetHostViewAura); };
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index c47445c..40162d65 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -18,7 +18,7 @@ #include "base/process/kill.h" #include "base/strings/string16.h" #include "build/build_config.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/output/compositor_frame.h" #include "cc/surfaces/surface_id.h" #include "content/browser/renderer_host/event_with_latency_info.h" @@ -224,8 +224,7 @@ // expected not to return resources belonging to the old // RendererCompositorFrameSink after this method finishes. virtual void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* - renderer_compositor_frame_sink) = 0; + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) = 0; virtual void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) = 0;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 2c0d66ee..9dcacd2 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -307,7 +307,7 @@ void FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) override; void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index d936b5f..ec313b3c 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1413,7 +1413,7 @@ } void RenderWidgetHostViewMac::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { browser_compositor_->DidCreateNewRendererCompositorFrameSink( renderer_compositor_frame_sink); } @@ -3354,8 +3354,8 @@ color_space = base::mac::GetSystemColorSpace(); gfx::ICCProfile icc_profile = gfx::ICCProfile::FromCGColorSpace(color_space); - renderWidgetHostView_->browser_compositor_->SetDisplayColorProfile( - icc_profile); + renderWidgetHostView_->browser_compositor_->SetDisplayColorSpace( + icc_profile.GetColorSpace()); } }
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 84b906e..58b55db 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -711,10 +711,7 @@ results->depth_per_component = display.depth_per_component(); results->is_monochrome = display.is_monochrome(); results->device_scale_factor = display.device_scale_factor(); - results->icc_profile = gfx::ICCProfile::FromBestMonitor(); - if (!results->icc_profile.IsValid()) - gfx::ColorSpace::CreateSRGB().GetICCProfile(&results->icc_profile); - DCHECK(results->icc_profile.IsValid()); + display.color_space().GetICCProfile(&results->icc_profile); // The Display rotation and the ScreenInfo orientation are not the same // angle. The former is the physical display rotation while the later is the
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index ebd0ce3..f046623 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -89,7 +89,7 @@ content::ScreenInfo results; results.device_scale_factor = static_cast<int>(display.device_scale_factor()); - results.icc_profile = display.icc_profile(); + display.color_space().GetICCProfile(&results.icc_profile); results.depth = display.color_depth(); results.depth_per_component = display.depth_per_component(); results.is_monochrome = display.is_monochrome();
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index 1d7e0db..1e4ab807 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -1112,17 +1112,18 @@ response->SetDidServiceWorkerNavigationPreload( info.did_service_worker_navigation_preload); response->SetEncodedDataLength(info.encoded_data_length); + response->SetAlpnNegotiatedProtocol( + WebString::FromUTF8(info.alpn_negotiated_protocol)); + response->SetConnectionInfo(info.connection_info); SetSecurityStyleAndDetails(url, info, response, report_security_info); - WebURLResponseExtraDataImpl* extra_data = - new WebURLResponseExtraDataImpl(info.alpn_negotiated_protocol); + WebURLResponseExtraDataImpl* extra_data = new WebURLResponseExtraDataImpl(); response->SetExtraData(extra_data); extra_data->set_was_fetched_via_spdy(info.was_fetched_via_spdy); extra_data->set_was_alpn_negotiated(info.was_alpn_negotiated); extra_data->set_was_alternate_protocol_available( info.was_alternate_protocol_available); - extra_data->set_connection_info(info.connection_info); extra_data->set_previews_state(info.previews_state); extra_data->set_effective_connection_type(info.effective_connection_type);
diff --git a/content/child/weburlresponse_extradata_impl.cc b/content/child/weburlresponse_extradata_impl.cc index 485a5b5..ebd4d03 100644 --- a/content/child/weburlresponse_extradata_impl.cc +++ b/content/child/weburlresponse_extradata_impl.cc
@@ -6,11 +6,8 @@ namespace content { -WebURLResponseExtraDataImpl::WebURLResponseExtraDataImpl( - const std::string& alpn_negotiated_protocol) - : alpn_negotiated_protocol_(alpn_negotiated_protocol), - is_ftp_directory_listing_(false), - connection_info_(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN), +WebURLResponseExtraDataImpl::WebURLResponseExtraDataImpl() + : is_ftp_directory_listing_(false), effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {} WebURLResponseExtraDataImpl::~WebURLResponseExtraDataImpl() {
diff --git a/content/child/weburlresponse_extradata_impl.h b/content/child/weburlresponse_extradata_impl.h index a87e8748..58b75d1 100644 --- a/content/child/weburlresponse_extradata_impl.h +++ b/content/child/weburlresponse_extradata_impl.h
@@ -20,14 +20,9 @@ class CONTENT_EXPORT WebURLResponseExtraDataImpl : public NON_EXPORTED_BASE(blink::WebURLResponse::ExtraData) { public: - explicit WebURLResponseExtraDataImpl( - const std::string& alpn_negotiated_protocol); + WebURLResponseExtraDataImpl(); ~WebURLResponseExtraDataImpl() override; - const std::string& alpn_negotiated_protocol() const { - return alpn_negotiated_protocol_; - } - /// Flag whether this request was loaded via the SPDY protocol or not. // SPDY is an experimental web protocol, see http://dev.chromium.org/spdy bool was_fetched_via_spdy() const { @@ -37,15 +32,6 @@ was_fetched_via_spdy_ = was_fetched_via_spdy; } - // Information about the type of connection used to fetch this response. - net::HttpResponseInfo::ConnectionInfo connection_info() const { - return connection_info_; - } - void set_connection_info( - net::HttpResponseInfo::ConnectionInfo connection_info) { - connection_info_ = connection_info; - } - // Flag whether this request was loaded after the // TLS/Next-Protocol-Negotiation was used. // This is related to SPDY. @@ -84,11 +70,9 @@ } private: - std::string alpn_negotiated_protocol_; bool is_ftp_directory_listing_; bool was_fetched_via_spdy_; bool was_alpn_negotiated_; - net::HttpResponseInfo::ConnectionInfo connection_info_; bool was_alternate_protocol_available_; PreviewsState previews_state_; net::EffectiveConnectionType effective_connection_type_;
diff --git a/content/common/frame_sink_provider.mojom b/content/common/frame_sink_provider.mojom index 5c2b129..18ac47c5 100644 --- a/content/common/frame_sink_provider.mojom +++ b/content/common/frame_sink_provider.mojom
@@ -1,10 +1,10 @@ module content.mojom; -import "cc/ipc/mojo_compositor_frame_sink.mojom"; +import "cc/ipc/compositor_frame_sink.mojom"; -// This interface provides MojoCompositorFrameSink for the renderer. +// This interface provides CompositorFrameSink for the renderer. interface FrameSinkProvider { CreateForWidget( - int32 widget_id, cc.mojom.MojoCompositorFrameSink& request, - cc.mojom.MojoCompositorFrameSinkClient client); + int32 widget_id, cc.mojom.CompositorFrameSink& request, + cc.mojom.CompositorFrameSinkClient client); };
diff --git a/content/common/message_port.cc b/content/common/message_port.cc index 5e70e7e..5457d05 100644 --- a/content/common/message_port.cc +++ b/content/common/message_port.cc
@@ -11,14 +11,11 @@ namespace content { -MessagePort::~MessagePort() { -} +MessagePort::~MessagePort() {} -MessagePort::MessagePort() : state_(new State()) { -} +MessagePort::MessagePort() : state_(new State()) {} -MessagePort::MessagePort(const MessagePort& other) : state_(other.state_) { -} +MessagePort::MessagePort(const MessagePort& other) : state_(other.state_) {} MessagePort& MessagePort::operator=(const MessagePort& other) { state_ = other.state_; @@ -26,8 +23,7 @@ } MessagePort::MessagePort(mojo::ScopedMessagePipeHandle handle) - : state_(new State(std::move(handle))) { -} + : state_(new State(std::move(handle))) {} const mojo::ScopedMessagePipeHandle& MessagePort::GetHandle() const { return state_->handle(); @@ -121,12 +117,10 @@ state_->StopWatching(); } -MessagePort::State::State() { -} +MessagePort::State::State() {} MessagePort::State::State(mojo::ScopedMessagePipeHandle handle) - : handle_(std::move(handle)) { -} + : handle_(std::move(handle)) {} void MessagePort::State::StartWatching(const base::Closure& callback) { base::AutoLock lock(lock_); @@ -143,9 +137,9 @@ // NOTE: An HTML MessagePort does not receive an event to tell it when the // peer has gone away, so we only watch for readability here. - rv = - MojoWatch(watcher_handle_.get().value(), handle_.get().value(), - MOJO_HANDLE_SIGNAL_READABLE, reinterpret_cast<uintptr_t>(this)); + rv = MojoWatch(watcher_handle_.get().value(), handle_.get().value(), + MOJO_HANDLE_SIGNAL_READABLE, MOJO_WATCH_CONDITION_SATISFIED, + reinterpret_cast<uintptr_t>(this)); DCHECK_EQ(MOJO_RESULT_OK, rv); ArmWatcher();
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java index aab86ba..aeb5cb4 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
@@ -365,14 +365,22 @@ @Override public void onChildProcessDied(ChildProcessConnection connection) { assert LauncherThread.runningOnLauncherThread(); - if (connection.getPid() != 0) { - stop(connection.getPid()); - } + // Forward the call to the provided callback if any. The spare connection // uses that for clean-up. if (deathCallback != null) { deathCallback.onChildProcessDied(connection); } + // TODO(jcivelli): make SparedChildConnection use an allocator instead of + // calling this method, so it does not have to be static and we can retrieve + // the launcher directly. + int pid = connection.getPid(); + if (pid != 0) { + // If the PID has not been set the connection has not been connected yet + // and we don't need to notify the process stopped. + ChildProcessLauncherHelper launcher = getLauncherForPid(pid); + launcher.onChildProcessStopped(); + } } }; @@ -513,7 +521,7 @@ mConnection.setupConnection(connectionBundle, getIBinderCallback(), connectionCallback); } - public void onChildProcessStarted() { + private void onChildProcessStarted() { assert LauncherThread.runningOnLauncherThread(); int pid = mConnection.getPid(); @@ -540,6 +548,12 @@ mNativeChildProcessLauncherHelper = 0; } + private void onChildProcessStopped() { + assert LauncherThread.runningOnLauncherThread(); + onConnectionLost(mConnection, getPid()); + sLauncherByPid.remove(getPid()); + } + public int getPid() { assert LauncherThread.runningOnLauncherThread(); return mConnection == null ? NULL_PROCESS_HANDLE : mConnection.getPid(); @@ -571,13 +585,11 @@ static void stop(int pid) { assert LauncherThread.runningOnLauncherThread(); Log.d(TAG, "stopping child connection: pid=%d", pid); - ChildProcessLauncherHelper launcher = sLauncherByPid.remove(pid); - if (launcher == null) { - // Can happen for single process. - return; + ChildProcessLauncherHelper launcher = sLauncherByPid.get(pid); + // Launcher can be null for single process. + if (launcher != null) { + launcher.mConnection.stop(); } - launcher.onConnectionLost(launcher.mConnection, pid); - launcher.mConnection.stop(); } @CalledByNative
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java index 5698e61..a82a6a4 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
@@ -129,7 +129,8 @@ null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */); Assert.assertEquals(1, getConnectedSandboxedServicesCount()); - Assert.assertNotEquals(0, getPid(launcher)); + int pid = getPid(launcher); + Assert.assertNotEquals(0, pid); // Crash the service. ChildProcessConnection connection = retrieveConnection(launcher); @@ -140,6 +141,8 @@ // Verify that the connection pid remains set after termination. Assert.assertTrue(ChildProcessLauncherTestUtils.getConnectionPid(connection) != 0); + // And that the launcher is cleared. + Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid)); } /** @@ -349,9 +352,13 @@ // The warm-up connection was used, so no new process should have been created. Assert.assertEquals(1, getConnectedSandboxedServicesCount()); + int pid = getPid(launcherHelper); + Assert.assertNotEquals(0, pid); + stopProcess(launcherHelper); waitForConnectedSandboxedServicesCount(0); + Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid)); } @Test @@ -377,7 +384,7 @@ @Test @MediumTest @Feature({"ProcessManagement"}) - public void testWarmUpProcessCrash() throws RemoteException { + public void testWarmUpProcessCrashBeforeUse() throws RemoteException { Assert.assertEquals(0, getConnectedSandboxedServicesCount()); Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); @@ -400,6 +407,32 @@ Assert.assertNotNull(ChildProcessLauncherTestUtils.getConnection(launcher)); } + // Tests that the warm-up connection is freed from its allocator if it crashes after being used. + @Test + @MediumTest + @Feature({"ProcessManagement"}) + public void testWarmUpProcessCrashAfterUse() throws RemoteException { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + warmUpOnUiThreadBlocking(context); + + Assert.assertEquals(1, getConnectedSandboxedServicesCount()); + + ChildProcessLauncherHelper launcherHelper = startSandboxedChildProcessWithCreationParams( + null /* creationParams */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */); + + // The warm-up connection was used, so no new process should have been created. + Assert.assertEquals(1, getConnectedSandboxedServicesCount()); + + int pid = getPid(launcherHelper); + Assert.assertNotEquals(0, pid); + + ChildProcessConnection connection = retrieveConnection(launcherHelper); + connection.crashServiceForTesting(); + + waitForConnectedSandboxedServicesCount(0); + Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid)); + } + @Test @MediumTest @Feature({"ProcessManagement"})
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 0326e861..aa398ecb 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -58,7 +58,7 @@ "requires": { "*": [ "app" ], // In classic ash, the browser supplies ash interfaces to itself. - "content_browser": [ "ash", "display", "memory_instrumentation" ], + "content_browser": [ "ash", "display", "memory_instrumentation", "url_keyed_metrics" ], "content_gpu": [ "browser" ], "content_plugin": [ "browser" ], "content_renderer": [ "browser" ], @@ -83,9 +83,8 @@ "barcode_detection", "face_detection", "text_detection" - ], - "resource_coordinator": [ "coordination_unit" ], + "resource_coordinator": [ "coordination_unit", "service_callbacks" ], "video_capture": [ "capture", "tests" ] } },
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc index 5955dae..4bf1c74 100644 --- a/content/renderer/mus/renderer_window_tree_client.cc +++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -77,11 +77,11 @@ scoped_refptr<cc::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const LayerTreeFrameSinkCallback& callback) { - cc::mojom::MojoCompositorFrameSinkPtrInfo sink_info; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtrInfo sink_info; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink_info); - cc::mojom::MojoCompositorFrameSinkClientPtr client; - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientPtr client; + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&client); constexpr bool enable_surface_synchronization = true; auto frame_sink = base::MakeUnique<viz::ClientLayerTreeFrameSink>(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index ed778ed9..d8b13a9 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4441,11 +4441,10 @@ extra_data->was_fetched_via_spdy()); document_state->set_was_alpn_negotiated(extra_data->was_alpn_negotiated()); document_state->set_alpn_negotiated_protocol( - extra_data->alpn_negotiated_protocol()); + response.AlpnNegotiatedProtocol().Utf8()); document_state->set_was_alternate_protocol_available( extra_data->was_alternate_protocol_available()); - document_state->set_connection_info( - extra_data->connection_info()); + document_state->set_connection_info(response.ConnectionInfo()); } InternalDocumentStateData* internal_data = InternalDocumentStateData::FromDocumentState(document_state);
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index f8e4685a..1cae4a69 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1956,11 +1956,11 @@ } #endif - cc::mojom::MojoCompositorFrameSinkPtrInfo sink_info; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtrInfo sink_info; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink_info); - cc::mojom::MojoCompositorFrameSinkClientPtr client; - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientPtr client; + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&client); if (command_line.HasSwitch(switches::kEnableVulkan)) {
diff --git a/content/test/fake_renderer_compositor_frame_sink.cc b/content/test/fake_renderer_compositor_frame_sink.cc index 1fa897a..9ae044e 100644 --- a/content/test/fake_renderer_compositor_frame_sink.cc +++ b/content/test/fake_renderer_compositor_frame_sink.cc
@@ -7,8 +7,8 @@ namespace content { FakeRendererCompositorFrameSink::FakeRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkPtr sink, - cc::mojom::MojoCompositorFrameSinkClientRequest request) + cc::mojom::CompositorFrameSinkPtr sink, + cc::mojom::CompositorFrameSinkClientRequest request) : binding_(this, std::move(request)), sink_(std::move(sink)) {} FakeRendererCompositorFrameSink::~FakeRendererCompositorFrameSink() = default;
diff --git a/content/test/fake_renderer_compositor_frame_sink.h b/content/test/fake_renderer_compositor_frame_sink.h index 5bcdfa3..0f16c881 100644 --- a/content/test/fake_renderer_compositor_frame_sink.h +++ b/content/test/fake_renderer_compositor_frame_sink.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_TEST_FAKE_RENDERER_COMPOSITOR_FRAME_SINK_H_ #define CONTENT_TEST_FAKE_RENDERER_COMPOSITOR_FRAME_SINK_H_ -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "mojo/public/cpp/bindings/binding.h" namespace content { @@ -13,11 +13,11 @@ // This class is given to RenderWidgetHost/RenderWidgetHostView unit tests // instead of RendererCompositorFrameSink. class FakeRendererCompositorFrameSink - : public cc::mojom::MojoCompositorFrameSinkClient { + : public cc::mojom::CompositorFrameSinkClient { public: FakeRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkPtr sink, - cc::mojom::MojoCompositorFrameSinkClientRequest request); + cc::mojom::CompositorFrameSinkPtr sink, + cc::mojom::CompositorFrameSinkClientRequest request); ~FakeRendererCompositorFrameSink() override; bool did_receive_ack() { return did_receive_ack_; } @@ -25,7 +25,7 @@ return last_reclaimed_resources_; } - // cc::mojom::MojoCompositorFrameSinkClient implementation. + // cc::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const cc::ReturnedResourceArray& resources) override; void OnBeginFrame(const cc::BeginFrameArgs& args) override {} @@ -38,8 +38,8 @@ void Flush(); private: - mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> binding_; - cc::mojom::MojoCompositorFrameSinkPtr sink_; + mojo::Binding<cc::mojom::CompositorFrameSinkClient> binding_; + cc::mojom::CompositorFrameSinkPtr sink_; bool did_receive_ack_ = false; cc::ReturnedResourceArray last_reclaimed_resources_;
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 8076686..01cf24a 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -41,14 +41,10 @@ self.Skip('deqp/functional/gles3/builtinprecision/*.html', bug=619403) # All platforms. - - # Remove the following when the test update is rolled into Chromium: - # https://github.com/KhronosGroup/WebGL/pull/2424/files - self.Fail('conformance2/rendering/instanced-arrays.html', bug=736070) - self.Fail('deqp/functional/gles3/negativevertexarrayapi.html', bug=736070) - # When remove the above entry, please uncomment the one for Mac NVidia. - self.Flaky('conformance2/query/occlusion-query.html', bug=603168) + # TODO(kbr): remove following suppression during next WebGL conformance + # roll. + self.Fail('conformance2/extensions/ext-color-buffer-float.html', bug=736499) self.Fail('conformance2/glsl3/tricky-loop-conditions.html', bug=483282) self.Fail('conformance2/rendering/depth-stencil-feedback-loop.html', @@ -354,6 +350,9 @@ ['win', 'passthrough', 'd3d11'], bug=602688) # Mac only. + self.Fail('conformance2/renderbuffers/' + + 'multisampled-depth-renderbuffer-initialization.html', + ['mac'], bug=696126) # Regressions in 10.12.4. self.Fail('conformance2/textures/misc/tex-base-level-bug.html', @@ -423,8 +422,8 @@ self.Fail('deqp/functional/gles3/pixelbufferobject.html', ['mac', ('nvidia', 0xfe9)], bug=483282) - #self.Fail('deqp/functional/gles3/negativevertexarrayapi.html', - # ['mac', ('nvidia', 0xfe9)], bug=483282) + self.Fail('deqp/functional/gles3/negativevertexarrayapi.html', + ['mac', ('nvidia', 0xfe9)], bug=483282) self.Fail('deqp/functional/gles3/shaderindexing/varying.html', ['mac', ('nvidia', 0xfe9)], bug=483282) self.Fail('deqp/functional/gles3/texturespecification/' + @@ -753,8 +752,9 @@ ['linux', ('nvidia', 0x1cb3)], bug=709320) # Linux Intel - self.Fail('conformance2/extensions/ext-color-buffer-float.html', - ['linux', 'intel'], bug=640389) + # TODO(kbr): re-enable after next conformance roll. crbug.com/736499 + # self.Fail('conformance2/extensions/ext-color-buffer-float.html', + # ['linux', 'intel'], bug=640389) self.Fail('WebglExtension_EXT_disjoint_timer_query_webgl2', ['linux', 'intel'], bug=687210) @@ -1034,8 +1034,9 @@ ['linux', 'amd', 'no_angle'], bug=483282) self.Fail('conformance2/textures/misc/tex-unpack-params.html', ['linux', 'amd', 'no_angle'], bug=483282) - self.Fail('conformance2/extensions/ext-color-buffer-float.html', - ['linux', 'amd'], bug=633022) + # TODO(kbr): re-enable after next conformance roll. crbug.com/736499 + # self.Fail('conformance2/extensions/ext-color-buffer-float.html', + # ['linux', 'amd'], bug=633022) self.Fail('conformance2/rendering/blitframebuffer-filter-outofbounds.html', ['linux', 'amd'], bug=655147)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt index 715d537..4b8e5fd 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 331fe3a462b2e1f5c9baa1a710312a1b5888e404 +Current webgl revision 9ffa3b5a09e9d86be4ec4cdf6c151a503fa1c0e0
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index 527fac2..de720ae 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -198,7 +198,7 @@ } void TestRenderWidgetHostView::DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) { did_change_compositor_frame_sink_ = true; }
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index b923434..e562bb1 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -93,7 +93,7 @@ void StopSpeaking() override; #endif // defined(OS_MACOSX) void DidCreateNewRendererCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + cc::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) override; void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override;
diff --git a/docs/design/threading.md b/docs/design/threading.md index 105891c..244e536 100644 --- a/docs/design/threading.md +++ b/docs/design/threading.md
@@ -19,7 +19,7 @@ to keep track of. Each thread has a `MessageLoop` (see [`base/message_loop/message_loop.h`](https://cs.chromium.org/chromium/src/base/message_loop/message_loop.h) that processes messages for that thread. You can get the message loop for a -thread using the `Thread.message_loop()` function. More details about +thread using the `Thread.message_loop()` function. More details about `MessageLoop` can be found in [Anatomy of Chromium MessageLoop](https://docs.google.com/document/d/1_pJUHO3f3VyRSQjEhKVvUU7NzCyuTCQshZvbWeQiCXU/view#). @@ -242,15 +242,30 @@ public: void DoSomething() { scoped_refptr<SomeParamObject> param(new SomeParamObject); - thread_->message_loop()->PostTask(FROM_HERE - base::Bind(&MyObject::DoSomethingOnAnotherThread, this, param)); + + // Without RetainedRef, the scoped_refptr would try to implicitly + // convert to a raw pointer and fail compilation. + thread_->message_loop()->PostTask(FROM_HERE, + base::Bind(&MyObject::DoSomethingOnAnotherThread, this, + base::RetainedRef(param))); } + void DoSomething2() { SomeParamObject* param = new SomeParamObject; - thread_->message_loop()->PostTask(FROM_HERE + thread_->message_loop()->PostTask(FROM_HERE, base::Bind(&MyObject::DoSomethingOnAnotherThread, this, - make_scoped_refptr(param))); + base::RetainedRef(make_scoped_refptr(param)))); } + + void DoSomething3() { + scoped_refptr<SomeParamObject> param(new SomeParamObject); + + // Moving |param| prevents an extra AddRef()/Release() pair. + thread_->message_loop()->PostTask(FROM_HERE, + base::Bind(&MyObject::DoSomethingOnAnotherThread, this, + base::RetainedRef(std::move(param)))); + } + // Note how this takes a raw pointer. The important part is that // base::Bind() was passed a scoped_refptr; using a scoped_refptr // here would result in an extra AddRef()/Release() pair.
diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc index f2290795..c74fbf93 100644 --- a/google_apis/gaia/fake_gaia.cc +++ b/google_apis/gaia/fake_gaia.cc
@@ -245,10 +245,7 @@ gaia_urls->service_login_url(), HandleServiceLogin); // Handles /embedded/setup/chromeos GAIA call. - REGISTER_RESPONSE_HANDLER(gaia_urls->embedded_setup_chromeos_url(1), - HandleEmbeddedSetupChromeos); - // Handles /embedded/setup/v2/chromeos GAIA call. - REGISTER_RESPONSE_HANDLER(gaia_urls->embedded_setup_chromeos_url(2), + REGISTER_RESPONSE_HANDLER(gaia_urls->embedded_setup_chromeos_url(), HandleEmbeddedSetupChromeos); // Handles /OAuthLogin GAIA call.
diff --git a/google_apis/gaia/gaia_urls.cc b/google_apis/gaia/gaia_urls.cc index e314a10..bff2ab3 100644 --- a/google_apis/gaia/gaia_urls.cc +++ b/google_apis/gaia/gaia_urls.cc
@@ -20,8 +20,7 @@ // API calls from accounts.google.com const char kClientLoginUrlSuffix[] = "ClientLogin"; const char kServiceLoginUrlSuffix[] = "ServiceLogin"; -const char kEmbeddedSetupChromeOsUrlSuffixV1[] = "embedded/setup/chromeos"; -const char kEmbeddedSetupChromeOsUrlSuffixV2[] = "embedded/setup/v2/chromeos"; +const char kEmbeddedSetupChromeOsUrlSuffix[] = "embedded/setup/chromeos"; const char kServiceLoginAuthUrlSuffix[] = "ServiceLoginAuth"; const char kServiceLogoutUrlSuffix[] = "Logout"; const char kIssueAuthTokenUrlSuffix[] = "IssueAuthToken"; @@ -98,10 +97,8 @@ // URLs from accounts.google.com. client_login_url_ = gaia_url_.Resolve(kClientLoginUrlSuffix); service_login_url_ = gaia_url_.Resolve(kServiceLoginUrlSuffix); - embedded_setup_chromeos_url_v1_ = - gaia_url_.Resolve(kEmbeddedSetupChromeOsUrlSuffixV1); - embedded_setup_chromeos_url_v2_ = - gaia_url_.Resolve(kEmbeddedSetupChromeOsUrlSuffixV2); + embedded_setup_chromeos_url_ = + gaia_url_.Resolve(kEmbeddedSetupChromeOsUrlSuffix); service_login_auth_url_ = gaia_url_.Resolve(kServiceLoginAuthUrlSuffix); service_logout_url_ = gaia_url_.Resolve(kServiceLogoutUrlSuffix); issue_auth_token_url_ = gaia_url_.Resolve(kIssueAuthTokenUrlSuffix); @@ -163,13 +160,8 @@ return service_login_url_; } -const GURL& GaiaUrls::embedded_setup_chromeos_url(unsigned version) const { - DCHECK_GT(version, 0U); - DCHECK_LE(version, 2U); - if (version == 2U) - return embedded_setup_chromeos_url_v2_; - - return embedded_setup_chromeos_url_v1_; +const GURL& GaiaUrls::embedded_setup_chromeos_url() const { + return embedded_setup_chromeos_url_; }
diff --git a/google_apis/gaia/gaia_urls.h b/google_apis/gaia/gaia_urls.h index b4951d4..6268163 100644 --- a/google_apis/gaia/gaia_urls.h +++ b/google_apis/gaia/gaia_urls.h
@@ -22,7 +22,7 @@ const GURL& captcha_base_url() const; const GURL& client_login_url() const; const GURL& service_login_url() const; - const GURL& embedded_setup_chromeos_url(unsigned version) const; + const GURL& embedded_setup_chromeos_url() const; const GURL& service_login_auth_url() const; const GURL& service_logout_url() const; const GURL& issue_auth_token_url() const; @@ -72,8 +72,7 @@ GURL client_login_url_; GURL service_login_url_; - GURL embedded_setup_chromeos_url_v1_; - GURL embedded_setup_chromeos_url_v2_; + GURL embedded_setup_chromeos_url_; GURL service_login_auth_url_; GURL service_logout_url_; GURL issue_auth_token_url_;
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 005a523..b256a8f6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -3768,12 +3768,7 @@ } error::Error GLES2DecoderPassthroughImpl::DoFlushDriverCachesCHROMIUM() { - // On Adreno Android devices we need to use a workaround to force caches to - // clear. - if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) { - context_->ReleaseCurrent(nullptr); - context_->MakeCurrent(surface_.get()); - } + NOTIMPLEMENTED(); return error::kNoError; }
diff --git a/headless/lib/browser/headless_window_tree_host.cc b/headless/lib/browser/headless_window_tree_host.cc index 6b59e30..7936cd6 100644 --- a/headless/lib/browser/headless_window_tree_host.cc +++ b/headless/lib/browser/headless_window_tree_host.cc
@@ -79,8 +79,4 @@ void HeadlessWindowTreeHost::OnCursorVisibilityChangedNative(bool show) {} -gfx::ICCProfile HeadlessWindowTreeHost::GetICCProfileForCurrentDisplay() { - return gfx::ICCProfile(); -} - } // namespace headless
diff --git a/headless/lib/browser/headless_window_tree_host.h b/headless/lib/browser/headless_window_tree_host.h index 097435a..b813b145 100644 --- a/headless/lib/browser/headless_window_tree_host.h +++ b/headless/lib/browser/headless_window_tree_host.h
@@ -48,7 +48,6 @@ void SetCursorNative(gfx::NativeCursor cursor_type) override; void MoveCursorToScreenLocationInPixels(const gfx::Point& location) override; void OnCursorVisibilityChangedNative(bool show) override; - gfx::ICCProfile GetICCProfileForCurrentDisplay() override; private: gfx::Rect bounds_;
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm index d8513197..0ae98530 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -387,11 +387,13 @@ GREYFail(error); }; + chrome_test_util::CloseAllTabsInCurrentMode(); GURL URL = web::test::HttpServer::MakeUrl(kTestUrl1); NewMainTabWithURL(URL, kURL1FirstWord); OpenNewIncognitoTabUsingUIAndEvictMainTabs(); SwitchToNormalMode(); [ChromeEarlGrey waitForWebViewContainingText:kURL1FirstWord]; + chrome_test_util::AssertMainTabCount(1); histogramTester.ExpectUniqueSample(kEvictedTabReloadSuccessRate, TabUsageRecorder::LOAD_SUCCESS, 1,
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index fd4b13b1..61ee232 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1200,6 +1200,10 @@ // Remove the web view now. Otherwise, delegate callbacks occur. [self removeWebViewAllowingCachedReconstruction:NO]; + // Explicitly reset content to clean up views and avoid dangling KVO + // observers. + [_containerView resetContent]; + _webStateImpl = nullptr; DCHECK(!_webView);
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 53b635b..d7cada6d 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -270,7 +270,7 @@ // Enter/exit fullscreen when device is rotated to/from the video orientation. const base::Feature kVideoRotateToFullscreen{"VideoRotateToFullscreen", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // An experimental feature to enable persistent-license type support in MediaDrm // when using Encrypted Media Extensions (EME) API.
diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc index 96048028..43c4c22 100644 --- a/mojo/edk/embedder/entrypoints.cc +++ b/mojo/edk/embedder/entrypoints.cc
@@ -50,8 +50,9 @@ MojoResult MojoWatchImpl(MojoHandle watcher_handle, MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context) { - return g_core->Watch(watcher_handle, handle, signals, context); + return g_core->Watch(watcher_handle, handle, signals, condition, context); } MojoResult MojoCancelWatchImpl(MojoHandle watcher_handle, uintptr_t context) {
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index 6b837022..07c076db 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc
@@ -429,6 +429,7 @@ MojoResult Core::Watch(MojoHandle watcher_handle, MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context) { RequestContext request_context; scoped_refptr<Dispatcher> watcher = GetDispatcher(watcher_handle); @@ -437,7 +438,7 @@ scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; - return watcher->WatchDispatcher(dispatcher, signals, context); + return watcher->WatchDispatcher(dispatcher, signals, condition, context); } MojoResult Core::CancelWatch(MojoHandle watcher_handle, uintptr_t context) {
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 7c8c0a14..43b2253b 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h
@@ -183,6 +183,7 @@ MojoResult Watch(MojoHandle watcher_handle, MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context); MojoResult CancelWatch(MojoHandle watcher_handle, uintptr_t context); MojoResult ArmWatcher(MojoHandle watcher_handle,
diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc index 027c518..2855cd96 100644 --- a/mojo/edk/system/dispatcher.cc +++ b/mojo/edk/system/dispatcher.cc
@@ -25,6 +25,7 @@ MojoResult Dispatcher::WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context) { return MOJO_RESULT_INVALID_ARGUMENT; } @@ -146,7 +147,9 @@ return true; } -bool Dispatcher::BeginTransit() { return true; } +bool Dispatcher::BeginTransit() { + return true; +} void Dispatcher::CompleteTransitAndClose() {} @@ -163,13 +166,13 @@ size_t num_platform_handles) { switch (type) { case Type::MESSAGE_PIPE: - return MessagePipeDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); + return MessagePipeDispatcher::Deserialize(bytes, num_bytes, ports, + num_ports, platform_handles, + num_platform_handles); case Type::SHARED_BUFFER: - return SharedBufferDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); + return SharedBufferDispatcher::Deserialize(bytes, num_bytes, ports, + num_ports, platform_handles, + num_platform_handles); case Type::DATA_PIPE_CONSUMER: return DataPipeConsumerDispatcher::Deserialize( bytes, num_bytes, ports, num_ports, platform_handles, @@ -179,9 +182,9 @@ bytes, num_bytes, ports, num_ports, platform_handles, num_platform_handles); case Type::PLATFORM_HANDLE: - return PlatformHandleDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); + return PlatformHandleDispatcher::Deserialize(bytes, num_bytes, ports, + num_ports, platform_handles, + num_platform_handles); default: LOG(ERROR) << "Deserializing invalid dispatcher type."; return nullptr;
diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h index 60eff86..e99b8cf 100644 --- a/mojo/edk/system/dispatcher.h +++ b/mojo/edk/system/dispatcher.h
@@ -72,6 +72,7 @@ virtual MojoResult WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context); virtual MojoResult CancelWatch(uintptr_t context); virtual MojoResult Arm(uint32_t* num_ready_contexts, @@ -215,14 +216,13 @@ virtual void CancelTransit(); // Deserializes a specific dispatcher type from an incoming message. - static scoped_refptr<Dispatcher> Deserialize( - Type type, - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* platform_handles, - size_t num_platform_handles); + static scoped_refptr<Dispatcher> Deserialize(Type type, + const void* bytes, + size_t num_bytes, + const ports::PortName* ports, + size_t num_ports, + PlatformHandle* platform_handles, + size_t num_platform_handles); protected: friend class base::RefCountedThreadSafe<Dispatcher>;
diff --git a/mojo/edk/system/signals_unittest.cc b/mojo/edk/system/signals_unittest.cc index 021aa10..4c43379 100644 --- a/mojo/edk/system/signals_unittest.cc +++ b/mojo/edk/system/signals_unittest.cc
@@ -130,20 +130,24 @@ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_NOT_SATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_NOT_SATISFIED)); RunTestClient("RemotePeersClient", [&](MojoHandle h) { // The bootstrap pipe should eventually signal remoteness. - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE)); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_SATISFIED)); // And so should |a| after we send its peer. WriteMessageWithHandles(h, ":)", &b, 1); - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE)); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_SATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); @@ -151,8 +155,8 @@ MojoHandle c, d; CreateMessagePipe(&c, &d); EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(d, a)); - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(c, MOJO_HANDLE_SIGNAL_PEER_REMOTE)); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_SATISFIED)); EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(c, &state)); EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); @@ -164,30 +168,27 @@ // Read |b| back before joining the client. EXPECT_EQ("O_O", ReadMessageWithHandles(h, &b, 1)); + + // Wait for |a| to see its peer as local again. + EXPECT_EQ(MOJO_RESULT_OK, + WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_NOT_SATISFIED)); + EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); + EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); }); - - // We have no way to wait for signals to go low, but because the above code - // blocks until the child process cleanly terminated, it is effectively - // guaranteed in practice that |a| and |b| must both see their peers as local - // again by this point. - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); - EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); - EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); - - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); - EXPECT_TRUE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); - EXPECT_FALSE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_REMOTE); } DEFINE_TEST_CLIENT_TEST_WITH_PIPE(RemotePeersClient, SignalsTest, h) { // The bootstrap pipe should eventually signal remoteness. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE)); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_SATISFIED)); MojoHandle b; EXPECT_EQ(":)", ReadMessageWithHandles(h, &b, 1)); // And so should |b|. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE)); + EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_REMOTE, + MOJO_WATCH_CONDITION_SATISFIED)); // Wait for the test to signal that it's ready to read |b| back. EXPECT_EQ("OK!", ReadMessage(h));
diff --git a/mojo/edk/system/watch.cc b/mojo/edk/system/watch.cc index cf08ac3..faeae0ae 100644 --- a/mojo/edk/system/watch.cc +++ b/mojo/edk/system/watch.cc
@@ -13,11 +13,13 @@ Watch::Watch(const scoped_refptr<WatcherDispatcher>& watcher, const scoped_refptr<Dispatcher>& dispatcher, uintptr_t context, - MojoHandleSignals signals) + MojoHandleSignals signals, + MojoWatchCondition condition) : watcher_(watcher), dispatcher_(dispatcher), context_(context), - signals_(signals) {} + signals_(signals), + condition_(condition) {} bool Watch::NotifyState(const HandleSignalsState& state, bool allowed_to_call_callback) { @@ -28,12 +30,18 @@ MojoResult rv = MOJO_RESULT_SHOULD_WAIT; RequestContext* const request_context = RequestContext::current(); - if (state.satisfies(signals_)) { + const bool notify_success = + (state.satisfies_any(signals_) && + condition_ == MOJO_WATCH_CONDITION_SATISFIED) || + (!state.satisfies_all(signals_) && + condition_ == MOJO_WATCH_CONDITION_NOT_SATISFIED); + if (notify_success) { rv = MOJO_RESULT_OK; if (allowed_to_call_callback && rv != last_known_result_) { request_context->AddWatchNotifyFinalizer(this, MOJO_RESULT_OK, state); } - } else if (!state.can_satisfy(signals_)) { + } else if (condition_ == MOJO_WATCH_CONDITION_SATISFIED && + !state.can_satisfy_any(signals_)) { rv = MOJO_RESULT_FAILED_PRECONDITION; if (allowed_to_call_callback && rv != last_known_result_) { request_context->AddWatchNotifyFinalizer(
diff --git a/mojo/edk/system/watch.h b/mojo/edk/system/watch.h index f277de9..e706e91 100644 --- a/mojo/edk/system/watch.h +++ b/mojo/edk/system/watch.h
@@ -30,7 +30,8 @@ Watch(const scoped_refptr<WatcherDispatcher>& watcher, const scoped_refptr<Dispatcher>& dispatcher, uintptr_t context, - MojoHandleSignals signals); + MojoHandleSignals signals, + MojoWatchCondition condition); // Notifies the Watch of a potential state change. // @@ -95,6 +96,7 @@ const scoped_refptr<Dispatcher> dispatcher_; const uintptr_t context_; const MojoHandleSignals signals_; + const MojoWatchCondition condition_; // The result code with which this Watch would notify if currently armed, // based on the last known signaling state of |dispatcher_|. Guarded by the
diff --git a/mojo/edk/system/watcher_dispatcher.cc b/mojo/edk/system/watcher_dispatcher.cc index 409dd2a9..4f7e982 100644 --- a/mojo/edk/system/watcher_dispatcher.cc +++ b/mojo/edk/system/watcher_dispatcher.cc
@@ -26,7 +26,7 @@ return; // Maybe fire a notification to the watch assoicated with this dispatcher, - // provided we're armed it cares about the new state. + // provided we're armed and it cares about the new state. if (it->second->NotifyState(state, armed_)) { ready_watches_.insert(it->second.get()); @@ -112,6 +112,7 @@ MojoResult WatcherDispatcher::WatchDispatcher( scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context) { // NOTE: Because it's critical to avoid acquiring any other dispatcher locks // while |lock_| is held, we defer adding oursevles to the dispatcher until @@ -121,7 +122,8 @@ if (watches_.count(context) || watched_handles_.count(dispatcher.get())) return MOJO_RESULT_ALREADY_EXISTS; - scoped_refptr<Watch> watch = new Watch(this, dispatcher, context, signals); + scoped_refptr<Watch> watch = + new Watch(this, dispatcher, context, signals, condition); watches_.insert({context, watch}); auto result = watched_handles_.insert(std::make_pair(dispatcher.get(), watch));
diff --git a/mojo/edk/system/watcher_dispatcher.h b/mojo/edk/system/watcher_dispatcher.h index 605a315..0c5f2552 100644 --- a/mojo/edk/system/watcher_dispatcher.h +++ b/mojo/edk/system/watcher_dispatcher.h
@@ -45,6 +45,7 @@ MojoResult Close() override; MojoResult WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context) override; MojoResult CancelWatch(uintptr_t context) override; MojoResult Arm(uint32_t* num_ready_contexts,
diff --git a/mojo/edk/system/watcher_unittest.cc b/mojo/edk/system/watcher_unittest.cc index dd396cd..9987e483 100644 --- a/mojo/edk/system/watcher_unittest.cc +++ b/mojo/edk/system/watcher_unittest.cc
@@ -130,10 +130,12 @@ // Try to watch unwatchable handles. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWatch(w, w, MOJO_HANDLE_SIGNAL_READABLE, 0)); + MojoWatch(w, w, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, 0)); MojoHandle buffer_handle = CreateBuffer(42); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWatch(w, buffer_handle, MOJO_HANDLE_SIGNAL_READABLE, 0)); + MojoWatch(w, buffer_handle, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, 0)); // Try to cancel a watch on an invalid watcher handle. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(buffer_handle, 0)); @@ -186,7 +188,8 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -243,7 +246,8 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); // Test that closing a watched handle fires an appropriate notification, even // when the watcher is unarmed. @@ -272,7 +276,8 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); // Test that closing a watched handle's peer with an armed watcher fires an // appropriate notification. @@ -325,6 +330,7 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_consumer_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -391,7 +397,7 @@ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - new_data_context)); + MOJO_WATCH_CONDITION_SATISFIED, new_data_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -478,6 +484,7 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, writable_producer_context)); // The producer is already writable, so arming should fail with relevant @@ -548,6 +555,7 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_consumer_context)); // Closing the consumer should fire a cancellation notification. @@ -577,6 +585,7 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_consumer_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -619,6 +628,7 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, writable_producer_context)); // Closing the consumer should fire a cancellation notification. @@ -655,6 +665,7 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, writable_producer_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -698,9 +709,11 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, 0)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, 0)); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, 0)); + MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, 0)); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); @@ -719,7 +732,8 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, 0)); // |a| is always writable, so we can never arm this watcher. constexpr size_t kMaxReadyContexts = 10; @@ -745,7 +759,8 @@ MojoHandle w; EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, 0)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, 0)); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); @@ -799,9 +814,11 @@ // Add two independent watch contexts to watch for |a| or |b| readability. EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, readable_b_context)); + MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_b_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -872,7 +889,8 @@ CreateMessagePipe(&c, &d); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, c, MOJO_HANDLE_SIGNAL_WRITABLE, writable_c_context)); + MojoWatch(w, c, MOJO_HANDLE_SIGNAL_WRITABLE, + MOJO_WATCH_CONDITION_SATISFIED, writable_c_context)); num_ready_contexts = kMaxReadyContexts; EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, MojoArmWatcher(w, &num_ready_contexts, ready_contexts, @@ -933,9 +951,11 @@ &event, w, b)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, readable_b_context)); + MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_b_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -982,7 +1002,8 @@ &expected_notifications, w, a, b, &event)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1048,9 +1069,11 @@ w, a, b, c)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, readable_c_context)); + MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_c_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1113,9 +1136,11 @@ &event, readable_a_context, w, a, b, c)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, readable_c_context)); + MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_c_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1202,14 +1227,15 @@ }, cd_watcher, readable_c_context, c)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, - readable_b_context)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_b_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(cd_watcher, c, MOJO_HANDLE_SIGNAL_READABLE, - readable_c_context)); + MOJO_WATCH_CONDITION_SATISFIED, readable_c_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(cd_watcher, d, MOJO_HANDLE_SIGNAL_READABLE, - readable_d_context)); + MOJO_WATCH_CONDITION_SATISFIED, readable_d_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr)); @@ -1264,7 +1290,8 @@ &event, w, a)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1312,7 +1339,8 @@ &event, w, a, b)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1352,7 +1380,8 @@ &event, w, a)); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1422,7 +1451,8 @@ runner.Start(); EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); @@ -1515,12 +1545,14 @@ }, &wait_for_a_to_cancel, &wait_for_b_to_cancel, &b_cancelled)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE, - readable_a_context)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(a_watcher, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, - readable_b_context)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_b_context)); EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr)); @@ -1560,8 +1592,8 @@ // Cancel via |MojoCancelWatch()|. uintptr_t context = helper.CreateContextWithCancel( WatchHelper::ContextCallback(), signal_event); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, context)); EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, context)); event.Wait(); event.Reset(); @@ -1569,8 +1601,8 @@ // Cancel by closing the watched handle. context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(), signal_event); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, context)); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); event.Wait(); event.Reset(); @@ -1578,8 +1610,8 @@ // Cancel by closing the watcher handle. context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(), signal_event); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, context)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, context)); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); event.Wait(); @@ -1608,7 +1640,8 @@ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); for (size_t i = 0; i < kNumTestHandles; ++i) { EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, handles[i], MOJO_HANDLE_SIGNAL_READABLE, i)); + MojoWatch(w, handles[i], MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, i)); } // Keep trying to arm |w| until every watch gets an entry in |ready_contexts|. @@ -1632,6 +1665,63 @@ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); } +TEST_F(WatcherTest, WatchNotSatisfied) { + MojoHandle a, b; + CreateMessagePipe(&a, &b); + + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + WatchHelper helper; + const uintptr_t readable_a_context = helper.CreateContext(base::Bind( + [](base::WaitableEvent* event, MojoResult result, + MojoHandleSignalsState state) { + EXPECT_EQ(MOJO_RESULT_OK, result); + event->Signal(); + }, + &event)); + + MojoHandle w; + EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, readable_a_context)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); + + const char kMessage[] = "this is not a message"; + + WriteMessage(b, kMessage); + event.Wait(); + + // Now we know |a| is readable. Cancel the watch and watch for the + // not-readable state. + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); + const uintptr_t not_readable_a_context = helper.CreateContext(base::Bind( + [](base::WaitableEvent* event, MojoResult result, + MojoHandleSignalsState state) { + EXPECT_EQ(MOJO_RESULT_OK, result); + event->Signal(); + }, + &event)); + EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_NOT_SATISFIED, + not_readable_a_context)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); + + // This should not block, because the event should be signaled by + // |not_readable_a_context| when we read the only available message off of + // |a|. + event.Reset(); + EXPECT_EQ(kMessage, ReadMessage(a)); + event.Wait(); + + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); +} + } // namespace } // namespace edk } // namespace mojo
diff --git a/mojo/edk/test/mojo_test_base.cc b/mojo/edk/test/mojo_test_base.cc index cb1bbae..d5f7c101 100644 --- a/mojo/edk/test/mojo_test_base.cc +++ b/mojo/edk/test/mojo_test_base.cc
@@ -108,7 +108,7 @@ } // static -void MojoTestBase::CreateMessagePipe(MojoHandle *p0, MojoHandle* p1) { +void MojoTestBase::CreateMessagePipe(MojoHandle* p0, MojoHandle* p1) { MojoCreateMessagePipe(nullptr, p0, p1); CHECK_NE(*p0, MOJO_HANDLE_INVALID); CHECK_NE(*p1, MOJO_HANDLE_INVALID); @@ -117,7 +117,7 @@ // static void MojoTestBase::WriteMessageWithHandles(MojoHandle mp, const std::string& message, - const MojoHandle *handles, + const MojoHandle* handles, uint32_t num_handles) { CHECK_EQ(WriteMessageRaw(MessagePipeHandle(mp), message.data(), static_cast<uint32_t>(message.size()), handles, @@ -176,9 +176,7 @@ } // static -void MojoTestBase::ReadMessage(MojoHandle mp, - char* data, - size_t num_bytes) { +void MojoTestBase::ReadMessage(MojoHandle mp, char* data, size_t num_bytes) { CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); std::vector<uint8_t> bytes; @@ -202,8 +200,7 @@ } // static -void MojoTestBase::VerifyEcho(MojoHandle mp, - const std::string& message) { +void MojoTestBase::VerifyEcho(MojoHandle mp, const std::string& message) { VerifyTransmission(mp, mp, message); } @@ -218,9 +215,8 @@ MojoHandle MojoTestBase::DuplicateBuffer(MojoHandle h, bool read_only) { MojoHandle new_handle; MojoDuplicateBufferHandleOptions options = { - sizeof(MojoDuplicateBufferHandleOptions), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE - }; + sizeof(MojoDuplicateBufferHandleOptions), + MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; if (read_only) options.flags |= MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY; EXPECT_EQ(MOJO_RESULT_OK, @@ -253,7 +249,7 @@ } // static -void MojoTestBase::CreateDataPipe(MojoHandle *p0, +void MojoTestBase::CreateDataPipe(MojoHandle* p0, MojoHandle* p1, size_t capacity) { MojoCreateDataPipeOptions options; @@ -285,7 +281,7 @@ std::vector<char> buffer(size); uint32_t num_bytes = static_cast<uint32_t>(size); CHECK_EQ(MojoReadData(consumer, buffer.data(), &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE), + MOJO_WRITE_DATA_FLAG_ALL_OR_NONE), MOJO_RESULT_OK); CHECK_EQ(num_bytes, static_cast<uint32_t>(size)); @@ -302,8 +298,16 @@ // static MojoResult MojoTestBase::WaitForSignals(MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, MojoHandleSignalsState* state) { - return Wait(Handle(handle), signals, state); + return Wait(Handle(handle), signals, condition, state); +} + +// static +MojoResult MojoTestBase::WaitForSignals(MojoHandle handle, + MojoHandleSignals signals, + MojoHandleSignalsState* state) { + return Wait(Handle(handle), signals, MOJO_WATCH_CONDITION_SATISFIED, state); } } // namespace test
diff --git a/mojo/edk/test/mojo_test_base.h b/mojo/edk/test/mojo_test_base.h index e928d82..9c13074e 100644 --- a/mojo/edk/test/mojo_test_base.h +++ b/mojo/edk/test/mojo_test_base.h
@@ -157,7 +157,13 @@ // Queries the signals state of |handle|. static MojoHandleSignalsState GetSignalsState(MojoHandle handle); - // Helper to block the calling thread waiting for signals to be raised. + // Helper to block the calling thread waiting for signals to go high or low. + static MojoResult WaitForSignals(MojoHandle handle, + MojoHandleSignals signals, + MojoWatchCondition condition, + MojoHandleSignalsState* state = nullptr); + + // Like above but only waits for signals to go high. static MojoResult WaitForSignals(MojoHandle handle, MojoHandleSignals signals, MojoHandleSignalsState* state = nullptr);
diff --git a/mojo/public/c/system/thunks.cc b/mojo/public/c/system/thunks.cc index 8a549dc7..43a5d28 100644 --- a/mojo/public/c/system/thunks.cc +++ b/mojo/public/c/system/thunks.cc
@@ -147,9 +147,10 @@ MojoResult MojoWatch(MojoHandle watcher_handle, MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context) { assert(g_thunks.Watch); - return g_thunks.Watch(watcher_handle, handle, signals, context); + return g_thunks.Watch(watcher_handle, handle, signals, condition, context); } MojoResult MojoCancelWatch(MojoHandle watcher_handle, uintptr_t context) {
diff --git a/mojo/public/c/system/thunks.h b/mojo/public/c/system/thunks.h index 1e4a8dd..e329724 100644 --- a/mojo/public/c/system/thunks.h +++ b/mojo/public/c/system/thunks.h
@@ -77,6 +77,7 @@ MojoResult (*Watch)(MojoHandle watcher_handle, MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context); MojoResult (*CancelWatch)(MojoHandle watcher_handle, uintptr_t context); MojoResult (*ArmWatcher)(MojoHandle watcher_handle,
diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h index 1006310a..84e35b7 100644 --- a/mojo/public/c/system/types.h +++ b/mojo/public/c/system/types.h
@@ -212,6 +212,28 @@ ((MojoWatcherNotificationFlags)1 << 0); #endif +// |MojoWatchCondition|: Given to |MojoWatch()| to indicate whether the +// watched signals should trigger a notification when becoming satisfied or +// becoming not-satisfied. +// +// |MOJO_WATCH_CONDITION_NOT_SATISFIED| - A watch added with this setting will +// trigger a notification when any of the watched signals transition from +// being not-satisfied to being satisfied. +// |MOJO_WATCH_CONDITION_SATISFIED| - A watch added with this setting will +// trigger a notification when any of the watched signals transition from +// being satisfied to being not-satisfied, or when none of the watched +// signals can ever be satisfied again. + +typedef uint32_t MojoWatchCondition; + +#ifdef __cplusplus +const MojoWatchCondition MOJO_WATCH_CONDITION_NOT_SATISFIED = 0; +const MojoWatchCondition MOJO_WATCH_CONDITION_SATISFIED = 1; +#else +#define MOJO_WATCH_CONDITION_NOT_SATISFIED ((MojoWatchCondition)0) +#define MOJO_WATCH_CONDITION_SATISFIED ((MojoWatchCondition)1) +#endif + // |MojoPropertyType|: Property types that can be passed to |MojoGetProperty()| // to retrieve system properties. May take the following values: // |MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED| - Whether making synchronous calls
diff --git a/mojo/public/c/system/watcher.h b/mojo/public/c/system/watcher.h index e32856b6..10b9168 100644 --- a/mojo/public/c/system/watcher.h +++ b/mojo/public/c/system/watcher.h
@@ -65,6 +65,7 @@ // |watcher_handle|: The watcher to which |handle| is to be added. // |handle|: The handle to add to the watcher. // |signals|: The signals to watch for on |handle|. +// |level|: The level to watch for on |signals|. // |context|: An arbitrary context value given to any invocation of the // watcher's callback when invoked as a result of some state change // relevant to this combination of |handle| and |signals|. Must be @@ -97,6 +98,7 @@ MOJO_SYSTEM_EXPORT MojoResult MojoWatch(MojoHandle watcher_handle, MojoHandle handle, MojoHandleSignals signals, + MojoWatchCondition condition, uintptr_t context); // Removes a watch from a watcher.
diff --git a/mojo/public/cpp/system/handle_signals_state.h b/mojo/public/cpp/system/handle_signals_state.h index 487d64d..4c658f3d 100644 --- a/mojo/public/cpp/system/handle_signals_state.h +++ b/mojo/public/cpp/system/handle_signals_state.h
@@ -35,51 +35,59 @@ satisfiable_signals == other.satisfiable_signals; } - bool satisfies(MojoHandleSignals signals) const { + bool satisfies_any(MojoHandleSignals signals) const { return !!(satisfied_signals & signals); } - bool can_satisfy(MojoHandleSignals signals) const { + bool satisfies_all(MojoHandleSignals signals) const { + return (satisfied_signals & signals) == signals; + } + + bool can_satisfy_any(MojoHandleSignals signals) const { return !!(satisfiable_signals & signals); } // The handle is currently readable. May apply to a message pipe handle or // data pipe consumer handle. - bool readable() const { return satisfies(MOJO_HANDLE_SIGNAL_READABLE); } + bool readable() const { return satisfies_any(MOJO_HANDLE_SIGNAL_READABLE); } // The handle is currently writable. May apply to a message pipe handle or // data pipe producer handle. - bool writable() const { return satisfies(MOJO_HANDLE_SIGNAL_WRITABLE); } + bool writable() const { return satisfies_any(MOJO_HANDLE_SIGNAL_WRITABLE); } // The handle's peer is closed. May apply to any message pipe or data pipe // handle. - bool peer_closed() const { return satisfies(MOJO_HANDLE_SIGNAL_PEER_CLOSED); } + bool peer_closed() const { + return satisfies_any(MOJO_HANDLE_SIGNAL_PEER_CLOSED); + } // The handle's peer exists in a remote execution context (e.g. in another // process.) - bool peer_remote() const { return satisfies(MOJO_HANDLE_SIGNAL_PEER_REMOTE); } + bool peer_remote() const { + return satisfies_any(MOJO_HANDLE_SIGNAL_PEER_REMOTE); + } // The handle will never be |readable()| again. bool never_readable() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_READABLE); + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_READABLE); } // The handle will never be |writable()| again. bool never_writable() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_WRITABLE); + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_WRITABLE); } // The handle can never indicate |peer_closed()|. Never true for message pipe // or data pipe handles (they can always signal peer closure), but always true // for other types of handles (they have no peer.) bool never_peer_closed() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_PEER_CLOSED); + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_PEER_CLOSED); } // THe handle will never indicate |peer_remote()| again. True iff the peer is // known to be closed. bool never_peer_remote() const { - return !can_satisfy(MOJO_HANDLE_SIGNAL_PEER_REMOTE); + return !can_satisfy_any(MOJO_HANDLE_SIGNAL_PEER_REMOTE); } // (Copy and assignment allowed.)
diff --git a/mojo/public/cpp/system/simple_watcher.cc b/mojo/public/cpp/system/simple_watcher.cc index 4d3f3be..9e34b16 100644 --- a/mojo/public/cpp/system/simple_watcher.cc +++ b/mojo/public/cpp/system/simple_watcher.cc
@@ -27,6 +27,7 @@ WatcherHandle watcher_handle, Handle handle, MojoHandleSignals signals, + MojoWatchCondition condition, int watch_id, MojoResult* watch_result) { scoped_refptr<Context> context = @@ -38,7 +39,7 @@ context->AddRef(); *watch_result = MojoWatch(watcher_handle.value(), handle.value(), signals, - context->value()); + condition, context->value()); if (*watch_result != MOJO_RESULT_OK) { // Balanced by the AddRef() above since watching failed. context->Release(); @@ -146,6 +147,7 @@ MojoResult SimpleWatcher::Watch(Handle handle, MojoHandleSignals signals, + MojoWatchCondition condition, const ReadyCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!IsWatching()); @@ -157,8 +159,8 @@ MojoResult watch_result = MOJO_RESULT_UNKNOWN; context_ = Context::Create(weak_factory_.GetWeakPtr(), task_runner_, - watcher_handle_.get(), handle_, signals, watch_id_, - &watch_result); + watcher_handle_.get(), handle_, signals, condition, + watch_id_, &watch_result); if (!context_) { handle_.set_value(kInvalidHandleValue); callback_.Reset();
diff --git a/mojo/public/cpp/system/simple_watcher.h b/mojo/public/cpp/system/simple_watcher.h index 8136892..86e38ecd 100644 --- a/mojo/public/cpp/system/simple_watcher.h +++ b/mojo/public/cpp/system/simple_watcher.h
@@ -111,8 +111,16 @@ // Destroying the SimpleWatcher implicitly calls |Cancel()|. MojoResult Watch(Handle handle, MojoHandleSignals signals, + MojoWatchCondition condition, const ReadyCallback& callback); + // DEPRECATED: Please use the above signature instead. + MojoResult Watch(Handle handle, + MojoHandleSignals signals, + const ReadyCallback& callback) { + return Watch(handle, signals, MOJO_WATCH_CONDITION_SATISFIED, callback); + } + // Cancels the current watch. Once this returns, the ReadyCallback previously // passed to |Watch()| will never be called again for this SimpleWatcher. //
diff --git a/mojo/public/cpp/system/wait.cc b/mojo/public/cpp/system/wait.cc index e4e124f2..bb383fe2 100644 --- a/mojo/public/cpp/system/wait.cc +++ b/mojo/public/cpp/system/wait.cc
@@ -69,6 +69,7 @@ MojoResult Wait(Handle handle, MojoHandleSignals signals, + MojoWatchCondition condition, MojoHandleSignalsState* signals_state) { ScopedWatcherHandle watcher; MojoResult rv = CreateWatcher(&WatchContext::OnNotification, &watcher); @@ -80,7 +81,7 @@ // Otherwise balanced immediately below. context->AddRef(); - rv = MojoWatch(watcher.get().value(), handle.value(), signals, + rv = MojoWatch(watcher.get().value(), handle.value(), signals, condition, context->context_value()); if (rv == MOJO_RESULT_INVALID_ARGUMENT) { // Balanced above. @@ -135,8 +136,9 @@ // Otherwise balanced immediately below. contexts[i]->AddRef(); - MojoResult rv = MojoWatch(watcher.get().value(), handles[i].value(), - signals[i], contexts[i]->context_value()); + MojoResult rv = + MojoWatch(watcher.get().value(), handles[i].value(), signals[i], + MOJO_WATCH_CONDITION_SATISFIED, contexts[i]->context_value()); if (rv == MOJO_RESULT_INVALID_ARGUMENT) { if (result_index) *result_index = i;
diff --git a/mojo/public/cpp/system/wait.h b/mojo/public/cpp/system/wait.h index 808e44fc2..c597edb 100644 --- a/mojo/public/cpp/system/wait.h +++ b/mojo/public/cpp/system/wait.h
@@ -14,8 +14,8 @@ namespace mojo { // Blocks the calling thread, waiting for one or more signals in |signals| to be -// become satisfied -- or for all of them to become unsatisfiable -- on the -// given Handle. +// become satisfied, not-satisfied, or permanently unsatisfiable on the handle, +// depending on the |condition| selected. // // If |signals_state| is non-null, |handle| is valid, the wait is not cancelled // (see return values below), the last known signaling state of |handle| is @@ -23,17 +23,29 @@ // // Return values: // |MOJO_RESULT_OK| if one or more signals in |signals| has been raised on -// |handle| . +// |handle| with |condition| set to |MOJO_WATCH_CONDITION_SATISFIED|, or +// one or more signals in |signals| has been lowered on |handle| with +// |condition| set to |MOJO_WATCH_CONDITION_NOT_SATISFIED|. // |MOJO_RESULT_FAILED_PRECONDITION| if the state of |handle| changes such -// that no signals in |signals| can ever be raised again. +// that no signals in |signals| can ever be raised again and |condition| +// is |MOJO_WATCH_CONDITION_SATISFIED|. // |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle. // |MOJO_RESULT_CANCELLED| if the wait was cancelled because |handle| was // closed by some other thread while waiting. MOJO_CPP_SYSTEM_EXPORT MojoResult Wait(Handle handle, MojoHandleSignals signals, + MojoWatchCondition condition, MojoHandleSignalsState* signals_state = nullptr); +// A pseudonym for the above Wait() which always waits on +// |MOJO_WATCH_CONDITION_SATISFIED|. +inline MojoResult Wait(Handle handle, + MojoHandleSignals signals, + MojoHandleSignalsState* signals_state = nullptr) { + return Wait(handle, signals, MOJO_WATCH_CONDITION_SATISFIED, signals_state); +} + // Waits on |handles[0]|, ..., |handles[num_handles-1]| until: // - At least one handle satisfies a signal indicated in its respective // |signals[0]|, ..., |signals[num_handles-1]|.
diff --git a/mojo/public/cpp/system/wait_set.cc b/mojo/public/cpp/system/wait_set.cc index 2081309..6dcf26f 100644 --- a/mojo/public/cpp/system/wait_set.cc +++ b/mojo/public/cpp/system/wait_set.cc
@@ -73,8 +73,9 @@ // This can notify immediately if the watcher is already armed. Don't hold // |lock_| while calling it. - MojoResult rv = MojoWatch(watcher_handle_.get().value(), handle.value(), - signals, context->context_value()); + MojoResult rv = + MojoWatch(watcher_handle_.get().value(), handle.value(), signals, + MOJO_WATCH_CONDITION_SATISFIED, context->context_value()); if (rv == MOJO_RESULT_INVALID_ARGUMENT) { base::AutoLock lock(lock_); handle_to_context_.erase(handle);
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 385a55b..b8536c7f 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -1627,7 +1627,30 @@ void PDFiumEngine::SaveSelectedFormForPrint() { FORM_ForceToKillFocus(form_); - client_->FormTextFieldFocusChange(false); + SetInFormTextArea(false); +} + +void PDFiumEngine::SetFormSelectedText(FPDF_FORMHANDLE form_handle, + FPDF_PAGE page) { + unsigned long form_sel_text_len = + FORM_GetSelectedText(form_handle, page, nullptr, 0); + + // Check to see if there is selected text in the form. When + // |form_sel_text_len| is 2, that represents a wide string with just a + // NUL-terminator. + if (form_sel_text_len <= 2) + return; + + base::string16 selected_form_text16; + PDFiumAPIStringBufferSizeInBytesAdapter<base::string16> string_adapter( + &selected_form_text16, form_sel_text_len, false); + string_adapter.Close(FORM_GetSelectedText( + form_handle, page, string_adapter.GetData(), form_sel_text_len)); + + std::string selected_form_text = base::UTF16ToUTF8(selected_form_text16); + if (!selected_form_text.empty()) { + pp::PDF::SetSelectedText(GetPluginInstance(), selected_form_text.c_str()); + } } void PDFiumEngine::PrintEnd() { @@ -1724,18 +1747,21 @@ FORM_OnLButtonDown(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); if (form_type > FPDF_FORMFIELD_UNKNOWN) { // returns -1 sometimes... - mouse_down_state_.Set(PDFiumPage::NONSELECTABLE_AREA, target); + mouse_down_state_.Set(PDFiumPage::FormTypeToArea(form_type), target); + bool is_valid_control = (form_type == FPDF_FORMFIELD_TEXTFIELD || form_type == FPDF_FORMFIELD_COMBOBOX); + +// TODO(bug_62400): figure out selection and copying +// for XFA fields #if defined(PDF_ENABLE_XFA) is_valid_control |= (form_type == FPDF_FORMFIELD_XFA); #endif - client_->FormTextFieldFocusChange(is_valid_control); + SetInFormTextArea(is_valid_control); return true; // Return now before we get into the selection code. } } - - client_->FormTextFieldFocusChange(false); + SetInFormTextArea(false); if (area != PDFiumPage::TEXT_AREA) return true; // Return true so WebKit doesn't do its own highlighting. @@ -1810,12 +1836,12 @@ middle_button, alt_key, ctrl_key, meta_key, shift_key); client_->NavigateTo(target.url, disposition); - client_->FormTextFieldFocusChange(false); + SetInFormTextArea(false); return true; } if (area == PDFiumPage::DOCLINK_AREA) { client_->ScrollToPage(target.page); - client_->FormTextFieldFocusChange(false); + SetInFormTextArea(false); return true; } } @@ -1831,6 +1857,9 @@ FORM_OnLButtonUp(form_, pages_[page_index]->GetPage(), 0, page_x, page_y); } + if (area == PDFiumPage::FORM_TEXT_AREA) + SetFormSelectedText(form_, pages_[last_page_mouse_down_]->GetPage()); + if (!selecting_) return false; @@ -1862,6 +1891,7 @@ cursor = PP_CURSORTYPE_HAND; break; case PDFiumPage::NONSELECTABLE_AREA: + case PDFiumPage::FORM_TEXT_AREA: default: switch (form_type) { case FPDF_FORMFIELD_PUSHBUTTON: @@ -1988,6 +2018,14 @@ OnChar(synthesized); } + // If form selected text is empty and key pressed within form text area, + // plugin text selection should be cleared. + if (in_form_text_area_ && + FORM_GetSelectedText(form_, pages_[last_page_mouse_down_]->GetPage(), + nullptr, 0) <= 2) { + pp::PDF::SetSelectedText(GetPluginInstance(), ""); + } + return rv; } @@ -1995,6 +2033,11 @@ if (last_page_mouse_down_ == -1) return false; + if (in_form_text_area_) { + if (event.GetKeyCode() == ui::VKEY_SHIFT) + SetFormSelectedText(form_, pages_[last_page_mouse_down_]->GetPage()); + } + return !!FORM_OnKeyUp(form_, pages_[last_page_mouse_down_]->GetPage(), event.GetKeyCode(), event.GetModifiers()); } @@ -3556,6 +3599,11 @@ client_->IsSelectingChanged(selecting); } +void PDFiumEngine::SetInFormTextArea(bool in_form_text_area) { + client_->FormTextFieldFocusChange(in_form_text_area); + in_form_text_area_ = in_form_text_area; +} + void PDFiumEngine::ScheduleTouchTimer(const pp::TouchInputEvent& evt) { touch_timers_[++next_touch_timer_id_] = evt; client_->ScheduleTouchTimerCallback(next_touch_timer_id_,
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index ca45b676..5b0e4aa1 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -318,6 +318,10 @@ const PP_PrintSettings_Dev& print_settings); void SaveSelectedFormForPrint(); + // Checks if |page| has selected text in a form element. If so, sets that as + // the plugin's text selection. + void SetFormSelectedText(FPDF_FORMHANDLE form_handle, FPDF_PAGE page); + // Given a mouse event, returns which page and character location it's closest // to. PDFiumPage::Area GetCharIndex(const pp::MouseInputEvent& event, @@ -437,9 +441,14 @@ // Common code shared by RotateClockwise() and RotateCounterclockwise(). void RotateInternal(); - // Setting selection status of document. + // Sets text selection status of document. This does not include text + // within form text fields. void SetSelecting(bool selecting); + // Sets whether or not focus is in form text field or form combobox text + // field. + void SetInFormTextArea(bool in_form_text_area); + bool PageIndexInBounds(int index) const; void ScheduleTouchTimer(const pp::TouchInputEvent& event); @@ -640,12 +649,15 @@ bool defer_page_unload_; std::vector<int> deferred_page_unloads_; - // Used for selection. There could be more than one range if selection spans - // more than one page. + // Used for text selection, but does not include text within form text fields. + // There could be more than one range if selection spans more than one page. std::vector<PDFiumRange> selection_; - // True if we're in the middle of selection. + // True if we're in the middle of text selection. bool selecting_; + // True if focus is in form text field or form combobox text field. + bool in_form_text_area_; + MouseDownState mouse_down_state_; // Used for searching.
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc index 7d85d36..860767a5 100644 --- a/pdf/pdfium/pdfium_page.cc +++ b/pdf/pdfium/pdfium_page.cc
@@ -264,7 +264,7 @@ DCHECK_NE(control_z_order, link_z_order); if (control_z_order > link_z_order) { *form_type = control; - return PDFiumPage::NONSELECTABLE_AREA; + return FormTypeToArea(*form_type); } // We don't handle all possible link types of the PDF. For example, @@ -283,7 +283,7 @@ return area; } else if (control > FPDF_FORMFIELD_UNKNOWN) { *form_type = control; - return PDFiumPage::NONSELECTABLE_AREA; + return FormTypeToArea(*form_type); } if (rv < 0) @@ -292,6 +292,17 @@ return GetLink(*char_index, target) != -1 ? WEBLINK_AREA : TEXT_AREA; } +// static +PDFiumPage::Area PDFiumPage::FormTypeToArea(int form_type) { + switch (form_type) { + case FPDF_FORMFIELD_COMBOBOX: + case FPDF_FORMFIELD_TEXTFIELD: + return PDFiumPage::FORM_TEXT_AREA; + default: + return PDFiumPage::NONSELECTABLE_AREA; + } +} + base::char16 PDFiumPage::GetCharAtIndex(int index) { if (!available_) return L'\0';
diff --git a/pdf/pdfium/pdfium_page.h b/pdf/pdfium/pdfium_page.h index acb2e7df..7dfa79c 100644 --- a/pdf/pdfium/pdfium_page.h +++ b/pdf/pdfium/pdfium_page.h
@@ -51,9 +51,13 @@ enum Area { NONSELECTABLE_AREA, - TEXT_AREA, - WEBLINK_AREA, // Area is a hyperlink. - DOCLINK_AREA, // Area is a link to a different part of the same document. + TEXT_AREA, // Area contains regular, selectable text not + // within form fields. + WEBLINK_AREA, // Area is a hyperlink. + DOCLINK_AREA, // Area is a link to a different part of the same + // document. + FORM_TEXT_AREA, // Area is a form text field or form combobox text + // field. }; struct LinkTarget { @@ -73,6 +77,9 @@ int* form_type, LinkTarget* target); + // Converts a form type to its corresponding Area. + static Area FormTypeToArea(int form_type); + // Gets the character at the given index. base::char16 GetCharAtIndex(int index);
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 163dabae..0c43ddcc 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -264,6 +264,10 @@ "single_window_input_injector_win.cc", "switches.cc", "switches.h", + "test_echo_extension.cc", + "test_echo_extension.h", + "test_echo_extension_session.cc", + "test_echo_extension_session.h", "third_party_auth_config.cc", "third_party_auth_config.h", "token_validator_base.cc",
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index da82ef7..0dd9389 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -201,20 +201,11 @@ void ClientSession::DeliverClientMessage( const protocol::ExtensionMessage& message) { if (message.has_type()) { - if (message.type() == "test-echo") { - protocol::ExtensionMessage reply; - reply.set_type("test-echo-reply"); - if (message.has_data()) - reply.set_data(message.data().substr(0, 16)); - connection_->client_stub()->DeliverHostMessage(reply); + if (extension_manager_->OnExtensionMessage(message)) return; - } else { - if (extension_manager_->OnExtensionMessage(message)) - return; - DLOG(INFO) << "Unexpected message received: " - << message.type() << ": " << message.data(); - } + DLOG(INFO) << "Unexpected message received: " << message.type() << ": " + << message.data(); } }
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 9fbeeeb4..a4f12046 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -84,6 +84,7 @@ #include "remoting/host/signaling_connector.h" #include "remoting/host/single_window_desktop_environment.h" #include "remoting/host/switches.h" +#include "remoting/host/test_echo_extension.h" #include "remoting/host/third_party_auth_config.h" #include "remoting/host/token_validator_factory_impl.h" #include "remoting/host/usage_stats_consent.h" @@ -1492,6 +1493,8 @@ base::MakeUnique<SecurityKeyExtension>(context_->file_task_runner())); } + host_->AddExtension(base::MakeUnique<TestEchoExtension>()); + // TODO(simonmorris): Get the maximum session duration from a policy. #if defined(OS_LINUX) host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
diff --git a/remoting/host/test_echo_extension.cc b/remoting/host/test_echo_extension.cc new file mode 100644 index 0000000..1fd2e23 --- /dev/null +++ b/remoting/host/test_echo_extension.cc
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/test_echo_extension.h" + +#include "base/memory/ptr_util.h" +#include "remoting/host/test_echo_extension_session.h" + +namespace { +constexpr char kCapability[] = ""; +} + +namespace remoting { + +TestEchoExtension::TestEchoExtension() = default; + +TestEchoExtension::~TestEchoExtension() = default; + +std::string TestEchoExtension::capability() const { + return kCapability; +} + +std::unique_ptr<HostExtensionSession> TestEchoExtension::CreateExtensionSession( + ClientSessionDetails* details, + protocol::ClientStub* client_stub) { + return base::MakeUnique<TestEchoExtensionSession>(); +} + +} // namespace remoting
diff --git a/remoting/host/test_echo_extension.h b/remoting/host/test_echo_extension.h new file mode 100644 index 0000000..5d8b5ec --- /dev/null +++ b/remoting/host/test_echo_extension.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_HOST_TEST_ECHO_EXTENSION_H_ +#define REMOTING_HOST_TEST_ECHO_EXTENSION_H_ + +#include "base/macros.h" +#include "remoting/host/host_extension.h" + +namespace remoting { + +class TestEchoExtension : public HostExtension { + public: + TestEchoExtension(); + ~TestEchoExtension() override; + + // HostExtension interface. + std::string capability() const override; + std::unique_ptr<HostExtensionSession> CreateExtensionSession( + ClientSessionDetails* client_session_details, + protocol::ClientStub* client_stub) override; + + private: + DISALLOW_COPY_AND_ASSIGN(TestEchoExtension); +}; + +} // namespace remoting + +#endif // REMOTING_HOST_TEST_ECHO_EXTENSION_H_
diff --git a/remoting/host/test_echo_extension_session.cc b/remoting/host/test_echo_extension_session.cc new file mode 100644 index 0000000..c468746b --- /dev/null +++ b/remoting/host/test_echo_extension_session.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 "remoting/host/test_echo_extension_session.h" + +#include "base/logging.h" +#include "remoting/proto/control.pb.h" +#include "remoting/protocol/client_stub.h" + +namespace { +constexpr char kExtensionMessageType[] = "test-echo"; +} + +namespace remoting { + +TestEchoExtensionSession::TestEchoExtensionSession() = default; + +TestEchoExtensionSession::~TestEchoExtensionSession() = default; + +bool TestEchoExtensionSession::OnExtensionMessage( + ClientSessionDetails* client_session_details, + protocol::ClientStub* client_stub, + const protocol::ExtensionMessage& message) { + DCHECK(client_stub); + + if (message.type() != kExtensionMessageType) { + return false; + } + + protocol::ExtensionMessage reply; + reply.set_type("test-echo-reply"); + if (message.has_data()) { + reply.set_data(message.data().substr(0, 16)); + } + + client_stub->DeliverHostMessage(reply); + return true; +} + +} // namespace remoting
diff --git a/remoting/host/test_echo_extension_session.h b/remoting/host/test_echo_extension_session.h new file mode 100644 index 0000000..5298ed3 --- /dev/null +++ b/remoting/host/test_echo_extension_session.h
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_HOST_TEST_ECHO_EXTENSION_SESSION_H_ +#define REMOTING_HOST_TEST_ECHO_EXTENSION_SESSION_H_ + +#include "remoting/host/host_extension_session.h" + +namespace remoting { + +class TestEchoExtensionSession : public HostExtensionSession { + public: + TestEchoExtensionSession(); + ~TestEchoExtensionSession() override; + + // HostExtensionSession interface. + bool OnExtensionMessage(ClientSessionDetails* client_session_details, + protocol::ClientStub* client_stub, + const protocol::ExtensionMessage& message) override; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_TEST_ECHO_EXTENSION_SESSION_H_
diff --git a/services/resource_coordinator/BUILD.gn b/services/resource_coordinator/BUILD.gn index fdd1dcce..7582b287 100644 --- a/services/resource_coordinator/BUILD.gn +++ b/services/resource_coordinator/BUILD.gn
@@ -30,10 +30,13 @@ "memory_instrumentation/process_map.h", "resource_coordinator_service.cc", "resource_coordinator_service.h", + "service_callbacks_impl.cc", + "service_callbacks_impl.h", ] public_deps = [ "//base", + "//components/ukm:ukm", "//mojo/public/cpp/bindings", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", "//services/service_manager/public/cpp/standalone_service:standalone_service",
diff --git a/services/resource_coordinator/DEPS b/services/resource_coordinator/DEPS index 12e75222..f8703ea4 100644 --- a/services/resource_coordinator/DEPS +++ b/services/resource_coordinator/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+components/ukm/public", "+third_party/smhasher", "+services/service_manager/public" ]
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc b/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc index 42e8d3a9..c0e3c01 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc +++ b/services/resource_coordinator/coordination_unit/coordination_unit_manager.cc
@@ -9,12 +9,17 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/macros.h" +#include "components/ukm/public/mojo_ukm_recorder.h" +#include "components/ukm/public/ukm_recorder.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_graph_observer.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_impl.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_provider_impl.h" #include "services/resource_coordinator/public/cpp/coordination_unit_types.h" #include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/service_context.h" + +namespace ukm { +class UkmEntryBuilder; +} // namespace ukm namespace resource_coordinator { @@ -50,4 +55,11 @@ coordination_unit->WillBeDestroyed(); } +std::unique_ptr<ukm::UkmEntryBuilder> +CoordinationUnitManager::CreateUkmEntryBuilder(const char* event_name) { + DCHECK(ukm_recorder_ != nullptr); + return ukm_recorder_->GetEntryBuilder(ukm::UkmRecorder::GetNewSourceID(), + event_name); +} + } // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_manager.h b/services/resource_coordinator/coordination_unit/coordination_unit_manager.h index d558870..2f3bcba 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_manager.h +++ b/services/resource_coordinator/coordination_unit/coordination_unit_manager.h
@@ -11,6 +11,11 @@ #include "base/macros.h" #include "services/service_manager/public/cpp/binder_registry.h" +namespace ukm { +class MojoUkmRecorder; +class UkmEntryBuilder; +} // namespace ukm + namespace service_manager { class ServiceContextRefFactory; } // service_manager @@ -29,6 +34,10 @@ CoordinationUnitManager(); ~CoordinationUnitManager(); + void set_ukm_recorder(ukm::MojoUkmRecorder* ukm_recorder) { + ukm_recorder_ = ukm_recorder; + } + void OnStart(service_manager::BinderRegistry* registry, service_manager::ServiceContextRefFactory* service_ref_factory); void RegisterObserver( @@ -37,6 +46,9 @@ void OnCoordinationUnitWillBeDestroyed( CoordinationUnitImpl* coordination_unit); + std::unique_ptr<ukm::UkmEntryBuilder> CreateUkmEntryBuilder( + const char* event_name); + std::vector<std::unique_ptr<CoordinationUnitGraphObserver>>& observers_for_testing() { return observers_; @@ -44,6 +56,7 @@ private: std::vector<std::unique_ptr<CoordinationUnitGraphObserver>> observers_; + ukm::MojoUkmRecorder* ukm_recorder_ = nullptr; static void Create( service_manager::ServiceContextRefFactory* service_ref_factory);
diff --git a/services/resource_coordinator/manifest.json b/services/resource_coordinator/manifest.json index 87ce583..78624785 100644 --- a/services/resource_coordinator/manifest.json +++ b/services/resource_coordinator/manifest.json
@@ -4,7 +4,8 @@ "interface_provider_specs": { "service_manager:connector": { "provides": { - "coordination_unit": [ "resource_coordinator::mojom::CoordinationUnitProvider"], + "coordination_unit": [ "resource_coordinator::mojom::CoordinationUnitProvider" ], + "service_callbacks": [ "resource_coordinator::mojom::ServiceCallbacks" ], "tests": [ "*" ] }, "requires": {
diff --git a/services/resource_coordinator/public/interfaces/BUILD.gn b/services/resource_coordinator/public/interfaces/BUILD.gn index 35c4ca5..1b4026de 100644 --- a/services/resource_coordinator/public/interfaces/BUILD.gn +++ b/services/resource_coordinator/public/interfaces/BUILD.gn
@@ -13,11 +13,13 @@ "events.mojom", "memory_instrumentation/constants.mojom", "memory_instrumentation/memory_instrumentation.mojom", + "service_callbacks.mojom", "service_constants.mojom", "tracing/tracing.mojom", ] public_deps = [ + "//components/ukm/public/interfaces:interfaces", "//mojo/common:common_custom_types", ]
diff --git a/services/resource_coordinator/public/interfaces/service_callbacks.mojom b/services/resource_coordinator/public/interfaces/service_callbacks.mojom new file mode 100644 index 0000000..62d066c --- /dev/null +++ b/services/resource_coordinator/public/interfaces/service_callbacks.mojom
@@ -0,0 +1,29 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module resource_coordinator.mojom; + +import "components/ukm/public/interfaces/ukm_interface.mojom"; + +// This class is intended to provide an interface to register mojo interfaces +// that are not currently accessible to the resource_coordinator service. For +// example (and the reason for this interface), the UKM mojo interface is +// accessible to the resource_coordinator code, as its in //components/, +// but it's bound within the content_browser service. Therefore, the +// content_browser service needs to bind to it and pass the message pointer +// (i.e. message pipe) to the resource_coordinator service. As a result, the +// ServiceCallbacks interface is strategically called within content_browser +// to pass in the initialized UkmRecorderInterfacePtr to the +// resource_coordinator. +interface ServiceCallbacks { + // Checks to see if the resource_coordinator service is already active. Any + // call to EnsureUkmRecorderInterface should enclosed in the passed callback + // and called only when active == true to avoid creating an unecessary + // UkmRecorderInterface mojo connections as resource_coordinator will ignore + // the UkmRecorderInterface passed into EnsureUkmRecorderInterface if it is + // already active. + IsUkmRecorderInterfaceInitialized() => (bool ukm_recorder_already_initialized); + + SetUkmRecorderInterface(ukm.mojom.UkmRecorderInterface ukm_recorder_interface); +};
diff --git a/services/resource_coordinator/resource_coordinator_service.cc b/services/resource_coordinator/resource_coordinator_service.cc index 9455599..1b879a9 100644 --- a/services/resource_coordinator/resource_coordinator_service.cc +++ b/services/resource_coordinator/resource_coordinator_service.cc
@@ -4,11 +4,9 @@ #include "services/resource_coordinator/resource_coordinator_service.h" -#include <string> #include <utility> -#include "base/macros.h" -#include "services/resource_coordinator/coordination_unit/coordination_unit_provider_impl.h" +#include "services/resource_coordinator/service_callbacks_impl.h" #include "services/service_manager/public/cpp/service_context.h" namespace resource_coordinator { @@ -27,6 +25,10 @@ base::Bind(&service_manager::ServiceContext::RequestQuit, base::Unretained(context())))); + registry_.AddInterface(base::Bind(ServiceCallbacksImpl::Create, + base::Unretained(ref_factory_.get()), + base::Unretained(this))); + coordination_unit_manager_.OnStart(®istry_, ref_factory_.get()); } @@ -38,4 +40,10 @@ std::move(interface_pipe)); } +void ResourceCoordinatorService::SetUkmRecorder( + std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder) { + ukm_recorder_ = std::move(ukm_recorder); + coordination_unit_manager_.set_ukm_recorder(ukm_recorder_.get()); +} + } // namespace resource_coordinator
diff --git a/services/resource_coordinator/resource_coordinator_service.h b/services/resource_coordinator/resource_coordinator_service.h index 4246cb952..a56fda5 100644 --- a/services/resource_coordinator/resource_coordinator_service.h +++ b/services/resource_coordinator/resource_coordinator_service.h
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "components/ukm/public/mojo_ukm_recorder.h" #include "services/resource_coordinator/coordination_unit/coordination_unit_manager.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h" @@ -33,10 +34,19 @@ const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; + void SetUkmRecorder(std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder); + + service_manager::BinderRegistry& registry() { return registry_; } + service_manager::ServiceContextRefFactory* ref_factory() { + return ref_factory_.get(); + } + ukm::MojoUkmRecorder* ukm_recorder() { return ukm_recorder_.get(); } + private: service_manager::BinderRegistry registry_; std::unique_ptr<service_manager::ServiceContextRefFactory> ref_factory_; CoordinationUnitManager coordination_unit_manager_; + std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder_; // WeakPtrFactory members should always come last so WeakPtrs are destructed // before other members.
diff --git a/services/resource_coordinator/service_callbacks_impl.cc b/services/resource_coordinator/service_callbacks_impl.cc new file mode 100644 index 0000000..acefed1 --- /dev/null +++ b/services/resource_coordinator/service_callbacks_impl.cc
@@ -0,0 +1,50 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/resource_coordinator/service_callbacks_impl.h" + +#include <utility> + +#include "base/memory/ptr_util.h" +#include "components/ukm/public/mojo_ukm_recorder.h" +#include "services/resource_coordinator/resource_coordinator_service.h" +#include "services/service_manager/public/cpp/service_context_ref.h" + +namespace resource_coordinator { + +ServiceCallbacksImpl::ServiceCallbacksImpl( + service_manager::ServiceContextRefFactory* service_ref_factory, + ResourceCoordinatorService* resource_coordinator_service) + : resource_coordinator_service_(resource_coordinator_service) { + DCHECK(service_ref_factory); + service_ref_ = service_ref_factory->CreateRef(); +} + +ServiceCallbacksImpl::~ServiceCallbacksImpl() = default; + +// static +void ServiceCallbacksImpl::Create( + service_manager::ServiceContextRefFactory* service_ref_factory, + ResourceCoordinatorService* resource_coordinator_service, + const service_manager::BindSourceInfo& source_info, + resource_coordinator::mojom::ServiceCallbacksRequest request) { + mojo::MakeStrongBinding( + base::MakeUnique<ServiceCallbacksImpl>(service_ref_factory, + resource_coordinator_service), + std::move(request)); +} + +void ServiceCallbacksImpl::SetUkmRecorderInterface( + ukm::mojom::UkmRecorderInterfacePtr ukm_recorder_interface) { + resource_coordinator_service_->SetUkmRecorder( + base::MakeUnique<ukm::MojoUkmRecorder>( + std::move(ukm_recorder_interface))); +} + +void ServiceCallbacksImpl::IsUkmRecorderInterfaceInitialized( + const IsUkmRecorderInterfaceInitializedCallback& callback) { + callback.Run(resource_coordinator_service_->ukm_recorder() != nullptr); +} + +} // namespace resource_coordinator
diff --git a/services/resource_coordinator/service_callbacks_impl.h b/services/resource_coordinator/service_callbacks_impl.h new file mode 100644 index 0000000..936be69 --- /dev/null +++ b/services/resource_coordinator/service_callbacks_impl.h
@@ -0,0 +1,52 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_RESOURCE_COORDINATOR_SERVICE_CALLBACKS_IMPL_H_ +#define SERVICES_RESOURCE_COORDINATOR_SERVICE_CALLBACKS_IMPL_H_ + +#include <memory> + +#include "components/ukm/public/interfaces/ukm_interface.mojom.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/resource_coordinator/public/interfaces/service_callbacks.mojom.h" +#include "services/service_manager/public/cpp/bind_source_info.h" + +namespace service_manager { +class ServiceContextRefFactory; +class ServiceContextRef; +} // namespace service_manager + +namespace resource_coordinator { + +class ResourceCoordinatorService; + +class ServiceCallbacksImpl : public mojom::ServiceCallbacks { + public: + ServiceCallbacksImpl( + service_manager::ServiceContextRefFactory* service_ref_factory, + ResourceCoordinatorService* resource_coordinator_service); + ~ServiceCallbacksImpl() override; + + static void Create( + service_manager::ServiceContextRefFactory* service_ref_factory, + ResourceCoordinatorService* resource_coordinator_service, + const service_manager::BindSourceInfo& source_info, + resource_coordinator::mojom::ServiceCallbacksRequest request); + + void IsUkmRecorderInterfaceInitialized( + const IsUkmRecorderInterfaceInitializedCallback& callback) override; + void SetUkmRecorderInterface(ukm::mojom::UkmRecorderInterfacePtr + ukm_recorder_interface_request) override; + + private: + ResourceCoordinatorService* resource_coordinator_service_; + std::unique_ptr<service_manager::ServiceContextRef> service_ref_; + + DISALLOW_COPY_AND_ASSIGN(ServiceCallbacksImpl); +}; + +} // namespace resource_coordinator + +#endif // SERVICES_RESOURCE_COORDINATOR_SERVICE_CALLBACKS_IMPL_H_
diff --git a/services/ui/public/interfaces/window_tree.mojom b/services/ui/public/interfaces/window_tree.mojom index f1a50c5..2459b28 100644 --- a/services/ui/public/interfaces/window_tree.mojom +++ b/services/ui/public/interfaces/window_tree.mojom
@@ -8,7 +8,7 @@ import "cc/ipc/local_surface_id.mojom"; import "cc/ipc/surface_id.mojom"; import "cc/ipc/surface_info.mojom"; -import "cc/ipc/mojo_compositor_frame_sink.mojom"; +import "cc/ipc/compositor_frame_sink.mojom"; import "services/ui/public/interfaces/cursor/cursor.mojom"; import "services/ui/public/interfaces/event_matcher.mojom"; import "services/ui/public/interfaces/mus_constants.mojom"; @@ -152,8 +152,8 @@ // Attaches a CompositorFrameSink to a particular window. AttachCompositorFrameSink( uint32 window_id, - cc.mojom.MojoCompositorFrameSink& compositor_frame_sink, - cc.mojom.MojoCompositorFrameSinkClient client); + cc.mojom.CompositorFrameSink& compositor_frame_sink, + cc.mojom.CompositorFrameSinkClient client); // Reparents a window. // This fails for any of the following reasons:
diff --git a/services/ui/ws/compositor_frame_sink_client_binding.cc b/services/ui/ws/compositor_frame_sink_client_binding.cc index a0dc3d0b..4d7e171 100644 --- a/services/ui/ws/compositor_frame_sink_client_binding.cc +++ b/services/ui/ws/compositor_frame_sink_client_binding.cc
@@ -8,9 +8,9 @@ namespace ws { CompositorFrameSinkClientBinding::CompositorFrameSinkClientBinding( - cc::mojom::MojoCompositorFrameSinkClient* sink_client, - cc::mojom::MojoCompositorFrameSinkClientRequest sink_client_request, - cc::mojom::MojoCompositorFrameSinkAssociatedPtr compositor_frame_sink, + cc::mojom::CompositorFrameSinkClient* sink_client, + cc::mojom::CompositorFrameSinkClientRequest sink_client_request, + cc::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink, cc::mojom::DisplayPrivateAssociatedPtr display_private) : binding_(sink_client, std::move(sink_client_request)), display_private_(std::move(display_private)),
diff --git a/services/ui/ws/compositor_frame_sink_client_binding.h b/services/ui/ws/compositor_frame_sink_client_binding.h index c588c5b2..76ef6a2 100644 --- a/services/ui/ws/compositor_frame_sink_client_binding.h +++ b/services/ui/ws/compositor_frame_sink_client_binding.h
@@ -6,8 +6,8 @@ #define SERVICES_UI_WS_COMPOSITOR_FRAME_SINK_CLIENT_BINDING_H_ #include "base/macros.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/ipc/frame_sink_manager.mojom.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "mojo/public/cpp/bindings/binding.h" @@ -15,29 +15,28 @@ namespace ws { // CompositorFrameSinkClientBinding manages the binding between a FrameGenerator -// and its MojoCompositorFrameSink. CompositorFrameSinkClientBinding exists so -// that a mock implementation of MojoCompositorFrameSink can be injected for +// and its CompositorFrameSink. CompositorFrameSinkClientBinding exists so +// that a mock implementation of CompositorFrameSink can be injected for // tests. FrameGenerator owns its associated CompositorFrameSinkClientBinding. -class CompositorFrameSinkClientBinding - : public cc::mojom::MojoCompositorFrameSink { +class CompositorFrameSinkClientBinding : public cc::mojom::CompositorFrameSink { public: CompositorFrameSinkClientBinding( - cc::mojom::MojoCompositorFrameSinkClient* sink_client, - cc::mojom::MojoCompositorFrameSinkClientRequest sink_client_request, - cc::mojom::MojoCompositorFrameSinkAssociatedPtr compositor_frame_sink, + cc::mojom::CompositorFrameSinkClient* sink_client, + cc::mojom::CompositorFrameSinkClientRequest sink_client_request, + cc::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink, cc::mojom::DisplayPrivateAssociatedPtr display_private); ~CompositorFrameSinkClientBinding() override; private: - // cc::mojom::MojoCompositorFrameSink implementation: + // cc::mojom::CompositorFrameSink implementation: void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override; void SetNeedsBeginFrame(bool needs_begin_frame) override; void DidNotProduceFrame(const cc::BeginFrameAck& ack) override; - mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> binding_; + mojo::Binding<cc::mojom::CompositorFrameSinkClient> binding_; cc::mojom::DisplayPrivateAssociatedPtr display_private_; - cc::mojom::MojoCompositorFrameSinkAssociatedPtr compositor_frame_sink_; + cc::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink_; cc::LocalSurfaceId local_surface_id_; cc::LocalSurfaceIdAllocator id_allocator_; gfx::Size last_submitted_frame_size_;
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc index ca5b7c0..3bc702a 100644 --- a/services/ui/ws/frame_generator.cc +++ b/services/ui/ws/frame_generator.cc
@@ -60,7 +60,7 @@ } void FrameGenerator::Bind( - std::unique_ptr<cc::mojom::MojoCompositorFrameSink> compositor_frame_sink) { + std::unique_ptr<cc::mojom::CompositorFrameSink> compositor_frame_sink) { DCHECK(!compositor_frame_sink_); compositor_frame_sink_ = std::move(compositor_frame_sink); }
diff --git a/services/ui/ws/frame_generator.h b/services/ui/ws/frame_generator.h index d395ab3..ef61aec 100644 --- a/services/ui/ws/frame_generator.h +++ b/services/ui/ws/frame_generator.h
@@ -8,7 +8,7 @@ #include <memory> #include "base/macros.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/surfaces/local_surface_id_allocator.h" #include "cc/surfaces/surface_id.h" @@ -25,7 +25,7 @@ // Responsible for redrawing the display in response to the redraw requests by // submitting CompositorFrames to the owned CompositorFrameSink. -class FrameGenerator : public cc::mojom::MojoCompositorFrameSinkClient { +class FrameGenerator : public cc::mojom::CompositorFrameSinkClient { public: FrameGenerator(); ~FrameGenerator() override; @@ -38,11 +38,11 @@ void OnWindowDamaged(); void OnWindowSizeChanged(const gfx::Size& pixel_size); - void Bind(std::unique_ptr<cc::mojom::MojoCompositorFrameSink> - compositor_frame_sink); + void Bind( + std::unique_ptr<cc::mojom::CompositorFrameSink> compositor_frame_sink); private: - // cc::mojom::MojoCompositorFrameSinkClient implementation: + // cc::mojom::CompositorFrameSinkClient implementation: void DidReceiveCompositorFrameAck( const cc::ReturnedResourceArray& resources) override; void OnBeginFrame(const cc::BeginFrameArgs& args) override; @@ -60,7 +60,7 @@ float device_scale_factor_ = 1.f; gfx::Size pixel_size_; - std::unique_ptr<cc::mojom::MojoCompositorFrameSink> compositor_frame_sink_; + std::unique_ptr<cc::mojom::CompositorFrameSink> compositor_frame_sink_; cc::BeginFrameArgs last_begin_frame_args_; cc::BeginFrameAck current_begin_frame_ack_; bool high_contrast_mode_enabled_ = false;
diff --git a/services/ui/ws/frame_generator_unittest.cc b/services/ui/ws/frame_generator_unittest.cc index ac156edf..88c273f 100644 --- a/services/ui/ws/frame_generator_unittest.cc +++ b/services/ui/ws/frame_generator_unittest.cc
@@ -33,15 +33,14 @@ // TestClientBinding Observes a BeginFrame and accepts CompositorFrame submitted // from FrameGenerator. It provides a way to inspect CompositorFrames. -class TestClientBinding : public cc::mojom::MojoCompositorFrameSink, +class TestClientBinding : public cc::mojom::CompositorFrameSink, public cc::BeginFrameObserver { public: - explicit TestClientBinding( - cc::mojom::MojoCompositorFrameSinkClient* sink_client) + explicit TestClientBinding(cc::mojom::CompositorFrameSinkClient* sink_client) : sink_client_(sink_client) {} ~TestClientBinding() override = default; - // cc::mojom::MojoCompositorFrameSink implementation: + // cc::mojom::CompositorFrameSink implementation: void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, cc::CompositorFrame frame) override { ++frames_submitted_; @@ -95,7 +94,7 @@ } private: - cc::mojom::MojoCompositorFrameSinkClient* sink_client_; + cc::mojom::CompositorFrameSinkClient* sink_client_; cc::BeginFrameArgs last_begin_frame_args_; cc::CompositorFrame last_frame_; cc::BeginFrameSource* begin_frame_source_ = nullptr;
diff --git a/services/ui/ws/frame_sink_manager_client_binding.cc b/services/ui/ws/frame_sink_manager_client_binding.cc index c41e253..d0b2cda 100644 --- a/services/ui/ws/frame_sink_manager_client_binding.cc +++ b/services/ui/ws/frame_sink_manager_client_binding.cc
@@ -24,9 +24,9 @@ void FrameSinkManagerClientBinding::CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request) { frame_sink_manager_->CreateRootCompositorFrameSink( frame_sink_id, surface_handle, std::move(request), @@ -36,9 +36,9 @@ void FrameSinkManagerClientBinding::CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client) { frame_sink_manager_->CreateCompositorFrameSink( frame_sink_id, std::move(request), std::move(private_request), std::move(client));
diff --git a/services/ui/ws/frame_sink_manager_client_binding.h b/services/ui/ws/frame_sink_manager_client_binding.h index 680847a..d951153 100644 --- a/services/ui/ws/frame_sink_manager_client_binding.h +++ b/services/ui/ws/frame_sink_manager_client_binding.h
@@ -31,16 +31,16 @@ void CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_private_request) override; void CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) override; + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkPrivateRequest private_request, + cc::mojom::CompositorFrameSinkClientPtr client) override; void RegisterFrameSinkHierarchy( const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& child_frame_sink_id) override;
diff --git a/services/ui/ws/platform_display_default.cc b/services/ui/ws/platform_display_default.cc index f26e1d0..0b4bf02 100644 --- a/services/ui/ws/platform_display_default.cc +++ b/services/ui/ws/platform_display_default.cc
@@ -248,10 +248,10 @@ widget_ = widget; delegate_->OnAcceleratedWidgetAvailable(); - cc::mojom::MojoCompositorFrameSinkAssociatedPtr compositor_frame_sink; + cc::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink; cc::mojom::DisplayPrivateAssociatedPtr display_private; - cc::mojom::MojoCompositorFrameSinkClientPtr compositor_frame_sink_client; - cc::mojom::MojoCompositorFrameSinkClientRequest + cc::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client; + cc::mojom::CompositorFrameSinkClientRequest compositor_frame_sink_client_request = mojo::MakeRequest(&compositor_frame_sink_client);
diff --git a/services/ui/ws/server_window.cc b/services/ui/ws/server_window.cc index 0a773e8..4db0ea66 100644 --- a/services/ui/ws/server_window.cc +++ b/services/ui/ws/server_window.cc
@@ -88,8 +88,8 @@ void ServerWindow::CreateRootCompositorFrameSink( gfx::AcceleratedWidget widget, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest sink_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest sink_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_request) { GetOrCreateCompositorFrameSinkManager()->CreateRootCompositorFrameSink( widget, std::move(sink_request), std::move(client), @@ -97,8 +97,8 @@ } void ServerWindow::CreateCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client) { GetOrCreateCompositorFrameSinkManager()->CreateCompositorFrameSink( std::move(request), std::move(client)); }
diff --git a/services/ui/ws/server_window.h b/services/ui/ws/server_window.h index cc8fce16..e7b91049 100644 --- a/services/ui/ws/server_window.h +++ b/services/ui/ws/server_window.h
@@ -14,8 +14,8 @@ #include "base/logging.h" #include "base/macros.h" #include "base/observer_list.h" +#include "cc/ipc/compositor_frame_sink.mojom.h" #include "cc/ipc/frame_sink_manager.mojom.h" -#include "cc/ipc/mojo_compositor_frame_sink.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/ui/public/interfaces/window_tree.mojom.h" #include "services/ui/ws/ids.h" @@ -62,13 +62,13 @@ // existing. void CreateRootCompositorFrameSink( gfx::AcceleratedWidget widget, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest sink_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest sink_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_request); void CreateCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client); + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client); const WindowId& id() const { return id_; }
diff --git a/services/ui/ws/server_window_compositor_frame_sink_manager.cc b/services/ui/ws/server_window_compositor_frame_sink_manager.cc index 94ab45b..caec9a8c 100644 --- a/services/ui/ws/server_window_compositor_frame_sink_manager.cc +++ b/services/ui/ws/server_window_compositor_frame_sink_manager.cc
@@ -24,8 +24,8 @@ void ServerWindowCompositorFrameSinkManager::CreateRootCompositorFrameSink( gfx::AcceleratedWidget widget, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest sink_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest sink_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_request) { if (!pending_compositor_frame_sink_request_.is_pending()) { pending_compositor_frame_sink_request_ = @@ -42,8 +42,8 @@ } void ServerWindowCompositorFrameSinkManager::CreateCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client) { if (!pending_compositor_frame_sink_request_.is_pending()) { pending_compositor_frame_sink_request_ = mojo::MakeRequest(&compositor_frame_sink_);
diff --git a/services/ui/ws/server_window_compositor_frame_sink_manager.h b/services/ui/ws/server_window_compositor_frame_sink_manager.h index 7da79d2..5c7ba94 100644 --- a/services/ui/ws/server_window_compositor_frame_sink_manager.h +++ b/services/ui/ws/server_window_compositor_frame_sink_manager.h
@@ -29,13 +29,13 @@ // existing one of the specified type. void CreateRootCompositorFrameSink( gfx::AcceleratedWidget widget, - cc::mojom::MojoCompositorFrameSinkAssociatedRequest sink_request, - cc::mojom::MojoCompositorFrameSinkClientPtr client, + cc::mojom::CompositorFrameSinkAssociatedRequest sink_request, + cc::mojom::CompositorFrameSinkClientPtr client, cc::mojom::DisplayPrivateAssociatedRequest display_request); void CreateCompositorFrameSink( - cc::mojom::MojoCompositorFrameSinkRequest request, - cc::mojom::MojoCompositorFrameSinkClientPtr client); + cc::mojom::CompositorFrameSinkRequest request, + cc::mojom::CompositorFrameSinkClientPtr client); // Claims this FrameSinkId will embed |surface_id| so it should own the // temporary reference to |surface_id|. @@ -43,8 +43,8 @@ private: ServerWindow* const window_; - cc::mojom::MojoCompositorFrameSinkPrivatePtr compositor_frame_sink_; - cc::mojom::MojoCompositorFrameSinkPrivateRequest + cc::mojom::CompositorFrameSinkPrivatePtr compositor_frame_sink_; + cc::mojom::CompositorFrameSinkPrivateRequest pending_compositor_frame_sink_request_; DISALLOW_COPY_AND_ASSIGN(ServerWindowCompositorFrameSinkManager);
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc index e57adb8f..c756b53 100644 --- a/services/ui/ws/window_tree.cc +++ b/services/ui/ws/window_tree.cc
@@ -1644,8 +1644,8 @@ void WindowTree::AttachCompositorFrameSink( Id transport_window_id, - cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest compositor_frame_sink, + cc::mojom::CompositorFrameSinkClientPtr client) { ServerWindow* window = GetWindowByClientId(ClientWindowId(transport_window_id)); if (!window) {
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h index 3aef1350..b30ebf2 100644 --- a/services/ui/ws/window_tree.h +++ b/services/ui/ws/window_tree.h
@@ -459,8 +459,8 @@ float opacity) override; void AttachCompositorFrameSink( Id transport_window_id, - cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink, - cc::mojom::MojoCompositorFrameSinkClientPtr client) override; + cc::mojom::CompositorFrameSinkRequest compositor_frame_sink, + cc::mojom::CompositorFrameSinkClientPtr client) override; void Embed(Id transport_window_id, mojom::WindowTreeClientPtr client, uint32_t flags,
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc index ca6d030..425d3b5 100644 --- a/services/ui/ws/window_tree_client_unittest.cc +++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -2197,9 +2197,9 @@ // Submit a CompositorFrame to window_1_100_in_ws2 (the embedded window in // wt2) and make sure the server gets it. { - cc::mojom::MojoCompositorFrameSinkPtr surface_ptr; - cc::mojom::MojoCompositorFrameSinkClientRequest client_request; - cc::mojom::MojoCompositorFrameSinkClientPtr surface_client_ptr; + cc::mojom::CompositorFrameSinkPtr surface_ptr; + cc::mojom::CompositorFrameSinkClientRequest client_request; + cc::mojom::CompositorFrameSinkClientPtr surface_client_ptr; client_request = mojo::MakeRequest(&surface_client_ptr); wt2()->AttachCompositorFrameSink(window_1_100_in_ws2, mojo::MakeRequest(&surface_ptr), @@ -2235,9 +2235,9 @@ // Submit a CompositorFrame to window_2_101_in_ws2 (a regular window in // wt2) and make sure client gets it. { - cc::mojom::MojoCompositorFrameSinkPtr surface_ptr; - cc::mojom::MojoCompositorFrameSinkClientRequest client_request; - cc::mojom::MojoCompositorFrameSinkClientPtr surface_client_ptr; + cc::mojom::CompositorFrameSinkPtr surface_ptr; + cc::mojom::CompositorFrameSinkClientRequest client_request; + cc::mojom::CompositorFrameSinkClientPtr surface_client_ptr; client_request = mojo::MakeRequest(&surface_client_ptr); wt2()->AttachCompositorFrameSink(window_2_101, mojo::MakeRequest(&surface_ptr),
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index c1a681e6..015c3fb 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -755,36 +755,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-webview", - "--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk" - ], - "isolate_name": "telemetry_perf_webview_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_webview_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build243-m4--device3", - "os": "Android", - "pool": "Chrome-perf-fyi" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results", @@ -3944,65 +3914,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build245-m4--device6", - "os": "Android", - "pool": "Chrome-perf-fyi" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build245-m4--device6", - "os": "Android", - "pool": "Chrome-perf-fyi" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results",
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 3120360..534c107 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -1525,65 +1525,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build13-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build13-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results", @@ -6377,65 +6318,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build73-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build73-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results", @@ -11249,65 +11131,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build15-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build15-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results", @@ -16121,65 +15944,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build9-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build9-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results", @@ -20973,65 +20737,6 @@ }, { "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=android-chromium" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build17-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ - "memory.desktop", - "-v", - "--upload-results", - "--output-format=chartjson", - "--browser=reference", - "--output-trace-tag=_ref" - ], - "isolate_name": "telemetry_perf_tests", - "name": "memory.desktop.reference", - "override_compile_targets": [ - "telemetry_perf_tests" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "android_devices": "1", - "id": "build17-b1--device6", - "os": "Android", - "pool": "Chrome-perf" - } - ], - "expiration": 36000, - "hard_timeout": 10800, - "ignore_task_failure": true, - "io_timeout": 3600 - } - }, - { - "args": [ "memory.long_running_idle_gmail_background_tbmv2", "-v", "--upload-results",
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 03afb62..56b257b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1506,10 +1506,10 @@ crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Failure ] crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-007.html [ Failure ] crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Failure Pass ] -crbug.com/736319 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure Pass ] -crbug.com/736319 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-003.html [ Failure Pass ] +crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure Pass ] +crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-003.html [ Failure Pass ] crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-004.html [ Failure Pass ] -crbug.com/736319 [ Linux ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005.html [ Failure Pass ] +crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005.html [ Failure Pass ] # These need a rebaseline due crbug.com/504745 on Windows when they are activated again. crbug.com/521124 crbug.com/410145 [ Win7 ] fast/css/font-weight-1.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_exist.html b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_exist.html index 3d0a83b..b6048e06 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_exist.html +++ b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_exist.html
@@ -31,6 +31,7 @@ 'loadEventEnd', 'loadEventStart', 'name', + 'nextHopProtocol', 'redirectCount', 'redirectEnd', 'redirectStart',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_values.html b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_values.html index 1ca4a1b..a4b2f6a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_values.html +++ b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_test_attributes_values.html
@@ -70,12 +70,13 @@ "Expected duration to be equal to loadEventEnd."); assert_equals(entries[0].initiatorType, "navigation", "Expected initiatorType to be: navigation."); + assert_equals(entries[0].nextHopProtocol, "http/1.1"); // This test may fail when response is from cach. Disable or clean cach before // running this test. assert_true(entries[0].transferSize > entries[0].encodedBodySize, "Expected transferSize to be greater than encodedBodySize in uncached navigation."); - assert_equals(entries[0].encodedBodySize, 4154); - assert_equals(entries[0].decodedBodySize, 4154); + assert_equals(entries[0].encodedBodySize, 4229); + assert_equals(entries[0].decodedBodySize, 4229); verifyTimingEventOrder(entries[0], navTiming2EventOrder1); // When unloadEvent happens if (entries[0]["unloadEventStart"] != 0) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/test_resource_timing-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/test_resource_timing-expected.txt index 21111a7..14d8b07 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/test_resource_timing-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/test_resource_timing-expected.txt
@@ -3,22 +3,22 @@ PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe) PASS PerformanceEntry has correct order of timing attributes (iframe) PASS PerformanceEntry has correct network transfer attributes (iframe) -FAIL PerformanceEntry has correct protocol attribute (iframe) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined +PASS PerformanceEntry has correct protocol attribute (iframe) PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (img) PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (img) PASS PerformanceEntry has correct order of timing attributes (img) PASS PerformanceEntry has correct network transfer attributes (img) -FAIL PerformanceEntry has correct protocol attribute (img) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined +PASS PerformanceEntry has correct protocol attribute (img) PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link) PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (link) PASS PerformanceEntry has correct order of timing attributes (link) PASS PerformanceEntry has correct network transfer attributes (link) -FAIL PerformanceEntry has correct protocol attribute (link) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined +PASS PerformanceEntry has correct protocol attribute (link) PASS window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (script) PASS PerformanceEntry has correct name, initiatorType, startTime, and duration (script) PASS PerformanceEntry has correct order of timing attributes (script) PASS PerformanceEntry has correct network transfer attributes (script) -FAIL PerformanceEntry has correct protocol attribute (script) assert_equals: expected protocol expected (string) "http/1.1" but got (undefined) undefined +PASS PerformanceEntry has correct protocol attribute (script) FAIL window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (xmlhttprequest) assert_equals: should have a single entry for each resource (without type) expected 1 but got 0 FAIL PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest) Cannot read property 'name' of undefined FAIL PerformanceEntry has correct order of timing attributes (xmlhttprequest) Cannot read property 'connectStart' of undefined
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt index f0840dd2..1541881 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4141,6 +4141,7 @@ getter encodedBodySize getter fetchStart getter initiatorType + getter nextHopProtocol getter redirectEnd getter redirectStart getter requestStart
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt index 8fe4d5d..2a1c321 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4070,6 +4070,7 @@ getter encodedBodySize getter fetchStart getter initiatorType + getter nextHopProtocol getter redirectEnd getter redirectStart getter requestStart
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt index 476bbe3..974714f 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -4857,6 +4857,7 @@ getter encodedBodySize getter fetchStart getter initiatorType + getter nextHopProtocol getter redirectEnd getter redirectStart getter requestStart
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 3372d5c6..1503604 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4864,6 +4864,7 @@ getter encodedBodySize getter fetchStart getter initiatorType + getter nextHopProtocol getter redirectEnd getter redirectStart getter requestStart
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn index 4ece224..c272330 100644 --- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn +++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -206,7 +206,7 @@ deps = [ ":bindings_core_impl_generated", "//skia", - "//third_party/WebKit/Source/platform/wtf", + "//third_party/WebKit/Source/platform", "//v8", ] }
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index a98fa7a..a2b64cc6 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -108,7 +108,7 @@ "//skia", "//third_party/WebKit/Source/core/inspector:generated", "//third_party/WebKit/Source/core/probe:generated", - "//third_party/WebKit/Source/platform/wtf", + "//third_party/WebKit/Source/platform", "//third_party/angle:translator", "//third_party/iccjpeg", "//third_party/icu", @@ -129,7 +129,6 @@ # FIXME: don't depend on bindings_modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules/v8:bindings_modules_v8_generated", - "//third_party/WebKit/Source/platform", ] public_configs = [ @@ -1504,6 +1503,7 @@ "timing/PerformanceBaseTest.cpp", "timing/PerformanceNavigationTimingTest.cpp", "timing/PerformanceObserverTest.cpp", + "timing/PerformanceResourceTimingTest.cpp", "timing/PerformanceTest.cpp", "workers/DedicatedWorkerTest.cpp", "workers/MainThreadWorkletTest.cpp",
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h index 74adaa5..012541c1 100644 --- a/third_party/WebKit/Source/core/frame/Frame.h +++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -145,6 +145,17 @@ void SetDocumentHasReceivedUserGesture(); bool HasReceivedUserGesture() const { return has_received_user_gesture_; } + void ClearDocumentHasReceivedUserGesture() { + has_received_user_gesture_ = false; + } + + void SetDocumentHasReceivedUserGestureBeforeNavigation(bool value) { + has_received_user_gesture_before_nav_ = value; + } + + bool HasReceivedUserGestureBeforeNavigation() const { + return has_received_user_gesture_before_nav_; + } bool IsAttached() const { return lifecycle_.GetState() == FrameLifecycle::kAttached; @@ -170,6 +181,7 @@ Member<DOMWindow> dom_window_; bool has_received_user_gesture_ = false; + bool has_received_user_gesture_before_nav_ = false; FrameLifecycle lifecycle_;
diff --git a/third_party/WebKit/Source/core/frame/FrameTest.cpp b/third_party/WebKit/Source/core/frame/FrameTest.cpp index 992662b..b5ac98b 100644 --- a/third_party/WebKit/Source/core/frame/FrameTest.cpp +++ b/third_party/WebKit/Source/core/frame/FrameTest.cpp
@@ -6,6 +6,7 @@ #include "core/dom/UserGestureIndicator.h" #include "core/testing/DummyPageHolder.h" +#include "platform/testing/UnitTestHelpers.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink { @@ -14,11 +15,31 @@ public: void SetUp() override { dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600)); + Navigate("https://example.com/"); + ASSERT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + ASSERT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); } Document& GetDocument() const { return dummy_page_holder_->GetDocument(); } + void Navigate(const String& destinationUrl) { + const KURL& url = KURL(KURL(), destinationUrl); + FrameLoadRequest request( + nullptr, ResourceRequest(url), + SubstituteData(SharedBuffer::Create(), "text/html", "UTF-8", KURL())); + GetDocument().GetFrame()->Loader().Load(request); + blink::testing::RunPendingTasks(); + ASSERT_EQ(url.GetString(), GetDocument().Url().GetString()); + } + + void NavigateSameDomain(const String& page) { + Navigate("https://test.example.com/" + page); + } + + void NavigateDifferentDomain() { Navigate("https://example.org/"); } + private: std::unique_ptr<DummyPageHolder> dummy_page_holder_; }; @@ -44,15 +65,85 @@ EXPECT_TRUE(GetDocument().GetFrame()->HasReceivedUserGesture()); } -TEST_F(FrameTest, Navigate) { +TEST_F(FrameTest, NavigateDifferentDomain) { UserGestureToken::Create(&GetDocument()); - ASSERT_TRUE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_TRUE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); // Navigate to a different Document. In the main frame, user gesture state - // will get reset. - GetDocument().GetFrame()->Loader().Load( - FrameLoadRequest(nullptr, ResourceRequest())); + // will get reset. State will not persist since the domain has changed. + NavigateDifferentDomain(); EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); +} + +TEST_F(FrameTest, NavigateSameDomainMultipleTimes) { + UserGestureToken::Create(&GetDocument()); + EXPECT_TRUE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + // Navigate to a different Document in the same domain. In the main frame, + // user gesture state will get reset, but persisted state will be true. + NavigateSameDomain("page1"); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_TRUE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + // Navigate to a different Document in the same domain, the persisted + // state will be true. + NavigateSameDomain("page2"); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_TRUE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + // Navigate to the same URL in the same domain, the persisted state + // will be true, but the user gesture state will be reset. + NavigateSameDomain("page2"); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_TRUE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + // Navigate to a different Document in the same domain, the persisted + // state will be true. + NavigateSameDomain("page3"); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_TRUE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); +} + +TEST_F(FrameTest, NavigateSameDomainDifferentDomain) { + UserGestureToken::Create(&GetDocument()); + EXPECT_TRUE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + // Navigate to a different Document in the same domain. In the main frame, + // user gesture state will get reset, but persisted state will be true. + NavigateSameDomain("page1"); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_TRUE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + // Navigate to a different Document in a different domain, the persisted + // state will be reset. + NavigateDifferentDomain(); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); +} + +TEST_F(FrameTest, NavigateSameDomainNoGesture) { + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); + + NavigateSameDomain("page1"); + EXPECT_FALSE(GetDocument().GetFrame()->HasReceivedUserGesture()); + EXPECT_FALSE( + GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation()); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index 42b6646..46f5a7d 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -395,8 +395,6 @@ Selection().DocumentAttached(GetDocument()); GetInputMethodController().DocumentAttached(GetDocument()); GetSpellChecker().DocumentAttached(GetDocument()); - if (IsMainFrame()) - has_received_user_gesture_ = false; } Frame* LocalFrame::FindFrameForNavigation(const AtomicString& name,
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp index 0287ed2..c98bbdc 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -78,6 +78,7 @@ #include "platform/mhtml/ArchiveResource.h" #include "platform/network/ContentSecurityPolicyResponseHeaders.h" #include "platform/network/HTTPParsers.h" +#include "platform/network/NetworkUtils.h" #include "platform/network/mime/MIMETypeRegistry.h" #include "platform/plugins/PluginData.h" #include "platform/weborigin/SchemeRegistry.h" @@ -1018,6 +1019,32 @@ previous_security_origin); } +// static +bool DocumentLoader::CheckOriginIsHttpOrHttps(const SecurityOrigin* origin) { + return origin && + (origin->Protocol() == "http" || origin->Protocol() == "https"); +} + +// static +bool DocumentLoader::ShouldPersistUserGestureValue( + const SecurityOrigin* previous_security_origin, + const SecurityOrigin* new_security_origin) { + if (!CheckOriginIsHttpOrHttps(previous_security_origin) || + !CheckOriginIsHttpOrHttps(new_security_origin)) + return false; + + if (previous_security_origin->Host() == new_security_origin->Host()) + return true; + + String previous_domain = NetworkUtils::GetDomainAndRegistry( + previous_security_origin->Host(), + NetworkUtils::kIncludePrivateRegistries); + String new_domain = NetworkUtils::GetDomainAndRegistry( + new_security_origin->Host(), NetworkUtils::kIncludePrivateRegistries); + + return !previous_domain.IsEmpty() && previous_domain == new_domain; +} + void DocumentLoader::InstallNewDocument( const DocumentInit& init, const AtomicString& mime_type, @@ -1041,8 +1068,23 @@ if (!init.ShouldReuseDefaultView()) frame_->SetDOMWindow(LocalDOMWindow::Create(*frame_)); + bool user_gesture_bit_set = frame_->HasReceivedUserGesture() || + frame_->HasReceivedUserGestureBeforeNavigation(); + Document* document = frame_->DomWindow()->InstallNewDocument(mime_type, init); + // Persist the user gesture state between frames. + if (user_gesture_bit_set) { + frame_->SetDocumentHasReceivedUserGestureBeforeNavigation( + ShouldPersistUserGestureValue(previous_security_origin, + document->GetSecurityOrigin())); + + // Clear the user gesture bit that is not persisted. + // TODO(crbug.com/736415): Clear this bit unconditionally for all frames. + if (frame_->IsMainFrame()) + frame_->ClearDocumentHasReceivedUserGesture(); + } + if (ShouldClearWindowName(*frame_, previous_security_origin, *document)) { // TODO(andypaicu): experimentalSetNullName will just record the fact // that the name would be nulled and if the name is accessed after we will
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h index c213073..189ece92 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.h +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -336,6 +336,11 @@ bool was_blocked_after_csp_; + static bool ShouldPersistUserGestureValue( + const SecurityOrigin* previous_security_origin, + const SecurityOrigin* new_security_origin); + static bool CheckOriginIsHttpOrHttps(const SecurityOrigin*); + // PlzNavigate: set when committing a navigation. The data has originally been // captured when the navigation was sent to the browser process, and it is // sent back at commit time.
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp index d25446ad..e51fe2e0a 100644 --- a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp +++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
@@ -92,6 +92,7 @@ DCHECK_EQ(MOJO_RESULT_OK, result); result = MojoWatch(watcher_handle_.get().value(), handle.value(), signals, + MOJO_WATCH_CONDITION_SATISFIED, reinterpret_cast<uintptr_t>(this)); if (result != MOJO_RESULT_OK) return result;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp index fe75b4c9..f0263af90 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.cpp
@@ -125,6 +125,14 @@ resource_timing_info_->FinalResponse(), *security_origin, context); } +AtomicString PerformanceNavigationTiming::AlpnNegotiatedProtocol() const { + return resource_timing_info_->FinalResponse().AlpnNegotiatedProtocol(); +} + +AtomicString PerformanceNavigationTiming::ConnectionInfo() const { + return resource_timing_info_->FinalResponse().ConnectionInfoString(); +} + DOMHighResTimeStamp PerformanceNavigationTiming::unloadEventStart() const { bool allow_redirect_details = GetAllowRedirectDetails(); DocumentLoadTiming* timing = GetDocumentLoadTiming();
diff --git a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h index b79becd..baf431eb 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h +++ b/third_party/WebKit/Source/core/timing/PerformanceNavigationTiming.h
@@ -80,6 +80,9 @@ bool GetAllowRedirectDetails() const; + AtomicString AlpnNegotiatedProtocol() const override; + AtomicString ConnectionInfo() const override; + double time_origin_; RefPtr<ResourceTimingInfo> resource_timing_info_; };
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp index 48678a8..7133ad5 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp +++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
@@ -57,6 +57,8 @@ info.LoadFinishTime(), info.NegativeAllowed())), initiator_type_(info.InitiatorType()), + alpn_negotiated_protocol_(info.FinalResponse().AlpnNegotiatedProtocol()), + connection_info_(info.FinalResponse().ConnectionInfoString()), time_origin_(time_origin), timing_(info.FinalResponse().GetResourceLoadTiming()), last_redirect_end_time_(last_redirect_end_time), @@ -106,6 +108,37 @@ return initiator_type_; } +AtomicString PerformanceResourceTiming::AlpnNegotiatedProtocol() const { + return alpn_negotiated_protocol_; +} + +AtomicString PerformanceResourceTiming::ConnectionInfo() const { + return connection_info_; +} + +AtomicString PerformanceResourceTiming::GetNextHopProtocol( + const AtomicString& alpn_negotiated_protocol, + const AtomicString& connection_info) { + // Fallback to connection_info when alpn_negotiated_protocol is unknown. + AtomicString returnedProtocol = (alpn_negotiated_protocol == "unknown") + ? connection_info + : alpn_negotiated_protocol; + // If connection_info is also unknown, return empty string. + // (https://github.com/w3c/navigation-timing/issues/71) + returnedProtocol = (returnedProtocol == "unknown") ? "" : returnedProtocol; + // If the protocol is http over quic (e.g. http/2+quic/37), convert it to the + // alpn id "hq". (https://github.com/w3c/navigation-timing/issues/71) + if (returnedProtocol.Contains("quic")) + returnedProtocol = "hq"; + + return returnedProtocol; +} + +AtomicString PerformanceResourceTiming::nextHopProtocol() const { + return PerformanceResourceTiming::GetNextHopProtocol(AlpnNegotiatedProtocol(), + ConnectionInfo()); +} + DOMHighResTimeStamp PerformanceResourceTiming::workerStart() const { ResourceLoadTiming* timing = GetResourceLoadTiming(); if (!timing || timing->WorkerStart() == 0.0) @@ -277,6 +310,7 @@ void PerformanceResourceTiming::BuildJSONValue(V8ObjectBuilder& builder) const { PerformanceEntry::BuildJSONValue(builder); builder.AddString("initiatorType", initiatorType()); + builder.AddString("nextHopProtocol", nextHopProtocol()); builder.AddNumber("workerStart", workerStart()); builder.AddNumber("redirectStart", redirectStart()); builder.AddNumber("redirectEnd", redirectEnd());
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h index 53c1d8c1..45f5d4e0 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h +++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.h
@@ -44,6 +44,7 @@ class CORE_EXPORT PerformanceResourceTiming : public PerformanceEntry { DEFINE_WRAPPERTYPEINFO(); + friend class PerformanceResourceTimingTest; public: ~PerformanceResourceTiming() override; @@ -67,6 +68,7 @@ } // Related doc: https://goo.gl/uNecAj. virtual AtomicString initiatorType() const; + AtomicString nextHopProtocol() const; DOMHighResTimeStamp workerStart() const; virtual DOMHighResTimeStamp redirectStart() const; virtual DOMHighResTimeStamp redirectEnd() const; @@ -92,6 +94,8 @@ const String& entry_type, double start_time, double duration); + virtual AtomicString AlpnNegotiatedProtocol() const; + virtual AtomicString ConnectionInfo() const; private: PerformanceResourceTiming(const ResourceTimingInfo&, @@ -101,6 +105,10 @@ bool allow_timing_details, bool allow_redirect_details); + static AtomicString GetNextHopProtocol( + const AtomicString& alpn_negotiated_protocol, + const AtomicString& connection_info); + double WorkerReady() const; virtual ResourceLoadTiming* GetResourceLoadTiming() const; @@ -111,6 +119,8 @@ virtual unsigned long long GetDecodedBodySize() const; AtomicString initiator_type_; + AtomicString alpn_negotiated_protocol_; + AtomicString connection_info_; double time_origin_; RefPtr<ResourceLoadTiming> timing_; double last_redirect_end_time_;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.idl b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.idl index 49be19d6..27cd520 100644 --- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.idl +++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.idl
@@ -33,7 +33,7 @@ // TODO(foolip): This interface should be [Exposed=(Window,Worker)]. interface PerformanceResourceTiming : PerformanceEntry { readonly attribute DOMString initiatorType; - // TODO(foolip): readonly attribute DOMString nextHopProtocol; + readonly attribute DOMString nextHopProtocol; readonly attribute DOMHighResTimeStamp workerStart; readonly attribute DOMHighResTimeStamp redirectStart; readonly attribute DOMHighResTimeStamp redirectEnd;
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTimingTest.cpp b/third_party/WebKit/Source/core/timing/PerformanceResourceTimingTest.cpp new file mode 100644 index 0000000..54e4dac --- /dev/null +++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTimingTest.cpp
@@ -0,0 +1,48 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/timing/PerformanceResourceTiming.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +class PerformanceResourceTimingTest : public ::testing::Test { + protected: + AtomicString GetNextHopProtocol(const AtomicString& alpn_negotiated_protocol, + const AtomicString& connection_info) { + return PerformanceResourceTiming::GetNextHopProtocol( + alpn_negotiated_protocol, connection_info); + } +}; + +TEST_F(PerformanceResourceTimingTest, + TestFallbackToConnectionInfoWhenALPNUnknown) { + AtomicString connection_info = "http/1.1"; + AtomicString alpn_negotiated_protocol = "unknown"; + EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), + connection_info); +} + +TEST_F(PerformanceResourceTimingTest, + TestFallbackToHTTPInfoWhenALPNAndConnectionInfoUnknown) { + AtomicString connection_info = "unknown"; + AtomicString alpn_negotiated_protocol = "unknown"; + EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), ""); +} + +TEST_F(PerformanceResourceTimingTest, TestFallbackToHQWhenContainsQuic) { + AtomicString connection_info = "http/1.1"; + AtomicString alpn_negotiated_protocol = "quic/1spdy/3"; + EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), + "hq"); +} + +TEST_F(PerformanceResourceTimingTest, TestNoChangeWhenOtherwise) { + AtomicString connection_info = "http/1.1"; + AtomicString alpn_negotiated_protocol = "RandomProtocol"; + EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), + alpn_negotiated_protocol); +} +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/exported/BUILD.gn b/third_party/WebKit/Source/modules/exported/BUILD.gn index 372abf31..8e869c56 100644 --- a/third_party/WebKit/Source/modules/exported/BUILD.gn +++ b/third_party/WebKit/Source/modules/exported/BUILD.gn
@@ -33,7 +33,7 @@ "//skia", "//third_party/WebKit/Source/core:testing", "//third_party/WebKit/Source/modules:modules_testing", - "//third_party/WebKit/Source/platform/wtf", + "//third_party/WebKit/Source/platform", "//v8", ]
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index 7c3679c..f96ef511 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -867,9 +867,9 @@ }; // Exposed by EXT_color_buffer_float -static const GLenum kSupportedInternalFormatsFloatES3[] = { - GL_R16F, GL_R32F, GL_RG16F, GL_RG32F, - GL_RGBA16F, GL_RGBA32F, GL_R11F_G11F_B10F}; +static const GLenum kSupportedInternalFormatsCopyTexImageFloatES3[] = { + GL_R16F, GL_R32F, GL_RG16F, GL_RG32F, GL_RGB16F, + GL_RGB32F, GL_RGBA16F, GL_RGBA32F, GL_R11F_G11F_B10F}; // ES3 enums supported by TexImageSource static const GLenum kSupportedInternalFormatsTexImageSourceES3[] = { @@ -2076,7 +2076,7 @@ if (!is_ext_color_buffer_float_formats_added_ && ExtensionEnabled(kEXTColorBufferFloatName)) { ADD_VALUES_TO_SET(supported_internal_formats_copy_tex_image_, - kSupportedInternalFormatsFloatES3); + kSupportedInternalFormatsCopyTexImageFloatES3); is_ext_color_buffer_float_formats_added_ = true; }
diff --git a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp index e51c6865..61cf41e 100644 --- a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp +++ b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
@@ -372,6 +372,24 @@ resource_response_->AppendRedirectResponse(response.ToResourceResponse()); } +WebString WebURLResponse::AlpnNegotiatedProtocol() const { + return resource_response_->AlpnNegotiatedProtocol(); +} + +void WebURLResponse::SetAlpnNegotiatedProtocol( + const WebString& alpn_negotiated_protocol) { + resource_response_->SetAlpnNegotiatedProtocol(alpn_negotiated_protocol); +} + +net::HttpResponseInfo::ConnectionInfo WebURLResponse::ConnectionInfo() const { + return resource_response_->ConnectionInfo(); +} + +void WebURLResponse::SetConnectionInfo( + net::HttpResponseInfo::ConnectionInfo connection_info) { + resource_response_->SetConnectionInfo(connection_info); +} + WebURLResponse::WebURLResponse(ResourceResponse& r) : resource_response_(&r) {} } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp index 5e3ad60..f540f99 100644 --- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp +++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -56,7 +56,7 @@ Platform::Current()->GetInterfaceProvider()->GetInterface( mojo::MakeRequest(&provider)); - cc::mojom::blink::MojoCompositorFrameSinkClientPtr client; + cc::mojom::blink::CompositorFrameSinkClientPtr client; binding_.Bind(mojo::MakeRequest(&client)); provider->CreateCompositorFrameSink(frame_sink_id_, std::move(client), mojo::MakeRequest(&sink_));
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h index 8c66a57..22281382a 100644 --- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h +++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.h
@@ -6,7 +6,7 @@ #define OffscreenCanvasFrameDispatcherImpl_h #include <memory> -#include "cc/ipc/mojo_compositor_frame_sink.mojom-blink.h" +#include "cc/ipc/compositor_frame_sink.mojom-blink.h" #include "cc/output/begin_frame_args.h" #include "cc/resources/shared_bitmap.h" #include "cc/surfaces/local_surface_id_allocator.h" @@ -20,8 +20,7 @@ class PLATFORM_EXPORT OffscreenCanvasFrameDispatcherImpl final : public OffscreenCanvasFrameDispatcher, - NON_EXPORTED_BASE( - public cc::mojom::blink::MojoCompositorFrameSinkClient) { + NON_EXPORTED_BASE(public cc::mojom::blink::CompositorFrameSinkClient) { public: OffscreenCanvasFrameDispatcherImpl(OffscreenCanvasFrameDispatcherClient*, uint32_t client_id, @@ -43,7 +42,7 @@ void ReclaimResource(unsigned resource_id) final; void Reshape(int width, int height) final; - // cc::mojom::blink::MojoCompositorFrameSinkClient implementation. + // cc::mojom::blink::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const cc::ReturnedResourceArray& resources) final; void OnBeginFrame(const cc::BeginFrameArgs&) final; @@ -97,8 +96,8 @@ bool VerifyImageSize(const IntSize); void PostImageToPlaceholder(RefPtr<StaticBitmapImage>); - cc::mojom::blink::MojoCompositorFrameSinkPtr sink_; - mojo::Binding<cc::mojom::blink::MojoCompositorFrameSinkClient> binding_; + cc::mojom::blink::CompositorFrameSinkPtr sink_; + mojo::Binding<cc::mojom::blink::CompositorFrameSinkClient> binding_; int placeholder_canvas_id_;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp index ff945347..ae852e1f 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.cpp
@@ -101,6 +101,8 @@ last_modified_(0.0), app_cache_id_(0), response_time_(0), + connection_info_( + net::HttpResponseInfo::ConnectionInfo::CONNECTION_INFO_UNKNOWN), encoded_data_length_(0), encoded_body_length_(0), decoded_body_length_(0) {} @@ -572,6 +574,14 @@ return url_list_via_service_worker_.back(); } +AtomicString ResourceResponse::ConnectionInfoString() const { + std::string connection_info_string = + net::HttpResponseInfo::ConnectionInfoToString(connection_info_); + return AtomicString( + reinterpret_cast<const LChar*>(connection_info_string.data()), + connection_info_string.length()); +} + void ResourceResponse::SetEncodedDataLength(long long value) { encoded_data_length_ = value; }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h index 811fcef..da5c9ef 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponse.h
@@ -341,6 +341,22 @@ unsigned short RemotePort() const { return remote_port_; } void SetRemotePort(unsigned short value) { remote_port_ = value; } + const AtomicString& AlpnNegotiatedProtocol() const { + return alpn_negotiated_protocol_; + } + void SetAlpnNegotiatedProtocol(const AtomicString& value) { + alpn_negotiated_protocol_ = value; + } + + net::HttpResponseInfo::ConnectionInfo ConnectionInfo() const { + return connection_info_; + } + void SetConnectionInfo(net::HttpResponseInfo::ConnectionInfo value) { + connection_info_ = value; + } + + AtomicString ConnectionInfoString() const; + long long EncodedDataLength() const { return encoded_data_length_; } void SetEncodedDataLength(long long value); @@ -477,6 +493,12 @@ // responses, this time could be "far" in the past. int64_t response_time_; + // ALPN negotiated protocol of the socket which fetched this resource. + AtomicString alpn_negotiated_protocol_; + + // Information about the type of connection used to fetch this resource. + net::HttpResponseInfo::ConnectionInfo connection_info_; + // Size of the response in bytes prior to decompression. long long encoded_data_length_;
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index f412b84a0..1cfc957b 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -640,6 +640,7 @@ ] public_deps = [ + "//net", "//skia", "//url", ]
diff --git a/third_party/WebKit/public/platform/DEPS b/third_party/WebKit/public/platform/DEPS index 15c3183f..7a60c49 100644 --- a/third_party/WebKit/public/platform/DEPS +++ b/third_party/WebKit/public/platform/DEPS
@@ -18,6 +18,7 @@ # http://crbug.com/582327 "+media/midi/midi_service.mojom-shared.h", "+mojo/public", + "+net/http", "+platform", "+platform/weborigin", "+public/platform",
diff --git a/third_party/WebKit/public/platform/WebURLResponse.h b/third_party/WebKit/public/platform/WebURLResponse.h index a77d464..d00f6f1 100644 --- a/third_party/WebKit/public/platform/WebURLResponse.h +++ b/third_party/WebKit/public/platform/WebURLResponse.h
@@ -31,13 +31,14 @@ #ifndef WebURLResponse_h #define WebURLResponse_h +#include <memory> +#include "net/http/http_response_info.h" #include "public/platform/WebCString.h" #include "public/platform/WebCommon.h" #include "public/platform/WebSecurityStyle.h" #include "public/platform/WebString.h" #include "public/platform/WebVector.h" #include "public/platform/modules/serviceworker/WebServiceWorkerResponseType.h" -#include <memory> namespace blink { @@ -269,6 +270,16 @@ BLINK_PLATFORM_EXPORT unsigned short RemotePort() const; BLINK_PLATFORM_EXPORT void SetRemotePort(unsigned short); + // ALPN negotiated protocol of the socket which fetched this resource. + BLINK_PLATFORM_EXPORT WebString AlpnNegotiatedProtocol() const; + BLINK_PLATFORM_EXPORT void SetAlpnNegotiatedProtocol(const WebString&); + + // Information about the type of connection used to fetch this resource. + BLINK_PLATFORM_EXPORT net::HttpResponseInfo::ConnectionInfo ConnectionInfo() + const; + BLINK_PLATFORM_EXPORT void SetConnectionInfo( + net::HttpResponseInfo::ConnectionInfo); + // Original size of the response before decompression. BLINK_PLATFORM_EXPORT void SetEncodedDataLength(long long);
diff --git a/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom b/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom index 7d57bee..a2d52d1 100644 --- a/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom +++ b/third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom
@@ -6,7 +6,7 @@ import "cc/ipc/frame_sink_id.mojom"; import "cc/ipc/frame_sink_manager.mojom"; -import "cc/ipc/mojo_compositor_frame_sink.mojom"; +import "cc/ipc/compositor_frame_sink.mojom"; import "cc/ipc/surface_id.mojom"; import "cc/ipc/surface_info.mojom"; import "cc/ipc/surface_sequence.mojom"; @@ -20,7 +20,7 @@ OnSurfaceCreated(cc.mojom.SurfaceInfo surface_info); }; -// Creates OffscreenCanvasSurface and MojoCompositorFrameSink instances for use +// Creates OffscreenCanvasSurface and CompositorFrameSink instances for use // with offscreen canvas. interface OffscreenCanvasProvider { // Create an OffscreenCanvasSurface for |frame_sink_id|. |client| will observe @@ -30,9 +30,9 @@ OffscreenCanvasSurfaceClient client, OffscreenCanvasSurface& surface); - // Create an MojoCompositorFrameSink for |frame_sink_id|. This must happen + // Create an CompositorFrameSink for |frame_sink_id|. This must happen // after creating an OffsreenCanvasSurface for |frame_sink_id|. CreateCompositorFrameSink(cc.mojom.FrameSinkId frame_sink_id, - cc.mojom.MojoCompositorFrameSinkClient client, - cc.mojom.MojoCompositorFrameSink& sink); + cc.mojom.CompositorFrameSinkClient client, + cc.mojom.CompositorFrameSink& sink); }; \ No newline at end of file
diff --git a/tools/binary_size/libsupersize/describe.py b/tools/binary_size/libsupersize/describe.py index 759525b..19dd607c 100644 --- a/tools/binary_size/libsupersize/describe.py +++ b/tools/binary_size/libsupersize/describe.py
@@ -122,17 +122,18 @@ if sym.IsDelta(): if sym.IsGroup(): - b = sum(s.before_symbol.size_without_padding if s.before_symbol else 0 - for s in sym) - a = sum(s.after_symbol.size_without_padding if s.after_symbol else 0 - for s in sym) + b = sum(s.before_symbol.pss_without_padding if s.before_symbol else 0 + for s in sym.IterLeafSymbols()) + a = sum(s.after_symbol.pss_without_padding if s.after_symbol else 0 + for s in sym.IterLeafSymbols()) else: - b = sym.before_symbol.size_without_padding if sym.before_symbol else 0 - a = sym.after_symbol.size_without_padding if sym.after_symbol else 0 + b = sym.before_symbol.pss_without_padding if sym.before_symbol else 0 + a = sym.after_symbol.pss_without_padding if sym.after_symbol else 0 pss_with_sign = _FormatPss(sym.pss) if pss_with_sign[0] not in '~-': pss_with_sign = '+' + pss_with_sign - pss_field = '{} ({}->{})'.format(pss_with_sign, b, a) + pss_field = '{} ({}->{})'.format( + pss_with_sign, _FormatPss(b), _FormatPss(a)) elif sym.num_aliases > 1: pss_field = '{} (size={})'.format(_FormatPss(sym.pss), sym.size) else:
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d9373ed..7fbe92c0 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -18773,7 +18773,9 @@ <int value="1" label="Transaction begin"/> <int value="2" label="Meta table init"/> <int value="3" label="Create tables"/> - <int value="4" label="Version check and migration (check History.MigrateFailureToVersion)"/> + <int value="4" + label="Version check and migration (check + History.MigrateFailureToVersion)"/> <int value="5" label="Commit"/> </enum> @@ -29797,10 +29799,12 @@ <int value="0" label="Timestamp shown"/> <int value="1" label="Timestamp not shown because the preview was not stale"/> <int value="2" - label="Timestamp not shown because the staleness was negative."/> + label="Timestamp not shown because the staleness was negative"/> <int value="3" label="Timestamp not shown because the staleness was greater than the max"/> + <int value="4" + label="Timestamp shown indicating the page was just updated on reload"/> </enum> <enum name="PreviewsUserOptedOut">
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 11f19bc..57d8554 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -413,5 +413,17 @@ def SetExpectations(self): self.PermanentlyDisableBenchmark( [story.expectations.ANDROID_NEXUS5X], 'crbug.com/702319') + self.DisableStory( + 'v1-large-deep-layout.html', + [story.expectations.ANDROID_ONE], + 'crbug.com/736512') + self.DisableStory( + 'v1-large-deep-distribution.html', + [story.expectations.ANDROID_ONE], + 'crbug.com/736512') + self.DisableStory( + 'v1-distribution-disconnected-and-reconnected.html', + [story.expectations.ANDROID_ONE], + 'crbug.com/736512') return StoryExpectations()
diff --git a/tools/perf/benchmarks/memory.py b/tools/perf/benchmarks/memory.py index 7cfa093..cea629c 100644 --- a/tools/perf/benchmarks/memory.py +++ b/tools/perf/benchmarks/memory.py
@@ -53,6 +53,7 @@ @benchmark.Enabled('mac') @benchmark.Enabled('win') +@benchmark.Disabled('android') @benchmark.Owner(emails=['erikchen@chromium.org']) class MemoryBenchmarkTrivialSitesDesktop(_MemoryInfra): """Measure memory usage on trivial sites."""
diff --git a/tools/perf/page_sets/service_worker.py b/tools/perf/page_sets/service_worker.py index 060d5ad2..84af0bd 100644 --- a/tools/perf/page_sets/service_worker.py +++ b/tools/perf/page_sets/service_worker.py
@@ -44,4 +44,6 @@ class ServiceWorkerStoryExpectations(story.expectations.StoryExpectations): def SetExpectations(self): - pass # Nothing disabled. + self.DisableStory('first_load', + [story.expectations.ANDROID_ONE], + 'crbug.com/736518')
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc index 1a71df4..f563009 100644 --- a/ui/app_list/app_list_constants.cc +++ b/ui/app_list/app_list_constants.cc
@@ -147,6 +147,9 @@ const char kSearchResultDistanceFromOrigin[] = "Apps.AppListSearchResultDistanceFromOrigin"; +// The height of tiles in search result. +const int kSearchTileHeight = 92; + gfx::ShadowValue GetShadowForZHeight(int z_height) { if (z_height <= 0) return gfx::ShadowValue();
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h index f615589..ee16eb0 100644 --- a/ui/app_list/app_list_constants.h +++ b/ui/app_list/app_list_constants.h
@@ -100,6 +100,8 @@ APP_LIST_EXPORT extern const char kSearchQueryLength[]; APP_LIST_EXPORT extern const char kSearchResultDistanceFromOrigin[]; +APP_LIST_EXPORT extern const int kSearchTileHeight; + // Returns the shadow values for a view at |z_height|. APP_LIST_EXPORT gfx::ShadowValue GetShadowForZHeight(int z_height);
diff --git a/ui/app_list/search_result.h b/ui/app_list/search_result.h index c88751d..afa0054 100644 --- a/ui/app_list/search_result.h +++ b/ui/app_list/search_result.h
@@ -49,6 +49,16 @@ DISPLAY_TYPE_LAST, }; + // Type of the search result. This should be set in corresponding subclass's + // constructor. + enum ResultType { + RESULT_UNKNOWN, // Unknown type. + RESULT_INSTALLED_APP, // Installed apps. + RESULT_PLAYSTORE_APP, // Uninstalled apps from playstore. + RESULT_INSTANT_APP, // Instant apps. + // Add new values here. + }; + // A tagged range in search result text. struct APP_LIST_EXPORT Tag { // Similar to ACMatchClassification::Style, the style values are not @@ -135,6 +145,9 @@ display_type_ = display_type; } + ResultType result_type() const { return result_type_; } + void set_result_type(ResultType result_type) { result_type_ = result_type; } + int distance_from_origin() { return distance_from_origin_; } void set_distance_from_origin(int distance) { distance_from_origin_ = distance; @@ -223,6 +236,8 @@ double relevance_ = 0; DisplayType display_type_ = DISPLAY_LIST; + ResultType result_type_ = RESULT_UNKNOWN; + // The Manhattan distance from the origin of all search results to this // result. This is logged for UMA. int distance_from_origin_ = -1;
diff --git a/ui/app_list/views/search_result_tile_item_list_view.cc b/ui/app_list/views/search_result_tile_item_list_view.cc index 446d700..344db2a 100644 --- a/ui/app_list/views/search_result_tile_item_list_view.cc +++ b/ui/app_list/views/search_result_tile_item_list_view.cc
@@ -15,6 +15,7 @@ #include "ui/gfx/geometry/insets.h" #include "ui/views/background.h" #include "ui/views/border.h" +#include "ui/views/controls/separator.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/layout/box_layout.h" @@ -27,9 +28,14 @@ constexpr int kTopBottomPadding = 8; // Layout constants used when fullscreen app list feature is enabled. +constexpr size_t kMaxNumSearchResultTiles = 6; constexpr int kItemListVerticalSpacing = 16; constexpr int kItemListHorizontalSpacing = 12; constexpr int kBetweenItemSpacing = 8; +constexpr int kSeparatorLeftRightPadding = 4; +constexpr int kSeparatorHeight = 36; + +constexpr SkColor kSeparatorColor = SkColorSetARGBMacro(0x1F, 0x00, 0x00, 0x00); } // namespace @@ -45,22 +51,36 @@ views::BoxLayout::kHorizontal, gfx::Insets(kItemListVerticalSpacing, kItemListHorizontalSpacing), kBetweenItemSpacing)); + for (size_t i = 0; i < kMaxNumSearchResultTiles; ++i) { + views::Separator* separator = new views::Separator; + separator->SetVisible(false); + separator->SetBorder(views::CreateEmptyBorder( + 0, kSeparatorLeftRightPadding, kSearchTileHeight - kSeparatorHeight, + kSeparatorLeftRightPadding)); + separator->SetColor(kSeparatorColor); + + separator_views_.push_back(separator); + AddChildView(separator); + + SearchResultTileItemView* tile_item = + new SearchResultTileItemView(this, view_delegate); + tile_item->SetParentBackgroundColor(kCardBackgroundColor); + tile_views_.push_back(tile_item); + AddChildView(tile_item); + } } else { SetLayoutManager(new views::BoxLayout( views::BoxLayout::kHorizontal, gfx::Insets(0, kHorizontalBorderSpacing), kBetweenTileSpacing)); - } - - for (size_t i = 0; i < kNumSearchResultTiles; ++i) { - SearchResultTileItemView* tile_item = - new SearchResultTileItemView(this, view_delegate); - tile_item->SetParentBackgroundColor(kCardBackgroundColor); - if (!is_fullscreen_app_list_enabled_) { + for (size_t i = 0; i < kNumSearchResultTiles; ++i) { + SearchResultTileItemView* tile_item = + new SearchResultTileItemView(this, view_delegate); + tile_item->SetParentBackgroundColor(kCardBackgroundColor); tile_item->SetBorder( views::CreateEmptyBorder(kTopBottomPadding, 0, kTopBottomPadding, 0)); + tile_views_.push_back(tile_item); + AddChildView(tile_item); } - tile_views_.push_back(tile_item); - AddChildView(tile_item); } } @@ -92,11 +112,42 @@ int SearchResultTileItemListView::DoUpdate() { std::vector<SearchResult*> display_results = AppListModel::FilterSearchResultsByDisplayType( - results(), SearchResult::DISPLAY_TILE, kNumSearchResultTiles); - for (size_t i = 0; i < kNumSearchResultTiles; ++i) { - SearchResult* item = - i < display_results.size() ? display_results[i] : nullptr; - tile_views_[i]->SetSearchResult(item); + results(), SearchResult::DISPLAY_TILE, + is_fullscreen_app_list_enabled_ ? kMaxNumSearchResultTiles + : kNumSearchResultTiles); + + if (is_fullscreen_app_list_enabled_) { + SearchResult::ResultType previous_type = SearchResult::RESULT_UNKNOWN; + + for (size_t i = 0; i < kMaxNumSearchResultTiles; ++i) { + if (i >= display_results.size()) { + separator_views_[i]->SetVisible(false); + tile_views_[i]->SetSearchResult(nullptr); + continue; + } + + SearchResult* item = display_results[i]; + tile_views_[i]->SetSearchResult(item); + + if (i > 0 && item->result_type() != previous_type) { + // Add a separator to separate search results of different types. + // The strategy here is to only add a separator only if current search + // result type is different from the previous one. The strategy is + // based on the assumption that the search results are already + // separated in groups based on their result types. + separator_views_[i]->SetVisible(true); + } else { + separator_views_[i]->SetVisible(false); + } + + previous_type = item->result_type(); + } + } else { + for (size_t i = 0; i < kNumSearchResultTiles; ++i) { + SearchResult* item = + i < display_results.size() ? display_results[i] : nullptr; + tile_views_[i]->SetSearchResult(item); + } } set_container_score(
diff --git a/ui/app_list/views/search_result_tile_item_list_view.h b/ui/app_list/views/search_result_tile_item_list_view.h index d5f9c2f..2b306be 100644 --- a/ui/app_list/views/search_result_tile_item_list_view.h +++ b/ui/app_list/views/search_result_tile_item_list_view.h
@@ -12,6 +12,7 @@ namespace views { class Textfield; +class Separator; } namespace app_list { @@ -43,6 +44,8 @@ std::vector<SearchResultTileItemView*> tile_views_; + std::vector<views::Separator*> separator_views_; + views::Textfield* search_box_; // Owned by the views hierarchy. // Whether the fullscreen app list feature is enabled.
diff --git a/ui/app_list/views/search_result_tile_item_view.cc b/ui/app_list/views/search_result_tile_item_view.cc index b5705e48..70c8e26 100644 --- a/ui/app_list/views/search_result_tile_item_view.cc +++ b/ui/app_list/views/search_result_tile_item_view.cc
@@ -19,7 +19,6 @@ namespace { constexpr int kSearchTileWidth = 80; -constexpr int kSearchTileHeight = 92; constexpr int kSearchTileTopPadding = 4; constexpr int kSearchTitleSpacing = 6;
diff --git a/ui/aura/mus/DEPS b/ui/aura/mus/DEPS index 1fae0da..c447b50 100644 --- a/ui/aura/mus/DEPS +++ b/ui/aura/mus/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+cc/base/switches.h", - "+cc/ipc/mojo_compositor_frame_sink.mojom.h", + "+cc/ipc/compositor_frame_sink.mojom.h", "+cc/output/layer_tree_frame_sink_client.h", "+cc/output/layer_tree_frame_sink.h", "+cc/scheduler/begin_frame_source.h",
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc index 2902086..77d34df 100644 --- a/ui/aura/mus/window_port_mus.cc +++ b/ui/aura/mus/window_port_mus.cc
@@ -100,11 +100,11 @@ WindowPortMus::RequestLayerTreeFrameSink( scoped_refptr<cc::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { - cc::mojom::MojoCompositorFrameSinkPtrInfo sink_info; - cc::mojom::MojoCompositorFrameSinkRequest sink_request = + cc::mojom::CompositorFrameSinkPtrInfo sink_info; + cc::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink_info); - cc::mojom::MojoCompositorFrameSinkClientPtr client; - cc::mojom::MojoCompositorFrameSinkClientRequest client_request = + cc::mojom::CompositorFrameSinkClientPtr client; + cc::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&client); constexpr bool enable_surface_synchronization = true; auto layer_tree_frame_sink = base::MakeUnique<viz::ClientLayerTreeFrameSink>(
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index fb078bc..a92650e 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -367,8 +367,8 @@ void WindowTreeClient::AttachCompositorFrameSink( Id window_id, - cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink, - cc::mojom::MojoCompositorFrameSinkClientPtr client) { + cc::mojom::CompositorFrameSinkRequest compositor_frame_sink, + cc::mojom::CompositorFrameSinkClientPtr client) { DCHECK(tree_); tree_->AttachCompositorFrameSink(window_id, std::move(compositor_frame_sink), std::move(client));
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h index 3bcc36d8a..65935b9 100644 --- a/ui/aura/mus/window_tree_client.h +++ b/ui/aura/mus/window_tree_client.h
@@ -155,8 +155,8 @@ void AttachCompositorFrameSink( Id window_id, - cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink, - cc::mojom::MojoCompositorFrameSinkClientPtr client); + cc::mojom::CompositorFrameSinkRequest compositor_frame_sink, + cc::mojom::CompositorFrameSinkClientPtr client); bool IsRoot(WindowMus* window) const { return roots_.count(window) > 0; }
diff --git a/ui/aura/mus/window_tree_host_mus.cc b/ui/aura/mus/window_tree_host_mus.cc index 5e60905..eeecd66 100644 --- a/ui/aura/mus/window_tree_host_mus.cc +++ b/ui/aura/mus/window_tree_host_mus.cc
@@ -193,11 +193,6 @@ OnHostCloseRequested(); } -gfx::ICCProfile WindowTreeHostMus::GetICCProfileForCurrentDisplay() { - // TODO: This should read the profile from mus. crbug.com/647510 - return gfx::ICCProfile(); -} - void WindowTreeHostMus::MoveCursorToScreenLocationInPixels( const gfx::Point& location_in_pixels) { gfx::Point screen_location_in_pixels = location_in_pixels;
diff --git a/ui/aura/mus/window_tree_host_mus.h b/ui/aura/mus/window_tree_host_mus.h index ee7eba1..764a7b0e9 100644 --- a/ui/aura/mus/window_tree_host_mus.h +++ b/ui/aura/mus/window_tree_host_mus.h
@@ -96,7 +96,6 @@ void OnClosed() override; void OnActivationChanged(bool active) override; void OnCloseRequest() override; - gfx::ICCProfile GetICCProfileForCurrentDisplay() override; void MoveCursorToScreenLocationInPixels( const gfx::Point& location_in_pixels) override;
diff --git a/ui/aura/test/mus/test_window_tree.cc b/ui/aura/test/mus/test_window_tree.cc index a20c1eb..5d8dc3f1 100644 --- a/ui/aura/test/mus/test_window_tree.cc +++ b/ui/aura/test/mus/test_window_tree.cc
@@ -187,8 +187,8 @@ void TestWindowTree::AttachCompositorFrameSink( uint32_t window_id, - mojo::InterfaceRequest<cc::mojom::MojoCompositorFrameSink> surface, - cc::mojom::MojoCompositorFrameSinkClientPtr client) {} + mojo::InterfaceRequest<cc::mojom::CompositorFrameSink> surface, + cc::mojom::CompositorFrameSinkClientPtr client) {} void TestWindowTree::AddWindow(uint32_t change_id, uint32_t parent,
diff --git a/ui/aura/test/mus/test_window_tree.h b/ui/aura/test/mus/test_window_tree.h index 13fed01..c73cec1 100644 --- a/ui/aura/test/mus/test_window_tree.h +++ b/ui/aura/test/mus/test_window_tree.h
@@ -149,8 +149,8 @@ float opacity) override; void AttachCompositorFrameSink( uint32_t window_id, - mojo::InterfaceRequest<cc::mojom::MojoCompositorFrameSink> surface, - cc::mojom::MojoCompositorFrameSinkClientPtr client) override; + mojo::InterfaceRequest<cc::mojom::CompositorFrameSink> surface, + cc::mojom::CompositorFrameSinkClientPtr client) override; void AddWindow(uint32_t change_id, uint32_t parent, uint32_t child) override; void RemoveWindowFromParent(uint32_t change_id, uint32_t window_id) override; void AddTransientWindow(uint32_t change_id,
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index 5bf1eb1..f8a6519 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc
@@ -37,10 +37,6 @@ const char kWindowTreeHostForAcceleratedWidget[] = "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__"; -float GetDeviceScaleFactorFromDisplay(Window* window) { - return ui::GetScaleFactorForNativeView(window); -} - //////////////////////////////////////////////////////////////////////////////// // WindowTreeHost, public: @@ -278,10 +274,12 @@ } void WindowTreeHost::InitCompositor() { - compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), + display::Display display = + display::Screen::GetScreen()->GetDisplayNearestWindow(window()); + compositor_->SetScaleAndSize(display.device_scale_factor(), GetBoundsInPixels().size()); compositor_->SetRootLayer(window()->layer()); - compositor_->SetDisplayColorProfile(GetICCProfileForCurrentDisplay()); + compositor_->SetDisplayColorSpace(display.color_space()); } void WindowTreeHost::OnAcceleratedWidgetAvailable() { @@ -306,7 +304,7 @@ output_surface_padding_in_pixels_.height()); // The compositor should have the same size as the native root window host. // Get the latest scale from display because it might have been changed. - compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), + compositor_->SetScaleAndSize(ui::GetScaleFactorForNativeView(window()), adjusted_size); gfx::Size layer_size = GetBoundsInPixels().size(); @@ -337,12 +335,6 @@ capture_window->ReleaseCapture(); } -gfx::ICCProfile WindowTreeHost::GetICCProfileForCurrentDisplay() { - // TODO(hubbe): Get the color space from the *current* monitor and - // update it when window is moved or color space configuration changes. - return gfx::ICCProfile::FromBestMonitor(); -} - ui::EventSink* WindowTreeHost::GetEventSink() { return dispatcher_.get(); }
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index f2aa248f..0d5e7d4 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -20,7 +20,6 @@ #include "ui/gfx/native_widget_types.h" namespace gfx { -class ICCProfile; class Insets; class Point; class Rect; @@ -225,8 +224,6 @@ // Hides the WindowTreeHost. virtual void HideImpl() = 0; - virtual gfx::ICCProfile GetICCProfileForCurrentDisplay(); - // Overridden from ui::EventSource: ui::EventSink* GetEventSink() override;
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 4303f63..01c52ef 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -316,14 +316,14 @@ } } -void Compositor::SetDisplayColorProfile(const gfx::ICCProfile& icc_profile) { - blending_color_space_ = icc_profile.GetColorSpace(); +void Compositor::SetDisplayColorSpace(const gfx::ColorSpace& color_space) { + blending_color_space_ = color_space; output_color_space_ = blending_color_space_; if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR)) { blending_color_space_ = gfx::ColorSpace::CreateExtendedSRGB(); output_color_space_ = gfx::ColorSpace::CreateSCRGBLinear(); } - host_->SetRasterColorSpace(icc_profile.GetParametricColorSpace()); + host_->SetRasterColorSpace(color_space.GetParametricApproximation()); // Color space is reset when the output surface is lost, so this must also be // updated then. // TODO(fsamuel): Get rid of this.
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 9c72fc4..205c66b 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -246,7 +246,7 @@ void SetScaleAndSize(float scale, const gfx::Size& size_in_pixel); // Set the output color profile into which this compositor should render. - void SetDisplayColorProfile(const gfx::ICCProfile& icc_profile); + void SetDisplayColorSpace(const gfx::ColorSpace& color_space); // Returns the size of the widget that is being drawn to in pixel coordinates. const gfx::Size& size() const { return size_; }
diff --git a/ui/display/display.cc b/ui/display/display.cc index 4ec8ea0..a86c7203 100644 --- a/ui/display/display.cc +++ b/ui/display/display.cc
@@ -16,6 +16,7 @@ #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/icc_profile.h" namespace display { namespace { @@ -57,6 +58,12 @@ int64_t internal_display_id_ = -1; +gfx::ColorSpace GetForcedColorSpace() { + if (gfx::ICCProfile::HasForcedProfile()) + return gfx::ICCProfile::GetForcedProfile().GetColorSpace(); + return gfx::ColorSpace::CreateSRGB(); +} + } // namespace bool CompareDisplayIds(int64_t id1, int64_t id2) { @@ -108,6 +115,7 @@ bounds_(bounds), work_area_(bounds), device_scale_factor_(GetForcedDeviceScaleFactor()), + color_space_(GetForcedColorSpace()), color_depth_(DEFAULT_BITS_PER_PIXEL), depth_per_component_(DEFAULT_BITS_PER_COMPONENT) { if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR)) {
diff --git a/ui/display/display.h b/ui/display/display.h index 2f30a59..f5c92899 100644 --- a/ui/display/display.h +++ b/ui/display/display.h
@@ -11,8 +11,8 @@ #include "mojo/public/cpp/bindings/struct_traits.h" #include "ui/display/display_export.h" #include "ui/display/types/display_constants.h" +#include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect.h" -#include "ui/gfx/icc_profile.h" namespace display { @@ -184,10 +184,10 @@ maximum_cursor_size_ = size; } - // The full ICC profile of the display. - gfx::ICCProfile icc_profile() const { return icc_profile_; } - void set_icc_profile(const gfx::ICCProfile& icc_profile) { - icc_profile_ = icc_profile; + // The full color space of the display. + gfx::ColorSpace color_space() const { return color_space_; } + void set_color_space(const gfx::ColorSpace& color_space) { + color_space_ = color_space; } // The number of bits per pixel. Used by media query APIs. @@ -226,7 +226,7 @@ gfx::Size maximum_cursor_size_; // NOTE: this is not currently written to the mojom as it is not used in // aura. - gfx::ICCProfile icc_profile_; + gfx::ColorSpace color_space_; int color_depth_; int depth_per_component_; bool is_monochrome_ = false;
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm index d9d07345..0b8c32a 100644 --- a/ui/display/mac/screen_mac.mm +++ b/ui/display/mac/screen_mac.mm
@@ -20,6 +20,7 @@ #include "ui/display/display.h" #include "ui/display/display_change_notifier.h" #include "ui/gfx/color_space_switches.h" +#include "ui/gfx/icc_profile.h" #include "ui/gfx/mac/coordinate_conversion.h" extern "C" { @@ -88,7 +89,8 @@ if (base::mac::IsAtLeastOS10_12() && !color_correct_rendering_enabled) color_space = base::mac::GetSystemColorSpace(); - display.set_icc_profile(gfx::ICCProfile::FromCGColorSpace(color_space)); + display.set_color_space( + gfx::ICCProfile::FromCGColorSpace(color_space).GetColorSpace()); display.set_color_depth(NSBitsPerPixelFromDepth([screen depth])); display.set_depth_per_component(NSBitsPerSampleFromDepth([screen depth])); display.set_is_monochrome(CGDisplayUsesForceToGray());
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc index 8b436cc2..f585989 100644 --- a/ui/display/win/screen_win.cc +++ b/ui/display/win/screen_win.cc
@@ -25,6 +25,7 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d.h" +#include "ui/gfx/icc_profile.h" namespace display { namespace win { @@ -89,6 +90,11 @@ display.set_bounds(gfx::ScaleToEnclosingRect(display_info.screen_rect(), 1.0f / scale_factor)); display.set_rotation(display_info.rotation()); + + // TODO(ccameron): Populate this based on this specific display. + // http://crbug.com/735613 + display.set_color_space(gfx::ICCProfile::FromBestMonitor().GetColorSpace()); + return display; }
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc index 8cb06ac..2c0ae682 100644 --- a/ui/gfx/color_space.cc +++ b/ui/gfx/color_space.cc
@@ -158,6 +158,25 @@ transfer_ == TransferID::IEC61966_2_4; } +bool ColorSpace::IsParametric() const { + return primaries_ != PrimaryID::ICC_BASED && + transfer_ != TransferID::ICC_BASED; +} + +ColorSpace ColorSpace::GetParametricApproximation() const { + // If this is parametric already, return it directly. + if (IsParametric()) + return *this; + + // Query the ICC profile, if available, for the parametric approximation. + ICCProfile icc_profile; + if (GetICCProfile(&icc_profile)) + return icc_profile.GetParametricColorSpace(); + + // Fall back to sRGB if the ICC profile is no longer cached. + return CreateSRGB(); +} + bool ColorSpace::operator!=(const ColorSpace& other) const { return !(*this == other); }
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h index 813d7d808..5819c5fe 100644 --- a/ui/gfx/color_space.h +++ b/ui/gfx/color_space.h
@@ -160,6 +160,12 @@ // Returns true if the encoded values can be outside of the 0.0-1.0 range. bool FullRangeEncodedValues() const; + // Returns true if this color space can be represented parametrically. + bool IsParametric() const; + // Return a parametric approximation of this color space (if it is not already + // parametric). + gfx::ColorSpace GetParametricApproximation() const; + // Return this color space with any range adjust or YUV to RGB conversion // stripped off. gfx::ColorSpace GetAsFullRangeRGB() const;
diff --git a/ui/gfx/icc_profile.cc b/ui/gfx/icc_profile.cc index a8d643d..c57eb526 100644 --- a/ui/gfx/icc_profile.cc +++ b/ui/gfx/icc_profile.cc
@@ -104,7 +104,8 @@ return icc_profile; } -#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(USE_X11) +#if (!defined(OS_WIN) && !defined(USE_X11) && !defined(OS_MACOSX)) || \ + defined(OS_IOS) // static ICCProfile ICCProfile::FromBestMonitor() { if (HasForcedProfile())
diff --git a/ui/gfx/icc_profile.h b/ui/gfx/icc_profile.h index 07f6fcb..691d2f69 100644 --- a/ui/gfx/icc_profile.h +++ b/ui/gfx/icc_profile.h
@@ -57,6 +57,11 @@ // Create directly from profile data. static ICCProfile FromData(const void* icc_profile, size_t size); + // TODO(ccameron): Move this flag to display::Display, like forcing device + // scale factor. + static bool HasForcedProfile(); + static ICCProfile GetForcedProfile(); + // Return a ColorSpace that references this ICCProfile. ColorTransforms // created using this ColorSpace will match this ICCProfile precisely. const ColorSpace& GetColorSpace() const; @@ -103,9 +108,6 @@ size_t size, uint64_t id); - static bool HasForcedProfile(); - static ICCProfile GetForcedProfile(); - void ComputeColorSpaceAndCache(); // This globally identifies this ICC profile. It is used to look up this ICC
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc index d7b8a33..55ed1a94 100644 --- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -26,6 +26,7 @@ #include "ui/gfx/font_render_params.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/icc_profile.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_types.h" @@ -374,6 +375,11 @@ if (is_primary_display) primary_display_index_ = displays.size(); + // TODO(ccameron): Populate this based on this specific display. + // http://crbug.com/735613 + display.set_color_space( + gfx::ICCProfile::FromBestMonitor().GetColorSpace()); + displays.push_back(display); } }
diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html index dfca072..1b1bbe4 100644 --- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html +++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html
@@ -54,13 +54,14 @@ opacity: 1; } - :host ::content .drawer-header { + .drawer-header { -webkit-padding-start: 24px; align-items: center; border-bottom: var(--cr-separator-line); display: flex; font-size: 123.08%; /* go to 16px from 13px */ min-height: 56px; + outline: none; } :host ::content .drawer-content { @@ -69,6 +70,7 @@ } </style> <div id="container" on-tap="onContainerTap_"> + <div class="drawer-header" tabindex="-1">[[title]]</div> <content></content> </div> </template>
diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.js b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.js index 2676734..5a8b56bf 100644 --- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.js +++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.js
@@ -7,6 +7,8 @@ extends: 'dialog', properties: { + title: String, + /** Enables notifications for |Dialog.open|. */ open: { type: Boolean,