diff --git a/AUTHORS b/AUTHORS index 84b49da..cba67225 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -225,6 +225,7 @@ Franklin Ta <fta2012@gmail.com> Frédéric Jacob <frederic.jacob.78@gmail.com> Frédéric Wang <fred.wang@free.fr> +Fu Junwei <junwei.fu@intel.com> Gaetano Mendola <mendola@gmail.com> Gajendra N <gajendra.n@samsung.com> Gajendra Singh <wxjg68@motorola.com>
diff --git a/DEPS b/DEPS index 4c30044..bc5aac6 100644 --- a/DEPS +++ b/DEPS
@@ -40,7 +40,7 @@ # 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': '5aa9158a24bc0bd27db7d740e4ec07f6aa64f060', + 'skia_revision': '54d212e1bfaea0be88c3c40820d0b1ae0daebecf', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '32b94557c605f02fa969bc84b3c9b6f5277c258e', + 'pdfium_revision': '742fa8c3b39f0e3713c3450b1f9979174fbb4c8f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -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': '84775f4ca78a0be205752065afdbd44432555a1b', + 'catapult_revision': '8cbbd7f6c6207e388918855a3536c5b7f30bff29', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc index a0e3871..5f44b673 100644 --- a/base/metrics/persistent_histogram_allocator.cc +++ b/base/metrics/persistent_histogram_allocator.cc
@@ -785,24 +785,6 @@ #endif // !defined(OS_NACL) // static -void GlobalHistogramAllocator::CreateWithSharedMemory( - std::unique_ptr<SharedMemory> memory, - size_t size, - uint64_t id, - StringPiece name) { - if ((!memory->memory() && !memory->Map(size)) || - !SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(*memory)) { - NOTREACHED(); - return; - } - - DCHECK_LE(memory->mapped_size(), size); - Set(WrapUnique( - new GlobalHistogramAllocator(MakeUnique<SharedPersistentMemoryAllocator>( - std::move(memory), 0, StringPiece(), /*readonly=*/false)))); -} - -// static void GlobalHistogramAllocator::CreateWithSharedMemoryHandle( const SharedMemoryHandle& handle, size_t size) {
diff --git a/base/metrics/persistent_histogram_allocator.h b/base/metrics/persistent_histogram_allocator.h index 2eb28dfa..851d7ef 100644 --- a/base/metrics/persistent_histogram_allocator.h +++ b/base/metrics/persistent_histogram_allocator.h
@@ -431,15 +431,6 @@ FilePath* out_active_path); #endif - // Create a global allocator using a block of shared |memory| of the - // specified |size|. The allocator takes ownership of the shared memory - // and releases it upon destruction, though the memory will continue to - // live if other processes have access to it. - static void CreateWithSharedMemory(std::unique_ptr<SharedMemory> memory, - size_t size, - uint64_t id, - StringPiece name); - // Create a global allocator using a block of shared memory accessed // through the given |handle| and |size|. The allocator takes ownership // of the handle and closes it upon destruction, though the memory will
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 74e3f19..0419926d 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -302,13 +302,20 @@ # Linux/Android common flags setup. # --------------------------------- if (is_linux || is_android) { + if (use_pic) { + cflags += [ + "-fPIC", + ] + ldflags += [ + "-fPIC", + ] + } + cflags += [ - "-fPIC", "-pipe", # Use pipes for communicating between sub-processes. Faster. ] ldflags += [ - "-fPIC", "-Wl,-z,noexecstack", "-Wl,-z,now", "-Wl,-z,relro",
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 787990a..66c65e05 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -58,6 +58,9 @@ # # See crbug.com/669854. linkrepro_root_dir = "" + + # Whether or not we should use position independent code. + use_pic = true } declare_args() {
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index 3819e7e..695e85d 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc
@@ -25,6 +25,8 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/transform.h" +namespace { + static gfx::Transform OrthoProjectionMatrix(float left, float right, float bottom, @@ -62,6 +64,13 @@ return canvas; } +// Switching between enabling DC layers and not is expensive, so only +// switch away after a large number of frames not needing DC layers have +// been produced. +constexpr int kNumberOfFramesBeforeDisablingDCLayers = 60; + +} // namespace + namespace cc { DirectRenderer::DrawingFrame::DrawingFrame() = default; @@ -87,8 +96,8 @@ if (context_provider) { if (context_provider->ContextCapabilities().commit_overlay_planes) allow_empty_swap_ = true; - if (context_provider->ContextCapabilities().set_draw_rectangle) - use_set_draw_rectangle_ = true; + if (context_provider->ContextCapabilities().dc_layers) + supports_dc_layers_ = true; } initialized_ = true; @@ -314,6 +323,19 @@ ¤t_frame()->dc_layer_overlay_list, ¤t_frame()->root_damage_rect, ¤t_frame()->root_content_bounds); + bool was_using_dc_layers = using_dc_layers_; + if (!current_frame()->dc_layer_overlay_list.empty()) { + DCHECK(supports_dc_layers_); + using_dc_layers_ = true; + frames_since_using_dc_layers_ = 0; + } else if (++frames_since_using_dc_layers_ >= + kNumberOfFramesBeforeDisablingDCLayers) { + using_dc_layers_ = false; + } + if (was_using_dc_layers != using_dc_layers_) { + current_frame()->root_damage_rect = + current_frame()->root_render_pass->output_rect; + } // We can skip all drawing if the damage rect is now empty. bool skip_drawing_root_render_pass = @@ -523,7 +545,7 @@ // outside the damage rectangle, even if the damage rectangle is the size of // the full backbuffer. bool render_pass_is_clipped = - (use_set_draw_rectangle_ && is_root_render_pass) || + (supports_dc_layers_ && is_root_render_pass) || !render_pass_scissor_in_draw_space.Contains(surface_rect_in_draw_space); bool has_external_stencil_test = is_root_render_pass && output_surface_->HasExternalStencilTest(); @@ -597,8 +619,10 @@ if (render_pass == current_frame()->root_render_pass) { BindFramebufferToOutputSurface(); - if (use_set_draw_rectangle_) + if (supports_dc_layers_) { + SetEnableDCLayers(using_dc_layers_); output_surface_->SetDrawRectangle(current_frame()->root_damage_rect); + } InitializeViewport(current_frame(), render_pass->output_rect, gfx::Rect(current_frame()->device_viewport_size), current_frame()->device_viewport_size);
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h index eb8ddab3..70632063 100644 --- a/cc/output/direct_renderer.h +++ b/cc/output/direct_renderer.h
@@ -166,6 +166,7 @@ virtual void DidChangeVisibility() = 0; virtual void CopyCurrentRenderPassToBitmap( std::unique_ptr<CopyOutputRequest> request) = 0; + virtual void SetEnableDCLayers(bool enable) = 0; gfx::Size surface_size_for_swap_buffers() const { return reshape_surface_size_; @@ -184,8 +185,14 @@ bool use_partial_swap_ = false; // Whether overdraw feedback is enabled and can be used. bool overdraw_feedback_ = false; - // Whether the SetDrawRectangle command is in use. - bool use_set_draw_rectangle_ = false; + // Whether the SetDrawRectangle and EnableDCLayers commands are in + // use. + bool supports_dc_layers_ = false; + // Whether the output surface is actually using DirectComposition. + bool using_dc_layers_ = false; + // This counts the number of draws since the last time + // DirectComposition layers needed to be used. + int frames_since_using_dc_layers_ = 0; // TODO(danakj): Just use a vector of pairs here? Hash map is way overkill. std::unordered_map<int, std::unique_ptr<ScopedResource>>
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index d3d4851..809bbdd 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc
@@ -2464,6 +2464,10 @@ FlushTextureQuadCache(SHARED_BINDING); } +void GLRenderer::SetEnableDCLayers(bool enable) { + gl_->SetEnableDCLayersCHROMIUM(enable); +} + bool GLRenderer::FlippedFramebuffer() const { if (force_drawing_frame_framebuffer_unflipped_) return false;
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h index 8e6f9d6..682a3d7ca 100644 --- a/cc/output/gl_renderer.h +++ b/cc/output/gl_renderer.h
@@ -100,6 +100,7 @@ void EnsureScissorTestDisabled() override; void CopyCurrentRenderPassToBitmap( std::unique_ptr<CopyOutputRequest> request) override; + void SetEnableDCLayers(bool enable) override; void FinishDrawingQuadList() override; // Returns true if quad requires antialiasing and false otherwise.
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index 39929f4..fd5faa1 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc
@@ -1641,8 +1641,7 @@ // Returns true if draw quads can be represented as CALayers (Mac only). MOCK_METHOD0(AllowCALayerOverlays, bool()); - - bool AllowDCLayerOverlays() override { return false; } + MOCK_METHOD0(AllowDCLayerOverlays, bool()); // A list of possible overlay candidates is presented to this function. // The expected result is that those candidates that can be in a separate @@ -1733,6 +1732,7 @@ // list because the render pass is cleaned up by DrawFrame. EXPECT_CALL(*processor->strategy_, Attempt(_, _, _, _)).Times(0); EXPECT_CALL(*validator, AllowCALayerOverlays()).Times(0); + EXPECT_CALL(*validator, AllowDCLayerOverlays()).Times(0); DrawFrame(&renderer, viewport_size); Mock::VerifyAndClearExpectations(processor->strategy_); Mock::VerifyAndClearExpectations(validator.get()); @@ -1752,6 +1752,9 @@ EXPECT_CALL(*validator, AllowCALayerOverlays()) .Times(1) .WillOnce(::testing::Return(false)); + EXPECT_CALL(*validator, AllowDCLayerOverlays()) + .Times(1) + .WillOnce(::testing::Return(false)); EXPECT_CALL(*processor->strategy_, Attempt(_, _, _, _)).Times(1); DrawFrame(&renderer, viewport_size); @@ -1904,20 +1907,21 @@ class PartialSwapMockGLES2Interface : public TestGLES2Interface { public: - explicit PartialSwapMockGLES2Interface(bool support_set_draw_rectangle) - : support_set_draw_rectangle_(support_set_draw_rectangle) {} + explicit PartialSwapMockGLES2Interface(bool support_dc_layers) + : support_dc_layers_(support_dc_layers) {} void InitializeTestContext(TestWebGraphicsContext3D* context) override { context->set_have_post_sub_buffer(true); - context->set_support_set_draw_rectangle(support_set_draw_rectangle_); + context->set_enable_dc_layers(support_dc_layers_); } MOCK_METHOD1(Enable, void(GLenum cap)); MOCK_METHOD1(Disable, void(GLenum cap)); MOCK_METHOD4(Scissor, void(GLint x, GLint y, GLsizei width, GLsizei height)); + MOCK_METHOD1(SetEnableDCLayersCHROMIUM, void(GLboolean enable)); private: - bool support_set_draw_rectangle_; + bool support_dc_layers_; }; class GLRendererPartialSwapTest : public GLRendererTest { @@ -2016,6 +2020,103 @@ RunTest(false, true); } +class DCLayerValidator : public OverlayCandidateValidator { + public: + void GetStrategies(OverlayProcessor::StrategyList* strategies) override {} + bool AllowCALayerOverlays() override { return false; } + bool AllowDCLayerOverlays() override { return true; } + void CheckOverlaySupport(OverlayCandidateList* surfaces) override {} +}; + +// Test that SetEnableDCLayersCHROMIUM is properly called when enabling +// and disabling DC layers. +TEST_F(GLRendererTest, DCLayerOverlaySwitch) { + auto gl_owned = base::MakeUnique<PartialSwapMockGLES2Interface>(true); + auto* gl = gl_owned.get(); + + auto provider = TestContextProvider::Create(std::move(gl_owned)); + provider->BindToCurrentThread(); + + FakeOutputSurfaceClient output_surface_client; + std::unique_ptr<FakeOutputSurface> output_surface( + FakeOutputSurface::Create3d(std::move(provider))); + output_surface->BindToClient(&output_surface_client); + + std::unique_ptr<ResourceProvider> resource_provider = + FakeResourceProvider::Create(output_surface->context_provider(), nullptr); + + RendererSettings settings; + settings.partial_swap_enabled = true; + FakeRendererGL renderer(&settings, output_surface.get(), + resource_provider.get()); + renderer.Initialize(); + renderer.SetVisible(true); + TestOverlayProcessor* processor = + new TestOverlayProcessor(output_surface.get()); + processor->Initialize(); + renderer.SetOverlayProcessor(processor); + std::unique_ptr<DCLayerValidator> validator(new DCLayerValidator); + output_surface->SetOverlayCandidateValidator(validator.get()); + + gfx::Size viewport_size(100, 100); + + TextureMailbox mailbox = + TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), GL_TEXTURE_2D, + gfx::Size(256, 256), true, false); + std::unique_ptr<SingleReleaseCallbackImpl> release_callback = + SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); + ResourceId resource_id = resource_provider->CreateResourceFromTextureMailbox( + mailbox, std::move(release_callback)); + + for (int i = 0; i < 65; i++) { + int root_pass_id = 1; + RenderPass* root_pass = AddRenderPass( + &render_passes_in_draw_order_, root_pass_id, gfx::Rect(viewport_size), + gfx::Transform(), FilterOperations()); + if (i == 0) { + gfx::Rect rect(0, 0, 100, 100); + gfx::RectF tex_coord_rect(0, 0, 1, 1); + SharedQuadState* shared_state = + root_pass->CreateAndAppendSharedQuadState(); + shared_state->SetAll(gfx::Transform(), rect.size(), rect, rect, false, 1, + SkBlendMode::kSrcOver, 0); + YUVVideoDrawQuad* quad = + root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); + quad->SetNew(shared_state, rect, rect, rect, tex_coord_rect, + tex_coord_rect, rect.size(), rect.size(), resource_id, + resource_id, resource_id, resource_id, + YUVVideoDrawQuad::REC_601, gfx::ColorSpace(), 0, 1.0, 8); + } + + // A bunch of initialization that happens. + EXPECT_CALL(*gl, Disable(_)).Times(AnyNumber()); + EXPECT_CALL(*gl, Enable(_)).Times(AnyNumber()); + EXPECT_CALL(*gl, Scissor(_, _, _, _)).Times(AnyNumber()); + + // Partial frame, we should use a scissor to swap only that part when + // partial swap is enabled. + root_pass->damage_rect = gfx::Rect(2, 2, 3, 3); + // Frame 0 should be completely damaged because it's the first. + // Frame 1 should be because it changed. Frame 60 should be + // because it's disabling DC layers. + gfx::Rect output_rectangle = (i == 0 || i == 1 || i == 60) + ? root_pass->output_rect + : root_pass->damage_rect; + + // Frame 0 should have DC Layers enabled because of the overlay. + // After 60 frames of no overlays DC layers should be disabled again. + if (i < 60) + EXPECT_CALL(*gl, SetEnableDCLayersCHROMIUM(GL_TRUE)); + else + EXPECT_CALL(*gl, SetEnableDCLayersCHROMIUM(GL_FALSE)); + + renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_); + DrawFrame(&renderer, viewport_size); + EXPECT_EQ(output_rectangle, output_surface->last_set_draw_rectangle()); + testing::Mock::VerifyAndClearExpectations(gl); + } +} + class GLRendererWithMockContextTest : public ::testing::Test { protected: class MockContextSupport : public TestContextSupport {
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h index 35165f75..d1715cb 100644 --- a/cc/output/output_surface.h +++ b/cc/output/output_surface.h
@@ -84,8 +84,8 @@ virtual void BindFramebuffer() = 0; // Marks that the given rectangle will be drawn to on the default, bound - // framebuffer. Only valid for surfaces with set_draw_rectangle in the - // context capabilities. + // framebuffer. Only valid for surfaces with dc_layers in the context + // capabilities. virtual void SetDrawRectangle(const gfx::Rect& rect) = 0; // Get the class capable of informing cc of hardware overlay capability.
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index c39672c..8bd1e381 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc
@@ -583,6 +583,10 @@ request->SendBitmapResult(std::move(bitmap)); } +void SoftwareRenderer::SetEnableDCLayers(bool enable) { + NOTIMPLEMENTED(); +} + void SoftwareRenderer::DidChangeVisibility() { if (visible_) output_surface_->EnsureBackbuffer();
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h index 7349a6e..c7204ad 100644 --- a/cc/output/software_renderer.h +++ b/cc/output/software_renderer.h
@@ -51,6 +51,7 @@ void EnsureScissorTestDisabled() override; void CopyCurrentRenderPassToBitmap( std::unique_ptr<CopyOutputRequest> request) override; + void SetEnableDCLayers(bool enable) override; void DidChangeVisibility() override; private:
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index c16db55..233c067e 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h
@@ -347,8 +347,8 @@ void set_gpu_rasterization(bool gpu_rasterization) { test_capabilities_.gpu_rasterization = gpu_rasterization; } - void set_support_set_draw_rectangle(bool support) { - test_capabilities_.set_draw_rectangle = support; + void set_enable_dc_layers(bool support) { + test_capabilities_.dc_layers = support; } // When this context is lost, all contexts in its share group are also lost.
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 7975234..00a7a89 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -213,6 +213,7 @@ "//services/service_manager/public/interfaces:interfaces_java", "//services/service_manager/public/java:service_manager_java", "//services/shape_detection/public/interfaces:interfaces_java", + "//skia/public/interfaces:interfaces_java", "//third_party/WebKit/public:android_mojo_bindings_java", "//third_party/WebKit/public:blink_headers_java", "//third_party/WebKit/public:mojo_bindings_java",
diff --git a/chrome/android/java/res/layout/data_reduction_promo_screen.xml b/chrome/android/java/res/layout/data_reduction_promo_screen.xml deleted file mode 100644 index 8370f8e..0000000 --- a/chrome/android/java/res/layout/data_reduction_promo_screen.xml +++ /dev/null
@@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2015 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:chrome="http://schemas.android.com/apk/res-auto" - android:background="#c000" > - - <RelativeLayout - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_gravity="center" - android:background="#FFFF" > - - <LinearLayout - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_alignParentTop="true" - android:orientation="vertical" > - - <ScrollView - android:id="@+id/data_reduction_promo_scroll" - android:layout_height="0dp" - android:layout_width="match_parent" - android:layout_weight="1" - android:fillViewport="true" - android:requiresFadingEdge="vertical" - android:fadingEdgeLength="20dp" > - - <LinearLayout - android:id="@+id/data_reduction_promo_content" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:paddingEnd="24dp" - android:paddingStart="24dp" - android:paddingTop="64dp" > - - <ImageView - android:id="@+id/data_reduction_illustration" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_gravity="center" - android:adjustViewBounds="true" - android:contentDescription="@null" - android:src="@drawable/data_reduction_illustration" /> - - <LinearLayout - android:id="@+id/text_wrapper" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:orientation="vertical" > - - <TextView - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_marginBottom="8dp" - android:text="@string/data_reduction_promo_title" - android:textColor="@color/default_text_color" - android:textSize="@dimen/data_reduction_promo_title_text_size" /> - - <TextView - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_marginBottom="30dp" - android:lineSpacingMultiplier="1.3" - android:text="@string/data_reduction_promo_summary" - android:textColor="#646464" - android:textSize="@dimen/data_reduction_promo_normal_text_size" /> - </LinearLayout> - </LinearLayout> - </ScrollView> - - <LinearLayout - android:id="@+id/data_reduction_promo_buttons" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:orientation="horizontal" - android:clipToPadding="false" - android:padding="16dp" - android:gravity="end" > - - <Button - android:id="@+id/no_thanks_button" - android:layout_height="match_parent" - android:layout_width="wrap_content" - android:layout_marginEnd="8dp" - android:minHeight="40dp" - android:text="@string/no_thanks" - android:textColor="@color/light_normal_color" - android:textSize="@dimen/data_reduction_promo_button_text_size" - style="@style/ButtonCompatBorderless" /> - - <org.chromium.ui.widget.ButtonCompat - android:id="@+id/enable_button" - android:layout_height="match_parent" - android:layout_width="wrap_content" - android:elevation="0dp" - android:minHeight="40dp" - android:text="@string/data_reduction_enable_button" - android:textColor="#FFFFFF" - android:textSize="@dimen/data_reduction_promo_button_text_size" - chrome:buttonColor="@color/light_active_color" /> - </LinearLayout> - </LinearLayout> - - <org.chromium.chrome.browser.widget.TintedImageButton - android:id="@+id/close_button" - android:layout_height="56dp" - android:layout_width="56dp" - android:layout_alignParentEnd="true" - android:layout_alignParentTop="true" - android:background="?android:attr/selectableItemBackground" - android:contentDescription="@string/close" - android:src="@drawable/btn_close" /> - - </RelativeLayout> -</org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoView>
diff --git a/chrome/android/java/res/layout/promo_dialog_layout.xml b/chrome/android/java/res/layout/promo_dialog_layout.xml new file mode 100644 index 0000000..a6aff720 --- /dev/null +++ b/chrome/android/java/res/layout/promo_dialog_layout.xml
@@ -0,0 +1,85 @@ +<?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. --> + +<!-- This XML should not be inflated by anything except PromoDialog.java. + + This layout is deeply nested to account for the various bits having to flop orientations + in landscape. If these become more frequently used, we should investigate optimizing the + layout. +--> +<merge xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto" > + + <org.chromium.chrome.browser.widget.PromoDialogLayout + android:id="@+id/promo_dialog_layout" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="vertical" + android:background="@drawable/menu_bg" + chrome:maxWidth="@dimen/promo_dialog_max_width" > + + <org.chromium.chrome.browser.widget.FadingEdgeScrollView + android:id="@+id/promo_container" + android:layout_width="wrap_content" + android:layout_height="0dp" + android:layout_weight="1" > + + <!-- This layout pivots when the dialog is wider than it is tall. --> + <LinearLayout + android:id="@+id/promo_content" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="@dimen/promo_dialog_padding" + android:gravity="center" + android:orientation="vertical" > + + <ImageView + android:id="@+id/illustration" + android:layout_width="@dimen/promo_dialog_illustration_width" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_margin="@dimen/promo_dialog_illustration_margin" + android:scaleType="fitCenter" + android:contentDescription="@null" /> + + <org.chromium.chrome.browser.widget.BoundedLinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + chrome:maxWidth="@dimen/promo_dialog_max_content_width" > + + <TextView + android:id="@+id/header" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="14dp" + android:textColor="@color/default_text_color" + android:textSize="@dimen/promo_dialog_title_text_size" /> + + <TextView + android:id="@+id/subheader" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:lineSpacingMultiplier="1.3" + android:textColor="#646464" + android:textSize="@dimen/promo_dialog_normal_text_size" /> + </org.chromium.chrome.browser.widget.BoundedLinearLayout> + </LinearLayout> + + </org.chromium.chrome.browser.widget.FadingEdgeScrollView> + + <org.chromium.chrome.browser.widget.DualControlLayout + android:id="@+id/button_bar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:padding="@dimen/promo_dialog_padding" + chrome:buttonAlignment="end" + chrome:stackedMargin="@dimen/infobar_padding" /> + + </org.chromium.chrome.browser.widget.PromoDialogLayout> + +</merge>
diff --git a/chrome/android/java/res/layout/search_engine_promo.xml b/chrome/android/java/res/layout/search_engine_promo.xml deleted file mode 100644 index bfd03fbe..0000000 --- a/chrome/android/java/res/layout/search_engine_promo.xml +++ /dev/null
@@ -1,79 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2016 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:chrome="http://schemas.android.com/apk/res-auto" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="#FAFAFA" > - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="10dp" - android:orientation="vertical" - android:padding="20dp" > - - <ImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:layout_margin="22dp" - android:contentDescription="@null" - android:src="@drawable/search_sogou" /> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="14dp" - android:text="@string/search_with_sogou" - android:textColor="@color/default_text_color" - android:textSize="16sp" /> - - <TextView - android:id="@+id/description" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="30dp" - android:lineSpacingMultiplier="1.3" - android:textColor="#646464" - android:textSize="14sp" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:clipToPadding="false" - android:gravity="end" - android:orientation="horizontal" > - - <Button - android:id="@+id/keep_google_button" - style="@style/ButtonCompatBorderless" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginEnd="8dp" - android:minHeight="40dp" - android:text="@string/keep_google" - android:textAllCaps="true" - android:textColor="@color/light_active_color" - android:textSize="13sp" /> - - <org.chromium.ui.widget.ButtonCompat - android:id="@+id/ok_button" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:elevation="0dp" - android:minHeight="30dp" - android:text="@string/ok" - android:textAllCaps="true" - android:textColor="#FFFFFF" - android:textSize="13sp" - chrome:buttonColor="@color/light_active_color" - chrome:buttonRaised="false" /> - </LinearLayout> - </LinearLayout> - -</ScrollView> \ No newline at end of file
diff --git a/chrome/android/java/res/values-sw600dp/dimens.xml b/chrome/android/java/res/values-sw600dp/dimens.xml index 3a75891..bb92312 100644 --- a/chrome/android/java/res/values-sw600dp/dimens.xml +++ b/chrome/android/java/res/values-sw600dp/dimens.xml
@@ -17,8 +17,6 @@ <!-- Data Saver --> <dimen name="data_usage_chart_height">325dp</dimen> - <dimen name="data_reduction_promo_screen_width">382dp</dimen> - <dimen name="data_reduction_promo_illustration_margin_bottom">62dp</dimen> <!-- Tab Strip Dimensions --> <dimen name="tab_strip_height">40dp</dimen>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index c550e0c..89936ce 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -294,8 +294,8 @@ <item name="android:windowEnterAnimation">@anim/fullscreen_notification_in</item> </style> - <!-- Data Saver --> - <style name="DataReductionPromoScreenDialog" > + <!-- Promo dialogs --> + <style name="PromoDialog" > <item name="android:background">@android:color/transparent</item> <item name="android:backgroundDimEnabled">false</item> <item name="android:clipChildren">false</item> @@ -310,6 +310,7 @@ <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> </style> + <!-- Cast and media playback notifications --> <style name="MediaNotificationTitle"
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index d156c87..241c4ae 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -30,6 +30,7 @@ <color name="semi_opaque_white">#80ffffff</color> <color name="toolbar_light_tint">#A3000000</color> <color name="light_grey">#ccc</color> + <color name="modal_dialog_scrim_color">#7f000000</color> <!-- Infobar colors --> <color name="infobar_accent_blue">#4285f4</color> @@ -189,7 +190,6 @@ <color name="bottom_bar_shadow_color">#1d000000</color> <!-- Payments UI colors --> - <color name="payments_ui_scrim">#000000</color> <color name="payments_section_edit_background">#f5f5f5</color> <color name="payments_section_chevron">#b2b2b2</color> <color name="payments_section_separator">#e0e0e0</color>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index eb14fca..07eaf696 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -131,14 +131,17 @@ <!-- Minimum height/width for a touchable item --> <dimen name="min_touch_target_size">48dp</dimen> + <!-- Promo dialogs --> + <dimen name="promo_dialog_illustration_margin">24dp</dimen> + <dimen name="promo_dialog_illustration_width">150dp</dimen> + <dimen name="promo_dialog_padding">16dp</dimen> + <dimen name="promo_dialog_max_width">600dp</dimen> + <dimen name="promo_dialog_max_content_width">320dp</dimen> + <dimen name="promo_dialog_title_text_size">23sp</dimen> + <dimen name="promo_dialog_normal_text_size">14sp</dimen> + <!-- Data Saver --> <dimen name="data_usage_chart_height">252dp</dimen> - <dimen name="data_reduction_promo_screen_width">330dp</dimen> - <dimen name="data_reduction_promo_screen_width_horizontal">500dp</dimen> - <dimen name="data_reduction_promo_title_text_size">20sp</dimen> - <dimen name="data_reduction_promo_normal_text_size">14sp</dimen> - <dimen name="data_reduction_promo_button_text_size">13sp</dimen> - <dimen name="data_reduction_promo_illustration_margin_bottom">30dp</dimen> <!-- The size of the text for tab titles. --> <dimen name="compositor_tab_title_text_size">13sp</dimen> @@ -381,7 +384,6 @@ <dimen name="payments_section_largest_spacing">32dp</dimen> <dimen name="payments_section_checking_spacing">6dp</dimen> <dimen name="payments_section_descriptive_item_spacing">40dp</dimen> - <dimen name="payments_section_separator_height">1dp</dimen> <dimen name="payments_section_logo_width">38dp</dimen> <dimen name="payments_section_add_button_height">48dp</dimen> <dimen name="payments_ui_max_dialog_width">0dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java index 371d303..2f2b57a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java
@@ -211,6 +211,15 @@ int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); if (status == DownloadManager.STATUS_SUCCESSFUL) { downloadStatus = DownloadManagerService.DOWNLOAD_STATUS_COMPLETE; + if (mDownloadItem.getDownloadInfo().getFileName() == null) { + DownloadInfo info = + DownloadInfo.Builder + .fromDownloadInfo(mDownloadItem.getDownloadInfo()) + .setFileName(c.getString( + c.getColumnIndex(DownloadManager.COLUMN_TITLE))) + .build(); + mDownloadItem.setDownloadInfo(info); + } if (mShowNotifications) { canResolve = DownloadManagerService.isOMADownloadDescription( mDownloadItem.getDownloadInfo())
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index c1c51ac..d6a0faf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -137,6 +137,15 @@ // Flag to track if we need to post a task to update download notifications. private boolean mIsUIUpdateScheduled; private int mAutoResumptionLimit = -1; + private DownloadManagerRequestInterceptor mDownloadManagerRequestInterceptor; + + /** + * Interface to intercept download request to Android DownloadManager. This is implemented by + * tests so that we don't need to actually enqueue a download into the Android DownloadManager. + */ + static interface DownloadManagerRequestInterceptor { + void interceptDownloadRequest(DownloadItem item, boolean notifyComplete); + } /** * Class representing progress of a download. @@ -243,10 +252,13 @@ } @VisibleForTesting - protected DownloadManagerService(Context context, - DownloadNotifier downloadNotifier, - Handler handler, - long updateDelayInMillis) { + void setDownloadManagerRequestInterceptor(DownloadManagerRequestInterceptor interceptor) { + mDownloadManagerRequestInterceptor = interceptor; + } + + @VisibleForTesting + protected DownloadManagerService(Context context, DownloadNotifier downloadNotifier, + Handler handler, long updateDelayInMillis) { mContext = context; mSharedPrefs = ContextUtils.getAppSharedPreferences(); // Clean up unused shared prefs. TODO(qinmin): remove this after M61. @@ -855,6 +867,10 @@ */ public void enqueueDownloadManagerRequest( final DownloadItem item, boolean notifyCompleted) { + if (mDownloadManagerRequestInterceptor != null) { + mDownloadManagerRequestInterceptor.interceptDownloadRequest(item, notifyCompleted); + return; + } EnqueueDownloadRequestTask task = new EnqueueDownloadRequestTask(item); task.execute(notifyCompleted); } @@ -891,10 +907,12 @@ request.setMimeType(info.getMimeType()); try { if (notifyCompleted) { - // Set downloaded file destination to /sdcard/Download or, should it be - // set to one of several Environment.DIRECTORY* dirs depending on mimetype? - request.setDestinationInExternalPublicDir( - Environment.DIRECTORY_DOWNLOADS, info.getFileName()); + if (info.getFileName() != null) { + // Set downloaded file destination to /sdcard/Download or, should it be + // set to one of several Environment.DIRECTORY* dirs depending on mimetype? + request.setDestinationInExternalPublicDir( + Environment.DIRECTORY_DOWNLOADS, info.getFileName()); + } } else { File dir = new File(mContext.getExternalFilesDir(null), DOWNLOAD_DIRECTORY); if (dir.mkdir() || dir.isDirectory()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java index 19658cf9..4e6c623 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java
@@ -171,7 +171,7 @@ return false; } - new SearchEnginePromoDialog(context, this).show(); + new SogouPromoDialog(context, this).show(); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/SearchEnginePromoDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java similarity index 72% rename from chrome/android/java/src/org/chromium/chrome/browser/locale/SearchEnginePromoDialog.java rename to chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java index ced1b25e..cddcab9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/locale/SearchEnginePromoDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java
@@ -4,10 +4,8 @@ package org.chromium.chrome.browser.locale; -import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.os.Bundle; import android.support.annotation.IntDef; @@ -23,6 +21,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.chrome.browser.preferences.SearchEnginePreference; +import org.chromium.chrome.browser.widget.PromoDialog; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; import org.chromium.ui.text.SpanApplier.SpanInfo; @@ -33,8 +32,7 @@ /** * A promotion dialog showing that the default search provider will be set to Sogou. */ -public class SearchEnginePromoDialog extends Dialog - implements View.OnClickListener, OnDismissListener { +public class SogouPromoDialog extends PromoDialog { // These constants are here to back a uma histogram. Append new constants at the end of this // list (do not rearrange) and don't forget to update CHOICE_ENUM_COUNT. @Retention(RetentionPolicy.SOURCE) @@ -52,53 +50,61 @@ @Override public void onClick(View widget) { mChoice = CHOICE_SETTINGS; - Intent intent = PreferencesLauncher.createIntentForSettingsPage(getContext(), - SearchEnginePreference.class.getName()); + Intent intent = PreferencesLauncher.createIntentForSettingsPage( + getContext(), SearchEnginePreference.class.getName()); getContext().startActivity(intent); dismiss(); } }; - @UserChoice private int mChoice = CHOICE_BACK_KEY; + @UserChoice + private int mChoice = CHOICE_BACK_KEY; /** * Creates an instance of the dialog. */ - public SearchEnginePromoDialog(Context context, LocaleManager localeManager) { - super(context, R.style.SimpleDialog); + public SogouPromoDialog(Context context, LocaleManager localeManager) { + super(context); mLocaleManager = localeManager; setOnDismissListener(this); setCanceledOnTouchOutside(false); } @Override + protected DialogParams getDialogParams() { + PromoDialog.DialogParams params = new PromoDialog.DialogParams(); + params.drawableResource = R.drawable.search_sogou; + params.headerStringResource = R.string.search_with_sogou; + params.subheaderStringResource = R.string.sogou_explanation; + params.primaryButtonStringResource = R.string.ok; + params.secondaryButtonStringResource = R.string.keep_google; + return params; + } + + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Do not allow this dialog to be reconstructed because it requires native side loaded. if (savedInstanceState != null) { dismiss(); return; } - setContentView(R.layout.search_engine_promo); - View keepGoogleButton = findViewById(R.id.keep_google_button); - View okButton = findViewById(R.id.ok_button); - keepGoogleButton.setOnClickListener(this); - okButton.setOnClickListener(this); - - TextView textView = (TextView) findViewById(R.id.description); + StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD); + TextView textView = (TextView) findViewById(R.id.subheader); SpannableString description = SpanApplier.applySpans( getContext().getString(R.string.sogou_explanation), - new SpanInfo("<link>", "</link>", mSpan), - new SpanInfo("<b>", "</b>", new StyleSpan(android.graphics.Typeface.BOLD))); + new SpanInfo("<link>", "</link>", mSpan), new SpanInfo("<b>", "</b>", boldSpan)); textView.setText(description); textView.setMovementMethod(LinkMovementMethod.getInstance()); } @Override public void onClick(View view) { - if (view.getId() == R.id.keep_google_button) { + if (view.getId() == R.id.button_secondary) { mChoice = CHOICE_KEEP_GOOGLE; - } else if (view.getId() == R.id.ok_button) { + } else if (view.getId() == R.id.button_primary) { mChoice = CHOICE_USE_SOGOU; } else { assert false : "Not handled click."; @@ -131,9 +137,11 @@ default: assert false : "Unexpected choice"; } - ContextUtils.getAppSharedPreferences().edit() - .putBoolean(LocaleManager.PREF_PROMO_SHOWN, true).apply(); - RecordHistogram.recordEnumeratedHistogram("SpecialLocale.PromotionDialog", mChoice, - CHOICE_ENUM_COUNT); + ContextUtils.getAppSharedPreferences() + .edit() + .putBoolean(LocaleManager.PREF_PROMO_SHOWN, true) + .apply(); + RecordHistogram.recordEnumeratedHistogram( + "SpecialLocale.PromotionDialog", mChoice, CHOICE_ENUM_COUNT); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java index 491e92e0..a6e4df9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -1441,9 +1441,9 @@ Resources resources = parent.getContext().getResources(); setBackgroundColor(ApiCompatibilityUtils.getColor( resources, R.color.payments_section_separator)); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, - resources.getDimensionPixelSize(R.dimen.payments_section_separator_height)); + LinearLayout.LayoutParams params = + new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, + resources.getDimensionPixelSize(R.dimen.separator_height)); int margin = resources.getDimensionPixelSize(R.dimen.payments_section_large_spacing); ApiCompatibilityUtils.setMarginStart(params, margin);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java index 3e17036..39363f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -427,8 +427,8 @@ // requires exploration of how interactions would work when the dialog can be sent back and // forth between the peeking and expanded state. mFullContainer = new FrameLayout(mContext); - mFullContainer.setBackgroundColor( - ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.payments_ui_scrim)); + mFullContainer.setBackgroundColor(ApiCompatibilityUtils.getColor( + mContext.getResources(), R.color.modal_dialog_scrim_color)); FrameLayout.LayoutParams bottomSheetParams = new FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); bottomSheetParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; @@ -1229,7 +1229,7 @@ mRequestView.removeOnLayoutChangeListener(this); Animator scrimFader = ObjectAnimator.ofInt(mFullContainer.getBackground(), - AnimatorProperties.DRAWABLE_ALPHA_PROPERTY, 0, 127); + AnimatorProperties.DRAWABLE_ALPHA_PROPERTY, 0, 255); Animator alphaAnimator = ObjectAnimator.ofFloat(mFullContainer, View.ALPHA, 0f, 1f); AnimatorSet alphaSet = new AnimatorSet();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java index 0c10d0b8..818e58e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java
@@ -5,35 +5,22 @@ package org.chromium.chrome.browser.preferences.datareduction; import android.app.Activity; -import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.LinearLayout.LayoutParams; import org.chromium.chrome.R; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; +import org.chromium.chrome.browser.widget.PromoDialog; import org.chromium.ui.widget.Toast; /** * The promo screen encouraging users to enable Data Saver. */ -public class DataReductionPromoScreen extends Dialog implements View.OnClickListener, - DialogInterface.OnDismissListener { +public class DataReductionPromoScreen extends PromoDialog { private int mState; - private static View getContentView(Context context) { - LayoutInflater inflater = (LayoutInflater) context.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - return inflater.inflate(R.layout.data_reduction_promo_screen, null); - } - /** * Launch the data reduction promo, if it needs to be displayed. */ @@ -58,53 +45,30 @@ * @param context An Android context. */ public DataReductionPromoScreen(Context context) { - super(context, R.style.DataReductionPromoScreenDialog); - setContentView(getContentView(context), new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); - - // Remove the shadow from the enable button. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - Button enableButton = (Button) findViewById(R.id.enable_button); - enableButton.setStateListAnimator(null); - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Keep the window full screen otherwise the flip animation will frame-skip. - getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - - addListenerOnButton(); - + super(context); mState = DataReductionProxyUma.ACTION_DISMISSED; } - private void addListenerOnButton() { - int [] interactiveViewIds = new int[] { - R.id.no_thanks_button, - R.id.enable_button, - R.id.close_button - }; - - for (int interactiveViewId : interactiveViewIds) { - findViewById(interactiveViewId).setOnClickListener(this); - } + @Override + protected DialogParams getDialogParams() { + PromoDialog.DialogParams params = new PromoDialog.DialogParams(); + params.drawableResource = R.drawable.data_reduction_illustration; + params.headerStringResource = R.string.data_reduction_promo_title; + params.subheaderStringResource = R.string.data_reduction_promo_summary; + params.primaryButtonStringResource = R.string.data_reduction_enable_button; + params.secondaryButtonStringResource = R.string.no_thanks; + return params; } - @Override public void onClick(View v) { int id = v.getId(); - if (id == R.id.no_thanks_button) { - handleCloseButtonPressed(); - } else if (id == R.id.enable_button) { + if (id == R.id.button_secondary) { + dismiss(); + } else if (id == R.id.button_primary) { mState = DataReductionProxyUma.ACTION_ENABLED; handleEnableButtonPressed(); - } else if (id == R.id.close_button) { - handleCloseButtonPressed(); } else { assert false : "Unhandled onClick event"; } @@ -123,10 +87,6 @@ Toast.LENGTH_LONG).show(); } - private void handleCloseButtonPressed() { - dismiss(); - } - @Override public void dismiss() { if (mState < DataReductionProxyUma.ACTION_INDEX_BOUNDARY) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoView.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoView.java deleted file mode 100644 index 093d455..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoView.java +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.preferences.datareduction; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.view.View.MeasureSpec; -import android.widget.LinearLayout; - -import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.widget.PaddedFrameLayout; - -/** - * View that handles orientation changes for the Data Reduction Proxy promo. When the width is - * greater than the height, switches the promo content view from vertical to horizontal and moves - * the illustration from the top of the text to the side of the text. - */ -public class DataReductionPromoView extends PaddedFrameLayout { - - private static final int ILLUSTRATION_HORIZONTAL_PADDING_DP = 24; - private static final int FRAME_HEIGHT_MARGIN_DP = 30; - - private View mIllustration; - private LinearLayout mPromoContent; - private int mMaxChildWidth; - private int mMaxChildWidthHorizontal; - private int mIllustrationPaddingBottom; - private int mIllustrationPaddingSide; - private int mFrameHeightMargin; - - public DataReductionPromoView(Context context, AttributeSet attrs) { - super(context, attrs); - mMaxChildWidth = getResources() - .getDimensionPixelSize(R.dimen.data_reduction_promo_screen_width); - mMaxChildWidthHorizontal = getResources() - .getDimensionPixelSize(R.dimen.data_reduction_promo_screen_width_horizontal); - mIllustrationPaddingBottom = getResources() - .getDimensionPixelSize(R.dimen.data_reduction_promo_illustration_margin_bottom); - float density = getResources().getDisplayMetrics().density; - mIllustrationPaddingSide = (int) (ILLUSTRATION_HORIZONTAL_PADDING_DP * density + 0.5f); - mFrameHeightMargin = (int) (FRAME_HEIGHT_MARGIN_DP * density + 0.5f); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mIllustration = findViewById(R.id.data_reduction_illustration); - mPromoContent = (LinearLayout) findViewById(R.id.data_reduction_promo_content); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = MeasureSpec.getSize(widthMeasureSpec); - int height = MeasureSpec.getSize(heightMeasureSpec); - - if (width >= 2 * mIllustration.getWidth() && width > height) { - mPromoContent.setOrientation(LinearLayout.HORIZONTAL); - setMaxChildWidth(mMaxChildWidthHorizontal); - ApiCompatibilityUtils.setPaddingRelative( - mIllustration, 0, 0, mIllustrationPaddingSide, 0); - } else { - mPromoContent.setOrientation(LinearLayout.VERTICAL); - setMaxChildWidth(mMaxChildWidth); - mIllustration.setPadding(0, 0, 0, mIllustrationPaddingBottom); - } - - setMaxChildHeight(height - mFrameHeightMargin); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/BarcodeDetectionImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/BarcodeDetectionImpl.java index 6d46e5f..f7d8f73 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/BarcodeDetectionImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/BarcodeDetectionImpl.java
@@ -20,11 +20,10 @@ import org.chromium.gfx.mojom.PointF; import org.chromium.gfx.mojom.RectF; import org.chromium.mojo.system.MojoException; -import org.chromium.mojo.system.SharedBufferHandle; -import org.chromium.mojo.system.SharedBufferHandle.MapFlags; import org.chromium.services.service_manager.InterfaceFactory; import org.chromium.shape_detection.mojom.BarcodeDetection; import org.chromium.shape_detection.mojom.BarcodeDetectionResult; +import org.chromium.skia.mojom.ColorType; import java.nio.ByteBuffer; @@ -43,8 +42,7 @@ } @Override - public void detect( - SharedBufferHandle frameData, int width, int height, DetectResponse callback) { + public void detect(org.chromium.skia.mojom.Bitmap bitmapData, DetectResponse callback) { if (!ExternalAuthUtils.getInstance().canUseGooglePlayServices( mContext, new UserRecoverableErrorHandler.Silent())) { Log.e(TAG, "Google Play Services not available"); @@ -61,9 +59,21 @@ return; } + // TODO(junwei.fu): Consider supporting other bitmap pixel formats, + // https://crbug.com/684921. + if (bitmapData.colorType != ColorType.RGBA_8888 + && bitmapData.colorType != ColorType.BGRA_8888) { + Log.e(TAG, "Unsupported bitmap pixel format"); + callback.call(new BarcodeDetectionResult[0]); + return; + } + + int width = bitmapData.width; + int height = bitmapData.height; final long numPixels = (long) width * height; // TODO(mcasas): https://crbug.com/670028 homogeneize overflow checking. - if (!frameData.isValid() || width <= 0 || height <= 0 || numPixels > (Long.MAX_VALUE / 4)) { + if (bitmapData.pixelData == null || width <= 0 || height <= 0 + || numPixels > (Long.MAX_VALUE / 4)) { callback.call(new BarcodeDetectionResult[0]); return; } @@ -71,7 +81,7 @@ // Mapping |frameData| will fail if the intended mapped size is larger // than its actual capacity, which is limited by the appropriate // mojo::edk::Configuration entry. - ByteBuffer imageBuffer = frameData.map(0, numPixels * 4, MapFlags.none()); + ByteBuffer imageBuffer = ByteBuffer.wrap(bitmapData.pixelData); if (imageBuffer.capacity() <= 0) { callback.call(new BarcodeDetectionResult[0]); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/TextDetectionImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/TextDetectionImpl.java index 2f4fab0..6af95153 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/TextDetectionImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/shapedetection/TextDetectionImpl.java
@@ -18,11 +18,10 @@ import org.chromium.chrome.browser.externalauth.UserRecoverableErrorHandler; import org.chromium.gfx.mojom.RectF; import org.chromium.mojo.system.MojoException; -import org.chromium.mojo.system.SharedBufferHandle; -import org.chromium.mojo.system.SharedBufferHandle.MapFlags; import org.chromium.services.service_manager.InterfaceFactory; import org.chromium.shape_detection.mojom.TextDetection; import org.chromium.shape_detection.mojom.TextDetectionResult; +import org.chromium.skia.mojom.ColorType; import java.nio.ByteBuffer; @@ -41,8 +40,7 @@ } @Override - public void detect( - SharedBufferHandle frameData, int width, int height, DetectResponse callback) { + public void detect(org.chromium.skia.mojom.Bitmap bitmapData, DetectResponse callback) { if (!ExternalAuthUtils.getInstance().canUseGooglePlayServices( mContext, new UserRecoverableErrorHandler.Silent())) { Log.e(TAG, "Google Play Services not available"); @@ -59,9 +57,21 @@ return; } + // TODO(junwei.fu): Consider supporting other bitmap pixel formats, + // https://crbug.com/684921. + if (bitmapData.colorType != ColorType.RGBA_8888 + && bitmapData.colorType != ColorType.BGRA_8888) { + Log.e(TAG, "Unsupported bitmap pixel format"); + callback.call(new TextDetectionResult[0]); + return; + } + + int width = bitmapData.width; + int height = bitmapData.height; final long numPixels = (long) width * height; // TODO(xianglu): https://crbug.com/670028 homogeneize overflow checking. - if (!frameData.isValid() || width <= 0 || height <= 0 || numPixels > (Long.MAX_VALUE / 4)) { + if (bitmapData.pixelData == null || width <= 0 || height <= 0 + || numPixels > (Long.MAX_VALUE / 4)) { callback.call(new TextDetectionResult[0]); return; } @@ -69,7 +79,7 @@ // Mapping |frameData| will fail if the intended mapped size is larger // than its actual capacity, which is limited by the appropriate // mojo::edk::Configuration entry. - ByteBuffer imageBuffer = frameData.map(0, numPixels * 4, MapFlags.none()); + ByteBuffer imageBuffer = ByteBuffer.wrap(bitmapData.pixelData); if (imageBuffer.capacity() <= 0) { callback.call(new TextDetectionResult[0]); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java index ab7b35181..653d42a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
@@ -94,10 +94,10 @@ mTabCreationState = creationState; mLastTabStateChangeMillis = System.currentTimeMillis(); - if (mTabCreationState == TabCreationState.LIVE_IN_FOREGROUND - || mTabCreationState == TabCreationState.FROZEN_ON_RESTORE) { + if (mTabCreationState == TabCreationState.LIVE_IN_FOREGROUND) { updateTabState(TAB_STATE_ACTIVE); } else if (mTabCreationState == TabCreationState.LIVE_IN_BACKGROUND + || mTabCreationState == TabCreationState.FROZEN_ON_RESTORE || mTabCreationState == TabCreationState.FROZEN_FOR_LAZY_LOAD) { updateTabState(TAB_STATE_INACTIVE); } else if (mTabCreationState == TabCreationState.FROZEN_ON_RESTORE_FAILED) { @@ -196,6 +196,9 @@ * @param newState New state of the tab. */ void updateTabState(int newState) { + if (mLastTabState == newState) { + return; + } long now = System.currentTimeMillis(); recordTabStateTransition(mLastTabState, newState, now - mLastTabStateChangeMillis); mLastTabStateChangeMillis = now;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java new file mode 100644 index 0000000..f1abf4f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java
@@ -0,0 +1,79 @@ +// 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.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.FrameLayout; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.chrome.R; + +/** + * Generic builder for promo dialogs. + */ +public abstract class PromoDialog + extends Dialog implements View.OnClickListener, DialogInterface.OnDismissListener { + /** Parameters that can be used to create a new PromoDialog. */ + public static class DialogParams { + /** Optional: Resource ID of the Drawable to use for the promo illustration. */ + public int drawableResource; + + /** Resource ID of the String to show as the promo title. */ + public int headerStringResource; + + /** Optional: Resource ID of the String to show as descriptive text. */ + public int subheaderStringResource; + + /** Optional: Resource ID of the String to show on the primary/ok button. */ + public int primaryButtonStringResource; + + /** Optional: Resource ID of the String to show on the secondary/cancel button. */ + public int secondaryButtonStringResource; + } + + private static final int[] CLICKABLE_BUTTON_IDS = {R.id.button_primary, R.id.button_secondary}; + + private final FrameLayout mScrimView; + private final PromoDialogLayout mDialogLayout; + + protected PromoDialog(Context context) { + super(context, R.style.PromoDialog); + + mScrimView = new FrameLayout(context); + mScrimView.setBackgroundColor(ApiCompatibilityUtils.getColor( + context.getResources(), R.color.modal_dialog_scrim_color)); + LayoutInflater.from(context).inflate(R.layout.promo_dialog_layout, mScrimView, true); + + mDialogLayout = (PromoDialogLayout) mScrimView.findViewById(R.id.promo_dialog_layout); + mDialogLayout.initialize(getDialogParams()); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(mScrimView); + + // Force the window to allow the dialog contents be as wide as necessary. + getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + // Connect all the buttons to this class. + for (int interactiveViewId : CLICKABLE_BUTTON_IDS) { + View view = findViewById(interactiveViewId); + if (view != null) view.setOnClickListener(this); + } + } + + @Override + public void onClick(View view) {} + + /** Returns a set of {@link DialogParams} that define what is shown in the promo dialog. */ + protected abstract DialogParams getDialogParams(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialogLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialogLayout.java new file mode 100644 index 0000000..41243fb1 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialogLayout.java
@@ -0,0 +1,102 @@ +// 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.util.AttributeSet; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.widget.PromoDialog.DialogParams; + +/** + * View that handles orientation changes for the promo dialogs. When the width is greater than the + * height, the promo content switches from vertical to horizontal and moves the illustration from + * the top of the text to the side of the text. + */ +public final class PromoDialogLayout extends BoundedLinearLayout { + /** Content in the dialog that can be scrolled. */ + private LinearLayout mScrollableContent; + + /** Illustration that teases the thing being promoted. */ + private ImageView mIllustrationView; + + /** View containing the header of the promo. */ + private TextView mHeaderView; + + /** View containing text explaining the promo. */ + private TextView mSubheaderView; + + /** Paramters used to build the promo. */ + private DialogParams mParams; + + public PromoDialogLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void onFinishInflate() { + mScrollableContent = (LinearLayout) findViewById(R.id.promo_content); + mIllustrationView = (ImageView) findViewById(R.id.illustration); + mHeaderView = (TextView) findViewById(R.id.header); + mSubheaderView = (TextView) findViewById(R.id.subheader); + + super.onFinishInflate(); + } + + /** Initializes the dialog contents using the given params. Should only be called once. */ + void initialize(DialogParams params) { + assert mParams == null && params != null; + mParams = params; + + if (mParams.drawableResource == 0) { + ((ViewGroup) mIllustrationView.getParent()).removeView(mIllustrationView); + } else { + mIllustrationView.setImageResource(mParams.drawableResource); + } + + // TODO(dfalcantara): Lock the title in place, if requested by the DialogParams. + mHeaderView.setText(mParams.headerStringResource); + + if (mParams.subheaderStringResource == 0) { + ((ViewGroup) mSubheaderView.getParent()).removeView(mSubheaderView); + } else { + mSubheaderView.setText(mParams.subheaderStringResource); + } + + DualControlLayout buttonBar = (DualControlLayout) findViewById(R.id.button_bar); + if (mParams.primaryButtonStringResource != 0) { + String primaryString = getResources().getString(mParams.primaryButtonStringResource); + buttonBar.addView(DualControlLayout.createButtonForLayout( + getContext(), true, primaryString, null)); + + if (mParams.secondaryButtonStringResource != 0) { + String secondaryString = + getResources().getString(mParams.secondaryButtonStringResource); + buttonBar.addView(DualControlLayout.createButtonForLayout( + getContext(), false, secondaryString, null)); + } + } else { + assert mParams.secondaryButtonStringResource == 0; + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int availableWidth = MeasureSpec.getSize(widthMeasureSpec); + int availableHeight = MeasureSpec.getSize(heightMeasureSpec); + + if (availableWidth > availableHeight * 1.5) { + mScrollableContent.setOrientation(LinearLayout.HORIZONTAL); + } else { + mScrollableContent.setOrientation(LinearLayout.VERTICAL); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } +}
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index b4a9e21..53ea8bba 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -487,7 +487,7 @@ "java/src/org/chromium/chrome/browser/invalidation/InvalidationServiceFactory.java", "java/src/org/chromium/chrome/browser/invalidation/UniqueIdInvalidationClientNameGenerator.java", "java/src/org/chromium/chrome/browser/locale/LocaleManager.java", - "java/src/org/chromium/chrome/browser/locale/SearchEnginePromoDialog.java", + "java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java", "java/src/org/chromium/chrome/browser/locale/SpecialLocaleHandler.java", "java/src/org/chromium/chrome/browser/media/MediaCaptureNotificationService.java", "java/src/org/chromium/chrome/browser/media/VideoPersister.java", @@ -836,7 +836,6 @@ "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPreferences.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoUtils.java", - "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoView.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionProxyUma.java", "java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java", "java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java", @@ -1154,6 +1153,8 @@ "java/src/org/chromium/chrome/browser/widget/ProgressAnimationFastStart.java", "java/src/org/chromium/chrome/browser/widget/ProgressAnimationLinear.java", "java/src/org/chromium/chrome/browser/widget/ProgressAnimationSmooth.java", + "java/src/org/chromium/chrome/browser/widget/PromoDialog.java", + "java/src/org/chromium/chrome/browser/widget/PromoDialogLayout.java", "java/src/org/chromium/chrome/browser/widget/RadioButtonWithDescription.java", "java/src/org/chromium/chrome/browser/widget/RoundedIconGenerator.java", "java/src/org/chromium/chrome/browser/widget/TextBubble.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java index 3a368bf..7883000 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
@@ -6,13 +6,16 @@ import android.os.Environment; import android.support.test.filters.MediumTest; +import android.util.Pair; import android.view.View; import org.chromium.base.Log; +import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.RetryOnFailure; +import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.CompositorViewHolder; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; @@ -23,10 +26,14 @@ import org.chromium.chrome.test.util.InfoBarUtil; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; +import org.chromium.content.browser.test.util.DOMUtils; import org.chromium.content.browser.test.util.TouchCommon; import org.chromium.net.test.EmbeddedTestServer; +import org.chromium.net.test.util.TestWebServer; import java.io.File; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Callable; /** @@ -53,6 +60,17 @@ FILENAME_GZIP }; + static class DownloadManagerRequestInterceptorForTest + implements DownloadManagerService.DownloadManagerRequestInterceptor { + public DownloadItem mDownloadItem; + + @Override + public void interceptDownloadRequest(DownloadItem item, boolean notifyComplete) { + mDownloadItem = item; + assertTrue(notifyComplete); + } + } + @Override protected void setUp() throws Exception { super.setUp(); @@ -374,6 +392,43 @@ assertTrue(hasDownload(FILENAME_WALLPAPER, null)); } + @MediumTest + @Feature({"Navigation"}) + public void testOMADownloadInterception() throws Exception { + TestWebServer webServer = TestWebServer.start(); + try { + final DownloadManagerRequestInterceptorForTest interceptor = + new DownloadManagerRequestInterceptorForTest(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + DownloadManagerService + .getDownloadManagerService(getInstrumentation().getContext()) + .setDownloadManagerRequestInterceptor(interceptor); + } + }); + List<Pair<String, String>> headers = new ArrayList<Pair<String, String>>(); + headers.add(Pair.create("Content-Type", "application/vnd.oma.drm.message")); + final String url = webServer.setResponse("/test.dm", "testdata", headers); + loadUrl(UrlUtils.encodeHtmlDataUri("<script>" + + " function download() {" + + " window.open( '" + url + "')" + + " }" + + "</script>" + + "<body id='body' onclick='download()'></body>")); + DOMUtils.clickNode(getActivity().getCurrentContentViewCore(), "body"); + CriteriaHelper.pollUiThread(new Criteria() { + @Override + public boolean isSatisfied() { + return interceptor.mDownloadItem != null + && url.equals(interceptor.mDownloadItem.getDownloadInfo().getUrl()); + } + }); + } finally { + webServer.shutdown(); + } + } + private void waitForFocus() { View currentView = getActivity().getActivityTab().getView(); if (!currentView.hasFocus()) {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 0cede831..8f8689b 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -15044,6 +15044,15 @@ <message name="IDS_FLAGS_MOJO_LOADING_DESCRIPTION" desc="Description for the flag to enable Mojo IPC for resource loading" translateable="false"> Use Mojo IPC instead of traditional Chrome IPC for resource loading. </message> + + <if expr="is_android"> + <message name="IDS_FLAGS_USE_NEW_DOODLE_API_NAME" desc="Name for the flag to enable the new Doodle API" translateable="false"> + Use new Doodle API + </message> + <message name="IDS_FLAGS_USE_NEW_DOODLE_API_DESCRIPTION" desc="Description for the flag to enable the new Doodle API" translateable="false"> + Enables the new API to fetch Doodles for the NTP. + </message> + </if> </messages> </release> </grit>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1410962..72549bd 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2408,6 +2408,12 @@ MULTI_VALUE_TYPE(kForceTabletModeChoices)}, #endif // OS_CHROMEOS +#if defined(OS_ANDROID) + {"use-new-doodle-api", IDS_FLAGS_USE_NEW_DOODLE_API_NAME, + IDS_FLAGS_USE_NEW_DOODLE_API_DESCRIPTION, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kUseNewDoodleApi)}, +#endif // OS_ANDROID + // NOTE: Adding new command-line switches requires adding corresponding // entries to enum "LoginCustomFlags" in histograms.xml. See note in // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index e313b4f7..4d6b2a3 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -180,6 +180,9 @@ const base::Feature kUploadCrashReportsUsingJobScheduler{ "UploadCrashReportsUsingJobScheduler", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kUseNewDoodleApi{"UseNewDoodleApi", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kUserMediaScreenCapturing{ "UserMediaScreenCapturing", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 54aa8161..3651662e 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -41,6 +41,7 @@ extern const base::Feature kTabsInCBD; extern const base::Feature kTabReparenting; extern const base::Feature kUploadCrashReportsUsingJobScheduler; +extern const base::Feature kUseNewDoodleApi; extern const base::Feature kUserMediaScreenCapturing; extern const base::Feature kWebPaymentsModifiers; extern const base::Feature kWebPaymentsSingleAppUiSkip;
diff --git a/chrome/browser/android/logo_bridge.cc b/chrome/browser/android/logo_bridge.cc index 26c8b1a..cd6284ac 100644 --- a/chrome/browser/android/logo_bridge.cc +++ b/chrome/browser/android/logo_bridge.cc
@@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" +#include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/android/logo_service.h" #include "chrome/browser/doodle/doodle_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -39,9 +40,6 @@ namespace { -const base::Feature kUseNewDoodleApi{"UseNewDoodleApi", - base::FEATURE_DISABLED_BY_DEFAULT}; - ScopedJavaLocalRef<jobject> MakeJavaLogo(JNIEnv* env, const SkBitmap* bitmap, const GURL& on_click_url, @@ -198,7 +196,7 @@ Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); DCHECK(profile); - if (base::FeatureList::IsEnabled(kUseNewDoodleApi)) { + if (base::FeatureList::IsEnabled(chrome::android::kUseNewDoodleApi)) { doodle_service_ = DoodleServiceFactory::GetForProfile(profile); image_fetcher_ = base::MakeUnique<image_fetcher::ImageFetcherImpl>( base::MakeUnique<suggestions::ImageDecoderImpl>(),
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 19d6551c..736341f 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -263,6 +263,8 @@ <include name="IDR_MD_BOOKMARKS_APP_JS" file="resources\md_bookmarks\app.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_BOOKMARKS_HTML" file="resources\md_bookmarks\bookmarks.html" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\bookmarks_store.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML" file="resources\md_bookmarks\edit_dialog.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_JS" file="resources\md_bookmarks\edit_dialog.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_HTML" file="resources\md_bookmarks\folder_node.html" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_FOLDER_NODE_JS" file="resources\md_bookmarks\folder_node.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_ICONS_HTML" file="resources\md_bookmarks\icons.html" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 528148a0..938c3015 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2306,7 +2306,7 @@ callback) { DCHECK(web_contents); if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME) { - // A sub-resource has a certificate error. The user doesn't really + // A sub-resource has a certificate error. The user doesn't really // have a context for making the right decision, so block the // request hard, without an info bar to allow showing the insecure // content.
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc index 5453150..0625ae20 100644 --- a/chrome/browser/extensions/process_manager_browsertest.cc +++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -44,6 +44,11 @@ #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#if defined(CHROMEOS) +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chromeos/chromeos_switches.h" +#endif + namespace extensions { namespace { @@ -123,8 +128,6 @@ EXPECT_EQ("foo", result); } -} // namespace - // Takes a snapshot of all frames upon construction. When Wait() is called, a // MessageLoop is created and Quit when all previously recorded frames are // either present in the tab, or deleted. If a navigation happens between the @@ -270,6 +273,50 @@ std::vector<std::unique_ptr<TestExtensionDir>> temp_dirs_; }; +class DefaultProfileExtensionBrowserTest : public ExtensionBrowserTest { + protected: + DefaultProfileExtensionBrowserTest() { +#if defined(OS_CHROMEOS) + // We want signin profile on ChromeOS, not logged in user profile. + set_chromeos_user_ = false; +#endif + } + + private: + void SetUpCommandLine(base::CommandLine* command_line) override { + ExtensionBrowserTest::SetUpCommandLine(command_line); +#if defined(OS_CHROMEOS) + command_line->AppendSwitch(chromeos::switches::kLoginManager); + command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); +#endif + } +}; + +} // namespace + +// By default, no extension hosts should be present in the profile; +// they should only be present if non-component extensions are loaded +// or if the user takes some action to trigger a component extension. +// TODO(achuith): Expand this testing to include more in-depth +// testing for the signin profile, where we explicitly disallow all +// extension hosts unless it's the off-the-record profile. +IN_PROC_BROWSER_TEST_F(DefaultProfileExtensionBrowserTest, NoExtensionHosts) { + // Explicitly get the original and off-the-record-profiles, since on CrOS, + // the signin profile (profile()) is the off-the-record version. + Profile* original = profile()->GetOriginalProfile(); + Profile* otr = original->GetOffTheRecordProfile(); +#if defined(OS_CHROMEOS) + EXPECT_EQ(profile(), otr); + EXPECT_TRUE(chromeos::ProfileHelper::IsSigninProfile(original)); +#endif + + ProcessManager* pm = ProcessManager::Get(original); + EXPECT_EQ(0u, pm->background_hosts().size()); + + pm = ProcessManager::Get(otr); + EXPECT_EQ(0u, pm->background_hosts().size()); +} + // Test that basic extension loading creates the appropriate ExtensionHosts // and background pages. IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index 0ddcbdb..ecc07c0 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -562,14 +562,21 @@ content::RESOURCE_TYPE_MAIN_FRAME, throttles); #if defined(OS_ANDROID) - throttles->push_back( - base::MakeUnique<InterceptDownloadResourceThrottle>( - request, info->GetWebContentsGetterForRequest())); // On Android, forward text/html downloads to OfflinePages backend. throttles->push_back( base::MakeUnique<offline_pages::downloads::ResourceThrottle>(request)); #endif } + +#if defined(OS_ANDROID) + // Add the InterceptDownloadResourceThrottle after calling + // AppendStandardResourceThrottles so the download will not bypass + // safebrowsing checks. + if (is_content_initiated) { + throttles->push_back(base::MakeUnique<InterceptDownloadResourceThrottle>( + request, info->GetWebContentsGetterForRequest())); + } +#endif } ResourceDispatcherHostLoginDelegate*
diff --git a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp index f281ac36..b2e1a70 100644 --- a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp +++ b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
@@ -46,6 +46,16 @@ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'] }, { + 'target_name': 'edit_dialog', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', + '<(EXTERNS_GYP):chrome_extensions', + 'types', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'] + }, + { 'target_name': 'folder_node', 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], 'dependencies': [ @@ -72,6 +82,7 @@ '<(EXTERNS_GYP):bookmark_manager_private', '<(EXTERNS_GYP):chrome_extensions', 'actions', + 'edit_dialog', 'item', 'store_client', ],
diff --git a/chrome/browser/resources/md_bookmarks/edit_dialog.html b/chrome/browser/resources/md_bookmarks/edit_dialog.html new file mode 100644 index 0000000..7361e15 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/edit_dialog.html
@@ -0,0 +1,37 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> + +<dom-module id="bookmarks-edit-dialog"> + <template> + <style include="cr-shared-style"></style> + <dialog is="cr-dialog" id="dialog"> + <div class="title">[[getDialogTitle_(isFolder_)]]</div> + <div class="body"> + <paper-input always-float-label id="name" + label="$i18n{editDialogNameInput}" + value="{{titleValue_}}" + autofocus> + </paper-input> + <paper-input always-float-label id="url" + label="$i18n{editDialogUrlInput}" + value="{{urlValue_}}" + hidden$="[[isFolder_]]"> + </paper-input> + </div> + <div class="button-container"> + <paper-button class="cancel-button" on-tap="onCancelButtonTap_"> + $i18n{cancelEdit} + </paper-button> + <paper-button id="saveButton" class="action-button" + on-tap="onSaveButtonTap_"> + $i18n{saveEdit} + </paper-button> + </div> + </dialog> + </template> + <script src="chrome://bookmarks/edit_dialog.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/edit_dialog.js b/chrome/browser/resources/md_bookmarks/edit_dialog.js new file mode 100644 index 0000000..c2a4873c --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/edit_dialog.js
@@ -0,0 +1,60 @@ +// 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. + +Polymer({ + is: 'bookmarks-edit-dialog', + + properties: { + /** @private {BookmarkNode} */ + editItem_: Object, + + /** @private */ + isFolder_: Boolean, + + /** @private */ + titleValue_: String, + + /** @private */ + urlValue_: String, + }, + + /** @param {BookmarkNode} editItem */ + showEditDialog: function(editItem) { + this.editItem_ = editItem; + this.isFolder_ = !editItem.url; + + this.titleValue_ = editItem.title; + if (!this.isFolder_) + this.urlValue_ = assert(editItem.url); + + this.$.dialog.showModal(); + }, + + /** + * @param {boolean} isFolder + * @return {string} + * @private + */ + getDialogTitle_: function(isFolder) { + return loadTimeData.getString( + isFolder ? 'renameFolderTitle' : 'editBookmarkTitle'); + }, + + /** @private */ + onSaveButtonTap_: function() { + // TODO(tsergeant): Save changes when enter is pressed. + // TODO(tsergeant): Verify values. + var edit = {'title': this.titleValue_}; + if (!this.isFolder_) + edit['url'] = this.urlValue_; + + chrome.bookmarks.update(this.editItem_.id, edit); + this.$.dialog.close(); + }, + + /** @private */ + onCancelButtonTap_: function() { + this.$.dialog.cancel(); + }, +});
diff --git a/chrome/browser/resources/md_bookmarks/list.html b/chrome/browser/resources/md_bookmarks/list.html index d36a1f4..05bb411 100644 --- a/chrome/browser/resources/md_bookmarks/list.html +++ b/chrome/browser/resources/md_bookmarks/list.html
@@ -1,11 +1,9 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> -<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> +<link rel="import" href="chrome://bookmarks/edit_dialog.html"> <link rel="import" href="chrome://bookmarks/item.html"> <link rel="import" href="chrome://bookmarks/shared_style.html"> <link rel="import" href="chrome://bookmarks/store_client.html"> @@ -13,7 +11,7 @@ <dom-module id="bookmarks-list"> <template> - <style include="shared-style cr-shared-style"> + <style include="shared-style"> :host { overflow-y: auto; padding: 20px 32px 20px calc(32px - var(--splitter-width)); @@ -49,29 +47,6 @@ $i18n{menuDelete} </button> </dialog> - <dialog is="cr-dialog" id="editBookmark"> - <div class="title">[[getEditorTitle_(menuItem_)]]</div> - <div class="body"> - <paper-input always-float-label id="name" - label="$i18n{editDialogNameInput}" - value="{{menuItem_.title}}"> - </paper-input> - <paper-input always-float-label id="url" - label="$i18n{editDialogUrlInput}" - value="{{menuItem_.url}}" - hidden$="[[!menuItem_.url]]"> - </paper-input> - </div> - <div class="button-container"> - <paper-button class="cancel-button" on-tap="onCancelEditTap_"> - $i18n{cancelEdit} - </paper-button> - <paper-button class="action-button" on-tap="onSaveEditTap_" - id='saveButton'> - $i18n{saveEdit} - </paper-button> - </div> - </dialog> <div id="bookmarksCard" hidden$="[[isEmptyList_(displayedList_.length)]]"> <template is="dom-repeat" items="[[displayedList_]]" as="id"> <bookmarks-item item-id="[[id]]"> @@ -82,6 +57,9 @@ hidden$="[[!isEmptyList_(displayedList_.length)]]"> [[emptyListMessage_(searchTerm_)]] </div> + <template is="cr-lazy-render" id="editDialog"> + <bookmarks-edit-dialog></bookmarks-edit-dialog> + </template> </template> <script src="chrome://bookmarks/list.js"></script> </dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/list.js b/chrome/browser/resources/md_bookmarks/list.js index 296620b..0edfcbb 100644 --- a/chrome/browser/resources/md_bookmarks/list.js +++ b/chrome/browser/resources/md_bookmarks/list.js
@@ -55,7 +55,8 @@ /** @private */ onEditTap_: function() { this.closeDropdownMenu_(); - this.$.editBookmark.showModal(); + /** @type {BookmarksEditDialogElement} */ (this.$.editDialog.get()) + .showEditDialog(this.menuItem_); }, /** @private */ @@ -82,21 +83,6 @@ }, /** @private */ - onSaveEditTap_: function() { - var edit = {'title': this.menuItem_.title}; - if (this.menuItem_.url) - edit['url'] = this.menuItem_.url; - - chrome.bookmarks.update(this.menuItem_.id, edit); - this.$.editBookmark.close(); - }, - - /** @private */ - onCancelEditTap_: function() { - this.$.editBookmark.cancel(); - }, - - /** @private */ closeDropdownMenu_: function() { var menu = /** @type {!CrActionMenuElement} */ ( this.$.dropdown); @@ -110,12 +96,6 @@ }, /** @private */ - getEditorTitle_: function() { - var title = this.menuItem_.url ? 'editBookmarkTitle' : 'renameFolderTitle'; - return loadTimeData.getString(title); - }, - - /** @private */ emptyListMessage_: function() { var emptyListMessage = this.searchTerm_ ? 'noSearchResults' : 'emptyList'; return loadTimeData.getString(emptyListMessage);
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc index 5be1073c..9c65ca31 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -346,27 +346,25 @@ } // Verify that when you unblock popup, the popup shows in history and omnibox. -// TODO(crbug.com/663333) Flaky on Linux. -#if defined(OS_LINUX) -#define MAYBE_UnblockedPopupShowsInHistoryAndOmnibox \ - DISABLED_UnblockedPopupShowsInHistoryAndOmnibox -#else -#define MAYBE_UnblockedPopupShowsInHistoryAndOmnibox \ - UnblockedPopupShowsInHistoryAndOmnibox -#endif IN_PROC_BROWSER_TEST_F(PopupBlockerBrowserTest, - MAYBE_UnblockedPopupShowsInHistoryAndOmnibox) { + UnblockedPopupShowsInHistoryAndOmnibox) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); GURL url(embedded_test_server()->GetURL( "/popup_blocker/popup-blocked-to-post-blank.html")); NavigateAndCheckPopupShown(url, ExpectTab); + // Make sure the navigation in the new tab actually finished. + WebContents* web_contents = browser()->tab_strip_model()->GetWebContentsAt(1); + base::string16 expected_title(base::ASCIIToUTF16("Popup Success!")); + content::TitleWatcher title_watcher(web_contents, expected_title); + EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); + WaitForHistoryBackendToRun(browser()->profile()); + std::string search_string = "data:text/html,<title>Popup Success!</title>you should not see this " "message if popup blocker is enabled"; - WaitForHistoryBackendToRun(browser()->profile()); ui_test_utils::HistoryEnumerator history(browser()->profile()); std::vector<GURL>& history_urls = history.urls(); ASSERT_EQ(2u, history_urls.size());
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc index 9d6836d2..e370ea20 100644 --- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -75,6 +75,9 @@ source->AddResourcePath("app.js", IDR_MD_BOOKMARKS_APP_JS); source->AddResourcePath("bookmarks_store.js", IDR_MD_BOOKMARKS_BOOKMARKS_STORE_JS); + source->AddResourcePath("edit_dialog.html", + IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML); + source->AddResourcePath("edit_dialog.js", IDR_MD_BOOKMARKS_EDIT_DIALOG_JS); source->AddResourcePath("folder_node.html", IDR_MD_BOOKMARKS_FOLDER_NODE_HTML); source->AddResourcePath("folder_node.js",
diff --git a/chrome/install_static/chromium_install_modes.cc b/chrome/install_static/chromium_install_modes.cc index 997aa4b..8e6068c 100644 --- a/chrome/install_static/chromium_install_modes.cc +++ b/chrome/install_static/chromium_install_modes.cc
@@ -33,7 +33,10 @@ L"", // No logo suffix for the primary install mode. L"", // Empty app_guid since no integraion with Google Update. L"Chromium", // A distinct base_app_id. - L"", // Empty default channel name as above. + L"ChromiumHTM", // ProgID prefix. + L"Chromium HTML Document", // ProgID description. + L"{7D2B3E1D-D096-4594-9D8F-A6667F12E0AC}", // Active Setup GUID. + L"", // Empty default channel name since no update integration. ChannelStrategy::UNSUPPORTED, true, // Supports system-level installs. true, // Supported multi-install.
diff --git a/chrome/install_static/google_chrome_install_modes.cc b/chrome/install_static/google_chrome_install_modes.cc index a4906845..b5c3ce37 100644 --- a/chrome/install_static/google_chrome_install_modes.cc +++ b/chrome/install_static/google_chrome_install_modes.cc
@@ -33,6 +33,9 @@ L"", // No logo suffix for the primary install mode. L"{8A69D345-D564-463c-AFF1-A69D9E530F96}", L"Chrome", // A distinct base_app_id. + L"ChromeHTML", // ProgID prefix. + L"Chrome HTML Document", // ProgID description. + L"{8A69D345-D564-463c-AFF1-A69D9E530F96}", // Active Setup GUID. L"", // The empty string means "stable". ChannelStrategy::ADDITIONAL_PARAMETERS, true, // Supports system-level installs. @@ -48,6 +51,9 @@ L"Canary", L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}", L"ChromeCanary", // A distinct base_app_id. + L"ChromeSSHTM", // ProgID prefix. + L"Chrome Canary HTML Document", // ProgID description. + L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}", // Active Setup GUID. L"canary", ChannelStrategy::FIXED, false, // Does not support system-level installs.
diff --git a/chrome/install_static/install_constants.h b/chrome/install_static/install_constants.h index b5e4a86..504fd57 100644 --- a/chrome/install_static/install_constants.h +++ b/chrome/install_static/install_constants.h
@@ -68,6 +68,20 @@ // directly. const wchar_t* base_app_id; + // The prefix for the browser's ProgID. This prefix may be no more than 11 + // characters long; see ShellUtil::GetBrowserProgId and + // https://msdn.microsoft.com/library/windows/desktop/dd542719.aspx. + const wchar_t* prog_id_prefix; + + // A human-readable description of the browser, used when registering with + // Windows. + const wchar_t* prog_id_description; + + // The GUID to be used when registering this install mode for Active Setup. + // Active Setup is used to perform certain operations in a user's context for + // system-level installs. + const wchar_t* active_setup_guid; + // The default name for this mode's update channel. const wchar_t* default_channel_name;
diff --git a/chrome/install_static/install_modes_unittest.cc b/chrome/install_static/install_modes_unittest.cc index e4593633..3e0f01b 100644 --- a/chrome/install_static/install_modes_unittest.cc +++ b/chrome/install_static/install_modes_unittest.cc
@@ -4,17 +4,40 @@ #include "chrome/install_static/install_modes.h" +#include <windows.h> + +#include <ctype.h> + #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::Eq; using ::testing::Gt; +using ::testing::Le; using ::testing::Ne; +using ::testing::Not; +using ::testing::ResultOf; using ::testing::StrEq; using ::testing::StrNe; namespace install_static { +namespace { + +// A matcher that returns true if |arg| contains a character that is neither +// alpha-numeric nor a period. +MATCHER(ContainsIllegalProgIdChar, "") { + const wchar_t* scan = arg; + wint_t c; + while ((c = *scan++) != 0) { + if (!iswalnum(c) && c != L'.') + return true; + } + return false; +} + +} // namespace + TEST(InstallModes, VerifyModes) { ASSERT_THAT(NUM_INSTALL_MODES, Gt(0)); for (int i = 0; i < NUM_INSTALL_MODES; ++i) { @@ -47,6 +70,20 @@ else ASSERT_THAT(mode.app_guid, StrEq(L"")); + // The ProgID prefix must not be empty, must be no greater than 11 + // characters long, must contain no punctuation, and may not start with a + // digit (https://msdn.microsoft.com/library/windows/desktop/dd542719.aspx). + ASSERT_THAT(mode.prog_id_prefix, StrNe(L"")); + ASSERT_THAT(lstrlen(mode.prog_id_prefix), Le(11)); + ASSERT_THAT(mode.prog_id_prefix, Not(ContainsIllegalProgIdChar())); + ASSERT_THAT(*mode.prog_id_prefix, ResultOf(iswdigit, Eq(0))); + + // The ProgID description must not be empty. + ASSERT_THAT(mode.prog_id_description, StrNe(L"")); + + // Every mode must have an Active Setup GUID. + ASSERT_THAT(mode.active_setup_guid, StrNe(L"")); + // UNSUPPORTED and kUseGoogleUpdateIntegration are mutually exclusive. if (kUseGoogleUpdateIntegration) ASSERT_THAT(mode.channel_strategy, Ne(ChannelStrategy::UNSUPPORTED));
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc index 9ff2bcd..ffb6147 100644 --- a/chrome/install_static/install_util.cc +++ b/chrome/install_static/install_util.cc
@@ -324,6 +324,20 @@ return InstallDetails::Get().base_app_id(); } +const wchar_t* GetProgIdPrefix() { + return InstallDetails::Get().mode().prog_id_prefix; +} + +const wchar_t* GetProgIdDescription() { + return InstallDetails::Get().mode().prog_id_description; +} + +std::wstring GetActiveSetupPath() { + return std::wstring( + L"Software\\Microsoft\\Active Setup\\Installed Components\\") + .append(InstallDetails::Get().mode().active_setup_guid); +} + bool GetCollectStatsConsent() { bool enabled = true;
diff --git a/chrome/install_static/install_util.h b/chrome/install_static/install_util.h index a66554e5..20060890 100644 --- a/chrome/install_static/install_util.h +++ b/chrome/install_static/install_util.h
@@ -80,6 +80,22 @@ // directly. const wchar_t* GetBaseAppId(); +// Returns the browser's ProgID prefix (e.g., ChromeHTML or ChromiumHTM). The +// full id is of the form |prefix|.|suffix| and is limited to a maximum length +// of 39 characters including null-terminator; see +// https://msdn.microsoft.com/library/windows/desktop/dd542719.aspx for details. +// We define |suffix| as a fixed-length 26-character alphanumeric identifier, +// therefore the return value of this function must have a maximum length of +// 39 - 1(null-term) - 26(|suffix|) - 1(dot separator) = 11 characters. +const wchar_t* GetProgIdPrefix(); + +// Returns the browser's ProgId description. +const wchar_t* GetProgIdDescription(); + +// Returns the path to the Active Setup registry entries +// (e.g., Software\Microsoft\Active Setup\Installed Components\[guid]). +std::wstring GetActiveSetupPath(); + // Returns true if usage stats collecting is enabled for this user for the // current executable. bool GetCollectStatsConsent();
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc index e1e121a..85ff23a31 100644 --- a/chrome/installer/setup/install.cc +++ b/chrome/installer/setup/install.cc
@@ -22,6 +22,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/shortcut.h" #include "chrome/install_static/install_details.h" +#include "chrome/install_static/install_util.h" #include "chrome/installer/setup/install_worker.h" #include "chrome/installer/setup/installer_crash_reporting.h" #include "chrome/installer/setup/installer_state.h" @@ -649,7 +650,7 @@ UpdateDefaultBrowserBeaconForPath(chrome_exe); } else { UpdateActiveSetupVersionWorkItem active_setup_work_item( - InstallUtil::GetActiveSetupPath(chrome.distribution()), + install_static::GetActiveSetupPath(), UpdateActiveSetupVersionWorkItem:: UPDATE_AND_BUMP_OS_UPGRADES_COMPONENT); if (active_setup_work_item.Do())
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index 342983bd0..ec50d24 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc
@@ -807,7 +807,7 @@ DCHECK(installer_state.RequiresActiveSetup()); const HKEY root = HKEY_LOCAL_MACHINE; - const base::string16 active_setup_path(InstallUtil::GetActiveSetupPath(dist)); + const base::string16 active_setup_path(install_static::GetActiveSetupPath()); VLOG(1) << "Adding registration items for Active Setup."; list->AddCreateRegKeyWorkItem(
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc index d012207..6d14e7c 100644 --- a/chrome/installer/setup/uninstall.cc +++ b/chrome/installer/setup/uninstall.cc
@@ -440,9 +440,8 @@ base::string16 classes_path(ShellUtil::kRegClasses); classes_path.push_back(base::FilePath::kSeparators[0]); - BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); - const base::string16 prog_id( - distribution->GetBrowserProgIdPrefix() + browser_entry_suffix); + const base::string16 prog_id(install_static::GetProgIdPrefix() + + browser_entry_suffix); // Delete each filetype association if it references this Chrome. Take care // not to delete the association if it references a system-level install of @@ -521,19 +520,15 @@ // but otherwise respects the no rollback/best effort uninstall mentality. // This will only apply for system-level installs of Chrome/Chromium and will be // a no-op for all other types of installs. -void UninstallActiveSetupEntries(const InstallerState& installer_state, - const Product& product) { +void UninstallActiveSetupEntries(const InstallerState& installer_state) { VLOG(1) << "Uninstalling registry entries for Active Setup."; - BrowserDistribution* distribution = product.distribution(); if (!installer_state.system_install()) { - VLOG(1) << "No Active Setup processing to do for user-level " - << distribution->GetDisplayName(); + VLOG(1) << "No Active Setup processing to do for user-level install."; return; } - const base::string16 active_setup_path( - InstallUtil::GetActiveSetupPath(distribution)); + const base::string16 active_setup_path(install_static::GetActiveSetupPath()); InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path, WorkItem::kWow64Default); @@ -639,8 +634,9 @@ base::FilePath chrome_exe(installer_state.target_path().Append(kChromeExe)); // Delete Software\Classes\ChromeHTML. - const base::string16 prog_id( - dist->GetBrowserProgIdPrefix() + browser_entry_suffix); + DCHECK_EQ(BrowserDistribution::GetDistribution(), dist); + const base::string16 prog_id(install_static::GetProgIdPrefix() + + browser_entry_suffix); base::string16 reg_prog_id(ShellUtil::kRegClasses); reg_prog_id.push_back(base::FilePath::kSeparators[0]); reg_prog_id.append(prog_id); @@ -651,7 +647,6 @@ reg_app_id.push_back(base::FilePath::kSeparators[0]); // Append the requested suffix manually here (as ShellUtil::GetBrowserModelId // would otherwise try to figure out the currently installed suffix). - DCHECK_EQ(BrowserDistribution::GetDistribution(), dist); reg_app_id.append(install_static::GetBaseAppId() + browser_entry_suffix); InstallUtil::DeleteRegistryKey(root, reg_app_id, WorkItem::kWow64Default); @@ -972,7 +967,7 @@ ProcessChromeWorkItems(installer_state, product); - UninstallActiveSetupEntries(installer_state, product); + UninstallActiveSetupEntries(installer_state); UninstallFirewallRules(browser_dist, chrome_exe);
diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc index d5ed7b2..51d8f71 100644 --- a/chrome/installer/util/browser_distribution.cc +++ b/chrome/installer/util/browser_distribution.cc
@@ -33,9 +33,6 @@ namespace { -const wchar_t kChromiumActiveSetupGuid[] = - L"{7D2B3E1D-D096-4594-9D8F-A6667F12E0AC}"; - const wchar_t kCommandExecuteImplUuid[] = L"{A2DF06F9-A21A-44A8-8A99-8B9C84F29160}"; @@ -109,10 +106,6 @@ const base::string16& distribution_data) { } -base::string16 BrowserDistribution::GetActiveSetupGuid() { - return kChromiumActiveSetupGuid; -} - base::string16 BrowserDistribution::GetBaseAppName() { return L"Chromium"; } @@ -144,18 +137,6 @@ } } -base::string16 BrowserDistribution::GetBrowserProgIdPrefix() { - // This used to be "ChromiumHTML", but was forced to become "ChromiumHTM" - // because of http://crbug.com/153349. See the declaration of this function - // in the header file for more details. - return L"ChromiumHTM"; -} - -base::string16 BrowserDistribution::GetBrowserProgIdDesc() { - return L"Chromium HTML Document"; -} - - base::string16 BrowserDistribution::GetPublisherName() { return L"Chromium"; }
diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h index f3e0ce7e..237e2343 100644 --- a/chrome/installer/util/browser_distribution.h +++ b/chrome/installer/util/browser_distribution.h
@@ -51,9 +51,6 @@ const base::FilePath& local_data_path, const base::string16& distribution_data); - // Returns the GUID to be used when registering for Active Setup. - virtual base::string16 GetActiveSetupGuid(); - // Returns the unsuffixed application name of this program. // This is the base of the name registered with Default Programs on Windows. // IMPORTANT: This should only be called by the installer which needs to make @@ -80,18 +77,6 @@ virtual base::string16 GetStartMenuShortcutSubfolder( Subfolder subfolder_type); - // Returns the Browser ProgId prefix (e.g. ChromeHTML, ChromiumHTM, etc...). - // The full id is of the form |prefix|.|suffix| and is limited to a maximum - // length of 39 characters including null-terminator. See - // http://msdn.microsoft.com/library/aa911706.aspx for details. We define - // |suffix| as a fixed-length 26-character alphanumeric identifier, therefore - // the return value of this function must have a maximum length of - // 39 - 1(null-term) - 26(|suffix|) - 1(dot separator) = 11 characters. - virtual base::string16 GetBrowserProgIdPrefix(); - - // Returns the Browser ProgId description. - virtual base::string16 GetBrowserProgIdDesc(); - virtual base::string16 GetPublisherName(); virtual base::string16 GetAppDescription();
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc index 11d2af1..48e74091 100644 --- a/chrome/installer/util/google_chrome_distribution.cc +++ b/chrome/installer/util/google_chrome_distribution.cc
@@ -41,8 +41,6 @@ namespace { const wchar_t kChromeGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; -const wchar_t kBrowserProgIdPrefix[] = L"ChromeHTML"; -const wchar_t kBrowserProgIdDesc[] = L"Chrome HTML Document"; const wchar_t kCommandExecuteImplUuid[] = L"{5C65F4B0-3651-4514-B207-D10CB699B14B}"; @@ -146,10 +144,6 @@ NavigateToUrlWithIExplore(url); } -base::string16 GoogleChromeDistribution::GetActiveSetupGuid() { - return install_static::GetAppGuid(); -} - base::string16 GoogleChromeDistribution::GetBaseAppName() { // I'd really like to return L ## PRODUCT_FULLNAME_STRING; but that's no good // since it'd be "Chromium" in a non-Chrome build, which isn't at all what I @@ -165,14 +159,6 @@ return icon_resources::kApplicationIndex; } -base::string16 GoogleChromeDistribution::GetBrowserProgIdPrefix() { - return kBrowserProgIdPrefix; -} - -base::string16 GoogleChromeDistribution::GetBrowserProgIdDesc() { - return kBrowserProgIdDesc; -} - base::string16 GoogleChromeDistribution::GetPublisherName() { const base::string16& publisher_name = installer::GetLocalizedString(IDS_ABOUT_VERSION_COMPANY_NAME_BASE);
diff --git a/chrome/installer/util/google_chrome_distribution.h b/chrome/installer/util/google_chrome_distribution.h index b84a6e59..f3cecd6 100644 --- a/chrome/installer/util/google_chrome_distribution.h +++ b/chrome/installer/util/google_chrome_distribution.h
@@ -35,8 +35,6 @@ const base::FilePath& local_data_path, const base::string16& distribution_data) override; - base::string16 GetActiveSetupGuid() override; - base::string16 GetShortcutName() override; base::string16 GetIconFilename() override; @@ -45,10 +43,6 @@ base::string16 GetBaseAppName() override; - base::string16 GetBrowserProgIdPrefix() override; - - base::string16 GetBrowserProgIdDesc() override; - base::string16 GetPublisherName() override; base::string16 GetAppDescription() override;
diff --git a/chrome/installer/util/google_chrome_distribution_dummy.cc b/chrome/installer/util/google_chrome_distribution_dummy.cc index 3e6eab3..c65892c 100644 --- a/chrome/installer/util/google_chrome_distribution_dummy.cc +++ b/chrome/installer/util/google_chrome_distribution_dummy.cc
@@ -36,10 +36,6 @@ const base::string16& distribution_data) { } -base::string16 GoogleChromeDistribution::GetActiveSetupGuid() { - return base::string16(); -} - base::string16 GoogleChromeDistribution::GetBaseAppName() { return base::string16(); } @@ -52,14 +48,6 @@ return 0; } -base::string16 GoogleChromeDistribution::GetBrowserProgIdPrefix() { - return base::string16(); -} - -base::string16 GoogleChromeDistribution::GetBrowserProgIdDesc() { - return base::string16(); -} - base::string16 GoogleChromeDistribution::GetPublisherName() { return base::string16(); }
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.cc b/chrome/installer/util/google_chrome_sxs_distribution.cc index 4a2186fc..66f272f 100644 --- a/chrome/installer/util/google_chrome_sxs_distribution.cc +++ b/chrome/installer/util/google_chrome_sxs_distribution.cc
@@ -15,8 +15,6 @@ namespace { const wchar_t kChromeSxSGuid[] = L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}"; -const wchar_t kBrowserProgIdPrefix[] = L"ChromeSSHTM"; -const wchar_t kBrowserProgIdDesc[] = L"Chrome Canary HTML Document"; const wchar_t kCommandExecuteImplUuid[] = L"{1BEAC3E3-B852-44F4-B468-8906C062422E}"; @@ -46,14 +44,6 @@ } } -base::string16 GoogleChromeSxSDistribution::GetBrowserProgIdPrefix() { - return kBrowserProgIdPrefix; -} - -base::string16 GoogleChromeSxSDistribution::GetBrowserProgIdDesc() { - return kBrowserProgIdDesc; -} - base::string16 GoogleChromeSxSDistribution::GetUninstallRegPath() { return GoogleChromeDistribution::GetUninstallRegPath().append( installer::kSxSSuffix);
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.h b/chrome/installer/util/google_chrome_sxs_distribution.h index ea98696..69e285f9 100644 --- a/chrome/installer/util/google_chrome_sxs_distribution.h +++ b/chrome/installer/util/google_chrome_sxs_distribution.h
@@ -24,8 +24,6 @@ int GetIconIndex() override; base::string16 GetStartMenuShortcutSubfolder( Subfolder subfolder_type) override; - base::string16 GetBrowserProgIdPrefix() override; - base::string16 GetBrowserProgIdDesc() override; base::string16 GetUninstallRegPath() override; DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; base::string16 GetCommandExecuteImplClsid() override;
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc index a1446fa..181fbd63 100644 --- a/chrome/installer/util/install_util.cc +++ b/chrome/installer/util/install_util.cc
@@ -28,6 +28,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/install_static/install_details.h" #include "chrome/install_static/install_modes.h" +#include "chrome/install_static/install_util.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/installation_state.h" @@ -80,15 +81,8 @@ } // namespace -base::string16 InstallUtil::GetActiveSetupPath(BrowserDistribution* dist) { - static const wchar_t kInstalledComponentsPath[] = - L"Software\\Microsoft\\Active Setup\\Installed Components\\"; - return kInstalledComponentsPath + dist->GetActiveSetupGuid(); -} - void InstallUtil::TriggerActiveSetupCommand() { - base::string16 active_setup_reg( - GetActiveSetupPath(BrowserDistribution::GetDistribution())); + base::string16 active_setup_reg(install_static::GetActiveSetupPath()); base::win::RegKey active_setup_key( HKEY_LOCAL_MACHINE, active_setup_reg.c_str(), KEY_QUERY_VALUE); base::string16 cmd_str;
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h index 1ce2356..70c7498 100644 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h
@@ -32,10 +32,6 @@ // independently. class InstallUtil { public: - // Get the path to this distribution's Active Setup registry entries. - // e.g. Software\Microsoft\Active Setup\Installed Components\<dist_guid> - static base::string16 GetActiveSetupPath(BrowserDistribution* dist); - // Attempts to trigger the command that would be run by Active Setup for a // system-level Chrome. For use only when system-level Chrome is installed. static void TriggerActiveSetupCommand();
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc index 335d1c2..81311fb 100644 --- a/chrome/installer/util/shell_util.cc +++ b/chrome/installer/util/shell_util.cc
@@ -88,8 +88,7 @@ // "ChromeHTML|suffix|"). // |suffix| can be the empty string. base::string16 GetBrowserProgId(const base::string16& suffix) { - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - base::string16 chrome_html(dist->GetBrowserProgIdPrefix()); + base::string16 chrome_html(install_static::GetProgIdPrefix()); chrome_html.append(suffix); // ProgIds cannot be longer than 39 characters. @@ -350,18 +349,20 @@ const base::FilePath& chrome_exe, const base::string16& suffix, ScopedVector<RegistryEntry>* entries) { + // Assert that this is only called with the one relevant distribution. + // TODO(grt): Remove this when BrowserDistribution goes away. + DCHECK_EQ(BrowserDistribution::GetDistribution(), dist); int chrome_icon_index = dist->GetIconIndex(); ApplicationInfo app_info; app_info.prog_id = GetBrowserProgId(suffix); - app_info.file_type_name = dist->GetBrowserProgIdDesc(); + app_info.file_type_name = install_static::GetProgIdDescription(); // File types associated with Chrome are just given the Chrome icon. app_info.file_type_icon_path = chrome_exe; app_info.file_type_icon_index = chrome_icon_index; app_info.command_line = ShellUtil::GetChromeShellOpenCmd(chrome_exe); // For user-level installs: entries for the app id will be in HKCU; thus we // do not need a suffix on those entries. - DCHECK_EQ(BrowserDistribution::GetDistribution(), dist); app_info.app_id = ShellUtil::GetBrowserModelId(InstallUtil::IsPerUserInstall()); @@ -795,6 +796,9 @@ const base::FilePath& chrome_exe, const base::string16& suffix, RegistrationConfirmationLevel confirmation_level) { + // Assert that this is only called with the one relevant distribution. + // TODO(grt): Remove this when BrowserDistribution goes away. + DCHECK_EQ(BrowserDistribution::GetDistribution(), dist); // Get the appropriate key to look for based on the level desired. base::string16 reg_key; switch (confirmation_level) { @@ -802,7 +806,7 @@ // Software\Classes\ChromeHTML|suffix| reg_key = ShellUtil::kRegClasses; reg_key.push_back(base::FilePath::kSeparators[0]); - reg_key.append(dist->GetBrowserProgIdPrefix()); + reg_key.append(install_static::GetProgIdPrefix()); reg_key.append(suffix); break; case CONFIRM_SHELL_REGISTRATION: @@ -1036,8 +1040,8 @@ if (FAILED(hr)) return ShellUtil::UNKNOWN_DEFAULT; + base::string16 prog_id(install_static::GetProgIdPrefix()); BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - base::string16 prog_id(dist->GetBrowserProgIdPrefix()); prog_id += ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe); for (size_t i = 0; i < num_protocols; ++i) {
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc index 59873dc2..8860d48 100644 --- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -797,4 +797,20 @@ } } +TEST_F(PasswordGenerationAgentTest, JavascriptClearedTheField) { + LoadHTMLWithUserGesture(kAccountCreationFormHTML); + SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML); + SetAccountCreationFormsDetectedMessage(password_generation_, + GetMainFrame()->document(), 0, 1); + + const char kGenerationElementId[] = "first_password"; + ExpectGenerationAvailable(kGenerationElementId, true); + password_generation_->GeneratedPasswordAccepted(base::ASCIIToUTF16("pwd")); + ExecuteJavaScriptForTests( + "document.getElementById('first_password').value = '';"); + FocusField(kGenerationElementId); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(fake_driver_.called_password_no_longer_generated()); +} + } // namespace autofill
diff --git a/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js b/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js new file mode 100644 index 0000000..5bc4269 --- /dev/null +++ b/chrome/test/data/webui/md_bookmarks/edit_dialog_test.js
@@ -0,0 +1,58 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +suite('<bookmarks-edit-dialog>', function() { + var dialog; + var lastUpdate; + + suiteSetup(function() { + chrome.bookmarks.update = function(id, edit) { + lastUpdate.id = id; + lastUpdate.edit = edit; + } + }); + + setup(function() { + lastUpdate = {}; + dialog = document.createElement('bookmarks-edit-dialog'); + replaceBody(dialog); + }); + + test('editing an item shows the url field', function() { + var item = createItem('0'); + dialog.showEditDialog(item); + + assertFalse(dialog.$.url.hidden); + }); + + test('editing a folder hides the url field', function() { + var folder = createFolder('0', []); + dialog.showEditDialog(folder); + + assertTrue(dialog.$.url.hidden); + }); + + test('editing passes the correct details to the update', function() { + // Editing an item without changing anything. + var item = createItem('1', {url: 'www.website.com', title: 'website'}); + dialog.showEditDialog(item); + + MockInteractions.tap(dialog.$.saveButton); + + assertEquals(item.id, lastUpdate.id); + assertEquals(item.url, lastUpdate.edit.url); + assertEquals(item.title, lastUpdate.edit.title); + + // Editing a folder, changing the title. + var folder = createFolder('2', [], {title: 'Cool Sites'}); + dialog.showEditDialog(folder); + dialog.titleValue_ = 'Awesome websites'; + + MockInteractions.tap(dialog.$.saveButton); + + assertEquals(folder.id, lastUpdate.id); + assertEquals(undefined, lastUpdate.edit.url); + assertEquals('Awesome websites', lastUpdate.edit.title); + }); +});
diff --git a/chrome/test/data/webui/md_bookmarks/list_test.js b/chrome/test/data/webui/md_bookmarks/list_test.js index a2cd6f9..155f2776 100644 --- a/chrome/test/data/webui/md_bookmarks/list_test.js +++ b/chrome/test/data/webui/md_bookmarks/list_test.js
@@ -25,40 +25,6 @@ Polymer.dom.flush(); }); - test('folder menu item hides the url field', function() { - // Bookmark editor shows the url field. - list.menuItem_ = store.data.nodes['1']; - assertFalse(list.$['url'].hidden); - - // Folder editor hides the url field. - list.menuItem_ = store.data.nodes['3']; - assertTrue(list.$['url'].hidden); - }); - - test('saving edit passes correct details to the update', function() { - // Saving bookmark edit. - var menuItem = store.data.nodes['1']; - chrome.bookmarks.update = function(id, edit) { - assertEquals(menuItem.id, id); - assertEquals(menuItem.url, edit.url); - assertEquals(menuItem.title, edit.title); - }; - list.menuItem_ = menuItem; - list.$.editBookmark.showModal(); - MockInteractions.tap(list.$.saveButton); - - // Saving folder rename. - menuItem = store.data.nodes['3']; - chrome.bookmarks.update = function(id, edit) { - assertEquals(menuItem.id, id); - assertEquals(menuItem.title, edit.title); - assertEquals(undefined, edit.url); - }; - list.menuItem_ = menuItem; - list.$.editBookmark.showModal(); - MockInteractions.tap(list.$.saveButton); - }); - test('renders correct <bookmark-item> elements', function() { var items = list.root.querySelectorAll('bookmarks-item'); var ids = Array.from(items).map((item) => item.itemId);
diff --git a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js index 02f230a..8205db5 100644 --- a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js +++ b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
@@ -55,6 +55,20 @@ mocha.run(); }); +function MaterialBookmarksEditDialogTest() {} + +MaterialBookmarksEditDialogTest.prototype = { + __proto__: MaterialBookmarksBrowserTest.prototype, + + extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + 'edit_dialog_test.js', + ]), +}; + +TEST_F('MaterialBookmarksEditDialogTest', 'All', function() { + mocha.run(); +}); + function MaterialBookmarksItemTest() {} MaterialBookmarksItemTest.prototype = {
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc index 868e950..6e3fc67 100644 --- a/components/autofill/content/renderer/password_generation_agent.cc +++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -452,8 +452,12 @@ return false; if (password_is_generated_) { - generation_element_.setShouldRevealPassword(true); - ShowEditingPopup(); + if (generation_element_.value().isEmpty()) { + PasswordNoLongerGenerated(); + } else { + generation_element_.setShouldRevealPassword(true); + ShowEditingPopup(); + } return true; } @@ -478,21 +482,9 @@ if (element.value().isEmpty()) { if (password_is_generated_) { // User generated a password and then deleted it. - password_generation::LogPasswordGenerationEvent( - password_generation::PASSWORD_DELETED); - CopyElementValueToOtherInputElements(&element, - &generation_form_data_->password_elements); - std::unique_ptr<PasswordForm> presaved_form( - CreatePasswordFormToPresave()); - if (presaved_form) { - GetPasswordManagerDriver()->PasswordNoLongerGenerated(*presaved_form); - } + PasswordNoLongerGenerated(); } - // Do not treat the password as generated, either here or in the browser. - password_is_generated_ = false; - generation_element_.setShouldRevealPassword(false); - // Offer generation again. ShowGenerationPopup(); } else if (password_is_generated_) { @@ -544,6 +536,22 @@ GetPasswordManagerClient()->HidePasswordGenerationPopup(); } +void PasswordGenerationAgent::PasswordNoLongerGenerated() { + // Do not treat the password as generated, either here or in the browser. + password_is_generated_ = false; + generation_element_.setShouldRevealPassword(false); + for (blink::WebInputElement& password : + generation_form_data_->password_elements) + password.setAutofilled(false); + password_generation::LogPasswordGenerationEvent( + password_generation::PASSWORD_DELETED); + CopyElementValueToOtherInputElements( + &generation_element_, &generation_form_data_->password_elements); + std::unique_ptr<PasswordForm> presaved_form(CreatePasswordFormToPresave()); + if (presaved_form) + GetPasswordManagerDriver()->PasswordNoLongerGenerated(*presaved_form); +} + void PasswordGenerationAgent::UserTriggeredGeneratePassword() { if (last_focused_password_element_.isNull() || !render_frame()) return;
diff --git a/components/autofill/content/renderer/password_generation_agent.h b/components/autofill/content/renderer/password_generation_agent.h index c7cb5fb2..2af6282 100644 --- a/components/autofill/content/renderer/password_generation_agent.h +++ b/components/autofill/content/renderer/password_generation_agent.h
@@ -113,6 +113,9 @@ // Hides a password generation popup if one exists. void HidePopup(); + // Stops treating a password as generated. + void PasswordNoLongerGenerated(); + // Runs HTML parsing based classifier and saves its outcome to proto. // TODO(crbug.com/621442): Remove client-side form classifier when server-side // classifier is ready.
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn index d642c3f6..a99765e 100644 --- a/components/ntp_snippets/BUILD.gn +++ b/components/ntp_snippets/BUILD.gn
@@ -152,6 +152,7 @@ "remote/test_utils.h", "sessions/foreign_sessions_suggestions_provider_unittest.cc", "sessions/tab_delegate_sync_adapter_unittest.cc", + "user_classifier_unittest.cc", ] deps = [
diff --git a/components/ntp_snippets/user_classifier_unittest.cc b/components/ntp_snippets/user_classifier_unittest.cc new file mode 100644 index 0000000..f8f3a43 --- /dev/null +++ b/components/ntp_snippets/user_classifier_unittest.cc
@@ -0,0 +1,317 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/ntp_snippets/user_classifier.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/memory/ptr_util.h" +#include "base/test/histogram_tester.h" +#include "base/test/simple_test_clock.h" +#include "base/time/time.h" +#include "components/ntp_snippets/features.h" +#include "components/ntp_snippets/ntp_snippets_constants.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#include "components/variations/variations_params_manager.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::DoubleNear; +using testing::Eq; +using testing::Gt; +using testing::Lt; +using testing::SizeIs; + +namespace ntp_snippets { +namespace { + +char kNowString[] = "2017-03-01 10:45"; + +class UserClassifierTest : public testing::Test { + public: + UserClassifierTest() { + UserClassifier::RegisterProfilePrefs(test_prefs_.registry()); + } + + UserClassifier* CreateUserClassifier() { + auto test_clock = base::MakeUnique<base::SimpleTestClock>(); + test_clock_ = test_clock.get(); + + base::Time now; + CHECK(base::Time::FromUTCString(kNowString, &now)); + test_clock_->SetNow(now); + + user_classifier_ = + base::MakeUnique<UserClassifier>(&test_prefs_, std::move(test_clock)); + return user_classifier_.get(); + } + + base::SimpleTestClock* test_clock() { return test_clock_; } + + private: + TestingPrefServiceSimple test_prefs_; + std::unique_ptr<UserClassifier> user_classifier_; + + // Owned by the UserClassifier. + base::SimpleTestClock* test_clock_; + + DISALLOW_COPY_AND_ASSIGN(UserClassifierTest); +}; + +TEST_F(UserClassifierTest, ShouldBeActiveNtpUserInitially) { + UserClassifier* user_classifier = CreateUserClassifier(); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_NTP_USER)); +} + +TEST_F(UserClassifierTest, + ShouldBecomeActiveSuggestionsConsumerByClickingOften) { + UserClassifier* user_classifier = CreateUserClassifier(); + + // After one click still only an active user. + user_classifier->OnEvent(UserClassifier::Metric::SUGGESTIONS_USED); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_NTP_USER)); + + // After a few more clicks, become an active consumer. + for (int i = 0; i < 5; i++) { + test_clock()->Advance(base::TimeDelta::FromHours(1)); + user_classifier->OnEvent(UserClassifier::Metric::SUGGESTIONS_USED); + } + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER)); +} + +TEST_F(UserClassifierTest, + ShouldBecomeActiveSuggestionsConsumerByClickingOftenWithDecreasedParam) { + // Increase the param to one half. + variations::testing::VariationParamsManager variation_params( + kStudyName, + {{"user_classifier_active_consumer_clicks_at_least_once_per_hours", + "36"}}, + {kArticleSuggestionsFeature.name}); + UserClassifier* user_classifier = CreateUserClassifier(); + + // After two clicks still only an active user. + user_classifier->OnEvent(UserClassifier::Metric::SUGGESTIONS_USED); + test_clock()->Advance(base::TimeDelta::FromHours(1)); + user_classifier->OnEvent(UserClassifier::Metric::SUGGESTIONS_USED); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_NTP_USER)); + + // One more click to become an active consumer. + test_clock()->Advance(base::TimeDelta::FromHours(1)); + user_classifier->OnEvent(UserClassifier::Metric::SUGGESTIONS_USED); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER)); +} + +TEST_F(UserClassifierTest, ShouldBecomeRareNtpUserByNoActivity) { + UserClassifier* user_classifier = CreateUserClassifier(); + + // After two days of waiting still an active user. + test_clock()->Advance(base::TimeDelta::FromDays(2)); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_NTP_USER)); + + // Two more days to become a rare user. + test_clock()->Advance(base::TimeDelta::FromDays(2)); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::RARE_NTP_USER)); +} + +TEST_F(UserClassifierTest, + ShouldBecomeRareNtpUserByNoActivityWithDecreasedParam) { + // Decrease the param to one half. + variations::testing::VariationParamsManager variation_params( + kStudyName, + {{"user_classifier_rare_user_opens_ntp_at_most_once_per_hours", "48"}}, + {kArticleSuggestionsFeature.name}); + UserClassifier* user_classifier = CreateUserClassifier(); + + // After one days of waiting still an active user. + test_clock()->Advance(base::TimeDelta::FromDays(1)); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::ACTIVE_NTP_USER)); + + // One more day to become a rare user. + test_clock()->Advance(base::TimeDelta::FromDays(1)); + EXPECT_THAT(user_classifier->GetUserClass(), + Eq(UserClassifier::UserClass::RARE_NTP_USER)); +} + +class UserClassifierMetricTest + : public UserClassifierTest, + public ::testing::WithParamInterface< + std::pair<UserClassifier::Metric, std::string>> { + public: + UserClassifierMetricTest() : UserClassifierTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(UserClassifierMetricTest); +}; + +TEST_P(UserClassifierMetricTest, ShouldDecreaseEstimateAfterEvent) { + UserClassifier::Metric metric = GetParam().first; + UserClassifier* user_classifier = CreateUserClassifier(); + + // The initial event does not decrease the estimate. + user_classifier->OnEvent(metric); + + for (int i = 0; i < 10; i++) { + test_clock()->Advance(base::TimeDelta::FromHours(1)); + double old_metric = user_classifier->GetEstimatedAvgTime(metric); + user_classifier->OnEvent(metric); + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), Lt(old_metric)); + } +} + +TEST_P(UserClassifierMetricTest, ShouldReportToUmaOnEvent) { + UserClassifier::Metric metric = GetParam().first; + const std::string& histogram_name = GetParam().second; + base::HistogramTester histogram_tester; + UserClassifier* user_classifier = CreateUserClassifier(); + + user_classifier->OnEvent(metric); + EXPECT_THAT(histogram_tester.GetAllSamples(histogram_name), SizeIs(1)); +} + +TEST_P(UserClassifierMetricTest, ShouldConvergeTowardsPattern) { + UserClassifier::Metric metric = GetParam().first; + UserClassifier* user_classifier = CreateUserClassifier(); + + // Have the pattern of an event every five hours and start changing it towards + // an event every 10 hours. + for (int i = 0; i < 100; i++) { + test_clock()->Advance(base::TimeDelta::FromHours(5)); + user_classifier->OnEvent(metric); + } + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), + DoubleNear(5.0, 0.1)); + for (int i = 0; i < 3; i++) { + test_clock()->Advance(base::TimeDelta::FromHours(10)); + user_classifier->OnEvent(metric); + } + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), Gt(5.5)); + for (int i = 0; i < 100; i++) { + test_clock()->Advance(base::TimeDelta::FromHours(10)); + user_classifier->OnEvent(metric); + } + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), + DoubleNear(10.0, 0.1)); +} + +TEST_P(UserClassifierMetricTest, ShouldIgnoreSubsequentEventsForHalfAnHour) { + UserClassifier::Metric metric = GetParam().first; + UserClassifier* user_classifier = CreateUserClassifier(); + + // The initial event + user_classifier->OnEvent(metric); + // Subsequent events get ignored for the next 30 minutes. + for (int i = 0; i < 5; i++) { + test_clock()->Advance(base::TimeDelta::FromMinutes(5)); + double old_metric = user_classifier->GetEstimatedAvgTime(metric); + user_classifier->OnEvent(metric); + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), Eq(old_metric)); + } + // An event 30 minutes after the initial event is finally not ignored. + test_clock()->Advance(base::TimeDelta::FromMinutes(5)); + double old_metric = user_classifier->GetEstimatedAvgTime(metric); + user_classifier->OnEvent(metric); + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), Lt(old_metric)); +} + +TEST_P(UserClassifierMetricTest, + ShouldIgnoreSubsequentEventsWithIncreasedLimit) { + UserClassifier::Metric metric = GetParam().first; + // Increase the min_hours to 1.0, i.e. 60 minutes. + variations::testing::VariationParamsManager variation_params( + kStudyName, {{"user_classifier_min_hours", "1.0"}}, + {kArticleSuggestionsFeature.name}); + UserClassifier* user_classifier = CreateUserClassifier(); + + // The initial event + user_classifier->OnEvent(metric); + // Subsequent events get ignored for the next 60 minutes. + for (int i = 0; i < 11; i++) { + test_clock()->Advance(base::TimeDelta::FromMinutes(5)); + double old_metric = user_classifier->GetEstimatedAvgTime(metric); + user_classifier->OnEvent(metric); + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), Eq(old_metric)); + } + // An event 60 minutes after the initial event is finally not ignored. + test_clock()->Advance(base::TimeDelta::FromMinutes(5)); + double old_metric = user_classifier->GetEstimatedAvgTime(metric); + user_classifier->OnEvent(metric); + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), Lt(old_metric)); +} + +TEST_P(UserClassifierMetricTest, ShouldCapDelayBetweenEvents) { + UserClassifier::Metric metric = GetParam().first; + UserClassifier* user_classifier = CreateUserClassifier(); + + // The initial event + user_classifier->OnEvent(metric); + // Wait for an insane amount of time + test_clock()->Advance(base::TimeDelta::FromDays(365)); + user_classifier->OnEvent(metric); + double metric_after_a_year = user_classifier->GetEstimatedAvgTime(metric); + + // Now repeat the same with s/one year/one week. + user_classifier->ClearClassificationForDebugging(); + user_classifier->OnEvent(metric); + test_clock()->Advance(base::TimeDelta::FromDays(7)); + user_classifier->OnEvent(metric); + + // The results should be the same. + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), + Eq(metric_after_a_year)); +} + +TEST_P(UserClassifierMetricTest, + ShouldCapDelayBetweenEventsWithDecreasedLimit) { + UserClassifier::Metric metric = GetParam().first; + // Decrease the max_hours to 72, i.e. 3 days. + variations::testing::VariationParamsManager variation_params( + kStudyName, {{"user_classifier_max_hours", "72"}}, + {kArticleSuggestionsFeature.name}); + UserClassifier* user_classifier = CreateUserClassifier(); + + // The initial event + user_classifier->OnEvent(metric); + // Wait for an insane amount of time + test_clock()->Advance(base::TimeDelta::FromDays(365)); + user_classifier->OnEvent(metric); + double metric_after_a_year = user_classifier->GetEstimatedAvgTime(metric); + + // Now repeat the same with s/one year/two days. + user_classifier->ClearClassificationForDebugging(); + user_classifier->OnEvent(metric); + test_clock()->Advance(base::TimeDelta::FromDays(3)); + user_classifier->OnEvent(metric); + + // The results should be the same. + EXPECT_THAT(user_classifier->GetEstimatedAvgTime(metric), + Eq(metric_after_a_year)); +} + +INSTANTIATE_TEST_CASE_P( + , // An empty prefix for the parametrized tests names (no need to + // distinguish the only instance we make here). + UserClassifierMetricTest, + testing::Values( + std::make_pair(UserClassifier::Metric::NTP_OPENED, + "NewTabPage.UserClassifier.AverageHoursToOpenNTP"), + std::make_pair( + UserClassifier::Metric::SUGGESTIONS_SHOWN, + "NewTabPage.UserClassifier.AverageHoursToShowSuggestions"), + std::make_pair( + UserClassifier::Metric::SUGGESTIONS_USED, + "NewTabPage.UserClassifier.AverageHoursToUseSuggestions"))); + +} // namespace +} // namespace ntp_snippets
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn index 426fd6e..6a6acd9 100644 --- a/components/subresource_filter/content/browser/BUILD.gn +++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -8,6 +8,8 @@ "activation_state_computing_navigation_throttle.h", "async_document_subresource_filter.cc", "async_document_subresource_filter.h", + "content_activation_list_utils.cc", + "content_activation_list_utils.h", "content_ruleset_service.cc", "content_ruleset_service.h", "content_subresource_filter_driver_factory.cc",
diff --git a/components/subresource_filter/content/browser/content_activation_list_utils.cc b/components/subresource_filter/content/browser/content_activation_list_utils.cc new file mode 100644 index 0000000..6689d60 --- /dev/null +++ b/components/subresource_filter/content/browser/content_activation_list_utils.cc
@@ -0,0 +1,26 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/subresource_filter/content/browser/content_activation_list_utils.h" + +namespace subresource_filter { + +ActivationList GetListForThreatTypeAndMetadata( + safe_browsing::SBThreatType threat_type, + safe_browsing::ThreatPatternType threat_type_metadata) { + bool is_phishing_interstitial = + (threat_type == safe_browsing::SB_THREAT_TYPE_URL_PHISHING); + bool is_soc_engineering_ads_interstitial = + threat_type_metadata == + safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS; + if (is_phishing_interstitial) { + if (is_soc_engineering_ads_interstitial) { + return ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL; + } + return ActivationList::PHISHING_INTERSTITIAL; + } + return ActivationList::NONE; +} + +} // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/content_activation_list_utils.h b/components/subresource_filter/content/browser/content_activation_list_utils.h new file mode 100644 index 0000000..dc23a48 --- /dev/null +++ b/components/subresource_filter/content/browser/content_activation_list_utils.h
@@ -0,0 +1,19 @@ +// 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 COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_ACTIVATION_LIST_UTILS_H_ +#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_ACTIVATION_LIST_UTILS_H_ + +#include "components/safe_browsing_db/util.h" +#include "components/subresource_filter/core/common/activation_list.h" + +namespace subresource_filter { + +ActivationList GetListForThreatTypeAndMetadata( + safe_browsing::SBThreatType threat_type, + safe_browsing::ThreatPatternType threat_type_metadata); + +} // namespace subresource_filter + +#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_CONTENT_ACTIVATION_LIST_UTILS_H_
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc index b9c7d1c..bce50cd 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
@@ -7,6 +7,7 @@ #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/time/time.h" +#include "components/subresource_filter/content/browser/content_activation_list_utils.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/common/subresource_filter_messages.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" @@ -41,6 +42,17 @@ return rate == 1 || (rate > 0 && base::RandDouble() < rate); } +// Records histograms about the length of redirect chains, and about the pattern +// of whether each URL in the chain matched the activation list. +#define REPORT_REDIRECT_PATTERN_FOR_SUFFIX(suffix, hits_pattern, chain_size) \ + do { \ + UMA_HISTOGRAM_ENUMERATION( \ + "SubresourceFilter.PageLoad.RedirectChainMatchPattern." suffix, \ + hits_pattern, 0x10); \ + UMA_HISTOGRAM_COUNTS( \ + "SubresourceFilter.PageLoad.RedirectChainLength." suffix, chain_size); \ + } while (0) + } // namespace // static @@ -120,18 +132,8 @@ const std::vector<GURL>& redirect_urls, safe_browsing::SBThreatType threat_type, safe_browsing::ThreatPatternType threat_type_metadata) { - bool is_phishing_interstitial = - (threat_type == safe_browsing::SB_THREAT_TYPE_URL_PHISHING); - bool is_soc_engineering_ads_interstitial = - threat_type_metadata == - safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS; - - if (is_phishing_interstitial) { - if (is_soc_engineering_ads_interstitial) { - AddActivationListMatch(url, ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); - } - AddActivationListMatch(url, ActivationList::PHISHING_INTERSTITIAL); - } + AddActivationListMatch( + url, GetListForThreatTypeAndMetadata(threat_type, threat_type_metadata)); } void ContentSubresourceFilterDriverFactory::AddHostOfURLToWhitelistSet( @@ -158,15 +160,23 @@ switch (scope) { case ActivationScope::ALL_SITES: return ActivationDecision::ACTIVATED; - case ActivationScope::ACTIVATION_LIST: + case ActivationScope::ACTIVATION_LIST: { // The logic to ensure only http/https URLs are activated lives in // AddActivationListMatch to ensure the activation list only has relevant // entries. DCHECK(url.SchemeIsHTTPOrHTTPS() || - !DidURLMatchCurrentActivationList(url)); - return DidURLMatchCurrentActivationList(url) - ? ActivationDecision::ACTIVATED - : ActivationDecision::ACTIVATION_LIST_NOT_MATCHED; + !DidURLMatchActivationList(url, GetCurrentActivationList())); + bool should_activate = + DidURLMatchActivationList(url, GetCurrentActivationList()); + if (GetCurrentActivationList() == ActivationList::PHISHING_INTERSTITIAL) { + // Handling special case, where activation on the phishing sites also + // mean the activation on the sites with social engineering metadata. + should_activate |= DidURLMatchActivationList( + url, ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); + } + return should_activate ? ActivationDecision::ACTIVATED + : ActivationDecision::ACTIVATION_LIST_NOT_MATCHED; + } default: return ActivationDecision::ACTIVATION_DISABLED; } @@ -321,54 +331,79 @@ ActivateForFrameHostIfNeeded(render_frame_host, url); } -bool ContentSubresourceFilterDriverFactory::DidURLMatchCurrentActivationList( - const GURL& url) const { +bool ContentSubresourceFilterDriverFactory::DidURLMatchActivationList( + const GURL& url, + ActivationList activation_list) const { auto match_types = activation_list_matches_.find(DistillURLToHostAndPath(url)); return match_types != activation_list_matches_.end() && - match_types->second.find(GetCurrentActivationList()) != - match_types->second.end(); + match_types->second.find(activation_list) != match_types->second.end(); } void ContentSubresourceFilterDriverFactory::AddActivationListMatch( const GURL& url, ActivationList match_type) { + if (match_type == ActivationList::NONE) + return; if (url.has_host() && url.SchemeIsHTTPOrHTTPS()) activation_list_matches_[DistillURLToHostAndPath(url)].insert(match_type); } -void ContentSubresourceFilterDriverFactory::RecordRedirectChainMatchPattern() - const { +int ContentSubresourceFilterDriverFactory::CalculateHitPatternForActivationList( + ActivationList activation_list) const { int hits_pattern = 0; const int kInitialURLHitMask = 0x4; const int kRedirectURLHitMask = 0x2; const int kFinalURLHitMask = 0x1; if (navigation_chain_.size() > 1) { - if (DidURLMatchCurrentActivationList(navigation_chain_.back())) + if (DidURLMatchActivationList(navigation_chain_.back(), activation_list)) hits_pattern |= kFinalURLHitMask; - if (DidURLMatchCurrentActivationList(navigation_chain_.front())) + if (DidURLMatchActivationList(navigation_chain_.front(), activation_list)) hits_pattern |= kInitialURLHitMask; // Examine redirects. for (size_t i = 1; i < navigation_chain_.size() - 1; ++i) { - if (DidURLMatchCurrentActivationList(navigation_chain_[i])) { + if (DidURLMatchActivationList(navigation_chain_[i], activation_list)) { hits_pattern |= kRedirectURLHitMask; break; } } } else { if (navigation_chain_.size() && - DidURLMatchCurrentActivationList(navigation_chain_.front())) { + DidURLMatchActivationList(navigation_chain_.front(), activation_list)) { hits_pattern = 0x8; // One url hit. } } + return hits_pattern; +} + +void ContentSubresourceFilterDriverFactory::RecordRedirectChainMatchPattern() + const { + RecordRedirectChainMatchPatternForList( + ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL); + RecordRedirectChainMatchPatternForList(ActivationList::PHISHING_INTERSTITIAL); +} + +void ContentSubresourceFilterDriverFactory:: + RecordRedirectChainMatchPatternForList( + ActivationList activation_list) const { + int hits_pattern = CalculateHitPatternForActivationList(activation_list); if (!hits_pattern) return; - UMA_HISTOGRAM_ENUMERATION( - "SubresourceFilter.PageLoad.RedirectChainMatchPattern", hits_pattern, - 0x10 /* max value */); - UMA_HISTOGRAM_COUNTS("SubresourceFilter.PageLoad.RedirectChainLength", - navigation_chain_.size()); + size_t chain_size = navigation_chain_.size(); + switch (activation_list) { + case ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL: + REPORT_REDIRECT_PATTERN_FOR_SUFFIX("SocialEngineeringAdsInterstitial", + hits_pattern, chain_size); + break; + case ActivationList::PHISHING_INTERSTITIAL: + REPORT_REDIRECT_PATTERN_FOR_SUFFIX("PhishingInterstital", hits_pattern, + chain_size); + break; + default: + NOTREACHED(); + break; + } } } // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h index ee1abda..658f6261 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h +++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
@@ -152,11 +152,17 @@ const content::Referrer& referrer, ui::PageTransition page_transition); - bool DidURLMatchCurrentActivationList(const GURL& url) const; + bool DidURLMatchActivationList(const GURL& url, + ActivationList activation_list) const; void AddActivationListMatch(const GURL& url, ActivationList match_type); + int CalculateHitPatternForActivationList( + ActivationList activation_list) const; void RecordRedirectChainMatchPattern() const; + void RecordRedirectChainMatchPatternForList( + ActivationList activation_list) const; + std::unique_ptr<SubresourceFilterClient> client_; HostPathSet whitelisted_hosts_;
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc index 2c1e34e..f02b9d6 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
@@ -9,10 +9,12 @@ #include "base/metrics/field_trial.h" #include "base/test/histogram_tester.h" #include "components/safe_browsing_db/util.h" +#include "components/subresource_filter/content/browser/content_activation_list_utils.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/common/subresource_filter_messages.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h" +#include "components/subresource_filter/core/common/activation_list.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/mock_render_process_host.h" @@ -61,6 +63,18 @@ NUM_HIT_PATTERNS, }; +std::string GetSuffixForList(const ActivationList& type) { + switch (type) { + case ActivationList::SOCIAL_ENG_ADS_INTERSTITIAL: + return ".SocialEngineeringAdsInterstitial"; + case ActivationList::PHISHING_INTERSTITIAL: + return ".PhishingInterstital"; + case ActivationList::NONE: + return std::string(); + } + return std::string(); +} + struct ActivationListTestData { ActivationDecision expected_activation_decision; const char* const activation_list; @@ -124,6 +138,10 @@ subresource_filter::kActivationListSocialEngineeringAdsInterstitial, safe_browsing::SB_THREAT_TYPE_URL_PHISHING, safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS}, + {ActivationDecision::ACTIVATED, + subresource_filter::kActivationListPhishingInterstitial, + safe_browsing::SB_THREAT_TYPE_URL_PHISHING, + safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS}, }; struct ActivationScopeTestData { @@ -268,18 +286,20 @@ content::RenderFrameHostTester* rfh_tester = content::RenderFrameHostTester::For(main_rfh()); rfh_tester->AppendChild(kSubframeName); + ActivationList activation_list = + GetListForThreatTypeAndMetadata(threat_type, threat_type_metadata); + const std::string suffix(GetSuffixForList(activation_list)); if (expected_pattern != EMPTY) { - EXPECT_THAT(tester.GetAllSamples(kMatchesPatternHistogramName), + EXPECT_THAT(tester.GetAllSamples(kMatchesPatternHistogramName + suffix), ::testing::ElementsAre(base::Bucket(expected_pattern, 1))); EXPECT_THAT( - tester.GetAllSamples(kNavigationChainSize), + tester.GetAllSamples(kNavigationChainSize + suffix), ::testing::ElementsAre(base::Bucket(navigation_chain.size(), 1))); - } else { - EXPECT_THAT(tester.GetAllSamples(kMatchesPatternHistogramName), + EXPECT_THAT(tester.GetAllSamples(kMatchesPatternHistogramName + suffix), ::testing::IsEmpty()); - EXPECT_THAT(tester.GetAllSamples(kNavigationChainSize), + EXPECT_THAT(tester.GetAllSamples(kNavigationChainSize + suffix), ::testing::IsEmpty()); } } @@ -426,10 +446,10 @@ kActivationScopeAllSites, kActivationListSocialEngineeringAdsInterstitial); const GURL url(kExampleUrlWithParams); - NavigateAndExpectActivation({true}, {url}, EMPTY, + NavigateAndExpectActivation({true}, {url}, NO_REDIRECTS_HIT, ActivationDecision::ACTIVATION_DISABLED); factory()->AddHostOfURLToWhitelistSet(url); - NavigateAndExpectActivation({true}, {url}, EMPTY, + NavigateAndExpectActivation({true}, {url}, NO_REDIRECTS_HIT, ActivationDecision::ACTIVATION_DISABLED); } @@ -488,6 +508,8 @@ EmulateFailedNavigationAndExpectNoActivation(url); } +// TODO(melandory): refactor the test so it no longer require the current +// activation list to be matching. TEST_F(ContentSubresourceFilterDriverFactoryTest, RedirectPatternTest) { base::FieldTrialList field_trial_list(nullptr); testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle( @@ -675,13 +697,14 @@ const GURL test_url("https://example.com/nonsoceng?q=engsocnon"); std::vector<GURL> navigation_chain; - const bool expected_activation = - test_data.expected_activation_decision == ActivationDecision::ACTIVATED; + ActivationList effective_list = GetListForThreatTypeAndMetadata( + test_data.threat_type, test_data.threat_type_metadata); NavigateAndExpectActivation( {false, false, false, true}, {GURL(kUrlA), GURL(kUrlB), GURL(kUrlC), test_url}, test_data.threat_type, test_data.threat_type_metadata, content::Referrer(), - ui::PAGE_TRANSITION_LINK, expected_activation ? F0M0L1 : EMPTY, + ui::PAGE_TRANSITION_LINK, + effective_list != ActivationList::NONE ? F0M0L1 : EMPTY, test_data.expected_activation_decision); };
diff --git a/components/subresource_filter/core/browser/BUILD.gn b/components/subresource_filter/core/browser/BUILD.gn index 4dbd01a..88b446da 100644 --- a/components/subresource_filter/core/browser/BUILD.gn +++ b/components/subresource_filter/core/browser/BUILD.gn
@@ -33,6 +33,7 @@ "//base/test:test_support", "//components/variations", "//testing/gtest", + "//third_party/protobuf:protobuf_lite", ] }
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 9166cfe3..20d5c188 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -584,8 +584,8 @@ DCHECK(gfx::SkIRectToRect(actual_bmp.bounds()).Contains(matching_mask)); - for (int x = matching_mask.x(); x < matching_mask.width(); ++x) { - for (int y = matching_mask.y(); y < matching_mask.height(); ++y) { + for (int x = matching_mask.x(); x < matching_mask.right(); ++x) { + for (int y = matching_mask.y(); y < matching_mask.bottom(); ++y) { SkColor actual_color = actual_bmp.getColor(x, y); SkColor expected_color = expected_bmp.getColor(x, y); if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) { @@ -613,10 +613,12 @@ protected: enum ScreenshotEncoding { ENCODING_PNG, ENCODING_JPEG }; void CaptureScreenshotAndCompareTo(const SkBitmap& expected_bitmap, - ScreenshotEncoding encoding) { + ScreenshotEncoding encoding, + bool fromSurface) { std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue()); params->SetString("format", encoding == ENCODING_PNG ? "png" : "jpeg"); params->SetInteger("quality", 100); + params->SetBoolean("fromSurface", fromSurface); SendCommand("Page.captureScreenshot", std::move(params)); std::string base64; @@ -701,7 +703,7 @@ expected_bitmap.allocN32Pixels(scaled_box_size.width(), scaled_box_size.height()); expected_bitmap.eraseColor(SkColorSetRGB(0x00, 0x00, 0xff)); - CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG, true); // Reset for next screenshot. SendCommand("Emulation.resetViewport", nullptr); @@ -735,7 +737,7 @@ ->GetPhysicalBackingSize(); expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); - CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_PNG, false); } IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, CaptureScreenshotJpeg) { @@ -758,7 +760,7 @@ ->GetPhysicalBackingSize(); expected_bitmap.allocN32Pixels(view_size.width(), view_size.height()); expected_bitmap.eraseColor(SkColorSetRGB(0x12, 0x34, 0x56)); - CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_JPEG); + CaptureScreenshotAndCompareTo(expected_bitmap, ENCODING_JPEG, false); } // Setting frame size (through RWHV) is not supported on Android. @@ -1414,6 +1416,121 @@ EXPECT_EQ(transient_entry->GetSSL().certificate, last_shown_certificate()); } +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, CertificateError) { + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); + https_server.ServeFilesFromSourceDirectory("content/test/data"); + ASSERT_TRUE(https_server.Start()); + GURL test_url = https_server.GetURL("/devtools/navigation.html"); + std::unique_ptr<base::DictionaryValue> params; + std::unique_ptr<base::DictionaryValue> command_params; + int eventId; + + shell()->LoadURL(GURL("about:blank")); + WaitForLoadStop(shell()->web_contents()); + + Attach(); + SendCommand("Network.enable", nullptr, true); + SendCommand("Security.enable", nullptr, false); + command_params.reset(new base::DictionaryValue()); + command_params->SetBoolean("override", true); + SendCommand("Security.setOverrideCertificateErrors", + std::move(command_params), true); + + // Test cancel. + SendCommand("Network.clearBrowserCache", nullptr, true); + SendCommand("Network.clearBrowserCookies", nullptr, true); + TestNavigationObserver cancel_observer(shell()->web_contents(), 1); + shell()->LoadURL(test_url); + params = WaitForNotification("Security.certificateError", false); + EXPECT_TRUE(shell()->web_contents()->GetController().GetPendingEntry()); + EXPECT_EQ( + test_url, + shell()->web_contents()->GetController().GetPendingEntry()->GetURL()); + EXPECT_TRUE(params->GetInteger("eventId", &eventId)); + command_params.reset(new base::DictionaryValue()); + command_params->SetInteger("eventId", eventId); + command_params->SetString("action", "cancel"); + SendCommand("Security.handleCertificateError", std::move(command_params), + false); + cancel_observer.Wait(); + EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry()); + EXPECT_EQ(GURL("about:blank"), shell() + ->web_contents() + ->GetController() + .GetLastCommittedEntry() + ->GetURL()); + + // Test continue. + SendCommand("Network.clearBrowserCache", nullptr, true); + SendCommand("Network.clearBrowserCookies", nullptr, true); + TestNavigationObserver continue_observer(shell()->web_contents(), 1); + shell()->LoadURL(test_url); + params = WaitForNotification("Security.certificateError", false); + EXPECT_TRUE(params->GetInteger("eventId", &eventId)); + command_params.reset(new base::DictionaryValue()); + command_params->SetInteger("eventId", eventId); + command_params->SetString("action", "continue"); + SendCommand("Security.handleCertificateError", std::move(command_params), + false); + WaitForNotification("Network.loadingFinished", true); + continue_observer.Wait(); + EXPECT_EQ(test_url, shell() + ->web_contents() + ->GetController() + .GetLastCommittedEntry() + ->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SubresourceWithCertificateError) { + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_EXPIRED); + https_server.ServeFilesFromSourceDirectory("content/test/data/devtools"); + ASSERT_TRUE(https_server.Start()); + GURL test_url = https_server.GetURL("/image.html"); + std::unique_ptr<base::DictionaryValue> params; + std::unique_ptr<base::DictionaryValue> command_params; + int eventId; + + shell()->LoadURL(GURL("about:blank")); + WaitForLoadStop(shell()->web_contents()); + + Attach(); + SendCommand("Security.enable", nullptr, false); + command_params.reset(new base::DictionaryValue()); + command_params->SetBoolean("override", true); + SendCommand("Security.setOverrideCertificateErrors", + std::move(command_params), true); + + TestNavigationObserver observer(shell()->web_contents(), 1); + shell()->LoadURL(test_url); + + // Expect certificateError event for main frame. + params = WaitForNotification("Security.certificateError", false); + EXPECT_TRUE(params->GetInteger("eventId", &eventId)); + command_params.reset(new base::DictionaryValue()); + command_params->SetInteger("eventId", eventId); + command_params->SetString("action", "continue"); + SendCommand("Security.handleCertificateError", std::move(command_params), + false); + + // Expect certificateError event for image. + params = WaitForNotification("Security.certificateError", false); + EXPECT_TRUE(params->GetInteger("eventId", &eventId)); + command_params.reset(new base::DictionaryValue()); + command_params->SetInteger("eventId", eventId); + command_params->SetString("action", "continue"); + SendCommand("Security.handleCertificateError", std::move(command_params), + false); + + observer.Wait(); + EXPECT_EQ(test_url, shell() + ->web_contents() + ->GetController() + .GetLastCommittedEntry() + ->GetURL()); +} + IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetDiscovery) { std::string temp; std::set<std::string> ids;
diff --git a/content/browser/devtools/protocol/security_handler.cc b/content/browser/devtools/protocol/security_handler.cc index 6b6808e..f3468b4 100644 --- a/content/browser/devtools/protocol/security_handler.cc +++ b/content/browser/devtools/protocol/security_handler.cc
@@ -146,6 +146,32 @@ Maybe<std::string>(security_style_explanations.summary)); } +void SecurityHandler::DidFinishNavigation(NavigationHandle* navigation_handle) { + if (certificate_errors_overriden_) + FlushPendingCertificateErrorNotifications(); +} + +void SecurityHandler::FlushPendingCertificateErrorNotifications() { + for (auto callback : cert_error_callbacks_) + callback.second.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL); + cert_error_callbacks_.clear(); +} + +bool SecurityHandler::NotifyCertificateError(int cert_error, + const GURL& request_url, + CertErrorCallback handler) { + if (!enabled_) + return false; + frontend_->CertificateError(++last_cert_error_id_, + net::ErrorToShortString(cert_error), + request_url.spec()); + if (!certificate_errors_overriden_) { + return false; + } + cert_error_callbacks_[last_cert_error_id_] = handler; + return true; +} + Response SecurityHandler::Enable() { enabled_ = true; if (host_) @@ -156,7 +182,9 @@ Response SecurityHandler::Disable() { enabled_ = false; + certificate_errors_overriden_ = false; WebContentsObserver::Observe(nullptr); + FlushPendingCertificateErrorNotifications(); return Response::OK(); } @@ -173,5 +201,36 @@ return Response::OK(); } +Response SecurityHandler::HandleCertificateError(int event_id, + const String& action) { + if (cert_error_callbacks_.find(event_id) == cert_error_callbacks_.end()) { + return Response::Error( + String("Unknown event id: " + std::to_string(event_id))); + } + content::CertificateRequestResultType type = + content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL; + Response response = Response::OK(); + if (action == Security::CertificateErrorActionEnum::Continue) { + type = content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE; + } else if (action == Security::CertificateErrorActionEnum::Cancel) { + type = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL; + } else { + response = + Response::Error(String("Unknown Certificate Error Action: " + action)); + } + cert_error_callbacks_[event_id].Run(type); + cert_error_callbacks_.erase(event_id); + return response; +} + +Response SecurityHandler::SetOverrideCertificateErrors(bool override) { + if (override && !enabled_) + return Response::Error("Security domain not enabled"); + certificate_errors_overriden_ = override; + if (!override) + FlushPendingCertificateErrorNotifications(); + return Response::OK(); +} + } // namespace protocol } // namespace content
diff --git a/content/browser/devtools/protocol/security_handler.h b/content/browser/devtools/protocol/security_handler.h index 136811a5..e9085699 100644 --- a/content/browser/devtools/protocol/security_handler.h +++ b/content/browser/devtools/protocol/security_handler.h
@@ -5,9 +5,12 @@ #ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_SECURITY_HANDLER_H_ #define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_SECURITY_HANDLER_H_ +#include <unordered_map> + #include "base/macros.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/security.h" +#include "content/public/browser/certificate_request_result_type.h" #include "content/public/browser/web_contents_observer.h" namespace content { @@ -21,27 +24,48 @@ public Security::Backend, public WebContentsObserver { public: + using CertErrorCallback = + base::Callback<void(content::CertificateRequestResultType)>; + SecurityHandler(); ~SecurityHandler() override; + static SecurityHandler* FromAgentHost(DevToolsAgentHostImpl* host); + + // DevToolsDomainHandler overrides void Wire(UberDispatcher* dispatcher) override; void SetRenderFrameHost(RenderFrameHostImpl* host) override; - static SecurityHandler* FromAgentHost(DevToolsAgentHostImpl* host); - + // Security::Backend overrides. Response Enable() override; Response Disable() override; Response ShowCertificateViewer() override; + Response HandleCertificateError(int event_id, const String& action) override; + Response SetOverrideCertificateErrors(bool override) override; + + // NotifyCertificateError will send a CertificateError event. Returns true if + // the error is expected to be handled by a corresponding + // HandleCertificateError command, and false otherwise. + bool NotifyCertificateError(int cert_error, + const GURL& request_url, + CertErrorCallback callback); private: + using CertErrorCallbackMap = std::unordered_map<int, CertErrorCallback>; + void AttachToRenderFrameHost(); + void FlushPendingCertificateErrorNotifications(); // WebContentsObserver overrides void DidChangeVisibleSecurityState() override; + void DidFinishNavigation(NavigationHandle* navigation_handle) override; std::unique_ptr<Security::Frontend> frontend_; bool enabled_; RenderFrameHostImpl* host_; + int last_cert_error_id_ = 0; + CertErrorCallbackMap cert_error_callbacks_; + bool certificate_errors_overriden_ = false; DISALLOW_COPY_AND_ASSIGN(SecurityHandler); };
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index 7c2a2063..399409d6 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -71,7 +71,7 @@ FrameTreeNode* frame_tree_node() { return frame_tree_node_; } - // DevTooolsAgentHost overrides. + // DevToolsAgentHost overrides. void DisconnectWebContents() override; void ConnectWebContents(WebContents* web_contents) override; BrowserContext* GetBrowserContext() override;
diff --git a/content/browser/pointer_lock_browsertest.cc b/content/browser/pointer_lock_browsertest.cc index 07dd093..cf1a792e 100644 --- a/content/browser/pointer_lock_browsertest.cc +++ b/content/browser/pointer_lock_browsertest.cc
@@ -272,4 +272,47 @@ EXPECT_EQ(17, movementY); } +// Flaky on Mac. See comment on https://codereview.chromium.org/2760343002. +#if defined(OS_MACOSX) +#define MAYBE_PointerLockChildFrameDetached \ + DISABLED_PointerLockChildFrameDetached +#else +#define MAYBE_PointerLockChildFrameDetached PointerLockChildFrameDetached +#endif +// Tests that the browser will not unlock the pointer if a RenderWidgetHostView +// that doesn't hold the pointer lock is destroyed. +IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, + MAYBE_PointerLockChildFrameDetached) { + GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b)")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + + // Request a pointer lock on the root frame's body. + EXPECT_TRUE(ExecuteScript(root, "document.body.requestPointerLock()")); + + // Root frame should have been granted pointer lock. + bool locked = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool(root, + "window.domAutomationController.send(" + "document.pointerLockElement == " + "document.body);", + &locked)); + EXPECT_TRUE(locked); + + // Root (platform) RenderWidgetHostView should have the pointer locked. + EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked()); + EXPECT_EQ(root->current_frame_host()->GetRenderWidgetHost(), + web_contents()->GetMouseLockWidget()); + + // Detach the child frame. + EXPECT_TRUE(ExecuteScript(root, "document.querySelector('iframe').remove()")); + + // Root (platform) RenderWidgetHostView should still have the pointer locked. + EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked()); + EXPECT_EQ(root->current_frame_host()->GetRenderWidgetHost(), + web_contents()->GetMouseLockWidget()); +} + } // namespace content
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc index df2e757..c9341eb 100644 --- a/content/browser/ssl/ssl_manager.cc +++ b/content/browser/ssl/ssl_manager.cc
@@ -11,6 +11,8 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "base/supports_user_data.h" +#include "content/browser/devtools/devtools_agent_host_impl.h" +#include "content/browser/devtools/protocol/security_handler.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_request_info_impl.h" @@ -20,6 +22,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/certificate_request_result_type.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/ssl_host_state_delegate.h" #include "net/url_request/url_request.h" @@ -37,8 +40,17 @@ SSL_GOOD_CERT_SEEN_EVENT_MAX = 2 }; +void OnAllowCertificateWithRecordDecision( + bool record_decision, + const base::Callback<void(bool, content::CertificateRequestResultType)>& + callback, + CertificateRequestResultType decision) { + callback.Run(record_decision, decision); +} + void OnAllowCertificate(SSLErrorHandler* handler, SSLHostStateDelegate* state_delegate, + bool record_decision, CertificateRequestResultType decision) { DCHECK(handler->ssl_info().is_valid()); switch (decision) { @@ -53,7 +65,7 @@ // While AllowCert() executes synchronously on this thread, // ContinueRequest() gets posted to a different thread. Calling // AllowCert() first ensures deterministic ordering. - if (state_delegate) { + if (record_decision && state_delegate) { state_delegate->AllowCert(handler->request_url().host(), *handler->ssl_info().cert.get(), handler->cert_error()); @@ -356,11 +368,24 @@ const net::SSLInfo& ssl_info = handler->ssl_info(); const GURL& request_url = handler->request_url(); ResourceType resource_type = handler->resource_type(); - GetContentClient()->browser()->AllowCertificateError( - web_contents, cert_error, ssl_info, request_url, resource_type, - overridable, strict_enforcement, expired_previous_decision, + + base::Callback<void(bool, content::CertificateRequestResultType)> callback = base::Bind(&OnAllowCertificate, base::Owned(handler.release()), - ssl_host_state_delegate_)); + ssl_host_state_delegate_); + + DevToolsAgentHostImpl* agent_host = static_cast<DevToolsAgentHostImpl*>( + DevToolsAgentHost::GetOrCreateFor(web_contents).get()); + protocol::SecurityHandler* security_handler = + protocol::SecurityHandler::FromAgentHost(agent_host); + if (!security_handler || + !security_handler->NotifyCertificateError( + cert_error, request_url, + base::Bind(&OnAllowCertificateWithRecordDecision, false, callback))) { + GetContentClient()->browser()->AllowCertificateError( + web_contents, cert_error, ssl_info, request_url, resource_type, + overridable, strict_enforcement, expired_previous_decision, + base::Bind(&OnAllowCertificateWithRecordDecision, true, callback)); + } } void SSLManager::UpdateEntry(NavigationEntryImpl* entry,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 093f1f22..b165369 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1739,7 +1739,7 @@ view_->RestoreFocus(); } - if (mouse_lock_widget_) + if (render_widget_host == mouse_lock_widget_) LostMouseLock(mouse_lock_widget_); }
diff --git a/content/common/service_worker/service_worker_utils_unittest.cc b/content/common/service_worker/service_worker_utils_unittest.cc index 96564a2..f75f04c7 100644 --- a/content/common/service_worker/service_worker_utils_unittest.cc +++ b/content/common/service_worker/service_worker_utils_unittest.cc
@@ -91,6 +91,10 @@ // URLs canonicalize \ to / so this is equivalent to "...//x" ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches( GURL("http://www.example.com/\\x"), GURL("http://www.example.com//x"))); + + // URLs that are in different origin shouldn't match. + ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches( + GURL("https://evil.com"), GURL("https://evil.com.example.com"))); } TEST(ServiceWorkerUtilsTest, FindLongestScopeMatch) {
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index f7dce75..ad87adc 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -60,6 +60,7 @@ "//services/service_manager/public/interfaces:interfaces_java", "//services/service_manager/public/java:service_manager_java", "//services/shape_detection/public/interfaces:interfaces_java", + "//skia/public/interfaces:interfaces_java", "//third_party/WebKit/public:blink_headers_java", "//third_party/WebKit/public:mojo_bindings_java", "//third_party/android_tools:android_support_annotations_java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/shapedetection/FaceDetectionImpl.java b/content/public/android/java/src/org/chromium/content/browser/shapedetection/FaceDetectionImpl.java index 17ff5506..50bc619 100644 --- a/content/public/android/java/src/org/chromium/content/browser/shapedetection/FaceDetectionImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/shapedetection/FaceDetectionImpl.java
@@ -12,11 +12,10 @@ import org.chromium.base.Log; import org.chromium.gfx.mojom.RectF; import org.chromium.mojo.system.MojoException; -import org.chromium.mojo.system.SharedBufferHandle; -import org.chromium.mojo.system.SharedBufferHandle.MapFlags; import org.chromium.shape_detection.mojom.FaceDetection; import org.chromium.shape_detection.mojom.FaceDetectionResult; import org.chromium.shape_detection.mojom.FaceDetectorOptions; +import org.chromium.skia.mojom.ColorType; import java.nio.ByteBuffer; @@ -36,29 +35,42 @@ } @Override - public void detect( - SharedBufferHandle frameData, int width, int height, DetectResponse callback) { + public void detect(org.chromium.skia.mojom.Bitmap bitmapData, DetectResponse callback) { + int width = bitmapData.width; + int height = bitmapData.height; final long numPixels = (long) width * height; // TODO(xianglu): https://crbug.com/670028 homogeneize overflow checking. - if (!frameData.isValid() || width <= 0 || height <= 0 || numPixels > (Long.MAX_VALUE / 4)) { + if (bitmapData.pixelData == null || width <= 0 || height <= 0 + || numPixels > (Long.MAX_VALUE / 4)) { Log.d(TAG, "Invalid argument(s)."); callback.call(new FaceDetectionResult()); return; } - ByteBuffer imageBuffer = frameData.map(0, numPixels * 4, MapFlags.none()); - if (imageBuffer.capacity() <= 0) { - Log.d(TAG, "Failed to map from SharedBufferHandle."); + // TODO(junwei.fu): Consider supporting other bitmap pixel formats, + // https://crbug.com/684921. + if (bitmapData.colorType != ColorType.RGBA_8888 + && bitmapData.colorType != ColorType.BGRA_8888) { + Log.e(TAG, "Unsupported bitmap pixel format"); callback.call(new FaceDetectionResult()); return; } + ByteBuffer imageBuffer = ByteBuffer.wrap(bitmapData.pixelData); + if (imageBuffer.capacity() <= 0) { + Log.d(TAG, "Failed to wrap from Bitmap."); + callback.call(new FaceDetectionResult()); + return; + } + + // TODO(junwei.fu): Use |bitmapData| directly for |unPremultipliedBitmap| to spare a copy + // if the bitmap pixel format is RGB_565, the ARGB_8888 Bitmap doesn't need to be created + // in this case, https://crbug.com/684930. Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); // An int array is needed to construct a Bitmap. However the Bytebuffer - // we get from |sharedBufferHandle| is directly allocated and does not - // have a supporting array. Therefore we need to copy from |imageBuffer| - // to create this intermediate Bitmap. + // we get from |bitmapData| is directly allocated and does not have a supporting array. + // Therefore we need to copy from |imageBuffer| to create this intermediate Bitmap. // TODO(xianglu): Consider worker pool as appropriate threads. // http://crbug.com/655814 bitmap.copyPixelsFromBuffer(imageBuffer);
diff --git a/content/test/data/devtools/image.html b/content/test/data/devtools/image.html new file mode 100644 index 0000000..19e6ef61 --- /dev/null +++ b/content/test/data/devtools/image.html
@@ -0,0 +1,6 @@ +<html> +<body> +Image page. +<img src="test.jpg"> +</body> +</html>
diff --git a/content/test/data/devtools/test.jpg b/content/test/data/devtools/test.jpg new file mode 100644 index 0000000..be004c9 --- /dev/null +++ b/content/test/data/devtools/test.jpg Binary files differ
diff --git a/courgette/disassembler_elf_32.cc b/courgette/disassembler_elf_32.cc index e305b4ce..e35a3af 100644 --- a/courgette/disassembler_elf_32.cc +++ b/courgette/disassembler_elf_32.cc
@@ -181,13 +181,6 @@ return false; } - // Finally sort rel32 locations. - std::sort(rel32_locations_.begin(), - rel32_locations_.end(), - TypedRVA::IsLessThanByRVA); - DCHECK(rel32_locations_.empty() || - rel32_locations_.back()->rva() != kUnassignedRVA); - program->DefaultAssignIndexes(); return true; } @@ -384,6 +377,11 @@ if (!found_rel32) VLOG(1) << "Warning: Found no rel32 addresses. Missing .text section?"; + std::sort(rel32_locations_.begin(), rel32_locations_.end(), + TypedRVA::IsLessThanByRVA); + DCHECK(rel32_locations_.empty() || + rel32_locations_.back()->rva() != kUnassignedRVA); + return true; } @@ -418,15 +416,18 @@ // Walk all the bytes in the file, whether or not in a section. FileOffset file_offset = 0; - std::vector<FileOffset> abs_offsets; - // File parsing follows file offset order, and we visit abs32 and rel32 // locations in lockstep. Therefore we need to extract and sort file offsets - // of all abs32 and rel32 locations. + // of all abs32 and rel32 locations. For abs32, we copy the offsets to a new + // array. + std::vector<FileOffset> abs_offsets; if (!RVAsToFileOffsets(abs32_locations_, &abs_offsets)) return false; - std::sort(abs32_locations_.begin(), abs32_locations_.end()); + std::sort(abs_offsets.begin(), abs_offsets.end()); + // For rel32, TypedRVA (rather than raw offset) is stored, so sort-by-offset + // is performed in place to save memory. At the end of function we will + // sort-by-RVA. if (!RVAsToFileOffsets(&rel32_locations_)) return false; std::sort(rel32_locations_.begin(), @@ -496,6 +497,10 @@ if (!ParseSimpleRegion(file_offset, length(), receptor)) return false; + // Restore original rel32 location order and sort by RVA order. + std::sort(rel32_locations_.begin(), rel32_locations_.end(), + TypedRVA::IsLessThanByRVA); + // Make certain we consume all of the relocations as expected return (current_abs_offset == end_abs_offset); }
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm index f33d7929..667bbd6 100644 --- a/device/bluetooth/bluetooth_adapter_mac.mm +++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -519,14 +519,16 @@ // otherwise update the existing device. const bool is_new_device = device_mac == nullptr; if (is_new_device) { - VLOG(1) << "LowEnergyDeviceUpdated new device"; // A new device has been found. device_mac = new BluetoothLowEnergyDeviceMac(this, peripheral); + VLOG(1) << *device_mac << ": New Device."; } else if (DoesCollideWithKnownDevice(peripheral, device_mac)) { return; } DCHECK(device_mac); + VLOG(3) << *device_mac << ": Device updated with " + << base::SysNSStringToUTF8([advertisement_data description]); // Get Advertised UUIDs BluetoothDevice::UUIDList advertised_uuids; @@ -576,7 +578,10 @@ } // TODO(krstnmnlsn): Implement. crbug.com/511025 -void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() {} +void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() { + VLOG(1) << "Central manager state updated: " + << [low_energy_central_manager_ state]; +} void BluetoothAdapterMac::AddPairedDevices() { // Add any new paired devices. @@ -594,6 +599,7 @@ const BluetoothUUID* uuid) { NSArray* cbUUIDs = nil; if (!uuid) { + VLOG(1) << "Retrieving all connected devices."; // It is not possible to ask for all connected peripherals with // -[CBCentralManager retrieveConnectedPeripheralsWithServices:] by passing // nil. To try to get most of the peripherals, the search is done with @@ -601,6 +607,8 @@ CBUUID* genericAccessServiceUUID = [CBUUID UUIDWithString:@"1800"]; cbUUIDs = @[ genericAccessServiceUUID ]; } else { + VLOG(1) << "Retrieving connected devices with UUID: " + << uuid->canonical_value(); NSString* uuidString = base::SysUTF8ToNSString(uuid->canonical_value().c_str()); cbUUIDs = @[ [CBUUID UUIDWithString:uuidString] ]; @@ -626,6 +634,7 @@ } } connected_devices.push_back(device_mac); + VLOG(1) << *device_mac << ": New connected device."; } return connected_devices; } @@ -661,15 +670,15 @@ [low_energy_central_manager_ cancelPeripheralConnection:peripheral]; return; } - VLOG(1) << "Failed to connect to peripheral"; BluetoothDevice::ConnectErrorCode error_code = BluetoothDevice::ConnectErrorCode::ERROR_UNKNOWN; if (error) { error_code = BluetoothDeviceMac::GetConnectErrorCodeFromNSError(error); - VLOG(1) << "Bluetooth error, domain: " << error.domain.UTF8String - << ", error code: " << error.code - << ", converted into: " << error_code; + VLOG(1) << "Converting Bluetooth error, domain: " << error.domain.UTF8String + << ", error code: " << error.code << ", to: " << error_code; } + VLOG(1) << *device_mac << ": Failed to connect to peripheral with error " + << error; device_mac->DidFailToConnectGatt(error_code); } @@ -681,11 +690,6 @@ [low_energy_central_manager_ cancelPeripheralConnection:peripheral]; return; } - VLOG(1) << "Disconnected from peripheral."; - if (error) { - VLOG(1) << "Bluetooth error, domain: " << error.domain.UTF8String - << ", error code: " << error.code; - } device_mac->DidDisconnectPeripheral(error); }
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.h b/device/bluetooth/bluetooth_low_energy_device_mac.h index b25bfff5..0b1aafd 100644 --- a/device/bluetooth/bluetooth_low_energy_device_mac.h +++ b/device/bluetooth/bluetooth_low_energy_device_mac.h
@@ -151,6 +151,11 @@ DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyDeviceMac); }; +// Stream operator for logging. +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothLowEnergyDeviceMac& device); + } // namespace device #endif // DEVICE_BLUETOOTH_BLUETOOTH_LOW_ENERGY_DEVICE_MAC_H_
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.mm b/device/bluetooth/bluetooth_low_energy_device_mac.mm index 6fa8927..4693e3f 100644 --- a/device/bluetooth/bluetooth_low_energy_device_mac.mm +++ b/device/bluetooth/bluetooth_low_energy_device_mac.mm
@@ -176,11 +176,13 @@ void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() { if (!IsGattConnected()) { + VLOG(1) << *this << ": CreateGattConnection."; GetMacAdapter()->CreateGattConnection(this); } } void BluetoothLowEnergyDeviceMac::DisconnectGatt() { + VLOG(1) << *this << ": Disconnect."; GetMacAdapter()->DisconnectGatt(this); } @@ -189,7 +191,7 @@ if (discovery_pending_count_ < 0) { // This should never happens, just in case it happens with a device, // discovery_pending_count_ is set back to 0. - VLOG(1) << GetName()->c_str() + VLOG(1) << *this << ": BluetoothLowEnergyDeviceMac::discovery_pending_count_ " << discovery_pending_count_; discovery_pending_count_ = 0; @@ -199,18 +201,19 @@ // TODO(http://crbug.com/609320): Need to pass the error. // TODO(http://crbug.com/609844): Decide what to do if discover failed // a device services. - VLOG(1) << "Can't discover primary services: " + VLOG(1) << *this << ": Can't discover primary services: " << error.localizedDescription.UTF8String << " (" << error.domain - << ": " << error.code << ")"; + << ": " << error.code << ")."; return; } - VLOG(1) << "DidDiscoverPrimaryServices, pending count: " - << discovery_pending_count_; if (!IsGattConnected()) { // Don't create services if the device disconnected. + VLOG(1) << *this << ": DidDiscoverPrimaryServices, gatt not connected."; return; } + VLOG(1) << *this << ": DidDiscoverPrimaryServices, pending count: " + << discovery_pending_count_; for (CBService* cb_service in GetPeripheral().services) { BluetoothRemoteGattServiceMac* gatt_service = @@ -221,7 +224,10 @@ auto result_iter = gatt_services_.insert(std::make_pair( gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); DCHECK(result_iter.second); + VLOG(1) << *gatt_service << ": New service."; adapter_->NotifyGattServiceAdded(gatt_service); + } else { + VLOG(1) << *gatt_service << ": Known service."; } } if (discovery_pending_count_ == 0) { @@ -241,14 +247,14 @@ if (error) { // TODO(http://crbug.com/609320): Need to pass the error. // TODO(http://crbug.com/609844): Decide what to do if discover failed - VLOG(1) << "Can't discover characteristics: " + VLOG(1) << *this << ": Can't discover characteristics: " << error.localizedDescription.UTF8String << " (" << error.domain - << ": " << error.code << ")"; + << ": " << error.code << ")."; return; } - VLOG(1) << "DidDiscoverCharacteristics."; if (!IsGattConnected()) { + VLOG(1) << *this << ": DidDiscoverCharacteristics, gatt disconnected."; // Don't create characteristics if the device disconnected. return; } @@ -262,7 +268,9 @@ void BluetoothLowEnergyDeviceMac::DidModifyServices( NSArray* invalidatedServices) { - VLOG(1) << "DidModifyServices: "; + VLOG(1) << *this << ": DidModifyServices: " + << " invalidated services " + << base::SysNSStringToUTF8([invalidatedServices description]); for (CBService* cb_service in invalidatedServices) { BluetoothRemoteGattServiceMac* gatt_service = GetBluetoothRemoteGattService(cb_service); @@ -282,7 +290,6 @@ void BluetoothLowEnergyDeviceMac::DidUpdateValue( CBCharacteristic* characteristic, NSError* error) { - VLOG(1) << "DidUpdateValue."; BluetoothRemoteGattServiceMac* gatt_service = GetBluetoothRemoteGattService(characteristic.service); DCHECK(gatt_service); @@ -292,7 +299,6 @@ void BluetoothLowEnergyDeviceMac::DidWriteValue( CBCharacteristic* characteristic, NSError* error) { - VLOG(1) << "DidWriteValue."; BluetoothRemoteGattServiceMac* gatt_service = GetBluetoothRemoteGattService(characteristic.service); DCHECK(gatt_service); @@ -302,7 +308,6 @@ void BluetoothLowEnergyDeviceMac::DidUpdateNotificationState( CBCharacteristic* characteristic, NSError* error) { - VLOG(1) << "DidUpdateNotificationState"; BluetoothRemoteGattServiceMac* gatt_service = GetBluetoothRemoteGattService(characteristic.service); DCHECK(gatt_service); @@ -315,13 +320,13 @@ if (error) { // TODO(http://crbug.com/609320): Need to pass the error. // TODO(http://crbug.com/609844): Decide what to do if discover failed - VLOG(1) << "Can't discover descriptors: " + VLOG(1) << *this << ": Can't discover descriptors: " << error.localizedDescription.UTF8String << " (" << error.domain - << ": " << error.code << ")"; + << ": " << error.code << ")."; return; } - VLOG(1) << "DidDiscoverDescriptors."; if (!IsGattConnected()) { + VLOG(1) << *this << ": DidDiscoverDescriptors, disconnected."; // Don't discover descriptors if the device disconnected. return; } @@ -353,7 +358,8 @@ } void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { - VLOG(1) << "DidDiscoverDescriptors pending count" << discovery_pending_count_; + VLOG(1) << *this << ": DiscoverPrimaryServices, pending count " + << discovery_pending_count_; ++discovery_pending_count_; [GetPeripheral() discoverServices:nil]; } @@ -370,6 +376,7 @@ ->IsDiscoveryComplete(); }) == gatt_services_.end(); if (discovery_complete) { + VLOG(1) << *this << ": Discovery complete."; device_uuids_.ReplaceServiceUUIDs(gatt_services_); SetGattServicesDiscoveryComplete(true); adapter_->NotifyGattServicesDiscovered(this); @@ -399,6 +406,11 @@ } void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral(NSError* error) { + VLOG(1) << *this << ": Disconnected from peripheral."; + if (error) { + VLOG(1) << *this << ": Bluetooth error, domain: " << error.domain.UTF8String + << ", error code: " << error.code; + } SetGattServicesDiscoveryComplete(false); // Removing all services at once to ensure that calling GetGattService on // removed service in GattServiceRemoved returns null. @@ -419,3 +431,16 @@ // TODO(http://crbug.com/585897): Need to pass the error. DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); } + +namespace device { + +std::ostream& operator<<(std::ostream& out, + const BluetoothLowEnergyDeviceMac& device) { + // TODO(crbug.com/703878): Should use + // BluetoothLowEnergyDeviceMac::GetNameForDisplay() instead. + base::Optional<std::string> name = device.GetName(); + const char* name_cstr = name ? name->c_str() : ""; + return out << "<BluetoothLowEnergyDeviceMac " << device.GetAddress() << "/" + << &device << ", \"" << name_cstr << "\">"; +} +} // namespace device
diff --git a/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm b/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm index f4f13ee..609186b 100644 --- a/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm +++ b/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
@@ -93,7 +93,6 @@ CBPeripheral* peripheral, NSDictionary* advertisementData, int rssi) { - VLOG(3) << "DiscoveredPeripheral"; observer_->LowEnergyDeviceUpdated(peripheral, advertisementData, rssi); }
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h index 4b628c6..229daff6 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
@@ -135,6 +135,11 @@ gatt_descriptor_macs_; }; +// Stream operator for logging. +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothRemoteGattCharacteristicMac& characteristic); + } // namespace device #endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_MAC_H_
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm index 2e2da4e6..0e860b5 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
@@ -152,6 +152,7 @@ const ValueCallback& callback, const ErrorCallback& error_callback) { if (!IsReadable()) { + VLOG(1) << *this << ": Characteristic not readable."; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(error_callback, @@ -159,12 +160,14 @@ return; } if (characteristic_value_read_or_write_in_progress_) { + VLOG(1) << *this << ": Characteristic read already in progress."; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(error_callback, BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); return; } + VLOG(1) << *this << ": Read characteristic."; characteristic_value_read_or_write_in_progress_ = true; read_characteristic_value_callbacks_ = std::make_pair(callback, error_callback); @@ -176,6 +179,7 @@ const base::Closure& callback, const ErrorCallback& error_callback) { if (!IsWritable()) { + VLOG(1) << *this << ": Characteristic not writable."; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(error_callback, @@ -183,12 +187,14 @@ return; } if (characteristic_value_read_or_write_in_progress_) { + VLOG(1) << *this << ": Characteristic write already in progress."; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(error_callback, BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); return; } + VLOG(1) << *this << ": Write characteristic."; characteristic_value_read_or_write_in_progress_ = true; write_characteristic_value_callbacks_ = std::make_pair(callback, error_callback); @@ -210,6 +216,7 @@ BluetoothRemoteGattDescriptor* ccc_descriptor, const base::Closure& callback, const ErrorCallback& error_callback) { + VLOG(1) << *this << ": Subscribe to characteristic."; DCHECK(subscribe_to_notification_callbacks_.first.is_null()); DCHECK(subscribe_to_notification_callbacks_.second.is_null()); DCHECK(unsubscribe_from_notification_callbacks_.first.is_null()); @@ -224,6 +231,7 @@ BluetoothRemoteGattDescriptor* ccc_descriptor, const base::Closure& callback, const ErrorCallback& error_callback) { + VLOG(1) << *this << ": Unsubscribe from characteristic."; DCHECK(subscribe_to_notification_callbacks_.first.is_null()); DCHECK(subscribe_to_notification_callbacks_.second.is_null()); DCHECK(unsubscribe_from_notification_callbacks_.first.is_null()); @@ -235,6 +243,7 @@ } void BluetoothRemoteGattCharacteristicMac::DiscoverDescriptors() { + VLOG(1) << *this << ": Discover descriptors."; is_discovery_complete_ = false; [GetCBPeripheral() discoverDescriptorsForCharacteristic:cb_characteristic_.get()]; @@ -249,7 +258,8 @@ callbacks.swap(read_characteristic_value_callbacks_); characteristic_value_read_or_write_in_progress_ = false; if (error) { - VLOG(1) << "Bluetooth error while reading for characteristic, domain: " + VLOG(1) << *this + << ": Bluetooth error while reading for characteristic, domain: " << base::SysNSStringToUTF8(error.domain) << ", error code: " << error.code; BluetoothGattService::GattErrorCode error_code = @@ -257,17 +267,21 @@ callbacks.second.Run(error_code); return; } + VLOG(1) << *this << ": Read request arrived."; UpdateValue(); callbacks.first.Run(value_); } else if (IsNotifying()) { + VLOG(1) << *this << ": Notification arrived."; UpdateValue(); gatt_service_->GetMacAdapter()->NotifyGattCharacteristicValueChanged( this, value_); } else { // In case of buggy device, nothing should be done if receiving extra // read confirmation. - VLOG(1) << "Characteristic value updated while having no pending read nor " - "notification."; + VLOG(1) + << *this + << ": Characteristic value updated while having no pending read nor " + "notification."; } } @@ -282,14 +296,16 @@ if (!characteristic_value_read_or_write_in_progress_) { // In case of buggy device, nothing should be done if receiving extra // write confirmation. - VLOG(1) << "Write notification while no write operation pending."; + VLOG(1) << *this + << ": Write notification while no write operation pending."; return; } std::pair<base::Closure, ErrorCallback> callbacks; callbacks.swap(write_characteristic_value_callbacks_); characteristic_value_read_or_write_in_progress_ = false; if (error) { - VLOG(1) << "Bluetooth error while writing for characteristic, domain: " + VLOG(1) << *this + << ": Bluetooth error while writing for characteristic, domain: " << base::SysNSStringToUTF8(error.domain) << ", error code: " << error.code; BluetoothGattService::GattErrorCode error_code = @@ -297,6 +313,7 @@ callbacks.second.Run(error_code); return; } + VLOG(1) << *this << ": Write value succeeded."; callbacks.first.Run(); } @@ -310,12 +327,12 @@ DCHECK(![GetCBCharacteristic() isNotifying] || error); reentrant_safe_callbacks.swap(unsubscribe_from_notification_callbacks_); } else { - VLOG(1) << "No pending notification update for characteristic " - << GetUUID().value(); + VLOG(1) << *this << ": No pending notification update for characteristic."; return; } if (error) { - VLOG(1) << "Bluetooth error while modifying notification state for " + VLOG(1) << *this + << ": Bluetooth error while modifying notification state for " "characteristic, domain: " << base::SysNSStringToUTF8(error.domain) << ", error code: " << error.code << ", localized description: " @@ -330,6 +347,7 @@ void BluetoothRemoteGattCharacteristicMac::DidDiscoverDescriptors() { DCHECK(!is_discovery_complete_); + VLOG(1) << *this << ": Did discover descriptors."; std::unordered_set<std::string> descriptor_identifier_to_remove; for (const auto& iter : gatt_descriptor_macs_) { descriptor_identifier_to_remove.insert(iter.first); @@ -339,6 +357,7 @@ BluetoothRemoteGattDescriptorMac* gatt_descriptor_mac = GetBluetoothRemoteGattDescriptorMac(cb_descriptor); if (gatt_descriptor_mac) { + VLOG(1) << *gatt_descriptor_mac << ": Known descriptor."; const std::string& identifier = gatt_descriptor_mac->GetIdentifier(); descriptor_identifier_to_remove.erase(identifier); continue; @@ -350,11 +369,13 @@ {identifier, base::WrapUnique(gatt_descriptor_mac)}); DCHECK(result_iter.second); GetMacAdapter()->NotifyGattDescriptorAdded(gatt_descriptor_mac); + VLOG(1) << *gatt_descriptor_mac << ": New descriptor."; } for (const std::string& identifier : descriptor_identifier_to_remove) { auto pair_to_remove = gatt_descriptor_macs_.find(identifier); std::unique_ptr<BluetoothRemoteGattDescriptorMac> descriptor_to_remove; + VLOG(1) << *descriptor_to_remove << ": Removed descriptor."; pair_to_remove->second.swap(descriptor_to_remove); gatt_descriptor_macs_.erase(pair_to_remove); GetMacAdapter()->NotifyGattDescriptorRemoved(descriptor_to_remove.get()); @@ -420,4 +441,17 @@ return found->second.get(); } } + +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothRemoteGattCharacteristicMac& characteristic) { + const BluetoothRemoteGattServiceMac* service_mac = + static_cast<const BluetoothRemoteGattServiceMac*>( + characteristic.GetService()); + return out << "<BluetoothRemoteGattCharacteristicMac " + << characteristic.GetUUID().canonical_value() << "/" + << &characteristic + << ", service: " << service_mac->GetUUID().canonical_value() << "/" + << service_mac << ">"; +} } // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h b/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h index 9749322..60d4062 100644 --- a/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.h
@@ -60,6 +60,11 @@ std::vector<uint8_t> value_; }; +// Stream operator for logging. +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothRemoteGattDescriptorMac& descriptor); + } // namespace device #endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_MAC_H_
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm b/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm index d867349ab..76cda0c 100644 --- a/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_mac.mm
@@ -74,4 +74,17 @@ return cb_descriptor_.get(); } +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothRemoteGattDescriptorMac& descriptor) { + const BluetoothRemoteGattCharacteristicMac* characteristic_mac = + static_cast<const BluetoothRemoteGattCharacteristicMac*>( + descriptor.GetCharacteristic()); + return out << "<BluetoothRemoteGattServiceMac " + << descriptor.GetUUID().canonical_value() << "/" << &descriptor + << ", characteristic: " + << characteristic_mac->GetUUID().canonical_value() << "/" + << characteristic_mac << ">"; +} + } // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_mac.h b/device/bluetooth/bluetooth_remote_gatt_service_mac.h index 60d1f110..1c5d1c8 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_mac.h +++ b/device/bluetooth/bluetooth_remote_gatt_service_mac.h
@@ -102,6 +102,11 @@ DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceMac); }; +// Stream operator for logging. +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothRemoteGattServiceMac& service); + } // namespace device #endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_MAC_H_
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_mac.mm b/device/bluetooth/bluetooth_remote_gatt_service_mac.mm index 505321e..5d2b736 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_mac.mm +++ b/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
@@ -78,12 +78,14 @@ } void BluetoothRemoteGattServiceMac::DiscoverCharacteristics() { + VLOG(1) << *this << ": DiscoverCharacteristics."; is_discovery_complete_ = false; [GetCBPeripheral() discoverCharacteristics:nil forService:GetService()]; } void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() { DCHECK(!is_discovery_complete_); + VLOG(1) << *this << ": DidDiscoverCharacteristics."; std::unordered_set<std::string> characteristic_identifier_to_remove; for (const auto& iter : gatt_characteristic_macs_) { characteristic_identifier_to_remove.insert(iter.first); @@ -93,6 +95,9 @@ BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac = GetBluetoothRemoteGattCharacteristicMac(cb_characteristic); if (gatt_characteristic_mac) { + VLOG(1) << *gatt_characteristic_mac + << ": Known characteristic, properties " + << gatt_characteristic_mac->GetProperties(); const std::string& identifier = gatt_characteristic_mac->GetIdentifier(); characteristic_identifier_to_remove.erase(identifier); gatt_characteristic_mac->DiscoverDescriptors(); @@ -104,6 +109,8 @@ auto result_iter = gatt_characteristic_macs_.insert( {identifier, base::WrapUnique(gatt_characteristic_mac)}); DCHECK(result_iter.second); + VLOG(1) << *gatt_characteristic_mac << ": New characteristic, properties " + << gatt_characteristic_mac->GetProperties(); gatt_characteristic_mac->DiscoverDescriptors(); GetMacAdapter()->NotifyGattCharacteristicAdded(gatt_characteristic_mac); } @@ -113,6 +120,7 @@ std::unique_ptr<BluetoothRemoteGattCharacteristicMac> characteristic_to_remove; pair_to_remove->second.swap(characteristic_to_remove); + VLOG(1) << *characteristic_to_remove << ": Removed characteristic."; gatt_characteristic_macs_.erase(pair_to_remove); GetMacAdapter()->NotifyGattCharacteristicRemoved( characteristic_to_remove.get()); @@ -142,6 +150,7 @@ return pair.second->IsDiscoveryComplete(); }) == gatt_characteristic_macs_.end(); if (is_discovery_complete_) { + VLOG(1) << *this << ": Discovery complete."; GetMacAdapter()->NotifyGattServiceChanged(this); } } @@ -207,4 +216,15 @@ } } +DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<( + std::ostream& out, + const BluetoothRemoteGattServiceMac& service) { + const BluetoothLowEnergyDeviceMac* bluetooth_device_mac_ = + static_cast<const BluetoothLowEnergyDeviceMac*>(service.GetDevice()); + return out << "<BluetoothRemoteGattServiceMac " + << service.GetUUID().canonical_value() << "/" << &service + << ", device: " << bluetooth_device_mac_->GetAddress() << "/" + << bluetooth_device_mac_ << ">"; +} + } // namespace device
diff --git a/extensions/browser/api/runtime/runtime_apitest.cc b/extensions/browser/api/runtime/runtime_apitest.cc index 5c65d3d0..1bb7850 100644 --- a/extensions/browser/api/runtime/runtime_apitest.cc +++ b/extensions/browser/api/runtime/runtime_apitest.cc
@@ -7,11 +7,10 @@ #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/test_extension_dir.h" #include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/notification_service.h" #include "extensions/browser/api/runtime/runtime_api.h" #include "extensions/browser/extension_dialog_auto_confirm.h" #include "extensions/browser/extension_registry.h" -#include "extensions/browser/notification_types.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/test/result_catcher.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -106,22 +105,21 @@ // to reload itself that often without being terminated, the test fails // anyway. for (int i = 0; i < 30; i++) { - content::WindowedNotificationObserver unload_observer( - extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, - content::NotificationService::AllSources()); - content::WindowedNotificationObserver load_observer( - extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, - content::NotificationService::AllSources()); - + TestExtensionRegistryObserver unload_observer(registry, extension_id); + TestExtensionRegistryObserver load_observer(registry, extension_id); ASSERT_TRUE(ExecuteScriptInBackgroundPageNoWait( extension_id, "chrome.runtime.reload();")); - unload_observer.Wait(); + unload_observer.WaitForExtensionUnloaded(); + base::RunLoop().RunUntilIdle(); if (registry->GetExtensionById(extension_id, ExtensionRegistry::TERMINATED)) { break; } else { - load_observer.Wait(); + load_observer.WaitForExtensionLoaded(); + // We need to let other registry observers handle the notification to + // finish initialization + base::RunLoop().RunUntilIdle(); WaitForExtensionViewsToLoad(); } }
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index 603acdc..b5114bd 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -388,5 +388,6 @@ #define glSwapBuffersWithBoundsCHROMIUM \ GLES2_GET_FUN(SwapBuffersWithBoundsCHROMIUM) #define glSetDrawRectangleCHROMIUM GLES2_GET_FUN(SetDrawRectangleCHROMIUM) +#define glSetEnableDCLayersCHROMIUM GLES2_GET_FUN(SetEnableDCLayersCHROMIUM) #endif // GPU_GLES2_GL2CHROMIUM_AUTOGEN_H_
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index e5a13b1..d3836079 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4548,6 +4548,10 @@ 'decoder_func': 'DoSetDrawRectangleCHROMIUM', 'extension': 'CHROMIUM_set_draw_rectangle', }, + 'SetEnableDCLayersCHROMIUM': { + 'decoder_func': 'DoSetEnableDCLayersCHROMIUM', + 'extension': 'CHROMIUM_dc_layers', + }, }
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index d8b3a2e..5940339 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1745,6 +1745,9 @@ GLint height) { gles2::GetGLContext()->SetDrawRectangleCHROMIUM(x, y, width, height); } +void GL_APIENTRY GLES2SetEnableDCLayersCHROMIUM(GLboolean enabled) { + gles2::GetGLContext()->SetEnableDCLayersCHROMIUM(enabled); +} namespace gles2 { @@ -3061,6 +3064,10 @@ reinterpret_cast<GLES2FunctionPointer>(glSetDrawRectangleCHROMIUM), }, { + "glSetEnableDCLayersCHROMIUM", + reinterpret_cast<GLES2FunctionPointer>(glSetEnableDCLayersCHROMIUM), + }, + { NULL, NULL, }, };
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index b3cba3c..5ff6a5f 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -3230,4 +3230,12 @@ } } +void SetEnableDCLayersCHROMIUM(GLboolean enabled) { + gles2::cmds::SetEnableDCLayersCHROMIUM* c = + GetCmdSpace<gles2::cmds::SetEnableDCLayersCHROMIUM>(); + if (c) { + c->Init(enabled); + } +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 7107004..47bea0c 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1225,4 +1225,6 @@ GLint width, GLint height) override; +void SetEnableDCLayersCHROMIUM(GLboolean enabled) override; + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 73a9676..562b12f 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -3524,4 +3524,12 @@ CheckGLError(); } +void GLES2Implementation::SetEnableDCLayersCHROMIUM(GLboolean enabled) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSetEnableDCLayersCHROMIUM(" + << GLES2Util::GetStringBool(enabled) << ")"); + helper_->SetEnableDCLayersCHROMIUM(enabled); + CheckGLError(); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 2e17662d..cee92feee 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -3058,4 +3058,15 @@ gl_->SetDrawRectangleCHROMIUM(1, 2, 3, 4); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } + +TEST_F(GLES2ImplementationTest, SetEnableDCLayersCHROMIUM) { + struct Cmds { + cmds::SetEnableDCLayersCHROMIUM cmd; + }; + Cmds expected; + expected.cmd.Init(true); + + gl_->SetEnableDCLayersCHROMIUM(true); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_UNITTEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 291168e..c142d27 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -909,4 +909,5 @@ GLint y, GLint width, GLint height) = 0; +virtual void SetEnableDCLayersCHROMIUM(GLboolean enabled) = 0; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index cd95940..f987b73 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -882,4 +882,5 @@ GLint y, GLint width, GLint height) override; +void SetEnableDCLayersCHROMIUM(GLboolean enabled) override; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 5a93370..ddf50bd 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -1187,4 +1187,5 @@ GLint /* y */, GLint /* width */, GLint /* height */) {} +void GLES2InterfaceStub::SetEnableDCLayersCHROMIUM(GLboolean /* enabled */) {} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 160da4a..6ad358c 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -882,4 +882,5 @@ GLint y, GLint width, GLint height) override; +void SetEnableDCLayersCHROMIUM(GLboolean enabled) override; #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index b7f304a..5516df7 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2536,4 +2536,9 @@ gl_->SetDrawRectangleCHROMIUM(x, y, width, height); } +void GLES2TraceImplementation::SetEnableDCLayersCHROMIUM(GLboolean enabled) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SetEnableDCLayersCHROMIUM"); + gl_->SetEnableDCLayersCHROMIUM(enabled); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 101aa5a..3c8dfcd2 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -368,3 +368,6 @@ // Extension CHROMIUM_set_draw_rectangle GL_APICALL void GL_APIENTRY glSetDrawRectangleCHROMIUM (GLint x, GLint y, GLint width, GLint height); + +// Extension CHROMIUM_dc_overlays +GL_APICALL void GL_APIENTRY glSetEnableDCLayersCHROMIUM (GLboolean enabled);
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h index b6445c37..29d025f7 100644 --- a/gpu/command_buffer/common/capabilities.h +++ b/gpu/command_buffer/common/capabilities.h
@@ -154,7 +154,8 @@ bool disable_multisampling_color_mask_usage = false; bool disable_webgl_rgb_multisampling_usage = false; bool gpu_rasterization = false; - bool set_draw_rectangle = false; + // True if DirectComposition layers are enabled. + bool dc_layers = false; // When this parameter is true, a CHROMIUM image created with RGB format will // actually have RGBA format. The client is responsible for handling most of
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index ad6106c..f0ab255 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -15866,4 +15866,37 @@ static_assert(offsetof(SetDrawRectangleCHROMIUM, height) == 16, "offset of SetDrawRectangleCHROMIUM height should be 16"); +struct SetEnableDCLayersCHROMIUM { + typedef SetEnableDCLayersCHROMIUM ValueType; + static const CommandId kCmdId = kSetEnableDCLayersCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLboolean _enabled) { + SetHeader(); + enabled = _enabled; + } + + void* Set(void* cmd, GLboolean _enabled) { + static_cast<ValueType*>(cmd)->Init(_enabled); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t enabled; +}; + +static_assert(sizeof(SetEnableDCLayersCHROMIUM) == 8, + "size of SetEnableDCLayersCHROMIUM should be 8"); +static_assert(offsetof(SetEnableDCLayersCHROMIUM, header) == 0, + "offset of SetEnableDCLayersCHROMIUM header should be 0"); +static_assert(offsetof(SetEnableDCLayersCHROMIUM, enabled) == 4, + "offset of SetEnableDCLayersCHROMIUM enabled should be 4"); + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index c26cd229..d43cd509 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -5313,4 +5313,15 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, SetEnableDCLayersCHROMIUM) { + cmds::SetEnableDCLayersCHROMIUM& cmd = + *GetBufferAs<cmds::SetEnableDCLayersCHROMIUM>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLboolean>(11)); + EXPECT_EQ(static_cast<uint32_t>(cmds::SetEnableDCLayersCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLboolean>(11), cmd.enabled); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 8dd3ab7..ffef2d5 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -332,7 +332,8 @@ OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 573 */ \ OP(OverlayPromotionHintCHROMIUM) /* 574 */ \ OP(SwapBuffersWithBoundsCHROMIUMImmediate) /* 575 */ \ - OP(SetDrawRectangleCHROMIUM) /* 576 */ + OP(SetDrawRectangleCHROMIUM) /* 576 */ \ + OP(SetEnableDCLayersCHROMIUM) /* 577 */ enum CommandId { kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index b119c7a..5b1b6e6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1704,6 +1704,8 @@ // Wrapper for glSetDrawRectangleCHROMIUM void DoSetDrawRectangleCHROMIUM(GLint x, GLint y, GLint width, GLint height); + void DoSetEnableDCLayersCHROMIUM(GLboolean enable); + // Wrapper for glReadBuffer void DoReadBuffer(GLenum src); @@ -2369,7 +2371,7 @@ bool supports_swap_buffers_with_bounds_; bool supports_commit_overlay_planes_; bool supports_async_swap_; - bool supports_set_draw_rectangle_ = false; + bool supports_dc_layers_ = false; // These flags are used to override the state of the shared feature_info_ // member. Because the same FeatureInfo instance may be shared among many @@ -3594,8 +3596,7 @@ supports_async_swap_ = surface->SupportsAsyncSwap(); - supports_set_draw_rectangle_ = - !offscreen && surface->SupportsSetDrawRectangle(); + supports_dc_layers_ = !offscreen && surface->SupportsDCLayers(); if (workarounds().reverse_point_sprite_coord_origin) { glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); @@ -3771,7 +3772,7 @@ bool is_offscreen = !!offscreen_target_frame_buffer_.get(); caps.flips_vertically = !is_offscreen && surface_->FlipsVertically(); caps.msaa_is_slow = workarounds().msaa_is_slow; - caps.set_draw_rectangle = supports_set_draw_rectangle_; + caps.dc_layers = supports_dc_layers_; caps.blend_equation_advanced = feature_info_->feature_flags().blend_equation_advanced; @@ -5667,15 +5668,14 @@ return; state_.fbo_binding_for_scissor_workaround_dirty = false; - if (supports_set_draw_rectangle_) { + if (supports_dc_layers_) { gfx::Vector2d draw_offset = GetBoundFramebufferDrawOffset(); glViewport(state_.viewport_x + draw_offset.x(), state_.viewport_y + draw_offset.y(), state_.viewport_width, state_.viewport_height); } - if (workarounds().restore_scissor_on_fbo_change || - supports_set_draw_rectangle_) { + if (workarounds().restore_scissor_on_fbo_change || supports_dc_layers_) { // The driver forgets the correct scissor when modifying the FBO binding. gfx::Vector2d scissor_offset = GetBoundFramebufferDrawOffset(); glScissor(state_.scissor_x + scissor_offset.x(), @@ -8741,7 +8741,7 @@ "framebuffer must not be bound"); return; } - if (!supports_set_draw_rectangle_) { + if (!supports_dc_layers_) { LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glSetDrawRectangleCHROMIUM", "surface doesn't support SetDrawRectangle"); return; @@ -8754,6 +8754,24 @@ OnFboChanged(); } +void GLES2DecoderImpl::DoSetEnableDCLayersCHROMIUM(GLboolean enable) { + Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER); + if (framebuffer) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glSetEnableDCLayersCHROMIUM", + "framebuffer must not be bound"); + return; + } + if (!supports_dc_layers_) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glSetEnableDCLayersCHROMIUM", + "surface doesn't support SetDrawRectangle"); + return; + } + if (!surface_->SetEnableDCLayers(!!enable)) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glSetEnableDCLayersCHROMIUM", + "failed on surface"); + } +} + void GLES2DecoderImpl::DoReadBuffer(GLenum src) { Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER); if (framebuffer) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index e4b62da..b0e70227 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -5172,6 +5172,17 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleSetEnableDCLayersCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::SetEnableDCLayersCHROMIUM& c = + *static_cast<const volatile gles2::cmds::SetEnableDCLayersCHROMIUM*>( + cmd_data); + GLboolean enabled = static_cast<GLboolean>(c.enabled); + DoSetEnableDCLayersCHROMIUM(enabled); + return error::kNoError; +} + bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { switch (cap) { case GL_BLEND:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h index 28d286c3..47b3ea86 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -968,3 +968,4 @@ GLint y, GLint width, GLint height); +error::Error DoSetEnableDCLayersCHROMIUM(GLboolean enable);
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 93b5050..85d3bc7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -3529,5 +3529,11 @@ return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::DoSetEnableDCLayersCHROMIUM( + GLboolean enable) { + NOTIMPLEMENTED(); + return error::kNoError; +} + } // namespace gles2 } // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc index 37639206..bc19ef16 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers_autogen.cc
@@ -4385,5 +4385,19 @@ return error::kNoError; } +error::Error GLES2DecoderPassthroughImpl::HandleSetEnableDCLayersCHROMIUM( + uint32_t immediate_data_size, + const volatile void* cmd_data) { + const volatile gles2::cmds::SetEnableDCLayersCHROMIUM& c = + *static_cast<const volatile gles2::cmds::SetEnableDCLayersCHROMIUM*>( + cmd_data); + GLboolean enabled = static_cast<GLboolean>(c.enabled); + error::Error error = DoSetEnableDCLayersCHROMIUM(enabled); + if (error != error::kNoError) { + return error; + } + return error::kNoError; +} + } // namespace gles2 } // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h index 264c667..671309d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_4_autogen.h
@@ -33,4 +33,13 @@ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } + +TEST_P(GLES2DecoderTest4, SetEnableDCLayersCHROMIUMValidArgs) { + EXPECT_CALL(*gl_, SetEnableDCLayersCHROMIUM(true)); + SpecializedSetup<cmds::SetEnableDCLayersCHROMIUM, 0>(true); + cmds::SetEnableDCLayersCHROMIUM cmd; + cmd.Init(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_4_AUTOGEN_H_
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h index 4dc28d1..87a3eb1 100644 --- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -127,7 +127,7 @@ IPC_STRUCT_TRAITS_MEMBER(gpu_rasterization) IPC_STRUCT_TRAITS_MEMBER(chromium_image_rgb_emulation) IPC_STRUCT_TRAITS_MEMBER(emulate_rgb_buffer_with_rgba) - IPC_STRUCT_TRAITS_MEMBER(set_draw_rectangle) + IPC_STRUCT_TRAITS_MEMBER(dc_layers) IPC_STRUCT_TRAITS_MEMBER(major_version) IPC_STRUCT_TRAITS_MEMBER(minor_version)
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index 48a8cd9..7f652134 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -5,6 +5,7 @@ #include "gpu/ipc/service/direct_composition_surface_win.h" #include "base/optional.h" +#include "base/synchronization/waitable_event.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/switches.h" @@ -154,32 +155,83 @@ eglCreatePbufferSurface(display, GetConfig(), &pbuffer_attribs[0]); CHECK(!!default_surface_); - InitializeSurface(); - return true; } -void DirectCompositionSurfaceWin::InitializeSurface() { - ScopedReleaseCurrent release_current(this); - ReleaseDrawTexture(); +void DirectCompositionSurfaceWin::ReleaseCurrentSurface() { + ReleaseDrawTexture(true); dcomp_surface_.Release(); - HRESULT hr = dcomp_device_->CreateSurface( - size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive()); - has_been_rendered_to_ = false; - - CHECK(SUCCEEDED(hr)); + swap_chain_.Release(); } -void DirectCompositionSurfaceWin::ReleaseDrawTexture() { +void DirectCompositionSurfaceWin::InitializeSurface() { + DCHECK(!dcomp_surface_); + DCHECK(!swap_chain_); + if (enable_dc_layers_) { + HRESULT hr = dcomp_device_->CreateSurface( + size_.width(), size_.height(), DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_ALPHA_MODE_PREMULTIPLIED, dcomp_surface_.Receive()); + has_been_rendered_to_ = false; + CHECK(SUCCEEDED(hr)); + } else { + base::win::ScopedComPtr<IDXGIDevice> dxgi_device; + d3d11_device_.QueryInterface(dxgi_device.Receive()); + base::win::ScopedComPtr<IDXGIAdapter> dxgi_adapter; + dxgi_device->GetAdapter(dxgi_adapter.Receive()); + base::win::ScopedComPtr<IDXGIFactory2> dxgi_factory; + dxgi_adapter->GetParent(IID_PPV_ARGS(dxgi_factory.Receive())); + + DXGI_SWAP_CHAIN_DESC1 desc = {}; + desc.Width = size_.width(); + desc.Height = size_.height(); + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.Stereo = FALSE; + desc.SampleDesc.Count = 1; + desc.BufferCount = 2; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.Scaling = DXGI_SCALING_STRETCH; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; + desc.Flags = 0; + HRESULT hr = dxgi_factory->CreateSwapChainForComposition( + d3d11_device_.get(), &desc, nullptr, swap_chain_.Receive()); + has_been_rendered_to_ = false; + first_swap_ = true; + CHECK(SUCCEEDED(hr)); + } +} + +void DirectCompositionSurfaceWin::ReleaseDrawTexture(bool will_discard) { if (real_surface_) { eglDestroySurface(GetDisplay(), real_surface_); real_surface_ = nullptr; } if (draw_texture_) { draw_texture_.Release(); - HRESULT hr = dcomp_surface_->EndDraw(); - CHECK(SUCCEEDED(hr)); + if (dcomp_surface_) { + HRESULT hr = dcomp_surface_->EndDraw(); + CHECK(SUCCEEDED(hr)); + } else if (!will_discard) { + DXGI_PRESENT_PARAMETERS params = {}; + RECT dirty_rect = swap_rect_.ToRECT(); + params.DirtyRectsCount = 1; + params.pDirtyRects = &dirty_rect; + swap_chain_->Present1(first_swap_ ? 0 : 1, 0, ¶ms); + if (first_swap_) { + // Wait for the GPU to finish executing its commands before + // committing the DirectComposition tree, or else the swapchain + // may flicker black when it's first presented. + base::win::ScopedComPtr<IDXGIDevice2> dxgi_device2; + HRESULT hr = d3d11_device_.QueryInterface(dxgi_device2.Receive()); + DCHECK(SUCCEEDED(hr)); + base::WaitableEvent event( + base::WaitableEvent::ResetPolicy::AUTOMATIC, + base::WaitableEvent::InitialState::NOT_SIGNALED); + dxgi_device2->EnqueueSetEvent(event.handle()); + event.Wait(); + first_swap_ = false; + } + } } if (dcomp_surface_ == g_current_surface) g_current_surface = nullptr; @@ -200,8 +252,11 @@ } real_surface_ = nullptr; } - if (dcomp_surface_ == g_current_surface) + if (dcomp_surface_ && (dcomp_surface_ == g_current_surface)) { + HRESULT hr = dcomp_surface_->EndDraw(); + CHECK(SUCCEEDED(hr)); g_current_surface = nullptr; + } draw_texture_.Release(); dcomp_surface_.Release(); } @@ -231,7 +286,9 @@ return false; } size_ = size; - InitializeSurface(); + ScopedReleaseCurrent release_current(this); + // New surface will be initialized in SetDrawRectangle. + ReleaseCurrentSurface(); return true; } @@ -239,19 +296,16 @@ gfx::SwapResult DirectCompositionSurfaceWin::SwapBuffers() { { ScopedReleaseCurrent release_current(this); - ReleaseDrawTexture(); - visual_->SetContent(dcomp_surface_.get()); + ReleaseDrawTexture(false); + DCHECK(dcomp_surface_ || swap_chain_); + if (dcomp_surface_) + visual_->SetContent(dcomp_surface_.get()); + else + visual_->SetContent(swap_chain_.get()); CommitAndClearPendingOverlays(); dcomp_device_->Commit(); } - // Force the driver to finish drawing before clearing the contents to - // transparent, to reduce or eliminate the period of time where the contents - // have flashed black. - if (first_swap_) { - glFinish(); - first_swap_ = false; - } child_window_.ClearInvalidContents(); return gfx::SwapResult::SWAP_ACK; } @@ -260,13 +314,9 @@ int y, int width, int height) { - ScopedReleaseCurrent release_current(this); - ReleaseDrawTexture(); - visual_->SetContent(dcomp_surface_.get()); - CommitAndClearPendingOverlays(); - dcomp_device_->Commit(); - child_window_.ClearInvalidContents(); - return gfx::SwapResult::SWAP_ACK; + // The arguments are ignored because SetDrawRectangle specified the area to + // be swapped. + return SwapBuffers(); } gfx::VSyncProvider* DirectCompositionSurfaceWin::GetVSyncProvider() { @@ -284,6 +334,11 @@ return true; } +bool DirectCompositionSurfaceWin::SetEnableDCLayers(bool enable) { + enable_dc_layers_ = enable; + return true; +} + bool DirectCompositionSurfaceWin::CommitAndClearPendingOverlays() { pending_overlays_.clear(); return true; @@ -313,13 +368,23 @@ return true; } -bool DirectCompositionSurfaceWin::SupportsSetDrawRectangle() const { +bool DirectCompositionSurfaceWin::SupportsDCLayers() const { return true; } bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) { if (draw_texture_) return false; + + DCHECK(!real_surface_); + ScopedReleaseCurrent release_current(this); + + if ((enable_dc_layers_ && !dcomp_surface_) || + (!enable_dc_layers_ && !swap_chain_)) { + ReleaseCurrentSurface(); + InitializeSurface(); + } + if (!gfx::Rect(size_).Contains(rectangle)) { DLOG(ERROR) << "Draw rectangle must be contained within size of surface"; return false; @@ -329,20 +394,24 @@ return false; } - DCHECK(!real_surface_); CHECK(!g_current_surface); - ScopedReleaseCurrent release_current(this); RECT rect = rectangle.ToRECT(); - POINT update_offset; - - HRESULT hr = dcomp_surface_->BeginDraw( - &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset); - CHECK(SUCCEEDED(hr)); + if (dcomp_surface_) { + POINT update_offset; + HRESULT hr = dcomp_surface_->BeginDraw( + &rect, IID_PPV_ARGS(draw_texture_.Receive()), &update_offset); + draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin(); + CHECK(SUCCEEDED(hr)); + } else { + HRESULT hr = + swap_chain_->GetBuffer(0, IID_PPV_ARGS(draw_texture_.Receive())); + swap_rect_ = rectangle; + draw_offset_ = gfx::Vector2d(); + CHECK(SUCCEEDED(hr)); + } has_been_rendered_to_ = true; - draw_offset_ = gfx::Point(update_offset) - gfx::Rect(rect).origin(); - g_current_surface = dcomp_surface_.get(); std::vector<EGLint> pbuffer_attribs{
diff --git a/gpu/ipc/service/direct_composition_surface_win.h b/gpu/ipc/service/direct_composition_surface_win.h index ddcdd272..f514f9c 100644 --- a/gpu/ipc/service/direct_composition_surface_win.h +++ b/gpu/ipc/service/direct_composition_surface_win.h
@@ -49,16 +49,20 @@ gl::GLImage* image, const gfx::Rect& bounds_rect, const gfx::RectF& crop_rect) override; + bool SetEnableDCLayers(bool enable) override; bool FlipsVertically() const override; bool SupportsPostSubBuffer() override; bool OnMakeCurrent(gl::GLContext* context) override; - bool SupportsSetDrawRectangle() const override; + bool SupportsDCLayers() const override; bool SetDrawRectangle(const gfx::Rect& rect) override; gfx::Vector2d GetDrawOffset() const override; bool Initialize(std::unique_ptr<gfx::VSyncProvider> vsync_provider); scoped_refptr<base::TaskRunner> GetWindowTaskRunnerForTesting(); + base::win::ScopedComPtr<IDXGISwapChain1> swap_chain() const { + return swap_chain_; + } protected: ~DirectCompositionSurfaceWin() override; @@ -82,8 +86,12 @@ }; bool CommitAndClearPendingOverlays(); + void ReleaseCurrentSurface(); void InitializeSurface(); - void ReleaseDrawTexture(); + // Release the texture that's currently being drawn to. If will_discard is + // true then the surface should be discarded without swapping any contents + // to it. + void ReleaseDrawTexture(bool will_discard); ChildWindowWin child_window_; @@ -97,8 +105,10 @@ EGLSurface real_surface_ = 0; gfx::Size size_ = gfx::Size(1, 1); bool first_swap_ = true; + bool enable_dc_layers_ = false; std::unique_ptr<gfx::VSyncProvider> vsync_provider_; std::vector<Overlay> pending_overlays_; + gfx::Rect swap_rect_; gfx::Vector2d draw_offset_; @@ -107,6 +117,7 @@ base::win::ScopedComPtr<IDCompositionTarget> dcomp_target_; base::win::ScopedComPtr<IDCompositionVisual2> visual_; base::win::ScopedComPtr<IDCompositionSurface> dcomp_surface_; + base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_; base::win::ScopedComPtr<ID3D11Texture2D> draw_texture_; // Keep track of whether the texture has been rendered to, as the first draw
diff --git a/gpu/ipc/service/direct_composition_surface_win_unittest.cc b/gpu/ipc/service/direct_composition_surface_win_unittest.cc index 19a1d2c..862e1525 100644 --- a/gpu/ipc/service/direct_composition_surface_win_unittest.cc +++ b/gpu/ipc/service/direct_composition_surface_win_unittest.cc
@@ -42,6 +42,21 @@ done.Wait(); } +void DestroySurface(scoped_refptr<DirectCompositionSurfaceWin> surface) { + scoped_refptr<base::TaskRunner> task_runner = + surface->GetWindowTaskRunnerForTesting(); + DCHECK(surface->HasOneRef()); + + surface = nullptr; + + // Ensure that the ChildWindowWin posts the task to delete the thread to the + // main loop before doing RunUntilIdle. Otherwise the child threads could + // outlive the main thread. + RunPendingTasks(task_runner); + + base::RunLoop().RunUntilIdle(); +} + TEST(DirectCompositionSurfaceTest, TestMakeCurrent) { if (!gl::QueryDirectCompositionDevice( gl::QueryD3D11DeviceObjectFromANGLE())) { @@ -52,6 +67,74 @@ TestImageTransportSurfaceDelegate delegate; + scoped_refptr<DirectCompositionSurfaceWin> surface1( + new DirectCompositionSurfaceWin(delegate.AsWeakPtr(), + ui::GetHiddenWindow())); + EXPECT_TRUE(surface1->Initialize()); + surface1->SetEnableDCLayers(true); + + scoped_refptr<gl::GLContext> context1 = gl::init::CreateGLContext( + nullptr, surface1.get(), gl::GLContextAttribs()); + EXPECT_TRUE(surface1->Resize(gfx::Size(100, 100), 1.0, true)); + + // First SetDrawRectangle must be full size of surface. + EXPECT_FALSE(surface1->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); + EXPECT_TRUE(surface1->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); + + // SetDrawRectangle can't be called again until swap. + EXPECT_FALSE(surface1->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); + + EXPECT_TRUE(context1->MakeCurrent(surface1.get())); + EXPECT_EQ(gfx::SwapResult::SWAP_ACK, surface1->SwapBuffers()); + + EXPECT_TRUE(context1->IsCurrent(surface1.get())); + + // SetDrawRectangle must be contained within surface. + EXPECT_FALSE(surface1->SetDrawRectangle(gfx::Rect(0, 0, 101, 101))); + EXPECT_TRUE(surface1->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); + EXPECT_TRUE(context1->IsCurrent(surface1.get())); + + EXPECT_TRUE(surface1->Resize(gfx::Size(50, 50), 1.0, true)); + EXPECT_TRUE(context1->IsCurrent(surface1.get())); + EXPECT_TRUE(surface1->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); + EXPECT_TRUE(context1->IsCurrent(surface1.get())); + + scoped_refptr<DirectCompositionSurfaceWin> surface2( + new DirectCompositionSurfaceWin(delegate.AsWeakPtr(), + ui::GetHiddenWindow())); + EXPECT_TRUE(surface2->Initialize()); + + scoped_refptr<gl::GLContext> context2 = gl::init::CreateGLContext( + nullptr, surface2.get(), gl::GLContextAttribs()); + surface2->SetEnableDCLayers(true); + EXPECT_TRUE(context2->MakeCurrent(surface2.get())); + EXPECT_TRUE(surface2->Resize(gfx::Size(100, 100), 1.0, true)); + // The previous IDCompositionSurface should be suspended when another + // surface is being drawn to. + EXPECT_TRUE(surface2->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); + EXPECT_TRUE(context2->IsCurrent(surface2.get())); + + // It should be possible to switch back to the previous surface and + // unsuspend it. + EXPECT_TRUE(context1->MakeCurrent(surface1.get())); + context2 = nullptr; + context1 = nullptr; + + DestroySurface(std::move(surface1)); + DestroySurface(std::move(surface2)); +} + +// Tests that switching using EnableDCLayers works. +TEST(DirectCompositionSurfaceTest, DXGIDCLayerSwitch) { + if (!gl::QueryDirectCompositionDevice( + gl::QueryD3D11DeviceObjectFromANGLE())) { + LOG(WARNING) + << "GL implementation not using DirectComposition, skipping test."; + return; + } + + TestImageTransportSurfaceDelegate delegate; + scoped_refptr<DirectCompositionSurfaceWin> surface( new DirectCompositionSurfaceWin(delegate.AsWeakPtr(), ui::GetHiddenWindow())); @@ -60,10 +143,13 @@ scoped_refptr<gl::GLContext> context = gl::init::CreateGLContext(nullptr, surface.get(), gl::GLContextAttribs()); EXPECT_TRUE(surface->Resize(gfx::Size(100, 100), 1.0, true)); + EXPECT_FALSE(surface->swap_chain()); - // First SetDrawRectangle must be full size of surface. + // First SetDrawRectangle must be full size of surface for DXGI + // swapchain. EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); + EXPECT_TRUE(surface->swap_chain()); // SetDrawRectangle can't be called again until swap. EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); @@ -73,50 +159,27 @@ EXPECT_TRUE(context->IsCurrent(surface.get())); - // SetDrawRectangle must be contained within surface. - EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 101, 101))); + surface->SetEnableDCLayers(true); + + // Surface switched to use IDCompositionSurface, so must draw to + // entire surface. + EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); EXPECT_TRUE(context->IsCurrent(surface.get())); + EXPECT_FALSE(surface->swap_chain()); - EXPECT_TRUE(surface->Resize(gfx::Size(50, 50), 1.0, true)); - EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); - EXPECT_TRUE(context->IsCurrent(surface.get())); + surface->SetEnableDCLayers(false); - scoped_refptr<DirectCompositionSurfaceWin> surface2( - new DirectCompositionSurfaceWin(delegate.AsWeakPtr(), - ui::GetHiddenWindow())); - EXPECT_TRUE(surface2->Initialize()); + EXPECT_EQ(gfx::SwapResult::SWAP_ACK, surface->SwapBuffers()); - scoped_refptr<gl::GLContext> context2 = gl::init::CreateGLContext( - nullptr, surface2.get(), gl::GLContextAttribs()); - EXPECT_TRUE(context2->MakeCurrent(surface2.get())); - EXPECT_TRUE(surface2->Resize(gfx::Size(100, 100), 1.0, true)); - // The previous IDCompositionSurface should be suspended when another - // surface is being drawn to. - EXPECT_TRUE(surface2->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); - EXPECT_TRUE(context2->IsCurrent(surface2.get())); + // Surface switched to use IDXGISwapChain, so must draw to entire + // surface. + EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); + EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); + EXPECT_TRUE(surface->swap_chain()); - // It should be possible to switch back to the previous surface and - // unsuspend it. - EXPECT_TRUE(context->MakeCurrent(surface.get())); - scoped_refptr<base::TaskRunner> task_runner1 = - surface->GetWindowTaskRunnerForTesting(); - scoped_refptr<base::TaskRunner> task_runner2 = - surface2->GetWindowTaskRunnerForTesting(); - - context2 = nullptr; - surface2 = nullptr; context = nullptr; - surface = nullptr; - - // Ensure that the ChildWindowWin posts the task to delete the thread to the - // main loop before doing RunUntilIdle. Otherwise the child threads could - // outlive the main thread. - RunPendingTasks(task_runner1); - RunPendingTasks(task_runner2); - - base::RunLoop().RunUntilIdle(); + DestroySurface(std::move(surface)); } - } // namespace } // namespace gpu
diff --git a/ios/chrome/browser/dom_distiller/distiller_viewer.cc b/ios/chrome/browser/dom_distiller/distiller_viewer.cc index 44edeb7..f9fa0bfb 100644 --- a/ios/chrome/browser/dom_distiller/distiller_viewer.cc +++ b/ios/chrome/browser/dom_distiller/distiller_viewer.cc
@@ -68,9 +68,11 @@ article_proto->pages(0).html().empty(); if (!is_empty) { std::vector<ImageInfo> images; - for (int i = 0; i < article_proto->pages(0).image_size(); i++) { - auto image = article_proto->pages(0).image(i); - images.push_back(ImageInfo{GURL(image.url()), image.data()}); + for (int p = 0; p < article_proto->pages_size(); p++) { + for (int i = 0; i < article_proto->pages(p).image_size(); i++) { + auto image = article_proto->pages(p).image(i); + images.push_back(ImageInfo{GURL(image.url()), image.data()}); + } } const std::string html = viewer::GetUnsafeArticleTemplateHtml( url_.spec(), distilled_page_prefs_->GetTheme(),
diff --git a/ios/chrome/browser/reading_list/reading_list_distiller_page.h b/ios/chrome/browser/reading_list/reading_list_distiller_page.h index 9b139f2..2a80e44 100644 --- a/ios/chrome/browser/reading_list/reading_list_distiller_page.h +++ b/ios/chrome/browser/reading_list/reading_list_distiller_page.h
@@ -45,10 +45,11 @@ public: typedef base::Callback<void(const GURL&, const GURL&)> RedirectionCallback; - // Creates a ReadingListDistillerPage. WebStates to download the pages will - // be provided by web_state_dispatcher. + // Creates a ReadingListDistillerPage to distill |url|. WebStates to download + // the pages will be provided by web_state_dispatcher. // |browser_state|, |web_state_dispatcher| and |delegate| must not be null. explicit ReadingListDistillerPage( + const GURL& url, web::BrowserState* browser_state, FaviconWebStateDispatcher* web_state_dispatcher, ReadingListDistillerPageDelegate* delegate); @@ -97,6 +98,7 @@ // Continues distillation by calling superclass |OnLoadURLDone|. void DelayedOnLoadURLDone(int delayed_task_id); GURL original_url_; + bool distilling_main_page_; FaviconWebStateDispatcher* web_state_dispatcher_; ReadingListDistillerPageDelegate* delegate_;
diff --git a/ios/chrome/browser/reading_list/reading_list_distiller_page.mm b/ios/chrome/browser/reading_list/reading_list_distiller_page.mm index e2fd850a..97262da 100644 --- a/ios/chrome/browser/reading_list/reading_list_distiller_page.mm +++ b/ios/chrome/browser/reading_list/reading_list_distiller_page.mm
@@ -55,10 +55,12 @@ ReadingListDistillerPageDelegate::~ReadingListDistillerPageDelegate() {} ReadingListDistillerPage::ReadingListDistillerPage( + const GURL& url, web::BrowserState* browser_state, FaviconWebStateDispatcher* web_state_dispatcher, ReadingListDistillerPageDelegate* delegate) : dom_distiller::DistillerPageIOS(browser_state), + original_url_(url), web_state_dispatcher_(web_state_dispatcher), delegate_(delegate), delayed_task_id_(0), @@ -77,8 +79,9 @@ std::unique_ptr<web::WebState> new_web_state = web_state_dispatcher_->RequestWebState(); AttachWebState(std::move(new_web_state)); - original_url_ = url; + delayed_task_id_++; + distilling_main_page_ = url == original_url_; FetchFavicon(url); DistillerPageIOS::DistillPageImpl(url, script); @@ -153,8 +156,10 @@ DistillerPageIOS::OnLoadURLDone(load_completion_status); return; } - delegate_->DistilledPageHasMimeType(original_url_, - CurrentWebState()->GetContentsMimeType()); + if (distilling_main_page_) { + delegate_->DistilledPageHasMimeType( + original_url_, CurrentWebState()->GetContentsMimeType()); + } if (!CurrentWebState()->ContentIsHTML()) { // If content is not HTML, distillation will fail immediatly. // Call the handler to make sure cleaning methods are called correctly. @@ -205,7 +210,7 @@ // If the visible URL is not the original URL, notify the caller that URL // changed. GURL redirected_url = CurrentWebState()->GetVisibleURL(); - if (redirected_url != original_url_ && delegate_) { + if (redirected_url != original_url_ && delegate_ && distilling_main_page_) { delegate_->DistilledPageRedirectedToURL(original_url_, redirected_url); } DistillerPageIOS::OnLoadURLDone(web::PageLoadCompletionStatus::SUCCESS);
diff --git a/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.h b/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.h index c1d2787..daabebe 100644 --- a/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.h +++ b/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "url/gurl.h" namespace web { class BrowserState; @@ -28,8 +29,10 @@ explicit ReadingListDistillerPageFactory(web::BrowserState* browser_state); virtual ~ReadingListDistillerPageFactory(); - // Creates a ReadingListDistillerPage. + // Creates a ReadingListDistillerPage to distill |url|. + // Information about page will be reported to |delegate|. std::unique_ptr<ReadingListDistillerPage> CreateReadingListDistillerPage( + const GURL& url, ReadingListDistillerPageDelegate* delegate) const; // Releases all WebState owned by |web_state_dispatcher_|.
diff --git a/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.mm b/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.mm index eba07b7..6adb7689b5 100644 --- a/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.mm +++ b/ios/chrome/browser/reading_list/reading_list_distiller_page_factory.mm
@@ -23,9 +23,10 @@ std::unique_ptr<ReadingListDistillerPage> ReadingListDistillerPageFactory::CreateReadingListDistillerPage( + const GURL& url, ReadingListDistillerPageDelegate* delegate) const { return base::MakeUnique<ReadingListDistillerPage>( - browser_state_, web_state_dispatcher_.get(), delegate); + url, browser_state_, web_state_dispatcher_.get(), delegate); } void ReadingListDistillerPageFactory::ReleaseAllRetainedWebState() {
diff --git a/ios/chrome/browser/reading_list/url_downloader.cc b/ios/chrome/browser/reading_list/url_downloader.cc index 0f58433b..358015e 100644 --- a/ios/chrome/browser/reading_list/url_downloader.cc +++ b/ios/chrome/browser/reading_list/url_downloader.cc
@@ -173,7 +173,7 @@ saved_size_ = 0; std::unique_ptr<reading_list::ReadingListDistillerPage> reading_list_distiller_page = - distiller_page_factory_->CreateReadingListDistillerPage(this); + distiller_page_factory_->CreateReadingListDistillerPage(url, this); distiller_.reset(new dom_distiller::DistillerViewer( distiller_factory_, std::move(reading_list_distiller_page), pref_service_,
diff --git a/ios/showcase/BUILD.gn b/ios/showcase/BUILD.gn index d19ba9c..369f9965 100644 --- a/ios/showcase/BUILD.gn +++ b/ios/showcase/BUILD.gn
@@ -28,6 +28,7 @@ "//ios/clean/chrome/browser/ui/tools:tools_ui", "//ios/showcase/settings", "//ios/showcase/suggestions", + "//ios/showcase/tab", "//ios/showcase/tab_grid", "//ios/showcase/tab_strip", "//ios/showcase/toolbar", @@ -51,6 +52,8 @@ # Add all eg_tests targets below. "//ios/showcase/core:eg_tests", + "//ios/showcase/suggestions:eg_tests", + "//ios/showcase/tab:eg_tests", "//ios/showcase/tab_grid:eg_tests", # All shared libraries must have the sanitizer deps to properly link in
diff --git a/ios/showcase/core/showcase_model.mm b/ios/showcase/core/showcase_model.mm index 7aafb0c..daec8c3 100644 --- a/ios/showcase/core/showcase_model.mm +++ b/ios/showcase/core/showcase_model.mm
@@ -17,11 +17,6 @@ + (NSArray<showcase::ModelRow*>*)model { return @[ @{ - showcase::kClassForDisplayKey : @"SettingsViewController", - showcase::kClassForInstantiationKey : @"SCSettingsCoordinator", - showcase::kUseCaseKey : @"Main settings screen", - }, - @{ showcase::kClassForDisplayKey : @"ContentSuggestionsViewController", showcase::kClassForInstantiationKey : @"SCSuggestionsCoordinator", showcase::kUseCaseKey : @"New Suggestions UI", @@ -32,9 +27,9 @@ showcase::kUseCaseKey : @"Tools menu", }, @{ - showcase::kClassForDisplayKey : @"UITableViewCell", - showcase::kClassForInstantiationKey : @"UIKitTableViewCellViewController", - showcase::kUseCaseKey : @"UIKit Table Cells", + showcase::kClassForDisplayKey : @"SettingsViewController", + showcase::kClassForInstantiationKey : @"SCSettingsCoordinator", + showcase::kUseCaseKey : @"Main settings screen", }, @{ showcase::kClassForDisplayKey : @"TabGridViewController", @@ -47,10 +42,25 @@ showcase::kUseCaseKey : @"Tab strip container", }, @{ + showcase::kClassForDisplayKey : @"TopToolbarTabViewController", + showcase::kClassForInstantiationKey : @"SCTopToolbarTabCoordinator", + showcase::kUseCaseKey : @"Top toolbar tab", + }, + @{ + showcase::kClassForDisplayKey : @"BottomToolbarTabViewController", + showcase::kClassForInstantiationKey : @"SCBottomToolbarTabCoordinator", + showcase::kUseCaseKey : @"Bottom toolbar tab", + }, + @{ showcase::kClassForDisplayKey : @"ToolbarViewController", showcase::kClassForInstantiationKey : @"SCToolbarCoordinator", showcase::kUseCaseKey : @"Toolbar", }, + @{ + showcase::kClassForDisplayKey : @"UITableViewCell", + showcase::kClassForInstantiationKey : @"UIKitTableViewCellViewController", + showcase::kUseCaseKey : @"UIKit Table Cells", + }, ]; }
diff --git a/ios/showcase/suggestions/sc_suggestions_egtest.mm b/ios/showcase/suggestions/sc_suggestions_egtest.mm index 8509dea4..c698878f 100644 --- a/ios/showcase/suggestions/sc_suggestions_egtest.mm +++ b/ios/showcase/suggestions/sc_suggestions_egtest.mm
@@ -4,6 +4,7 @@ #import <EarlGrey/EarlGrey.h> +#import "ios/showcase/test/showcase_matchers.h" #import "ios/showcase/test/showcase_test_case.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -17,10 +18,12 @@ @implementation SCSuggestionsTestCase // Tests launching ContentSuggestionsViewController. -- (void)testLaunchAndTappingCell { +- (void)testLaunch { [[EarlGrey selectElementWithMatcher:grey_text(@"ContentSuggestionsViewController")] performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:showcase_matchers::FirstLevelBackButton()] + performAction:grey_tap()]; } @end
diff --git a/ios/showcase/tab/BUILD.gn b/ios/showcase/tab/BUILD.gn new file mode 100644 index 0000000..b3df825 --- /dev/null +++ b/ios/showcase/tab/BUILD.gn
@@ -0,0 +1,33 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("tab") { + sources = [ + "sc_bottom_toolbar_tab_coordinator.h", + "sc_bottom_toolbar_tab_coordinator.mm", + "sc_top_toolbar_tab_coordinator.h", + "sc_top_toolbar_tab_coordinator.mm", + ] + deps = [ + "//base", + "//ios/clean/chrome/browser/ui/commands", + "//ios/clean/chrome/browser/ui/tab:tab_ui", + "//ios/showcase/common", + ] + libs = [ "UIKit.framework" ] + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("eg_tests") { + testonly = true + sources = [ + "sc_tab_egtest.mm", + ] + deps = [ + "//ios/showcase/test", + "//ios/third_party/earl_grey", + ] + libs = [ "XCTest.framework" ] + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.h b/ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.h new file mode 100644 index 0000000..66b1557 --- /dev/null +++ b/ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.h
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_SHOWCASE_TAB_SC_BOTTOM_TOOLBAR_TAB_COORDINATOR_H_ +#define IOS_SHOWCASE_TAB_SC_BOTTOM_TOOLBAR_TAB_COORDINATOR_H_ + +#import <UIKit/UIKit.h> + +#import "ios/showcase/common/navigation_coordinator.h" + +@interface SCBottomToolbarTabCoordinator : NSObject<NavigationCoordinator> +@end + +#endif // IOS_SHOWCASE_TAB_SC_BOTTOM_TOOLBAR_TAB_COORDINATOR_H_
diff --git a/ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.mm b/ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.mm new file mode 100644 index 0000000..ae2c688 --- /dev/null +++ b/ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.mm
@@ -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. + +#import "ios/showcase/tab/sc_bottom_toolbar_tab_coordinator.h" + +#import "ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation SCBottomToolbarTabCoordinator + +@synthesize baseViewController; + +- (void)start { + UIViewController* bottomToolbarTabViewController = + [[BottomToolbarTabViewController alloc] init]; + bottomToolbarTabViewController.title = @"Bottom toolbar tab"; + [self.baseViewController pushViewController:bottomToolbarTabViewController + animated:YES]; +} + +@end
diff --git a/ios/showcase/tab/sc_tab_egtest.mm b/ios/showcase/tab/sc_tab_egtest.mm new file mode 100644 index 0000000..c1ab075 --- /dev/null +++ b/ios/showcase/tab/sc_tab_egtest.mm
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <EarlGrey/EarlGrey.h> + +#import "ios/showcase/test/showcase_matchers.h" +#import "ios/showcase/test/showcase_test_case.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Tests for the tab container view controller. +@interface SCTabTestCase : ShowcaseTestCase +@end + +@implementation SCTabTestCase + +// Tests launching TopToolbarTabViewController. +- (void)testLaunchWithTopToolbar { + [[EarlGrey selectElementWithMatcher:grey_text(@"TopToolbarTabViewController")] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:showcase_matchers::FirstLevelBackButton()] + performAction:grey_tap()]; +} + +// Tests launching BottomToolbarTabViewController. +- (void)testLaunchWithBottomToolbar { + [[EarlGrey + selectElementWithMatcher:grey_text(@"BottomToolbarTabViewController")] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:showcase_matchers::FirstLevelBackButton()] + performAction:grey_tap()]; +} + +@end
diff --git a/ios/showcase/tab/sc_top_toolbar_tab_coordinator.h b/ios/showcase/tab/sc_top_toolbar_tab_coordinator.h new file mode 100644 index 0000000..6f59a82 --- /dev/null +++ b/ios/showcase/tab/sc_top_toolbar_tab_coordinator.h
@@ -0,0 +1,15 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_SHOWCASE_TAB_SC_TOP_TOOLBAR_TAB_COORDINATOR_H_ +#define IOS_SHOWCASE_TAB_SC_TOP_TOOLBAR_TAB_COORDINATOR_H_ + +#import <UIKit/UIKit.h> + +#import "ios/showcase/common/navigation_coordinator.h" + +@interface SCTopToolbarTabCoordinator : NSObject<NavigationCoordinator> +@end + +#endif // IOS_SHOWCASE_TAB_SC_TOP_TOOLBAR_TAB_COORDINATOR_H_
diff --git a/ios/showcase/tab/sc_top_toolbar_tab_coordinator.mm b/ios/showcase/tab/sc_top_toolbar_tab_coordinator.mm new file mode 100644 index 0000000..563dfcd --- /dev/null +++ b/ios/showcase/tab/sc_top_toolbar_tab_coordinator.mm
@@ -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. + +#import "ios/showcase/tab/sc_top_toolbar_tab_coordinator.h" + +#import "ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation SCTopToolbarTabCoordinator + +@synthesize baseViewController; + +- (void)start { + UIViewController* topToolbarTabViewController = + [[TopToolbarTabViewController alloc] init]; + topToolbarTabViewController.title = @"Top toolbar tab"; + [self.baseViewController pushViewController:topToolbarTabViewController + animated:YES]; +} + +@end
diff --git a/ios/showcase/tab_grid/sc_tab_grid_egtest.mm b/ios/showcase/tab_grid/sc_tab_grid_egtest.mm index cf0c922..c99c5db 100644 --- a/ios/showcase/tab_grid/sc_tab_grid_egtest.mm +++ b/ios/showcase/tab_grid/sc_tab_grid_egtest.mm
@@ -4,6 +4,7 @@ #import <EarlGrey/EarlGrey.h> +#import "ios/showcase/test/showcase_matchers.h" #import "ios/showcase/test/showcase_test_case.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -32,6 +33,8 @@ [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel( @"protocol_alerter_done")] performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:showcase_matchers::FirstLevelBackButton()] + performAction:grey_tap()]; } @end
diff --git a/ios/showcase/test/BUILD.gn b/ios/showcase/test/BUILD.gn index 9be866c..277ef348 100644 --- a/ios/showcase/test/BUILD.gn +++ b/ios/showcase/test/BUILD.gn
@@ -5,6 +5,8 @@ source_set("test") { testonly = true sources = [ + "showcase_matchers.h", + "showcase_matchers.mm", "showcase_test_case.h", "showcase_test_case.mm", ]
diff --git a/ios/showcase/test/showcase_matchers.h b/ios/showcase/test/showcase_matchers.h new file mode 100644 index 0000000..e8fb5ceb --- /dev/null +++ b/ios/showcase/test/showcase_matchers.h
@@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_SHOWCASE_TEST_SHOWCASE_MATCHERS_H_ +#define IOS_SHOWCASE_TEST_SHOWCASE_MATCHERS_H_ + +#import <EarlGrey/EarlGrey.h> + +namespace showcase_matchers { + +// Matcher for the back button on screens presented from the Showcase home +// screen. +id<GREYMatcher> FirstLevelBackButton(); + +} // namespace showcase_matchers + +#endif // IOS_SHOWCASE_TEST_SHOWCASE_MATCHERS_H_
diff --git a/ios/showcase/test/showcase_matchers.mm b/ios/showcase/test/showcase_matchers.mm new file mode 100644 index 0000000..9eb945f2 --- /dev/null +++ b/ios/showcase/test/showcase_matchers.mm
@@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/showcase/test/showcase_matchers.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace showcase_matchers { + +id<GREYMatcher> FirstLevelBackButton() { + return grey_kindOfClass( + NSClassFromString(@"_UINavigationBarBackIndicatorView")); +} + +} // namespace showcase_matchers
diff --git a/ios/web_view/internal/translate/BUILD.gn b/ios/web_view/internal/translate/BUILD.gn index 3c0d86a..d42ff35 100644 --- a/ios/web_view/internal/translate/BUILD.gn +++ b/ios/web_view/internal/translate/BUILD.gn
@@ -29,4 +29,6 @@ "//ios/web_view/public", "//url", ] + + configs += [ "//build/config/compiler:enable_arc" ] }
diff --git a/ios/web_view/internal/translate/cwv_translate_manager_impl.mm b/ios/web_view/internal/translate/cwv_translate_manager_impl.mm index 25e60df8..1f087aa 100644 --- a/ios/web_view/internal/translate/cwv_translate_manager_impl.mm +++ b/ios/web_view/internal/translate/cwv_translate_manager_impl.mm
@@ -9,6 +9,10 @@ #include "components/translate/core/browser/translate_manager.h" #include "components/translate/core/browser/translate_ui_delegate.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + @implementation CWVTranslateManagerImpl { std::unique_ptr<translate::TranslateUIDelegate> _translateUIDelegate; }
diff --git a/ios/web_view/internal/translate/web_view_translate_client.h b/ios/web_view/internal/translate/web_view_translate_client.h index ea80696..9d0816b 100644 --- a/ios/web_view/internal/translate/web_view_translate_client.h +++ b/ios/web_view/internal/translate/web_view_translate_client.h
@@ -8,14 +8,15 @@ #include <memory> #include <string> +#import "base/ios/weak_nsobject.h" #include "components/translate/core/browser/translate_client.h" #include "components/translate/core/browser/translate_step.h" #include "components/translate/core/common/translate_errors.h" #import "components/translate/ios/browser/ios_translate_driver.h" #include "ios/web/public/web_state/web_state_observer.h" #import "ios/web/public/web_state/web_state_user_data.h" +#import "ios/web_view/public/cwv_translate_delegate.h" -@protocol CWVTranslateDelegate; class PrefService; namespace translate { @@ -38,7 +39,7 @@ // Sets the delegate passed by the embedder. // |delegate| is assumed to outlive this WebViewTranslateClient. void set_translate_delegate(id<CWVTranslateDelegate> delegate) { - delegate_ = delegate; + delegate_.reset(delegate); } private: @@ -72,7 +73,7 @@ translate::IOSTranslateDriver translate_driver_; // Delegate provided by the embedder. - id<CWVTranslateDelegate> delegate_; // Weak. + base::WeakNSProtocol<id<CWVTranslateDelegate>> delegate_; DISALLOW_COPY_AND_ASSIGN(WebViewTranslateClient); };
diff --git a/ios/web_view/internal/translate/web_view_translate_client.mm b/ios/web_view/internal/translate/web_view_translate_client.mm index 188e9de..d0f7171 100644 --- a/ios/web_view/internal/translate/web_view_translate_client.mm +++ b/ios/web_view/internal/translate/web_view_translate_client.mm
@@ -26,6 +26,10 @@ #import "ios/web_view/public/cwv_translate_delegate.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + DEFINE_WEB_STATE_USER_DATA_KEY(ios_web_view::WebViewTranslateClient); namespace ios_web_view { @@ -55,7 +59,7 @@ const std::string& target_language, translate::TranslateErrors::Type error_type, bool triggered_from_menu) { - if (!delegate_) + if (!delegate_.get()) return; if (error_type != translate::TranslateErrors::NONE)
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index 91836b8..4085df6 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc
@@ -540,6 +540,15 @@ config->Initialize(codec, profile, format, color_space, coded_size, visible_rect, natural_size, extra_data, GetEncryptionScheme(stream)); + + const AVCodecParameters* codec_parameters = stream->codecpar; + config->set_color_space_info(gfx::ColorSpace::CreateVideo( + codec_parameters->color_primaries, codec_parameters->color_trc, + codec_parameters->color_space, + codec_parameters->color_range != AVCOL_RANGE_MPEG + ? gfx::ColorSpace::RangeID::FULL + : gfx::ColorSpace::RangeID::LIMITED)); + return true; }
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc index 6a924df..b3a071a 100644 --- a/media/gpu/video_encode_accelerator_unittest.cc +++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -2224,8 +2224,9 @@ ::testing::Values( std::make_tuple(1, false, 0, true, false, true, false, false, false))); +// TODO(kcwu): add back bitrate test after crbug.com/693336 fixed. INSTANTIATE_TEST_CASE_P( - MidStreamParamSwitchFPS, + DISABLED_MidStreamParamSwitchFPS, VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(1, false, 0, true, false, false, true, false, false))); @@ -2235,7 +2236,6 @@ VideoEncodeAcceleratorTest, ::testing::Values( std::make_tuple(3, false, 0, false, false, false, false, false, false), - std::make_tuple(3, false, 0, true, false, false, true, false, false), std::make_tuple(3, false, 0, true, false, true, false, false, false))); INSTANTIATE_TEST_CASE_P(
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h index 0aea756..b519fe9 100644 --- a/mojo/public/cpp/bindings/interface_endpoint_client.h +++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -96,7 +96,7 @@ // state. bool Accept(Message* message) override; bool AcceptWithResponder(Message* message, - MessageReceiver* responder) override; + std::unique_ptr<MessageReceiver> responder) override; // The following methods are called by the router. They must be called // outside of the router's lock.
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h index 72f7960..a4b51882 100644 --- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h +++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
@@ -131,7 +131,7 @@ void ForwardMessageWithResponder(Message message, std::unique_ptr<MessageReceiver> responder) { - endpoint_client_->AcceptWithResponder(&message, responder.release()); + endpoint_client_->AcceptWithResponder(&message, std::move(responder)); } private:
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc index c90aadad..1b7bb78 100644 --- a/mojo/public/cpp/bindings/lib/control_message_handler.cc +++ b/mojo/public/cpp/bindings/lib/control_message_handler.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/logging.h" +#include "base/macros.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/lib/validation_util.h" @@ -80,19 +81,20 @@ bool ControlMessageHandler::AcceptWithResponder( Message* message, - MessageReceiverWithStatus* responder) { + std::unique_ptr<MessageReceiverWithStatus> responder) { if (!ValidateControlRequestWithResponse(message)) return false; if (message->header()->name == interface_control::kRunMessageId) - return Run(message, responder); + return Run(message, std::move(responder)); NOTREACHED(); return false; } -bool ControlMessageHandler::Run(Message* message, - MessageReceiverWithStatus* responder) { +bool ControlMessageHandler::Run( + Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder) { interface_control::internal::RunMessageParams_Data* params = reinterpret_cast<interface_control::internal::RunMessageParams_Data*>( message->mutable_payload()); @@ -124,9 +126,7 @@ nullptr; Serialize<interface_control::RunResponseMessageParamsDataView>( response_params_ptr, builder.buffer(), &response_params, &context_); - bool ok = responder->Accept(builder.message()); - ALLOW_UNUSED_LOCAL(ok); - delete responder; + ignore_result(responder->Accept(builder.message())); return true; }
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.h b/mojo/public/cpp/bindings/lib/control_message_handler.h index 3c385e4..5d1f716 100644 --- a/mojo/public/cpp/bindings/lib/control_message_handler.h +++ b/mojo/public/cpp/bindings/lib/control_message_handler.h
@@ -27,12 +27,13 @@ // Call the following methods only if IsControlMessage() returned true. bool Accept(Message* message) override; - // Takes ownership of |responder|. - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override; + bool AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder) override; private: - bool Run(Message* message, MessageReceiverWithStatus* responder); + bool Run(Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder); bool RunOrClosePipe(Message* message); uint32_t interface_version_;
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc index 23de991..d082b49 100644 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -85,9 +85,10 @@ interface_control::internal::RunMessageParams_Data* params = nullptr; Serialize<interface_control::RunMessageParamsDataView>( params_ptr, builder.buffer(), ¶ms, &context); - MessageReceiver* responder = new RunResponseForwardToCallback(callback); - if (!receiver->AcceptWithResponder(builder.message(), responder)) - delete responder; + std::unique_ptr<MessageReceiver> responder = + base::MakeUnique<RunResponseForwardToCallback>(callback); + ignore_result( + receiver->AcceptWithResponder(builder.message(), std::move(responder))); } Message ConstructRunOrClosePipeMessage( @@ -115,8 +116,7 @@ interface_control::RunOrClosePipeInputPtr input_ptr) { Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr))); - bool ok = receiver->Accept(&message); - ALLOW_UNUSED_LOCAL(ok); + ignore_result(receiver->Accept(&message)); } void RunVersionCallback(
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc index 3eca5a1..4682e72f 100644 --- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc +++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -234,8 +234,9 @@ return controller_->SendMessage(message); } -bool InterfaceEndpointClient::AcceptWithResponder(Message* message, - MessageReceiver* responder) { +bool InterfaceEndpointClient::AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiver> responder) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(message->has_flag(Message::kFlagExpectsResponse)); DCHECK(!handle_.pending_association()); @@ -261,15 +262,13 @@ return false; if (!is_sync) { - // We assume ownership of |responder|. - async_responders_[request_id] = base::WrapUnique(responder); + async_responders_[request_id] = std::move(responder); return true; } SyncCallRestrictions::AssertSyncCallAllowed(); bool response_received = false; - std::unique_ptr<MessageReceiver> sync_responder(responder); sync_responses_.insert(std::make_pair( request_id, base::MakeUnique<SyncResponseInfo>(&response_received))); @@ -282,11 +281,10 @@ auto iter = sync_responses_.find(request_id); DCHECK_EQ(&response_received, iter->second->response_received); if (response_received) - ignore_result(sync_responder->Accept(&iter->second->response)); + ignore_result(responder->Accept(&iter->second->response)); sync_responses_.erase(iter); } - // Return true means that we take ownership of |responder|. return true; } @@ -375,17 +373,16 @@ } if (message->has_flag(Message::kFlagExpectsResponse)) { - MessageReceiverWithStatus* responder = - new ResponderThunk(weak_ptr_factory_.GetWeakPtr(), task_runner_); - bool ok = false; + std::unique_ptr<MessageReceiverWithStatus> responder = + base::MakeUnique<ResponderThunk>(weak_ptr_factory_.GetWeakPtr(), + task_runner_); if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) { - ok = control_message_handler_.AcceptWithResponder(message, responder); + return control_message_handler_.AcceptWithResponder(message, + std::move(responder)); } else { - ok = incoming_receiver_->AcceptWithResponder(message, responder); + return incoming_receiver_->AcceptWithResponder(message, + std::move(responder)); } - if (!ok) - delete responder; - return ok; } else if (message->has_flag(Message::kFlagIsResponse)) { uint64_t request_id = message->request_id();
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h index 8f5b4ff..fa54979 100644 --- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h +++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -163,7 +163,7 @@ void ForwardMessageWithResponder(Message message, std::unique_ptr<MessageReceiver> responder) { ConfigureProxyIfNecessary(); - endpoint_client_->AcceptWithResponder(&message, responder.release()); + endpoint_client_->AcceptWithResponder(&message, std::move(responder)); } private:
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc index 701108e1..1029c2c4 100644 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc +++ b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
@@ -7,8 +7,8 @@ #include <stddef.h> #include <utility> -#include "base/compiler_specific.h" #include "base/logging.h" +#include "base/macros.h" #include "mojo/public/cpp/bindings/lib/message_builder.h" #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" @@ -44,8 +44,7 @@ InterfaceId id, const base::Optional<DisconnectReason>& reason) { Message message(ConstructPeerEndpointClosedMessage(id, reason)); - bool ok = receiver_->Accept(&message); - ALLOW_UNUSED_LOCAL(ok); + ignore_result(receiver_->Accept(&message)); } // static
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h index 65d6cec..48e6900 100644 --- a/mojo/public/cpp/bindings/message.h +++ b/mojo/public/cpp/bindings/message.h
@@ -183,14 +183,8 @@ // responder) to handle the response message generated from the given // message. The responder's Accept method may be called during // AcceptWithResponder or some time after its return. - // - // NOTE: Upon returning true, AcceptWithResponder assumes ownership of - // |responder| and will delete it after calling |responder->Accept| or upon - // its own destruction. - // - // TODO(yzshen): consider changing |responder| to - // std::unique_ptr<MessageReceiver>. - virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder) + virtual bool AcceptWithResponder(Message* message, + std::unique_ptr<MessageReceiver> responder) WARN_UNUSED_RESULT = 0; }; @@ -222,16 +216,9 @@ // the responder) to handle the response message generated from the given // message. Any of the responder's methods (Accept or IsValid) may be called // during AcceptWithResponder or some time after its return. - // - // NOTE: Upon returning true, AcceptWithResponder assumes ownership of - // |responder| and will delete it after calling |responder->Accept| or upon - // its own destruction. - // - // TODO(yzshen): consider changing |responder| to - // std::unique_ptr<MessageReceiver>. virtual bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) - WARN_UNUSED_RESULT = 0; + std::unique_ptr<MessageReceiverWithStatus> + responder) WARN_UNUSED_RESULT = 0; }; class MOJO_CPP_BINDINGS_EXPORT PassThroughFilter
diff --git a/mojo/public/cpp/bindings/tests/bindings_perftest.cc b/mojo/public/cpp/bindings/tests/bindings_perftest.cc index 6a50de4..65b3c8c1 100644 --- a/mojo/public/cpp/bindings/tests/bindings_perftest.cc +++ b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
@@ -160,8 +160,9 @@ return true; } - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override { + bool AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder) override { NOTREACHED(); return true; } @@ -232,8 +233,9 @@ return true; } - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override { + bool AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder) override { NOTREACHED(); return true; }
diff --git a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc index 31963e0..8950928 100644 --- a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc +++ b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
@@ -72,8 +72,8 @@ MessageQueue message_queue; base::RunLoop run_loop; client0.AcceptWithResponder( - &request, - new MessageAccumulator(&message_queue, run_loop.QuitClosure())); + &request, base::MakeUnique<MessageAccumulator>(&message_queue, + run_loop.QuitClosure())); run_loop.Run(); @@ -91,8 +91,8 @@ base::RunLoop run_loop2; client0.AcceptWithResponder( - &request2, - new MessageAccumulator(&message_queue, run_loop2.QuitClosure())); + &request2, base::MakeUnique<MessageAccumulator>(&message_queue, + run_loop2.QuitClosure())); run_loop2.Run(); @@ -117,7 +117,8 @@ AllocRequestMessage(1, "hello", &request); MessageQueue message_queue; - client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + client0.AcceptWithResponder( + &request, base::MakeUnique<MessageAccumulator>(&message_queue)); router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); @@ -134,8 +135,8 @@ Message request2; AllocRequestMessage(1, "hello again", &request2); - client0.AcceptWithResponder(&request2, - new MessageAccumulator(&message_queue)); + client0.AcceptWithResponder( + &request2, base::MakeUnique<MessageAccumulator>(&message_queue)); router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); @@ -167,8 +168,8 @@ MessageQueue message_queue; base::RunLoop run_loop2; client0.AcceptWithResponder( - &request, - new MessageAccumulator(&message_queue, run_loop2.QuitClosure())); + &request, base::MakeUnique<MessageAccumulator>(&message_queue, + run_loop2.QuitClosure())); run_loop.Run(); // The request has been received but the response has not been sent yet. @@ -194,8 +195,8 @@ base::RunLoop run_loop4; client0.AcceptWithResponder( - &request2, - new MessageAccumulator(&message_queue, run_loop4.QuitClosure())); + &request2, base::MakeUnique<MessageAccumulator>(&message_queue, + run_loop4.QuitClosure())); run_loop3.Run(); // The request has been received but the response has not been sent yet. @@ -246,7 +247,8 @@ AllocRequestMessage(1, "hello", &request); MessageQueue message_queue; - client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); + client0.AcceptWithResponder( + &request, base::MakeUnique<MessageAccumulator>(&message_queue)); run_loop3.Run(); // The request has been received but no response has been sent. @@ -293,8 +295,8 @@ AllocRequestMessage(1, "hello", &request); MessageQueue message_queue; - client0.AcceptWithResponder(&request, - new MessageAccumulator(&message_queue)); + client0.AcceptWithResponder( + &request, base::MakeUnique<MessageAccumulator>(&message_queue)); run_loop.Run();
diff --git a/mojo/public/cpp/bindings/tests/router_test_util.cc b/mojo/public/cpp/bindings/tests/router_test_util.cc index b9b93d8..9bab1cb 100644 --- a/mojo/public/cpp/bindings/tests/router_test_util.cc +++ b/mojo/public/cpp/bindings/tests/router_test_util.cc
@@ -58,14 +58,13 @@ bool ResponseGenerator::AcceptWithResponder( Message* message, - MessageReceiverWithStatus* responder) { + std::unique_ptr<MessageReceiverWithStatus> responder) { EXPECT_TRUE(message->has_flag(Message::kFlagExpectsResponse)); bool result = SendResponse(message->name(), message->request_id(), reinterpret_cast<const char*>(message->payload()), - responder); + responder.get()); EXPECT_TRUE(responder->IsValid()); - delete responder; return result; } @@ -84,18 +83,16 @@ LazyResponseGenerator::LazyResponseGenerator(const base::Closure& closure) : responder_(nullptr), name_(0), request_id_(0), closure_(closure) {} -LazyResponseGenerator::~LazyResponseGenerator() { - delete responder_; -} +LazyResponseGenerator::~LazyResponseGenerator() = default; bool LazyResponseGenerator::AcceptWithResponder( Message* message, - MessageReceiverWithStatus* responder) { + std::unique_ptr<MessageReceiverWithStatus> responder) { name_ = message->name(); request_id_ = message->request_id(); request_string_ = std::string(reinterpret_cast<const char*>(message->payload())); - responder_ = responder; + responder_ = std::move(responder); if (!closure_.is_null()) { closure_.Run(); closure_.Reset(); @@ -105,9 +102,8 @@ void LazyResponseGenerator::Complete(bool send_response) { if (send_response) { - SendResponse(name_, request_id_, request_string_.c_str(), responder_); + SendResponse(name_, request_id_, request_string_.c_str(), responder_.get()); } - delete responder_; responder_ = nullptr; }
diff --git a/mojo/public/cpp/bindings/tests/router_test_util.h b/mojo/public/cpp/bindings/tests/router_test_util.h index c6fb372d..dd6aff63 100644 --- a/mojo/public/cpp/bindings/tests/router_test_util.h +++ b/mojo/public/cpp/bindings/tests/router_test_util.h
@@ -42,9 +42,9 @@ bool Accept(Message* message) override; - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override; - + bool AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder) override; bool SendResponse(uint32_t name, uint64_t request_id, const char* request_string, @@ -58,8 +58,9 @@ ~LazyResponseGenerator() override; - bool AcceptWithResponder(Message* message, - MessageReceiverWithStatus* responder) override; + bool AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiverWithStatus> responder) override; bool has_responder() const { return !!responder_; } @@ -78,7 +79,7 @@ // also sends a response. void Complete(bool send_response); - MessageReceiverWithStatus* responder_; + std::unique_ptr<MessageReceiverWithStatus> responder_; uint32_t name_; uint64_t request_id_; std::string request_string_;
diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc index 579576fd..1f95a27a 100644 --- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc +++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -295,8 +295,9 @@ return stub.Accept(message); } - bool AcceptWithResponder(mojo::Message* message, - mojo::MessageReceiver* responder) override { + bool AcceptWithResponder( + mojo::Message* message, + std::unique_ptr<mojo::MessageReceiver> responder) override { return false; } };
diff --git a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h index bab6d22c..8b32b30b 100644 --- a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h +++ b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
@@ -73,16 +73,17 @@ return true; } - bool AcceptWithResponder(Message* message, - MessageReceiver* response_receiver) override { + bool AcceptWithResponder( + Message* message, + std::unique_ptr<MessageReceiver> response_receiver) override { if (!message->associated_endpoint_handles()->empty()) { // Please see comment for the DCHECK in the previous method. DCHECK(associated_group_.GetController()); message->SerializeAssociatedEndpointHandles( associated_group_.GetController()); } - auto responder = base::MakeUnique<ForwardToCallingThread>( - base::WrapUnique(response_receiver)); + auto responder = + base::MakeUnique<ForwardToCallingThread>(std::move(response_receiver)); task_runner_->PostTask( FROM_HERE, base::Bind(forward_with_responder_, base::Passed(message), base::Passed(&responder)));
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index a23b107..aba18380 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -169,14 +169,14 @@ "&serialization_context")}} bool result = false; - mojo::MessageReceiver* responder = + std::unique_ptr<mojo::MessageReceiver> responder( new {{class_name}}_{{method.name}}_HandleSyncResponse( &result {%- for param in method.response_parameters -%} , param_{{param.name}} -{%- endfor %}); - if (!receiver_->AcceptWithResponder(builder.message(), responder)) - delete responder; +{%- endfor %})); + ignore_result(receiver_->AcceptWithResponder(builder.message(), + std::move(responder))); return result; } {%- endif %} @@ -200,15 +200,15 @@ "&serialization_context")}} {%- if method.response_parameters != None %} - mojo::MessageReceiver* responder = - new {{class_name}}_{{method.name}}_ForwardToCallback(std::move(callback)); - if (!receiver_->AcceptWithResponder(builder.message(), responder)) - delete responder; + std::unique_ptr<mojo::MessageReceiver> responder( + new {{class_name}}_{{method.name}}_ForwardToCallback( + std::move(callback))); + ignore_result(receiver_->AcceptWithResponder(builder.message(), + std::move(responder))); {%- else %} - bool ok = receiver_->Accept(builder.message()); - // This return value may be ignored as !ok implies the Connector has + // This return value may be ignored as false implies the Connector has // encountered an error, which will be visible through other means. - ALLOW_UNUSED_LOCAL(ok); + ignore_result(receiver_->Accept(builder.message())); {%- endif %} } {%- endfor %} @@ -226,10 +226,10 @@ static {{class_name}}::{{method.name}}Callback CreateCallback( uint64_t request_id, bool is_sync, - mojo::MessageReceiverWithStatus* responder) { + std::unique_ptr<mojo::MessageReceiverWithStatus> responder) { std::unique_ptr<{{class_name}}_{{method.name}}_ProxyToResponder> proxy( new {{class_name}}_{{method.name}}_ProxyToResponder( - request_id, is_sync, responder)); + request_id, is_sync, std::move(responder))); return base::Bind(&{{class_name}}_{{method.name}}_ProxyToResponder::Run, base::Passed(&proxy)); } @@ -245,17 +245,17 @@ #endif // If the Callback was dropped then deleting the responder will close // the pipe so the calling application knows to stop waiting for a reply. - delete responder_; + responder_ = nullptr; } private: {{class_name}}_{{method.name}}_ProxyToResponder( uint64_t request_id, bool is_sync, - mojo::MessageReceiverWithStatus* responder) + std::unique_ptr<mojo::MessageReceiverWithStatus> responder) : request_id_(request_id), is_sync_(is_sync), - responder_(responder) { + responder_(std::move(responder)) { } void Run( @@ -264,7 +264,7 @@ uint64_t request_id_; bool is_sync_; - mojo::MessageReceiverWithStatus* responder_; + std::unique_ptr<mojo::MessageReceiverWithStatus> responder_; DISALLOW_COPY_AND_ASSIGN({{class_name}}_{{method.name}}_ProxyToResponder); }; @@ -285,12 +285,10 @@ {{build_message(response_params_struct, "in_%s", params_description, "&serialization_context")}} - bool ok = responder_->Accept(builder.message()); - ALLOW_UNUSED_LOCAL(ok); - // TODO(darin): !ok returned here indicates a malformed message, and that may - // be good reason to close the connection. However, we don't have a way to do - // that from here. We should add a way. - delete responder_; + ignore_result(responder_->Accept(builder.message())); + // TODO(darin): Accept() returning false indicates a malformed message, and + // that may be good reason to close the connection. However, we don't have a + // way to do that from here. We should add a way. responder_ = nullptr; } {%- endif -%} @@ -334,7 +332,7 @@ bool {{class_name}}StubDispatch::AcceptWithResponder( {{interface.name}}* impl, mojo::Message* message, - mojo::MessageReceiverWithStatus* responder) { + std::unique_ptr<mojo::MessageReceiverWithStatus> responder) { {%- if interface.methods %} switch (message->header()->name) { {%- for method in interface.methods %} @@ -350,7 +348,8 @@ {{class_name}}::{{method.name}}Callback callback = {{class_name}}_{{method.name}}_ProxyToResponder::CreateCallback( message->request_id(), - message->has_flag(mojo::Message::kFlagIsSync), responder); + message->has_flag(mojo::Message::kFlagIsSync), + std::move(responder)); // A null |impl| means no implementation was bound. assert(impl); TRACE_EVENT0("mojom", "{{class_name}}::{{method.name}}");
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl index 9f01348..79ab46f 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl
@@ -1,9 +1,10 @@ class {{export_attribute}} {{interface.name}}StubDispatch { public: static bool Accept({{interface.name}}* impl, mojo::Message* message); - static bool AcceptWithResponder({{interface.name}}* impl, - mojo::Message* message, - mojo::MessageReceiverWithStatus* responder); + static bool AcceptWithResponder( + {{interface.name}}* impl, + mojo::Message* message, + std::unique_ptr<mojo::MessageReceiverWithStatus> responder); }; template <typename ImplRefTraits = @@ -28,11 +29,11 @@ bool AcceptWithResponder( mojo::Message* message, - mojo::MessageReceiverWithStatus* responder) override { + std::unique_ptr<mojo::MessageReceiverWithStatus> responder) override { if (ImplRefTraits::IsNull(sink_)) return false; return {{interface.name}}StubDispatch::AcceptWithResponder( - ImplRefTraits::GetRawPointer(&sink_), message, responder); + ImplRefTraits::GetRawPointer(&sink_), message, std::move(responder)); } private:
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index acdad5e..804a46b 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -40,6 +40,7 @@ #include <utility> #include "base/callback.h" +#include "base/macros.h" #include "base/optional.h" #include "mojo/public/cpp/bindings/associated_interface_ptr.h" #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
diff --git a/services/shape_detection/DEPS b/services/shape_detection/DEPS index a2872a2..1987787 100644 --- a/services/shape_detection/DEPS +++ b/services/shape_detection/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+media/capture/video/scoped_result_callback.h", + "+skia/ext/skia_utils_mac.h", "+third_party/skia/include", "+ui/gfx/codec", "+ui/gl/gl_switches.h"
diff --git a/services/shape_detection/barcode_detection_impl_mac.h b/services/shape_detection/barcode_detection_impl_mac.h index a7779897..6a5609a 100644 --- a/services/shape_detection/barcode_detection_impl_mac.h +++ b/services/shape_detection/barcode_detection_impl_mac.h
@@ -7,6 +7,7 @@ #include "base/mac/scoped_nsobject.h" #include "services/shape_detection/public/interfaces/barcodedetection.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" @class CIDetector; @@ -18,9 +19,7 @@ BarcodeDetectionImplMac(); ~BarcodeDetectionImplMac() override; - void Detect(mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height, + void Detect(const SkBitmap& bitmap, const shape_detection::mojom::BarcodeDetection::DetectCallback& callback) override;
diff --git a/services/shape_detection/barcode_detection_impl_mac.mm b/services/shape_detection/barcode_detection_impl_mac.mm index ec0ac0b..2abbc03 100644 --- a/services/shape_detection/barcode_detection_impl_mac.mm +++ b/services/shape_detection/barcode_detection_impl_mac.mm
@@ -50,22 +50,20 @@ BarcodeDetectionImplMac::~BarcodeDetectionImplMac() {} -void BarcodeDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height, +void BarcodeDetectionImplMac::Detect(const SkBitmap& bitmap, const DetectCallback& callback) { media::ScopedResultCallback<DetectCallback> scoped_callback( base::Bind(&RunCallbackWithBarcodes, callback), base::Bind(&RunCallbackWithNoBarcodes)); - base::scoped_nsobject<CIImage> ci_image = - CreateCIImageFromSharedMemory(std::move(frame_data), width, height); + base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); if (!ci_image) return; NSArray* const features = [detector_ featuresInImage:ci_image]; std::vector<mojom::BarcodeDetectionResultPtr> results; + const int height = bitmap.height(); for (CIQRCodeFeature* const f in features) { shape_detection::mojom::BarcodeDetectionResultPtr result = shape_detection::mojom::BarcodeDetectionResult::New();
diff --git a/services/shape_detection/barcode_detection_impl_mac_unittest.mm b/services/shape_detection/barcode_detection_impl_mac_unittest.mm index 55c2cd27..d3c305c 100644 --- a/services/shape_detection/barcode_detection_impl_mac_unittest.mm +++ b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
@@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/utils/mac/SkCGUtils.h" #include "ui/gl/gl_switches.h" namespace shape_detection { @@ -64,7 +65,6 @@ const gfx::Size size([qr_code_image extent].size.width, [qr_code_image extent].size.height); - const int num_bytes = size.GetArea() * 4 /* bytes per pixel */; base::scoped_nsobject<CIContext> context([[CIContext alloc] init]); @@ -73,30 +73,16 @@ EXPECT_EQ(static_cast<size_t>(size.width()), CGImageGetWidth(cg_image)); EXPECT_EQ(static_cast<size_t>(size.height()), CGImageGetHeight(cg_image)); - base::ScopedCFTypeRef<CFDataRef> raw_cg_image_data( - CGDataProviderCopyData(CGImageGetDataProvider(cg_image))); - EXPECT_TRUE(CFDataGetBytePtr(raw_cg_image_data)); - EXPECT_EQ(num_bytes, CFDataGetLength(raw_cg_image_data)); - - // Generate a new ScopedSharedBufferHandle of the aproppriate size, map it and - // copy the generated qr code image pixels into it. - mojo::ScopedSharedBufferHandle handle = - mojo::SharedBufferHandle::Create(num_bytes); - ASSERT_TRUE(handle->is_valid()); - - mojo::ScopedSharedBufferMapping mapping = handle->Map(num_bytes); - ASSERT_TRUE(mapping); - - memcpy(mapping.get(), CFDataGetBytePtr(raw_cg_image_data), num_bytes); + SkBitmap bitmap; + ASSERT_TRUE(SkCreateBitmapFromCGImage(&bitmap, cg_image)); base::RunLoop run_loop; base::Closure quit_closure = run_loop.QuitClosure(); // Send the image Detect() and expect the response in callback. EXPECT_CALL(*this, Detection(1, kInfoString)) .WillOnce(RunClosure(quit_closure)); - impl_.Detect(std::move(handle), size.width(), size.height(), - base::Bind(&BarcodeDetectionImplMacTest::DetectCallback, - base::Unretained(this))); + impl_.Detect(bitmap, base::Bind(&BarcodeDetectionImplMacTest::DetectCallback, + base::Unretained(this))); run_loop.Run(); }
diff --git a/services/shape_detection/detection_utils_mac.h b/services/shape_detection/detection_utils_mac.h index 98e3c0f..69e46426 100644 --- a/services/shape_detection/detection_utils_mac.h +++ b/services/shape_detection/detection_utils_mac.h
@@ -9,15 +9,14 @@ #include "base/mac/scoped_nsobject.h" #include "services/shape_detection/public/interfaces/barcodedetection.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace shape_detection { // Takes a ScopedSharedBufferHandle with dimensions and produces a new CIImage // with the same contents, or a null scoped_nsobject is something goes wrong. -base::scoped_nsobject<CIImage> CreateCIImageFromSharedMemory( - mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height); +base::scoped_nsobject<CIImage> CreateCIImageFromSkBitmap( + const SkBitmap& bitmap); } // namespace shape_detection
diff --git a/services/shape_detection/detection_utils_mac.mm b/services/shape_detection/detection_utils_mac.mm index 4e87812e99..554cd7e5 100644 --- a/services/shape_detection/detection_utils_mac.mm +++ b/services/shape_detection/detection_utils_mac.mm
@@ -9,61 +9,31 @@ #include "base/memory/shared_memory.h" #include "mojo/public/cpp/system/platform_handle.h" #include "services/shape_detection/barcode_detection_impl.h" +#include "skia/ext/skia_utils_mac.h" +#include "third_party/skia/include/utils/mac/SkCGUtils.h" namespace shape_detection { -// These formats are available but not public until Mac 10.11. -#if !defined(MAC_OS_X_VERSION_10_11) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11 -const int kCIFormatRGBA8 = 24; -#else -//static_assert(kCIFormatRGBA8 == 24, "RGBA8 format enum index."); -#endif - -base::scoped_nsobject<CIImage> CreateCIImageFromSharedMemory( - mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height) { +base::scoped_nsobject<CIImage> CreateCIImageFromSkBitmap( + const SkBitmap& bitmap) { base::CheckedNumeric<uint32_t> num_pixels = - base::CheckedNumeric<uint32_t>(width) * height; + base::CheckedNumeric<uint32_t>(bitmap.width()) * bitmap.height(); base::CheckedNumeric<uint32_t> num_bytes = num_pixels * 4; if (!num_bytes.IsValid()) { DLOG(ERROR) << "Data overflow"; return base::scoped_nsobject<CIImage>(); } - base::SharedMemoryHandle memory_handle; - size_t memory_size = 0; - bool read_only_flag = false; - const MojoResult result = mojo::UnwrapSharedMemoryHandle( - std::move(frame_data), &memory_handle, &memory_size, &read_only_flag); - DCHECK_EQ(MOJO_RESULT_OK, result) << "Failed to unwrap SharedBufferHandle"; - if (!memory_size || memory_size != num_bytes.ValueOrDie()) { - DLOG(ERROR) << "Invalid image size"; + // First convert SkBitmap to CGImageRef. + base::ScopedCFTypeRef<CGImageRef> cg_image( + SkCreateCGImageRefWithColorspace(bitmap, NULL)); + if (!cg_image) { + DLOG(ERROR) << "Failed to create CGImageRef"; return base::scoped_nsobject<CIImage>(); } - auto shared_memory = - base::MakeUnique<base::SharedMemory>(memory_handle, true /* read_only */); - if (!shared_memory->Map(memory_size)) { - DLOG(ERROR) << "Failed to map bytes from shared memory"; - return base::scoped_nsobject<CIImage>(); - } - - NSData* byte_data = [NSData dataWithBytesNoCopy:shared_memory->memory() - length:num_bytes.ValueOrDie() - freeWhenDone:NO]; - - base::ScopedCFTypeRef<CGColorSpaceRef> colorspace( - CGColorSpaceCreateWithName(kCGColorSpaceSRGB)); - - // CIImage will return nil if RGBA8 is not supported in a certain version. - base::scoped_nsobject<CIImage> ci_image([[CIImage alloc] - initWithBitmapData:byte_data - bytesPerRow:width * 4 - size:CGSizeMake(width, height) - format:kCIFormatRGBA8 - colorSpace:colorspace]); + base::scoped_nsobject<CIImage> ci_image( + [[CIImage alloc] initWithCGImage:cg_image]); if (!ci_image) { DLOG(ERROR) << "Failed to create CIImage"; return base::scoped_nsobject<CIImage>();
diff --git a/services/shape_detection/face_detection_impl_mac.h b/services/shape_detection/face_detection_impl_mac.h index fb978c7..459ffa7 100644 --- a/services/shape_detection/face_detection_impl_mac.h +++ b/services/shape_detection/face_detection_impl_mac.h
@@ -7,6 +7,7 @@ #include "base/mac/scoped_nsobject.h" #include "services/shape_detection/public/interfaces/facedetection.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" @class CIDetector; @@ -18,9 +19,7 @@ shape_detection::mojom::FaceDetectorOptionsPtr options); ~FaceDetectionImplMac() override; - void Detect(mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height, + void Detect(const SkBitmap& bitmap, const shape_detection::mojom::FaceDetection::DetectCallback& callback) override;
diff --git a/services/shape_detection/face_detection_impl_mac.mm b/services/shape_detection/face_detection_impl_mac.mm index 151e0a7c..8bece619 100644 --- a/services/shape_detection/face_detection_impl_mac.mm +++ b/services/shape_detection/face_detection_impl_mac.mm
@@ -47,21 +47,19 @@ FaceDetectionImplMac::~FaceDetectionImplMac() {} -void FaceDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height, +void FaceDetectionImplMac::Detect(const SkBitmap& bitmap, const DetectCallback& callback) { media::ScopedResultCallback<DetectCallback> scoped_callback( base::Bind(&RunCallbackWithFaces, callback), base::Bind(&RunCallbackWithNoFaces)); - base::scoped_nsobject<CIImage> ci_image = - CreateCIImageFromSharedMemory(std::move(frame_data), width, height); + base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); if (!ci_image) return; NSArray* const features = [detector_ featuresInImage:ci_image]; + const int height = bitmap.height(); shape_detection::mojom::FaceDetectionResultPtr faces = shape_detection::mojom::FaceDetectionResult::New(); for (CIFaceFeature* const f in features) {
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm index e07f700f..9b9c569 100644 --- a/services/shape_detection/face_detection_impl_mac_unittest.mm +++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -76,24 +76,12 @@ const int num_bytes = size.GetArea() * 4 /* bytes per pixel */; ASSERT_EQ(num_bytes, image->computeSize64()); - // Generate a new ScopedSharedBufferHandle of the aproppriate size, map it and - // copy the image pixels into it. - mojo::ScopedSharedBufferHandle handle = - mojo::SharedBufferHandle::Create(num_bytes); - ASSERT_TRUE(handle->is_valid()); - - mojo::ScopedSharedBufferMapping mapping = handle->Map(num_bytes); - ASSERT_TRUE(mapping); - - memcpy(mapping.get(), image->getPixels(), num_bytes); - base::RunLoop run_loop; base::Closure quit_closure = run_loop.QuitClosure(); // Send the image to Detect() and expect the response in callback. EXPECT_CALL(*this, Detection(1)).WillOnce(RunClosure(quit_closure)); - impl_->Detect(std::move(handle), size.width(), size.height(), - base::Bind(&FaceDetectionImplMacTest::DetectCallback, - base::Unretained(this))); + impl_->Detect(*image, base::Bind(&FaceDetectionImplMacTest::DetectCallback, + base::Unretained(this))); run_loop.Run(); }
diff --git a/services/shape_detection/public/interfaces/BUILD.gn b/services/shape_detection/public/interfaces/BUILD.gn index 953742864..44522415 100644 --- a/services/shape_detection/public/interfaces/BUILD.gn +++ b/services/shape_detection/public/interfaces/BUILD.gn
@@ -14,6 +14,7 @@ ] public_deps = [ + "//skia/public/interfaces", "//ui/gfx/geometry/mojo", ] }
diff --git a/services/shape_detection/public/interfaces/barcodedetection.mojom b/services/shape_detection/public/interfaces/barcodedetection.mojom index 27f95ecd..5ae9aef5 100644 --- a/services/shape_detection/public/interfaces/barcodedetection.mojom +++ b/services/shape_detection/public/interfaces/barcodedetection.mojom
@@ -6,6 +6,7 @@ module shape_detection.mojom; +import "skia/public/interfaces/bitmap.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; struct BarcodeDetectionResult { @@ -17,9 +18,7 @@ }; interface BarcodeDetection { - // |frame_data| contains tightly packed image pixels in ARGB32 format, - // row-major order. - // TODO(mcasas): Consider using mojo::Bitmap here, https://crbug.com/665488. - Detect(handle<shared_buffer> frame_data, uint32 width, uint32 height) + // |bitmap_data| contains tightly packed image pixels in row-major order. + Detect(skia.mojom.Bitmap bitmap_data) => (array<BarcodeDetectionResult> results); };
diff --git a/services/shape_detection/public/interfaces/facedetection.mojom b/services/shape_detection/public/interfaces/facedetection.mojom index 38102f8..0ee1390 100644 --- a/services/shape_detection/public/interfaces/facedetection.mojom +++ b/services/shape_detection/public/interfaces/facedetection.mojom
@@ -6,6 +6,7 @@ module shape_detection.mojom; +import "skia/public/interfaces/bitmap.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; // Since "//ui/gfx/geometry/mojo" is not exposed to blink, we need to declare @@ -21,9 +22,7 @@ }; interface FaceDetection { - // |frame_data| contains tightly packed image pixels in ARGB32 format, - // row-major order. - // TODO(mcasas): Consider using mojo::Bitmap here, https://crbug.com/665488. - Detect(handle<shared_buffer> frame_data, uint32 width, uint32 height) + // |bitmap_data| contains tightly packed image pixels in row-major order. + Detect(skia.mojom.Bitmap bitmap_data) => (FaceDetectionResult result); };
diff --git a/services/shape_detection/public/interfaces/textdetection.mojom b/services/shape_detection/public/interfaces/textdetection.mojom index 6e8bb01..7a0fed5 100644 --- a/services/shape_detection/public/interfaces/textdetection.mojom +++ b/services/shape_detection/public/interfaces/textdetection.mojom
@@ -4,6 +4,7 @@ module shape_detection.mojom; +import "skia/public/interfaces/bitmap.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; struct TextDetectionResult { @@ -12,8 +13,7 @@ }; interface TextDetection { - // |frame_data| contains tightly packed image pixels in ARGB32 format, - // row-major order. - Detect(handle<shared_buffer> frame_data, uint32 width, uint32 height) + // |bitmap_data| contains tightly packed image pixels in row-major order. + Detect(skia.mojom.Bitmap bitmap_data) => (array<TextDetectionResult> results); };
diff --git a/services/shape_detection/text_detection_impl_mac.h b/services/shape_detection/text_detection_impl_mac.h index d86be927..738d8da 100644 --- a/services/shape_detection/text_detection_impl_mac.h +++ b/services/shape_detection/text_detection_impl_mac.h
@@ -17,9 +17,7 @@ TextDetectionImplMac(); ~TextDetectionImplMac() override; - void Detect(mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height, + void Detect(const SkBitmap& bitmap, const mojom::TextDetection::DetectCallback& callback) override; private:
diff --git a/services/shape_detection/text_detection_impl_mac.mm b/services/shape_detection/text_detection_impl_mac.mm index 3894770a..45d8d46 100644 --- a/services/shape_detection/text_detection_impl_mac.mm +++ b/services/shape_detection/text_detection_impl_mac.mm
@@ -48,22 +48,20 @@ TextDetectionImplMac::~TextDetectionImplMac() {} -void TextDetectionImplMac::Detect(mojo::ScopedSharedBufferHandle frame_data, - uint32_t width, - uint32_t height, +void TextDetectionImplMac::Detect(const SkBitmap& bitmap, const DetectCallback& callback) { DCHECK(base::mac::IsAtLeastOS10_11()); media::ScopedResultCallback<DetectCallback> scoped_callback( base::Bind(&RunCallbackWithResults, callback), base::Bind(&RunCallbackWithNoResults)); - base::scoped_nsobject<CIImage> ci_image = - CreateCIImageFromSharedMemory(std::move(frame_data), width, height); + base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); if (!ci_image) return; NSArray* const features = [detector_ featuresInImage:ci_image]; + const int height = bitmap.height(); std::vector<mojom::TextDetectionResultPtr> results; for (CIRectangleFeature* const f in features) { // CIRectangleFeature only has bounding box information.
diff --git a/services/shape_detection/text_detection_impl_mac_unittest.mm b/services/shape_detection/text_detection_impl_mac_unittest.mm index 5333a51..7b27fe0 100644 --- a/services/shape_detection/text_detection_impl_mac_unittest.mm +++ b/services/shape_detection/text_detection_impl_mac_unittest.mm
@@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/utils/mac/SkCGUtils.h" #include "ui/gl/gl_switches.h" namespace shape_detection { @@ -81,29 +82,15 @@ EXPECT_EQ(static_cast<size_t>(width), CGImageGetWidth(cg_image)); EXPECT_EQ(static_cast<size_t>(height), CGImageGetHeight(cg_image)); - base::ScopedCFTypeRef<CFDataRef> raw_cg_image_data( - CGDataProviderCopyData(CGImageGetDataProvider(cg_image))); - EXPECT_TRUE(CFDataGetBytePtr(raw_cg_image_data)); - const int num_bytes = width * height * 4; - EXPECT_EQ(num_bytes, CFDataGetLength(raw_cg_image_data)); - - // Generate a new ScopedSharedBufferHandle of the aproppriate size, map it and - // copy the generated text image pixels into it. - auto handle = mojo::SharedBufferHandle::Create(num_bytes); - ASSERT_TRUE(handle->is_valid()); - - mojo::ScopedSharedBufferMapping mapping = handle->Map(num_bytes); - ASSERT_TRUE(mapping); - - memcpy(mapping.get(), CFDataGetBytePtr(raw_cg_image_data), num_bytes); + SkBitmap bitmap; + ASSERT_TRUE(SkCreateBitmapFromCGImage(&bitmap, cg_image)); base::RunLoop run_loop; base::Closure quit_closure = run_loop.QuitClosure(); // Send the image to Detect() and expect the response in callback. EXPECT_CALL(*this, Detection(1)).WillOnce(RunClosure(quit_closure)); - impl_.Detect(std::move(handle), width, height, - base::Bind(&TextDetectionImplMacTest::DetectCallback, - base::Unretained(this))); + impl_.Detect(bitmap, base::Bind(&TextDetectionImplMacTest::DetectCallback, + base::Unretained(this))); run_loop.Run(); }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 673bc0f..30934a5 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1402,6 +1402,20 @@ crbug.com/700795 [ Mac ] inspector/animation/animation-transition-setTiming-crash.html [ Timeout Pass ] +crbug.com/701500 inspector-protocol/debugger/debugger-doesnt-step-into-injected-script.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-pause/pause-on-elements-panel.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-into-across-timeouts.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-into-document-write.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-out-across-timeouts.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-out-document-write.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-out-event-listener.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-over-across-timeouts.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-over-document-write.html [ NeedsManualRebaseline ] +crbug.com/701500 inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html [ NeedsManualRebaseline ] + # Flaky on Win10 and Win7 crbug.com/619539 [ Win ] http/tests/workers/terminate-during-sync-operation-file.html [ Pass Timeout ] crbug.com/619539 [ Win ] virtual/mojo-loading/http/tests/workers/terminate-during-sync-operation-file.html [ Pass Timeout ] @@ -2651,7 +2665,7 @@ crbug.com/698521 external/wpt/preload/preload-with-type.html [ Failure Pass ] # Sheriff failures 2017-03-10 -crbug.com/402805 [ Mac10.10 Mac10.11 Mac10.12 Win10 ] inspector-protocol/input/emulateTouchFromMouseEvent.html [ Timeout ] +crbug.com/402805 [ Mac10.10 Mac10.11 Mac10.12 Win7 Win10 ] inspector-protocol/input/emulateTouchFromMouseEvent.html [ Timeout ] crbug.com/700374 [ Win ] virtual/mojo-loading/http/tests/inspector/workers-on-navigation.html [ Failure Pass ] crbug.com/700374 [ Win ] http/tests/inspector/workers-on-navigation.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/animations/interpolation/border-interpolation.html b/third_party/WebKit/LayoutTests/animations/interpolation/border-interpolation.html new file mode 100644 index 0000000..832b8101 --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/interpolation/border-interpolation.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<style> +.target { + width: 10px; + height: 10px; + background-color: black; +} +.expected { + background-color: green; +} +</style> +<body> +<script src="resources/interpolation-test.js"></script> +<script> + +assertInterpolation({ + property: 'border', + from: '10px solid #000', + to: '20px dashed #000', + method: 'CSS Transitions', +}, [ + {at: -0.3, is: '7px dashed #000'}, + {at: 0, is: '10px dashed #000'}, + {at: 0.3, is: '13px dashed #000'}, + {at: 0.6, is: '16px dashed #000'}, + {at: 1, is: '20px dashed #000'}, + {at: 1.5, is: '25px dashed #000'}, +]); + +assertInterpolation({ + property: 'border', + from: '10px solid #000', + to: '20px dashed #000', + method: 'CSS Animations', +}, [ + {at: -0.3, is: '7px solid #000'}, + {at: 0, is: '10px solid #000'}, + {at: 0.3, is: '13px solid #000'}, + {at: 0.6, is: '16px dashed #000'}, + {at: 1, is: '20px dashed #000'}, + {at: 1.5, is: '25px dashed #000'}, +]); + +assertInterpolation({ + property: 'border', + from: '10px solid #000', + to: '20px dashed #000', + method: 'Web Animations', +}, [ + {at: -0.3, is: '7px solid #000'}, + {at: 0, is: '10px solid #000'}, + {at: 0.3, is: '13px solid #000'}, + {at: 0.6, is: '16px dashed #000'}, + {at: 1, is: '20px dashed #000'}, + {at: 1.5, is: '25px dashed #000'}, +]); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/animations/interpolation/offset-interpolation.html b/third_party/WebKit/LayoutTests/animations/interpolation/offset-interpolation.html new file mode 100644 index 0000000..7bdcdcfe --- /dev/null +++ b/third_party/WebKit/LayoutTests/animations/interpolation/offset-interpolation.html
@@ -0,0 +1,102 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<style> +.target { + width: 10px; + height: 10px; + background-color: black; +} +.expected { + background-color: green; +} +</style> +<body> +<script src="resources/interpolation-test.js"></script> +<script> + +assertInterpolation({ + property: 'offset', + from: 'path("M0 200H 700") 500px 800deg', + to: 'path("M0 300H 700 Z") 600px 900deg', + method: 'CSS Transitions', +}, [ + {at: -0.3, is: 'path("M0 300H 700 Z") 470px 770deg'}, + {at: 0, is: 'path("M0 300H 700 Z") 500px 800deg'}, + {at: 0.3, is: 'path("M0 300H 700 Z") 530px 830deg'}, + {at: 0.6, is: 'path("M0 300H 700 Z") 560px 860deg'}, + {at: 1, is: 'path("M0 300H 700 Z") 600px 900deg'}, + {at: 1.5, is: 'path("M0 300H 700 Z") 650px 950deg'}, +]); + +assertInterpolation({ + property: 'offset', + from: 'path("M0 0H 200") 500px auto', + to: 'path("M0 0H 300") 600px 0deg', + method: 'CSS Transitions', +}, [ + {at: -0.3, is: 'path("M0 0H 300") 470px 0deg'}, + {at: 0, is: 'path("M0 0H 300") 500px 0deg'}, + {at: 0.3, is: 'path("M0 0H 300") 530px 0deg'}, + {at: 0.6, is: 'path("M0 0H 300") 560px 0deg'}, + {at: 1, is: 'path("M0 0H 300") 600px 0deg'}, + {at: 1.5, is: 'path("M0 0H 300") 650px 0deg'}, +]); + +assertInterpolation({ + property: 'offset', + from: 'path("M0 200H 700") 500px 800deg', + to: 'path("M0 300H 700 Z") 600px 900deg', + method: 'CSS Animations', +}, [ + {at: -0.3, is: 'path("M0 200H 700") 470px 770deg'}, + {at: 0, is: 'path("M0 200H 700") 500px 800deg'}, + {at: 0.3, is: 'path("M0 200H 700") 530px 830deg'}, + {at: 0.6, is: 'path("M0 300H 700 Z") 560px 860deg'}, + {at: 1, is: 'path("M0 300H 700 Z") 600px 900deg'}, + {at: 1.5, is: 'path("M0 300H 700 Z") 650px 950deg'}, +]); + +assertInterpolation({ + property: 'offset', + from: 'path("M0 0H 200") 500px auto', + to: 'path("M0 0H 300") 600px 0deg', + method: 'CSS Animations', +}, [ + {at: -0.3, is: 'path("M0 0H 200") 470px auto'}, + {at: 0, is: 'path("M0 0H 200") 500px auto'}, + {at: 0.3, is: 'path("M0 0H 200") 530px auto'}, + {at: 0.6, is: 'path("M0 0H 300") 560px 0deg'}, + {at: 1, is: 'path("M0 0H 300") 600px 0deg'}, + {at: 1.5, is: 'path("M0 0H 300") 650px 0deg'}, +]); + +assertInterpolation({ + property: 'offset', + from: 'path("M0 200H 700") 500px 800deg', + to: 'path("M0 300H 700 Z") 600px 900deg', + method: 'Web Animations', +}, [ + {at: -0.3, is: 'path("M0 200H 700") 470px 770deg'}, + {at: 0, is: 'path("M0 200H 700") 500px 800deg'}, + {at: 0.3, is: 'path("M0 200H 700") 530px 830deg'}, + {at: 0.6, is: 'path("M0 300H 700 Z") 560px 860deg'}, + {at: 1, is: 'path("M0 300H 700 Z") 600px 900deg'}, + {at: 1.5, is: 'path("M0 300H 700 Z") 650px 950deg'}, +]); + +assertInterpolation({ + property: 'offset', + from: 'path("M0 0H 200") 500px auto', + to: 'path("M0 0H 300") 600px 0deg', + method: 'Web Animations', +}, [ + {at: -0.3, is: 'path("M0 0H 200") 470px auto'}, + {at: 0, is: 'path("M0 0H 200") 500px auto'}, + {at: 0.3, is: 'path("M0 0H 200") 530px auto'}, + {at: 0.6, is: 'path("M0 0H 300") 560px 0deg'}, + {at: 1, is: 'path("M0 0H 300") 600px 0deg'}, + {at: 1.5, is: 'path("M0 0H 300") 650px 0deg'}, +]); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/animations/interpolation/resources/interpolation-test.js b/third_party/WebKit/LayoutTests/animations/interpolation/resources/interpolation-test.js index 4539a679..07b0853 100644 --- a/third_party/WebKit/LayoutTests/animations/interpolation/resources/interpolation-test.js +++ b/third_party/WebKit/LayoutTests/animations/interpolation/resources/interpolation-test.js
@@ -136,6 +136,8 @@ property = property.substring(0, i) + property[i + 1].toUpperCase() + property.substring(i + 2); } } + if (property === 'offset') + property = 'cssOffset'; } var keyframes = []; if (!isNeutralKeyframe(from)) {
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt index eab57bfa..204ea45c 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-doesnt-step-into-injected-script-expected.txt
@@ -14,6 +14,6 @@ Perform stepInto Stack trace: -foo:5:12 +foo:7:4
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-img-tooltip.html b/third_party/WebKit/LayoutTests/inspector/elements/elements-img-tooltip.html index 0385d0e..4929505 100644 --- a/third_party/WebKit/LayoutTests/inspector/elements/elements-img-tooltip.html +++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-img-tooltip.html
@@ -13,7 +13,7 @@ function step1(node) { - InspectorTest.firstElementsTreeOutline()._loadDimensionsForNode(node, step2); + InspectorTest.firstElementsTreeOutline()._loadDimensionsForNode(node).then(step2); } function step2(dimensions)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt index 75f29638..d01eacb 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout-expected.txt
@@ -19,7 +19,7 @@ Executing StepInto... Call stack: - 0) callback (frameworks-step-into-skips-setTimeout.html:15) + 0) callback (frameworks-step-into-skips-setTimeout.html:17) * 1) Framework_scheduleUntilDone (framework.js:142)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/pause-on-elements-panel-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/pause-on-elements-panel-expected.txt index 07e2d01..f203eda 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/pause-on-elements-panel-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-pause/pause-on-elements-panel-expected.txt
@@ -1,6 +1,6 @@ Tests that debugger pause button works on Elements panel after a DOM node highlighting. Chromium bug 433366 Call stack: - 0) callback (pause-on-elements-panel.html:8) + 0) callback (pause-on-elements-panel.html:10) PASS: Debugger paused.
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-across-timeouts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-across-timeouts-expected.txt index 04eab25..0e1c66e0 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-across-timeouts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-across-timeouts-expected.txt
@@ -7,6 +7,6 @@ Executing StepInto... Executing StepInto... Call stack: - 0) callback2 (debugger-step-into-across-timeouts.html:18) + 0) callback2 (debugger-step-into-across-timeouts.html:20)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write-expected.txt index d578283..241a77e 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write-expected.txt
@@ -6,11 +6,6 @@ Executing StepInto... Call stack: - 0) (:1) - 1) (debugger-step-into-document-write.html:4) - -Executing StepInto... -Call stack: 0) (:5) 1) (debugger-step-into-document-write.html:4) @@ -37,7 +32,7 @@ Executing StepInto... Call stack: - 0) (debugger-step-into-document-write.html:7) + 0) (debugger-step-into-document-write.html:8) Executing StepInto... Call stack:
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write.html index 180b9ad..08e42ab 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-document-write.html
@@ -15,7 +15,7 @@ function test() { - var numberOfStepInto = 8; + var numberOfStepInto = 7; InspectorTest.startDebuggerTest(step1, true);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt index 2e14f2d..8dc8ec8 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts-expected.txt
@@ -16,10 +16,6 @@ Executing StepInto... Call stack: - 0) (debugger-step-into-inlined-scripts.html:12) - -Executing StepInto... -Call stack: 0) (debugger-step-into-inlined-scripts.html:17) Executing StepInto...
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html index 1a09a42..fae7e5f 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-into-inlined-scripts.html
@@ -24,7 +24,7 @@ function test() { - var numberOfStepInto = 7; + var numberOfStepInto = 6; InspectorTest.startDebuggerTest(step1, true);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-across-timeouts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-across-timeouts-expected.txt index 307c071..3e085c1 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-across-timeouts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-across-timeouts-expected.txt
@@ -6,6 +6,6 @@ Executing StepOut... Call stack: - 0) callback2 (debugger-step-out-across-timeouts.html:19) + 0) callback2 (debugger-step-out-across-timeouts.html:21)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks-expected.txt index c87abf4..262f431 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks-expected.txt
@@ -14,7 +14,6 @@ 0) testFunction (debugger-step-out-custom-element-callbacks.html:29) Executing StepInto... -Executing StepInto... Call stack: 0) attributeChangedCallback (debugger-step-out-custom-element-callbacks.html:25) 1) testFunction (debugger-step-out-custom-element-callbacks.html:29) @@ -24,7 +23,6 @@ 0) testFunction (debugger-step-out-custom-element-callbacks.html:30) Executing StepInto... -Executing StepInto... Call stack: 0) attachedCallback (debugger-step-out-custom-element-callbacks.html:17) 1) testFunction (debugger-step-out-custom-element-callbacks.html:30) @@ -34,7 +32,6 @@ 0) testFunction (debugger-step-out-custom-element-callbacks.html:31) Executing StepInto... -Executing StepInto... Call stack: 0) detachedCallback (debugger-step-out-custom-element-callbacks.html:21) 1) testFunction (debugger-step-out-custom-element-callbacks.html:31)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks.html index e4363b8f8..56d73a5 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-custom-element-callbacks.html
@@ -45,11 +45,11 @@ var actions = [ "Print", // debugger; in createdCallback "StepOut", "Print", // at foo.setAttribute() - "StepInto", "StepInto", "Print", // at attributeChangedCallback + "StepInto", "Print", // at attributeChangedCallback "StepOut", "Print", // at document.body.appendChild() - "StepInto", "StepInto", "Print", // at attachedCallback + "StepInto", "Print", // at attachedCallback "StepOut", "Print", // at foo.remove() - "StepInto", "StepInto", "Print", // at detachedCallback + "StepInto", "Print", // at detachedCallback "StepOut", "Print", // at testFunction() return point ]; InspectorTest.waitUntilPausedAndPerformSteppingActions(actions, step3);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-document-write-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-document-write-expected.txt index 0e1177d..466abc6 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-document-write-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-document-write-expected.txt
@@ -6,11 +6,11 @@ Executing StepOut... Call stack: - 0) (debugger-step-out-document-write.html:9) + 0) (debugger-step-out-document-write.html:10) Executing StepOut... Call stack: - 0) (debugger-step-out-document-write.html:12) + 0) (debugger-step-out-document-write.html:18) Executing StepOut... Call stack: @@ -23,7 +23,7 @@ Executing StepOut... Call stack: - 0) (debugger-step-out-document-write.html:20) + 0) (debugger-step-out-document-write.html:21) Executing Resume... Page reloaded.
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-event-listener-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-event-listener-expected.txt index 60ba0b7..9def0dfa 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-event-listener-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-out-event-listener-expected.txt
@@ -10,13 +10,13 @@ Executing StepInto... Executing StepInto... Call stack: - 0) fooEventHandler1 (debugger-step-out-event-listener.html:14) + 0) fooEventHandler1 (debugger-step-out-event-listener.html:15) 1) inner (debugger-step-out-event-listener.html:27) 2) testFunction (debugger-step-out-event-listener.html:32) Executing StepOut... Call stack: - 0) fooEventHandler2 (debugger-step-out-event-listener.html:17) + 0) fooEventHandler2 (debugger-step-out-event-listener.html:19) 1) inner (debugger-step-out-event-listener.html:27) 2) testFunction (debugger-step-out-event-listener.html:32)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-across-timeouts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-across-timeouts-expected.txt index fb0d1210..f0beb72d 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-across-timeouts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-across-timeouts-expected.txt
@@ -7,6 +7,6 @@ Executing StepOver... Executing StepOver... Call stack: - 0) callback2 (debugger-step-over-across-timeouts.html:18) + 0) callback2 (debugger-step-over-across-timeouts.html:20)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write-expected.txt index b9bc3ce..c700f97 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write-expected.txt
@@ -10,10 +10,6 @@ Executing StepOver... Call stack: - 0) (debugger-step-over-document-write.html:7) - -Executing StepOver... -Call stack: 0) (debugger-step-over-document-write.html:8) Executing StepOver...
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write.html index 05f8a120..4fde2ded 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-document-write.html
@@ -15,7 +15,7 @@ function test() { - var numberOfStepOver = 4; + var numberOfStepOver = 3; InspectorTest.startDebuggerTest(step1, true);
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt index e0ebd50..2a44a8c 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts-expected.txt
@@ -16,10 +16,6 @@ Executing StepOver... Call stack: - 0) (debugger-step-over-inlined-scripts.html:12) - -Executing StepOver... -Call stack: 0) (debugger-step-over-inlined-scripts.html:17) Executing StepOver...
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html index 9afe966..d70debf 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-step/debugger-step-over-inlined-scripts.html
@@ -24,7 +24,7 @@ function test() { - var numberOfStepOver = 5; + var numberOfStepOver = 4; InspectorTest.startDebuggerTest(step1, true);
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js index 1f6a479..129c660ee 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-barcodedetection.js
@@ -18,8 +18,8 @@ handle => this.bindingSet_.addBinding(this, handle)); } - detect(frame_data, width, height) { - let receivedStruct = mojo.mapBuffer(frame_data, 0, width*height*4, 0); + detect(bitmap_data) { + let receivedStruct = new Uint8Array(bitmap_data.pixel_data); this.buffer_data_ = new Uint32Array(receivedStruct.buffer); return Promise.resolve({ results: [ @@ -45,7 +45,6 @@ }, ], }); - mojo.unmapBuffer(receivedStruct.buffer); } getFrameData() {
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js index 1faf89f..c02fda2 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-facedetection.js
@@ -44,8 +44,8 @@ request); } - detect(frame_data, width, height) { - let receivedStruct = mojo.mapBuffer(frame_data, 0, width*height*4, 0); + detect(bitmap_data) { + let receivedStruct = new Uint8Array(bitmap_data.pixel_data); this.buffer_data_ = new Uint32Array(receivedStruct.buffer); return Promise.resolve({ result: { @@ -56,7 +56,6 @@ ] } }); - mojo.unmapBuffer(receivedStruct.buffer); } } return new MockFaceDetectionProvider();
diff --git a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js index 08195c9..a622605 100644 --- a/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js +++ b/third_party/WebKit/LayoutTests/shapedetection/resources/mock-textdetection.js
@@ -17,8 +17,8 @@ handle => this.bindingSet_.addBinding(this, handle)); } - detect(frame_data, width, height) { - let receivedStruct = mojo.mapBuffer(frame_data, 0, width*height*4, 0); + detect(bitmap_data) { + let receivedStruct = new Uint8Array(bitmap_data.pixel_data); this.buffer_data_ = new Uint32Array(receivedStruct.buffer); return Promise.resolve({ results: [ @@ -32,7 +32,6 @@ }, ], }); - mojo.unmapBuffer(receivedStruct.buffer); } getFrameData() {
diff --git a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-custom-sweep-snr.html b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-custom-sweep-snr.html index 12d089bd..9d263d4 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-custom-sweep-snr.html +++ b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-custom-sweep-snr.html
@@ -21,8 +21,9 @@ // The thresholds are experimentally determined. tester.setThresholds({ - snr: 93.450, - maxDiff: 0.00004 + snr: 1000, + maxDiff: 0, + diffCount: 0 }); tester.runTest(context, "custom", "Custom Oscillator with Exponential Sweep", task, should);
diff --git a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sawtooth-sweep-snr.html b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sawtooth-sweep-snr.html index 8d90c61..e0ec7d8 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sawtooth-sweep-snr.html +++ b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sawtooth-sweep-snr.html
@@ -3,7 +3,7 @@ <head> <title>Test Oscillator Node: sawtooth</title> <script src="../../resources/testharness.js"></script> - <script src="../../resources/testharnessreport.js"></script> + <script src="../../resources/testharnessreport.js"></script> <script src="../resources/audit-util.js"></script> <script src="../resources/audit.js"></script> <script src="../resources/buffer-loader.js"></script> @@ -21,11 +21,13 @@ // The thresholds are experimentally determined. tester.setThresholds({ - snr: 92.858, - maxDiff: 0.0001 + snr: 1000, + maxDiff: 0, + diffCount: 0 }); tester.runTest(context, "sawtooth", - "Sawtooth Oscillator with Exponential Sweep", task, should); + "Sawtooth Oscillator with Exponential Sweep", + task, should); }); audit.run();
diff --git a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sine-sweep-snr.html b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sine-sweep-snr.html index e5937b7..d56ea415 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sine-sweep-snr.html +++ b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-sine-sweep-snr.html
@@ -21,11 +21,13 @@ // The thresholds are experimentally determined. tester.setThresholds({ - snr: 94.001, - maxDiff: 0.00006 + snr: 1000, + maxDiff: 0, + diffCount: 0 }); tester.runTest(context, "sine", - "Sine Oscillator with Exponential Sweep", task, should); + "Sine Oscillator with Exponential Sweep", + task, should); }); audit.run();
diff --git a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-square-sweep-snr.html b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-square-sweep-snr.html index 2a3d350..3389a666 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-square-sweep-snr.html +++ b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-square-sweep-snr.html
@@ -21,8 +21,9 @@ // The thresholds are experimentally determined. tester.setThresholds({ - snr: 93.325, - maxDiff: 0.00011 + snr: 1000, + maxDiff: 0, + diffCount: 0 }); tester.runTest(context, "square", "Square Oscillator with Exponential Sweep", task, should);
diff --git a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-triangle-sweep-snr.html b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-triangle-sweep-snr.html index 5d0366d..9728229 100644 --- a/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-triangle-sweep-snr.html +++ b/third_party/WebKit/LayoutTests/webaudio/Oscillator/osc-triangle-sweep-snr.html
@@ -19,10 +19,12 @@ let context = new OfflineAudioContext(1, tester.sampleRate * tester.lengthInSeconds, tester.sampleRate); - // The thresholds are experimentally determined. + // Thresholds for verifying the test passes. The thresholds are + // experimentally determined. tester.setThresholds({ - snr: 93.92, - maxDiff: 0.00005 + snr: 1000, + maxDiff: 0, + diffCount: 0 }); tester.runTest(context, "triangle", "Triangle Oscillator with Exponential Sweep ", task, should);
diff --git a/third_party/WebKit/LayoutTests/webaudio/PeriodicWave/periodicwave-contexts.html b/third_party/WebKit/LayoutTests/webaudio/PeriodicWave/periodicwave-contexts.html index 2144ded4f..9e16ba8e 100644 --- a/third_party/WebKit/LayoutTests/webaudio/PeriodicWave/periodicwave-contexts.html +++ b/third_party/WebKit/LayoutTests/webaudio/PeriodicWave/periodicwave-contexts.html
@@ -33,7 +33,8 @@ // The thresholds are experimentally determined. tester.setThresholds({ snr: 80.00, - maxDiff: 4.06 + maxDiff: 4.06, + diffCount: 15827 }); tester.runTest(context, "sawtooth", "Sawtooth PeriodicWave Test", task, should);
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/audit.js b/third_party/WebKit/LayoutTests/webaudio/resources/audit.js index ae615bdec..bd3051a5 100644 --- a/third_party/WebKit/LayoutTests/webaudio/resources/audit.js +++ b/third_party/WebKit/LayoutTests/webaudio/resources/audit.js
@@ -1191,19 +1191,15 @@ function loadFileFromUrl (fileUrl) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); - xhr.open('GET', fileUrl, true); + xhr.open('GET', fileUrl); xhr.responseType = 'arraybuffer'; xhr.onload = () => { - // |status = 0| is a workaround for the run-webkit-test server. We are - // speculating the server quits the transaction prematurely without - // completing the request. - if (xhr.status === 200 || xhr.status === 0) { + if (xhr.status === 200) { resolve(xhr.response); } else { let errorMessage = 'loadFile: Request failed when loading ' + - fileUrl + '. ' + xhr.statusText + '. (status = ' + - xhr.status + ')'; + fileUrl + '. (' + xhr.statusText + ')'; if (reject) { reject(errorMessage); } else {
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/oscillator-testing.js b/third_party/WebKit/LayoutTests/webaudio/resources/oscillator-testing.js index f2d8f9c..8454386 100644 --- a/third_party/WebKit/LayoutTests/webaudio/resources/oscillator-testing.js +++ b/third_party/WebKit/LayoutTests/webaudio/resources/oscillator-testing.js
@@ -43,6 +43,10 @@ // Max diff must be less than this to pass the test. var thresholdDiff = 0; +// Count the number of differences between the expected and actual result. The tests passes +// if the count is less than this threshold. +var thresholdDiffCount = 0; + // Mostly for debugging // An AudioBuffer for the reference (expected) result. @@ -119,6 +123,11 @@ maxError = Math.abs(diff); errorPosition = k; } + // The reference file is a 16-bit WAV file, so we will almost never get an exact match + // between it and the actual floating-point result. + if (diff > 0) { + diffCount++; + } } var snr = calculateSNR(signalPower, noisePower); @@ -127,6 +136,11 @@ should(maxError, "Maximum difference") .beLessThanOrEqualTo(thresholdDiff); + should(diffCount, + "Number of differences between actual and expected result out of " + + renderedData.length + " frames") + .beLessThanOrEqualTo(thresholdDiffCount); + var filename = "oscillator-" + oscType + "-actual.wav"; if (downloadAudioBuffer(renderedBuffer, filename, true)) should(true, "Saved reference file").message(filename, ""); @@ -147,6 +161,7 @@ lengthInSeconds: lengthInSeconds, thresholdSNR: thresholdSNR, thresholdDiff: thresholdDiff, + thresholdDiffCount: thresholdDiffCount, waveScaleFactor: waveScaleFactor, setThresholds: setThresholds, runTest: runTest,
diff --git a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-expected.txt b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-expected.txt index 2f9ec0b0..bf82aa1 100644 --- a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-expected.txt +++ b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-expected.txt
@@ -33,13 +33,10 @@ PASS Suspending OAC with no argument rejected correctly with TypeError. PASS Start OAC rendering resolved correctly. PASS < [basic] All assertions passed. (total 20 assertions) -PASS > [load-file-in-should] Test Audit.loadFileFromUrl() within |should| assertion. -PASS Loading file within should().beResolved() resolved correctly. -PASS < [load-file-in-should] All assertions passed. (total 1 assertions) PASS > [dummy-label-string] PASS < [dummy-label-string] All assertions passed. (total 0 assertions) PASS > [dummy-label-object] PASS < [dummy-label-object] All assertions passed. (total 0 assertions) -PASS # AUDIT TASK RUNNER FINISHED: 5 tasks ran successfully. +PASS # AUDIT TASK RUNNER FINISHED: 4 tasks ran successfully. Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures-expected.txt b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures-expected.txt index edd8fd8..36ff95f 100644 --- a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures-expected.txt +++ b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures-expected.txt
@@ -90,9 +90,6 @@ [6] 7.0000000000000000e+0 8.0000000000000000e+2 7.9300000000000000e+2 9.9124999999999996e-1 0.0000000000000000e+0 assert_true: expected true got false FAIL < [numerical-failures] 11 out of 11 assertions were failed. assert_true: expected true got false -PASS > [load-file-in-should] Testing the failure handling of Audit.loadFileFromUrl(). -FAIL X Loading non-existent file within should().beResolved() rejected incorrectly with loadFile: Network failure when loading non-existent-audio-file.wav.. Got undefined. assert_true: expected true got false -FAIL < [load-file-in-should] 1 out of 1 assertions were failed. assert_true: expected true got false -FAIL # AUDIT TASK RUNNER FINISHED: 3 out of 3 tasks were failed. assert_true: expected true got false +FAIL # AUDIT TASK RUNNER FINISHED: 2 out of 2 tasks were failed. assert_true: expected true got false Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures.html b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures.html index ccb863a..ea959d5 100644 --- a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures.html +++ b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit-failures.html
@@ -85,20 +85,6 @@ task.done(); }); - // Testing the failure handling of Audit.loadFileFromUrl(). - audit.define({ - label: 'load-file-in-should', - description: 'Testing the failure handling of Audit.loadFileFromUrl().' - }, (task, should) => { - let url = 'non-existent-audio-file.wav'; - let promise = should( - Audit.loadFileFromUrl(url), - 'Loading non-existent file within should().beResolved()') - .beResolved(); - promise.then(() => { task.done() }); - } - ); - // With no argument, this executes all tasks in the order defined. audit.run(); </script>
diff --git a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit.html b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit.html index adb2d785..27bc852 100644 --- a/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit.html +++ b/third_party/WebKit/LayoutTests/webaudio/unit-tests/audit.html
@@ -65,20 +65,6 @@ } ); - // Test Audit.loadFileFromUrl() within |should| assertion. - // See: crbug.com/701813 - audit.define({ - label: 'load-file-in-should', - description: 'Test Audit.loadFileFromUrl() within |should| assertion.' - }, (task, should) => { - let url = '../resources/hyper-reality/laughter.wav'; - let promise = should(Audit.loadFileFromUrl(url), - 'Loading file within should().beResolved()') - .beResolved(); - promise.then(() => { task.done() }); - } - ); - // The task headline needs to be printed even if there is no description is // given. @@ -103,8 +89,7 @@ // You can enumerate tasks you want to execute in the order, or simply pass // no argument to run all the defined tasks. - audit.run('numerical', 'basic', 'load-file-in-should', - 'dummy-label-string', 'dummy-label-object'); + audit.run('numerical', 'basic', 'dummy-label-string', 'dummy-label-object'); </script> </body> </html>
diff --git a/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp b/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp index 5a0a86c..d3a9dca 100644 --- a/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp
@@ -42,6 +42,8 @@ return CSSPropertyInvalid; if (property == "cssFloat") return CSSPropertyFloat; + if (property == "cssOffset") + return CSSPropertyOffset; StringBuilder builder; for (size_t i = 0; i < property.length(); ++i) {
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp index ba85f542..a31d95a1 100644 --- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp +++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
@@ -50,6 +50,12 @@ return networkStateNotifier().connectionType() == WebConnectionTypeCellular2G; } +bool isInterventionV2Enabled() { + return RuntimeEnabledFeatures::webFontsInterventionV2With2GEnabled() || + RuntimeEnabledFeatures::webFontsInterventionV2With3GEnabled() || + RuntimeEnabledFeatures::webFontsInterventionV2WithSlow2GEnabled(); +} + } // namespace RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, @@ -197,20 +203,16 @@ m_histograms.dataSource() == FontLoadHistograms::FromDataURL) return false; - bool isV2Enabled = - RuntimeEnabledFeatures::webFontsInterventionV2With2GEnabled() || - RuntimeEnabledFeatures::webFontsInterventionV2With3GEnabled() || - RuntimeEnabledFeatures::webFontsInterventionV2WithSlow2GEnabled(); - bool networkIsSlow = - isV2Enabled ? isEffectiveConnectionTypeSlowFor(m_fontSelector->document()) - : isConnectionTypeSlow(); + isInterventionV2Enabled() + ? isEffectiveConnectionTypeSlowFor(m_fontSelector->document()) + : isConnectionTypeSlow(); return networkIsSlow && m_display == FontDisplayAuto; } bool RemoteFontFaceSource::isLowPriorityLoadingAllowedForRemoteFont() const { - return m_isInterventionTriggered; + return m_isInterventionTriggered && isInterventionV2Enabled(); } PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp index 2dbafa11..46aacf5 100644 --- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp +++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -788,7 +788,6 @@ child->detachLayoutTree(childrenContext); setChildNeedsStyleRecalc(); - setChildNeedsReattachLayoutTree(); Node::detachLayoutTree(context); } @@ -801,10 +800,6 @@ setChildNeedsStyleRecalc(); markAncestorsWithChildNeedsStyleRecalc(); } - if (!childNeedsReattachLayoutTree()) { - setChildNeedsReattachLayoutTree(); - markAncestorsWithChildNeedsReattachLayoutTree(); - } } }
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 4b13bb38..4ba216f 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -139,7 +139,6 @@ #include "core/frame/DOMVisualViewport.h" #include "core/frame/EventHandlerRegistry.h" #include "core/frame/FrameConsole.h" -#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/History.h" #include "core/frame/HostsUsingFeatures.h" @@ -1661,9 +1660,6 @@ return m_frame ? m_frame->page() : nullptr; } -FrameHost* Document::frameHost() const { - return m_frame ? m_frame->host() : nullptr; -} Settings* Document::settings() const { return m_frame ? m_frame->settings() : nullptr;
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index ea9df469..83ac390 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -108,7 +108,6 @@ class FloatQuad; class FloatRect; class FormController; -class FrameHost; class FrameRequestCallback; class FrameView; class HTMLAllCollection; @@ -471,7 +470,6 @@ FrameView* view() const; // can be null LocalFrame* frame() const { return m_frame; } // can be null - FrameHost* frameHost() const; // can be null Page* page() const; // can be null Settings* settings() const; // can be null
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 8043437..a403176 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -92,7 +92,6 @@ #include "core/editing/serializers/Serialization.h" #include "core/events/EventDispatcher.h" #include "core/events/FocusEvent.h" -#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/HostsUsingFeatures.h" #include "core/frame/LocalDOMWindow.h" @@ -154,11 +153,11 @@ // We need to retain the scroll customization callbacks until the element // they're associated with is destroyed. It would be simplest if the callbacks -// could be stored in ElementRareData, but we can't afford the space -// increase. Instead, keep the scroll customization callbacks here. The other -// option would be to store these callbacks on the FrameHost or document, but -// that necessitates a bunch more logic for transferring the callbacks between -// FrameHosts when elements are moved around. +// could be stored in ElementRareData, but we can't afford the space increase. +// Instead, keep the scroll customization callbacks here. The other option would +// be to store these callbacks on the Page or document, but that necessitates a +// bunch more logic for transferring the callbacks between Pages when elements +// are moved around. ScrollCustomizationCallbacks& scrollCustomizationCallbacks() { DEFINE_STATIC_LOCAL(ScrollCustomizationCallbacks, scrollCustomizationCallbacks, @@ -605,8 +604,8 @@ // or CC. http://crbug.com/625676. DisableCompositingQueryAsserts disabler; - if (!document().frameHost()) { - // We should always have a frameHost if we're scrolling. See + if (!document().page()) { + // We should always have a Page if we're scrolling. See // crbug.com/689074 for details. return; } @@ -1882,8 +1881,13 @@ elementAnimations->setAnimationStyleChange(false); } } - if (parentComputedStyle()) + if (parentComputedStyle()) { change = recalcOwnStyle(change); + } else if (needsAttach()) { + setNeedsReattachLayoutTree(); + change = Reattach; + } + // Needed because the rebuildLayoutTree code needs to see what the // styleChangeType() was on reattach roots. See Node::reattachLayoutTree() // for an example.
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index 98b470d9..9e1e08e 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -725,6 +725,8 @@ } void Node::setNeedsReattachLayoutTree() { + DCHECK(document().inStyleRecalc()); + DCHECK(!document().childNeedsDistributionRecalc()); setFlag(NeedsReattachLayoutTree); markAncestorsWithChildNeedsReattachLayoutTree(); } @@ -932,7 +934,6 @@ layoutObject()->destroyAndCleanupAnonymousWrappers(); setLayoutObject(nullptr); setStyleChange(NeedsReattachStyleChange); - setFlag(NeedsReattachLayoutTree); clearChildNeedsStyleInvalidation(); }
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h index 870742f3..26d31c65 100644 --- a/third_party/WebKit/Source/core/dom/Node.h +++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -822,9 +822,7 @@ NeedsReattachLayoutTree = 1 << 26, ChildNeedsReattachLayoutTree = 1 << 27, - DefaultNodeFlags = IsFinishedParsingChildrenFlag | - NeedsReattachStyleChange | - NeedsReattachLayoutTree + DefaultNodeFlags = IsFinishedParsingChildrenFlag | NeedsReattachStyleChange }; // 4 bits remaining. @@ -969,7 +967,6 @@ detachLayoutTree(context); markAncestorsWithChildNeedsStyleRecalc(); - markAncestorsWithChildNeedsReattachLayoutTree(); } inline bool Node::shouldCallRecalcStyle(StyleRecalcChange change) {
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp index 3ea4dee..5037e303 100644 --- a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp +++ b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp
@@ -104,32 +104,9 @@ Member<Element> m_currentElement; }; -void SelectorDataList::initialize(const CSSSelectorList& selectorList) { - DCHECK(m_selectors.isEmpty()); - - unsigned selectorCount = 0; - for (const CSSSelector* selector = selectorList.first(); selector; - selector = CSSSelectorList::next(*selector)) - selectorCount++; - - m_usesDeepCombinatorOrShadowPseudo = false; - m_needsUpdatedDistribution = false; - m_selectors.reserveInitialCapacity(selectorCount); - for (const CSSSelector* selector = selectorList.first(); selector; - selector = CSSSelectorList::next(*selector)) { - if (selector->matchesPseudoElement()) - continue; - m_selectors.uncheckedAppend(selector); - m_usesDeepCombinatorOrShadowPseudo |= - selector->hasDeepCombinatorOrShadowPseudo(); - m_needsUpdatedDistribution |= selector->needsUpdatedDistribution(); - } -} - -inline bool SelectorDataList::selectorMatches( - const CSSSelector& selector, - Element& element, - const ContainerNode& rootNode) const { +inline bool selectorMatches(const CSSSelector& selector, + Element& element, + const ContainerNode& rootNode) { SelectorChecker::Init init; init.mode = SelectorChecker::QueryingRules; SelectorChecker checker(init); @@ -140,7 +117,7 @@ return checker.match(context); } -bool SelectorDataList::matches(Element& targetElement) const { +bool SelectorQuery::matches(Element& targetElement) const { if (m_needsUpdatedDistribution) targetElement.updateDistribution(); @@ -152,7 +129,7 @@ return false; } -Element* SelectorDataList::closest(Element& targetElement) const { +Element* SelectorQuery::closest(Element& targetElement) const { if (m_selectors.size() == 0) return nullptr; if (m_needsUpdatedDistribution) @@ -168,23 +145,23 @@ return nullptr; } -StaticElementList* SelectorDataList::queryAll(ContainerNode& rootNode) const { +StaticElementList* SelectorQuery::queryAll(ContainerNode& rootNode) const { HeapVector<Member<Element>> result; execute<AllElementsSelectorQueryTrait>(rootNode, result); return StaticElementList::adopt(result); } -Element* SelectorDataList::queryFirst(ContainerNode& rootNode) const { +Element* SelectorQuery::queryFirst(ContainerNode& rootNode) const { Element* matchedElement = nullptr; execute<SingleElementSelectorQueryTrait>(rootNode, matchedElement); return matchedElement; } template <typename SelectorQueryTrait> -void SelectorDataList::collectElementsByClassName( +static void collectElementsByClassName( ContainerNode& rootNode, const AtomicString& className, - typename SelectorQueryTrait::OutputType& output) const { + typename SelectorQueryTrait::OutputType& output) { for (Element& element : ElementTraversal::descendantsOf(rootNode)) { if (element.hasClass() && element.classNames().contains(className)) { SelectorQueryTrait::appendElement(output, element); @@ -210,10 +187,10 @@ } template <typename SelectorQueryTrait> -void SelectorDataList::collectElementsByTagName( +static void collectElementsByTagName( ContainerNode& rootNode, const QualifiedName& tagName, - typename SelectorQueryTrait::OutputType& output) const { + typename SelectorQueryTrait::OutputType& output) { DCHECK_EQ(tagName.namespaceURI(), starAtom); for (Element& element : ElementTraversal::descendantsOf(rootNode)) { if (matchesTagName(tagName, element)) { @@ -224,7 +201,7 @@ } } -inline bool SelectorDataList::canUseFastQuery( +inline bool SelectorQuery::canUseFastQuery( const ContainerNode& rootNode) const { if (m_usesDeepCombinatorOrShadowPseudo) return false; @@ -260,7 +237,7 @@ // The travseralRoots may be empty, regardless of the returned bool value, if // this method finds that the selectors won't match any element. template <typename SelectorQueryTrait> -void SelectorDataList::findTraverseRootsAndExecute( +void SelectorQuery::findTraverseRootsAndExecute( ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { // We need to return the matches in document order. To use id lookup while @@ -343,7 +320,7 @@ } template <typename SelectorQueryTrait> -void SelectorDataList::executeForTraverseRoot( +void SelectorQuery::executeForTraverseRoot( const CSSSelector& selector, ContainerNode* traverseRoot, MatchTraverseRootState matchTraverseRoot, @@ -368,7 +345,7 @@ } template <typename SelectorQueryTrait, typename SimpleElementListType> -void SelectorDataList::executeForTraverseRoots( +void SelectorQuery::executeForTraverseRoots( const CSSSelector& selector, SimpleElementListType& traverseRoots, MatchTraverseRootState matchTraverseRoots, @@ -402,7 +379,7 @@ } template <typename SelectorQueryTrait> -bool SelectorDataList::selectorListMatches( +bool SelectorQuery::selectorListMatches( ContainerNode& rootNode, Element& element, typename SelectorQueryTrait::OutputType& output) const { @@ -416,7 +393,7 @@ } template <typename SelectorQueryTrait> -void SelectorDataList::executeSlow( +void SelectorQuery::executeSlow( ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { for (Element& element : ElementTraversal::descendantsOf(rootNode)) { @@ -480,7 +457,7 @@ } template <typename SelectorQueryTrait> -void SelectorDataList::executeSlowTraversingShadowTree( +void SelectorQuery::executeSlowTraversingShadowTree( ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { for (ContainerNode* node = firstWithinTraversingShadowTree(rootNode); node; @@ -513,7 +490,7 @@ } template <typename SelectorQueryTrait> -void SelectorDataList::execute( +void SelectorQuery::execute( ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { if (m_selectors.isEmpty()) @@ -596,23 +573,25 @@ SelectorQuery::SelectorQuery(CSSSelectorList selectorList) { m_selectorList = std::move(selectorList); - m_selectors.initialize(m_selectorList); -} + DCHECK(m_selectors.isEmpty()); -bool SelectorQuery::matches(Element& element) const { - return m_selectors.matches(element); -} + unsigned selectorCount = 0; + for (const CSSSelector* selector = m_selectorList.first(); selector; + selector = CSSSelectorList::next(*selector)) + selectorCount++; -Element* SelectorQuery::closest(Element& element) const { - return m_selectors.closest(element); -} - -StaticElementList* SelectorQuery::queryAll(ContainerNode& rootNode) const { - return m_selectors.queryAll(rootNode); -} - -Element* SelectorQuery::queryFirst(ContainerNode& rootNode) const { - return m_selectors.queryFirst(rootNode); + m_usesDeepCombinatorOrShadowPseudo = false; + m_needsUpdatedDistribution = false; + m_selectors.reserveInitialCapacity(selectorCount); + for (const CSSSelector* selector = m_selectorList.first(); selector; + selector = CSSSelectorList::next(*selector)) { + if (selector->matchesPseudoElement()) + continue; + m_selectors.uncheckedAppend(selector); + m_usesDeepCombinatorOrShadowPseudo |= + selector->hasDeepCombinatorOrShadowPseudo(); + m_needsUpdatedDistribution |= selector->needsUpdatedDistribution(); + } } SelectorQuery* SelectorQueryCache::add(const AtomicString& selectors,
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.h b/third_party/WebKit/Source/core/dom/SelectorQuery.h index ce28ed3..f6591f91 100644 --- a/third_party/WebKit/Source/core/dom/SelectorQuery.h +++ b/third_party/WebKit/Source/core/dom/SelectorQuery.h
@@ -45,31 +45,29 @@ class StaticNodeTypeList; using StaticElementList = StaticNodeTypeList<Element>; -class SelectorDataList { - DISALLOW_NEW(); +class CORE_EXPORT SelectorQuery { + WTF_MAKE_NONCOPYABLE(SelectorQuery); + USING_FAST_MALLOC(SelectorQuery); public: - void initialize(const CSSSelectorList&); + static std::unique_ptr<SelectorQuery> adopt(CSSSelectorList); + + // https://dom.spec.whatwg.org/#dom-element-matches bool matches(Element&) const; + + // https://dom.spec.whatwg.org/#dom-element-closest Element* closest(Element&) const; + + // https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall StaticElementList* queryAll(ContainerNode& rootNode) const; + + // https://dom.spec.whatwg.org/#dom-parentnode-queryselector Element* queryFirst(ContainerNode& rootNode) const; private: - bool canUseFastQuery(const ContainerNode& rootNode) const; - bool selectorMatches(const CSSSelector&, - Element&, - const ContainerNode&) const; + explicit SelectorQuery(CSSSelectorList); - template <typename SelectorQueryTrait> - void collectElementsByClassName( - ContainerNode& rootNode, - const AtomicString& className, - typename SelectorQueryTrait::OutputType&) const; - template <typename SelectorQueryTrait> - void collectElementsByTagName(ContainerNode& rootNode, - const QualifiedName& tagName, - typename SelectorQueryTrait::OutputType&) const; + bool canUseFastQuery(const ContainerNode& rootNode) const; template <typename SelectorQueryTrait> void findTraverseRootsAndExecute( @@ -108,30 +106,12 @@ void execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const; + CSSSelectorList m_selectorList; Vector<const CSSSelector*> m_selectors; bool m_usesDeepCombinatorOrShadowPseudo : 1; bool m_needsUpdatedDistribution : 1; }; -class CORE_EXPORT SelectorQuery { - WTF_MAKE_NONCOPYABLE(SelectorQuery); - USING_FAST_MALLOC(SelectorQuery); - - public: - static std::unique_ptr<SelectorQuery> adopt(CSSSelectorList); - - bool matches(Element&) const; - Element* closest(Element&) const; - StaticElementList* queryAll(ContainerNode& rootNode) const; - Element* queryFirst(ContainerNode& rootNode) const; - - private: - explicit SelectorQuery(CSSSelectorList); - - SelectorDataList m_selectors; - CSSSelectorList m_selectorList; -}; - class SelectorQueryCache { USING_FAST_MALLOC(SelectorQueryCache);
diff --git a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp index c0c743f..8e5eec44 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp +++ b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp
@@ -86,7 +86,6 @@ shadowHost.setNeedsStyleRecalc( SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Shadow)); - shadowRoot->setNeedsReattachLayoutTree(); probe::didPushShadowRoot(&shadowHost, shadowRoot);
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp index 3d99595..17ff2f2 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp +++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp
@@ -142,8 +142,11 @@ StyleSharingDepthScope sharingScope(*this); - if (getStyleChangeType() >= SubtreeStyleChange) + if (getStyleChangeType() >= SubtreeStyleChange) { change = Force; + if (needsAttach()) + setNeedsReattachLayoutTree(); + } // There's no style to update so just calling recalcStyle means we're updated. clearNeedsStyleRecalc();
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp index a4e45f4..841eb77 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -212,6 +212,64 @@ EXPECT_STREQ("\xF0\x9F\x8F\x86\x61\x62", div->innerText().utf8().data()); } +TEST_F(InputMethodControllerTest, SetCompositionWithGraphemeCluster) { + insertHTMLElement("<div id='sample' contenteditable></div>", "sample"); + + Vector<CompositionUnderline> underlines; + underlines.push_back(CompositionUnderline(6, 6, Color(255, 0, 0), false, 0)); + document().updateStyleAndLayout(); + + // UTF16 = 0x0939 0x0947 0x0932 0x0932. Note that 0x0932 0x0932 is a grapheme + // cluster. + controller().setComposition( + String::fromUTF8("\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA4\xB2"), + underlines, 4, 4); + EXPECT_EQ(4u, controller().getSelectionOffsets().start()); + EXPECT_EQ(4u, controller().getSelectionOffsets().end()); + + // UTF16 = 0x0939 0x0947 0x0932 0x094D 0x0932 0x094B. + controller().setComposition( + String::fromUTF8("\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0" + "\xA4\xB2\xE0\xA5\x8B"), + underlines, 6, 6); + EXPECT_EQ(6u, controller().getSelectionOffsets().start()); + EXPECT_EQ(6u, controller().getSelectionOffsets().end()); +} + +TEST_F(InputMethodControllerTest, + SetCompositionWithGraphemeClusterAndMultipleNodes) { + Element* div = + insertHTMLElement("<div id='sample' contenteditable></div>", "sample"); + + Vector<CompositionUnderline> underlines; + underlines.push_back( + CompositionUnderline(12, 12, Color(255, 0, 0), false, 0)); + document().updateStyleAndLayout(); + + // UTF16 = 0x0939 0x0947 0x0932 0x094D 0x0932 0x094B. 0x0939 0x0947 0x0932 is + // a grapheme cluster, so is the remainding 0x0932 0x094B. + controller().commitText( + String::fromUTF8("\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0" + "\xA4\xB2\xE0\xA5\x8B"), + underlines, 1); + controller().commitText("\nab ", underlines, 1); + controller().setComposition(String("c"), underlines, 1, 1); + EXPECT_STREQ( + "\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0\xA4\xB2\xE0\xA5" + "\x8B\nab c", + div->innerText().utf8().data()); + EXPECT_EQ(11u, controller().getSelectionOffsets().start()); + EXPECT_EQ(11u, controller().getSelectionOffsets().end()); + + controller().setComposition(String("cd"), underlines, 2, 2); + EXPECT_STREQ( + "\xE0\xA4\xB9\xE0\xA5\x87\xE0\xA4\xB2\xE0\xA5\x8D\xE0\xA4\xB2\xE0\xA5" + "\x8B\nab cd", + div->innerText().utf8().data()); + EXPECT_EQ(12u, controller().getSelectionOffsets().start()); + EXPECT_EQ(12u, controller().getSelectionOffsets().end()); +} + TEST_F(InputMethodControllerTest, SetCompositionKeepingStyle) { Element* div = insertHTMLElement( "<div id='sample' "
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp index 4759d76..5d01df33 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertIncrementalTextCommand.cpp
@@ -51,17 +51,18 @@ adjustedPosition.computeOffsetInContainerNode()); } -size_t computeCommonGraphemeClusterPrefixLength( - const int selectionStart, - const String& oldText, - const String& newText, - const Element* rootEditableElement) { +size_t computeCommonGraphemeClusterPrefixLength(const Position& selectionStart, + const String& oldText, + const String& newText) { const size_t commonPrefixLength = computeCommonPrefixLength(oldText, newText); + const int selectionOffset = selectionStart.computeOffsetInContainerNode(); + const ContainerNode* selectionNode = + selectionStart.computeContainerNode()->parentNode(); // For grapheme cluster, we should adjust it for grapheme boundary. const EphemeralRange& range = - PlainTextRange(0, selectionStart + commonPrefixLength) - .createRange(*rootEditableElement); + PlainTextRange(0, selectionOffset + commonPrefixLength) + .createRange(*selectionNode); if (range.isNull()) return 0; const Position& position = range.endPosition(); @@ -83,22 +84,24 @@ position.computeOffsetInContainerNode()); } -size_t computeCommonGraphemeClusterSuffixLength( - const int selectionStart, - const String& oldText, - const String& newText, - const Element* rootEditableElement) { +size_t computeCommonGraphemeClusterSuffixLength(const Position& selectionStart, + const String& oldText, + const String& newText) { const size_t commonSuffixLength = computeCommonSuffixLength(oldText, newText); + const int selectionOffset = selectionStart.computeOffsetInContainerNode(); + const ContainerNode* selectionNode = + selectionStart.computeContainerNode()->parentNode(); // For grapheme cluster, we should adjust it for grapheme boundary. const EphemeralRange& range = - PlainTextRange(0, selectionStart + oldText.length() - commonSuffixLength) - .createRange(*rootEditableElement); + PlainTextRange(0, selectionOffset + oldText.length() - commonSuffixLength) + .createRange(*selectionNode); if (range.isNull()) return 0; const Position& position = range.endPosition(); const size_t diff = computeDistanceToRightGraphemeBoundary(position); - DCHECK_GE(commonSuffixLength, diff); + if (diff > commonSuffixLength) + return 0; return commonSuffixLength - diff; } @@ -153,16 +156,15 @@ const String oldText = plainText(selectionRange); const String& newText = m_text; - const int selectionStart = - endingSelection().start().computeOffsetInContainerNode(); + const Position& selectionStart = endingSelection().start(); const size_t newTextLength = newText.length(); const size_t oldTextLength = oldText.length(); const size_t commonPrefixLength = computeCommonGraphemeClusterPrefixLength( - selectionStart, oldText, newText, element); + selectionStart, oldText, newText); // We should ignore common prefix when finding common suffix. const size_t commonSuffixLength = computeCommonGraphemeClusterSuffixLength( selectionStart, oldText.right(oldTextLength - commonPrefixLength), - newText.right(newTextLength - commonPrefixLength), element); + newText.right(newTextLength - commonPrefixLength)); DCHECK_GE(oldTextLength, commonPrefixLength + commonSuffixLength); m_text =
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index 0d022a76..6e8030f 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -50,7 +50,6 @@ #include "core/events/ErrorEvent.h" #include "core/frame/BrowserControls.h" #include "core/frame/EventHandlerRegistry.h" -#include "core/frame/FrameHost.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameClient.h" #include "core/frame/Location.h" @@ -2753,8 +2752,8 @@ } void FrameView::didAttachDocument() { - FrameHost* frameHost = m_frame->host(); - DCHECK(frameHost); + Page* page = m_frame->page(); + DCHECK(page); DCHECK(m_frame->document()); @@ -2767,9 +2766,8 @@ RootFrameViewport::create(visualViewport, *layoutViewport); m_viewportScrollableArea = rootFrameViewport; - frameHost->page() - .globalRootScrollerController() - .initializeViewportScrollCallback(*rootFrameViewport); + page->globalRootScrollerController().initializeViewportScrollCallback( + *rootFrameViewport); } }
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 0424399..a5c9ff7 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1489,6 +1489,7 @@ CSSOverflowPaged = 1867, ChildSrcAllowedWorkerThatScriptSrcBlocked = 1868, HTMLTableElementPresentationAttributeBackground = 1869, + V8Navigator_GetInstalledRelatedApps_Method = 1870, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp index 14e6031..4a449c5 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp +++ b/third_party/WebKit/Source/core/html/HTMLInputElementTest.cpp
@@ -8,7 +8,6 @@ #include "core/dom/Document.h" #include "core/events/KeyboardEvent.h" #include "core/events/KeyboardEventInit.h" -#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/VisualViewport.h" #include "core/html/HTMLBodyElement.h" @@ -99,7 +98,7 @@ TEST_F(HTMLInputElementTest, NoAssertWhenMovedInNewDocument) { Document* documentWithoutFrame = Document::create(); - EXPECT_EQ(nullptr, documentWithoutFrame->frameHost()); + EXPECT_EQ(nullptr, documentWithoutFrame->page()); HTMLHtmlElement* html = HTMLHtmlElement::create(*documentWithoutFrame); html->appendChild(HTMLBodyElement::create(*documentWithoutFrame)); @@ -109,7 +108,7 @@ std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(); auto& document = pageHolder->document(); - EXPECT_NE(nullptr, document.frameHost()); + EXPECT_NE(nullptr, document.page()); // Put the input element inside a document with frame. document.body()->appendChild(documentWithoutFrame->body()->firstChild());
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index e2a0d5b..490f727 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -54,7 +54,6 @@ #include "core/events/WheelEvent.h" #include "core/frame/Deprecation.h" #include "core/frame/EventHandlerRegistry.h" -#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameClient.h" @@ -2093,11 +2092,4 @@ return WebInputEventResult::HandledSystem; } -FrameHost* EventHandler::frameHost() const { - if (!m_frame->page()) - return nullptr; - - return &m_frame->page()->frameHost(); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/input/EventHandler.h b/third_party/WebKit/Source/core/input/EventHandler.h index e3c9ce7..6080578 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.h +++ b/third_party/WebKit/Source/core/input/EventHandler.h
@@ -59,7 +59,6 @@ template <typename EventType> class EventWithHitTestResults; class FloatQuad; -class FrameHost; class HTMLFrameSetElement; class HitTestRequest; class HitTestResult; @@ -338,8 +337,6 @@ bool shouldBrowserControlsConsumeScroll(FloatSize) const; - FrameHost* frameHost() const; - bool rootFrameTouchPointerActiveInCurrentFrame(int pointerId) const; // NOTE: If adding a new field to this class please ensure that it is
diff --git a/third_party/WebKit/Source/core/input/GestureManager.cpp b/third_party/WebKit/Source/core/input/GestureManager.cpp index 4b4617d..8cdaaaa9 100644 --- a/third_party/WebKit/Source/core/input/GestureManager.cpp +++ b/third_party/WebKit/Source/core/input/GestureManager.cpp
@@ -8,7 +8,6 @@ #include "core/dom/DocumentUserGestureToken.h" #include "core/editing/SelectionController.h" #include "core/events/GestureEvent.h" -#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/Settings.h" #include "core/frame/VisualViewport.h" @@ -426,13 +425,6 @@ return WebInputEventResult::NotHandled; } -FrameHost* GestureManager::frameHost() const { - if (!m_frame->page()) - return nullptr; - - return &m_frame->page()->frameHost(); -} - WTF::Optional<WTF::TimeTicks> GestureManager::getLastShowPressTimestamp() const { return m_lastShowPressTimestamp;
diff --git a/third_party/WebKit/Source/core/input/GestureManager.h b/third_party/WebKit/Source/core/input/GestureManager.h index 6baedf1..6ac90b5 100644 --- a/third_party/WebKit/Source/core/input/GestureManager.h +++ b/third_party/WebKit/Source/core/input/GestureManager.h
@@ -61,8 +61,6 @@ WebInputEventResult sendContextMenuEventForGesture( const GestureEventWithHitTestResults&); - FrameHost* frameHost() const; - // NOTE: If adding a new field to this class please ensure that it is // cleared if needed in |GestureManager::clear()|.
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 6527abc4..35cb29e 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -907,6 +907,12 @@ { "name": "displayedInsecureContentStyle", "$ref": "SecurityState", "description": "Security state representing a page that displayed insecure content." } ], "description": "Information about insecure content on the page." + }, + { + "id": "CertificateErrorAction", + "type": "string", + "enum": ["continue", "cancel"], + "description": "The action to take when a certificate error occurs. continue will continue processing the request and cancel will cancel the request." } ], "commands": [ @@ -921,6 +927,21 @@ { "name": "showCertificateViewer", "description": "Displays native dialog with the certificate details." + }, + { + "name": "handleCertificateError", + "description": "Handles a certificate error that fired a certificateError event.", + "parameters": [ + { "name": "eventId", "type": "integer", "description": "The ID of the event."}, + { "name": "action", "$ref": "CertificateErrorAction", "description": "The action to take on the certificate error." } + ] + }, + { + "name": "setOverrideCertificateErrors", + "description": "Enable/disable overriding certificate errors. If enabled, all certificate error events need to be handled by the DevTools client and should be answered with handleCertificateError commands.", + "parameters": [ + { "name": "override", "type": "boolean", "description": "If true, certificate errors will be overridden."} + ] } ], "events": [ @@ -934,6 +955,15 @@ { "name": "insecureContentStatus", "$ref": "InsecureContentStatus", "description": "Information about insecure content on the page." }, { "name": "summary", "type": "string", "description": "Overrides user-visible description of the state.", "optional": true } ] + }, + { + "name": "certificateError", + "description": "There is a certificate error. If overriding certificate errors is enabled, then it should be handled with the handleCertificateError command. Note: this event does not fire if the certificate error has been allowed internally.", + "parameters": [ + { "name": "eventId", "type": "integer", "description": "The ID of the event."}, + { "name": "errorType", "type": "string", "description": "The type of the error."}, + { "name": "requestURL", "type": "string", "description": "The url that was requested."} + ] } ] },
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp index 0b1aaf72..88b23d77 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -941,41 +941,6 @@ return logicalRightOffsetForContent(); } -LayoutBlock* LayoutBlock::blockBeforeWithinSelectionRoot( - LayoutSize& offset) const { - if (isSelectionRoot()) - return nullptr; - - const LayoutObject* object = this; - LayoutObject* sibling; - do { - sibling = object->previousSibling(); - while (sibling && (!sibling->isLayoutBlock() || - toLayoutBlock(sibling)->isSelectionRoot())) - sibling = sibling->previousSibling(); - - offset -= LayoutSize(toLayoutBlock(object)->logicalLeft(), - toLayoutBlock(object)->logicalTop()); - object = object->parent(); - } while (!sibling && object && object->isLayoutBlock() && - !toLayoutBlock(object)->isSelectionRoot()); - - if (!sibling) - return nullptr; - - LayoutBlock* beforeBlock = toLayoutBlock(sibling); - - offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop()); - - LayoutObject* child = beforeBlock->lastChild(); - while (child && child->isLayoutBlock()) { - beforeBlock = toLayoutBlock(child); - offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop()); - child = beforeBlock->lastChild(); - } - return beforeBlock; -} - void LayoutBlock::setSelectionState(SelectionState state) { LayoutBox::setSelectionState(state);
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.h b/third_party/WebKit/Source/core/layout/LayoutBlock.h index 49de48e4..f1273cc 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.h +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.h
@@ -215,8 +215,6 @@ LayoutUnit blockDirectionOffset(const LayoutSize& offsetFromBlock) const; LayoutUnit inlineDirectionOffset(const LayoutSize& offsetFromBlock) const; - LayoutBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const; - void setSelectionState(SelectionState) override; static LayoutBlock* createAnonymousWithParentAndDisplay(
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h index 51df00a8..f49cccd 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutBlockFlow.h
@@ -184,10 +184,6 @@ bool containsFloats() const { return toBlockFlow()->containsFloats(); } - LayoutBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const { - return toBlockFlow()->blockBeforeWithinSelectionRoot(offset); - } - InlineBox* createAndAppendRootInlineBox() { return toBlockFlow()->createAndAppendRootInlineBox(); }
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index d88d5225..c2077930 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -1564,7 +1564,7 @@ static unsigned eventHandlerCount( Document& document, EventHandlerRegistry::EventHandlerClass handlerClass) { - if (!document.frameHost()) + if (!document.page()) return 0; EventHandlerRegistry* registry = &document.page()->eventHandlerRegistry(); unsigned count = 0;
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js index ddff22f0..771e9be 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -131,9 +131,8 @@ this._updatePlaybackControls(); this._previewContainer = this.contentElement.createChild('div', 'animation-timeline-buffer'); - this._popoverHelper = new UI.PopoverHelper(this._previewContainer, true); - this._popoverHelper.initializeCallbacks( - this._getPopoverAnchor.bind(this), this._showPopover.bind(this), this._onHidePopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this._previewContainer, this._getPopoverRequest.bind(this)); + this._popoverHelper.setDisableOnClick(true); this._popoverHelper.setTimeout(0); var emptyBufferHint = this.contentElement.createChild('div', 'animation-timeline-buffer-hint'); emptyBufferHint.textContent = Common.UIString('Listening for animations...'); @@ -162,49 +161,44 @@ } /** - * @param {!Element} element * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} + * @return {?UI.PopoverRequest} */ - _getPopoverAnchor(element, event) { - if (element.isDescendant(this._previewContainer)) - return element; - } + _getPopoverRequest(event) { + var element = event.target; + if (!element.isDescendant(this._previewContainer)) + return null; - /** - * @param {!Element|!AnchorBox} anchor - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showPopover(anchor, popover) { - var animGroup; - for (var group of this._previewMap.keysArray()) { - if (this._previewMap.get(group).element === anchor.parentElement) - animGroup = group; - } - console.assert(animGroup); - var screenshots = animGroup.screenshots(); - if (!screenshots.length) - return Promise.resolve(false); + return { + box: event.target.boxInWindow(), + show: popover => { + var animGroup; + for (var group of this._previewMap.keysArray()) { + if (this._previewMap.get(group).element === element.parentElement) + animGroup = group; + } + console.assert(animGroup); + var screenshots = animGroup.screenshots(); + if (!screenshots.length) + return Promise.resolve(false); - var fulfill; - var promise = new Promise(x => fulfill = x); - if (!screenshots[0].complete) - screenshots[0].onload = onFirstScreenshotLoaded.bind(null, screenshots); - else - onFirstScreenshotLoaded(screenshots); - return promise; + var fulfill; + var promise = new Promise(x => fulfill = x); + if (!screenshots[0].complete) + screenshots[0].onload = onFirstScreenshotLoaded.bind(null, screenshots); + else + onFirstScreenshotLoaded(screenshots); + return promise; - /** - * @param {!Array.<!Image>} screenshots - */ - function onFirstScreenshotLoaded(screenshots) { - new Animation.AnimationScreenshotPopover(screenshots).show(popover.contentElement); - fulfill(true); - } - } - - _onHidePopover() { + /** + * @param {!Array.<!Image>} screenshots + */ + function onFirstScreenshotLoaded(screenshots) { + new Animation.AnimationScreenshotPopover(screenshots).show(popover.contentElement); + fulfill(true); + } + } + }; } _togglePauseAll() {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js index 69a34727..cd0c0c9 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
@@ -148,36 +148,30 @@ * @param {!SDK.Target} target * @param {string} originalImageURL * @param {boolean} showDimensions - * @param {function(!Element=)} userCallback * @param {!Object=} precomputedFeatures + * @return {!Promise<?Element>} */ Components.DOMPresentationUtils.buildImagePreviewContents = function( - target, originalImageURL, showDimensions, userCallback, precomputedFeatures) { + target, originalImageURL, showDimensions, precomputedFeatures) { var resourceTreeModel = SDK.ResourceTreeModel.fromTarget(target); - if (!resourceTreeModel) { - userCallback(); - return; - } + if (!resourceTreeModel) + return Promise.resolve(/** @type {?Element} */ (null)); var resource = resourceTreeModel.resourceForURL(originalImageURL); var imageURL = originalImageURL; if (!isImageResource(resource) && precomputedFeatures && precomputedFeatures.currentSrc) { imageURL = precomputedFeatures.currentSrc; resource = resourceTreeModel.resourceForURL(imageURL); } - if (!isImageResource(resource)) { - userCallback(); - return; - } + if (!isImageResource(resource)) + return Promise.resolve(/** @type {?Element} */ (null)); + var fulfill; + var promise = new Promise(x => fulfill = x); var imageElement = createElement('img'); imageElement.addEventListener('load', buildContent, false); - imageElement.addEventListener('error', errorCallback, false); + imageElement.addEventListener('error', () => fulfill(null), false); resource.populateImageSource(imageElement); - - function errorCallback() { - // Drop the event parameter when invoking userCallback. - userCallback(); - } + return promise; /** * @param {?SDK.Resource} resource @@ -212,7 +206,7 @@ container.createChild('tr').createChild('td').createChild('span', 'description').textContent = String.sprintf('currentSrc: %s', imageURL.trimMiddle(100)); } - userCallback(container); + fulfill(container); } };
diff --git a/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js b/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js index dd12c01..f9d202ca 100644 --- a/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js +++ b/third_party/WebKit/Source/devtools/front_end/dom_extension/DOMExtension.js
@@ -472,6 +472,15 @@ this.width = width || 0; this.height = height || 0; } + + /** + * @param {number} x + * @param {number} y + * @return {boolean} + */ + contains(x, y) { + return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height; + } }; /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js index 6d0eeead..b095335 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -568,41 +568,29 @@ } /** - * @param {!Element} element * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} + * @return {?UI.PopoverRequest} */ - _getPopoverAnchor(element, event) { - var link = element; + _getPopoverRequest(event) { + var link = event.target; while (link && !link[Elements.ElementsTreeElement.HrefSymbol]) link = link.parentElementOrShadowHost(); - return link ? link : undefined; - } + if (!link) + return null; - /** - * @param {!Element|!AnchorBox} link - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showPopover(link, popover) { - var node = this.selectedDOMNode(); - if (!node) - return Promise.resolve(false); - - var fulfill; - var promise = new Promise(x => fulfill = x); - Components.DOMPresentationUtils.buildImagePreviewContents( - node.target(), link[Elements.ElementsTreeElement.HrefSymbol], true, showPopover); - return promise; - - /** - * @param {!Element=} contents - */ - function showPopover(contents) { - if (contents) - popover.contentElement.appendChild(contents); - fulfill(!!contents); - } + return { + box: link.boxInWindow(), + show: async popover => { + var node = this.selectedDOMNode(); + if (!node) + return false; + var preview = await Components.DOMPresentationUtils.buildImagePreviewContents( + node.target(), link[Elements.ElementsTreeElement.HrefSymbol], true); + if (preview) + popover.contentElement.appendChild(preview); + return !!preview; + } + }; } _jumpToSearchResult(index) { @@ -907,9 +895,8 @@ var tabbedPane = this.sidebarPaneView.tabbedPane(); if (this._popoverHelper) this._popoverHelper.hidePopover(); - this._popoverHelper = new UI.PopoverHelper(tabbedPane.element); + this._popoverHelper = new UI.PopoverHelper(tabbedPane.element, this._getPopoverRequest.bind(this)); this._popoverHelper.setHasPadding(true); - this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); this._popoverHelper.setTimeout(0); if (horizontally) {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js index 38d3a035c..3fe0a40 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -75,8 +75,7 @@ this._visible = false; - this._popoverHelper = new UI.PopoverHelper(this._element); - this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this._element, this._getPopoverRequest.bind(this)); this._popoverHelper.setHasPadding(true); this._popoverHelper.setTimeout(0, 100); @@ -522,36 +521,51 @@ } /** - * @param {!Element} element * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} + * @return {?UI.PopoverRequest} */ - _getPopoverAnchor(element, event) { - var link = element; + _getPopoverRequest(event) { + var link = event.target; while (link && !link[Elements.ElementsTreeElement.HrefSymbol]) link = link.parentElementOrShadowHost(); - return link ? link : undefined; + if (!link) + return null; + + return { + box: link.boxInWindow(), + show: async popover => { + var listItem = link.enclosingNodeOrSelfWithNodeName('li'); + var node = /** @type {!Elements.ElementsTreeElement} */ (listItem.treeElement).node(); + var precomputedFeatures = await this._loadDimensionsForNode(node); + var preview = await Components.DOMPresentationUtils.buildImagePreviewContents( + node.target(), link[Elements.ElementsTreeElement.HrefSymbol], true, precomputedFeatures); + if (preview) + popover.contentElement.appendChild(preview); + return !!preview; + } + }; } /** * @param {!SDK.DOMNode} node - * @param {function()} callback + * @return {!Promise<!Object|undefined>} */ - _loadDimensionsForNode(node, callback) { - if (!node.nodeName() || node.nodeName().toLowerCase() !== 'img') { - callback(); - return; - } + _loadDimensionsForNode(node) { + if (!node.nodeName() || node.nodeName().toLowerCase() !== 'img') + return Promise.resolve(); + var fulfill; + var promise = new Promise(x => fulfill = x); node.resolveToObject('', resolvedNode); + return promise; function resolvedNode(object) { if (!object) { - callback(); + fulfill(); return; } - object.callFunctionJSON(features, undefined, callback); + object.callFunctionJSON(features, undefined, fulfill); object.release(); /** @@ -571,32 +585,6 @@ } } - /** - * @param {!Element|!AnchorBox} link - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showPopover(link, popover) { - var fulfill; - var promise = new Promise(x => fulfill = x); - var listItem = link.enclosingNodeOrSelfWithNodeName('li'); - var node = /** @type {!Elements.ElementsTreeElement} */ (listItem.treeElement).node(); - this._loadDimensionsForNode( - node, Components.DOMPresentationUtils.buildImagePreviewContents.bind( - Components.DOMPresentationUtils, node.target(), link[Elements.ElementsTreeElement.HrefSymbol], true, - showPopover)); - return promise; - - /** - * @param {!Element=} contents - */ - function showPopover(contents) { - if (contents) - popover.contentElement.appendChild(contents); - fulfill(!!contents); - } - } - _onmousedown(event) { var element = this._treeElementFromEvent(event);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js index 5f26a5c..6508efe8 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -92,9 +92,7 @@ this._loadColumnExtensions(); this._loadCustomColumnsAndSettings(); - this._popoverHelper = new UI.PopoverHelper(this._networkLogView.element); - this._popoverHelper.initializeCallbacks( - this._getPopoverAnchor.bind(this), this._showPopover.bind(this), this._onHidePopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this._networkLogView.element, this._getPopoverRequest.bind(this)); this._popoverHelper.setHasPadding(true); /** @type {!DataGrid.SortableDataGrid<!Network.NetworkNode>} */ @@ -570,37 +568,31 @@ } /** - * @param {!Element} element * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} + * @return {?UI.PopoverRequest} */ - _getPopoverAnchor(element, event) { + _getPopoverRequest(event) { if (!this._gridMode) - return; - var anchor = element.enclosingNodeOrSelfWithClass('network-script-initiated'); - if (anchor && anchor.request) { - var initiator = /** @type {!SDK.NetworkRequest} */ (anchor.request).initiator(); - if (initiator && initiator.stack) - return anchor; - } - } + return null; - /** - * @param {!Element|!AnchorBox} anchor - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showPopover(anchor, popover) { - var request = /** @type {!SDK.NetworkRequest} */ (anchor.request); - var initiator = /** @type {!Protocol.Network.Initiator} */ (request.initiator()); - var content = Components.DOMPresentationUtils.buildStackTracePreviewContents( - request.target(), this._popupLinkifier, initiator.stack); - popover.contentElement.appendChild(content); - return Promise.resolve(true); - } + var anchor = event.target.enclosingNodeOrSelfWithClass('network-script-initiated'); + var request = /** @type {?SDK.NetworkRequest} */ (anchor ? anchor.request : null); + var initiator = request ? request.initiator() : null; + if (!initiator || !initiator.stack) + return null; - _onHidePopover() { - this._popupLinkifier.reset(); + return { + box: anchor.boxInWindow(), + show: popover => { + var content = Components.DOMPresentationUtils.buildStackTracePreviewContents( + anchor.request.target(), this._popupLinkifier, initiator.stack); + popover.contentElement.appendChild(content); + return Promise.resolve(true); + }, + hide: () => { + this._popupLinkifier.reset(); + } + }; } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js index 1f36a35..ed370ad2 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkWaterfallColumn.js
@@ -33,8 +33,7 @@ this._startTime = this._calculator.minimumBoundary(); this._endTime = this._calculator.maximumBoundary(); - this._popoverHelper = new UI.PopoverHelper(this.element); - this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this.element, this._getPopoverRequest.bind(this)); this._popoverHelper.setHasPadding(true); this._popoverHelper.setTimeout(300, 300); @@ -187,16 +186,15 @@ } /** - * @param {!Element} element * @param {!Event} event - * @return {!AnchorBox|undefined} + * @return {?UI.PopoverRequest} */ - _getPopoverAnchor(element, event) { + _getPopoverRequest(event) { if (!this._hoveredNode) - return; + return null; var request = this._hoveredNode.request(); if (!request) - return; + return null; var useTimingBars = !Common.moduleSetting('networkColorCodeResourceTypes').get() && !this._calculator.startAtZero; if (useTimingBars) { var range = Network.RequestTimingView.calculateRequestTimeRanges(request, 0) @@ -216,37 +214,30 @@ } if (event.clientX < this._canvasPosition.left + start || event.clientX > this._canvasPosition.left + end) - return; + return null; var rowIndex = this._nodes.findIndex(node => node.hovered()); var barHeight = this._getBarHeight(range.name); var y = this._headerHeight + (this._rowHeight * rowIndex - this._scrollTop) + ((this._rowHeight - barHeight) / 2); if (event.clientY < this._canvasPosition.top + y || event.clientY > this._canvasPosition.top + y + barHeight) - return; + return null; var anchorBox = this.element.boxInWindow(); anchorBox.x += start; anchorBox.y += y; anchorBox.width = end - start; anchorBox.height = barHeight; - return anchorBox; - } - /** - * @param {!Element|!AnchorBox} anchor - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showPopover(anchor, popover) { - if (!this._hoveredNode) - return Promise.resolve(false); - var request = this._hoveredNode.request(); - if (!request) - return Promise.resolve(false); - var content = Network.RequestTimingView.createTimingTable(request, this._calculator); - popover.contentElement.appendChild(content); - return Promise.resolve(true); + return { + box: anchorBox, + show: popover => { + var content = + Network.RequestTimingView.createTimingTable(/** @type {!SDK.NetworkRequest} */ (request), this._calculator); + popover.contentElement.appendChild(content); + return Promise.resolve(true); + } + }; } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network_conditions/NetworkConditionsSelector.js b/third_party/WebKit/Source/devtools/front_end/network_conditions/NetworkConditionsSelector.js index 82f6a33..25ab9f55 100644 --- a/third_party/WebKit/Source/devtools/front_end/network_conditions/NetworkConditionsSelector.js +++ b/third_party/WebKit/Source/devtools/front_end/network_conditions/NetworkConditionsSelector.js
@@ -176,21 +176,19 @@ SDK.MultitargetNetworkManager.Events.ConditionsChanged, networkConditionsChanged); checkbox.setChecked(SDK.multitargetNetworkManager.networkConditions() === SDK.NetworkManager.OfflineConditions); - var lastNetworkConditions; - function forceOffline() { if (checkbox.checked()) { - lastNetworkConditions = SDK.multitargetNetworkManager.networkConditions(); + NetworkConditions.NetworkConditionsSelector._lastNetworkConditions = + SDK.multitargetNetworkManager.networkConditions(); SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.OfflineConditions); } else { - SDK.multitargetNetworkManager.setNetworkConditions(lastNetworkConditions); + SDK.multitargetNetworkManager.setNetworkConditions( + NetworkConditions.NetworkConditionsSelector._lastNetworkConditions); } } function networkConditionsChanged() { var conditions = SDK.multitargetNetworkManager.networkConditions(); - if (conditions !== SDK.NetworkManager.OfflineConditions) - lastNetworkConditions = conditions; checkbox.setChecked(conditions === SDK.NetworkManager.OfflineConditions); } return checkbox;
diff --git a/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js b/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js index 4a222288..8a52f32 100644 --- a/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js +++ b/third_party/WebKit/Source/devtools/front_end/perf_ui/TimelineOverviewPane.js
@@ -53,9 +53,7 @@ this._overviewControls = []; this._markers = new Map(); - this._popoverHelper = new UI.PopoverHelper(this._cursorArea); - this._popoverHelper.initializeCallbacks( - this._getPopoverAnchor.bind(this), this._showPopover.bind(this), this._onHidePopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this._cursorArea, this._getPopoverRequest.bind(this)); this._popoverHelper.setHasPadding(true); this._popoverHelper.setTimeout(0); @@ -67,42 +65,27 @@ } /** - * @param {!Element} element * @param {!Event} event - * @return {!Element|!AnchorBox|undefined} + * @return {?UI.PopoverRequest} */ - _getPopoverAnchor(element, event) { - return this._cursorArea; - } - - /** - * @param {!Element|!AnchorBox} anchor - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showPopover(anchor, popover) { - return this._buildPopoverContents().then(maybeShowPopover.bind(this)); - - /** - * @this {PerfUI.TimelineOverviewPane} - * @param {!DocumentFragment} fragment - * @return {boolean} - */ - function maybeShowPopover(fragment) { - if (!fragment.firstChild) - return false; - var content = new PerfUI.TimelineOverviewPane.PopoverContents(); - this._popoverContents = content.contentElement.createChild('div'); - this._popoverContents.appendChild(fragment); - this._popover = popover; - content.show(popover.contentElement); - return true; - } - } - - _onHidePopover() { - this._popover = null; - this._popoverContents = null; + _getPopoverRequest(event) { + return { + box: this._cursorElement.boxInWindow(), + show: popover => this._buildPopoverContents().then(fragment => { + if (!fragment.firstChild) + return false; + var content = new PerfUI.TimelineOverviewPane.PopoverContents(); + this._popoverContents = content.contentElement.createChild('div'); + this._popoverContents.appendChild(fragment); + this._popover = popover; + content.show(popover.contentElement); + return true; + }), + hide: () => { + this._popover = null; + this._popoverContents = null; + } + }; } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js index 6ded00de..fe1ff3e 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js
@@ -133,10 +133,10 @@ /** * @param {!SDK.Target} target - * @param {function(!SDK.RemoteObject)} callback * @param {string} objectGroupName + * @return {!Promise<!SDK.RemoteObject>} */ - queryObjectContent(target, callback, objectGroupName) { + queryObjectContent(target, objectGroupName) { } /** @@ -605,15 +605,18 @@ /** * @override * @param {!SDK.Target} target - * @param {function(!SDK.RemoteObject)} callback * @param {string} objectGroupName + * @return {!Promise<!SDK.RemoteObject>} */ - queryObjectContent(target, callback, objectGroupName) { + queryObjectContent(target, objectGroupName) { + var fulfill; + var promise = new Promise(x => fulfill = x); + /** * @param {?SDK.RemoteObject} object */ function onResult(object) { - callback( + fulfill( object || target.runtimeModel.createRemoteObjectFromPrimitiveValue(Common.UIString('Preview is not available'))); } @@ -625,6 +628,7 @@ onResult(null); else heapProfilerModel.objectForSnapshotObjectId(String(this.snapshotNodeId), objectGroupName).then(onResult); + return promise; } updateHasChildren() {
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js index 95e833e..32551e390 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
@@ -153,9 +153,8 @@ this._selectedSizeText = new UI.ToolbarText(); - this._popoverHelper = new UI.PopoverHelper(this.element, true); - this._popoverHelper.initializeCallbacks( - this._getHoverAnchor.bind(this), this._showObjectPopover.bind(this), this._onHidePopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this.element, this._getPopoverRequest.bind(this)); + this._popoverHelper.setDisableOnClick(true); this._popoverHelper.setHasPadding(true); this.element.addEventListener('scroll', this._popoverHelper.hidePopover.bind(this._popoverHelper), true); @@ -607,58 +606,36 @@ } } - _getHoverAnchor(target) { - var span = target.enclosingNodeOrSelfWithNodeName('span'); - if (!span) - return; - var row = target.enclosingNodeOrSelfWithNodeName('tr'); - if (!row) - return; - span.node = row._dataGridNode; - return span; - } - /** - * @param {!Element|!AnchorBox} element - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} + * @param {!Event} event + * @return {?UI.PopoverRequest} */ - _showObjectPopover(element, popover) { - if (!this._profile.target() || !element.node) - return Promise.resolve(false); - - var fulfill; - var promise = new Promise(x => fulfill = x); - element.node.queryObjectContent(this._profile.target(), onObjectResolved.bind(this), 'popover'); - return promise; - - /** - * @param {?SDK.RemoteObject} result - * @this {Profiler.HeapSnapshotView} - */ - function onObjectResolved(result) { - if (!result) { - fulfill(false); - return; - } - ObjectUI.ObjectPopoverHelper.buildObjectPopover(result, popover).then(objectPopoverHelper => { + _getPopoverRequest(event) { + var span = event.target.enclosingNodeOrSelfWithNodeName('span'); + var row = event.target.enclosingNodeOrSelfWithNodeName('tr'); + var target = this._profile.target(); + if (!row || !span || !target) + return null; + var node = row._dataGridNode; + var objectPopoverHelper; + return { + box: span.boxInWindow(), + show: async popover => { + var remoteObject = await node.queryObjectContent(target, 'popover'); + if (!remoteObject) + return false; + objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopover(remoteObject, popover); if (!objectPopoverHelper) { - this._onHidePopover(); // Cleanup object resolving artifacts. - fulfill(false); - return; + target.runtimeModel.releaseObjectGroup('popover'); + return false; } - this._objectPopoverHelper = objectPopoverHelper; - fulfill(true); - }); - } - } - - _onHidePopover() { - if (this._objectPopoverHelper) { - this._objectPopoverHelper.dispose(); - delete this._objectPopoverHelper; - } - this._profile.target().runtimeModel.releaseObjectGroup('popover'); + return true; + }, + hide: () => { + target.runtimeModel.releaseObjectGroup('popover'); + objectPopoverHelper.dispose(); + } + }; } _updatePerspectiveOptions() {
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js index 9646937..b31fb71a 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSMetadata.js
@@ -252,6 +252,7 @@ 'border-top', 'border-top-color', 'box-shadow', + 'caret-color', 'color', 'column-rule', 'column-rule-color',
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index 078ee22c..5d6fcff 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -1185,6 +1185,36 @@ } /** + * @param {string} code + * @param {string} objectGroup + * @param {boolean} includeCommandLineAPI + * @param {boolean} silent + * @param {boolean} returnByValue + * @param {boolean} generatePreview + * @return {!Promise<?SDK.RemoteObject>} + */ + evaluatePromise(code, objectGroup, includeCommandLineAPI, silent, returnByValue, generatePreview) { + var fulfill; + var promise = new Promise(x => fulfill = x); + this.evaluate( + code, objectGroup, includeCommandLineAPI, silent, returnByValue, generatePreview, callback.bind(this)); + return promise; + + /** + * @param {?Protocol.Runtime.RemoteObject} result + * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails + * @param {string=} error + * @this {SDK.DebuggerModel.CallFrame} + */ + function callback(result, exceptionDetails, error) { + if (!result || exceptionDetails) + fulfill(null); + else + fulfill(this.debuggerModel._runtimeModel.createRemoteObject(result)); + } + } + + /** * @param {function(?Protocol.Error=)=} callback */ restart(callback) {
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js index 157f418..273c3a6 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityModel.js
@@ -108,4 +108,14 @@ securityState, schemeIsCryptographic, explanations, insecureContentStatus, summary || null); this._model.dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, pageSecurityState); } + + + /** + * @override + * @param {number} eventId + * @param {string} errorType + * @param {string} requestURL + */ + certificateError(eventId, errorType, requestURL) { + } };
diff --git a/third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js b/third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js index 33beb72..38935d66 100644 --- a/third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js +++ b/third_party/WebKit/Source/devtools/front_end/source_frame/UISourceCodeFrame.js
@@ -74,8 +74,7 @@ this._updateStyle(); this._updateDiffUISourceCode(); - this._errorPopoverHelper = new UI.PopoverHelper(this.element); - this._errorPopoverHelper.initializeCallbacks(this._getErrorAnchor.bind(this), this._showErrorPopover.bind(this)); + this._errorPopoverHelper = new UI.PopoverHelper(this.element, this._getErrorPopoverContent.bind(this)); this._errorPopoverHelper.setHasPadding(true); this._errorPopoverHelper.setTimeout(100, 100); @@ -401,33 +400,26 @@ } /** - * @param {!Element} target * @param {!Event} event - * @return {(!Element|undefined)} + * @return {?UI.PopoverRequest} */ - _getErrorAnchor(target, event) { - var element = target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') || - target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-wave'); + _getErrorPopoverContent(event) { + var element = event.target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') || + event.target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-wave'); if (!element) - return; - this._errorWavePopoverAnchor = new AnchorBox(event.clientX, event.clientY, 1, 1); - return element; - } - - /** - * @param {!Element|!AnchorBox} anchor - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showErrorPopover(anchor, popover) { - var element = /** @type {!Element} */ (anchor); - var messageBucket = element.enclosingNodeOrSelfWithClass('text-editor-line-decoration')._messageBucket; - var messagesOutline = messageBucket.messagesDescription(); - popover.setContentAnchorBox( - element.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ? element.boxInWindow() : - this._errorWavePopoverAnchor); - popover.contentElement.appendChild(messagesOutline); - return Promise.resolve(true); + return null; + var anchor = element.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ? + element.boxInWindow() : + new AnchorBox(event.clientX, event.clientY, 1, 1); + return { + box: anchor, + show: popover => { + var messageBucket = element.enclosingNodeOrSelfWithClass('text-editor-line-decoration')._messageBucket; + var messagesOutline = messageBucket.messagesDescription(); + popover.contentElement.appendChild(messagesOutline); + return Promise.resolve(true); + } + }; } _updateBucketDecorations() {
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js index 8cd68688..e76e19e 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -44,9 +44,8 @@ if (uiSourceCode.project().type() === Workspace.projectTypes.Debugger) this.element.classList.add('source-frame-debugger-script'); - this._popoverHelper = new UI.PopoverHelper(this._scriptsPanel.element, true); - this._popoverHelper.initializeCallbacks( - this._getPopoverAnchor.bind(this), this._showObjectPopover.bind(this), this._onHidePopover.bind(this)); + this._popoverHelper = new UI.PopoverHelper(this._scriptsPanel.element, this._getPopoverRequest.bind(this)); + this._popoverHelper.setDisableOnClick(true); this._popoverHelper.setTimeout(250, 250); this._popoverHelper.setHasPadding(true); this._scriptsPanel.element.addEventListener( @@ -376,150 +375,99 @@ return tokenType.startsWith('js-variable') || tokenType.startsWith('js-property') || tokenType === 'js-def'; } - _getPopoverAnchor(element, event) { + /** + * @param {!Event} event + * @return {?UI.PopoverRequest} + */ + _getPopoverRequest(event) { var target = UI.context.flavor(SDK.Target); var debuggerModel = target ? target.model(SDK.DebuggerModel) : null; if (!debuggerModel || !debuggerModel.isPaused()) - return; + return null; var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, event.y); if (!textPosition) - return; + return null; + var mouseLine = textPosition.startLine; var mouseColumn = textPosition.startColumn; var textSelection = this.textEditor.selection().normalize(); + var anchorBox; + var lineNumber; + var startHighlight; + var endHighlight; + if (textSelection && !textSelection.isEmpty()) { if (textSelection.startLine !== textSelection.endLine || textSelection.startLine !== mouseLine || mouseColumn < textSelection.startColumn || mouseColumn > textSelection.endColumn) - return; + return null; var leftCorner = this.textEditor.cursorPositionToCoordinates(textSelection.startLine, textSelection.startColumn); var rightCorner = this.textEditor.cursorPositionToCoordinates(textSelection.endLine, textSelection.endColumn); - var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); - anchorBox.highlight = { - lineNumber: textSelection.startLine, - startColumn: textSelection.startColumn, - endColumn: textSelection.endColumn - 1 - }; - anchorBox.forSelection = true; - return anchorBox; - } + anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); + lineNumber = textSelection.startLine; + startHighlight = textSelection.startColumn; + endHighlight = textSelection.endColumn - 1; + } else { + var token = this.textEditor.tokenAtTextPosition(textPosition.startLine, textPosition.startColumn); + if (!token || !token.type) + return null; + lineNumber = textPosition.startLine; + var line = this.textEditor.line(lineNumber); + var tokenContent = line.substring(token.startColumn, token.endColumn); - var token = this.textEditor.tokenAtTextPosition(textPosition.startLine, textPosition.startColumn); - if (!token || !token.type) - return; - var lineNumber = textPosition.startLine; - var line = this.textEditor.line(lineNumber); - var tokenContent = line.substring(token.startColumn, token.endColumn); + var isIdentifier = this._isIdentifier(token.type); + if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'this')) + return null; - var isIdentifier = this._isIdentifier(token.type); - if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'this')) - return; + var leftCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.startColumn); + var rightCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.endColumn - 1); + anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); - var leftCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.startColumn); - var rightCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.endColumn - 1); - var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); - - anchorBox.highlight = {lineNumber: lineNumber, startColumn: token.startColumn, endColumn: token.endColumn - 1}; - - return anchorBox; - } - - /** - * @param {!AnchorBox} anchorBox - * @return {!Promise<?SDK.RemoteObject>} - */ - _resolveObjectForPopover(anchorBox) { - var selectedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); - if (!selectedCallFrame) - return Promise.resolve(/** @type {?SDK.RemoteObject} */ (null)); - var lineNumber = anchorBox.highlight.lineNumber; - var startHighlight = anchorBox.highlight.startColumn; - var endHighlight = anchorBox.highlight.endColumn; - var line = this.textEditor.line(lineNumber); - if (!anchorBox.forSelection) { + startHighlight = token.startColumn; + endHighlight = token.endColumn - 1; while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.') { - var token = this.textEditor.tokenAtTextPosition(lineNumber, startHighlight - 2); - if (!token || !token.type) - return Promise.resolve(/** @type {?SDK.RemoteObject} */ (null)); - startHighlight = token.startColumn; + var tokenBefore = this.textEditor.tokenAtTextPosition(lineNumber, startHighlight - 2); + if (!tokenBefore || !tokenBefore.type) + return null; + startHighlight = tokenBefore.startColumn; } } - var evaluationText = line.substring(startHighlight, endHighlight + 1); - return Sources.SourceMapNamesResolver - .resolveExpression( - selectedCallFrame, evaluationText, this._debuggerSourceCode, lineNumber, startHighlight, endHighlight) - .then(onResolve.bind(this)); - /** - * @param {?string=} text - * @return {!Promise<?SDK.RemoteObject>} - * @this {Sources.JavaScriptSourceFrame} - */ - function onResolve(text) { - var fulfill; - var promise = new Promise(x => fulfill = x); - selectedCallFrame.evaluate( - text || evaluationText, 'popover', false, true, false, false, showObjectPopover.bind(this, fulfill)); - return promise; - } + var objectPopoverHelper; + var highlightDescriptor; - /** - * @param {function(?SDK.RemoteObject)} fulfill - * @param {?Protocol.Runtime.RemoteObject} result - * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails - * @this {Sources.JavaScriptSourceFrame} - */ - function showObjectPopover(fulfill, result, exceptionDetails) { - var target = UI.context.flavor(SDK.Target); - var potentiallyUpdatedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); - if (selectedCallFrame !== potentiallyUpdatedCallFrame || !result || exceptionDetails) { - fulfill(null); - return; - } - this._popoverAnchorBox = anchorBox; - this._popoverTarget = target; - var highlightRange = new Common.TextRange(lineNumber, startHighlight, lineNumber, endHighlight); - this._popoverAnchorBox._highlightDescriptor = - this.textEditor.highlightRange(highlightRange, 'source-frame-eval-expression'); - fulfill(target.runtimeModel.createRemoteObject(result)); - } - } - - /** - * @param {!AnchorBox|!Element} anchorBox - * @param {!UI.GlassPane} popover - * @return {!Promise<boolean>} - */ - _showObjectPopover(anchorBox, popover) { - return this._resolveObjectForPopover(/** @type {!AnchorBox} */ (anchorBox)).then(object => { - if (!object) - return false; - return ObjectUI.ObjectPopoverHelper.buildObjectPopover(object, popover).then(objectPopoverHelper => { - if (!objectPopoverHelper) { - this._onHidePopover(); // Cleanup artifacts from _resolveObjectForPopover. + return { + box: anchorBox, + show: async popover => { + var selectedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); + if (!selectedCallFrame) + return false; + var evaluationText = this.textEditor.line(lineNumber).substring(startHighlight, endHighlight + 1); + var resolvedText = await Sources.SourceMapNamesResolver.resolveExpression( + selectedCallFrame, evaluationText, this._debuggerSourceCode, lineNumber, startHighlight, endHighlight); + var remoteObject = await selectedCallFrame.evaluatePromise( + resolvedText || evaluationText, 'popover', false, true, false, false); + if (!remoteObject) + return false; + objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopover(remoteObject, popover); + var potentiallyUpdatedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); + if (!objectPopoverHelper || selectedCallFrame !== potentiallyUpdatedCallFrame) { + target.runtimeModel.releaseObjectGroup('popover'); + if (objectPopoverHelper) + objectPopoverHelper.dispose(); return false; } - this._objectPopoverHelper = objectPopoverHelper; + var highlightRange = new Common.TextRange(lineNumber, startHighlight, lineNumber, endHighlight); + highlightDescriptor = this.textEditor.highlightRange(highlightRange, 'source-frame-eval-expression'); return true; - }); - }); - } - - _onHidePopover() { - if (this._objectPopoverHelper) { - this._objectPopoverHelper.dispose(); - delete this._objectPopoverHelper; - } - if (this._popoverTarget) { - this._popoverTarget.runtimeModel.releaseObjectGroup('popover'); - delete this._popoverTarget; - } - if (this._popoverAnchorBox) { - if (this._popoverAnchorBox._highlightDescriptor) - this.textEditor.removeHighlight(this._popoverAnchorBox._highlightDescriptor); - delete this._popoverAnchorBox; - } + }, + hide: () => { + objectPopoverHelper.dispose(); + target.runtimeModel.releaseObjectGroup('popover'); + this.textEditor.removeHighlight(highlightDescriptor); + } + }; } _onKeyDown(event) {
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js index 614b5099..ee01b9a 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -694,7 +694,7 @@ var url = TimelineModel.TimelineData.forEvent(event).url; event[Timeline.TimelineUIUtils._previewElementSymbol] = await new Promise(fulfill => { if (url) - Components.DOMPresentationUtils.buildImagePreviewContents(target, url, false, fulfill); + Components.DOMPresentationUtils.buildImagePreviewContents(target, url, false).then(fulfill); else if (TimelineModel.TimelineData.forEvent(event).picture) Timeline.TimelineUIUtils.buildPicturePreviewContent(event, target, fulfill); else @@ -1131,13 +1131,15 @@ * @param {function(?Element)} fulfill */ function action(fulfill) { - Components.DOMPresentationUtils.buildImagePreviewContents( - /** @type {!SDK.Target} */ (target), request.url, false, saveImage); + Components.DOMPresentationUtils + .buildImagePreviewContents( + /** @type {!SDK.Target} */ (target), request.url, false) + .then(saveImage); /** - * @param {!Element=} element + * @param {?Element} element */ function saveImage(element) { - request.previewElement = element || null; + request.previewElement = element; fulfill(request.previewElement); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Popover.js b/third_party/WebKit/Source/devtools/front_end/ui/Popover.js index 5bc0a5f..e96c3d01 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/Popover.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/Popover.js
@@ -33,30 +33,23 @@ */ UI.PopoverHelper = class { /** - * @param {!Element} panelElement - * @param {boolean=} disableOnClick + * @param {!Element} container + * @param {function(!Event):?UI.PopoverRequest} getRequest */ - constructor(panelElement, disableOnClick) { - this._disableOnClick = !!disableOnClick; + constructor(container, getRequest) { + this._disableOnClick = false; this._hasPadding = false; - panelElement.addEventListener('mousedown', this._mouseDown.bind(this), false); - panelElement.addEventListener('mousemove', this._mouseMove.bind(this), false); - panelElement.addEventListener('mouseout', this._mouseOut.bind(this), false); + this._getRequest = getRequest; + this._scheduledRequest = null; + /** @type {?function()} */ + this._hidePopoverCallback = null; + container.addEventListener('mousedown', this._mouseDown.bind(this), false); + container.addEventListener('mousemove', this._mouseMove.bind(this), false); + container.addEventListener('mouseout', this._mouseOut.bind(this), false); this.setTimeout(1000, 500); } /** - * @param {function(!Element, !Event):(!Element|!AnchorBox|undefined)} getAnchor - * @param {function((!Element|!AnchorBox), !UI.GlassPane):!Promise<boolean>} showPopover - * @param {function()=} onHide - */ - initializeCallbacks(getAnchor, showPopover, onHide) { - this._getAnchor = getAnchor; - this._showPopover = showPopover; - this._onHide = onHide; - } - - /** * @param {number} timeout * @param {number=} hideTimeout */ @@ -76,147 +69,182 @@ } /** - * @param {!MouseEvent} event - * @return {boolean} + * @param {boolean} disableOnClick */ - _eventInHoverElement(event) { - if (!this._hoverElement) - return false; - var box = this._hoverElement instanceof AnchorBox ? this._hoverElement : this._hoverElement.boxInWindow(); - return ( - box.x <= event.clientX && event.clientX <= box.x + box.width && box.y <= event.clientY && - event.clientY <= box.y + box.height); + setDisableOnClick(disableOnClick) { + this._disableOnClick = disableOnClick; } + /** + * @param {!Event} event + * @return {boolean} + */ + _eventInScheduledContent(event) { + return this._scheduledRequest ? this._scheduledRequest.box.contains(event.clientX, event.clientY) : false; + } + + /** + * @param {!Event} event + */ _mouseDown(event) { - if (this._disableOnClick || !this._eventInHoverElement(event)) { + if (this._disableOnClick || !this._eventInScheduledContent(event)) { this.hidePopover(); } else { - this._killHidePopoverTimer(); - this._handleMouseAction(event, true); + this._stopHidePopoverTimer(); + this._stopShowPopoverTimer(); + this._startShowPopoverTimer(event, 0); } } + /** + * @param {!Event} event + */ _mouseMove(event) { // Pretend that nothing has happened. - if (this._eventInHoverElement(event)) + if (this._eventInScheduledContent(event)) return; this._startHidePopoverTimer(); - this._handleMouseAction(event, false); + this._stopShowPopoverTimer(); + if (event.which && this._disableOnClick) + return; + this._startShowPopoverTimer( + event, this.isPopoverVisible() ? Math.max(this._timeout * 0.6, this._hideTimeout) : this._timeout); } - _popoverMouseOut(event) { - if (!this.isPopoverVisible()) + /** + * @param {!Event} event + */ + _popoverMouseMove(event) { + this._stopHidePopoverTimer(); + } + + /** + * @param {!UI.GlassPane} popover + * @param {!Event} event + */ + _popoverMouseOut(popover, event) { + if (!popover.isShowing()) return; - if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this._popover.contentElement)) + if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(popover.contentElement)) this._startHidePopoverTimer(); } + /** + * @param {!Event} event + */ _mouseOut(event) { if (!this.isPopoverVisible()) return; - if (!this._eventInHoverElement(event)) + if (!this._eventInScheduledContent(event)) this._startHidePopoverTimer(); } _startHidePopoverTimer() { - // User has 500ms (this._hideTimeout) to reach the popup. - if (!this._popover || this._hidePopoverTimer) + // User has this._hideTimeout to reach the popup. + if (!this._hidePopoverCallback || this._hidePopoverTimer) return; - /** - * @this {UI.PopoverHelper} - */ - function doHide() { + this._hidePopoverTimer = setTimeout(() => { this._hidePopover(); delete this._hidePopoverTimer; - } - this._hidePopoverTimer = setTimeout(doHide.bind(this), this._hideTimeout); + }, this._hideTimeout); } - _handleMouseAction(event, isMouseDown) { - this._resetHoverTimer(); - if (event.which && this._disableOnClick) + /** + * @param {!Event} event + * @param {number} timeout + */ + _startShowPopoverTimer(event, timeout) { + this._scheduledRequest = this._getRequest.call(null, event); + if (!this._scheduledRequest) return; - this._hoverElement = this._getAnchor(event.target, event); - if (!this._hoverElement) - return; - const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout); - this._hoverTimer = - setTimeout(this._mouseHover.bind(this, this._hoverElement, event.target.ownerDocument), toolTipDelay); + + this._showPopoverTimer = setTimeout(() => { + delete this._showPopoverTimer; + this._showPopover(event.target.ownerDocument); + }, timeout); } - _resetHoverTimer() { - if (this._hoverTimer) { - clearTimeout(this._hoverTimer); - delete this._hoverTimer; - } + _stopShowPopoverTimer() { + if (!this._showPopoverTimer) + return; + clearTimeout(this._showPopoverTimer); + delete this._showPopoverTimer; } /** * @return {boolean} */ isPopoverVisible() { - return !!this._popover; + return !!this._hidePopoverCallback; } hidePopover() { - this._resetHoverTimer(); + this._stopShowPopoverTimer(); this._hidePopover(); } _hidePopover() { - if (!this._popover) + if (!this._hidePopoverCallback) return; - - delete UI.PopoverHelper._popover; - if (this._onHide) - this._onHide(); - - if (this._popover.isShowing()) - this._popover.hide(); - delete this._popover; - this._hoverElement = null; + this._hidePopoverCallback.call(null); + this._hidePopoverCallback = null; } - _mouseHover(element, document) { - delete this._hoverTimer; - this._hidePopover(); - this._hoverElement = element; + /** + * @param {!Document} document + */ + _showPopover(document) { + var popover = new UI.GlassPane(); + popover.registerRequiredCSS('ui/popover.css'); + popover.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent); + popover.setBlockPointerEvents(false); + popover.setShowArrow(true); + var request = this._scheduledRequest; + request.show.call(null, popover).then(success => { + if (!success) + return; - this._popover = new UI.GlassPane(); - this._popover.registerRequiredCSS('ui/popover.css'); - this._popover.setBlockPointerEvents(false); - this._popover.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent); - this._popover.setShowArrow(true); - this._popover.contentElement.classList.toggle('has-padding', this._hasPadding); - this._popover.contentElement.addEventListener('mousemove', this._killHidePopoverTimer.bind(this), true); - this._popover.contentElement.addEventListener('mouseout', this._popoverMouseOut.bind(this), true); - this._popover.setContentAnchorBox( - this._hoverElement instanceof AnchorBox ? this._hoverElement : this._hoverElement.boxInWindow()); + if (this._scheduledRequest !== request) { + if (request.hide) + request.hide.call(null); + return; + } - // This should not happen, but we hide previous popover to be on the safe side. - if (UI.PopoverHelper._popover) { - console.error('One popover is already visible'); - UI.PopoverHelper._popover.hide(); - } - UI.PopoverHelper._popover = this._popover; - var popover = this._popover; - this._showPopover(element, this._popover).then(success => { - if (success && this._popover === popover && this._hoverElement === element) - popover.show(document); + // This should not happen, but we hide previous popover to be on the safe side. + if (UI.PopoverHelper._popoverHelper) { + console.error('One popover is already visible'); + UI.PopoverHelper._popoverHelper.hidePopover(); + } + UI.PopoverHelper._popoverHelper = this; + + popover.contentElement.classList.toggle('has-padding', this._hasPadding); + popover.contentElement.addEventListener('mousemove', this._popoverMouseMove.bind(this), true); + popover.contentElement.addEventListener('mouseout', this._popoverMouseOut.bind(this, popover), true); + popover.setContentAnchorBox(request.box); + popover.show(document); + + this._hidePopoverCallback = () => { + if (request.hide) + request.hide.call(null); + popover.hide(); + delete UI.PopoverHelper._popoverHelper; + }; }); } - _killHidePopoverTimer() { - if (this._hidePopoverTimer) { - clearTimeout(this._hidePopoverTimer); - delete this._hidePopoverTimer; + _stopHidePopoverTimer() { + if (!this._hidePopoverTimer) + return; + clearTimeout(this._hidePopoverTimer); + delete this._hidePopoverTimer; - // We know that we reached the popup, but we might have moved over other elements. - // Discard pending command. - this._resetHoverTimer(); - } + // We know that we reached the popup, but we might have moved over other elements. + // Discard pending command. + this._stopShowPopoverTimer(); } }; + +/** @typedef {{box: !AnchorBox, show:(function(!UI.GlassPane):!Promise<boolean>), hide:(function()|undefined)}} */ +UI.PopoverRequest;
diff --git a/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.idl b/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.idl index 6aa0ce7..1d2f914 100644 --- a/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.idl +++ b/third_party/WebKit/Source/modules/installedapp/NavigatorInstalledApp.idl
@@ -8,5 +8,5 @@ [ RuntimeEnabled=InstalledApp, ] partial interface Navigator { - [SecureContext, CallWith=ScriptState] Promise<RelatedApplication> getInstalledRelatedApps(); + [SecureContext, CallWith=ScriptState, Measure] Promise<RelatedApplication> getInstalledRelatedApps(); };
diff --git a/third_party/WebKit/Source/modules/shapedetection/BUILD.gn b/third_party/WebKit/Source/modules/shapedetection/BUILD.gn index 8102c764..663f27599 100644 --- a/third_party/WebKit/Source/modules/shapedetection/BUILD.gn +++ b/third_party/WebKit/Source/modules/shapedetection/BUILD.gn
@@ -24,5 +24,6 @@ public_deps = [ "//services/shape_detection/public/interfaces:interfaces_blink", + "//skia/public/interfaces:interfaces_blink", ] }
diff --git a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp index a78d39b..6e9abeb 100644 --- a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp
@@ -26,11 +26,8 @@ wrapWeakPersistent(this)))); } -ScriptPromise BarcodeDetector::doDetect( - ScriptPromiseResolver* resolver, - mojo::ScopedSharedBufferHandle sharedBufferHandle, - int imageWidth, - int imageHeight) { +ScriptPromise BarcodeDetector::doDetect(ScriptPromiseResolver* resolver, + skia::mojom::blink::BitmapPtr bitmap) { ScriptPromise promise = resolver->promise(); if (!m_barcodeService) { resolver->reject(DOMException::create( @@ -39,10 +36,9 @@ } m_barcodeServiceRequests.insert(resolver); m_barcodeService->Detect( - std::move(sharedBufferHandle), imageWidth, imageHeight, - convertToBaseCallback(WTF::bind(&BarcodeDetector::onDetectBarcodes, - wrapPersistent(this), - wrapPersistent(resolver)))); + std::move(bitmap), convertToBaseCallback(WTF::bind( + &BarcodeDetector::onDetectBarcodes, + wrapPersistent(this), wrapPersistent(resolver)))); return promise; }
diff --git a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h index 2d0e5986..7e3fa4af8 100644 --- a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h +++ b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.h
@@ -29,9 +29,7 @@ ~BarcodeDetector() override = default; ScriptPromise doDetect(ScriptPromiseResolver*, - mojo::ScopedSharedBufferHandle, - int imageWidth, - int imageHeight) override; + skia::mojom::blink::BitmapPtr) override; void onDetectBarcodes( ScriptPromiseResolver*, Vector<shape_detection::mojom::blink::BarcodeDetectionResultPtr>);
diff --git a/third_party/WebKit/Source/modules/shapedetection/DEPS b/third_party/WebKit/Source/modules/shapedetection/DEPS index 372894a..76ba38ac 100644 --- a/third_party/WebKit/Source/modules/shapedetection/DEPS +++ b/third_party/WebKit/Source/modules/shapedetection/DEPS
@@ -10,6 +10,7 @@ "+platform", "+public/platform", "+services/shape_detection", + "+skia/public/interfaces/bitmap.mojom-blink.h", "+third_party/skia/include/core/SkImage.h", "+third_party/skia/include/core/SkImageInfo.h", "+ui/gfx/geometry",
diff --git a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp index 8593617..ca0b77b8 100644 --- a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
@@ -35,11 +35,8 @@ &FaceDetector::onFaceServiceConnectionError, wrapWeakPersistent(this)))); } -ScriptPromise FaceDetector::doDetect( - ScriptPromiseResolver* resolver, - mojo::ScopedSharedBufferHandle sharedBufferHandle, - int imageWidth, - int imageHeight) { +ScriptPromise FaceDetector::doDetect(ScriptPromiseResolver* resolver, + skia::mojom::blink::BitmapPtr bitmap) { ScriptPromise promise = resolver->promise(); if (!m_faceService) { resolver->reject(DOMException::create( @@ -47,7 +44,7 @@ return promise; } m_faceServiceRequests.insert(resolver); - m_faceService->Detect(std::move(sharedBufferHandle), imageWidth, imageHeight, + m_faceService->Detect(std::move(bitmap), convertToBaseCallback(WTF::bind( &FaceDetector::onDetectFaces, wrapPersistent(this), wrapPersistent(resolver))));
diff --git a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h index 84f6b9f..2047879c 100644 --- a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h +++ b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.h
@@ -31,9 +31,7 @@ ~FaceDetector() override = default; ScriptPromise doDetect(ScriptPromiseResolver*, - mojo::ScopedSharedBufferHandle, - int imageWidth, - int imageHeight) override; + skia::mojom::blink::BitmapPtr) override; void onDetectFaces(ScriptPromiseResolver*, shape_detection::mojom::blink::FaceDetectionResultPtr); void onFaceServiceConnectionError();
diff --git a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp index fd3119d..259193e 100644 --- a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.cpp
@@ -22,28 +22,19 @@ namespace { -mojo::ScopedSharedBufferHandle getSharedBufferOnData( - ScriptPromiseResolver* resolver, - uint8_t* data, - int size) { - DCHECK(data); - DCHECK(size); - ScriptPromise promise = resolver->promise(); +skia::mojom::blink::BitmapPtr createBitmapFromData(int width, + int height, + Vector<uint8_t> bitmapData) { + skia::mojom::blink::BitmapPtr bitmap = skia::mojom::blink::Bitmap::New(); - mojo::ScopedSharedBufferHandle sharedBufferHandle = - mojo::SharedBufferHandle::Create(size); - if (!sharedBufferHandle->is_valid()) { - resolver->reject( - DOMException::create(InvalidStateError, "Internal allocation error")); - return sharedBufferHandle; - } + bitmap->color_type = (kN32_SkColorType == kRGBA_8888_SkColorType) + ? skia::mojom::ColorType::RGBA_8888 + : skia::mojom::ColorType::BGRA_8888; + bitmap->width = width; + bitmap->height = height; + bitmap->pixel_data = std::move(bitmapData); - const mojo::ScopedSharedBufferMapping mappedBuffer = - sharedBufferHandle->Map(size); - DCHECK(mappedBuffer.get()); - memcpy(mappedBuffer.get(), data, size); - - return sharedBufferHandle; + return bitmap; } } // anonymous namespace @@ -134,13 +125,13 @@ return promise; } - mojo::ScopedSharedBufferHandle sharedBufferHandle = getSharedBufferOnData( - resolver, pixelDataPtr, allocationSize.ValueOrDefault(0)); - if (!sharedBufferHandle->is_valid()) - return promise; + WTF::Vector<uint8_t> bitmapData; + bitmapData.append(pixelDataPtr, + static_cast<int>(allocationSize.ValueOrDefault(0))); - return doDetect(resolver, std::move(sharedBufferHandle), image->width(), - image->height()); + return doDetect(resolver, + createBitmapFromData(image->width(), image->height(), + std::move(bitmapData))); } ScriptPromise ShapeDetector::detectShapesOnImageData( @@ -155,14 +146,12 @@ uint8_t* const data = imageData->data()->data(); WTF::CheckedNumeric<int> allocationSize = imageData->size().area() * 4; + WTF::Vector<uint8_t> bitmapData; + bitmapData.append(data, static_cast<int>(allocationSize.ValueOrDefault(0))); - mojo::ScopedSharedBufferHandle sharedBufferHandle = - getSharedBufferOnData(resolver, data, allocationSize.ValueOrDefault(0)); - if (!sharedBufferHandle->is_valid()) - return promise; - - return doDetect(resolver, std::move(sharedBufferHandle), imageData->width(), - imageData->height()); + return doDetect(resolver, + createBitmapFromData(imageData->width(), imageData->height(), + std::move(bitmapData))); } ScriptPromise ShapeDetector::detectShapesOnImageElement( @@ -201,26 +190,10 @@ const SkImageInfo skiaInfo = SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType()); + size_t rowBytes = skiaInfo.minRowBytes(); - const uint32_t allocationSize = skiaInfo.getSafeSize(skiaInfo.minRowBytes()); - - mojo::ScopedSharedBufferHandle sharedBufferHandle = - mojo::SharedBufferHandle::Create(allocationSize); - if (!sharedBufferHandle.is_valid()) { - DLOG(ERROR) << "Requested allocation : " << allocationSize - << "B, larger than |mojo::edk::kMaxSharedBufferSize| == 16MB "; - // TODO(xianglu): For now we reject the promise if the image is too large. - // But consider resizing the image to remove restriction on the user side. - // Also, add LayoutTests for this case later. - resolver->reject( - DOMException::create(InvalidStateError, "Image exceeds size limit.")); - return promise; - } - - const mojo::ScopedSharedBufferMapping mappedBuffer = - sharedBufferHandle->Map(allocationSize); - - const SkPixmap pixmap(skiaInfo, mappedBuffer.get(), skiaInfo.minRowBytes()); + Vector<uint8_t> bitmapData(skiaInfo.getSafeSize(rowBytes)); + const SkPixmap pixmap(skiaInfo, bitmapData.data(), rowBytes); if (!image->readPixels(pixmap, 0, 0)) { resolver->reject(DOMException::create( InvalidStateError, @@ -228,8 +201,9 @@ return promise; } - return doDetect(resolver, std::move(sharedBufferHandle), img->naturalWidth(), - img->naturalHeight()); + return doDetect( + resolver, createBitmapFromData(img->naturalWidth(), img->naturalHeight(), + std::move(bitmapData))); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h index 74b8e70e..cd55e5cc 100644 --- a/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h +++ b/third_party/WebKit/Source/modules/shapedetection/ShapeDetector.h
@@ -10,6 +10,7 @@ #include "core/imagebitmap/ImageBitmapFactories.h" #include "modules/ModulesExport.h" #include "modules/canvas2d/CanvasRenderingContext2D.h" +#include "skia/public/interfaces/bitmap.mojom-blink.h" namespace blink { @@ -27,9 +28,7 @@ const HTMLImageElement*); virtual ScriptPromise doDetect(ScriptPromiseResolver*, - mojo::ScopedSharedBufferHandle, - int imageWidth, - int imageHeight) = 0; + skia::mojom::blink::BitmapPtr) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp index 1b365ac..5b845570 100644 --- a/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp
@@ -24,11 +24,8 @@ &TextDetector::onTextServiceConnectionError, wrapWeakPersistent(this)))); } -ScriptPromise TextDetector::doDetect( - ScriptPromiseResolver* resolver, - mojo::ScopedSharedBufferHandle sharedBufferHandle, - int imageWidth, - int imageHeight) { +ScriptPromise TextDetector::doDetect(ScriptPromiseResolver* resolver, + skia::mojom::blink::BitmapPtr bitmap) { ScriptPromise promise = resolver->promise(); if (!m_textService) { resolver->reject(DOMException::create( @@ -36,7 +33,7 @@ return promise; } m_textServiceRequests.insert(resolver); - m_textService->Detect(std::move(sharedBufferHandle), imageWidth, imageHeight, + m_textService->Detect(std::move(bitmap), convertToBaseCallback(WTF::bind( &TextDetector::onDetectText, wrapPersistent(this), wrapPersistent(resolver))));
diff --git a/third_party/WebKit/Source/modules/shapedetection/TextDetector.h b/third_party/WebKit/Source/modules/shapedetection/TextDetector.h index 64791e3..800893c 100644 --- a/third_party/WebKit/Source/modules/shapedetection/TextDetector.h +++ b/third_party/WebKit/Source/modules/shapedetection/TextDetector.h
@@ -29,9 +29,7 @@ ~TextDetector() override = default; ScriptPromise doDetect(ScriptPromiseResolver*, - mojo::ScopedSharedBufferHandle, - int imageWidth, - int imageHeight) override; + skia::mojom::blink::BitmapPtr) override; void onDetectText( ScriptPromiseResolver*, Vector<shape_detection::mojom::blink::TextDetectionResultPtr>);
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp index f208ee6..0b78131 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -90,6 +90,7 @@ OfflineAudioContext* audioContext = new OfflineAudioContext( document, numberOfChannels, numberOfFrames, sampleRate, exceptionState); + audioContext->suspendIfNeeded(); if (!audioContext->destination()) { exceptionState.throwDOMException( @@ -123,7 +124,6 @@ offlineContextLengthHistogram.count(numberOfFrames); offlineContextSampleRateHistogram.count(sampleRate); - audioContext->suspendIfNeeded(); return audioContext; }
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestinationConsumer.h b/third_party/WebKit/Source/platform/audio/AudioDestinationConsumer.h index 99c2b5f..849fef2 100644 --- a/third_party/WebKit/Source/platform/audio/AudioDestinationConsumer.h +++ b/third_party/WebKit/Source/platform/audio/AudioDestinationConsumer.h
@@ -31,20 +31,17 @@ #ifndef AudioDestinationConsumer_h #define AudioDestinationConsumer_h +#include <memory> #include "platform/PlatformExport.h" -#include "platform/heap/Handle.h" namespace blink { class AudioBus; -class PLATFORM_EXPORT AudioDestinationConsumer - : public GarbageCollected<AudioDestinationConsumer> { +class PLATFORM_EXPORT AudioDestinationConsumer { public: virtual void setFormat(size_t numberOfChannels, float sampleRate) = 0; virtual void consumeAudio(AudioBus*, size_t numberOfFrames) = 0; - - DEFINE_INLINE_VIRTUAL_TRACE() {} }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp b/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp index 56e5e5a70..5e19c39 100644 --- a/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp +++ b/third_party/WebKit/Source/platform/exported/WebMediaStreamSource.cpp
@@ -148,6 +148,8 @@ } class ConsumerWrapper final : public AudioDestinationConsumer { + USING_FAST_MALLOC(ConsumerWrapper); + public: static ConsumerWrapper* create(WebAudioDestinationConsumer* consumer) { return new ConsumerWrapper(consumer); @@ -196,12 +198,10 @@ ASSERT(isMainThread()); ASSERT(!m_private.isNull() && consumer); - const HeapHashSet<Member<AudioDestinationConsumer>>& consumers = + const HashSet<AudioDestinationConsumer*>& consumers = m_private->audioConsumers(); - for (HeapHashSet<Member<AudioDestinationConsumer>>::const_iterator it = - consumers.begin(); - it != consumers.end(); ++it) { - ConsumerWrapper* wrapper = static_cast<ConsumerWrapper*>(it->get()); + for (AudioDestinationConsumer* it : consumers) { + ConsumerWrapper* wrapper = static_cast<ConsumerWrapper*>(it); if (wrapper->consumer() == consumer) { m_private->removeAudioConsumer(wrapper); return true;
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp index fe6021b24..ca12e1c 100644 --- a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp +++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.cpp
@@ -85,8 +85,7 @@ AudioDestinationConsumer* consumer) { ASSERT(m_requiresConsumer); MutexLocker locker(m_audioConsumersLock); - HeapHashSet<Member<AudioDestinationConsumer>>::iterator it = - m_audioConsumers.find(consumer); + auto it = m_audioConsumers.find(consumer); if (it == m_audioConsumers.end()) return false; m_audioConsumers.erase(it); @@ -101,10 +100,8 @@ float sampleRate) { ASSERT(m_requiresConsumer); MutexLocker locker(m_audioConsumersLock); - for (HeapHashSet<Member<AudioDestinationConsumer>>::iterator it = - m_audioConsumers.begin(); - it != m_audioConsumers.end(); ++it) - (*it)->setFormat(numberOfChannels, sampleRate); + for (AudioDestinationConsumer* consumer : m_audioConsumers) + consumer->setFormat(numberOfChannels, sampleRate); } void MediaStreamSource::consumeAudio(AudioBus* bus, size_t numberOfFrames) { @@ -113,15 +110,12 @@ // Prevent GCs from going ahead while this iteration runs, attempting to // pinpoint crbug.com/682945 failures. ThreadState::MainThreadGCForbiddenScope scope; - for (HeapHashSet<Member<AudioDestinationConsumer>>::iterator it = - m_audioConsumers.begin(); - it != m_audioConsumers.end(); ++it) - (*it)->consumeAudio(bus, numberOfFrames); + for (AudioDestinationConsumer* consumer : m_audioConsumers) + consumer->consumeAudio(bus, numberOfFrames); } DEFINE_TRACE(MediaStreamSource) { visitor->trace(m_observers); - visitor->trace(m_audioConsumers); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h index d05fc45e6..e41f74b 100644 --- a/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h +++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamSource.h
@@ -102,7 +102,7 @@ bool requiresAudioConsumer() const { return m_requiresConsumer; } void addAudioConsumer(AudioDestinationConsumer*); bool removeAudioConsumer(AudioDestinationConsumer*); - const HeapHashSet<Member<AudioDestinationConsumer>>& audioConsumers() { + const HashSet<AudioDestinationConsumer*>& audioConsumers() { return m_audioConsumers; } @@ -126,7 +126,7 @@ bool m_requiresConsumer; HeapHashSet<WeakMember<Observer>> m_observers; Mutex m_audioConsumersLock; - HeapHashSet<Member<AudioDestinationConsumer>> m_audioConsumers; + HashSet<AudioDestinationConsumer*> m_audioConsumers; std::unique_ptr<ExtraData> m_extraData; WebMediaConstraints m_constraints; };
diff --git a/third_party/WebKit/Source/wtf/Assertions.cpp b/third_party/WebKit/Source/platform/wtf/Assertions.cpp similarity index 97% rename from third_party/WebKit/Source/wtf/Assertions.cpp rename to third_party/WebKit/Source/platform/wtf/Assertions.cpp index 26ba322..ddcd361a 100644 --- a/third_party/WebKit/Source/wtf/Assertions.cpp +++ b/third_party/WebKit/Source/platform/wtf/Assertions.cpp
@@ -32,12 +32,12 @@ // we need to place this directive before any data or functions are defined. #pragma GCC diagnostic ignored "-Wmissing-format-attribute" -#include "wtf/Assertions.h" +#include "platform/wtf/Assertions.h" -#include "wtf/Compiler.h" -#include "wtf/PtrUtil.h" -#include "wtf/ThreadSpecific.h" -#include "wtf/Threading.h" +#include "platform/wtf/Compiler.h" +#include "platform/wtf/PtrUtil.h" +#include "platform/wtf/ThreadSpecific.h" +#include "platform/wtf/Threading.h" #include <memory> #include <stdarg.h> #include <stdio.h>
diff --git a/third_party/WebKit/Source/platform/wtf/BUILD.gn b/third_party/WebKit/Source/platform/wtf/BUILD.gn index 10ef3960..0aaac6d 100644 --- a/third_party/WebKit/Source/platform/wtf/BUILD.gn +++ b/third_party/WebKit/Source/platform/wtf/BUILD.gn
@@ -64,6 +64,7 @@ "AddressSanitizer.h", "Alignment.h", "Allocator.h", + "Assertions.cpp", "Assertions.h", "Atomics.h", "AutoReset.h", @@ -81,21 +82,38 @@ "DynamicAnnotations.cpp", "DynamicAnnotations.h", "Forward.h", + "Functional.h", "GetPtr.h", + "HashTableDeletedValueType.h", + "InstanceCounter.h", "LeakAnnotations.h", + "Locker.h", "NonCopyingSort.h", "Noncopyable.h", "NotFound.h", "Optional.h", + "PassRefPtr.h", + "PtrUtil.h", + "RefCounted.h", + "RefPtr.h", "SizeAssertions.h", "SpinLock.h", + "StackUtil.h", "StaticConstructors.h", + "StdLibExtras.h", "StringExtras.h", + "ThreadRestrictionVerifier.h", + "ThreadSafeRefCounted.h", + "ThreadSpecific.h", + "Threading.h", + "ThreadingPrimitives.h", "Time.h", + "TreeNode.h", "TriState.h", "TypeTraits.h", "WTF.h", "WTFExport.h", + "WeakPtr.h", "allocator/PartitionAllocator.cpp", "allocator/PartitionAllocator.h", "allocator/Partitions.cpp",
diff --git a/third_party/WebKit/Source/platform/wtf/Functional.h b/third_party/WebKit/Source/platform/wtf/Functional.h new file mode 100644 index 0000000..a6f1cb3 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/Functional.h
@@ -0,0 +1,300 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_Functional_h +#define WTF_Functional_h + +#include "base/bind.h" +#include "base/threading/thread_checker.h" +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Assertions.h" +#include "platform/wtf/PassRefPtr.h" +#include "platform/wtf/PtrUtil.h" +#include "platform/wtf/RefPtr.h" +#include "platform/wtf/ThreadSafeRefCounted.h" +#include "platform/wtf/TypeTraits.h" +#include <utility> + +namespace blink { +template <typename T> +class Member; +template <typename T> +class WeakMember; +} + +namespace WTF { + +// Functional.h provides a very simple way to bind a function pointer and +// arguments together into a function object that can be stored, copied and +// invoked, similar to boost::bind and std::bind in C++11. + +// Thread Safety: +// +// WTF::bind() and WTF::Closure should be used for same-thread closures +// only, i.e. the closures must be created, executed and destructed on +// the same thread. +// Use crossThreadBind() and CrossThreadClosure if the function/task is called +// or destructed on a (potentially) different thread from the current thread. + +// WTF::bind() and move semantics +// ============================== +// +// For unbound parameters (arguments supplied later on the bound functor +// directly), there are two ways to pass movable arguments: +// +// 1) Pass by rvalue reference. +// +// void yourFunction(Argument&& argument) { ... } +// std::unique_ptr<Function<void(Argument&&)>> functor = +// bind<Argument&&>(yourFunction); +// +// 2) Pass by value. +// +// void yourFunction(Argument argument) { ... } +// std::unique_ptr<Function<void(Argument)>> functor = +// bind<Argument>(yourFunction); +// +// Note that with the latter there will be *two* move constructions happening, +// because there needs to be at least one intermediary function call taking an +// argument of type "Argument" (i.e. passed by value). The former case does not +// require any move constructions inbetween. +// +// For bound parameters (arguments supplied on the creation of a functor), you +// can move your argument into the internal storage of the functor by supplying +// an rvalue to that argument (this is done in wrap() of ParamStorageTraits). +// However, to make the functor be able to get called multiple times, the +// stored object does not get moved out automatically when the underlying +// function is actually invoked. If you want to make an argument "auto-passed", +// you can do so by wrapping your bound argument with WTF::passed() function, as +// shown below: +// +// void yourFunction(Argument argument) +// { +// // |argument| is passed from the internal storage of functor. +// ... +// } +// +// ... +// std::unique_ptr<Function<void()>> functor = bind(yourFunction, +// WTF::passed(Argument())); +// ... +// (*functor)(); +// +// The underlying function must receive the argument wrapped by WTF::passed() by +// rvalue reference or by value. +// +// Obviously, if you create a functor this way, you shouldn't call the functor +// twice or more; after the second call, the passed argument may be invalid. + +enum FunctionThreadAffinity { CrossThreadAffinity, SameThreadAffinity }; + +template <typename T> +class PassedWrapper final { + public: + explicit PassedWrapper(T&& scoper) : m_scoper(std::move(scoper)) {} + PassedWrapper(PassedWrapper&& other) : m_scoper(std::move(other.m_scoper)) {} + T moveOut() const { return std::move(m_scoper); } + + private: + mutable T m_scoper; +}; + +template <typename T> +PassedWrapper<T> passed(T&& value) { + static_assert( + !std::is_reference<T>::value, + "You must pass an rvalue to WTF::passed() so it can be moved. Add " + "std::move() if necessary."); + static_assert(!std::is_const<T>::value, + "|value| must not be const so it can be moved."); + return PassedWrapper<T>(std::move(value)); +} + +template <typename T, FunctionThreadAffinity threadAffinity> +class UnretainedWrapper final { + public: + explicit UnretainedWrapper(T* ptr) : m_ptr(ptr) {} + T* value() const { return m_ptr; } + + private: + T* m_ptr; +}; + +template <typename T> +UnretainedWrapper<T, SameThreadAffinity> unretained(T* value) { + static_assert(!WTF::IsGarbageCollectedType<T>::value, + "WTF::unretained() + GCed type is forbidden"); + return UnretainedWrapper<T, SameThreadAffinity>(value); +} + +template <typename T> +UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) { + static_assert(!WTF::IsGarbageCollectedType<T>::value, + "crossThreadUnretained() + GCed type is forbidden"); + return UnretainedWrapper<T, CrossThreadAffinity>(value); +} + +template <typename T> +struct ParamStorageTraits { + typedef T StorageType; + + static_assert(!std::is_pointer<T>::value, + "Raw pointers are not allowed to bind into WTF::Function. Wrap " + "it with either wrapPersistent, wrapWeakPersistent, " + "wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, " + "RefPtr or unretained."); + static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && + !IsSubclassOfTemplate<T, blink::WeakMember>::value, + "Member and WeakMember are not allowed to bind into " + "WTF::Function. Wrap it with either wrapPersistent, " + "wrapWeakPersistent, wrapCrossThreadPersistent or " + "wrapCrossThreadWeakPersistent."); +}; + +template <typename T> +struct ParamStorageTraits<PassRefPtr<T>> { + typedef RefPtr<T> StorageType; +}; + +template <typename T> +struct ParamStorageTraits<RefPtr<T>> { + typedef RefPtr<T> StorageType; +}; + +template <typename> +class RetainPtr; + +template <typename T> +struct ParamStorageTraits<RetainPtr<T>> { + typedef RetainPtr<T> StorageType; +}; + +template <typename T> +struct ParamStorageTraits<PassedWrapper<T>> { + typedef PassedWrapper<T> StorageType; +}; + +template <typename T, FunctionThreadAffinity threadAffinity> +struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { + typedef UnretainedWrapper<T, threadAffinity> StorageType; +}; + +template <typename Signature, + FunctionThreadAffinity threadAffinity = SameThreadAffinity> +class Function; + +template <typename R, typename... Args, FunctionThreadAffinity threadAffinity> +class Function<R(Args...), threadAffinity> { + USING_FAST_MALLOC(Function); + WTF_MAKE_NONCOPYABLE(Function); + + public: + Function(base::Callback<R(Args...)> callback) + : m_callback(std::move(callback)) {} + + ~Function() { DCHECK(m_threadChecker.CalledOnValidThread()); } + + R operator()(Args... args) { + DCHECK(m_threadChecker.CalledOnValidThread()); + return m_callback.Run(std::forward<Args>(args)...); + } + + bool isCancelled() const { return m_callback.IsCancelled(); } + + friend base::Callback<R(Args...)> convertToBaseCallback( + std::unique_ptr<Function> function) { + if (function) + return std::move(function->m_callback); + return base::Callback<R(Args...)>(); + } + + private: + using MaybeThreadChecker = + typename std::conditional<threadAffinity == SameThreadAffinity, + base::ThreadChecker, + base::ThreadCheckerDoNothing>::type; + MaybeThreadChecker m_threadChecker; + base::Callback<R(Args...)> m_callback; +}; + +template <FunctionThreadAffinity threadAffinity, + typename FunctionType, + typename... BoundParameters> +std::unique_ptr< + Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>, + threadAffinity>> +bindInternal(FunctionType function, BoundParameters&&... boundParameters) { + using UnboundRunType = + base::MakeUnboundRunType<FunctionType, BoundParameters...>; + return WTF::wrapUnique(new Function<UnboundRunType, + threadAffinity>(base::Bind( + function, + typename ParamStorageTraits<typename std::decay<BoundParameters>::type>:: + StorageType(std::forward<BoundParameters>(boundParameters))...))); +} + +template <typename FunctionType, typename... BoundParameters> +std::unique_ptr< + Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>, + SameThreadAffinity>> +bind(FunctionType function, BoundParameters&&... boundParameters) { + return bindInternal<SameThreadAffinity>( + function, std::forward<BoundParameters>(boundParameters)...); +} + +typedef Function<void(), SameThreadAffinity> Closure; +typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; + +} // namespace WTF + +namespace base { + +template <typename T> +struct BindUnwrapTraits<WTF::RefPtr<T>> { + static T* Unwrap(const WTF::RefPtr<T>& wrapped) { return wrapped.get(); } +}; + +template <typename T> +struct BindUnwrapTraits<WTF::PassedWrapper<T>> { + static T Unwrap(const WTF::PassedWrapper<T>& wrapped) { + return wrapped.moveOut(); + } +}; + +template <typename T, WTF::FunctionThreadAffinity threadAffinity> +struct BindUnwrapTraits<WTF::UnretainedWrapper<T, threadAffinity>> { + static T* Unwrap(const WTF::UnretainedWrapper<T, threadAffinity>& wrapped) { + return wrapped.value(); + } +}; + +} // namespace base + +using WTF::crossThreadUnretained; + +using WTF::Function; +using WTF::CrossThreadClosure; + +#endif // WTF_Functional_h
diff --git a/third_party/WebKit/Source/platform/wtf/HashTableDeletedValueType.h b/third_party/WebKit/Source/platform/wtf/HashTableDeletedValueType.h new file mode 100644 index 0000000..06b5e5e --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/HashTableDeletedValueType.h
@@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HashTableDeletedValueType_h +#define HashTableDeletedValueType_h + +namespace WTF { + +enum HashTableDeletedValueType { HashTableDeletedValue }; + +} // namespace WTF + +#endif // HashTableDeletedValueType_h
diff --git a/third_party/WebKit/Source/platform/wtf/InstanceCounter.h b/third_party/WebKit/Source/platform/wtf/InstanceCounter.h new file mode 100644 index 0000000..35db9a1 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/InstanceCounter.h
@@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef InstanceCounter_h +#define InstanceCounter_h + +#include "platform/wtf/TypeTraits.h" +#include "platform/wtf/WTFExport.h" +#include "platform/wtf/build_config.h" + +namespace WTF { + +class String; +WTF_EXPORT String dumpRefCountedInstanceCounts(); + +#if ENABLE(INSTANCE_COUNTER) +WTF_EXPORT void incrementInstanceCount(const char* stringWithTypeName, + void* ptr); +WTF_EXPORT void decrementInstanceCount(const char* stringWithTypeName, + void* ptr); + +WTF_EXPORT String extractTypeNameFromFunctionName(const char* funcName); + +template <typename T> +inline void incrementInstanceCount(T* p) { + incrementInstanceCount(getStringWithTypeName<T>(), p); +} + +template <typename T> +inline void decrementInstanceCount(T* p) { + decrementInstanceCount(getStringWithTypeName<T>(), p); +} + +#endif // ENABLE(INSTANCE_COUNTER) + +} // namespace WTF + +#endif
diff --git a/third_party/WebKit/Source/platform/wtf/Locker.h b/third_party/WebKit/Source/platform/wtf/Locker.h new file mode 100644 index 0000000..4d29807e --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/Locker.h
@@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef Locker_h +#define Locker_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Noncopyable.h" + +namespace WTF { + +template <typename T> +class Locker final { + STACK_ALLOCATED(); + WTF_MAKE_NONCOPYABLE(Locker); + + public: + Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); } + ~Locker() { m_lockable.unlock(); } + + private: + T& m_lockable; +}; + +} // namespace WTF + +using WTF::Locker; + +#endif
diff --git a/third_party/WebKit/Source/platform/wtf/PassRefPtr.h b/third_party/WebKit/Source/platform/wtf/PassRefPtr.h new file mode 100644 index 0000000..68a421e --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/PassRefPtr.h
@@ -0,0 +1,224 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +// PassRefPtr will soon be deleted. +// New code should instead pass ownership of the contents of a RefPtr using +// std::move(). + +#ifndef WTF_PassRefPtr_h +#define WTF_PassRefPtr_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Assertions.h" +#include "platform/wtf/Compiler.h" +#include "platform/wtf/TypeTraits.h" + +namespace WTF { + +template <typename T> +class RefPtr; +template <typename T> +class PassRefPtr; +template <typename T> +PassRefPtr<T> adoptRef(T*); + +inline void adopted(const void*) {} + +// requireAdoption() is not overloaded for WTF::RefCounted, which has a built-in +// assumption that adoption is required. requireAdoption() is for bootstrapping +// alternate reference count classes that are compatible with ReftPtr/PassRefPtr +// but cannot have adoption checks enabled by default, such as skia's +// SkRefCnt. The purpose of requireAdoption() is to enable adoption checks only +// once it is known that the object will be used with RefPtr/PassRefPtr. +inline void requireAdoption(const void*) {} + +template <typename T> +ALWAYS_INLINE void refIfNotNull(T* ptr) { + if (LIKELY(ptr != 0)) { + requireAdoption(ptr); + ptr->ref(); + } +} + +template <typename T> +ALWAYS_INLINE void derefIfNotNull(T* ptr) { + if (LIKELY(ptr != 0)) + ptr->deref(); +} + +template <typename T> +class PassRefPtr { + DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); + + public: + PassRefPtr() : m_ptr(nullptr) {} + PassRefPtr(std::nullptr_t) : m_ptr(nullptr) {} + PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } + PassRefPtr(PassRefPtr&& o) : m_ptr(o.leakRef()) {} + template <typename U> + PassRefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) + : m_ptr(o.leakRef()) {} + + ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } + + template <typename U> + PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T)); + template <typename U> + PassRefPtr(RefPtr<U>&&, EnsurePtrConvertibleArgDecl(U, T)); + + T* get() const { return m_ptr; } + + WARN_UNUSED_RESULT T* leakRef() const; + + T& operator*() const { return *m_ptr; } + T* operator->() const { return m_ptr; } + + bool operator!() const { return !m_ptr; } + explicit operator bool() const { return m_ptr != nullptr; } + + friend PassRefPtr adoptRef<T>(T*); + + private: + enum AdoptRefTag { AdoptRef }; + PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) {} + + PassRefPtr& operator=(const PassRefPtr&) { + static_assert(!sizeof(T*), "PassRefPtr should never be assigned to"); + return *this; + } + + mutable T* m_ptr; +}; + +template <typename T> +PassRefPtr<T> wrapPassRefPtr(T* ptr) { + return PassRefPtr<T>(ptr); +} + +template <typename T> +template <typename U> +inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, + EnsurePtrConvertibleArgDefn(U, T)) + : m_ptr(o.get()) { + T* ptr = m_ptr; + refIfNotNull(ptr); +} + +template <typename T> +template <typename U> +inline PassRefPtr<T>::PassRefPtr(RefPtr<U>&& o, + EnsurePtrConvertibleArgDefn(U, T)) + : m_ptr(o.leakRef()) {} + +template <typename T> +inline T* PassRefPtr<T>::leakRef() const { + T* ptr = m_ptr; + m_ptr = nullptr; + return ptr; +} + +template <typename T, typename U> +inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) { + return a.get() == b.get(); +} + +template <typename T, typename U> +inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) { + return a.get() == b.get(); +} + +template <typename T, typename U> +inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) { + return a.get() == b.get(); +} + +template <typename T, typename U> +inline bool operator==(const PassRefPtr<T>& a, U* b) { + return a.get() == b; +} + +template <typename T, typename U> +inline bool operator==(T* a, const PassRefPtr<U>& b) { + return a == b.get(); +} + +template <typename T> +inline bool operator==(const PassRefPtr<T>& a, std::nullptr_t) { + return !a.get(); +} + +template <typename T> +inline bool operator==(std::nullptr_t, const PassRefPtr<T>& b) { + return !b.get(); +} + +template <typename T, typename U> +inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) { + return a.get() != b.get(); +} + +template <typename T, typename U> +inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) { + return a.get() != b.get(); +} + +template <typename T, typename U> +inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) { + return a.get() != b.get(); +} + +template <typename T, typename U> +inline bool operator!=(const PassRefPtr<T>& a, U* b) { + return a.get() != b; +} + +template <typename T, typename U> +inline bool operator!=(T* a, const PassRefPtr<U>& b) { + return a != b.get(); +} + +template <typename T> +inline bool operator!=(const PassRefPtr<T>& a, std::nullptr_t) { + return a.get(); +} + +template <typename T> +inline bool operator!=(std::nullptr_t, const PassRefPtr<T>& b) { + return b.get(); +} + +template <typename T> +PassRefPtr<T> adoptRef(T* p) { + adopted(p); + return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef); +} + +template <typename T> +inline T* getPtr(const PassRefPtr<T>& p) { + return p.get(); +} + +} // namespace WTF + +using WTF::PassRefPtr; +using WTF::adoptRef; + +#endif // WTF_PassRefPtr_h
diff --git a/third_party/WebKit/Source/platform/wtf/PtrUtil.h b/third_party/WebKit/Source/platform/wtf/PtrUtil.h new file mode 100644 index 0000000..57ba0a8 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/PtrUtil.h
@@ -0,0 +1,53 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PtrUtil_h +#define PtrUtil_h + +#include "base/memory/ptr_util.h" +#include "platform/wtf/TypeTraits.h" + +#include <memory> + +namespace WTF { + +template <typename T> +std::unique_ptr<T> wrapUnique(T* ptr) { + static_assert( + !WTF::IsGarbageCollectedType<T>::value, + "Garbage collected types should not be stored in std::unique_ptr!"); + return std::unique_ptr<T>(ptr); +} + +template <typename T> +std::unique_ptr<T[]> wrapArrayUnique(T* ptr) { + static_assert( + !WTF::IsGarbageCollectedType<T>::value, + "Garbage collected types should not be stored in std::unique_ptr!"); + return std::unique_ptr<T[]>(ptr); +} + +// WTF::makeUnique is base::MakeUnique. See base/ptr_util.h for documentation. +template <typename T, typename... Args> +auto makeUnique(Args&&... args) + -> decltype(base::MakeUnique<T>(std::forward<Args>(args)...)) { + static_assert( + !WTF::IsGarbageCollectedType<T>::value, + "Garbage collected types should not be stored in std::unique_ptr!"); + return base::MakeUnique<T>(std::forward<Args>(args)...); +} + +template <typename T> +auto makeUnique(size_t size) -> decltype(base::MakeUnique<T>(size)) { + static_assert( + !WTF::IsGarbageCollectedType<T>::value, + "Garbage collected types should not be stored in std::unique_ptr!"); + return base::MakeUnique<T>(size); +} + +} // namespace WTF + +using WTF::wrapArrayUnique; + +#endif // PtrUtil_h
diff --git a/third_party/WebKit/Source/platform/wtf/RefCounted.h b/third_party/WebKit/Source/platform/wtf/RefCounted.h new file mode 100644 index 0000000..357e294 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/RefCounted.h
@@ -0,0 +1,171 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RefCounted_h +#define RefCounted_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Assertions.h" +#include "platform/wtf/Noncopyable.h" +#include "platform/wtf/WTFExport.h" + +#if ENABLE(INSTANCE_COUNTER) +#include "platform/wtf/InstanceCounter.h" +#endif + +#if DCHECK_IS_ON() +#define CHECK_REF_COUNTED_LIFECYCLE 1 +#include "platform/wtf/ThreadRestrictionVerifier.h" +#else +#define CHECK_REF_COUNTED_LIFECYCLE 0 +#endif + +namespace WTF { + +// This base class holds the non-template methods and attributes. +// The RefCounted class inherits from it reducing the template bloat +// generated by the compiler (technique called template hoisting). +class WTF_EXPORT RefCountedBase { + public: + void ref() const { +#if CHECK_REF_COUNTED_LIFECYCLE + SECURITY_DCHECK(m_verifier.onRef(m_refCount)); + DCHECK(!m_adoptionIsRequired); +#endif + SECURITY_DCHECK(!m_deletionHasBegun); + ++m_refCount; + } + + bool hasOneRef() const { + SECURITY_DCHECK(!m_deletionHasBegun); +#if CHECK_REF_COUNTED_LIFECYCLE + SECURITY_DCHECK(m_verifier.isSafeToUse()); +#endif + return m_refCount == 1; + } + + int refCount() const { +#if CHECK_REF_COUNTED_LIFECYCLE + SECURITY_DCHECK(m_verifier.isSafeToUse()); +#endif + return m_refCount; + } + + protected: + RefCountedBase() + : m_refCount(1) +#if ENABLE(SECURITY_ASSERT) + , + m_deletionHasBegun(false) +#endif +#if CHECK_REF_COUNTED_LIFECYCLE + , + m_adoptionIsRequired(true) +#endif + { + } + + ~RefCountedBase() { + SECURITY_DCHECK(m_deletionHasBegun); +#if CHECK_REF_COUNTED_LIFECYCLE + DCHECK(!m_adoptionIsRequired); +#endif + } + + // Returns whether the pointer should be freed or not. + bool derefBase() const { + SECURITY_DCHECK(!m_deletionHasBegun); +#if CHECK_REF_COUNTED_LIFECYCLE + SECURITY_DCHECK(m_verifier.onDeref(m_refCount)); + DCHECK(!m_adoptionIsRequired); +#endif + + DCHECK_GT(m_refCount, 0); + --m_refCount; + if (!m_refCount) { +#if ENABLE(SECURITY_ASSERT) + m_deletionHasBegun = true; +#endif + return true; + } + + return false; + } + +#if CHECK_REF_COUNTED_LIFECYCLE + bool deletionHasBegun() const { return m_deletionHasBegun; } +#endif + + private: +#if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT) + friend void adopted(RefCountedBase*); +#endif + + mutable int m_refCount; +#if ENABLE(SECURITY_ASSERT) + mutable bool m_deletionHasBegun; +#endif +#if CHECK_REF_COUNTED_LIFECYCLE + mutable bool m_adoptionIsRequired; + mutable ThreadRestrictionVerifier m_verifier; +#endif +}; + +#if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT) +inline void adopted(RefCountedBase* object) { + if (!object) + return; + SECURITY_DCHECK(!object->m_deletionHasBegun); +#if CHECK_REF_COUNTED_LIFECYCLE + object->m_adoptionIsRequired = false; +#endif +} +#endif + +template <typename T> +class RefCounted : public RefCountedBase { + WTF_MAKE_NONCOPYABLE(RefCounted); + + // Put |T| in here instead of |RefCounted| so the heap profiler reports |T| + // instead of |RefCounted<T>|. This does not affect overloading of operator + // new. + USING_FAST_MALLOC(T); + + public: + void deref() const { + if (derefBase()) + delete static_cast<const T*>(this); + } + + protected: +#if ENABLE(INSTANCE_COUNTER) + RefCounted() { incrementInstanceCount<T>(static_cast<T*>(this)); } + + ~RefCounted() { decrementInstanceCount<T>(static_cast<T*>(this)); } +#else + RefCounted() {} +#endif +}; + +} // namespace WTF + +using WTF::RefCounted; + +#endif // RefCounted_h
diff --git a/third_party/WebKit/Source/platform/wtf/RefPtr.h b/third_party/WebKit/Source/platform/wtf/RefPtr.h new file mode 100644 index 0000000..0b15fb0 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/RefPtr.h
@@ -0,0 +1,222 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_RefPtr_h +#define WTF_RefPtr_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/HashTableDeletedValueType.h" +#include "platform/wtf/PassRefPtr.h" +#include "platform/wtf/allocator/PartitionAllocator.h" +#include <algorithm> +#include <utility> + +namespace WTF { + +template <typename T> +class PassRefPtr; +template <typename T> +class RefPtrValuePeeker; + +template <typename T> +class RefPtr { + USING_FAST_MALLOC(RefPtr); + + public: + ALWAYS_INLINE RefPtr() : m_ptr(nullptr) {} + ALWAYS_INLINE RefPtr(std::nullptr_t) : m_ptr(nullptr) {} + ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } + ALWAYS_INLINE explicit RefPtr(T& ref) : m_ptr(&ref) { m_ptr->ref(); } + ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { + refIfNotNull(m_ptr); + } + template <typename U> + RefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) + : m_ptr(o.get()) { + refIfNotNull(m_ptr); + } + RefPtr(RefPtr&& o) : m_ptr(o.m_ptr) { o.m_ptr = nullptr; } + + // See comments in PassRefPtr.h for an explanation of why this takes a const + // reference. + template <typename U> + RefPtr(const PassRefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T)); + + // Hash table deleted values, which are only constructed and never copied or + // destroyed. + RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) {} + bool isHashTableDeletedValue() const { + return m_ptr == hashTableDeletedValue(); + } + + ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); } + + ALWAYS_INLINE T* get() const { return m_ptr; } + T* leakRef() WARN_UNUSED_RESULT; + void clear(); + PassRefPtr<T> release() { + PassRefPtr<T> tmp = adoptRef(m_ptr); + m_ptr = nullptr; + return tmp; + } + + T& operator*() const { return *m_ptr; } + ALWAYS_INLINE T* operator->() const { return m_ptr; } + + bool operator!() const { return !m_ptr; } + explicit operator bool() const { return m_ptr != nullptr; } + + RefPtr& operator=(RefPtr o) { + swap(o); + return *this; + } + RefPtr& operator=(std::nullptr_t) { + clear(); + return *this; + } + // This is required by HashMap<RefPtr>>. + template <typename U> + RefPtr& operator=(RefPtrValuePeeker<U>); + + void swap(RefPtr&); + + static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } + + private: + T* m_ptr; +}; + +template <typename T> +template <typename U> +inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o, + EnsurePtrConvertibleArgDefn(U, T)) + : m_ptr(o.leakRef()) {} + +template <typename T> +inline T* RefPtr<T>::leakRef() { + T* ptr = m_ptr; + m_ptr = nullptr; + return ptr; +} + +template <typename T> +inline void RefPtr<T>::clear() { + T* ptr = m_ptr; + m_ptr = nullptr; + derefIfNotNull(ptr); +} + +template <typename T> +template <typename U> +inline RefPtr<T>& RefPtr<T>::operator=(RefPtrValuePeeker<U> optr) { + RefPtr ptr = static_cast<U*>(optr); + swap(ptr); + return *this; +} + +template <class T> +inline void RefPtr<T>::swap(RefPtr& o) { + std::swap(m_ptr, o.m_ptr); +} + +template <class T> +inline void swap(RefPtr<T>& a, RefPtr<T>& b) { + a.swap(b); +} + +template <typename T, typename U> +inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) { + return a.get() == b.get(); +} + +template <typename T, typename U> +inline bool operator==(const RefPtr<T>& a, U* b) { + return a.get() == b; +} + +template <typename T, typename U> +inline bool operator==(T* a, const RefPtr<U>& b) { + return a == b.get(); +} + +template <typename T> +inline bool operator==(const RefPtr<T>& a, std::nullptr_t) { + return !a.get(); +} + +template <typename T> +inline bool operator==(std::nullptr_t, const RefPtr<T>& b) { + return !b.get(); +} + +template <typename T, typename U> +inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) { + return a.get() != b.get(); +} + +template <typename T, typename U> +inline bool operator!=(const RefPtr<T>& a, U* b) { + return a.get() != b; +} + +template <typename T, typename U> +inline bool operator!=(T* a, const RefPtr<U>& b) { + return a != b.get(); +} + +template <typename T> +inline bool operator!=(const RefPtr<T>& a, std::nullptr_t) { + return a.get(); +} + +template <typename T> +inline bool operator!=(std::nullptr_t, const RefPtr<T>& b) { + return b.get(); +} + +template <typename T> +inline T* getPtr(const RefPtr<T>& p) { + return p.get(); +} + +template <typename T> +class RefPtrValuePeeker { + DISALLOW_NEW(); + + public: + ALWAYS_INLINE RefPtrValuePeeker(T* p) : m_ptr(p) {} + ALWAYS_INLINE RefPtrValuePeeker(std::nullptr_t) : m_ptr(nullptr) {} + template <typename U> + RefPtrValuePeeker(const RefPtr<U>& p) : m_ptr(p.get()) {} + template <typename U> + RefPtrValuePeeker(const PassRefPtr<U>& p) : m_ptr(p.get()) {} + + ALWAYS_INLINE operator T*() const { return m_ptr; } + + private: + T* m_ptr; +}; + +} // namespace WTF + +using WTF::RefPtr; + +#endif // WTF_RefPtr_h
diff --git a/third_party/WebKit/Source/platform/wtf/StackUtil.h b/third_party/WebKit/Source/platform/wtf/StackUtil.h new file mode 100644 index 0000000..3bf25de --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/StackUtil.h
@@ -0,0 +1,49 @@ +// 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 StackUtil_h +#define StackUtil_h + +#include "platform/wtf/Compiler.h" +#include "platform/wtf/WTFExport.h" +#include "platform/wtf/build_config.h" +#include <stddef.h> +#include <stdint.h> + +namespace WTF { + +WTF_EXPORT size_t getUnderestimatedStackSize(); +WTF_EXPORT void* getStackStart(); + +namespace internal { + +WTF_EXPORT extern uintptr_t s_mainThreadStackStart; +WTF_EXPORT extern uintptr_t s_mainThreadUnderestimatedStackSize; + +WTF_EXPORT void initializeMainThreadStackEstimate(); + +#if OS(WIN) && COMPILER(MSVC) +size_t threadStackSize(); +#endif + +} // namespace internal + +// Returns true if the function is not called on the main thread. Note carefully +// that this function may have false positives, i.e. it can return true even if +// we are on the main thread. If the function returns false, we are certainly +// on the main thread. +inline bool mayNotBeMainThread() { + uintptr_t dummy; + uintptr_t addressDiff = + internal::s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy); + // This is a fast way to judge if we are in the main thread. + // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from + // the stack start of the main thread, we judge that we are in + // the main thread. + return addressDiff >= internal::s_mainThreadUnderestimatedStackSize; +} + +} // namespace WTF + +#endif // StackUtil_h
diff --git a/third_party/WebKit/Source/platform/wtf/StdLibExtras.h b/third_party/WebKit/Source/platform/wtf/StdLibExtras.h new file mode 100644 index 0000000..8a99619 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/StdLibExtras.h
@@ -0,0 +1,269 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_StdLibExtras_h +#define WTF_StdLibExtras_h + +#include <cstddef> +#include "base/numerics/safe_conversions.h" +#include "platform/wtf/Assertions.h" +#include "platform/wtf/CPU.h" +#include "platform/wtf/LeakAnnotations.h" +#include "platform/wtf/Noncopyable.h" +#include "platform/wtf/TypeTraits.h" + +#if DCHECK_IS_ON() +#include "platform/wtf/Threading.h" +#endif + +// Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable +// (|static T;|) so that it is leaked and its destructors are not called at +// exit. T may also be a Blink garbage collected object, in which case it is +// wrapped up by an off-heap |Persistent<T>| reference to the object, keeping +// it alive across GCs. +// +// A |DEFINE_STATIC_LOCAL()| static should only be used on the thread it was +// created on. +// +#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ + static WTF::StaticSingleton<Type> s_##Name( \ + new WTF::StaticSingleton<Type>::WrapperType Arguments); \ + Type& Name = s_##Name.get(false) + +// |DEFINE_THREAD_SAFE_STATIC_LOCAL()| is the cross-thread accessible variant +// of |DEFINE_STATIC_LOCAL()|; use it if the singleton can be accessed by +// multiple threads. +// +// TODO: rename as DEFINE_CROSS_THREAD_STATIC_LOCAL() ? +#define DEFINE_THREAD_SAFE_STATIC_LOCAL(Type, Name, Initializer) \ + static WTF::StaticSingleton<Type> s_##Name(Initializer); \ + Type& Name = s_##Name.get(true) + +namespace blink { +template <typename T> +class Persistent; + +} // namespace blink + +namespace WTF { + +template <typename Type> +class StaticSingleton final { + WTF_MAKE_NONCOPYABLE(StaticSingleton); + + public: + template <typename T, + bool = WTF::IsGarbageCollectedType<T>::value && + !WTF::IsPersistentReferenceType<T>::value> + struct Wrapper { + using type = T; + + static T& unwrap(T* singleton) { return *singleton; } + }; + + template <typename T> + struct Wrapper<T, true> { + using type = blink::Persistent<T>; + + static T& unwrap(blink::Persistent<T>* singleton) { + DCHECK(singleton); + // If this assert triggers, you're supplying an empty ("()") 'Arguments' + // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish + // to create as a static singleton and wrapped up with a Persistent + // reference. + DCHECK(*singleton); + return **singleton; + } + }; + + using WrapperType = typename Wrapper<Type>::type; + + // To cooperate with leak detection(LSan) for Blink garbage collected objects, + // the objects owned by persistent local statics will in some cases have to be + // finalized prior to leak checking. This only applies to static references to + // Blink heap objects and what they transitively hold on to. Hence the + // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy + // details. + + explicit StaticSingleton(WrapperType* instance) + : m_instance(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance)) +#if DCHECK_IS_ON() + , + m_safelyInitialized(WTF::isBeforeThreadCreated()), + m_thread(WTF::internal::currentThreadSyscall()) +#endif + { + } + + Type& get(bool allowCrossThreadUse) const { +#if DCHECK_IS_ON() + DCHECK(isNotRacy(allowCrossThreadUse)); +#endif + ALLOW_UNUSED_LOCAL(allowCrossThreadUse); + return Wrapper<Type>::unwrap(m_instance); + } + + operator Type&() { return get(); } + + private: +#if DCHECK_IS_ON() + + bool isNotRacy(bool allowCrossThreadUse) const { + // Make sure that singleton is safely initialized, or + // keeps being called on the same thread if cross-thread + // use is not permitted. + return allowCrossThreadUse || m_safelyInitialized || + m_thread == WTF::internal::currentThreadSyscall(); + } +#endif + + WrapperType* m_instance; +#if DCHECK_IS_ON() + bool m_safelyInitialized; + ThreadIdentifier m_thread; +#endif +}; + +} // namespace WTF + +// Use this to declare and define a static local pointer to a ref-counted object +// so that it is leaked so that the object's destructors are not called at +// exit. This macro should be used with ref-counted objects rather than +// DEFINE_STATIC_LOCAL macro, as this macro does not lead to an extra memory +// allocation. +#define DEFINE_STATIC_REF(type, name, arguments) \ + static type* name = PassRefPtr<type>(arguments).leakRef(); + +/* + * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where + * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: + * increases required alignment of target type. + * + * An implicit or an extra static_cast<void*> bypasses the warning. + * For more info see the following bugzilla entries: + * - https://bugs.webkit.org/show_bug.cgi?id=38045 + * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 + */ +#if CPU(ARM) && COMPILER(GCC) +template <typename Type> +bool isPointerTypeAlignmentOkay(Type* ptr) { + return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type)); +} + +template <typename TypePtr> +TypePtr reinterpret_cast_ptr(void* ptr) { + DCHECK(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); + return reinterpret_cast<TypePtr>(ptr); +} + +template <typename TypePtr> +TypePtr reinterpret_cast_ptr(const void* ptr) { + DCHECK(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); + return reinterpret_cast<TypePtr>(ptr); +} +#else +template <typename Type> +bool isPointerTypeAlignmentOkay(Type*) { + return true; +} +#define reinterpret_cast_ptr reinterpret_cast +#endif + +namespace WTF { + +/* + * C++'s idea of a reinterpret_cast lacks sufficient cojones. + */ +template <typename TO, typename FROM> +inline TO bitwiseCast(FROM from) { + static_assert(sizeof(TO) == sizeof(FROM), + "WTF::bitwiseCast sizeof casted types should be equal"); + union { + FROM from; + TO to; + } u; + u.from = from; + return u.to; +} + +template <typename To, typename From> +inline To safeCast(From value) { + return base::checked_cast<To>(value); +} + +// Use the following macros to prevent errors caused by accidental +// implicit casting of function arguments. For example, this can +// be used to prevent overflows from non-promoting conversions. +// +// Example: +// +// HAS_STRICTLY_TYPED_ARG +// void sendData(void* data, STRICTLY_TYPED_ARG(size)) +// { +// ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t); +// ... +// } +// +// The previous example will prevent callers from passing, for example, an +// 'int'. On a 32-bit build, it will prevent use of an 'unsigned long long'. +#define HAS_STRICTLY_TYPED_ARG template <typename ActualArgType> +#define STRICTLY_TYPED_ARG(argName) ActualArgType argName +#define STRICT_ARG_TYPE(ExpectedArgType) \ + static_assert(std::is_same<ActualArgType, ExpectedArgType>::value, \ + "Strictly typed argument must be of type '" #ExpectedArgType \ + "'.") +#define ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(ExpectedArgType) \ + static_assert( \ + std::numeric_limits<ExpectedArgType>::is_integer == \ + std::numeric_limits<ActualArgType>::is_integer, \ + "Conversion between integer and non-integer types not allowed."); \ + static_assert(sizeof(ExpectedArgType) >= sizeof(ActualArgType), \ + "Truncating conversions not allowed."); \ + static_assert(!std::numeric_limits<ActualArgType>::is_signed || \ + std::numeric_limits<ExpectedArgType>::is_signed, \ + "Signed to unsigned conversion not allowed."); \ + static_assert((sizeof(ExpectedArgType) != sizeof(ActualArgType)) || \ + (std::numeric_limits<ActualArgType>::is_signed == \ + std::numeric_limits<ExpectedArgType>::is_signed), \ + "Unsigned to signed conversion not allowed for types with " \ + "identical size (could overflow)."); + +// Macro that returns a compile time constant with the length of an array, but +// gives an error if passed a non-array. +template <typename T, size_t Size> +char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; +// GCC needs some help to deduce a 0 length array. +#if COMPILER(GCC) +template <typename T> +char (&ArrayLengthHelperFunction(T (&)[0]))[0]; +#endif +#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) + +} // namespace WTF + +using WTF::bitwiseCast; +using WTF::safeCast; + +#endif // WTF_StdLibExtras_h
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadRestrictionVerifier.h b/third_party/WebKit/Source/platform/wtf/ThreadRestrictionVerifier.h new file mode 100644 index 0000000..44d1b16 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/ThreadRestrictionVerifier.h
@@ -0,0 +1,108 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ThreadRestrictionVerifier_h +#define ThreadRestrictionVerifier_h + +#include "platform/wtf/Assertions.h" + +#if DCHECK_IS_ON() + +#include "platform/wtf/Threading.h" + +namespace WTF { + +// Verifies that a class is used in a way that respects its lack of +// thread-safety. The default mode is to verify that the object will only be +// used on a single thread. The thread gets captured when setShared(true) is +// called. The mode may be changed by calling useMutexMode (or +// turnOffVerification). +class ThreadRestrictionVerifier { + public: + ThreadRestrictionVerifier() : m_shared(false), m_owningThread(0) {} + + // Call onRef() before refCount is incremented in ref(). Returns whether the + // ref() is safe. + template <typename COUNTERTYPE> + bool onRef(COUNTERTYPE refCount) { + // Start thread verification as soon as the ref count gets to 2. This + // heuristic reflects the fact that items are often created on one + // thread and then given to another thread to be used. + // FIXME: Make this restriction tigher. Especially as we move to more + // common methods for sharing items across threads like + // CrossThreadCopier.h + // We should be able to add a "detachFromThread" method to make this + // explicit. + if (refCount == 1) + setShared(true); + return isSafeToUse(); + } + + // Call onDeref() before refCount is decremented in deref(). Returns whether + // the deref() is safe. + template <typename COUNTERTYPE> + bool onDeref(COUNTERTYPE refCount) { + bool safe = isSafeToUse(); + // Stop thread verification when the ref goes to 1 because it + // is safe to be passed to another thread at this point. + if (refCount == 2) + setShared(false); + return safe; + } + + // Is it OK to use the object at this moment on the current thread? + bool isSafeToUse() const { + return !m_shared || m_owningThread == currentThread(); + } + + private: + // Indicates that the object may (or may not) be owned by more than one place. + void setShared(bool shared) { + bool previouslyShared = m_shared; + m_shared = shared; + + if (!m_shared) + return; + + DCHECK_NE(shared, previouslyShared); + // Capture the current thread to verify that subsequent ref/deref happen on + // this thread. + m_owningThread = currentThread(); + } + + bool m_shared; + + ThreadIdentifier m_owningThread; +}; + +} // namespace WTF + +#endif // DCHECK_IS_ON() +#endif // ThreadRestrictionVerifier_h
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadSafeRefCounted.h b/third_party/WebKit/Source/platform/wtf/ThreadSafeRefCounted.h new file mode 100644 index 0000000..3e49e99 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/ThreadSafeRefCounted.h
@@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ThreadSafeRefCounted_h +#define ThreadSafeRefCounted_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Atomics.h" +#include "platform/wtf/DynamicAnnotations.h" +#include "platform/wtf/Noncopyable.h" +#include "platform/wtf/WTFExport.h" + +namespace WTF { + +class WTF_EXPORT ThreadSafeRefCountedBase { + WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase); + USING_FAST_MALLOC(ThreadSafeRefCountedBase); + + public: + ThreadSafeRefCountedBase(int initialRefCount = 1) + : m_refCount(initialRefCount) {} + + void ref() { atomicIncrement(&m_refCount); } + + bool hasOneRef() { return refCount() == 1; } + + int refCount() const { return static_cast<int const volatile&>(m_refCount); } + + protected: + // Returns whether the pointer should be freed or not. + bool derefBase() { + WTF_ANNOTATE_HAPPENS_BEFORE(&m_refCount); + if (atomicDecrement(&m_refCount) <= 0) { + WTF_ANNOTATE_HAPPENS_AFTER(&m_refCount); + return true; + } + return false; + } + + private: + int m_refCount; +}; + +template <class T> +class ThreadSafeRefCounted : public ThreadSafeRefCountedBase { + public: + void deref() { + if (derefBase()) + delete static_cast<T*>(this); + } + + protected: + ThreadSafeRefCounted() {} +}; + +} // namespace WTF + +using WTF::ThreadSafeRefCounted; + +#endif // ThreadSafeRefCounted_h
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h b/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h new file mode 100644 index 0000000..ec237358 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h
@@ -0,0 +1,316 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Jian Li <jianli@chromium.org> + * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Thread local storage is implemented by using either pthread API or Windows + * native API. There is subtle semantic discrepancy for the cleanup function + * implementation as noted below: + * @ In pthread implementation, the destructor function will be called + * repeatedly if there is still non-NULL value associated with the function. + * @ In Windows native implementation, the destructor function will be called + * only once. + * This semantic discrepancy does not impose any problem because nowhere in + * WebKit the repeated call bahavior is utilized. + */ + +#ifndef WTF_ThreadSpecific_h +#define WTF_ThreadSpecific_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Noncopyable.h" +#include "platform/wtf/StackUtil.h" +#include "platform/wtf/StdLibExtras.h" +#include "platform/wtf/WTF.h" +#include "platform/wtf/WTFExport.h" +#include "platform/wtf/allocator/PartitionAllocator.h" +#include "platform/wtf/allocator/Partitions.h" + +#if OS(POSIX) +#include <pthread.h> +#elif OS(WIN) +#include <windows.h> +#endif + +namespace WTF { + +#if OS(WIN) +// ThreadSpecificThreadExit should be called each time when a thread is +// detached. +// This is done automatically for threads created with WTF::createThread. +WTF_EXPORT void ThreadSpecificThreadExit(); +#endif + +template <typename T> +class ThreadSpecific { + USING_FAST_MALLOC(ThreadSpecific); + WTF_MAKE_NONCOPYABLE(ThreadSpecific); + + public: + ThreadSpecific(); + bool + isSet(); // Useful as a fast check to see if this thread has set this value. + T* operator->(); + operator T*(); + T& operator*(); + + private: +#if OS(WIN) + WTF_EXPORT friend void ThreadSpecificThreadExit(); +#endif + + // Not implemented. It's technically possible to destroy a thread specific + // key, but one would need to make sure that all values have been destroyed + // already (usually, that all threads that used it have exited). It's + // unlikely that any user of this call will be in that situation - and having + // a destructor defined can be confusing, given that it has such strong + // pre-requisites to work correctly. + ~ThreadSpecific(); + + T* get(); + void set(T*); + void static destroy(void* ptr); + + struct Data { + WTF_MAKE_NONCOPYABLE(Data); + + public: + Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} + + T* value; + ThreadSpecific<T>* owner; +#if OS(WIN) + void (*destructor)(void*); +#endif + }; + +#if OS(POSIX) + pthread_key_t m_key; +#elif OS(WIN) + int m_index; +#endif + // This member must only be accessed or modified on the main thread. + T* m_mainThreadStorage = nullptr; +}; + +#if OS(POSIX) + +typedef pthread_key_t ThreadSpecificKey; + +inline void threadSpecificKeyCreate(ThreadSpecificKey* key, + void (*destructor)(void*)) { + int error = pthread_key_create(key, destructor); + if (error) + CRASH(); +} + +inline void threadSpecificKeyDelete(ThreadSpecificKey key) { + int error = pthread_key_delete(key); + if (error) + CRASH(); +} + +inline void threadSpecificSet(ThreadSpecificKey key, void* value) { + pthread_setspecific(key, value); +} + +inline void* threadSpecificGet(ThreadSpecificKey key) { + return pthread_getspecific(key); +} + +template <typename T> +inline ThreadSpecific<T>::ThreadSpecific() { + int error = pthread_key_create(&m_key, destroy); + if (error) + CRASH(); +} + +template <typename T> +inline T* ThreadSpecific<T>::get() { + Data* data = static_cast<Data*>(pthread_getspecific(m_key)); + return data ? data->value : 0; +} + +template <typename T> +inline void ThreadSpecific<T>::set(T* ptr) { + DCHECK(!get()); + pthread_setspecific(m_key, new Data(ptr, this)); +} + +#elif OS(WIN) + +// TLS_OUT_OF_INDEXES is not defined on WinCE. +#ifndef TLS_OUT_OF_INDEXES +#define TLS_OUT_OF_INDEXES 0xffffffff +#endif + +// The maximum number of TLS keys that can be created. For simplification, we +// assume that: +// 1) Once the instance of ThreadSpecific<> is created, it will not be +// destructed until the program dies. +// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed +// number should be far enough. +const int kMaxTlsKeySize = 256; + +WTF_EXPORT long& tlsKeyCount(); +WTF_EXPORT DWORD* tlsKeys(); + +class PlatformThreadSpecificKey; +typedef PlatformThreadSpecificKey* ThreadSpecificKey; + +WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void*)); +WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey); +WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*); +WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey); + +template <typename T> +inline ThreadSpecific<T>::ThreadSpecific() : m_index(-1) { + DWORD tlsKey = TlsAlloc(); + if (tlsKey == TLS_OUT_OF_INDEXES) + CRASH(); + + m_index = InterlockedIncrement(&tlsKeyCount()) - 1; + if (m_index >= kMaxTlsKeySize) + CRASH(); + tlsKeys()[m_index] = tlsKey; +} + +template <typename T> +inline ThreadSpecific<T>::~ThreadSpecific() { + // Does not invoke destructor functions. They will be called from + // ThreadSpecificThreadExit when the thread is detached. + TlsFree(tlsKeys()[m_index]); +} + +template <typename T> +inline T* ThreadSpecific<T>::get() { + Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); + return data ? data->value : 0; +} + +template <typename T> +inline void ThreadSpecific<T>::set(T* ptr) { + DCHECK(!get()); + Data* data = new Data(ptr, this); + data->destructor = &ThreadSpecific<T>::destroy; + TlsSetValue(tlsKeys()[m_index], data); +} + +#else +#error ThreadSpecific is not implemented for this platform. +#endif + +template <typename T> +inline void ThreadSpecific<T>::destroy(void* ptr) { + Data* data = static_cast<Data*>(ptr); + +#if OS(POSIX) + // We want get() to keep working while data destructor works, because it can + // be called indirectly by the destructor. Some pthreads implementations + // zero out the pointer before calling destroy(), so we temporarily reset it. + pthread_setspecific(data->owner->m_key, ptr); +#endif + + // Never call destructors on the main thread. This is fine because Blink no + // longer has a graceful shutdown sequence. Be careful to call this function + // (which can be re-entrant) while the pointer is still set, to avoid lazily + // allocating WTFThreadData after it is destroyed. + if (isMainThread()) + return; + + data->value->~T(); + Partitions::fastFree(data->value); + +#if OS(POSIX) + pthread_setspecific(data->owner->m_key, 0); +#elif OS(WIN) + TlsSetValue(tlsKeys()[data->owner->m_index], 0); +#else +#error ThreadSpecific is not implemented for this platform. +#endif + + delete data; +} + +template <typename T> +inline bool ThreadSpecific<T>::isSet() { + return !!get(); +} + +template <typename T> +inline ThreadSpecific<T>::operator T*() { + T* offThreadPtr; +#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) + // TLS is fast on these platforms. + // TODO(csharrison): Qualify this statement for Android. + const bool mainThreadAlwaysChecksTLS = true; + T** ptr = &offThreadPtr; + offThreadPtr = static_cast<T*>(get()); +#else + const bool mainThreadAlwaysChecksTLS = false; + T** ptr = &m_mainThreadStorage; + if (UNLIKELY(mayNotBeMainThread())) { + offThreadPtr = static_cast<T*>(get()); + ptr = &offThreadPtr; + } +#endif + // Set up thread-specific value's memory pointer before invoking constructor, + // in case any function it calls needs to access the value, to avoid + // recursion. + if (UNLIKELY(!*ptr)) { + *ptr = static_cast<T*>(Partitions::fastZeroedMalloc( + sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T))); + + // Even if we didn't realize we're on the main thread, we might still be. + // We need to double-check so that |m_mainThreadStorage| is populated. + if (!mainThreadAlwaysChecksTLS && UNLIKELY(ptr != &m_mainThreadStorage) && + isMainThread()) { + m_mainThreadStorage = *ptr; + } + + set(*ptr); + new (NotNull, *ptr) T; + } + return *ptr; +} + +template <typename T> +inline T* ThreadSpecific<T>::operator->() { + return operator T*(); +} + +template <typename T> +inline T& ThreadSpecific<T>::operator*() { + return *operator T*(); +} + +} // namespace WTF + +using WTF::ThreadSpecific; + +#endif // WTF_ThreadSpecific_h
diff --git a/third_party/WebKit/Source/platform/wtf/Threading.h b/third_party/WebKit/Source/platform/wtf/Threading.h new file mode 100644 index 0000000..9fa2f3b --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/Threading.h
@@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Threading_h +#define Threading_h + +#include "platform/wtf/Atomics.h" +#include "platform/wtf/TypeTraits.h" +#include "platform/wtf/WTFExport.h" +#include <stdint.h> + +namespace WTF { + +#if OS(WIN) +typedef uint32_t ThreadIdentifier; +#else +typedef intptr_t ThreadIdentifier; +#endif + +namespace internal { +WTF_EXPORT ThreadIdentifier currentThreadSyscall(); +} // namespace internal + +// Initializes global state required by |currentThread|. +// Needs to be called once during program execution, before |currentThread|. +WTF_EXPORT void initializeCurrentThread(); + +WTF_EXPORT ThreadIdentifier currentThread(); + +#if DCHECK_IS_ON() +WTF_EXPORT bool isBeforeThreadCreated(); +WTF_EXPORT void willCreateThread(); +#endif + +} // namespace WTF + +using WTF::ThreadIdentifier; +using WTF::currentThread; + +#endif // Threading_h
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadingPrimitives.h b/third_party/WebKit/Source/platform/wtf/ThreadingPrimitives.h new file mode 100644 index 0000000..d9335b3 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/ThreadingPrimitives.h
@@ -0,0 +1,175 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ThreadingPrimitives_h +#define ThreadingPrimitives_h + +#include "platform/wtf/Allocator.h" +#include "platform/wtf/Assertions.h" +#include "platform/wtf/Locker.h" +#include "platform/wtf/Noncopyable.h" +#include "platform/wtf/WTFExport.h" + +#if OS(WIN) +#include <windows.h> +#endif + +#if OS(POSIX) +#include <pthread.h> +#endif + +namespace WTF { + +#if OS(POSIX) +struct PlatformMutex { + pthread_mutex_t m_internalMutex; +#if DCHECK_IS_ON() + size_t m_recursionCount; +#endif +}; +typedef pthread_cond_t PlatformCondition; +#elif OS(WIN) +struct PlatformMutex { + CRITICAL_SECTION m_internalMutex; + size_t m_recursionCount; +}; +struct PlatformCondition { + size_t m_waitersGone; + size_t m_waitersBlocked; + size_t m_waitersToUnblock; + HANDLE m_blockLock; + HANDLE m_blockQueue; + HANDLE m_unblockLock; + + bool timedWait(PlatformMutex&, DWORD durationMilliseconds); + void signal(bool unblockAll); +}; +#else +typedef void* PlatformMutex; +typedef void* PlatformCondition; +#endif + +class WTF_EXPORT MutexBase { + WTF_MAKE_NONCOPYABLE(MutexBase); + USING_FAST_MALLOC(MutexBase); + + public: + ~MutexBase(); + + void lock(); + void unlock(); +#if DCHECK_IS_ON() + bool locked() { return m_mutex.m_recursionCount > 0; } +#endif + + public: + PlatformMutex& impl() { return m_mutex; } + + protected: + MutexBase(bool recursive); + + PlatformMutex m_mutex; +}; + +class WTF_EXPORT Mutex : public MutexBase { + public: + Mutex() : MutexBase(false) {} + bool tryLock(); +}; + +class WTF_EXPORT RecursiveMutex : public MutexBase { + public: + RecursiveMutex() : MutexBase(true) {} + bool tryLock(); +}; + +typedef Locker<MutexBase> MutexLocker; + +class MutexTryLocker final { + STACK_ALLOCATED(); + WTF_MAKE_NONCOPYABLE(MutexTryLocker); + + public: + MutexTryLocker(Mutex& mutex) : m_mutex(mutex), m_locked(mutex.tryLock()) {} + ~MutexTryLocker() { + if (m_locked) + m_mutex.unlock(); + } + + bool locked() const { return m_locked; } + + private: + Mutex& m_mutex; + bool m_locked; +}; + +class WTF_EXPORT ThreadCondition final { + USING_FAST_MALLOC(ThreadCondition); // Only HeapTest.cpp requires. + WTF_MAKE_NONCOPYABLE(ThreadCondition); + + public: + ThreadCondition(); + ~ThreadCondition(); + + void wait(MutexBase&); + // Returns true if the condition was signaled before absoluteTime, false if + // the absoluteTime was reached or is in the past. + // The absoluteTime is in seconds, starting on January 1, 1970. The time is + // assumed to use the same time zone as WTF::currentTime(). + bool timedWait(MutexBase&, double absoluteTime); + void signal(); + void broadcast(); + + private: + PlatformCondition m_condition; +}; + +#if OS(WIN) +// The absoluteTime is in seconds, starting on January 1, 1970. The time is +// assumed to use the same time zone as WTF::currentTime(). +// Returns an interval in milliseconds suitable for passing to one of the Win32 +// wait functions (e.g., ::WaitForSingleObject). +DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime); +#endif + +} // namespace WTF + +using WTF::MutexBase; +using WTF::Mutex; +using WTF::RecursiveMutex; +using WTF::MutexLocker; +using WTF::MutexTryLocker; +using WTF::ThreadCondition; + +#if OS(WIN) +using WTF::absoluteTimeToWaitTimeoutInterval; +#endif + +#endif // ThreadingPrimitives_h
diff --git a/third_party/WebKit/Source/platform/wtf/TreeNode.h b/third_party/WebKit/Source/platform/wtf/TreeNode.h new file mode 100644 index 0000000..7c46f5f2 --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/TreeNode.h
@@ -0,0 +1,212 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TreeNode_h +#define TreeNode_h + +#include "platform/wtf/Assertions.h" + +namespace WTF { + +// +// TreeNode is generic, ContainerNode-like linked tree data structure. +// There are a few notable difference between TreeNode and Node: +// +// * Each TreeNode node is NOT ref counted. The user have to retain its +// lifetime somehow. +// FIXME: lifetime management could be parameterized so that ref counted +// implementations can be used. +// * It checks invalid input. The callers have to ensure that given +// parameter is sound. +// * There is no branch-leaf difference. Every node can be a parent of other +// node. +// +// FIXME: oilpan: Trace tree node edges to ensure we don't have dangling +// pointers. +// As it is used in HTMLImport it is safe since they all die together. +template <class T> +class TreeNode { + public: + typedef T NodeType; + + TreeNode() + : m_next(0), + m_previous(0), + m_parent(0), + m_firstChild(0), + m_lastChild(0) {} + + NodeType* next() const { return m_next; } + NodeType* previous() const { return m_previous; } + NodeType* parent() const { return m_parent; } + NodeType* firstChild() const { return m_firstChild; } + NodeType* lastChild() const { return m_lastChild; } + NodeType* here() const { + return static_cast<NodeType*>(const_cast<TreeNode*>(this)); + } + + bool orphan() const { + return !m_parent && !m_next && !m_previous && !m_firstChild && !m_lastChild; + } + bool hasChildren() const { return m_firstChild; } + + void insertBefore(NodeType* newChild, NodeType* refChild) { + DCHECK(!newChild->parent()); + DCHECK(!newChild->next()); + DCHECK(!newChild->previous()); + + DCHECK(!refChild || this == refChild->parent()); + + if (!refChild) { + appendChild(newChild); + return; + } + + NodeType* newPrevious = refChild->previous(); + newChild->m_parent = here(); + newChild->m_next = refChild; + newChild->m_previous = newPrevious; + refChild->m_previous = newChild; + if (newPrevious) + newPrevious->m_next = newChild; + else + m_firstChild = newChild; + } + + void appendChild(NodeType* child) { + DCHECK(!child->parent()); + DCHECK(!child->next()); + DCHECK(!child->previous()); + + child->m_parent = here(); + + if (!m_lastChild) { + DCHECK(!m_firstChild); + m_lastChild = m_firstChild = child; + return; + } + + DCHECK(!m_lastChild->m_next); + NodeType* oldLast = m_lastChild; + m_lastChild = child; + + child->m_previous = oldLast; + oldLast->m_next = child; + } + + NodeType* removeChild(NodeType* child) { + DCHECK_EQ(child->parent(), this); + + if (m_firstChild == child) + m_firstChild = child->next(); + if (m_lastChild == child) + m_lastChild = child->previous(); + + NodeType* oldNext = child->next(); + NodeType* oldPrevious = child->previous(); + child->m_parent = child->m_next = child->m_previous = 0; + + if (oldNext) + oldNext->m_previous = oldPrevious; + if (oldPrevious) + oldPrevious->m_next = oldNext; + + return child; + } + + void takeChildrenFrom(NodeType* oldParent) { + DCHECK_NE(oldParent, this); + while (oldParent->hasChildren()) { + NodeType* child = oldParent->firstChild(); + oldParent->removeChild(child); + this->appendChild(child); + } + } + + private: + NodeType* m_next; + NodeType* m_previous; + NodeType* m_parent; + NodeType* m_firstChild; + NodeType* m_lastChild; +}; + +template <class T> +inline typename TreeNode<T>::NodeType* traverseNext( + const TreeNode<T>* current, + const TreeNode<T>* stayWithin = 0) { + if (typename TreeNode<T>::NodeType* next = current->firstChild()) + return next; + if (current == stayWithin) + return 0; + if (typename TreeNode<T>::NodeType* next = current->next()) + return next; + for (typename TreeNode<T>::NodeType* parent = current->parent(); parent; + parent = parent->parent()) { + if (parent == stayWithin) + return 0; + if (typename TreeNode<T>::NodeType* next = parent->next()) + return next; + } + + return 0; +} + +template <class T> +inline typename TreeNode<T>::NodeType* traverseFirstPostOrder( + const TreeNode<T>* current) { + typename TreeNode<T>::NodeType* first = current->here(); + while (first->firstChild()) + first = first->firstChild(); + return first; +} + +template <class T> +inline typename TreeNode<T>::NodeType* traverseNextPostOrder( + const TreeNode<T>* current, + const TreeNode<T>* stayWithin = 0) { + if (current == stayWithin) + return 0; + + typename TreeNode<T>::NodeType* next = current->next(); + if (!next) + return current->parent(); + while (next->firstChild()) + next = next->firstChild(); + return next; +} + +} // namespace WTF + +using WTF::TreeNode; +using WTF::traverseNext; +using WTF::traverseNextPostOrder; + +#endif
diff --git a/third_party/WebKit/Source/platform/wtf/WeakPtr.h b/third_party/WebKit/Source/platform/wtf/WeakPtr.h new file mode 100644 index 0000000..57b2e50c --- /dev/null +++ b/third_party/WebKit/Source/platform/wtf/WeakPtr.h
@@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Google, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_WeakPtr_h +#define WTF_WeakPtr_h + +#include "base/memory/weak_ptr.h" +#include "platform/wtf/Noncopyable.h" + +namespace WTF { + +template <typename T> +using WeakPtr = base::WeakPtr<T>; + +template <typename T> +class WeakPtrFactory { + WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>); + USING_FAST_MALLOC(WeakPtrFactory); + + public: + explicit WeakPtrFactory(T* ptr) : m_factory(ptr) {} + + WeakPtr<T> createWeakPtr() { return m_factory.GetWeakPtr(); } + + void revokeAll() { m_factory.InvalidateWeakPtrs(); } + + bool hasWeakPtrs() const { return m_factory.HasWeakPtrs(); } + + private: + base::WeakPtrFactory<T> m_factory; +}; + +} // namespace WTF + +using WTF::WeakPtr; +using WTF::WeakPtrFactory; + +#endif
diff --git a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp index 461ec069..09c5493 100644 --- a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp +++ b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
@@ -5,7 +5,6 @@ #include "bindings/core/v8/NodeOrString.h" #include "core/dom/ClientRect.h" #include "core/frame/BrowserControls.h" -#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/RootFrameViewport.h" #include "core/frame/VisualViewport.h" @@ -101,8 +100,6 @@ Page& page() const { return *m_helper.webView()->page(); } - FrameHost& frameHost() const { return page().frameHost(); } - LocalFrame* mainFrame() const { return webViewImpl()->mainFrameImpl()->frame(); }
diff --git a/third_party/WebKit/Source/wtf/BUILD.gn b/third_party/WebKit/Source/wtf/BUILD.gn index 6972003..fb01a91 100644 --- a/third_party/WebKit/Source/wtf/BUILD.gn +++ b/third_party/WebKit/Source/wtf/BUILD.gn
@@ -22,7 +22,6 @@ "AddressSanitizer.h", "Alignment.h", "Allocator.h", - "Assertions.cpp", "Assertions.h", "Atomics.h", "AutoReset.h",
diff --git a/third_party/WebKit/Source/wtf/BitwiseOperations.h b/third_party/WebKit/Source/wtf/BitwiseOperations.h index 9e313a571..f4ae1084 100644 --- a/third_party/WebKit/Source/wtf/BitwiseOperations.h +++ b/third_party/WebKit/Source/wtf/BitwiseOperations.h
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "platform/wtf/WTFExport.h" +#include "platform/wtf/BitwiseOperations.h" // The contents of this header was moved to platform/wtf as part of // WTF migration project. See the following post for details:
diff --git a/third_party/WebKit/Source/wtf/Functional.h b/third_party/WebKit/Source/wtf/Functional.h index 93e827da..c550eef 100644 --- a/third_party/WebKit/Source/wtf/Functional.h +++ b/third_party/WebKit/Source/wtf/Functional.h
@@ -1,300 +1,9 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 WTF_Functional_h -#define WTF_Functional_h +#include "platform/wtf/Functional.h" -#include "base/bind.h" -#include "base/threading/thread_checker.h" -#include "wtf/Allocator.h" -#include "wtf/Assertions.h" -#include "wtf/PassRefPtr.h" -#include "wtf/PtrUtil.h" -#include "wtf/RefPtr.h" -#include "wtf/ThreadSafeRefCounted.h" -#include "wtf/TypeTraits.h" -#include <utility> - -namespace blink { -template <typename T> -class Member; -template <typename T> -class WeakMember; -} - -namespace WTF { - -// Functional.h provides a very simple way to bind a function pointer and -// arguments together into a function object that can be stored, copied and -// invoked, similar to boost::bind and std::bind in C++11. - -// Thread Safety: -// -// WTF::bind() and WTF::Closure should be used for same-thread closures -// only, i.e. the closures must be created, executed and destructed on -// the same thread. -// Use crossThreadBind() and CrossThreadClosure if the function/task is called -// or destructed on a (potentially) different thread from the current thread. - -// WTF::bind() and move semantics -// ============================== -// -// For unbound parameters (arguments supplied later on the bound functor -// directly), there are two ways to pass movable arguments: -// -// 1) Pass by rvalue reference. -// -// void yourFunction(Argument&& argument) { ... } -// std::unique_ptr<Function<void(Argument&&)>> functor = -// bind<Argument&&>(yourFunction); -// -// 2) Pass by value. -// -// void yourFunction(Argument argument) { ... } -// std::unique_ptr<Function<void(Argument)>> functor = -// bind<Argument>(yourFunction); -// -// Note that with the latter there will be *two* move constructions happening, -// because there needs to be at least one intermediary function call taking an -// argument of type "Argument" (i.e. passed by value). The former case does not -// require any move constructions inbetween. -// -// For bound parameters (arguments supplied on the creation of a functor), you -// can move your argument into the internal storage of the functor by supplying -// an rvalue to that argument (this is done in wrap() of ParamStorageTraits). -// However, to make the functor be able to get called multiple times, the -// stored object does not get moved out automatically when the underlying -// function is actually invoked. If you want to make an argument "auto-passed", -// you can do so by wrapping your bound argument with WTF::passed() function, as -// shown below: -// -// void yourFunction(Argument argument) -// { -// // |argument| is passed from the internal storage of functor. -// ... -// } -// -// ... -// std::unique_ptr<Function<void()>> functor = bind(yourFunction, -// WTF::passed(Argument())); -// ... -// (*functor)(); -// -// The underlying function must receive the argument wrapped by WTF::passed() by -// rvalue reference or by value. -// -// Obviously, if you create a functor this way, you shouldn't call the functor -// twice or more; after the second call, the passed argument may be invalid. - -enum FunctionThreadAffinity { CrossThreadAffinity, SameThreadAffinity }; - -template <typename T> -class PassedWrapper final { - public: - explicit PassedWrapper(T&& scoper) : m_scoper(std::move(scoper)) {} - PassedWrapper(PassedWrapper&& other) : m_scoper(std::move(other.m_scoper)) {} - T moveOut() const { return std::move(m_scoper); } - - private: - mutable T m_scoper; -}; - -template <typename T> -PassedWrapper<T> passed(T&& value) { - static_assert( - !std::is_reference<T>::value, - "You must pass an rvalue to WTF::passed() so it can be moved. Add " - "std::move() if necessary."); - static_assert(!std::is_const<T>::value, - "|value| must not be const so it can be moved."); - return PassedWrapper<T>(std::move(value)); -} - -template <typename T, FunctionThreadAffinity threadAffinity> -class UnretainedWrapper final { - public: - explicit UnretainedWrapper(T* ptr) : m_ptr(ptr) {} - T* value() const { return m_ptr; } - - private: - T* m_ptr; -}; - -template <typename T> -UnretainedWrapper<T, SameThreadAffinity> unretained(T* value) { - static_assert(!WTF::IsGarbageCollectedType<T>::value, - "WTF::unretained() + GCed type is forbidden"); - return UnretainedWrapper<T, SameThreadAffinity>(value); -} - -template <typename T> -UnretainedWrapper<T, CrossThreadAffinity> crossThreadUnretained(T* value) { - static_assert(!WTF::IsGarbageCollectedType<T>::value, - "crossThreadUnretained() + GCed type is forbidden"); - return UnretainedWrapper<T, CrossThreadAffinity>(value); -} - -template <typename T> -struct ParamStorageTraits { - typedef T StorageType; - - static_assert(!std::is_pointer<T>::value, - "Raw pointers are not allowed to bind into WTF::Function. Wrap " - "it with either wrapPersistent, wrapWeakPersistent, " - "wrapCrossThreadPersistent, wrapCrossThreadWeakPersistent, " - "RefPtr or unretained."); - static_assert(!IsSubclassOfTemplate<T, blink::Member>::value && - !IsSubclassOfTemplate<T, blink::WeakMember>::value, - "Member and WeakMember are not allowed to bind into " - "WTF::Function. Wrap it with either wrapPersistent, " - "wrapWeakPersistent, wrapCrossThreadPersistent or " - "wrapCrossThreadWeakPersistent."); -}; - -template <typename T> -struct ParamStorageTraits<PassRefPtr<T>> { - typedef RefPtr<T> StorageType; -}; - -template <typename T> -struct ParamStorageTraits<RefPtr<T>> { - typedef RefPtr<T> StorageType; -}; - -template <typename> -class RetainPtr; - -template <typename T> -struct ParamStorageTraits<RetainPtr<T>> { - typedef RetainPtr<T> StorageType; -}; - -template <typename T> -struct ParamStorageTraits<PassedWrapper<T>> { - typedef PassedWrapper<T> StorageType; -}; - -template <typename T, FunctionThreadAffinity threadAffinity> -struct ParamStorageTraits<UnretainedWrapper<T, threadAffinity>> { - typedef UnretainedWrapper<T, threadAffinity> StorageType; -}; - -template <typename Signature, - FunctionThreadAffinity threadAffinity = SameThreadAffinity> -class Function; - -template <typename R, typename... Args, FunctionThreadAffinity threadAffinity> -class Function<R(Args...), threadAffinity> { - USING_FAST_MALLOC(Function); - WTF_MAKE_NONCOPYABLE(Function); - - public: - Function(base::Callback<R(Args...)> callback) - : m_callback(std::move(callback)) {} - - ~Function() { DCHECK(m_threadChecker.CalledOnValidThread()); } - - R operator()(Args... args) { - DCHECK(m_threadChecker.CalledOnValidThread()); - return m_callback.Run(std::forward<Args>(args)...); - } - - bool isCancelled() const { return m_callback.IsCancelled(); } - - friend base::Callback<R(Args...)> convertToBaseCallback( - std::unique_ptr<Function> function) { - if (function) - return std::move(function->m_callback); - return base::Callback<R(Args...)>(); - } - - private: - using MaybeThreadChecker = - typename std::conditional<threadAffinity == SameThreadAffinity, - base::ThreadChecker, - base::ThreadCheckerDoNothing>::type; - MaybeThreadChecker m_threadChecker; - base::Callback<R(Args...)> m_callback; -}; - -template <FunctionThreadAffinity threadAffinity, - typename FunctionType, - typename... BoundParameters> -std::unique_ptr< - Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>, - threadAffinity>> -bindInternal(FunctionType function, BoundParameters&&... boundParameters) { - using UnboundRunType = - base::MakeUnboundRunType<FunctionType, BoundParameters...>; - return WTF::wrapUnique(new Function<UnboundRunType, - threadAffinity>(base::Bind( - function, - typename ParamStorageTraits<typename std::decay<BoundParameters>::type>:: - StorageType(std::forward<BoundParameters>(boundParameters))...))); -} - -template <typename FunctionType, typename... BoundParameters> -std::unique_ptr< - Function<base::MakeUnboundRunType<FunctionType, BoundParameters...>, - SameThreadAffinity>> -bind(FunctionType function, BoundParameters&&... boundParameters) { - return bindInternal<SameThreadAffinity>( - function, std::forward<BoundParameters>(boundParameters)...); -} - -typedef Function<void(), SameThreadAffinity> Closure; -typedef Function<void(), CrossThreadAffinity> CrossThreadClosure; - -} // namespace WTF - -namespace base { - -template <typename T> -struct BindUnwrapTraits<WTF::RefPtr<T>> { - static T* Unwrap(const WTF::RefPtr<T>& wrapped) { return wrapped.get(); } -}; - -template <typename T> -struct BindUnwrapTraits<WTF::PassedWrapper<T>> { - static T Unwrap(const WTF::PassedWrapper<T>& wrapped) { - return wrapped.moveOut(); - } -}; - -template <typename T, WTF::FunctionThreadAffinity threadAffinity> -struct BindUnwrapTraits<WTF::UnretainedWrapper<T, threadAffinity>> { - static T* Unwrap(const WTF::UnretainedWrapper<T, threadAffinity>& wrapped) { - return wrapped.value(); - } -}; - -} // namespace base - -using WTF::crossThreadUnretained; - -using WTF::Function; -using WTF::CrossThreadClosure; - -#endif // WTF_Functional_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/HashTableDeletedValueType.h b/third_party/WebKit/Source/wtf/HashTableDeletedValueType.h index 06b5e5e..7a358fd2 100644 --- a/third_party/WebKit/Source/wtf/HashTableDeletedValueType.h +++ b/third_party/WebKit/Source/wtf/HashTableDeletedValueType.h
@@ -1,40 +1,9 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 HashTableDeletedValueType_h -#define HashTableDeletedValueType_h +#include "platform/wtf/HashTableDeletedValueType.h" -namespace WTF { - -enum HashTableDeletedValueType { HashTableDeletedValue }; - -} // namespace WTF - -#endif // HashTableDeletedValueType_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/InstanceCounter.h b/third_party/WebKit/Source/wtf/InstanceCounter.h index 8937de0..f5e7612d 100644 --- a/third_party/WebKit/Source/wtf/InstanceCounter.h +++ b/third_party/WebKit/Source/wtf/InstanceCounter.h
@@ -1,60 +1,9 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 InstanceCounter_h -#define InstanceCounter_h +#include "platform/wtf/InstanceCounter.h" -#include "wtf/TypeTraits.h" -#include "wtf/WTFExport.h" -#include "wtf/build_config.h" - -namespace WTF { - -class String; -WTF_EXPORT String dumpRefCountedInstanceCounts(); - -#if ENABLE(INSTANCE_COUNTER) -WTF_EXPORT void incrementInstanceCount(const char* stringWithTypeName, - void* ptr); -WTF_EXPORT void decrementInstanceCount(const char* stringWithTypeName, - void* ptr); - -WTF_EXPORT String extractTypeNameFromFunctionName(const char* funcName); - -template <typename T> -inline void incrementInstanceCount(T* p) { - incrementInstanceCount(getStringWithTypeName<T>(), p); -} - -template <typename T> -inline void decrementInstanceCount(T* p) { - decrementInstanceCount(getStringWithTypeName<T>(), p); -} - -#endif // ENABLE(INSTANCE_COUNTER) - -} // namespace WTF - -#endif +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/Locker.h b/third_party/WebKit/Source/wtf/Locker.h index 9e7381d..de56036 100644 --- a/third_party/WebKit/Source/wtf/Locker.h +++ b/third_party/WebKit/Source/wtf/Locker.h
@@ -1,53 +1,9 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef Locker_h -#define Locker_h +// 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 "wtf/Allocator.h" -#include "wtf/Noncopyable.h" +#include "platform/wtf/Locker.h" -namespace WTF { - -template <typename T> -class Locker final { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(Locker); - - public: - Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); } - ~Locker() { m_lockable.unlock(); } - - private: - T& m_lockable; -}; - -} // namespace WTF - -using WTF::Locker; - -#endif +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/PassRefPtr.h b/third_party/WebKit/Source/wtf/PassRefPtr.h index a65d744..0623e52b 100644 --- a/third_party/WebKit/Source/wtf/PassRefPtr.h +++ b/third_party/WebKit/Source/wtf/PassRefPtr.h
@@ -1,224 +1,9 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. - * All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ +// 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. -// PassRefPtr will soon be deleted. -// New code should instead pass ownership of the contents of a RefPtr using -// std::move(). +#include "platform/wtf/PassRefPtr.h" -#ifndef WTF_PassRefPtr_h -#define WTF_PassRefPtr_h - -#include "wtf/Allocator.h" -#include "wtf/Assertions.h" -#include "wtf/Compiler.h" -#include "wtf/TypeTraits.h" - -namespace WTF { - -template <typename T> -class RefPtr; -template <typename T> -class PassRefPtr; -template <typename T> -PassRefPtr<T> adoptRef(T*); - -inline void adopted(const void*) {} - -// requireAdoption() is not overloaded for WTF::RefCounted, which has a built-in -// assumption that adoption is required. requireAdoption() is for bootstrapping -// alternate reference count classes that are compatible with ReftPtr/PassRefPtr -// but cannot have adoption checks enabled by default, such as skia's -// SkRefCnt. The purpose of requireAdoption() is to enable adoption checks only -// once it is known that the object will be used with RefPtr/PassRefPtr. -inline void requireAdoption(const void*) {} - -template <typename T> -ALWAYS_INLINE void refIfNotNull(T* ptr) { - if (LIKELY(ptr != 0)) { - requireAdoption(ptr); - ptr->ref(); - } -} - -template <typename T> -ALWAYS_INLINE void derefIfNotNull(T* ptr) { - if (LIKELY(ptr != 0)) - ptr->deref(); -} - -template <typename T> -class PassRefPtr { - DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); - - public: - PassRefPtr() : m_ptr(nullptr) {} - PassRefPtr(std::nullptr_t) : m_ptr(nullptr) {} - PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } - PassRefPtr(PassRefPtr&& o) : m_ptr(o.leakRef()) {} - template <typename U> - PassRefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) - : m_ptr(o.leakRef()) {} - - ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } - - template <typename U> - PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T)); - template <typename U> - PassRefPtr(RefPtr<U>&&, EnsurePtrConvertibleArgDecl(U, T)); - - T* get() const { return m_ptr; } - - WARN_UNUSED_RESULT T* leakRef() const; - - T& operator*() const { return *m_ptr; } - T* operator->() const { return m_ptr; } - - bool operator!() const { return !m_ptr; } - explicit operator bool() const { return m_ptr != nullptr; } - - friend PassRefPtr adoptRef<T>(T*); - - private: - enum AdoptRefTag { AdoptRef }; - PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) {} - - PassRefPtr& operator=(const PassRefPtr&) { - static_assert(!sizeof(T*), "PassRefPtr should never be assigned to"); - return *this; - } - - mutable T* m_ptr; -}; - -template <typename T> -PassRefPtr<T> wrapPassRefPtr(T* ptr) { - return PassRefPtr<T>(ptr); -} - -template <typename T> -template <typename U> -inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, - EnsurePtrConvertibleArgDefn(U, T)) - : m_ptr(o.get()) { - T* ptr = m_ptr; - refIfNotNull(ptr); -} - -template <typename T> -template <typename U> -inline PassRefPtr<T>::PassRefPtr(RefPtr<U>&& o, - EnsurePtrConvertibleArgDefn(U, T)) - : m_ptr(o.leakRef()) {} - -template <typename T> -inline T* PassRefPtr<T>::leakRef() const { - T* ptr = m_ptr; - m_ptr = nullptr; - return ptr; -} - -template <typename T, typename U> -inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) { - return a.get() == b.get(); -} - -template <typename T, typename U> -inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) { - return a.get() == b.get(); -} - -template <typename T, typename U> -inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) { - return a.get() == b.get(); -} - -template <typename T, typename U> -inline bool operator==(const PassRefPtr<T>& a, U* b) { - return a.get() == b; -} - -template <typename T, typename U> -inline bool operator==(T* a, const PassRefPtr<U>& b) { - return a == b.get(); -} - -template <typename T> -inline bool operator==(const PassRefPtr<T>& a, std::nullptr_t) { - return !a.get(); -} - -template <typename T> -inline bool operator==(std::nullptr_t, const PassRefPtr<T>& b) { - return !b.get(); -} - -template <typename T, typename U> -inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) { - return a.get() != b.get(); -} - -template <typename T, typename U> -inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) { - return a.get() != b.get(); -} - -template <typename T, typename U> -inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) { - return a.get() != b.get(); -} - -template <typename T, typename U> -inline bool operator!=(const PassRefPtr<T>& a, U* b) { - return a.get() != b; -} - -template <typename T, typename U> -inline bool operator!=(T* a, const PassRefPtr<U>& b) { - return a != b.get(); -} - -template <typename T> -inline bool operator!=(const PassRefPtr<T>& a, std::nullptr_t) { - return a.get(); -} - -template <typename T> -inline bool operator!=(std::nullptr_t, const PassRefPtr<T>& b) { - return b.get(); -} - -template <typename T> -PassRefPtr<T> adoptRef(T* p) { - adopted(p); - return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef); -} - -template <typename T> -inline T* getPtr(const PassRefPtr<T>& p) { - return p.get(); -} - -} // namespace WTF - -using WTF::PassRefPtr; -using WTF::adoptRef; - -#endif // WTF_PassRefPtr_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/PtrUtil.h b/third_party/WebKit/Source/wtf/PtrUtil.h index 5184733..b61a57b 100644 --- a/third_party/WebKit/Source/wtf/PtrUtil.h +++ b/third_party/WebKit/Source/wtf/PtrUtil.h
@@ -1,53 +1,9 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// 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 PtrUtil_h -#define PtrUtil_h +#include "platform/wtf/PtrUtil.h" -#include "base/memory/ptr_util.h" -#include "wtf/TypeTraits.h" - -#include <memory> - -namespace WTF { - -template <typename T> -std::unique_ptr<T> wrapUnique(T* ptr) { - static_assert( - !WTF::IsGarbageCollectedType<T>::value, - "Garbage collected types should not be stored in std::unique_ptr!"); - return std::unique_ptr<T>(ptr); -} - -template <typename T> -std::unique_ptr<T[]> wrapArrayUnique(T* ptr) { - static_assert( - !WTF::IsGarbageCollectedType<T>::value, - "Garbage collected types should not be stored in std::unique_ptr!"); - return std::unique_ptr<T[]>(ptr); -} - -// WTF::makeUnique is base::MakeUnique. See base/ptr_util.h for documentation. -template <typename T, typename... Args> -auto makeUnique(Args&&... args) - -> decltype(base::MakeUnique<T>(std::forward<Args>(args)...)) { - static_assert( - !WTF::IsGarbageCollectedType<T>::value, - "Garbage collected types should not be stored in std::unique_ptr!"); - return base::MakeUnique<T>(std::forward<Args>(args)...); -} - -template <typename T> -auto makeUnique(size_t size) -> decltype(base::MakeUnique<T>(size)) { - static_assert( - !WTF::IsGarbageCollectedType<T>::value, - "Garbage collected types should not be stored in std::unique_ptr!"); - return base::MakeUnique<T>(size); -} - -} // namespace WTF - -using WTF::wrapArrayUnique; - -#endif // PtrUtil_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/RefCounted.h b/third_party/WebKit/Source/wtf/RefCounted.h index a2820ea..18654e4 100644 --- a/third_party/WebKit/Source/wtf/RefCounted.h +++ b/third_party/WebKit/Source/wtf/RefCounted.h
@@ -1,171 +1,9 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ +// 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 RefCounted_h -#define RefCounted_h +#include "platform/wtf/RefCounted.h" -#include "wtf/Allocator.h" -#include "wtf/Assertions.h" -#include "wtf/Noncopyable.h" -#include "wtf/WTFExport.h" - -#if ENABLE(INSTANCE_COUNTER) -#include "wtf/InstanceCounter.h" -#endif - -#if DCHECK_IS_ON() -#define CHECK_REF_COUNTED_LIFECYCLE 1 -#include "wtf/ThreadRestrictionVerifier.h" -#else -#define CHECK_REF_COUNTED_LIFECYCLE 0 -#endif - -namespace WTF { - -// This base class holds the non-template methods and attributes. -// The RefCounted class inherits from it reducing the template bloat -// generated by the compiler (technique called template hoisting). -class WTF_EXPORT RefCountedBase { - public: - void ref() const { -#if CHECK_REF_COUNTED_LIFECYCLE - SECURITY_DCHECK(m_verifier.onRef(m_refCount)); - DCHECK(!m_adoptionIsRequired); -#endif - SECURITY_DCHECK(!m_deletionHasBegun); - ++m_refCount; - } - - bool hasOneRef() const { - SECURITY_DCHECK(!m_deletionHasBegun); -#if CHECK_REF_COUNTED_LIFECYCLE - SECURITY_DCHECK(m_verifier.isSafeToUse()); -#endif - return m_refCount == 1; - } - - int refCount() const { -#if CHECK_REF_COUNTED_LIFECYCLE - SECURITY_DCHECK(m_verifier.isSafeToUse()); -#endif - return m_refCount; - } - - protected: - RefCountedBase() - : m_refCount(1) -#if ENABLE(SECURITY_ASSERT) - , - m_deletionHasBegun(false) -#endif -#if CHECK_REF_COUNTED_LIFECYCLE - , - m_adoptionIsRequired(true) -#endif - { - } - - ~RefCountedBase() { - SECURITY_DCHECK(m_deletionHasBegun); -#if CHECK_REF_COUNTED_LIFECYCLE - DCHECK(!m_adoptionIsRequired); -#endif - } - - // Returns whether the pointer should be freed or not. - bool derefBase() const { - SECURITY_DCHECK(!m_deletionHasBegun); -#if CHECK_REF_COUNTED_LIFECYCLE - SECURITY_DCHECK(m_verifier.onDeref(m_refCount)); - DCHECK(!m_adoptionIsRequired); -#endif - - DCHECK_GT(m_refCount, 0); - --m_refCount; - if (!m_refCount) { -#if ENABLE(SECURITY_ASSERT) - m_deletionHasBegun = true; -#endif - return true; - } - - return false; - } - -#if CHECK_REF_COUNTED_LIFECYCLE - bool deletionHasBegun() const { return m_deletionHasBegun; } -#endif - - private: -#if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT) - friend void adopted(RefCountedBase*); -#endif - - mutable int m_refCount; -#if ENABLE(SECURITY_ASSERT) - mutable bool m_deletionHasBegun; -#endif -#if CHECK_REF_COUNTED_LIFECYCLE - mutable bool m_adoptionIsRequired; - mutable ThreadRestrictionVerifier m_verifier; -#endif -}; - -#if CHECK_REF_COUNTED_LIFECYCLE || ENABLE(SECURITY_ASSERT) -inline void adopted(RefCountedBase* object) { - if (!object) - return; - SECURITY_DCHECK(!object->m_deletionHasBegun); -#if CHECK_REF_COUNTED_LIFECYCLE - object->m_adoptionIsRequired = false; -#endif -} -#endif - -template <typename T> -class RefCounted : public RefCountedBase { - WTF_MAKE_NONCOPYABLE(RefCounted); - - // Put |T| in here instead of |RefCounted| so the heap profiler reports |T| - // instead of |RefCounted<T>|. This does not affect overloading of operator - // new. - USING_FAST_MALLOC(T); - - public: - void deref() const { - if (derefBase()) - delete static_cast<const T*>(this); - } - - protected: -#if ENABLE(INSTANCE_COUNTER) - RefCounted() { incrementInstanceCount<T>(static_cast<T*>(this)); } - - ~RefCounted() { decrementInstanceCount<T>(static_cast<T*>(this)); } -#else - RefCounted() {} -#endif -}; - -} // namespace WTF - -using WTF::RefCounted; - -#endif // RefCounted_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/RefPtr.h b/third_party/WebKit/Source/wtf/RefPtr.h index 6dca0985..4fd6f10 100644 --- a/third_party/WebKit/Source/wtf/RefPtr.h +++ b/third_party/WebKit/Source/wtf/RefPtr.h
@@ -1,222 +1,9 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. - * All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ +// 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 WTF_RefPtr_h -#define WTF_RefPtr_h +#include "platform/wtf/RefPtr.h" -#include "wtf/Allocator.h" -#include "wtf/HashTableDeletedValueType.h" -#include "wtf/PassRefPtr.h" -#include "wtf/allocator/PartitionAllocator.h" -#include <algorithm> -#include <utility> - -namespace WTF { - -template <typename T> -class PassRefPtr; -template <typename T> -class RefPtrValuePeeker; - -template <typename T> -class RefPtr { - USING_FAST_MALLOC(RefPtr); - - public: - ALWAYS_INLINE RefPtr() : m_ptr(nullptr) {} - ALWAYS_INLINE RefPtr(std::nullptr_t) : m_ptr(nullptr) {} - ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } - ALWAYS_INLINE explicit RefPtr(T& ref) : m_ptr(&ref) { m_ptr->ref(); } - ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { - refIfNotNull(m_ptr); - } - template <typename U> - RefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) - : m_ptr(o.get()) { - refIfNotNull(m_ptr); - } - RefPtr(RefPtr&& o) : m_ptr(o.m_ptr) { o.m_ptr = nullptr; } - - // See comments in PassRefPtr.h for an explanation of why this takes a const - // reference. - template <typename U> - RefPtr(const PassRefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T)); - - // Hash table deleted values, which are only constructed and never copied or - // destroyed. - RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) {} - bool isHashTableDeletedValue() const { - return m_ptr == hashTableDeletedValue(); - } - - ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); } - - ALWAYS_INLINE T* get() const { return m_ptr; } - T* leakRef() WARN_UNUSED_RESULT; - void clear(); - PassRefPtr<T> release() { - PassRefPtr<T> tmp = adoptRef(m_ptr); - m_ptr = nullptr; - return tmp; - } - - T& operator*() const { return *m_ptr; } - ALWAYS_INLINE T* operator->() const { return m_ptr; } - - bool operator!() const { return !m_ptr; } - explicit operator bool() const { return m_ptr != nullptr; } - - RefPtr& operator=(RefPtr o) { - swap(o); - return *this; - } - RefPtr& operator=(std::nullptr_t) { - clear(); - return *this; - } - // This is required by HashMap<RefPtr>>. - template <typename U> - RefPtr& operator=(RefPtrValuePeeker<U>); - - void swap(RefPtr&); - - static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } - - private: - T* m_ptr; -}; - -template <typename T> -template <typename U> -inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o, - EnsurePtrConvertibleArgDefn(U, T)) - : m_ptr(o.leakRef()) {} - -template <typename T> -inline T* RefPtr<T>::leakRef() { - T* ptr = m_ptr; - m_ptr = nullptr; - return ptr; -} - -template <typename T> -inline void RefPtr<T>::clear() { - T* ptr = m_ptr; - m_ptr = nullptr; - derefIfNotNull(ptr); -} - -template <typename T> -template <typename U> -inline RefPtr<T>& RefPtr<T>::operator=(RefPtrValuePeeker<U> optr) { - RefPtr ptr = static_cast<U*>(optr); - swap(ptr); - return *this; -} - -template <class T> -inline void RefPtr<T>::swap(RefPtr& o) { - std::swap(m_ptr, o.m_ptr); -} - -template <class T> -inline void swap(RefPtr<T>& a, RefPtr<T>& b) { - a.swap(b); -} - -template <typename T, typename U> -inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) { - return a.get() == b.get(); -} - -template <typename T, typename U> -inline bool operator==(const RefPtr<T>& a, U* b) { - return a.get() == b; -} - -template <typename T, typename U> -inline bool operator==(T* a, const RefPtr<U>& b) { - return a == b.get(); -} - -template <typename T> -inline bool operator==(const RefPtr<T>& a, std::nullptr_t) { - return !a.get(); -} - -template <typename T> -inline bool operator==(std::nullptr_t, const RefPtr<T>& b) { - return !b.get(); -} - -template <typename T, typename U> -inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) { - return a.get() != b.get(); -} - -template <typename T, typename U> -inline bool operator!=(const RefPtr<T>& a, U* b) { - return a.get() != b; -} - -template <typename T, typename U> -inline bool operator!=(T* a, const RefPtr<U>& b) { - return a != b.get(); -} - -template <typename T> -inline bool operator!=(const RefPtr<T>& a, std::nullptr_t) { - return a.get(); -} - -template <typename T> -inline bool operator!=(std::nullptr_t, const RefPtr<T>& b) { - return b.get(); -} - -template <typename T> -inline T* getPtr(const RefPtr<T>& p) { - return p.get(); -} - -template <typename T> -class RefPtrValuePeeker { - DISALLOW_NEW(); - - public: - ALWAYS_INLINE RefPtrValuePeeker(T* p) : m_ptr(p) {} - ALWAYS_INLINE RefPtrValuePeeker(std::nullptr_t) : m_ptr(nullptr) {} - template <typename U> - RefPtrValuePeeker(const RefPtr<U>& p) : m_ptr(p.get()) {} - template <typename U> - RefPtrValuePeeker(const PassRefPtr<U>& p) : m_ptr(p.get()) {} - - ALWAYS_INLINE operator T*() const { return m_ptr; } - - private: - T* m_ptr; -}; - -} // namespace WTF - -using WTF::RefPtr; - -#endif // WTF_RefPtr_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/StackUtil.h b/third_party/WebKit/Source/wtf/StackUtil.h index c9b9e84..7c0be57 100644 --- a/third_party/WebKit/Source/wtf/StackUtil.h +++ b/third_party/WebKit/Source/wtf/StackUtil.h
@@ -2,48 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef StackUtil_h -#define StackUtil_h +#include "platform/wtf/StackUtil.h" -#include "wtf/Compiler.h" -#include "wtf/WTFExport.h" -#include "wtf/build_config.h" -#include <stddef.h> -#include <stdint.h> - -namespace WTF { - -WTF_EXPORT size_t getUnderestimatedStackSize(); -WTF_EXPORT void* getStackStart(); - -namespace internal { - -WTF_EXPORT extern uintptr_t s_mainThreadStackStart; -WTF_EXPORT extern uintptr_t s_mainThreadUnderestimatedStackSize; - -WTF_EXPORT void initializeMainThreadStackEstimate(); - -#if OS(WIN) && COMPILER(MSVC) -size_t threadStackSize(); -#endif - -} // namespace internal - -// Returns true if the function is not called on the main thread. Note carefully -// that this function may have false positives, i.e. it can return true even if -// we are on the main thread. If the function returns false, we are certainly -// on the main thread. -inline bool mayNotBeMainThread() { - uintptr_t dummy; - uintptr_t addressDiff = - internal::s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy); - // This is a fast way to judge if we are in the main thread. - // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from - // the stack start of the main thread, we judge that we are in - // the main thread. - return addressDiff >= internal::s_mainThreadUnderestimatedStackSize; -} - -} // namespace WTF - -#endif // StackUtil_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/StdLibExtras.h b/third_party/WebKit/Source/wtf/StdLibExtras.h index b83d321a..ec81685 100644 --- a/third_party/WebKit/Source/wtf/StdLibExtras.h +++ b/third_party/WebKit/Source/wtf/StdLibExtras.h
@@ -1,269 +1,9 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 WTF_StdLibExtras_h -#define WTF_StdLibExtras_h +#include "platform/wtf/StdLibExtras.h" -#include <cstddef> -#include "base/numerics/safe_conversions.h" -#include "wtf/Assertions.h" -#include "wtf/CPU.h" -#include "wtf/LeakAnnotations.h" -#include "wtf/Noncopyable.h" -#include "wtf/TypeTraits.h" - -#if DCHECK_IS_ON() -#include "wtf/Threading.h" -#endif - -// Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable -// (|static T;|) so that it is leaked and its destructors are not called at -// exit. T may also be a Blink garbage collected object, in which case it is -// wrapped up by an off-heap |Persistent<T>| reference to the object, keeping -// it alive across GCs. -// -// A |DEFINE_STATIC_LOCAL()| static should only be used on the thread it was -// created on. -// -#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ - static WTF::StaticSingleton<Type> s_##Name( \ - new WTF::StaticSingleton<Type>::WrapperType Arguments); \ - Type& Name = s_##Name.get(false) - -// |DEFINE_THREAD_SAFE_STATIC_LOCAL()| is the cross-thread accessible variant -// of |DEFINE_STATIC_LOCAL()|; use it if the singleton can be accessed by -// multiple threads. -// -// TODO: rename as DEFINE_CROSS_THREAD_STATIC_LOCAL() ? -#define DEFINE_THREAD_SAFE_STATIC_LOCAL(Type, Name, Initializer) \ - static WTF::StaticSingleton<Type> s_##Name(Initializer); \ - Type& Name = s_##Name.get(true) - -namespace blink { -template <typename T> -class Persistent; - -} // namespace blink - -namespace WTF { - -template <typename Type> -class StaticSingleton final { - WTF_MAKE_NONCOPYABLE(StaticSingleton); - - public: - template <typename T, - bool = WTF::IsGarbageCollectedType<T>::value && - !WTF::IsPersistentReferenceType<T>::value> - struct Wrapper { - using type = T; - - static T& unwrap(T* singleton) { return *singleton; } - }; - - template <typename T> - struct Wrapper<T, true> { - using type = blink::Persistent<T>; - - static T& unwrap(blink::Persistent<T>* singleton) { - DCHECK(singleton); - // If this assert triggers, you're supplying an empty ("()") 'Arguments' - // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish - // to create as a static singleton and wrapped up with a Persistent - // reference. - DCHECK(*singleton); - return **singleton; - } - }; - - using WrapperType = typename Wrapper<Type>::type; - - // To cooperate with leak detection(LSan) for Blink garbage collected objects, - // the objects owned by persistent local statics will in some cases have to be - // finalized prior to leak checking. This only applies to static references to - // Blink heap objects and what they transitively hold on to. Hence the - // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy - // details. - - explicit StaticSingleton(WrapperType* instance) - : m_instance(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance)) -#if DCHECK_IS_ON() - , - m_safelyInitialized(WTF::isBeforeThreadCreated()), - m_thread(WTF::internal::currentThreadSyscall()) -#endif - { - } - - Type& get(bool allowCrossThreadUse) const { -#if DCHECK_IS_ON() - DCHECK(isNotRacy(allowCrossThreadUse)); -#endif - ALLOW_UNUSED_LOCAL(allowCrossThreadUse); - return Wrapper<Type>::unwrap(m_instance); - } - - operator Type&() { return get(); } - - private: -#if DCHECK_IS_ON() - - bool isNotRacy(bool allowCrossThreadUse) const { - // Make sure that singleton is safely initialized, or - // keeps being called on the same thread if cross-thread - // use is not permitted. - return allowCrossThreadUse || m_safelyInitialized || - m_thread == WTF::internal::currentThreadSyscall(); - } -#endif - - WrapperType* m_instance; -#if DCHECK_IS_ON() - bool m_safelyInitialized; - ThreadIdentifier m_thread; -#endif -}; - -} // namespace WTF - -// Use this to declare and define a static local pointer to a ref-counted object -// so that it is leaked so that the object's destructors are not called at -// exit. This macro should be used with ref-counted objects rather than -// DEFINE_STATIC_LOCAL macro, as this macro does not lead to an extra memory -// allocation. -#define DEFINE_STATIC_REF(type, name, arguments) \ - static type* name = PassRefPtr<type>(arguments).leakRef(); - -/* - * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where - * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: - * increases required alignment of target type. - * - * An implicit or an extra static_cast<void*> bypasses the warning. - * For more info see the following bugzilla entries: - * - https://bugs.webkit.org/show_bug.cgi?id=38045 - * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 - */ -#if CPU(ARM) && COMPILER(GCC) -template <typename Type> -bool isPointerTypeAlignmentOkay(Type* ptr) { - return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type)); -} - -template <typename TypePtr> -TypePtr reinterpret_cast_ptr(void* ptr) { - DCHECK(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); - return reinterpret_cast<TypePtr>(ptr); -} - -template <typename TypePtr> -TypePtr reinterpret_cast_ptr(const void* ptr) { - DCHECK(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); - return reinterpret_cast<TypePtr>(ptr); -} -#else -template <typename Type> -bool isPointerTypeAlignmentOkay(Type*) { - return true; -} -#define reinterpret_cast_ptr reinterpret_cast -#endif - -namespace WTF { - -/* - * C++'s idea of a reinterpret_cast lacks sufficient cojones. - */ -template <typename TO, typename FROM> -inline TO bitwiseCast(FROM from) { - static_assert(sizeof(TO) == sizeof(FROM), - "WTF::bitwiseCast sizeof casted types should be equal"); - union { - FROM from; - TO to; - } u; - u.from = from; - return u.to; -} - -template <typename To, typename From> -inline To safeCast(From value) { - return base::checked_cast<To>(value); -} - -// Use the following macros to prevent errors caused by accidental -// implicit casting of function arguments. For example, this can -// be used to prevent overflows from non-promoting conversions. -// -// Example: -// -// HAS_STRICTLY_TYPED_ARG -// void sendData(void* data, STRICTLY_TYPED_ARG(size)) -// { -// ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t); -// ... -// } -// -// The previous example will prevent callers from passing, for example, an -// 'int'. On a 32-bit build, it will prevent use of an 'unsigned long long'. -#define HAS_STRICTLY_TYPED_ARG template <typename ActualArgType> -#define STRICTLY_TYPED_ARG(argName) ActualArgType argName -#define STRICT_ARG_TYPE(ExpectedArgType) \ - static_assert(std::is_same<ActualArgType, ExpectedArgType>::value, \ - "Strictly typed argument must be of type '" #ExpectedArgType \ - "'.") -#define ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(ExpectedArgType) \ - static_assert( \ - std::numeric_limits<ExpectedArgType>::is_integer == \ - std::numeric_limits<ActualArgType>::is_integer, \ - "Conversion between integer and non-integer types not allowed."); \ - static_assert(sizeof(ExpectedArgType) >= sizeof(ActualArgType), \ - "Truncating conversions not allowed."); \ - static_assert(!std::numeric_limits<ActualArgType>::is_signed || \ - std::numeric_limits<ExpectedArgType>::is_signed, \ - "Signed to unsigned conversion not allowed."); \ - static_assert((sizeof(ExpectedArgType) != sizeof(ActualArgType)) || \ - (std::numeric_limits<ActualArgType>::is_signed == \ - std::numeric_limits<ExpectedArgType>::is_signed), \ - "Unsigned to signed conversion not allowed for types with " \ - "identical size (could overflow)."); - -// Macro that returns a compile time constant with the length of an array, but -// gives an error if passed a non-array. -template <typename T, size_t Size> -char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; -// GCC needs some help to deduce a 0 length array. -#if COMPILER(GCC) -template <typename T> -char (&ArrayLengthHelperFunction(T (&)[0]))[0]; -#endif -#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) - -} // namespace WTF - -using WTF::bitwiseCast; -using WTF::safeCast; - -#endif // WTF_StdLibExtras_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/ThreadRestrictionVerifier.h b/third_party/WebKit/Source/wtf/ThreadRestrictionVerifier.h index 5af787c..fb22bea 100644 --- a/third_party/WebKit/Source/wtf/ThreadRestrictionVerifier.h +++ b/third_party/WebKit/Source/wtf/ThreadRestrictionVerifier.h
@@ -1,108 +1,9 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 ThreadRestrictionVerifier_h -#define ThreadRestrictionVerifier_h +#include "platform/wtf/ThreadRestrictionVerifier.h" -#include "wtf/Assertions.h" - -#if DCHECK_IS_ON() - -#include "wtf/Threading.h" - -namespace WTF { - -// Verifies that a class is used in a way that respects its lack of -// thread-safety. The default mode is to verify that the object will only be -// used on a single thread. The thread gets captured when setShared(true) is -// called. The mode may be changed by calling useMutexMode (or -// turnOffVerification). -class ThreadRestrictionVerifier { - public: - ThreadRestrictionVerifier() : m_shared(false), m_owningThread(0) {} - - // Call onRef() before refCount is incremented in ref(). Returns whether the - // ref() is safe. - template <typename COUNTERTYPE> - bool onRef(COUNTERTYPE refCount) { - // Start thread verification as soon as the ref count gets to 2. This - // heuristic reflects the fact that items are often created on one - // thread and then given to another thread to be used. - // FIXME: Make this restriction tigher. Especially as we move to more - // common methods for sharing items across threads like - // CrossThreadCopier.h - // We should be able to add a "detachFromThread" method to make this - // explicit. - if (refCount == 1) - setShared(true); - return isSafeToUse(); - } - - // Call onDeref() before refCount is decremented in deref(). Returns whether - // the deref() is safe. - template <typename COUNTERTYPE> - bool onDeref(COUNTERTYPE refCount) { - bool safe = isSafeToUse(); - // Stop thread verification when the ref goes to 1 because it - // is safe to be passed to another thread at this point. - if (refCount == 2) - setShared(false); - return safe; - } - - // Is it OK to use the object at this moment on the current thread? - bool isSafeToUse() const { - return !m_shared || m_owningThread == currentThread(); - } - - private: - // Indicates that the object may (or may not) be owned by more than one place. - void setShared(bool shared) { - bool previouslyShared = m_shared; - m_shared = shared; - - if (!m_shared) - return; - - DCHECK_NE(shared, previouslyShared); - // Capture the current thread to verify that subsequent ref/deref happen on - // this thread. - m_owningThread = currentThread(); - } - - bool m_shared; - - ThreadIdentifier m_owningThread; -}; - -} // namespace WTF - -#endif // DCHECK_IS_ON() -#endif // ThreadRestrictionVerifier_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h b/third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h index c7814bd..e6252f9 100644 --- a/third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h +++ b/third_party/WebKit/Source/wtf/ThreadSafeRefCounted.h
@@ -1,86 +1,9 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 ThreadSafeRefCounted_h -#define ThreadSafeRefCounted_h +#include "platform/wtf/ThreadSafeRefCounted.h" -#include "wtf/Allocator.h" -#include "wtf/Atomics.h" -#include "wtf/DynamicAnnotations.h" -#include "wtf/Noncopyable.h" -#include "wtf/WTFExport.h" - -namespace WTF { - -class WTF_EXPORT ThreadSafeRefCountedBase { - WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase); - USING_FAST_MALLOC(ThreadSafeRefCountedBase); - - public: - ThreadSafeRefCountedBase(int initialRefCount = 1) - : m_refCount(initialRefCount) {} - - void ref() { atomicIncrement(&m_refCount); } - - bool hasOneRef() { return refCount() == 1; } - - int refCount() const { return static_cast<int const volatile&>(m_refCount); } - - protected: - // Returns whether the pointer should be freed or not. - bool derefBase() { - WTF_ANNOTATE_HAPPENS_BEFORE(&m_refCount); - if (atomicDecrement(&m_refCount) <= 0) { - WTF_ANNOTATE_HAPPENS_AFTER(&m_refCount); - return true; - } - return false; - } - - private: - int m_refCount; -}; - -template <class T> -class ThreadSafeRefCounted : public ThreadSafeRefCountedBase { - public: - void deref() { - if (derefBase()) - delete static_cast<T*>(this); - } - - protected: - ThreadSafeRefCounted() {} -}; - -} // namespace WTF - -using WTF::ThreadSafeRefCounted; - -#endif // ThreadSafeRefCounted_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/ThreadSpecific.h b/third_party/WebKit/Source/wtf/ThreadSpecific.h index 57c6392..25935b0c 100644 --- a/third_party/WebKit/Source/wtf/ThreadSpecific.h +++ b/third_party/WebKit/Source/wtf/ThreadSpecific.h
@@ -1,316 +1,9 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Jian Li <jianli@chromium.org> - * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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. -/* Thread local storage is implemented by using either pthread API or Windows - * native API. There is subtle semantic discrepancy for the cleanup function - * implementation as noted below: - * @ In pthread implementation, the destructor function will be called - * repeatedly if there is still non-NULL value associated with the function. - * @ In Windows native implementation, the destructor function will be called - * only once. - * This semantic discrepancy does not impose any problem because nowhere in - * WebKit the repeated call bahavior is utilized. - */ +#include "platform/wtf/ThreadSpecific.h" -#ifndef WTF_ThreadSpecific_h -#define WTF_ThreadSpecific_h - -#include "wtf/Allocator.h" -#include "wtf/Noncopyable.h" -#include "wtf/StackUtil.h" -#include "wtf/StdLibExtras.h" -#include "wtf/WTF.h" -#include "wtf/WTFExport.h" -#include "wtf/allocator/PartitionAllocator.h" -#include "wtf/allocator/Partitions.h" - -#if OS(POSIX) -#include <pthread.h> -#elif OS(WIN) -#include <windows.h> -#endif - -namespace WTF { - -#if OS(WIN) -// ThreadSpecificThreadExit should be called each time when a thread is -// detached. -// This is done automatically for threads created with WTF::createThread. -WTF_EXPORT void ThreadSpecificThreadExit(); -#endif - -template <typename T> -class ThreadSpecific { - USING_FAST_MALLOC(ThreadSpecific); - WTF_MAKE_NONCOPYABLE(ThreadSpecific); - - public: - ThreadSpecific(); - bool - isSet(); // Useful as a fast check to see if this thread has set this value. - T* operator->(); - operator T*(); - T& operator*(); - - private: -#if OS(WIN) - WTF_EXPORT friend void ThreadSpecificThreadExit(); -#endif - - // Not implemented. It's technically possible to destroy a thread specific - // key, but one would need to make sure that all values have been destroyed - // already (usually, that all threads that used it have exited). It's - // unlikely that any user of this call will be in that situation - and having - // a destructor defined can be confusing, given that it has such strong - // pre-requisites to work correctly. - ~ThreadSpecific(); - - T* get(); - void set(T*); - void static destroy(void* ptr); - - struct Data { - WTF_MAKE_NONCOPYABLE(Data); - - public: - Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} - - T* value; - ThreadSpecific<T>* owner; -#if OS(WIN) - void (*destructor)(void*); -#endif - }; - -#if OS(POSIX) - pthread_key_t m_key; -#elif OS(WIN) - int m_index; -#endif - // This member must only be accessed or modified on the main thread. - T* m_mainThreadStorage = nullptr; -}; - -#if OS(POSIX) - -typedef pthread_key_t ThreadSpecificKey; - -inline void threadSpecificKeyCreate(ThreadSpecificKey* key, - void (*destructor)(void*)) { - int error = pthread_key_create(key, destructor); - if (error) - CRASH(); -} - -inline void threadSpecificKeyDelete(ThreadSpecificKey key) { - int error = pthread_key_delete(key); - if (error) - CRASH(); -} - -inline void threadSpecificSet(ThreadSpecificKey key, void* value) { - pthread_setspecific(key, value); -} - -inline void* threadSpecificGet(ThreadSpecificKey key) { - return pthread_getspecific(key); -} - -template <typename T> -inline ThreadSpecific<T>::ThreadSpecific() { - int error = pthread_key_create(&m_key, destroy); - if (error) - CRASH(); -} - -template <typename T> -inline T* ThreadSpecific<T>::get() { - Data* data = static_cast<Data*>(pthread_getspecific(m_key)); - return data ? data->value : 0; -} - -template <typename T> -inline void ThreadSpecific<T>::set(T* ptr) { - DCHECK(!get()); - pthread_setspecific(m_key, new Data(ptr, this)); -} - -#elif OS(WIN) - -// TLS_OUT_OF_INDEXES is not defined on WinCE. -#ifndef TLS_OUT_OF_INDEXES -#define TLS_OUT_OF_INDEXES 0xffffffff -#endif - -// The maximum number of TLS keys that can be created. For simplification, we -// assume that: -// 1) Once the instance of ThreadSpecific<> is created, it will not be -// destructed until the program dies. -// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed -// number should be far enough. -const int kMaxTlsKeySize = 256; - -WTF_EXPORT long& tlsKeyCount(); -WTF_EXPORT DWORD* tlsKeys(); - -class PlatformThreadSpecificKey; -typedef PlatformThreadSpecificKey* ThreadSpecificKey; - -WTF_EXPORT void threadSpecificKeyCreate(ThreadSpecificKey*, void (*)(void*)); -WTF_EXPORT void threadSpecificKeyDelete(ThreadSpecificKey); -WTF_EXPORT void threadSpecificSet(ThreadSpecificKey, void*); -WTF_EXPORT void* threadSpecificGet(ThreadSpecificKey); - -template <typename T> -inline ThreadSpecific<T>::ThreadSpecific() : m_index(-1) { - DWORD tlsKey = TlsAlloc(); - if (tlsKey == TLS_OUT_OF_INDEXES) - CRASH(); - - m_index = InterlockedIncrement(&tlsKeyCount()) - 1; - if (m_index >= kMaxTlsKeySize) - CRASH(); - tlsKeys()[m_index] = tlsKey; -} - -template <typename T> -inline ThreadSpecific<T>::~ThreadSpecific() { - // Does not invoke destructor functions. They will be called from - // ThreadSpecificThreadExit when the thread is detached. - TlsFree(tlsKeys()[m_index]); -} - -template <typename T> -inline T* ThreadSpecific<T>::get() { - Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); - return data ? data->value : 0; -} - -template <typename T> -inline void ThreadSpecific<T>::set(T* ptr) { - DCHECK(!get()); - Data* data = new Data(ptr, this); - data->destructor = &ThreadSpecific<T>::destroy; - TlsSetValue(tlsKeys()[m_index], data); -} - -#else -#error ThreadSpecific is not implemented for this platform. -#endif - -template <typename T> -inline void ThreadSpecific<T>::destroy(void* ptr) { - Data* data = static_cast<Data*>(ptr); - -#if OS(POSIX) - // We want get() to keep working while data destructor works, because it can - // be called indirectly by the destructor. Some pthreads implementations - // zero out the pointer before calling destroy(), so we temporarily reset it. - pthread_setspecific(data->owner->m_key, ptr); -#endif - - // Never call destructors on the main thread. This is fine because Blink no - // longer has a graceful shutdown sequence. Be careful to call this function - // (which can be re-entrant) while the pointer is still set, to avoid lazily - // allocating WTFThreadData after it is destroyed. - if (isMainThread()) - return; - - data->value->~T(); - Partitions::fastFree(data->value); - -#if OS(POSIX) - pthread_setspecific(data->owner->m_key, 0); -#elif OS(WIN) - TlsSetValue(tlsKeys()[data->owner->m_index], 0); -#else -#error ThreadSpecific is not implemented for this platform. -#endif - - delete data; -} - -template <typename T> -inline bool ThreadSpecific<T>::isSet() { - return !!get(); -} - -template <typename T> -inline ThreadSpecific<T>::operator T*() { - T* offThreadPtr; -#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) - // TLS is fast on these platforms. - // TODO(csharrison): Qualify this statement for Android. - const bool mainThreadAlwaysChecksTLS = true; - T** ptr = &offThreadPtr; - offThreadPtr = static_cast<T*>(get()); -#else - const bool mainThreadAlwaysChecksTLS = false; - T** ptr = &m_mainThreadStorage; - if (UNLIKELY(mayNotBeMainThread())) { - offThreadPtr = static_cast<T*>(get()); - ptr = &offThreadPtr; - } -#endif - // Set up thread-specific value's memory pointer before invoking constructor, - // in case any function it calls needs to access the value, to avoid - // recursion. - if (UNLIKELY(!*ptr)) { - *ptr = static_cast<T*>(Partitions::fastZeroedMalloc( - sizeof(T), WTF_HEAP_PROFILER_TYPE_NAME(T))); - - // Even if we didn't realize we're on the main thread, we might still be. - // We need to double-check so that |m_mainThreadStorage| is populated. - if (!mainThreadAlwaysChecksTLS && UNLIKELY(ptr != &m_mainThreadStorage) && - isMainThread()) { - m_mainThreadStorage = *ptr; - } - - set(*ptr); - new (NotNull, *ptr) T; - } - return *ptr; -} - -template <typename T> -inline T* ThreadSpecific<T>::operator->() { - return operator T*(); -} - -template <typename T> -inline T& ThreadSpecific<T>::operator*() { - return *operator T*(); -} - -} // namespace WTF - -using WTF::ThreadSpecific; - -#endif // WTF_ThreadSpecific_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/Threading.h b/third_party/WebKit/Source/wtf/Threading.h index 4c78f22..0210ff1 100644 --- a/third_party/WebKit/Source/wtf/Threading.h +++ b/third_party/WebKit/Source/wtf/Threading.h
@@ -1,66 +1,9 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 Threading_h -#define Threading_h +#include "platform/wtf/Threading.h" -#include "wtf/Atomics.h" -#include "wtf/TypeTraits.h" -#include "wtf/WTFExport.h" -#include <stdint.h> - -namespace WTF { - -#if OS(WIN) -typedef uint32_t ThreadIdentifier; -#else -typedef intptr_t ThreadIdentifier; -#endif - -namespace internal { -WTF_EXPORT ThreadIdentifier currentThreadSyscall(); -} // namespace internal - -// Initializes global state required by |currentThread|. -// Needs to be called once during program execution, before |currentThread|. -WTF_EXPORT void initializeCurrentThread(); - -WTF_EXPORT ThreadIdentifier currentThread(); - -#if DCHECK_IS_ON() -WTF_EXPORT bool isBeforeThreadCreated(); -WTF_EXPORT void willCreateThread(); -#endif - -} // namespace WTF - -using WTF::ThreadIdentifier; -using WTF::currentThread; - -#endif // Threading_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/ThreadingPrimitives.h b/third_party/WebKit/Source/wtf/ThreadingPrimitives.h index 84b72a6..0f40588 100644 --- a/third_party/WebKit/Source/wtf/ThreadingPrimitives.h +++ b/third_party/WebKit/Source/wtf/ThreadingPrimitives.h
@@ -1,175 +1,9 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ +// 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 ThreadingPrimitives_h -#define ThreadingPrimitives_h +#include "platform/wtf/ThreadingPrimitives.h" -#include "wtf/Allocator.h" -#include "wtf/Assertions.h" -#include "wtf/Locker.h" -#include "wtf/Noncopyable.h" -#include "wtf/WTFExport.h" - -#if OS(WIN) -#include <windows.h> -#endif - -#if OS(POSIX) -#include <pthread.h> -#endif - -namespace WTF { - -#if OS(POSIX) -struct PlatformMutex { - pthread_mutex_t m_internalMutex; -#if DCHECK_IS_ON() - size_t m_recursionCount; -#endif -}; -typedef pthread_cond_t PlatformCondition; -#elif OS(WIN) -struct PlatformMutex { - CRITICAL_SECTION m_internalMutex; - size_t m_recursionCount; -}; -struct PlatformCondition { - size_t m_waitersGone; - size_t m_waitersBlocked; - size_t m_waitersToUnblock; - HANDLE m_blockLock; - HANDLE m_blockQueue; - HANDLE m_unblockLock; - - bool timedWait(PlatformMutex&, DWORD durationMilliseconds); - void signal(bool unblockAll); -}; -#else -typedef void* PlatformMutex; -typedef void* PlatformCondition; -#endif - -class WTF_EXPORT MutexBase { - WTF_MAKE_NONCOPYABLE(MutexBase); - USING_FAST_MALLOC(MutexBase); - - public: - ~MutexBase(); - - void lock(); - void unlock(); -#if DCHECK_IS_ON() - bool locked() { return m_mutex.m_recursionCount > 0; } -#endif - - public: - PlatformMutex& impl() { return m_mutex; } - - protected: - MutexBase(bool recursive); - - PlatformMutex m_mutex; -}; - -class WTF_EXPORT Mutex : public MutexBase { - public: - Mutex() : MutexBase(false) {} - bool tryLock(); -}; - -class WTF_EXPORT RecursiveMutex : public MutexBase { - public: - RecursiveMutex() : MutexBase(true) {} - bool tryLock(); -}; - -typedef Locker<MutexBase> MutexLocker; - -class MutexTryLocker final { - STACK_ALLOCATED(); - WTF_MAKE_NONCOPYABLE(MutexTryLocker); - - public: - MutexTryLocker(Mutex& mutex) : m_mutex(mutex), m_locked(mutex.tryLock()) {} - ~MutexTryLocker() { - if (m_locked) - m_mutex.unlock(); - } - - bool locked() const { return m_locked; } - - private: - Mutex& m_mutex; - bool m_locked; -}; - -class WTF_EXPORT ThreadCondition final { - USING_FAST_MALLOC(ThreadCondition); // Only HeapTest.cpp requires. - WTF_MAKE_NONCOPYABLE(ThreadCondition); - - public: - ThreadCondition(); - ~ThreadCondition(); - - void wait(MutexBase&); - // Returns true if the condition was signaled before absoluteTime, false if - // the absoluteTime was reached or is in the past. - // The absoluteTime is in seconds, starting on January 1, 1970. The time is - // assumed to use the same time zone as WTF::currentTime(). - bool timedWait(MutexBase&, double absoluteTime); - void signal(); - void broadcast(); - - private: - PlatformCondition m_condition; -}; - -#if OS(WIN) -// The absoluteTime is in seconds, starting on January 1, 1970. The time is -// assumed to use the same time zone as WTF::currentTime(). -// Returns an interval in milliseconds suitable for passing to one of the Win32 -// wait functions (e.g., ::WaitForSingleObject). -DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime); -#endif - -} // namespace WTF - -using WTF::MutexBase; -using WTF::Mutex; -using WTF::RecursiveMutex; -using WTF::MutexLocker; -using WTF::MutexTryLocker; -using WTF::ThreadCondition; - -#if OS(WIN) -using WTF::absoluteTimeToWaitTimeoutInterval; -#endif - -#endif // ThreadingPrimitives_h +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/TreeNode.h b/third_party/WebKit/Source/wtf/TreeNode.h index ce0fecd3..071039fb 100644 --- a/third_party/WebKit/Source/wtf/TreeNode.h +++ b/third_party/WebKit/Source/wtf/TreeNode.h
@@ -1,212 +1,9 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 TreeNode_h -#define TreeNode_h +#include "platform/wtf/TreeNode.h" -#include "wtf/Assertions.h" - -namespace WTF { - -// -// TreeNode is generic, ContainerNode-like linked tree data structure. -// There are a few notable difference between TreeNode and Node: -// -// * Each TreeNode node is NOT ref counted. The user have to retain its -// lifetime somehow. -// FIXME: lifetime management could be parameterized so that ref counted -// implementations can be used. -// * It checks invalid input. The callers have to ensure that given -// parameter is sound. -// * There is no branch-leaf difference. Every node can be a parent of other -// node. -// -// FIXME: oilpan: Trace tree node edges to ensure we don't have dangling -// pointers. -// As it is used in HTMLImport it is safe since they all die together. -template <class T> -class TreeNode { - public: - typedef T NodeType; - - TreeNode() - : m_next(0), - m_previous(0), - m_parent(0), - m_firstChild(0), - m_lastChild(0) {} - - NodeType* next() const { return m_next; } - NodeType* previous() const { return m_previous; } - NodeType* parent() const { return m_parent; } - NodeType* firstChild() const { return m_firstChild; } - NodeType* lastChild() const { return m_lastChild; } - NodeType* here() const { - return static_cast<NodeType*>(const_cast<TreeNode*>(this)); - } - - bool orphan() const { - return !m_parent && !m_next && !m_previous && !m_firstChild && !m_lastChild; - } - bool hasChildren() const { return m_firstChild; } - - void insertBefore(NodeType* newChild, NodeType* refChild) { - DCHECK(!newChild->parent()); - DCHECK(!newChild->next()); - DCHECK(!newChild->previous()); - - DCHECK(!refChild || this == refChild->parent()); - - if (!refChild) { - appendChild(newChild); - return; - } - - NodeType* newPrevious = refChild->previous(); - newChild->m_parent = here(); - newChild->m_next = refChild; - newChild->m_previous = newPrevious; - refChild->m_previous = newChild; - if (newPrevious) - newPrevious->m_next = newChild; - else - m_firstChild = newChild; - } - - void appendChild(NodeType* child) { - DCHECK(!child->parent()); - DCHECK(!child->next()); - DCHECK(!child->previous()); - - child->m_parent = here(); - - if (!m_lastChild) { - DCHECK(!m_firstChild); - m_lastChild = m_firstChild = child; - return; - } - - DCHECK(!m_lastChild->m_next); - NodeType* oldLast = m_lastChild; - m_lastChild = child; - - child->m_previous = oldLast; - oldLast->m_next = child; - } - - NodeType* removeChild(NodeType* child) { - DCHECK_EQ(child->parent(), this); - - if (m_firstChild == child) - m_firstChild = child->next(); - if (m_lastChild == child) - m_lastChild = child->previous(); - - NodeType* oldNext = child->next(); - NodeType* oldPrevious = child->previous(); - child->m_parent = child->m_next = child->m_previous = 0; - - if (oldNext) - oldNext->m_previous = oldPrevious; - if (oldPrevious) - oldPrevious->m_next = oldNext; - - return child; - } - - void takeChildrenFrom(NodeType* oldParent) { - DCHECK_NE(oldParent, this); - while (oldParent->hasChildren()) { - NodeType* child = oldParent->firstChild(); - oldParent->removeChild(child); - this->appendChild(child); - } - } - - private: - NodeType* m_next; - NodeType* m_previous; - NodeType* m_parent; - NodeType* m_firstChild; - NodeType* m_lastChild; -}; - -template <class T> -inline typename TreeNode<T>::NodeType* traverseNext( - const TreeNode<T>* current, - const TreeNode<T>* stayWithin = 0) { - if (typename TreeNode<T>::NodeType* next = current->firstChild()) - return next; - if (current == stayWithin) - return 0; - if (typename TreeNode<T>::NodeType* next = current->next()) - return next; - for (typename TreeNode<T>::NodeType* parent = current->parent(); parent; - parent = parent->parent()) { - if (parent == stayWithin) - return 0; - if (typename TreeNode<T>::NodeType* next = parent->next()) - return next; - } - - return 0; -} - -template <class T> -inline typename TreeNode<T>::NodeType* traverseFirstPostOrder( - const TreeNode<T>* current) { - typename TreeNode<T>::NodeType* first = current->here(); - while (first->firstChild()) - first = first->firstChild(); - return first; -} - -template <class T> -inline typename TreeNode<T>::NodeType* traverseNextPostOrder( - const TreeNode<T>* current, - const TreeNode<T>* stayWithin = 0) { - if (current == stayWithin) - return 0; - - typename TreeNode<T>::NodeType* next = current->next(); - if (!next) - return current->parent(); - while (next->firstChild()) - next = next->firstChild(); - return next; -} - -} // namespace WTF - -using WTF::TreeNode; -using WTF::traverseNext; -using WTF::traverseNextPostOrder; - -#endif +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/WebKit/Source/wtf/WeakPtr.h b/third_party/WebKit/Source/wtf/WeakPtr.h index cddba0cf..6f751b85 100644 --- a/third_party/WebKit/Source/wtf/WeakPtr.h +++ b/third_party/WebKit/Source/wtf/WeakPtr.h
@@ -1,60 +1,9 @@ -/* - * Copyright (C) 2013 Google, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +// 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 WTF_WeakPtr_h -#define WTF_WeakPtr_h +#include "platform/wtf/WeakPtr.h" -#include "base/memory/weak_ptr.h" -#include "wtf/Noncopyable.h" - -namespace WTF { - -template <typename T> -using WeakPtr = base::WeakPtr<T>; - -template <typename T> -class WeakPtrFactory { - WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>); - USING_FAST_MALLOC(WeakPtrFactory); - - public: - explicit WeakPtrFactory(T* ptr) : m_factory(ptr) {} - - WeakPtr<T> createWeakPtr() { return m_factory.GetWeakPtr(); } - - void revokeAll() { m_factory.InvalidateWeakPtrs(); } - - bool hasWeakPtrs() const { return m_factory.HasWeakPtrs(); } - - private: - base::WeakPtrFactory<T> m_factory; -}; - -} // namespace WTF - -using WTF::WeakPtr; -using WTF::WeakPtrFactory; - -#endif +// The contents of this header was moved to platform/wtf as part of +// WTF migration project. See the following post for details: +// https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gYCAAJ
diff --git a/third_party/hamcrest/BUILD.gn b/third_party/hamcrest/BUILD.gn index 3680c10..3c0c4d4 100644 --- a/third_party/hamcrest/BUILD.gn +++ b/third_party/hamcrest/BUILD.gn
@@ -17,16 +17,19 @@ supports_android = true testonly = true jar_path = "lib/hamcrest-core-1.3.jar" + proguard_configs = [ "//third_party/hamcrest/proguard.flags" ] } java_prebuilt("hamcrest_integration_java") { supports_android = true testonly = true jar_path = "lib/hamcrest-integration-1.3.jar" + proguard_configs = [ "//third_party/hamcrest/proguard.flags" ] } java_prebuilt("hamcrest_library_java") { supports_android = true testonly = true jar_path = "lib/hamcrest-library-1.3.jar" + proguard_configs = [ "//third_party/hamcrest/proguard.flags" ] }
diff --git a/third_party/hamcrest/proguard.flags b/third_party/hamcrest/proguard.flags new file mode 100644 index 0000000..e9caf63 --- /dev/null +++ b/third_party/hamcrest/proguard.flags
@@ -0,0 +1 @@ +-dontobfuscate
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn index 6fb6d6a..829cfdfe 100644 --- a/third_party/protobuf/BUILD.gn +++ b/third_party/protobuf/BUILD.gn
@@ -203,9 +203,11 @@ } # Required for component builds. See http://crbug.com/172800. - if (is_component_build && (!is_linux || is_chromeos)) { + if (is_component_build) { public_configs += [ ":protobuf_use_dlls" ] - defines = [ "LIBPROTOBUF_EXPORTS" ] + if (!is_linux || is_chromeos) { + defines = [ "LIBPROTOBUF_EXPORTS" ] + } } }
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium index edb4d6f..3d69cc4 100644 --- a/third_party/protobuf/README.chromium +++ b/third_party/protobuf/README.chromium
@@ -29,10 +29,13 @@ 5. Extract all globals to src/google/protobuf/globals.cc and prefix these symbols with 'cr_'. On Linux, the command - $ objdump -t -j.data -j.bss obj/third_party/protobuf/libprotobuf_lite.a + $ objdump -t -j.data -j.bss -j.tdata -j.tbss \ + obj/third_party/protobuf/libprotobuf_lite.a should produce the output + objdump: section '.tbss' mentioned in a -j option, but not found in any input file + objdump: section '.tdata' mentioned in a -j option, but not found in any input file objdump: section '.bss' mentioned in a -j option, but not found in any input file objdump: section '.data' mentioned in a -j option, but not found in any input file
diff --git a/third_party/protobuf/patches/0012-extract-globals.patch b/third_party/protobuf/patches/0012-extract-globals.patch index f2c899a..6521c60 100644 --- a/third_party/protobuf/patches/0012-extract-globals.patch +++ b/third_party/protobuf/patches/0012-extract-globals.patch
@@ -1,15 +1,26 @@ diff -ru --new-file protobuf/src/google/protobuf/arena.cc protobuf2/src/google/protobuf/arena.cc ---- protobuf/src/google/protobuf/arena.cc 2017-03-17 22:40:59.379153132 -0700 -+++ protobuf2/src/google/protobuf/arena.cc 2017-03-17 22:40:52.667151339 -0700 -@@ -39,7 +39,6 @@ +--- protobuf/src/google/protobuf/arena.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/arena.cc 2017-03-21 21:50:11.671241466 -0700 +@@ -39,24 +39,18 @@ namespace protobuf { -google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_; #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) - Arena::ThreadCache& Arena::thread_cache() { +-Arena::ThreadCache& Arena::thread_cache() { ++Arena::ThreadCache& Arena::cr_thread_cache() { static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ = -@@ -56,7 +55,7 @@ + new internal::ThreadLocalStorage<ThreadCache>(); + return *thread_cache_->Get(); + } +-#elif defined(PROTOBUF_USE_DLLS) +-Arena::ThreadCache& Arena::thread_cache() { +- static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; +- return thread_cache_; +-} +-#else ++#elif !defined(PROTOBUF_USE_DLLS) + GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; #endif void Arena::Init() { @@ -18,7 +29,16 @@ blocks_ = 0; hint_ = 0; owns_first_block_ = true; -@@ -99,7 +98,7 @@ +@@ -74,7 +68,7 @@ + // Thread which calls Init() owns the first block. This allows the + // single-threaded case to allocate on the first block without taking any + // locks. +- first_block->owner = &thread_cache(); ++ first_block->owner = &cr_thread_cache(); + SetThreadCacheBlock(first_block); + AddBlockInternal(first_block); + owns_first_block_ = false; +@@ -99,7 +93,7 @@ uint64 Arena::Reset() { // Invalidate any ThreadCaches pointing to any blocks we just destroyed. @@ -27,9 +47,51 @@ return ResetInternal(); } +@@ -184,18 +178,18 @@ + // If this thread already owns a block in this arena then try to use that. + // This fast path optimizes the case where multiple threads allocate from the + // same arena. +- if (thread_cache().last_lifecycle_id_seen == lifecycle_id_ && +- thread_cache().last_block_used_ != NULL) { +- if (thread_cache().last_block_used_->avail() < n) { ++ if (cr_thread_cache().last_lifecycle_id_seen == lifecycle_id_ && ++ cr_thread_cache().last_block_used_ != NULL) { ++ if (cr_thread_cache().last_block_used_->avail() < n) { + return SlowAlloc(n); + } +- return AllocFromBlock(thread_cache().last_block_used_, n); ++ return AllocFromBlock(cr_thread_cache().last_block_used_, n); + } + + // Check whether we own the last accessed block on this arena. + // This fast path optimizes the case where a single thread uses multiple + // arenas. +- void* me = &thread_cache(); ++ void* me = &cr_thread_cache(); + Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_)); + if (!b || b->owner != me || b->avail() < n) { + return SlowAlloc(n); +@@ -213,7 +207,7 @@ + } + + void* Arena::SlowAlloc(size_t n) { +- void* me = &thread_cache(); ++ void* me = &cr_thread_cache(); + Block* b = FindBlock(me); // Find block owned by me. + // See if allocation fits in my latest block. + if (b != NULL && b->avail() >= n) { +@@ -290,7 +284,7 @@ + // Thread which calls Reset() owns the first block. This allows the + // single-threaded case to allocate on the first block without taking any + // locks. +- first_block->owner = &thread_cache(); ++ first_block->owner = &cr_thread_cache(); + SetThreadCacheBlock(first_block); + AddBlockInternal(first_block); + } diff -ru --new-file protobuf/src/google/protobuf/arena.h protobuf2/src/google/protobuf/arena.h ---- protobuf/src/google/protobuf/arena.h 2017-03-17 22:40:59.379153132 -0700 -+++ protobuf2/src/google/protobuf/arena.h 2017-03-17 22:40:52.667151339 -0700 +--- protobuf/src/google/protobuf/arena.h 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/arena.h 2017-03-21 21:50:11.671241466 -0700 @@ -70,6 +70,9 @@ template<typename Type> class GenericTypeHandler; // repeated_field.h @@ -40,7 +102,7 @@ // Templated cleanup methods. template<typename T> void arena_destruct_object(void* object) { reinterpret_cast<T*>(object)->~T(); -@@ -552,7 +555,6 @@ +@@ -552,19 +555,20 @@ }; static const size_t kHeaderSize = sizeof(Block); @@ -48,9 +110,37 @@ #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread // local storage class we implemented. + // iOS also does not support the GOOGLE_THREAD_LOCAL keyword. +- static ThreadCache& thread_cache(); ++ static ThreadCache& cr_thread_cache(); + #elif defined(PROTOBUF_USE_DLLS) + // Thread local variables cannot be exposed through DLL interface but we can + // wrap them in static functions. +- static ThreadCache& thread_cache(); ++ static ThreadCache& cr_thread_cache(); + #else + static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; +- static ThreadCache& thread_cache() { return thread_cache_; } ++ static ThreadCache& cr_thread_cache() { ++ return thread_cache_; ++ } + #endif + + // SFINAE for skipping addition to delete list for a message type when created +@@ -872,8 +876,8 @@ + uint64 ResetInternal(); + + inline void SetThreadCacheBlock(Block* block) { +- thread_cache().last_block_used_ = block; +- thread_cache().last_lifecycle_id_seen = lifecycle_id_; ++ cr_thread_cache().last_block_used_ = block; ++ cr_thread_cache().last_lifecycle_id_seen = lifecycle_id_; + } + + int64 lifecycle_id_; // Unique for each arena. Changes on Reset(). diff -ru --new-file protobuf/src/google/protobuf/extension_set.cc protobuf2/src/google/protobuf/extension_set.cc ---- protobuf/src/google/protobuf/extension_set.cc 2017-03-17 22:40:59.379153132 -0700 -+++ protobuf2/src/google/protobuf/extension_set.cc 2017-03-17 22:40:52.667151339 -0700 +--- protobuf/src/google/protobuf/extension_set.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/extension_set.cc 2017-03-21 21:50:11.671241466 -0700 @@ -46,6 +46,12 @@ namespace protobuf { namespace internal { @@ -200,8 +290,8 @@ } // namespace protobuf } // namespace google diff -ru --new-file protobuf/src/google/protobuf/extension_set.h protobuf2/src/google/protobuf/extension_set.h ---- protobuf/src/google/protobuf/extension_set.h 2017-03-17 22:40:59.379153132 -0700 -+++ protobuf2/src/google/protobuf/extension_set.h 2017-03-17 22:40:52.675151341 -0700 +--- protobuf/src/google/protobuf/extension_set.h 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/extension_set.h 2017-03-21 21:50:11.679241474 -0700 @@ -731,13 +731,13 @@ template<typename Type> friend class RepeatedPrimitiveTypeTraits; static void InitializeDefaultRepeatedFields(); @@ -282,8 +372,8 @@ // ------------------------------------------------------------------- diff -ru --new-file protobuf/src/google/protobuf/generated_message_util.cc protobuf2/src/google/protobuf/generated_message_util.cc ---- protobuf/src/google/protobuf/generated_message_util.cc 2017-03-17 22:40:59.379153132 -0700 -+++ protobuf2/src/google/protobuf/generated_message_util.cc 2017-03-17 22:40:52.691151345 -0700 +--- protobuf/src/google/protobuf/generated_message_util.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/generated_message_util.cc 2017-03-21 21:50:11.695241487 -0700 @@ -48,20 +48,18 @@ return std::numeric_limits<double>::quiet_NaN(); } @@ -310,8 +400,8 @@ } diff -ru --new-file protobuf/src/google/protobuf/generated_message_util.h protobuf2/src/google/protobuf/generated_message_util.h ---- protobuf/src/google/protobuf/generated_message_util.h 2017-03-17 22:40:59.379153132 -0700 -+++ protobuf2/src/google/protobuf/generated_message_util.h 2017-03-17 22:40:52.655151335 -0700 +--- protobuf/src/google/protobuf/generated_message_util.h 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/generated_message_util.h 2017-03-21 21:50:11.659241456 -0700 @@ -77,14 +77,14 @@ // Default empty string object. Don't use the pointer directly. Instead, call @@ -333,8 +423,8 @@ LIBPROTOBUF_EXPORT const ::std::string& GetEmptyString(); diff -ru --new-file protobuf/src/google/protobuf/globals.cc protobuf2/src/google/protobuf/globals.cc --- protobuf/src/google/protobuf/globals.cc 1969-12-31 16:00:00.000000000 -0800 -+++ protobuf2/src/google/protobuf/globals.cc 2017-03-17 22:40:52.655151335 -0700 -@@ -0,0 +1,113 @@ ++++ protobuf2/src/google/protobuf/globals.cc 2017-03-21 21:50:11.659241456 -0700 +@@ -0,0 +1,122 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2017 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ @@ -365,6 +455,7 @@ +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ++#include <google/protobuf/arena.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/stubs/atomicops.h> @@ -372,6 +463,14 @@ + +namespace google { +namespace protobuf { ++ ++#if !defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) && defined(PROTOBUF_USE_DLLS) ++Arena::ThreadCache& Arena::cr_thread_cache() { ++ static GOOGLE_THREAD_LOCAL ThreadCache cr_thread_cache_ = {-1, NULL}; ++ return cr_thread_cache_; ++} ++#endif ++ +namespace internal { + +SequenceNumber cr_lifecycle_id_generator_; @@ -449,8 +548,8 @@ +} // namespace protobuf +} // namespace google diff -ru --new-file protobuf/src/google/protobuf/io/coded_stream.cc protobuf2/src/google/protobuf/io/coded_stream.cc ---- protobuf/src/google/protobuf/io/coded_stream.cc 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/io/coded_stream.cc 2017-03-17 22:40:52.659151336 -0700 +--- protobuf/src/google/protobuf/io/coded_stream.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/io/coded_stream.cc 2017-03-21 21:50:11.663241460 -0700 @@ -83,7 +83,7 @@ } @@ -461,8 +560,8 @@ void CodedOutputStream::EnableAliasing(bool enabled) { diff -ru --new-file protobuf/src/google/protobuf/io/coded_stream.h protobuf2/src/google/protobuf/io/coded_stream.h ---- protobuf/src/google/protobuf/io/coded_stream.h 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/io/coded_stream.h 2017-03-17 22:40:52.659151336 -0700 +--- protobuf/src/google/protobuf/io/coded_stream.h 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/io/coded_stream.h 2017-03-21 21:50:11.663241460 -0700 @@ -613,7 +613,7 @@ static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB @@ -473,8 +572,8 @@ // Class which encodes and writes binary data which is composed of varint- diff -ru --new-file protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc protobuf2/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc ---- protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc 2017-03-17 22:40:52.671151340 -0700 +--- protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc 2017-03-21 21:50:11.675241470 -0700 @@ -58,23 +58,13 @@ : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) #endif @@ -540,8 +639,8 @@ - #endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff -ru --new-file protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h protobuf2/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h ---- protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h 2017-03-17 22:40:52.671151340 -0700 +--- protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h 2017-03-21 21:50:11.675241470 -0700 @@ -46,7 +46,9 @@ // after acquire compare-and-swap. bool has_sse2; // Processor has SSE2. @@ -608,8 +707,8 @@ } return x; diff -ru --new-file protobuf/src/google/protobuf/stubs/common.cc protobuf2/src/google/protobuf/stubs/common.cc ---- protobuf/src/google/protobuf/stubs/common.cc 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/stubs/common.cc 2017-03-17 22:40:52.671151340 -0700 +--- protobuf/src/google/protobuf/stubs/common.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/stubs/common.cc 2017-03-21 21:50:11.675241470 -0700 @@ -116,7 +116,8 @@ if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { return; @@ -777,8 +876,8 @@ #if PROTOBUF_USE_EXCEPTIONS diff -ru --new-file protobuf/src/google/protobuf/stubs/structurally_valid.cc protobuf2/src/google/protobuf/stubs/structurally_valid.cc ---- protobuf/src/google/protobuf/stubs/structurally_valid.cc 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/stubs/structurally_valid.cc 2017-03-17 22:40:52.675151341 -0700 +--- protobuf/src/google/protobuf/stubs/structurally_valid.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/stubs/structurally_valid.cc 2017-03-21 21:50:11.679241474 -0700 @@ -511,21 +511,10 @@ // UTF-8 strings. Since UTF-8 validation is only used for debugging // anyway, we simply always return success if initialization hasn't @@ -813,8 +912,8 @@ int bytes_consumed = 0; UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj, diff -ru --new-file protobuf/src/google/protobuf/stubs/strutil.cc protobuf2/src/google/protobuf/stubs/strutil.cc ---- protobuf/src/google/protobuf/stubs/strutil.cc 2017-03-17 22:40:59.383153133 -0700 -+++ protobuf2/src/google/protobuf/stubs/strutil.cc 2017-03-17 22:40:52.671151340 -0700 +--- protobuf/src/google/protobuf/stubs/strutil.cc 2017-03-21 21:50:28.399255503 -0700 ++++ protobuf2/src/google/protobuf/stubs/strutil.cc 2017-03-21 21:50:11.675241470 -0700 @@ -528,7 +528,7 @@ // Assumes that non-printable characters are escaped using octal sequences, and // that UTF-8 bytes are not handled specially.
diff --git a/third_party/protobuf/src/google/protobuf/arena.cc b/third_party/protobuf/src/google/protobuf/arena.cc index 40a15cc..3ce17e3 100755 --- a/third_party/protobuf/src/google/protobuf/arena.cc +++ b/third_party/protobuf/src/google/protobuf/arena.cc
@@ -40,17 +40,12 @@ #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) -Arena::ThreadCache& Arena::thread_cache() { +Arena::ThreadCache& Arena::cr_thread_cache() { static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ = new internal::ThreadLocalStorage<ThreadCache>(); return *thread_cache_->Get(); } -#elif defined(PROTOBUF_USE_DLLS) -Arena::ThreadCache& Arena::thread_cache() { - static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; - return thread_cache_; -} -#else +#elif !defined(PROTOBUF_USE_DLLS) GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; #endif @@ -73,7 +68,7 @@ // Thread which calls Init() owns the first block. This allows the // single-threaded case to allocate on the first block without taking any // locks. - first_block->owner = &thread_cache(); + first_block->owner = &cr_thread_cache(); SetThreadCacheBlock(first_block); AddBlockInternal(first_block); owns_first_block_ = false; @@ -183,18 +178,18 @@ // If this thread already owns a block in this arena then try to use that. // This fast path optimizes the case where multiple threads allocate from the // same arena. - if (thread_cache().last_lifecycle_id_seen == lifecycle_id_ && - thread_cache().last_block_used_ != NULL) { - if (thread_cache().last_block_used_->avail() < n) { + if (cr_thread_cache().last_lifecycle_id_seen == lifecycle_id_ && + cr_thread_cache().last_block_used_ != NULL) { + if (cr_thread_cache().last_block_used_->avail() < n) { return SlowAlloc(n); } - return AllocFromBlock(thread_cache().last_block_used_, n); + return AllocFromBlock(cr_thread_cache().last_block_used_, n); } // Check whether we own the last accessed block on this arena. // This fast path optimizes the case where a single thread uses multiple // arenas. - void* me = &thread_cache(); + void* me = &cr_thread_cache(); Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_)); if (!b || b->owner != me || b->avail() < n) { return SlowAlloc(n); @@ -212,7 +207,7 @@ } void* Arena::SlowAlloc(size_t n) { - void* me = &thread_cache(); + void* me = &cr_thread_cache(); Block* b = FindBlock(me); // Find block owned by me. // See if allocation fits in my latest block. if (b != NULL && b->avail() >= n) { @@ -289,7 +284,7 @@ // Thread which calls Reset() owns the first block. This allows the // single-threaded case to allocate on the first block without taking any // locks. - first_block->owner = &thread_cache(); + first_block->owner = &cr_thread_cache(); SetThreadCacheBlock(first_block); AddBlockInternal(first_block); }
diff --git a/third_party/protobuf/src/google/protobuf/arena.h b/third_party/protobuf/src/google/protobuf/arena.h index 72d8a9d..2836a618 100644 --- a/third_party/protobuf/src/google/protobuf/arena.h +++ b/third_party/protobuf/src/google/protobuf/arena.h
@@ -559,14 +559,16 @@ // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread // local storage class we implemented. // iOS also does not support the GOOGLE_THREAD_LOCAL keyword. - static ThreadCache& thread_cache(); + static ThreadCache& cr_thread_cache(); #elif defined(PROTOBUF_USE_DLLS) // Thread local variables cannot be exposed through DLL interface but we can // wrap them in static functions. - static ThreadCache& thread_cache(); + static ThreadCache& cr_thread_cache(); #else static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; - static ThreadCache& thread_cache() { return thread_cache_; } + static ThreadCache& cr_thread_cache() { + return thread_cache_; + } #endif // SFINAE for skipping addition to delete list for a message type when created @@ -874,8 +876,8 @@ uint64 ResetInternal(); inline void SetThreadCacheBlock(Block* block) { - thread_cache().last_block_used_ = block; - thread_cache().last_lifecycle_id_seen = lifecycle_id_; + cr_thread_cache().last_block_used_ = block; + cr_thread_cache().last_lifecycle_id_seen = lifecycle_id_; } int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
diff --git a/third_party/protobuf/src/google/protobuf/globals.cc b/third_party/protobuf/src/google/protobuf/globals.cc index f4122734..31fb6ba9 100644 --- a/third_party/protobuf/src/google/protobuf/globals.cc +++ b/third_party/protobuf/src/google/protobuf/globals.cc
@@ -28,6 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include <google/protobuf/arena.h> #include <google/protobuf/extension_set.h> #include <google/protobuf/generated_message_util.h> #include <google/protobuf/stubs/atomicops.h> @@ -35,6 +36,14 @@ namespace google { namespace protobuf { + +#if !defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) && defined(PROTOBUF_USE_DLLS) +Arena::ThreadCache& Arena::cr_thread_cache() { + static GOOGLE_THREAD_LOCAL ThreadCache cr_thread_cache_ = {-1, NULL}; + return cr_thread_cache_; +} +#endif + namespace internal { SequenceNumber cr_lifecycle_id_generator_;
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index f5f8b16d4..69a00de 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -93871,6 +93871,7 @@ <int value="1867" label="CSSOverflowPaged"/> <int value="1868" label="ChildSrcAllowedWorkerThatScriptSrcBlocked"/> <int value="1869" label="HTMLTableElementPresentationAttributeBackground"/> + <int value="1870" label="V8Navigator_GetInstalledRelatedApps_Method"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -99837,6 +99838,7 @@ <int value="-1052415111" label="malware-interstitial-v2"/> <int value="-1052219252" label="disable-captive-portal-bypass-proxy"/> <int value="-1045900007" label="NoCreditCardAbort:disabled"/> + <int value="-1045882995" label="UseNewDoodleApi:enabled"/> <int value="-1041650038" label="enable-forced-migration-to-tabbed-mode"/> <int value="-1039889738" label="NativeNotifications:enabled"/> <int value="-1039555838" label="GamepadExtensions:enabled"/> @@ -99907,6 +99909,7 @@ <int value="-795600188" label="disable-async-dns"/> <int value="-790036192" label="overscroll-start-threshold"/> <int value="-780798969" label="disable-single-click-autofill"/> + <int value="-775321548" label="UseNewDoodleApi:disabled"/> <int value="-770319039" label="enable-touch-editing"/> <int value="-763759697" label="enable-audio-support-for-desktop-share"/> <int value="-759830869" label="enable-tab-discarding"/> @@ -123017,6 +123020,15 @@ <affected-histogram name="WebRTC.Stun.SuccessPercent.UnknownNAT"/> </histogram_suffixes> +<histogram_suffixes name="SubresourceFilterOnlyExperiment" separator="."> + <suffix name="SocialEngineeringAdsInterstitial" + label="social eng ad blacklist pattern"/> + <suffix name="PhishingInterstitial" label="phishing blacklist pattern"/> + <affected-histogram name="SubresourceFilter.PageLoad.RedirectChainLength"/> + <affected-histogram + name="SubresourceFilter.PageLoad.RedirectChainMatchPattern"/> +</histogram_suffixes> + <histogram_suffixes name="SyncModelType" separator="."> <suffix name="APP" label="APP"/> <suffix name="APP_LIST" label="APP_LIST"/>
diff --git a/ui/arc/notification/arc_custom_notification_item.cc b/ui/arc/notification/arc_custom_notification_item.cc index d3cac1be..f44884d 100644 --- a/ui/arc/notification/arc_custom_notification_item.cc +++ b/ui/arc/notification/arc_custom_notification_item.cc
@@ -39,6 +39,8 @@ void Close(bool by_user) override { item_->Close(by_user); } + void Click() override { item_->Click(); } + private: // The destructor is private since this class is ref-counted. ~ArcNotificationDelegate() override {}
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc index 85c3234..edb2346 100644 --- a/ui/gl/gl_surface.cc +++ b/ui/gl/gl_surface.cc
@@ -161,6 +161,11 @@ return false; } +bool GLSurface::SetEnableDCLayers(bool enable) { + NOTIMPLEMENTED(); + return false; +} + bool GLSurface::IsSurfaceless() const { return false; } @@ -173,7 +178,7 @@ return false; } -bool GLSurface::SupportsSetDrawRectangle() const { +bool GLSurface::SupportsDCLayers() const { return false; } @@ -359,6 +364,10 @@ return surface_->ScheduleDCLayer(params); } +bool GLSurfaceAdapter::SetEnableDCLayers(bool enable) { + return surface_->SetEnableDCLayers(enable); +} + bool GLSurfaceAdapter::IsSurfaceless() const { return surface_->IsSurfaceless(); } @@ -371,8 +380,8 @@ return surface_->BuffersFlipped(); } -bool GLSurfaceAdapter::SupportsSetDrawRectangle() const { - return surface_->SupportsSetDrawRectangle(); +bool GLSurfaceAdapter::SupportsDCLayers() const { + return surface_->SupportsDCLayers(); } bool GLSurfaceAdapter::SetDrawRectangle(const gfx::Rect& rect) {
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h index 56d9a1c5..4287ad2 100644 --- a/ui/gl/gl_surface.h +++ b/ui/gl/gl_surface.h
@@ -201,6 +201,8 @@ virtual bool ScheduleDCLayer(const ui::DCRendererLayerParams& params); + virtual bool SetEnableDCLayers(bool enable); + virtual bool IsSurfaceless() const; virtual bool FlipsVertically() const; @@ -209,7 +211,7 @@ // the next buffer may be 2 frames old. virtual bool BuffersFlipped() const; - virtual bool SupportsSetDrawRectangle() const; + virtual bool SupportsDCLayers() const; // Set the rectangle that will be drawn into on the surface. virtual bool SetDrawRectangle(const gfx::Rect& rect); @@ -286,10 +288,11 @@ const gfx::Rect& bounds_rect, const gfx::RectF& crop_rect) override; bool ScheduleDCLayer(const ui::DCRendererLayerParams& params) override; + bool SetEnableDCLayers(bool enable) override; bool IsSurfaceless() const override; bool FlipsVertically() const override; bool BuffersFlipped() const override; - bool SupportsSetDrawRectangle() const override; + bool SupportsDCLayers() const override; bool SetDrawRectangle(const gfx::Rect& rect) override; gfx::Vector2d GetDrawOffset() const override; void OnSetSwapInterval(int interval) override;
diff --git a/ui/gl/gl_surface_stub.cc b/ui/gl/gl_surface_stub.cc index 857a4ef..6f93fa8 100644 --- a/ui/gl/gl_surface_stub.cc +++ b/ui/gl/gl_surface_stub.cc
@@ -39,7 +39,7 @@ return GLSurfaceFormat(); } -bool GLSurfaceStub::SupportsSetDrawRectangle() const { +bool GLSurfaceStub::SupportsDCLayers() const { return supports_draw_rectangle_; }
diff --git a/ui/gl/gl_surface_stub.h b/ui/gl/gl_surface_stub.h index 87f55655..7e11a9df 100644 --- a/ui/gl/gl_surface_stub.h +++ b/ui/gl/gl_surface_stub.h
@@ -31,7 +31,7 @@ void* GetHandle() override; bool BuffersFlipped() const override; GLSurfaceFormat GetFormat() override; - bool SupportsSetDrawRectangle() const override; + bool SupportsDCLayers() const override; gfx::Vector2d GetDrawOffset() const override; protected: