diff --git a/DEPS b/DEPS index 9ad3259..43651905 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '19769c12f2a6390893ccfc0a03a4784cebe7b180', + 'v8_revision': '726c1912373d6c58237b2c4d8dd1e5aad2a81d7c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other.
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn index a113979..137b2c3a 100644 --- a/build/toolchain/win/BUILD.gn +++ b/build/toolchain/win/BUILD.gn
@@ -120,6 +120,10 @@ # archives and understands bitcode (for lto builds). lib = "$prefix/$lld_link /lib /llvmlibthin" link = "$prefix/$lld_link" + if (host_os != "win") { + # See comment adding --rsp-quoting to $cl above for more information. + link = "$link --rsp-quoting=posix" + } } else { lib = "lib.exe" link = "link.exe"
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 3d7f41e..51fe1c1 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc
@@ -17,6 +17,7 @@ #include "cc/test/fake_raster_source.h" #include "cc/test/fake_recording_source.h" #include "cc/test/pixel_test.h" +#include "cc/test/test_in_process_context_provider.h" #include "components/viz/service/display/gl_renderer.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "media/base/video_frame.h" @@ -302,10 +303,20 @@ bits_per_channel = 10; } + viz::ResourceFormat yuv_highbit_resource_format = + resource_provider->YuvResourceFormat(bits_per_channel); + + float multiplier = 1.0; + + if (yuv_highbit_resource_format != viz::R16_EXT) + bits_per_channel = 8; + else + multiplier = 65535.0f / ((1 << bits_per_channel) - 1); + yuv_quad->SetNew(shared_state, rect, visible_rect, needs_blending, ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size, uv_tex_size, y_resource, u_resource, v_resource, a_resource, - color_space, video_color_space, 0.0f, 1.0f, + color_space, video_color_space, 0.0f, multiplier, bits_per_channel); } @@ -1304,9 +1315,35 @@ std::unique_ptr<VideoResourceUpdater> video_resource_updater_; }; +enum class HighbitTexture { + Y8, + R16_EXT, +}; + class VideoGLRendererPixelHiLoTest : public VideoGLRendererPixelTest, - public ::testing::WithParamInterface<bool> {}; + public ::testing::WithParamInterface< + ::testing::tuple<bool, HighbitTexture>> { + public: + void SetSupportHighbitTexture(HighbitTexture texture) { + TestInProcessContextProvider* context_provider = + GetTestInProcessContextProvider(); + switch (texture) { + case HighbitTexture::Y8: + break; + case HighbitTexture::R16_EXT: + context_provider->SetSupportTextureNorm16(true); + video_resource_updater_->SetUseR16ForTesting(true); + break; + } + } + + private: + TestInProcessContextProvider* GetTestInProcessContextProvider() { + return static_cast<TestInProcessContextProvider*>( + output_surface_->context_provider()); + } +}; TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) { gfx::Rect rect(this->device_viewport_size_); @@ -1320,7 +1357,10 @@ SharedQuadState* shared_state = CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - bool highbit = GetParam(); + const bool highbit = testing::get<0>(GetParam()); + const HighbitTexture format = testing::get<1>(GetParam()); + SetSupportHighbitTexture(format); + CreateTestYUVVideoDrawQuad_Striped( shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_SD_REC601, false, highbit, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(), @@ -1349,7 +1389,10 @@ SharedQuadState* shared_state = CreateTestSharedQuadState(gfx::Transform(), viewport, pass.get()); - bool highbit = GetParam(); + const bool highbit = testing::get<0>(GetParam()); + const HighbitTexture format = testing::get<1>(GetParam()); + SetSupportHighbitTexture(format); + CreateTestYUVVideoDrawQuad_Striped( shared_state, media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_SD_REC601, false, highbit, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(), @@ -1418,7 +1461,12 @@ } // First argument (test case prefix) is intentionally left empty. -INSTANTIATE_TEST_CASE_P(, VideoGLRendererPixelHiLoTest, ::testing::Bool()); +INSTANTIATE_TEST_CASE_P( + , + VideoGLRendererPixelHiLoTest, + testing::Combine(testing::Bool(), + testing::Values(HighbitTexture::Y8, + HighbitTexture::R16_EXT))); TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) { gfx::Rect rect(this->device_viewport_size_);
diff --git a/cc/raster/raster_buffer_provider.cc b/cc/raster/raster_buffer_provider.cc index 1eb0fd03..081aaf5 100644 --- a/cc/raster/raster_buffer_provider.cc +++ b/cc/raster/raster_buffer_provider.cc
@@ -37,6 +37,7 @@ case viz::RED_8: case viz::LUMINANCE_F16: case viz::RGBA_F16: + case viz::R16_EXT: return false; } NOTREACHED(); @@ -130,6 +131,7 @@ case viz::RGB_565: case viz::RED_8: case viz::LUMINANCE_F16: + case viz::R16_EXT: NOTREACHED(); return; } @@ -153,6 +155,7 @@ case viz::RED_8: case viz::LUMINANCE_F16: case viz::RGBA_F16: + case viz::R16_EXT: return false; } NOTREACHED();
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index b9ed1ba..ce45d13 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -106,6 +106,7 @@ case viz::ETC1: case viz::RED_8: case viz::LUMINANCE_F16: + case viz::R16_EXT: NOTREACHED(); break; } @@ -127,6 +128,7 @@ case viz::ETC1: case viz::RED_8: case viz::LUMINANCE_F16: + case viz::R16_EXT: return false; } return false; @@ -325,6 +327,9 @@ : default_resource_type(resource_settings.use_gpu_memory_buffer_resources ? RESOURCE_TYPE_GPU_MEMORY_BUFFER : RESOURCE_TYPE_GL_TEXTURE), + yuv_highbit_resource_format(resource_settings.high_bit_for_testing + ? viz::R16_EXT + : viz::LUMINANCE_8), enable_color_correct_rasterization(enable_color_correct_rasterization), delegated_sync_points_required(delegated_sync_points_required) { if (!compositor_context_provider) { @@ -347,9 +352,10 @@ yuv_resource_format = yuv_highbit_resource_format = viz::RGBA_8888; } else { yuv_resource_format = caps.texture_rg ? viz::RED_8 : viz::LUMINANCE_8; - yuv_highbit_resource_format = caps.texture_half_float_linear - ? viz::LUMINANCE_F16 - : yuv_resource_format; + if (resource_settings.use_r16_texture && caps.texture_norm16) + yuv_highbit_resource_format = viz::R16_EXT; + else if (caps.texture_half_float_linear) + yuv_highbit_resource_format = viz::LUMINANCE_F16; } GLES2Interface* gl = compositor_context_provider->ContextGL(); @@ -449,6 +455,8 @@ return caps.texture_format_etc1; case viz::RED_8: return caps.texture_rg; + case viz::R16_EXT: + return caps.texture_norm16; case viz::LUMINANCE_F16: case viz::RGBA_F16: return caps.texture_half_float_linear; @@ -482,6 +490,7 @@ case viz::RED_8: case viz::ETC1: case viz::LUMINANCE_F16: + case viz::R16_EXT: // We don't currently render into these formats. If we need to render into // these eventually, we should expand this logic. return false;
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index f27a011..f573170 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -464,12 +464,29 @@ } std::unique_ptr<media::HalfFloatMaker> half_float_maker; - if (resource_provider_->YuvResourceFormat(bits_per_channel) == - viz::LUMINANCE_F16) { - half_float_maker = - media::HalfFloatMaker::NewHalfFloatMaker(bits_per_channel); - external_resources.offset = half_float_maker->Offset(); - external_resources.multiplier = half_float_maker->Multiplier(); + + switch (resource_provider_->YuvResourceFormat(bits_per_channel)) { + case viz::LUMINANCE_F16: + half_float_maker = + media::HalfFloatMaker::NewHalfFloatMaker(bits_per_channel); + external_resources.offset = half_float_maker->Offset(); + external_resources.multiplier = half_float_maker->Multiplier(); + break; + case viz::R16_EXT: + external_resources.multiplier = 65535.0f / ((1 << bits_per_channel) - 1); + external_resources.offset = 0; + break; + case viz::LUMINANCE_8: + case viz::RED_8: + break; + case viz::ALPHA_8: + case viz::RGBA_8888: + case viz::RGBA_4444: + case viz::BGRA_8888: + case viz::RGB_565: + case viz::ETC1: + case viz::RGBA_F16: + NOTREACHED(); } for (size_t i = 0; i < plane_resources.size(); ++i) { @@ -504,6 +521,9 @@ // step. if (plane_resource.resource_format() == viz::LUMINANCE_F16) { needs_conversion = true; + } else if (plane_resource.resource_format() == viz::R16_EXT) { + // R16_EXT can represent 16-bit int, so we don't need a conversion step. + needs_conversion = false; } else if (bits_per_channel > 8) { // If bits_per_channel > 8 and we can't use viz::LUMINANCE_F16, we need // to shift the data down and create an 8-bit texture.
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index a7ac7e5..50ec17c 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h
@@ -86,6 +86,10 @@ VideoFrameExternalResources CreateExternalResourcesFromVideoFrame( scoped_refptr<media::VideoFrame> video_frame); + void SetUseR16ForTesting(bool use_r16_for_testing) { + use_r16_for_testing_ = use_r16_for_testing; + } + private: class PlaneResource { public: @@ -184,6 +188,7 @@ const bool use_stream_video_draw_quad_; std::unique_ptr<media::SkCanvasVideoRenderer> video_renderer_; std::vector<uint8_t> upload_pixels_; + bool use_r16_for_testing_ = false; // Recycle resources so that we can reduce the number of allocations and // data transfers.
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc index 8c0f6ca6..3054a23 100644 --- a/cc/resources/video_resource_updater_unittest.cc +++ b/cc/resources/video_resource_updater_unittest.cc
@@ -105,12 +105,12 @@ void SetUp() override { testing::Test::SetUp(); - shared_bitmap_manager_.reset(new SharedBitmapManagerAllocationCounter()); resource_provider3d_ = FakeResourceProvider::Create( - context_provider_.get(), shared_bitmap_manager_.get()); - resource_provider_software_ = - FakeResourceProvider::Create(nullptr, shared_bitmap_manager_.get()); + context_provider_.get(), shared_bitmap_manager_.get(), + high_bit_for_testing_); + resource_provider_software_ = FakeResourceProvider::Create( + nullptr, shared_bitmap_manager_.get(), high_bit_for_testing_); } scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() { @@ -251,6 +251,7 @@ std::unique_ptr<ResourceProvider> resource_provider3d_; std::unique_ptr<ResourceProvider> resource_provider_software_; gpu::SyncToken release_sync_token_; + bool high_bit_for_testing_; }; const gpu::SyncToken VideoResourceUpdaterTest::kMailboxSyncToken = @@ -312,6 +313,40 @@ EXPECT_NEAR(resources2.offset, 0.5, 0.1); } +class VideoResourceUpdaterTestWithR16 : public VideoResourceUpdaterTest { + public: + VideoResourceUpdaterTestWithR16() : VideoResourceUpdaterTest() { + high_bit_for_testing_ = true; + context3d_->set_support_texture_norm16(true); + } +}; + +TEST_F(VideoResourceUpdaterTestWithR16, HighBitFrame) { + bool use_stream_video_draw_quad = false; + VideoResourceUpdater updater(context_provider_.get(), + resource_provider3d_.get(), + use_stream_video_draw_quad); + updater.SetUseR16ForTesting(true); + scoped_refptr<media::VideoFrame> video_frame = CreateTestHighBitFrame(); + + VideoFrameExternalResources resources = + updater.CreateExternalResourcesFromVideoFrame(video_frame); + EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); + + // Max 10-bit values as read by a sampler. + double max_10bit_value = ((1 << 10) - 1) / 65535.0; + EXPECT_NEAR(resources.multiplier * max_10bit_value, 1.0, 0.0001); + EXPECT_NEAR(resources.offset, 0.0, 0.1); + + // Create the resource again, to test the path where the + // resources are cached. + VideoFrameExternalResources resources2 = + updater.CreateExternalResourcesFromVideoFrame(video_frame); + EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources2.type); + EXPECT_NEAR(resources2.multiplier * max_10bit_value, 1.0, 0.0001); + EXPECT_NEAR(resources2.offset, 0.0, 0.1); +} + TEST_F(VideoResourceUpdaterTest, HighBitFrameSoftwareCompositor) { bool use_stream_video_draw_quad = false; VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
diff --git a/cc/test/fake_resource_provider.h b/cc/test/fake_resource_provider.h index e5ecb355..07e7638 100644 --- a/cc/test/fake_resource_provider.h +++ b/cc/test/fake_resource_provider.h
@@ -18,11 +18,13 @@ public: static std::unique_ptr<FakeResourceProvider> Create( viz::ContextProvider* context_provider, - viz::SharedBitmapManager* shared_bitmap_manager) { + viz::SharedBitmapManager* shared_bitmap_manager, + bool high_bit_for_testing = false) { viz::ResourceSettings resource_settings; resource_settings.texture_id_allocation_chunk_size = 1; resource_settings.buffer_to_texture_target_map = viz::DefaultBufferToTextureTargetMapForTesting(); + resource_settings.high_bit_for_testing = high_bit_for_testing; return base::WrapUnique(new FakeResourceProvider( context_provider, shared_bitmap_manager, nullptr, nullptr, true, false, resource_settings)); @@ -44,11 +46,13 @@ static std::unique_ptr<FakeResourceProvider> Create( viz::ContextProvider* context_provider, viz::SharedBitmapManager* shared_bitmap_manager, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + bool high_bit_for_testing = false) { viz::ResourceSettings resource_settings; resource_settings.texture_id_allocation_chunk_size = 1; resource_settings.buffer_to_texture_target_map = viz::DefaultBufferToTextureTargetMapForTesting(); + resource_settings.high_bit_for_testing = high_bit_for_testing; return base::WrapUnique(new FakeResourceProvider( context_provider, shared_bitmap_manager, gpu_memory_buffer_manager, nullptr, true, false, resource_settings));
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc index 1243e35..7ae32d0 100644 --- a/cc/test/test_context_provider.cc +++ b/cc/test/test_context_provider.cc
@@ -28,9 +28,9 @@ // Various tests rely on functionality (capabilities) enabled by these extension // strings. -const char* const kExtensions[] = {"GL_EXT_stencil_wrap", - "GL_EXT_texture_format_BGRA8888", - "GL_OES_rgb8_rgba8"}; +const char* const kExtensions[] = { + "GL_EXT_stencil_wrap", "GL_EXT_texture_format_BGRA8888", + "GL_OES_rgb8_rgba8", "GL_EXT_texture_norm16"}; class TestGLES2InterfaceForContextProvider : public TestGLES2Interface { public:
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc index 6c566277..1ca0806 100644 --- a/cc/test/test_in_process_context_provider.cc +++ b/cc/test/test_in_process_context_provider.cc
@@ -110,6 +110,7 @@ gpu::Capabilities capabilities; capabilities.texture_rectangle = true; capabilities.sync_query = true; + capabilities.texture_norm16 = true; switch (viz::PlatformColor::Format()) { case viz::PlatformColor::SOURCE_FORMAT_RGBA8: capabilities.texture_format_bgra8888 = false;
diff --git a/cc/test/test_in_process_context_provider.h b/cc/test/test_in_process_context_provider.h index 7e3033a9..3568792b 100644 --- a/cc/test/test_in_process_context_provider.h +++ b/cc/test/test_in_process_context_provider.h
@@ -49,6 +49,9 @@ gpu::Capabilities ContextCapabilities() override; void SetLostContextCallback( const LostContextCallback& lost_context_callback) override; + void SetSupportTextureNorm16(bool support) { + capabilities_texture_norm16_ = support; + } protected: friend class base::RefCountedThreadSafe<TestInProcessContextProvider>; @@ -61,6 +64,7 @@ std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_; std::unique_ptr<viz::ContextCacheController> cache_controller_; base::Lock context_lock_; + bool capabilities_texture_norm16_ = false; }; } // namespace cc
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index c50893f90..ea35d2ac 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h
@@ -344,6 +344,9 @@ void set_support_texture_half_float_linear(bool support) { test_capabilities_.texture_half_float_linear = support; } + void set_support_texture_norm16(bool support) { + test_capabilities_.texture_norm16 = support; + } void set_msaa_is_slow(bool msaa_is_slow) { test_capabilities_.msaa_is_slow = msaa_is_slow; }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 78ecd75f..dcb43869 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -7971,6 +7971,10 @@ desc="Used to indicate that the speech recognition service didn't receive any voice input."> Please check your microphone and audio levels. </message> + <message name="IDS_NEW_TAB_VOICE_OTHER_ERROR" + desc="Used to indicate that the speech recognition service failed in an unknown way."> + Unknown error. + </message> <message name="IDS_NEW_TAB_VOICE_PERMISSION_ERROR" desc="Used to indicate that the speech recognition service did not get permission to use the microphone."> Voice search has been turned off.
diff --git a/chrome/browser/extensions/extension_navigation_throttle_unittest.cc b/chrome/browser/extensions/extension_navigation_throttle_unittest.cc index d458e075..6b56caf 100644 --- a/chrome/browser/extensions/extension_navigation_throttle_unittest.cc +++ b/chrome/browser/extensions/extension_navigation_throttle_unittest.cc
@@ -70,7 +70,7 @@ void CheckTestCase( content::RenderFrameHost* host, const GURL& extension_url, - NavigationThrottle::ThrottleCheckResult expected_will_start_result) { + NavigationThrottle::ThrottleAction expected_will_start_result) { // First subtest: direct navigation to |extension_url|. std::unique_ptr<content::NavigationHandle> handle = content::NavigationHandle::CreateNavigationHandleForTesting( @@ -91,7 +91,7 @@ // TODO(nick): https://crbug.com/695421 Once PlzNavigate is enabled 100%, it // should be possible to support return values other than PROCEED and CANCEL // from ExtensionNavigationThrottle::WillRedirectRequest. - NavigationThrottle::ThrottleCheckResult expected_will_redirect_result = + NavigationThrottle::ThrottleAction expected_will_redirect_result = (expected_will_start_result == NavigationThrottle::PROCEED) ? NavigationThrottle::PROCEED : NavigationThrottle::CANCEL;
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc index fce991e..41c3eab 100644 --- a/chrome/browser/metrics/thread_watcher.cc +++ b/chrome/browser/metrics/thread_watcher.cc
@@ -552,12 +552,8 @@ unresponsive_threshold, crash_on_hang_threads); StartWatching(BrowserThread::IO, "IO", kSleepTime, kUnresponsiveTime, unresponsive_threshold, crash_on_hang_threads); - StartWatching(BrowserThread::DB, "DB", kSleepTime, kUnresponsiveTime, - unresponsive_threshold, crash_on_hang_threads); StartWatching(BrowserThread::FILE, "FILE", kSleepTime, kUnresponsiveTime, unresponsive_threshold, crash_on_hang_threads); - StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, kUnresponsiveTime, - unresponsive_threshold, crash_on_hang_threads); } // static
diff --git a/chrome/browser/resources/local_ntp/voice.js b/chrome/browser/resources/local_ntp/voice.js index 6f8ed916..3627dea7 100644 --- a/chrome/browser/resources/local_ntp/voice.js +++ b/chrome/browser/resources/local_ntp/voice.js
@@ -86,6 +86,7 @@ * networkError: string, * noTranslation: string, * noVoice: string, + * otherError: string, * permissionError: string, * ready: string, * tryAgain: string, @@ -101,6 +102,7 @@ networkError: '', noTranslation: '', noVoice: '', + otherError: '', permissionError: '', ready: '', tryAgain: '', @@ -279,12 +281,12 @@ fakeboxMicrophoneElem.onmouseup = function(event) { // If propagated, closes the overlay (click on the background). event.stopPropagation(); - speech.toggleStartStop(); + speech.start(); }; fakeboxMicrophoneElem.onkeydown = function(event) { if (!event.repeat && (event.code == KEYCODE.ENTER || event.code == KEYCODE.NUMPAD_ENTER)) { - speech.toggleStartStop(); + speech.start(); } }; window.addEventListener('keydown', speech.onKeyDown); @@ -304,6 +306,7 @@ networkError: translatedStrings.networkError, noTranslation: translatedStrings.noTranslation, noVoice: translatedStrings.noVoice, + otherError: translatedStrings.otherError, permissionError: translatedStrings.permissionError, ready: translatedStrings.ready, tryAgain: translatedStrings.tryAgain, @@ -324,7 +327,6 @@ speech.recognition_.continuous = false; speech.recognition_.interimResults = true; speech.recognition_.lang = getChromeUILanguage(); - speech.recognition_.maxAlternatives = 4; speech.recognition_.onaudiostart = speech.handleRecognitionAudioStart_; speech.recognition_.onend = speech.handleRecognitionEnd_; speech.recognition_.onerror = speech.handleRecognitionError_; @@ -337,9 +339,8 @@ /** * Sets up the necessary states for voice search and then starts the * speech recognition interface. - * @private */ -speech.start_ = function() { +speech.start = function() { view.show(); speech.resetIdleTimer_(speech.IDLE_TIMEOUT_MS_); @@ -352,7 +353,7 @@ speech.initWebkitSpeech_(); } - // If |speech.start_()| is called too soon after |speech.stop_()| then the + // If |speech.start()| is called too soon after |speech.stop()| then the // recognition interface hasn't yet reset and an error occurs. In this case // we need to hard-reset it and reissue the |recognition_.start()| command. try { @@ -364,7 +365,7 @@ speech.recognition_.start(); speech.currentState_ = speech.State_.STARTED; } catch (error2) { - speech.stop_(); + speech.stop(); } } }; @@ -372,9 +373,8 @@ /** * Hides the overlay and resets the speech state. - * @private */ -speech.stop_ = function() { +speech.stop = function() { speech.recognition_.abort(); speech.currentState_ = speech.State_.STOPPED; view.hide(); @@ -586,13 +586,13 @@ event.ctrlKey || (speech.isUserAgentMac_() && event.metaKey); if (speech.currentState_ == speech.State_.READY && event.code == KEYCODE.PERIOD && event.shiftKey && ctrlKeyPressed) { - speech.toggleStartStop(); + speech.start(); } } else { // Ensures that keyboard events are not propagated during voice input. event.stopPropagation(); if (event.code == KEYCODE.ESC) { - speech.stop_(); + speech.stop(); } else if ( (event.code == KEYCODE.ENTER || event.code == KEYCODE.NUMPAD_ENTER) && speech.finalResult_) { @@ -621,7 +621,7 @@ case speech.State_.SPEECH_RECEIVED: case speech.State_.RESULT_RECEIVED: case speech.State_.ERROR_RECEIVED: - speech.stop_(); + speech.stop(); break; } }; @@ -638,7 +638,7 @@ } if (document.webkitHidden) { - speech.stop_(); + speech.stop(); } }; @@ -648,7 +648,7 @@ */ speech.onOmniboxFocused = function() { if (!speech.isUiDefinitelyHidden_()) { - speech.stop_(); + speech.stop(); } }; @@ -684,7 +684,7 @@ const queryUrl = new URL('/search', speech.googleBaseUrl_); queryUrl.search = searchParams; - speech.stop_(); + speech.stop(); speech.navigateToUrl_(queryUrl); }; @@ -761,7 +761,7 @@ */ speech.resetErrorTimer_ = function(duration) { window.clearTimeout(speech.errorTimer_); - speech.errorTimer_ = window.setTimeout(speech.stop_, duration); + speech.errorTimer_ = window.setTimeout(speech.stop, duration); }; @@ -802,18 +802,6 @@ /** - * Toggles starting and stopping of speech recognition by the speech tool. - */ -speech.toggleStartStop = function() { - if (speech.currentState_ == speech.State_.READY) { - speech.start_(); - } else { - speech.stop_(); - } -}; - - -/** * Handles click events during speech recognition. * @param {boolean} shouldSubmit True if a query should be submitted. * @param {boolean} shouldRetry True if the interface should be restarted. @@ -830,17 +818,16 @@ // If the user clicks on a "Learn more" or "Details" support page link // from an error message, do nothing, and let Chrome navigate to that page. } else { - speech.stop_(); + speech.stop(); } }; /** * Restarts voice recognition. Used for the 'Try again' error link. - * @private */ speech.restart = function() { speech.reset_(); - speech.toggleStartStop(); + speech.start(); }; @@ -929,6 +916,15 @@ /** + * Base link target for help regarding voice search. To be appended + * with a locale string for proper target site localization. + * @const @private + */ +text.SUPPORT_LINK_BASE_ = + 'https://support.google.com/chrome/?p=ui_voice_search&hl='; + + +/** * The final / high confidence speech recognition result element. * @private {Element} */ @@ -957,15 +953,6 @@ /** - * Base link target for help regarding voice search. To be appended - * with a locale string for proper target site localization. - * @const @private - */ -text.SUPPORT_LINK_BASE_ = - 'https://support.google.com/chrome/?p=ui_voice_search&hl='; - - -/** * Finds the text view elements. */ text.init = function() { @@ -1061,7 +1048,7 @@ case RecognitionError.LANGUAGE_NOT_SUPPORTED: return speech.messages.languageError; default: - return ''; + return speech.messages.otherError; } };
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 3e50a383..6805a14 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -141,6 +141,8 @@ AddString(translated_strings.get(), "tryAgain", IDS_NEW_TAB_VOICE_TRY_AGAIN); AddString(translated_strings.get(), "waiting", IDS_NEW_TAB_VOICE_WAITING); + AddString(translated_strings.get(), "otherError", + IDS_NEW_TAB_VOICE_OTHER_ERROR); } return translated_strings;
diff --git a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc index 5b389fc..9195e5b 100644 --- a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc +++ b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc
@@ -123,7 +123,7 @@ auto simulator = content::NavigationSimulator::CreateRendererInitiated(url, rfh); simulator->Commit(); - return simulator->GetLastThrottleCheckResult() == + return simulator->GetLastThrottleCheckResult().action() == content::NavigationThrottle::PROCEED ? simulator->GetFinalRenderFrameHost() : nullptr;
diff --git a/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc index ba725f4..354e3fda 100644 --- a/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc +++ b/chrome/browser/supervised_user/supervised_user_google_auth_navigation_throttle.cc
@@ -74,7 +74,7 @@ content::NavigationThrottle::ThrottleCheckResult result = ShouldProceed(child_account_service_->IsGoogleAuthenticated()); - if (result == content::NavigationThrottle::DEFER) { + if (result.action() == content::NavigationThrottle::DEFER) { google_auth_state_subscription_ = child_account_service_->ObserveGoogleAuthState( base::Bind(&SupervisedUserGoogleAuthNavigationThrottle:: @@ -90,7 +90,7 @@ content::NavigationThrottle::ThrottleCheckResult result = ShouldProceed(authenticated); - switch (result) { + switch (result.action()) { case content::NavigationThrottle::PROCEED: { google_auth_state_subscription_.reset(); Resume();
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc index e6207ffa..3eab10a5 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
@@ -159,8 +159,8 @@ if (got_result) behavior_ = SupervisedUserURLFilter::INVALID; if (deferred_) - return ThrottleCheckResult::DEFER; - return ThrottleCheckResult::PROCEED; + return NavigationThrottle::DEFER; + return NavigationThrottle::PROCEED; } void SupervisedUserNavigationThrottle::ShowInterstitial(
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 4b44dd2..7a14966 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -420,7 +420,7 @@ // Enables or disables the creation of (legacy) supervised users. Does not // affect existing supervised users. const base::Feature kSupervisedUserCreation{"SupervisedUserCreation", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #if defined(OS_CHROMEOS) // Enables or disables chrome://sys-internals.
diff --git a/chrome/test/data/local_ntp/voice_speech_browsertest.js b/chrome/test/data/local_ntp/voice_speech_browsertest.js index f16dcb2..509c447 100644 --- a/chrome/test/data/local_ntp/voice_speech_browsertest.js +++ b/chrome/test/data/local_ntp/voice_speech_browsertest.js
@@ -42,6 +42,7 @@ networkError: 'Network error', noTranslation: 'No translation', noVoice: 'No voice', + otherError: 'Unknown error', permissionError: 'Permission error', ready: 'Ready', tryAgain: 'Try again', @@ -158,7 +159,7 @@ }; this.continuous = false; this.interimResults = false; - this.maxAlternatives = 0; + this.maxAlternatives = 1; this.onerror = null; this.onnomatch = null; this.onend = null; @@ -178,10 +179,12 @@ * Tests if the controller has the correct speech recognition settings. */ test.speech.testSpeechRecognitionInitSettings = function() { + test.speech.recognitionStubs.reset(); + test.speech.initSpeech(); assertFalse(speech.recognition_.continuous); assertEquals('en-ZA', speech.recognition_.lang); - assertEquals(4, speech.recognition_.maxAlternatives); + assertEquals(1, speech.recognition_.maxAlternatives); assert(!!speech.recognition_); test.speech.validateInactive(); }; @@ -230,7 +233,7 @@ */ test.speech.testOmniboxFocusWithWorkingView = function() { test.speech.initSpeech(); - speech.start_(); + speech.start(); assertEquals(speech.State_.STARTED, speech.currentState_); assertEquals(1, test.speech.recognitionActiveCount); @@ -254,7 +257,7 @@ speech.recognition_ = undefined; assertEquals(speech.State_.READY, speech.currentState_); assert(!speech.recognition_); - speech.toggleStartStop(); + speech.start(); assertEquals(1, test.speech.recognitionActiveCount); assertEquals(1, test.speech.viewActiveCount); @@ -268,7 +271,7 @@ */ test.speech.testHandleAudioStart = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); assertTrue('ready' in test.speech.viewState); @@ -284,7 +287,7 @@ */ test.speech.testHandleSpeechStart = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); @@ -307,7 +310,7 @@ const responseEvent = test.speech.createInterimResponse(lowConfidenceText, highConfidenceText); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.recognition_.onresult(responseEvent); @@ -331,7 +334,7 @@ const responseEvent = test.speech.createFinalResponse(lowConfidenceText, highConfidenceText); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); // Handle a final transcript from the recognition API. @@ -363,13 +366,13 @@ const responseEvent = test.speech.createInterimResponse(lowConfidenceText, highConfidenceText); - speech.start_(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); // Handle an interim trancript from the recognition API. speech.recognition_.onresult(responseEvent); // The user interrupts speech. - speech.stop_(); + speech.stop(); assertFalse(speech.isRecognizing_()); assertEquals('', speech.interimResult_); @@ -393,10 +396,10 @@ */ test.speech.testInterruptSpeechInputBeforeResult = function() { test.speech.initSpeech(); - speech.start_(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); - speech.stop_(); + speech.stop(); test.speech.validateInactive(); }; @@ -408,7 +411,7 @@ */ test.speech.testSpeechRecognitionErrorTimeout = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onerror({error: 'some-error'}); assertFalse(speech.isRecognizing_()); @@ -431,7 +434,7 @@ */ test.speech.testNoSpeechInput = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onend(null); @@ -480,7 +483,7 @@ test.speech.initSpeech(); assertRecognitionHandlers(true); - speech.start_(); + speech.start(); assertRecognitionHandlers(true); speech.recognition_.onaudiostart(null); @@ -497,7 +500,7 @@ test.speech.validateInactive(); assertRecognitionHandlers(true); - speech.start_(); + speech.start(); assertRecognitionHandlers(true); }; @@ -505,7 +508,7 @@ /** * Tests starting and stopping the Speech Recognition API quickly * in succession. - * Motivation: If |speech.start_()| is called too soon after |speech.stop_()|, + * Motivation: If |speech.start()| is called too soon after |speech.stop()|, * then the recognition interface hasn't yet reset and an error occurs. * In this case we need to hard-reset it and reissue the |recognition_.start()| * command. @@ -514,7 +517,7 @@ test.speech.recognitionStubs.reset(); test.speech.initSpeech(); - speech.start_(); + speech.start(); assertEquals(speech.State_.STARTED, speech.currentState_); assertTrue(speech.isRecognizing_()); @@ -522,15 +525,15 @@ assertEquals(speech.State_.AUDIO_RECEIVED, speech.currentState_); assertTrue(speech.isRecognizing_()); - speech.stop_(); + speech.stop(); assertEquals(speech.State_.READY, speech.currentState_); test.speech.validateInactive(); - speech.start_(); + speech.start(); assertEquals(speech.State_.STARTED, speech.currentState_); assertTrue(speech.isRecognizing_()); - speech.stop_(); + speech.stop(); assertEquals(speech.State_.READY, speech.currentState_); test.speech.validateInactive(); }; @@ -572,7 +575,7 @@ */ test.speech.testEnterToSubmit = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.finalResult_ = 'test query'; @@ -596,7 +599,7 @@ */ test.speech.testClickToSubmit = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.finalResult_ = 'test query'; @@ -680,7 +683,7 @@ */ test.speech.testClickToAbort = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.onClick_( @@ -695,7 +698,7 @@ */ test.speech.testClickToRetryWhenStopped = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); // An onend event after onpeechstart forces an error and stops recognition. @@ -715,7 +718,7 @@ */ test.speech.testClickToRetryWhenNotStopped = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.onClick_( @@ -731,7 +734,7 @@ */ test.speech.testNoSpeechInputMatched = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.recognition_.onnomatch(null); @@ -762,7 +765,7 @@ test.speech.createInterimResponse(lowConfidenceText, highConfidenceText); speech.reset_(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.recognition_.onresult(responseEvent); @@ -800,7 +803,7 @@ test.speech.createInterimResponse(lowConfidenceText, highConfidenceText); speech.reset_(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.recognition_.onresult(responseEvent); @@ -823,7 +826,7 @@ */ test.speech.testQueryEncoding = function() { test.speech.initSpeech(); - speech.toggleStartStop(); + speech.start(); speech.recognition_.onaudiostart(null); speech.recognition_.onspeechstart(null); speech.finalResult_ = '🔍t&qôr 文字+weird*chär%?s?';
diff --git a/chrome/test/data/local_ntp/voice_text_browsertest.js b/chrome/test/data/local_ntp/voice_text_browsertest.js index c7684a7..789ab2e 100644 --- a/chrome/test/data/local_ntp/voice_text_browsertest.js +++ b/chrome/test/data/local_ntp/voice_text_browsertest.js
@@ -48,6 +48,7 @@ networkError: 'Network error', noTranslation: 'No translation', noVoice: 'No voice', + otherError: 'Unknown error', permissionError: 'Permission error', ready: 'Ready', tryAgain: 'Try again',
diff --git a/chrome/test/data/local_ntp/voice_view_browsertest.js b/chrome/test/data/local_ntp/voice_view_browsertest.js index 831fb733..eee8a838 100644 --- a/chrome/test/data/local_ntp/voice_view_browsertest.js +++ b/chrome/test/data/local_ntp/voice_view_browsertest.js
@@ -16,12 +16,13 @@ /** * The set of textual strings for different states. - * @enum {string} + * @const */ -test.view.Text = { - WAITING: 'Waiting...', +test.view.TEXT = { + BLANK: '', + ERROR: 'Error', SPEAK_NOW: 'Speak now', - BLANK: '' + WAITING: 'Waiting...' }; @@ -80,20 +81,24 @@ // Mock text area manipulating functions. test.view.stubs.replace(text, 'showInitializingMessage', function() { // Ignore the short timeout before showing "Waiting...". - test.view.interimText = test.view.Text.WAITING; - test.view.finalText = test.view.Text.BLANK; + test.view.interimText = test.view.TEXT.WAITING; + test.view.finalText = test.view.TEXT.BLANK; }); test.view.stubs.replace(text, 'showReadyMessage', function() { - test.view.interimText = test.view.Text.SPEAK_NOW; - test.view.finalText = test.view.Text.BLANK; + test.view.interimText = test.view.TEXT.SPEAK_NOW; + test.view.finalText = test.view.TEXT.BLANK; + }); + test.view.stubs.replace(text, 'showErrorMessage', function() { + test.view.interimText = test.view.TEXT.ERROR; + test.view.finalText = test.view.TEXT.BLANK; }); test.view.stubs.replace(text, 'updateTextArea', function(texti, textf = '') { test.view.interimText = texti; test.view.finalText = textf; }); test.view.stubs.replace(text, 'clear', function() { - test.view.interimText = test.view.Text.BLANK; - test.view.finalText = test.view.Text.BLANK; + test.view.interimText = test.view.TEXT.BLANK; + test.view.finalText = test.view.TEXT.BLANK; }); // Mock level animation state. @@ -127,8 +132,8 @@ view.show(); test.view.assertViewActive( - /*interim=*/test.view.Text.WAITING, - /*final=*/test.view.Text.BLANK, + /*interim=*/test.view.TEXT.WAITING, + /*final=*/test.view.TEXT.BLANK, /*containerClass=*/view.INACTIVE_CLASS_, /*levelAnimationActive=*/false); }; @@ -143,8 +148,8 @@ view.show(); test.view.assertViewActive( - /*interim=*/test.view.Text.WAITING, - /*final=*/test.view.Text.BLANK, + /*interim=*/test.view.TEXT.WAITING, + /*final=*/test.view.TEXT.BLANK, /*containerClass=*/view.INACTIVE_CLASS_, /*levelAnimationActive=*/false); }; @@ -173,8 +178,8 @@ view.setReadyForSpeech(); test.view.assertViewActive( - /*interim=*/test.view.Text.SPEAK_NOW, - /*final=*/test.view.Text.BLANK, + /*interim=*/test.view.TEXT.SPEAK_NOW, + /*final=*/test.view.TEXT.BLANK, /*containerClass=*/view.MICROPHONE_LISTENING_CLASS_, /*levelAnimationActive=*/false); }; @@ -202,8 +207,8 @@ view.setReceivingSpeech(); test.view.assertViewActive( - /*interim=*/test.view.Text.SPEAK_NOW, - /*final=*/test.view.Text.BLANK, + /*interim=*/test.view.TEXT.SPEAK_NOW, + /*final=*/test.view.TEXT.BLANK, /*containerClass=*/view.RECEIVING_SPEECH_CLASS_, /*levelAnimationActive=*/true); }; @@ -458,8 +463,8 @@ view.showError(RecognitionError.OTHER); test.view.assertViewActive( - /*interim=*/test.view.Text.BLANK, - /*final=*/test.view.Text.BLANK, + /*interim=*/test.view.TEXT.ERROR, + /*final=*/test.view.TEXT.BLANK, /*containerClass=*/view.ERROR_RECEIVED_CLASS_, /*levelAnimationActive=*/false); }; @@ -477,8 +482,8 @@ assertFalse(view.isNoMatchShown_); assertEquals(view.OVERLAY_HIDDEN_CLASS_, view.background_.className); - assertEquals(test.view.Text.BLANK, test.view.interimText); - assertEquals(test.view.Text.BLANK, test.view.finalText); + assertEquals(test.view.TEXT.BLANK, test.view.interimText); + assertEquals(test.view.TEXT.BLANK, test.view.finalText); assertEquals(view.INACTIVE_CLASS_, view.container_.className); assertFalse(test.view.levelAnimationActive); };
diff --git a/components/ntp_snippets/remote/proto/ntp_snippets.proto b/components/ntp_snippets/remote/proto/ntp_snippets.proto index 7aa3641..ffcb538 100644 --- a/components/ntp_snippets/remote/proto/ntp_snippets.proto +++ b/components/ntp_snippets/remote/proto/ntp_snippets.proto
@@ -22,7 +22,7 @@ optional int64 publish_date = 5; optional int64 expiry_date = 6; optional float score = 7; - repeated SnippetSourceProto sources = 8; + optional SnippetSourceProto source = 8; optional bool dismissed = 9; optional int32 remote_category_id = 10; // The time when the snippet was fetched from the server.
diff --git a/components/ntp_snippets/remote/remote_suggestion.cc b/components/ntp_snippets/remote/remote_suggestion.cc index 0157646..5569081 100644 --- a/components/ntp_snippets/remote/remote_suggestion.cc +++ b/components/ntp_snippets/remote/remote_suggestion.cc
@@ -16,39 +16,6 @@ namespace { -struct SnippetSource { - SnippetSource(const GURL& url, - const std::string& publisher_name, - const GURL& amp_url) - : url(url), publisher_name(publisher_name), amp_url(amp_url) {} - GURL url; - std::string publisher_name; - GURL amp_url; -}; - -const SnippetSource& FindBestSource(const std::vector<SnippetSource>& sources) { - // The same article can be hosted by multiple sources, e.g. nytimes.com, - // cnn.com, etc. We need to parse the list of sources for this article and - // find the best match. In order of preference: - // 1) A source that has URL, publisher name, AMP URL - // 2) A source that has URL, publisher name - // 3) A source that has URL and AMP URL, or URL only (since we won't show - // the snippet to users if the article does not have a publisher name, it - // doesn't matter whether the snippet has the AMP URL or not) - int best_source_index = 0; - for (size_t i = 0; i < sources.size(); ++i) { - const SnippetSource& source = sources[i]; - if (!source.publisher_name.empty()) { - best_source_index = i; - if (!source.amp_url.is_empty()) { - // This is the best possible source, stop looking. - break; - } - } - } - return sources[best_source_index]; -} - // dict.Get() specialization for base::Time values bool GetTimeValue(const base::DictionaryValue& dict, const std::string& key, @@ -81,8 +48,6 @@ kArticlesRemoteId, "kArticlesRemoteId has a wrong value?!"); -const int kChromeReaderDefaultExpiryTimeMins = 3 * 24 * 60; - RemoteSuggestion::RemoteSuggestion(const std::vector<std::string>& ids, int remote_category_id) : ids_(ids), @@ -97,128 +62,6 @@ // static std::unique_ptr<RemoteSuggestion> -RemoteSuggestion::CreateFromChromeReaderDictionary( - const base::DictionaryValue& dict, - const base::Time& fetch_date) { - const base::DictionaryValue* content = nullptr; - if (!dict.GetDictionary("contentInfo", &content)) { - return nullptr; - } - - // Need at least a primary id. - std::string primary_id; - if (!content->GetString("url", &primary_id) || primary_id.empty()) { - return nullptr; - } - - const base::ListValue* corpus_infos_list = nullptr; - if (!content->GetList("sourceCorpusInfo", &corpus_infos_list)) { - DLOG(WARNING) << "No sources found for article " << primary_id; - return nullptr; - } - - std::vector<std::string> ids(1, primary_id); - std::vector<SnippetSource> sources; - for (const auto& value : *corpus_infos_list) { - const base::DictionaryValue* dict_value = nullptr; - if (!value.GetAsDictionary(&dict_value)) { - DLOG(WARNING) << "Invalid source info for article " << primary_id; - continue; - } - - std::string corpus_id_str; - GURL corpus_id; - if (dict_value->GetString("corpusId", &corpus_id_str)) { - corpus_id = GURL(corpus_id_str); - } - - if (!corpus_id.is_valid()) { - // We must at least have a valid source URL. - DLOG(WARNING) << "Invalid article url " << corpus_id_str; - continue; - } - const base::DictionaryValue* publisher_data = nullptr; - std::string site_title; - if (dict_value->GetDictionary("publisherData", &publisher_data)) { - if (!publisher_data->GetString("sourceName", &site_title)) { - // It's possible but not desirable to have no publisher data. - DLOG(WARNING) << "No publisher name for article " << corpus_id_str; - } - } else { - DLOG(WARNING) << "No publisher data for article " << corpus_id_str; - } - - std::string amp_url_str; - GURL amp_url; - // Expected to not have AMP url sometimes. - if (dict_value->GetString("ampUrl", &_url_str)) { - amp_url = GURL(amp_url_str); - DLOG_IF(WARNING, !amp_url.is_valid()) - << "Invalid AMP url " << amp_url_str; - } - sources.emplace_back(corpus_id, site_title, - amp_url.is_valid() ? amp_url : GURL()); - // We use the raw string so that we can compare it against other primary - // IDs. Parsing the ID as a URL might add a trailing slash (and we don't do - // this for the primary ID). - ids.push_back(corpus_id_str); - } - if (sources.empty()) { - DLOG(WARNING) << "No sources found for article " << primary_id; - return nullptr; - } - - std::unique_ptr<RemoteSuggestion> snippet( - new RemoteSuggestion(ids, kArticlesRemoteId)); - snippet->fetch_date_ = fetch_date; - - std::string title; - if (content->GetString("title", &title)) { - snippet->title_ = title; - } - std::string salient_image_url; - if (content->GetString("thumbnailUrl", &salient_image_url)) { - snippet->salient_image_url_ = GURL(salient_image_url); - } - std::string snippet_str; - if (content->GetString("snippet", &snippet_str)) { - snippet->snippet_ = snippet_str; - } - // The creation and expiry timestamps are uint64s which are stored as strings. - std::string creation_timestamp_str; - if (content->GetString("creationTimestampSec", &creation_timestamp_str)) { - snippet->publish_date_ = TimeFromJsonString(creation_timestamp_str); - } - std::string expiry_timestamp_str; - if (content->GetString("expiryTimestampSec", &expiry_timestamp_str)) { - snippet->expiry_date_ = TimeFromJsonString(expiry_timestamp_str); - } - - // If publish and/or expiry date are missing, fill in reasonable defaults. - if (snippet->publish_date_.is_null()) { - snippet->publish_date_ = base::Time::Now(); - } - if (snippet->expiry_date_.is_null()) { - snippet->expiry_date_ = - snippet->publish_date() + - base::TimeDelta::FromMinutes(kChromeReaderDefaultExpiryTimeMins); - } - - const SnippetSource& source = FindBestSource(sources); - snippet->url_ = source.url; - snippet->publisher_name_ = source.publisher_name; - snippet->amp_url_ = source.amp_url; - - double score; - if (dict.GetDouble("score", &score)) { - snippet->score_ = score; - } - - return snippet; -} - -// static -std::unique_ptr<RemoteSuggestion> RemoteSuggestion::CreateFromContentSuggestionsDictionary( const base::DictionaryValue& dict, int remote_category_id, @@ -338,33 +181,25 @@ snippet->score_ = proto.score(); snippet->is_dismissed_ = proto.dismissed(); - std::vector<SnippetSource> sources; - for (int i = 0; i < proto.sources_size(); ++i) { - const SnippetSourceProto& source_proto = proto.sources(i); - GURL url(source_proto.url()); - if (!url.is_valid()) { - // We must at least have a valid source URL. - DLOG(WARNING) << "Invalid article url " << source_proto.url(); - continue; - } - GURL amp_url; - if (source_proto.has_amp_url()) { - amp_url = GURL(source_proto.amp_url()); - DLOG_IF(WARNING, !amp_url.is_valid()) - << "Invalid AMP URL " << source_proto.amp_url(); - } - - sources.emplace_back(url, source_proto.publisher_name(), amp_url); - } - - if (sources.empty()) { - DLOG(WARNING) << "No sources found for article " << snippet->id(); + if (!proto.has_source()) { + DLOG(WARNING) << "No source found for article " << snippet->id(); return nullptr; } - const SnippetSource& source = FindBestSource(sources); - snippet->url_ = source.url; - snippet->publisher_name_ = source.publisher_name; - snippet->amp_url_ = source.amp_url; + GURL url(proto.source().url()); + if (!url.is_valid()) { + // We must at least have a valid source URL. + DLOG(WARNING) << "Invalid article url " << proto.source().url(); + return nullptr; + } + GURL amp_url; + if (proto.source().has_amp_url()) { + amp_url = GURL(proto.source().amp_url()); + DLOG_IF(WARNING, !amp_url.is_valid()) + << "Invalid AMP URL " << proto.source().amp_url(); + } + snippet->url_ = url; + snippet->publisher_name_ = proto.source().publisher_name(); + snippet->amp_url_ = amp_url; if (proto.has_fetch_date()) { snippet->fetch_date_ = base::Time::FromInternalValue(proto.fetch_date()); @@ -404,7 +239,7 @@ result.set_dismissed(is_dismissed_); result.set_remote_category_id(remote_category_id_); - SnippetSourceProto* source_proto = result.add_sources(); + SnippetSourceProto* source_proto = result.mutable_source(); source_proto->set_url(url_.spec()); if (!publisher_name_.empty()) { source_proto->set_publisher_name(publisher_name_); @@ -458,24 +293,6 @@ } // static -base::Time RemoteSuggestion::TimeFromJsonString( - const std::string& timestamp_str) { - int64_t timestamp; - if (!base::StringToInt64(timestamp_str, ×tamp)) { - // Even if there's an error in the conversion, some garbage data may still - // be written to the output var, so reset it. - DLOG(WARNING) << "Invalid json timestamp: " << timestamp_str; - timestamp = 0; - } - return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(timestamp); -} - -// static -std::string RemoteSuggestion::TimeToJsonString(const base::Time& time) { - return base::Int64ToString((time - base::Time::UnixEpoch()).InSeconds()); -} - -// static std::unique_ptr<RemoteSuggestion> RemoteSuggestion::MakeUnique( const std::vector<std::string>& ids, int remote_category_id) {
diff --git a/components/ntp_snippets/remote/remote_suggestion.h b/components/ntp_snippets/remote/remote_suggestion.h index 367cd3e..fa1e483 100644 --- a/components/ntp_snippets/remote/remote_suggestion.h +++ b/components/ntp_snippets/remote/remote_suggestion.h
@@ -23,7 +23,6 @@ // Exposed for tests. extern const int kArticlesRemoteId; -extern const int kChromeReaderDefaultExpiryTimeMins; class SnippetProto; @@ -35,17 +34,9 @@ ~RemoteSuggestion(); - // Creates a RemoteSuggestion from a dictionary, as returned by Chrome Reader. - // Returns a null pointer if the dictionary doesn't correspond to a valid - // suggestion. The keys in the dictionary are expected to be the same as the - // property name, with exceptions documented in the property comment. - static std::unique_ptr<RemoteSuggestion> CreateFromChromeReaderDictionary( - const base::DictionaryValue& dict, - const base::Time& fetch_date); - // Creates a RemoteSuggestion from a dictionary, as returned by Chrome Content // Suggestions. Returns a null pointer if the dictionary doesn't correspond to - // a valid suggestion. Maps field names to Chrome Reader field names. + // a valid suggestion. static std::unique_ptr<RemoteSuggestion> CreateFromContentSuggestionsDictionary(const base::DictionaryValue& dict, int remote_category_id, @@ -87,13 +78,10 @@ const std::string& snippet() const { return snippet_; } // Link to an image representative of the content. Do not fetch this image - // directly. If initialized by CreateFromChromeReaderDictionary() the relevant - // key is 'thumbnailUrl' + // directly. const GURL& salient_image_url() const { return salient_image_url_; } - // When the page pointed by this suggestion was published. If initialized by - // CreateFromChromeReaderDictionary() the relevant key is - // 'creationTimestampSec' + // When the page pointed by this suggestion was published. const base::Time& publish_date() const { return publish_date_; } // After this expiration date this suggestion should no longer be presented to @@ -131,10 +119,6 @@ base::Time fetch_date() const { return fetch_date_; } - // Public for testing. - static base::Time TimeFromJsonString(const std::string& timestamp_str); - static std::string TimeToJsonString(const base::Time& time); - private: RemoteSuggestion(const std::vector<std::string>& ids, int remote_category_id);
diff --git a/components/ntp_snippets/remote/remote_suggestion_builder.cc b/components/ntp_snippets/remote/remote_suggestion_builder.cc index 95d3d02..f552601 100644 --- a/components/ntp_snippets/remote/remote_suggestion_builder.cc +++ b/components/ntp_snippets/remote/remote_suggestion_builder.cc
@@ -148,7 +148,7 @@ proto.set_score(score_.value_or(1)); proto.set_dismissed(is_dismissed_.value_or(false)); proto.set_remote_category_id(remote_category_id_.value_or(1)); - auto* source = proto.add_sources(); + auto* source = proto.mutable_source(); source->set_url(url_.value_or("http://url.com/")); source->set_publisher_name(publisher_name_.value_or("Publisher")); source->set_amp_url(amp_url_.value_or("http://amp_url.com/"));
diff --git a/components/ntp_snippets/remote/remote_suggestion_unittest.cc b/components/ntp_snippets/remote/remote_suggestion_unittest.cc index 6c8d7876..066bfa91 100644 --- a/components/ntp_snippets/remote/remote_suggestion_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestion_unittest.cc
@@ -35,7 +35,7 @@ *json_dict, kArticlesRemoteId, fetch_date); } -TEST(RemoteSuggestionTest, FromChromeContentSuggestionsDictionary) { +TEST(RemoteSuggestionTest, FromContentSuggestionsDictionary) { const std::string kJsonStr = "{" " \"ids\" : [\"http://localhost/foobar\"]," @@ -79,291 +79,6 @@ EXPECT_EQ(fetch_date, snippet->fetch_date()); } -std::unique_ptr<RemoteSuggestion> SnippetFromChromeReaderDict( - std::unique_ptr<base::DictionaryValue> dict, - const base::Time& fetch_date) { - if (!dict) { - return nullptr; - } - return RemoteSuggestion::CreateFromChromeReaderDictionary(*dict, fetch_date); -} - -const char kChromeReaderCreationTimestamp[] = "1234567890"; -const char kChromeReaderExpiryTimestamp[] = "2345678901"; - -// Old form, from chromereader-pa.googleapis.com. Two sources. -std::unique_ptr<base::DictionaryValue> ChromeReaderSnippetWithTwoSources() { - const std::string kJsonStr = base::StringPrintf( - "{\n" - " \"contentInfo\": {\n" - " \"url\": \"http://url.com\",\n" - " \"title\": \"Source 1 Title\",\n" - " \"snippet\": \"Source 1 Snippet\",\n" - " \"thumbnailUrl\": \"http://url.com/thumbnail\",\n" - " \"creationTimestampSec\": \"%s\",\n" - " \"expiryTimestampSec\": \"%s\",\n" - " \"sourceCorpusInfo\": [{\n" - " \"corpusId\": \"http://source1.com\",\n" - " \"publisherData\": {\n" - " \"sourceName\": \"Source 1\"\n" - " },\n" - " \"ampUrl\": \"http://source1.amp.com\"\n" - " }, {\n" - " \"corpusId\": \"http://source2.com\",\n" - " \"publisherData\": {\n" - " \"sourceName\": \"Source 2\"\n" - " },\n" - " \"ampUrl\": \"http://source2.amp.com\"\n" - " }]\n" - " },\n" - " \"score\": 5.0\n" - "}\n", - kChromeReaderCreationTimestamp, kChromeReaderExpiryTimestamp); - - auto json_value = base::JSONReader::Read(kJsonStr); - base::DictionaryValue* json_dict; - if (!json_value->GetAsDictionary(&json_dict)) { - return nullptr; - } - return json_dict->CreateDeepCopy(); -} - -TEST(RemoteSuggestionTest, TestMultipleSources) { - auto snippet = SnippetFromChromeReaderDict( - ChromeReaderSnippetWithTwoSources(), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - // Expect the first source to be chosen. - EXPECT_EQ(snippet->id(), "http://url.com"); - EXPECT_EQ(snippet->url(), GURL("http://source1.com")); - EXPECT_EQ(snippet->publisher_name(), std::string("Source 1")); - EXPECT_EQ(snippet->amp_url(), GURL("http://source1.amp.com")); -} - -TEST(RemoteSuggestionTest, TestMultipleIncompleteSources1) { - // Set Source 2 to have no AMP url, and Source 1 to have no publisher name - // Source 2 should win since we favor publisher name over amp url - auto dict = ChromeReaderSnippetWithTwoSources(); - base::ListValue* sources; - ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources)); - base::DictionaryValue* source; - ASSERT_TRUE(sources->GetDictionary(0, &source)); - source->Remove("publisherData.sourceName", nullptr); - ASSERT_TRUE(sources->GetDictionary(1, &source)); - source->Remove("ampUrl", nullptr); - - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - EXPECT_EQ(snippet->id(), "http://url.com"); - EXPECT_EQ(snippet->url(), GURL("http://source2.com")); - EXPECT_EQ(snippet->publisher_name(), std::string("Source 2")); - EXPECT_EQ(snippet->amp_url(), GURL()); -} - -TEST(RemoteSuggestionTest, TestMultipleIncompleteSources2) { - // Set Source 1 to have no AMP url, and Source 2 to have no publisher name - // Source 1 should win in this case since we prefer publisher name to AMP url - auto dict = ChromeReaderSnippetWithTwoSources(); - base::ListValue* sources; - ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources)); - base::DictionaryValue* source; - ASSERT_TRUE(sources->GetDictionary(0, &source)); - source->Remove("ampUrl", nullptr); - ASSERT_TRUE(sources->GetDictionary(1, &source)); - source->Remove("publisherData.sourceName", nullptr); - - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - EXPECT_EQ(snippet->id(), "http://url.com"); - EXPECT_EQ(snippet->url(), GURL("http://source1.com")); - EXPECT_EQ(snippet->publisher_name(), std::string("Source 1")); - EXPECT_EQ(snippet->amp_url(), GURL()); -} - -TEST(RemoteSuggestionTest, TestMultipleIncompleteSources3) { - // Set source 1 to have no AMP url and no source, and source 2 to only have - // amp url. There should be no snippets since we only add sources we consider - // complete - auto dict = ChromeReaderSnippetWithTwoSources(); - base::ListValue* sources; - ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources)); - base::DictionaryValue* source; - ASSERT_TRUE(sources->GetDictionary(0, &source)); - source->Remove("publisherData.sourceName", nullptr); - source->Remove("ampUrl", nullptr); - ASSERT_TRUE(sources->GetDictionary(1, &source)); - source->Remove("publisherData.sourceName", nullptr); - - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - ASSERT_FALSE(snippet->is_complete()); -} - -TEST(RemoteSuggestionTest, ShouldFillInCreation) { - auto dict = ChromeReaderSnippetWithTwoSources(); - ASSERT_TRUE(dict->Remove("contentInfo.creationTimestampSec", nullptr)); - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - // Publish date should have been filled with "now" - just make sure it's not - // empty and not the test default value. - base::Time publish_date = snippet->publish_date(); - EXPECT_FALSE(publish_date.is_null()); - EXPECT_NE(publish_date, RemoteSuggestion::TimeFromJsonString( - kChromeReaderCreationTimestamp)); - // Expiry date should have kept the test default value. - base::Time expiry_date = snippet->expiry_date(); - EXPECT_FALSE(expiry_date.is_null()); - EXPECT_EQ(expiry_date, - RemoteSuggestion::TimeFromJsonString(kChromeReaderExpiryTimestamp)); -} - -TEST(RemoteSuggestionTest, ShouldFillInExpiry) { - auto dict = ChromeReaderSnippetWithTwoSources(); - ASSERT_TRUE(dict->Remove("contentInfo.expiryTimestampSec", nullptr)); - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - base::Time publish_date = snippet->publish_date(); - ASSERT_FALSE(publish_date.is_null()); - // Expiry date should have been filled with creation date + offset. - base::Time expiry_date = snippet->expiry_date(); - EXPECT_FALSE(expiry_date.is_null()); - EXPECT_EQ(publish_date + base::TimeDelta::FromMinutes( - kChromeReaderDefaultExpiryTimeMins), - expiry_date); -} - -TEST(RemoteSuggestionTest, ShouldFillInCreationAndExpiry) { - auto dict = ChromeReaderSnippetWithTwoSources(); - ASSERT_TRUE(dict->Remove("contentInfo.creationTimestampSec", nullptr)); - ASSERT_TRUE(dict->Remove("contentInfo.expiryTimestampSec", nullptr)); - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - // Publish date should have been filled with "now" - just make sure it's not - // empty and not the test default value. - base::Time publish_date = snippet->publish_date(); - EXPECT_FALSE(publish_date.is_null()); - EXPECT_NE(publish_date, RemoteSuggestion::TimeFromJsonString( - kChromeReaderCreationTimestamp)); - // Expiry date should have been filled with creation date + offset. - base::Time expiry_date = snippet->expiry_date(); - EXPECT_FALSE(expiry_date.is_null()); - EXPECT_EQ(publish_date + base::TimeDelta::FromMinutes( - kChromeReaderDefaultExpiryTimeMins), - expiry_date); -} - -TEST(RemoteSuggestionTest, ShouldNotOverwriteExpiry) { - auto dict = ChromeReaderSnippetWithTwoSources(); - ASSERT_TRUE(dict->Remove("contentInfo.creationTimestampSec", nullptr)); - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - // Expiry date should have kept the test default value. - base::Time expiry_date = snippet->expiry_date(); - EXPECT_FALSE(expiry_date.is_null()); - EXPECT_EQ(expiry_date, - RemoteSuggestion::TimeFromJsonString(kChromeReaderExpiryTimestamp)); -} - -// Old form, from chromereader-pa.googleapis.com. Three sources. -std::unique_ptr<base::DictionaryValue> ChromeReaderSnippetWithThreeSources() { - const std::string kJsonStr = base::StringPrintf( - "{\n" - " \"contentInfo\": {\n" - " \"url\": \"http://url.com\",\n" - " \"title\": \"Source 1 Title\",\n" - " \"snippet\": \"Source 1 Snippet\",\n" - " \"thumbnailUrl\": \"http://url.com/thumbnail\",\n" - " \"creationTimestampSec\": \"%s\",\n" - " \"expiryTimestampSec\": \"%s\",\n" - " \"sourceCorpusInfo\": [{\n" - " \"corpusId\": \"http://source1.com\",\n" - " \"publisherData\": {\n" - " \"sourceName\": \"Source 1\"\n" - " },\n" - " \"ampUrl\": \"http://source1.amp.com\"\n" - " }, {\n" - " \"corpusId\": \"http://source2.com\",\n" - " \"publisherData\": {\n" - " \"sourceName\": \"Source 2\"\n" - " },\n" - " \"ampUrl\": \"http://source2.amp.com\"\n" - " }, {\n" - " \"corpusId\": \"http://source3.com\",\n" - " \"publisherData\": {\n" - " \"sourceName\": \"Source 3\"\n" - " },\n" - " \"ampUrl\": \"http://source3.amp.com\"\n" - " }]\n" - " },\n" - " \"score\": 5.0\n" - "}\n", - kChromeReaderCreationTimestamp, kChromeReaderExpiryTimestamp); - - auto json_value = base::JSONReader::Read(kJsonStr); - base::DictionaryValue* json_dict; - if (!json_value->GetAsDictionary(&json_dict)) { - return nullptr; - } - return json_dict->CreateDeepCopy(); -} - -TEST(RemoteSuggestionTest, TestMultipleCompleteSources1) { - // Test 2 complete sources, we should choose the first complete source - auto dict = ChromeReaderSnippetWithThreeSources(); - base::ListValue* sources; - ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources)); - base::DictionaryValue* source; - ASSERT_TRUE(sources->GetDictionary(1, &source)); - source->Remove("publisherData.sourceName", nullptr); - - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - EXPECT_EQ(snippet->id(), "http://url.com"); - EXPECT_THAT(snippet->GetAllIDs(), - ElementsAre("http://url.com", "http://source1.com", - "http://source2.com", "http://source3.com")); - EXPECT_EQ(snippet->url(), GURL("http://source1.com")); - EXPECT_EQ(snippet->publisher_name(), std::string("Source 1")); - EXPECT_EQ(snippet->amp_url(), GURL("http://source1.amp.com")); -} - -TEST(RemoteSuggestionTest, TestMultipleCompleteSources2) { - // Test 2 complete sources, we should choose the first complete source - auto dict = ChromeReaderSnippetWithThreeSources(); - base::ListValue* sources; - ASSERT_TRUE(dict->GetList("contentInfo.sourceCorpusInfo", &sources)); - base::DictionaryValue* source; - ASSERT_TRUE(sources->GetDictionary(0, &source)); - source->Remove("publisherData.sourceName", nullptr); - - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - EXPECT_EQ(snippet->id(), "http://url.com"); - EXPECT_EQ(snippet->url(), GURL("http://source2.com")); - EXPECT_EQ(snippet->publisher_name(), std::string("Source 2")); - EXPECT_EQ(snippet->amp_url(), GURL("http://source2.amp.com")); -} - -TEST(RemoteSuggestionTest, TestMultipleCompleteSources3) { - // Test 3 complete sources, we should choose the first complete source - auto dict = ChromeReaderSnippetWithThreeSources(); - auto snippet = SnippetFromChromeReaderDict(std::move(dict), base::Time()); - ASSERT_THAT(snippet, NotNull()); - - EXPECT_EQ(snippet->id(), "http://url.com"); - EXPECT_EQ(snippet->url(), GURL("http://source1.com")); - EXPECT_EQ(snippet->publisher_name(), std::string("Source 1")); - EXPECT_EQ(snippet->amp_url(), GURL("http://source1.amp.com")); -} - TEST(RemoteSuggestionTest, ShouldSupportMultipleIdsFromContentSuggestionsServer) { const std::string kJsonStr = @@ -401,7 +116,7 @@ proto.set_remote_category_id(1); proto.set_fetch_date(1476364691); proto.set_content_type(SnippetProto_ContentType_VIDEO); - auto* source = proto.add_sources(); + auto* source = proto.mutable_source(); source->set_url("http://cool-suggestions.com/"); source->set_publisher_name("Great Suggestions Inc."); source->set_amp_url("http://cdn.ampproject.org/c/foo/"); @@ -435,7 +150,7 @@ proto.set_score(0.1f); proto.set_dismissed(false); proto.set_remote_category_id(1); - auto* source = proto.add_sources(); + auto* source = proto.mutable_source(); source->set_url("http://cool-suggestions.com/"); source->set_publisher_name("Great Suggestions Inc."); source->set_amp_url("http://cdn.ampproject.org/c/foo/"); @@ -449,7 +164,6 @@ EXPECT_EQ(snippet->fetch_date(), base::Time()); } -// New form, from chromecontentsuggestions-pa.googleapis.com. std::unique_ptr<base::DictionaryValue> ContentSuggestionSnippet() { const std::string kJsonStr = "{"
diff --git a/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc index b951f4d6..613fc20 100644 --- a/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
@@ -44,7 +44,7 @@ SnippetProto proto; proto.add_ids("http://localhost"); proto.set_remote_category_id(1); // Articles - auto* source = proto.add_sources(); + auto* source = proto.mutable_source(); source->set_url("http://localhost"); source->set_publisher_name("Publisher"); source->set_amp_url("http://amp");
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h index cfcfce2..068e01b8 100644 --- a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h +++ b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
@@ -64,22 +64,6 @@ } private: - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestAuthenticated); - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestUnauthenticated); - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestExcludedIds); - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestNoUserClass); - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestWithTwoLanguages); - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestWithUILanguageOnly); - FRIEND_TEST_ALL_PREFIXES(ChromeReaderSnippetsFetcherTest, - BuildRequestWithOtherLanguageOnly); - friend class ChromeReaderSnippetsFetcherTest; - void FetchSnippetsNonAuthenticated(internal::JsonRequest::Builder builder, SnippetsAvailableCallback callback); void FetchSnippetsAuthenticated(internal::JsonRequest::Builder builder,
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc index 39b8687..c6550993 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -828,8 +828,6 @@ // from the server. crbug.com/653816 bool response_includes_article_category = false; for (FetchedCategory& fetched_category : *fetched_categories) { - // TODO(tschumann): Remove this histogram once we only talk to the content - // suggestions cloud backend. if (fetched_category.category == articles_category_) { UMA_HISTOGRAM_SPARSE_SLOWLY( "NewTabPage.Snippets.NumArticlesFetched",
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc index ae50314c..7799f92 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -151,7 +151,7 @@ snippet_proto.set_publish_date(SerializeTime(GetDefaultCreationTime())); snippet_proto.set_expiry_date(SerializeTime(GetDefaultExpirationTime())); snippet_proto.set_remote_category_id(1); - auto* source = snippet_proto.add_sources(); + auto* source = snippet_proto.mutable_source(); source->set_url(url); source->set_publisher_name("Publisher"); source->set_amp_url(url + "amp");
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc index 2db31a5e..27499e7 100644 --- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc +++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
@@ -79,7 +79,7 @@ parent_activation_state_->activation_level == ActivationLevel::DISABLED) { DCHECK(navigation_handle()->IsInMainFrame()); DCHECK(!ruleset_handle_); - return content::NavigationThrottle::ThrottleCheckResult::PROCEED; + return content::NavigationThrottle::PROCEED; } DCHECK(ruleset_handle_); @@ -99,7 +99,7 @@ weak_ptr_factory_.GetWeakPtr())); defer_timestamp_ = base::TimeTicks::Now(); - return content::NavigationThrottle::ThrottleCheckResult::DEFER; + return content::NavigationThrottle::DEFER; } const char* ActivationStateComputingNavigationThrottle::GetNameForLogging() {
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc index e904794e..b509103 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -194,36 +194,36 @@ } void SimulateStartAndExpectResult( - content::NavigationThrottle::ThrottleCheckResult expect_result) { + content::NavigationThrottle::ThrottleAction expect_result) { navigation_simulator_->Start(); content::NavigationThrottle::ThrottleCheckResult result = navigation_simulator_->GetLastThrottleCheckResult(); EXPECT_EQ(expect_result, result); - if (result != content::NavigationThrottle::PROCEED) + if (result.action() != content::NavigationThrottle::PROCEED) navigation_simulator_.reset(); } void SimulateRedirectAndExpectResult( const GURL& new_url, - content::NavigationThrottle::ThrottleCheckResult expect_result) { + content::NavigationThrottle::ThrottleAction expect_result) { navigation_simulator_->Redirect(new_url); content::NavigationThrottle::ThrottleCheckResult result = navigation_simulator_->GetLastThrottleCheckResult(); EXPECT_EQ(expect_result, result); - if (result != content::NavigationThrottle::PROCEED) + if (result.action() != content::NavigationThrottle::PROCEED) navigation_simulator_.reset(); } // Returns the RenderFrameHost that the navigation commit in. content::RenderFrameHost* SimulateCommitAndExpectResult( - content::NavigationThrottle::ThrottleCheckResult expect_result) { + content::NavigationThrottle::ThrottleAction expect_result) { navigation_simulator_->Commit(); content::NavigationThrottle::ThrottleCheckResult result = navigation_simulator_->GetLastThrottleCheckResult(); EXPECT_EQ(expect_result, result); auto scoped_simulator = std::move(navigation_simulator_); - if (result == content::NavigationThrottle::PROCEED) + if (result.action() == content::NavigationThrottle::PROCEED) return scoped_simulator->GetFinalRenderFrameHost(); return nullptr; } @@ -370,12 +370,12 @@ CreateSubframeWithTestNavigation( GURL("https://www.example.com/before-redirect.html"), main_rfh()); SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED); - content::NavigationThrottle::ThrottleCheckResult expected_result = + content::NavigationThrottle::ThrottleAction expected_action = content::IsBrowserSideNavigationEnabled() ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE : content::NavigationThrottle::CANCEL; SimulateRedirectAndExpectResult( - GURL("https://www.example.com/disallowed.html"), expected_result); + GURL("https://www.example.com/disallowed.html"), expected_action); EXPECT_EQ(1, disallowed_notification_count()); }
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc index 21a5f71a..c436bf7a 100644 --- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc +++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
@@ -63,7 +63,7 @@ SubframeNavigationFilteringThrottle::WillProcessResponse() { DCHECK_NE(load_policy_, LoadPolicy::DISALLOW); NotifyLoadPolicy(); - return content::NavigationThrottle::ThrottleCheckResult::PROCEED; + return PROCEED; } const char* SubframeNavigationFilteringThrottle::GetNameForLogging() { @@ -75,13 +75,13 @@ ThrottlingStage stage) { DCHECK_NE(load_policy_, LoadPolicy::DISALLOW); if (load_policy_ == LoadPolicy::WOULD_DISALLOW) - return content::NavigationThrottle::ThrottleCheckResult::PROCEED; + return PROCEED; parent_frame_filter_->GetLoadPolicyForSubdocument( navigation_handle()->GetURL(), base::Bind(&SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy, weak_ptr_factory_.GetWeakPtr(), stage)); last_defer_timestamp_ = base::TimeTicks::Now(); - return content::NavigationThrottle::ThrottleCheckResult::DEFER; + return DEFER; } void SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy( @@ -111,9 +111,7 @@ content::IsBrowserSideNavigationEnabled() || stage == ThrottlingStage::WillStartRequest; CancelDeferredNavigation( - block_and_collapse_is_supported - ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE - : content::NavigationThrottle::CANCEL); + block_and_collapse_is_supported ? BLOCK_REQUEST_AND_COLLAPSE : CANCEL); } else { Resume(); }
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc index 553c5d3..40fad386 100644 --- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
@@ -104,7 +104,7 @@ } void SimulateStartAndExpectResult( - content::NavigationThrottle::ThrottleCheckResult expect_result) { + content::NavigationThrottle::ThrottleAction expect_result) { navigation_simulator_->Start(); EXPECT_EQ(expect_result, navigation_simulator_->GetLastThrottleCheckResult()); @@ -112,14 +112,14 @@ void SimulateRedirectAndExpectResult( const GURL& new_url, - content::NavigationThrottle::ThrottleCheckResult expect_result) { + content::NavigationThrottle::ThrottleAction expect_result) { navigation_simulator_->Redirect(new_url); EXPECT_EQ(expect_result, navigation_simulator_->GetLastThrottleCheckResult()); } void SimulateCommitAndExpectResult( - content::NavigationThrottle::ThrottleCheckResult expect_result) { + content::NavigationThrottle::ThrottleAction expect_result) { navigation_simulator_->Commit(); EXPECT_EQ(expect_result, navigation_simulator_->GetLastThrottleCheckResult()); @@ -158,7 +158,7 @@ main_rfh()); SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED); - content::NavigationThrottle::ThrottleCheckResult expected_result = + content::NavigationThrottle::ThrottleAction expected_result = content::IsBrowserSideNavigationEnabled() ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE : content::NavigationThrottle::CANCEL; @@ -174,7 +174,7 @@ SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED); SimulateRedirectAndExpectResult(GURL("https://example.test/allowed2.html"), content::NavigationThrottle::PROCEED); - content::NavigationThrottle::ThrottleCheckResult expected_result = + content::NavigationThrottle::ThrottleAction expected_result = content::IsBrowserSideNavigationEnabled() ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE : content::NavigationThrottle::CANCEL; @@ -219,7 +219,7 @@ if (content::IsBrowserSideNavigationEnabled()) navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME); SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED); - content::NavigationThrottle::ThrottleCheckResult expected_result = + content::NavigationThrottle::ThrottleAction expected_result = content::IsBrowserSideNavigationEnabled() ? content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE : content::NavigationThrottle::CANCEL;
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc index 62c06cb..60d257a 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -119,7 +119,7 @@ SubresourceFilterSafeBrowsingActivationThrottle::WillRedirectRequest() { CheckCurrentUrl(); DCHECK(!database_client_ || !check_results_.empty()); - return content::NavigationThrottle::ThrottleCheckResult::PROCEED; + return PROCEED; } content::NavigationThrottle::ThrottleCheckResult @@ -128,12 +128,12 @@ // No need to defer the navigation if the check already happened. if (!database_client_ || check_results_.back().finished) { NotifyResult(); - return content::NavigationThrottle::ThrottleCheckResult::PROCEED; + return PROCEED; } CHECK(!deferring_); deferring_ = true; defer_time_ = base::TimeTicks::Now(); - return content::NavigationThrottle::ThrottleCheckResult::DEFER; + return DEFER; } const char*
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc index 16bb301..5ee61533 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -255,7 +255,7 @@ auto simulator = content::NavigationSimulator::CreateRendererInitiated( GURL("https://example.test/disallowed.html"), subframe); simulator->Commit(); - return simulator->GetLastThrottleCheckResult() == + return simulator->GetLastThrottleCheckResult().action() == content::NavigationThrottle::PROCEED ? simulator->GetFinalRenderFrameHost() : nullptr; @@ -280,7 +280,7 @@ content::NavigationSimulator::CreateRendererInitiated(first_url, rfh); navigation_simulator_->Start(); auto result = navigation_simulator_->GetLastThrottleCheckResult(); - if (result == content::NavigationThrottle::CANCEL) + if (result.action() == content::NavigationThrottle::CANCEL) navigation_simulator_.reset(); return result; } @@ -289,7 +289,7 @@ const GURL& new_url) { navigation_simulator_->Redirect(new_url); auto result = navigation_simulator_->GetLastThrottleCheckResult(); - if (result == content::NavigationThrottle::CANCEL) + if (result.action() == content::NavigationThrottle::CANCEL) navigation_simulator_.reset(); return result; }
diff --git a/components/viz/common/resources/platform_color.h b/components/viz/common/resources/platform_color.h index 9c0fa1e..5a6caba5 100644 --- a/components/viz/common/resources/platform_color.h +++ b/components/viz/common/resources/platform_color.h
@@ -60,6 +60,7 @@ case RED_8: case LUMINANCE_F16: case RGBA_F16: + case R16_EXT: NOTREACHED(); return false; }
diff --git a/components/viz/common/resources/platform_color_unittest.cc b/components/viz/common/resources/platform_color_unittest.cc index f8012176..feab684 100644 --- a/components/viz/common/resources/platform_color_unittest.cc +++ b/components/viz/common/resources/platform_color_unittest.cc
@@ -33,6 +33,7 @@ case RED_8: case LUMINANCE_F16: case RGBA_F16: + case R16_EXT: break; } }
diff --git a/components/viz/common/resources/resource_format.h b/components/viz/common/resources/resource_format.h index 1e90781..265a064cb 100644 --- a/components/viz/common/resources/resource_format.h +++ b/components/viz/common/resources/resource_format.h
@@ -20,7 +20,8 @@ RED_8, LUMINANCE_F16, RGBA_F16, - RESOURCE_FORMAT_MAX = RGBA_F16, + R16_EXT, + RESOURCE_FORMAT_MAX = R16_EXT, }; } // namespace viz
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc index 4cee8649..161290a 100644 --- a/components/viz/common/resources/resource_format_utils.cc +++ b/components/viz/common/resources/resource_format_utils.cc
@@ -29,6 +29,7 @@ case ETC1: case RED_8: case LUMINANCE_F16: + case R16_EXT: return kN32_SkColorType; case RGBA_F16: return kRGBA_F16_SkColorType; @@ -47,6 +48,7 @@ case RGBA_4444: case RGB_565: case LUMINANCE_F16: + case R16_EXT: return 16; case ALPHA_8: case LUMINANCE_8: @@ -72,6 +74,7 @@ GL_UNSIGNED_BYTE, // RED_8 GL_HALF_FLOAT_OES, // LUMINANCE_F16 GL_HALF_FLOAT_OES, // RGBA_F16 + GL_UNSIGNED_SHORT, // R16_EXT }; static_assert(arraysize(format_gl_data_type) == (RESOURCE_FORMAT_MAX + 1), "format_gl_data_type does not handle all cases."); @@ -92,6 +95,7 @@ GL_RED_EXT, // RED_8 GL_LUMINANCE, // LUMINANCE_F16 GL_RGBA, // RGBA_F16 + GL_R16_EXT, // R16_EXT }; static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1), "format_gl_data_format does not handle all cases."); @@ -123,6 +127,7 @@ GL_LUMINANCE, // RED_8 GL_LUMINANCE, // LUMINANCE_F16 GL_RGBA, // RGBA_F16 + GL_LUMINANCE, // R16_EXT }; static_assert(arraysize(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1), "format_gl_data_format does not handle all cases."); @@ -135,6 +140,8 @@ return gfx::BufferFormat::BGRA_8888; case RED_8: return gfx::BufferFormat::R_8; + case R16_EXT: + return gfx::BufferFormat::R_16; case RGBA_4444: return gfx::BufferFormat::RGBA_4444; case RGBA_8888: @@ -187,6 +194,7 @@ case ETC1: case RED_8: case LUMINANCE_F16: + case R16_EXT: return false; } NOTREACHED();
diff --git a/components/viz/common/resources/resource_settings.h b/components/viz/common/resources/resource_settings.h index 31ab9d0..4ace644 100644 --- a/components/viz/common/resources/resource_settings.h +++ b/components/viz/common/resources/resource_settings.h
@@ -21,6 +21,9 @@ size_t texture_id_allocation_chunk_size = 64; bool use_gpu_memory_buffer_resources = false; + bool high_bit_for_testing = false; + // TODO(riju): Remove after r16 is used without the flag. crbug.com/759456 + bool use_r16_texture = false; BufferToTextureTargetMap buffer_to_texture_target_map; };
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 31a250f..aae0db5 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -328,25 +328,12 @@ MSVC_DISABLE_OPTIMIZE() MSVC_PUSH_DISABLE_WARNING(4748) -NOINLINE void ResetThread_DB() { - volatile int inhibit_comdat = __LINE__; - ALLOW_UNUSED_LOCAL(inhibit_comdat); - BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::DB); -} - NOINLINE void ResetThread_FILE() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::FILE); } -NOINLINE void ResetThread_FILE_USER_BLOCKING() { - volatile int inhibit_comdat = __LINE__; - ALLOW_UNUSED_LOCAL(inhibit_comdat); - BrowserThreadImpl::StopRedirectionOfThreadID( - BrowserThread::FILE_USER_BLOCKING); -} - #if defined(OS_ANDROID) NOINLINE void ResetThread_PROCESS_LAUNCHER( std::unique_ptr<BrowserProcessSubThread> thread) { @@ -362,21 +349,6 @@ } #endif // defined(OS_ANDROID) -#if defined(OS_WIN) -NOINLINE void ResetThread_CACHE( - std::unique_ptr<BrowserProcessSubThread> thread) { - volatile int inhibit_comdat = __LINE__; - ALLOW_UNUSED_LOCAL(inhibit_comdat); - thread.reset(); -} -#else // defined(OS_WIN) -NOINLINE void ResetThread_CACHE() { - volatile int inhibit_comdat = __LINE__; - ALLOW_UNUSED_LOCAL(inhibit_comdat); - BrowserThreadImpl::StopRedirectionOfThreadID(BrowserThread::CACHE); -} -#endif // defined(OS_WIN) - NOINLINE void ResetThread_IO(std::unique_ptr<BrowserProcessSubThread> thread) { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); @@ -1059,18 +1031,6 @@ base::TaskShutdownBehavior::BLOCK_SHUTDOWN}; switch (thread_id) { - case BrowserThread::DB: - TRACE_EVENT_BEGIN1("startup", - "BrowserMainLoop::CreateThreads:start", - "Thread", "BrowserThread::DB"); - non_ui_non_io_task_runner_traits = kUserVisibleTraits; - break; - case BrowserThread::FILE_USER_BLOCKING: - TRACE_EVENT_BEGIN1("startup", - "BrowserMainLoop::CreateThreads:start", - "Thread", "BrowserThread::FILE_USER_BLOCKING"); - non_ui_non_io_task_runner_traits = kUserBlockingTraits; - break; case BrowserThread::FILE: TRACE_EVENT_BEGIN1("startup", "BrowserMainLoop::CreateThreads:start", @@ -1092,23 +1052,6 @@ non_ui_non_io_task_runner_traits = kUserBlockingTraits; #endif // defined(OS_ANDROID) break; - case BrowserThread::CACHE: - TRACE_EVENT_BEGIN1("startup", - "BrowserMainLoop::CreateThreads:start", - "Thread", "BrowserThread::CACHE"); -#if defined(OS_WIN) - // TaskScheduler doesn't support async I/O on Windows as CACHE thread is - // the only user and this use case is going away in - // https://codereview.chromium.org/2216583003/. - // TODO(gavinp): Remove this ifdef (and thus enable redirection of the - // CACHE thread on Windows) once that CL lands. - thread_to_start = &cache_thread_; - options = io_message_loop_options; - options.timer_slack = base::TIMER_SLACK_MAXIMUM; -#else // OS_WIN - non_ui_non_io_task_runner_traits = kUserBlockingTraits; -#endif // OS_WIN - break; case BrowserThread::IO: TRACE_EVENT_BEGIN1("startup", "BrowserMainLoop::CreateThreads:start", @@ -1306,14 +1249,7 @@ // - The PROCESS_LAUNCHER thread must be stopped after IO in case // the IO thread posted a task to terminate a process on the // process launcher thread. - // - // - (Not sure why DB stops last.) switch (thread_id) { - case BrowserThread::DB: { - TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread"); - ResetThread_DB(); - break; - } case BrowserThread::FILE: { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread"); // Clean up state that lives on or uses the FILE thread before it goes @@ -1323,12 +1259,6 @@ ResetThread_FILE(); break; } - case BrowserThread::FILE_USER_BLOCKING: { - TRACE_EVENT0("shutdown", - "BrowserMainLoop::Subsystem:FileUserBlockingThread"); - ResetThread_FILE_USER_BLOCKING(); - break; - } case BrowserThread::PROCESS_LAUNCHER: { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread"); #if defined(OS_ANDROID) @@ -1338,15 +1268,6 @@ #endif // defined(OS_ANDROID) break; } - case BrowserThread::CACHE: { - TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread"); -#if defined(OS_WIN) - ResetThread_CACHE(std::move(cache_thread_)); -#else // defined(OS_WIN) - ResetThread_CACHE(); -#endif // defined(OS_WIN) - break; - } case BrowserThread::IO: { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread"); ResetThread_IO(std::move(io_thread_));
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index d341e72d..fa962f29 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -316,13 +316,6 @@ // On Android, the PROCESS_LAUNCHER thread is handled by Java, // |process_launcher_thread_| is merely a proxy to the real message loop. std::unique_ptr<BrowserProcessSubThread> process_launcher_thread_; -#elif defined(OS_WIN) - // TaskScheduler doesn't support async I/O on Windows as CACHE thread is - // the only user and this use case is going away in - // https://codereview.chromium.org/2216583003/. - // TODO(gavinp): Remove this (and thus enable redirection of the CACHE thread - // on Windows) once that CL lands. - std::unique_ptr<BrowserProcessSubThread> cache_thread_; #endif // Members initialized in |BrowserThreadsStarted()| --------------------------
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc index 8bb84ee..a222c790 100644 --- a/content/browser/browser_thread_impl.cc +++ b/content/browser/browser_thread_impl.cc
@@ -34,11 +34,8 @@ // Friendly names for the well-known threads. static const char* const g_browser_thread_names[BrowserThread::ID_COUNT] = { "", // UI (name assembled in browser_main.cc). - "Chrome_DBThread", // DB "Chrome_FileThread", // FILE - "Chrome_FileUserBlockingThread", // FILE_USER_BLOCKING "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER - "Chrome_CacheThread", // CACHE "Chrome_IOThread", // IO }; @@ -211,11 +208,8 @@ } #endif // DCHECK_IS_ON() - if (identifier_ == BrowserThread::DB || - identifier_ == BrowserThread::FILE || - identifier_ == BrowserThread::FILE_USER_BLOCKING || - identifier_ == BrowserThread::PROCESS_LAUNCHER || - identifier_ == BrowserThread::CACHE) { + if (identifier_ == BrowserThread::FILE || + identifier_ == BrowserThread::PROCESS_LAUNCHER) { // Nesting and task observers are not allowed on redirected threads. base::RunLoop::DisallowNestingOnCurrentThread(); message_loop()->DisallowTaskObservers(); @@ -240,25 +234,12 @@ CHECK_GT(line_number, 0); } -NOINLINE void BrowserThreadImpl::DBThreadRun(base::RunLoop* run_loop) { - volatile int line_number = __LINE__; - Thread::Run(run_loop); - CHECK_GT(line_number, 0); -} - NOINLINE void BrowserThreadImpl::FileThreadRun(base::RunLoop* run_loop) { volatile int line_number = __LINE__; Thread::Run(run_loop); CHECK_GT(line_number, 0); } -NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun( - base::RunLoop* run_loop) { - volatile int line_number = __LINE__; - Thread::Run(run_loop); - CHECK_GT(line_number, 0); -} - NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun( base::RunLoop* run_loop) { volatile int line_number = __LINE__; @@ -266,12 +247,6 @@ CHECK_GT(line_number, 0); } -NOINLINE void BrowserThreadImpl::CacheThreadRun(base::RunLoop* run_loop) { - volatile int line_number = __LINE__; - Thread::Run(run_loop); - CHECK_GT(line_number, 0); -} - NOINLINE void BrowserThreadImpl::IOThreadRun(base::RunLoop* run_loop) { volatile int line_number = __LINE__; Thread::Run(run_loop); @@ -298,16 +273,10 @@ switch (identifier_) { case BrowserThread::UI: return UIThreadRun(run_loop); - case BrowserThread::DB: - return DBThreadRun(run_loop); case BrowserThread::FILE: return FileThreadRun(run_loop); - case BrowserThread::FILE_USER_BLOCKING: - return FileUserBlockingThreadRun(run_loop); case BrowserThread::PROCESS_LAUNCHER: return ProcessLauncherThreadRun(run_loop); - case BrowserThread::CACHE: - return CacheThreadRun(run_loop); case BrowserThread::IO: return IOThreadRun(run_loop); case BrowserThread::ID_COUNT:
diff --git a/content/browser/browser_thread_impl.h b/content/browser/browser_thread_impl.h index 00681000..050fae4e 100644 --- a/content/browser/browser_thread_impl.h +++ b/content/browser/browser_thread_impl.h
@@ -78,11 +78,8 @@ // The following are unique function names that makes it possible to tell // the thread id from the callstack alone in crash dumps. void UIThreadRun(base::RunLoop* run_loop); - void DBThreadRun(base::RunLoop* run_loop); void FileThreadRun(base::RunLoop* run_loop); - void FileUserBlockingThreadRun(base::RunLoop* run_loop); void ProcessLauncherThreadRun(base::RunLoop* run_loop); - void CacheThreadRun(base::RunLoop* run_loop); void IOThreadRun(base::RunLoop* run_loop); static bool PostTaskHelper(BrowserThread::ID identifier,
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 2e3951c..20c97cb 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -566,9 +566,9 @@ NavigationThrottle::ThrottleCheckResult WillProcessResponse() override { if (network_handler_ && network_handler_->ShouldCancelNavigation( navigation_handle()->GetGlobalRequestID())) { - return ThrottleCheckResult::CANCEL_AND_IGNORE; + return CANCEL_AND_IGNORE; } - return ThrottleCheckResult::PROCEED; + return PROCEED; } const char* GetNameForLogging() override {
diff --git a/content/browser/frame_host/form_submission_throttle_browsertest.cc b/content/browser/frame_host/form_submission_throttle_browsertest.cc index b3aec72..5632154 100644 --- a/content/browser/frame_host/form_submission_throttle_browsertest.cc +++ b/content/browser/frame_host/form_submission_throttle_browsertest.cc
@@ -33,8 +33,8 @@ const struct { GURL main_page_url; GURL form_page_url; - NavigationThrottle::ThrottleCheckResult start_expectation; - NavigationThrottle::ThrottleCheckResult redirect_expectation; + NavigationThrottle::ThrottleAction start_expectation; + NavigationThrottle::ThrottleAction redirect_expectation; } kTestCases[] = { // Form submissions is allowed by default when there is no CSP. {
diff --git a/content/browser/frame_host/mixed_content_navigation_throttle.cc b/content/browser/frame_host/mixed_content_navigation_throttle.cc index d0a7466..fd45a48 100644 --- a/content/browser/frame_host/mixed_content_navigation_throttle.cc +++ b/content/browser/frame_host/mixed_content_navigation_throttle.cc
@@ -127,26 +127,27 @@ MixedContentNavigationThrottle::~MixedContentNavigationThrottle() {} -ThrottleCheckResult MixedContentNavigationThrottle::WillStartRequest() { +NavigationThrottle::ThrottleCheckResult +MixedContentNavigationThrottle::WillStartRequest() { bool should_block = ShouldBlockNavigation(false); - return should_block ? ThrottleCheckResult::CANCEL - : ThrottleCheckResult::PROCEED; + return should_block ? CANCEL : PROCEED; } -ThrottleCheckResult MixedContentNavigationThrottle::WillRedirectRequest() { +NavigationThrottle::ThrottleCheckResult +MixedContentNavigationThrottle::WillRedirectRequest() { // Upon redirects the same checks are to be executed as for requests. bool should_block = ShouldBlockNavigation(true); - return should_block ? ThrottleCheckResult::CANCEL - : ThrottleCheckResult::PROCEED; + return should_block ? CANCEL : PROCEED; } -ThrottleCheckResult MixedContentNavigationThrottle::WillProcessResponse() { +NavigationThrottle::ThrottleCheckResult +MixedContentNavigationThrottle::WillProcessResponse() { // TODO(carlosk): At this point we are about to process the request response. // So if we ever need to, here/now it is a good moment to check for the final // attained security level of the connection. For instance, does it use an // outdated protocol? The implementation should be based off // MixedContentChecker::handleCertificateError. See https://crbug.com/576270. - return ThrottleCheckResult::PROCEED; + return PROCEED; } const char* MixedContentNavigationThrottle::GetNameForLogging() {
diff --git a/content/browser/frame_host/mixed_content_navigation_throttle.h b/content/browser/frame_host/mixed_content_navigation_throttle.h index c7ca00f7..7cad03b 100644 --- a/content/browser/frame_host/mixed_content_navigation_throttle.h +++ b/content/browser/frame_host/mixed_content_navigation_throttle.h
@@ -20,8 +20,6 @@ class FrameTreeNode; struct WebPreferences; -using ThrottleCheckResult = NavigationThrottle::ThrottleCheckResult; - // Responsible for browser-process-side mixed content security checks. It is // only enabled if PlzNavigate is and checks only for frame-level resource loads // (aka navigation loads). Sub-resources fetches are checked in the renderer
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index 2e4d0d9..bec56e0 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -588,7 +588,7 @@ // Notify each throttle of the request. base::Closure on_defer_callback_copy = on_defer_callback_for_testing_; NavigationThrottle::ThrottleCheckResult result = CheckWillStartRequest(); - if (result == NavigationThrottle::DEFER) { + if (result.action() == NavigationThrottle::DEFER) { if (!on_defer_callback_copy.is_null()) on_defer_callback_copy.Run(); // DO NOT ADD CODE: the NavigationHandle might have been destroyed during @@ -597,7 +597,7 @@ } TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this, - "StartRequest", "result", result); + "StartRequest", "result", result.action()); RunCompleteCallback(result); } @@ -653,7 +653,7 @@ // Notify each throttle of the request. base::Closure on_defer_callback_copy = on_defer_callback_for_testing_; NavigationThrottle::ThrottleCheckResult result = CheckWillRedirectRequest(); - if (result == NavigationThrottle::DEFER) { + if (result.action() == NavigationThrottle::DEFER) { if (!on_defer_callback_copy.is_null()) on_defer_callback_copy.Run(); // DO NOT ADD CODE: the NavigationHandle might have been destroyed during @@ -662,7 +662,7 @@ } TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this, - "RedirectRequest", "result", result); + "RedirectRequest", "result", result.action()); RunCompleteCallback(result); } @@ -696,7 +696,7 @@ // Notify each throttle of the response. base::Closure on_defer_callback_copy = on_defer_callback_for_testing_; NavigationThrottle::ThrottleCheckResult result = CheckWillProcessResponse(); - if (result == NavigationThrottle::DEFER) { + if (result.action() == NavigationThrottle::DEFER) { if (!on_defer_callback_copy.is_null()) on_defer_callback_copy.Run(); // DO NOT ADD CODE: the NavigationHandle might have been destroyed during @@ -709,11 +709,12 @@ // on its site (after any redirects). // Note: if MaybeTransferAndProceed returns false, this means that this // NavigationHandle was deleted, so return immediately. - if (result == NavigationThrottle::PROCEED && !MaybeTransferAndProceed()) + if (result.action() == NavigationThrottle::PROCEED && + !MaybeTransferAndProceed()) return; TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this, - "ProcessResponse", "result", result); + "ProcessResponse", "result", result.action()); RunCompleteCallback(result); } @@ -867,8 +868,9 @@ TRACE_EVENT_ASYNC_STEP_INTO0( "navigation", "NavigationHandle", this, base::StringPrintf("CheckWillStartRequest: %s: %d", - throttles_[i]->GetNameForLogging(), result)); - switch (result) { + throttles_[i]->GetNameForLogging(), + result.action())); + switch (result.action()) { case NavigationThrottle::PROCEED: continue; @@ -913,8 +915,9 @@ TRACE_EVENT_ASYNC_STEP_INTO0( "navigation", "NavigationHandle", this, base::StringPrintf("CheckWillRedirectRequest: %s: %d", - throttles_[i]->GetNameForLogging(), result)); - switch (result) { + throttles_[i]->GetNameForLogging(), + result.action())); + switch (result.action()) { case NavigationThrottle::PROCEED: continue; @@ -966,8 +969,9 @@ TRACE_EVENT_ASYNC_STEP_INTO0( "navigation", "NavigationHandle", this, base::StringPrintf("CheckWillProcessResponse: %s: %d", - throttles_[i]->GetNameForLogging(), result)); - switch (result) { + throttles_[i]->GetNameForLogging(), + result.action())); + switch (result.action()) { case NavigationThrottle::PROCEED: continue; @@ -1004,7 +1008,7 @@ base::Closure on_defer_callback_copy = on_defer_callback_for_testing_; if (state_ == DEFERRING_START) { result = CheckWillStartRequest(); - if (result == NavigationThrottle::DEFER) { + if (result.action() == NavigationThrottle::DEFER) { if (!on_defer_callback_copy.is_null()) on_defer_callback_copy.Run(); // DO NOT ADD CODE: the NavigationHandle might have been destroyed during @@ -1013,7 +1017,7 @@ } } else if (state_ == DEFERRING_REDIRECT) { result = CheckWillRedirectRequest(); - if (result == NavigationThrottle::DEFER) { + if (result.action() == NavigationThrottle::DEFER) { if (!on_defer_callback_copy.is_null()) on_defer_callback_copy.Run(); // DO NOT ADD CODE: the NavigationHandle might have been destroyed during @@ -1022,7 +1026,7 @@ } } else { result = CheckWillProcessResponse(); - if (result == NavigationThrottle::DEFER) { + if (result.action() == NavigationThrottle::DEFER) { if (!on_defer_callback_copy.is_null()) on_defer_callback_copy.Run(); // DO NOT ADD CODE: the NavigationHandle might have been destroyed during @@ -1036,10 +1040,11 @@ // redirects). // Note: if MaybeTransferAndProceed returns false, this means that this // NavigationHandle was deleted, so return immediately. - if (result == NavigationThrottle::PROCEED && !MaybeTransferAndProceed()) + if (result.action() == NavigationThrottle::PROCEED && + !MaybeTransferAndProceed()) return; } - DCHECK_NE(NavigationThrottle::DEFER, result); + DCHECK_NE(NavigationThrottle::DEFER, result.action()); TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, "Resuming"); @@ -1050,14 +1055,14 @@ NavigationThrottle::ThrottleCheckResult result) { DCHECK(state_ == DEFERRING_START || state_ == DEFERRING_REDIRECT || state_ == DEFERRING_RESPONSE); - DCHECK(result == NavigationThrottle::CANCEL_AND_IGNORE || - result == NavigationThrottle::CANCEL || - result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE); - DCHECK(result != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE || + DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE || + result.action() == NavigationThrottle::CANCEL || + result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE); + DCHECK(result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE || state_ == DEFERRING_START || (state_ == DEFERRING_REDIRECT && IsBrowserSideNavigationEnabled())); - if (result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) + if (result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) frame_tree_node_->SetCollapsed(true); TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, @@ -1155,7 +1160,7 @@ void NavigationHandleImpl::RunCompleteCallback( NavigationThrottle::ThrottleCheckResult result) { - DCHECK(result != NavigationThrottle::DEFER); + DCHECK(result.action() != NavigationThrottle::DEFER); ThrottleChecksFinishedCallback callback = complete_callback_; complete_callback_.Reset();
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc index ab2c3778..448c5e2 100644 --- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -39,9 +39,9 @@ public: TestNavigationThrottle( NavigationHandle* handle, - NavigationThrottle::ThrottleCheckResult will_start_result, - NavigationThrottle::ThrottleCheckResult will_redirect_result, - NavigationThrottle::ThrottleCheckResult will_process_result, + NavigationThrottle::ThrottleAction will_start_result, + NavigationThrottle::ThrottleAction will_redirect_result, + NavigationThrottle::ThrottleAction will_process_result, base::Closure did_call_will_start, base::Closure did_call_will_redirect, base::Closure did_call_will_process) @@ -100,9 +100,9 @@ return will_process_result_; } - NavigationThrottle::ThrottleCheckResult will_start_result_; - NavigationThrottle::ThrottleCheckResult will_redirect_result_; - NavigationThrottle::ThrottleCheckResult will_process_result_; + NavigationThrottle::ThrottleAction will_start_result_; + NavigationThrottle::ThrottleAction will_redirect_result_; + NavigationThrottle::ThrottleAction will_process_result_; base::Closure did_call_will_start_; base::Closure did_call_will_redirect_; base::Closure did_call_will_process_; @@ -117,9 +117,9 @@ public: TestNavigationThrottleInstaller( WebContents* web_contents, - NavigationThrottle::ThrottleCheckResult will_start_result, - NavigationThrottle::ThrottleCheckResult will_redirect_result, - NavigationThrottle::ThrottleCheckResult will_process_result, + NavigationThrottle::ThrottleAction will_start_result, + NavigationThrottle::ThrottleAction will_redirect_result, + NavigationThrottle::ThrottleAction will_process_result, const GURL& expected_start_url = GURL()) : WebContentsObserver(web_contents), will_start_result_(will_start_result), @@ -156,8 +156,8 @@ } void Continue(NavigationThrottle::ThrottleCheckResult result) { - ASSERT_NE(NavigationThrottle::DEFER, result); - if (result == NavigationThrottle::PROCEED) + ASSERT_NE(NavigationThrottle::DEFER, result.action()); + if (result.action() == NavigationThrottle::PROCEED) navigation_throttle()->ResumeNavigation(); else navigation_throttle()->CancelNavigation(result); @@ -215,9 +215,9 @@ navigation_throttle_ = nullptr; } - NavigationThrottle::ThrottleCheckResult will_start_result_; - NavigationThrottle::ThrottleCheckResult will_redirect_result_; - NavigationThrottle::ThrottleCheckResult will_process_result_; + NavigationThrottle::ThrottleAction will_start_result_; + NavigationThrottle::ThrottleAction will_redirect_result_; + NavigationThrottle::ThrottleAction will_process_result_; int will_start_called_ = 0; int will_redirect_called_ = 0; int will_process_called_ = 0; @@ -241,9 +241,9 @@ public: TestDeferringNavigationThrottleInstaller( WebContents* web_contents, - NavigationThrottle::ThrottleCheckResult will_start_result, - NavigationThrottle::ThrottleCheckResult will_redirect_result, - NavigationThrottle::ThrottleCheckResult will_process_result, + NavigationThrottle::ThrottleAction will_start_result, + NavigationThrottle::ThrottleAction will_redirect_result, + NavigationThrottle::ThrottleAction will_process_result, GURL expected_start_url = GURL()) : TestNavigationThrottleInstaller(web_contents, NavigationThrottle::DEFER, @@ -271,9 +271,9 @@ } private: - NavigationThrottle::ThrottleCheckResult will_start_deferred_result_; - NavigationThrottle::ThrottleCheckResult will_redirect_deferred_result_; - NavigationThrottle::ThrottleCheckResult will_process_deferred_result_; + NavigationThrottle::ThrottleAction will_start_deferred_result_; + NavigationThrottle::ThrottleAction will_redirect_deferred_result_; + NavigationThrottle::ThrottleAction will_process_deferred_result_; }; // Records all navigation start URLs from the WebContents. @@ -749,8 +749,8 @@ // Exercise both synchronous and deferred throttle check results, and both on // WillStartRequest and on WillRedirectRequest. const struct { - NavigationThrottle::ThrottleCheckResult will_start_result; - NavigationThrottle::ThrottleCheckResult will_redirect_result; + NavigationThrottle::ThrottleAction will_start_result; + NavigationThrottle::ThrottleAction will_redirect_result; bool deferred_block; } kTestCases[] = { {NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc index 3ffd938..f494483 100644 --- a/content/browser/frame_host/navigation_handle_impl_unittest.cc +++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -9,6 +9,7 @@ #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/request_context_type.h" #include "content/public/common/url_constants.h" +#include "content/public/test/browser_side_navigation_test_utils.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_render_frame_host.h" #include "content/test/test_web_contents.h" @@ -304,7 +305,7 @@ std::vector<std::unique_ptr<NavigationThrottle>> GetThrottles( NavigationHandle* handle) { auto throttle = base::MakeUnique<TestNavigationThrottle>( - handle, NavigationThrottle::ThrottleCheckResult::PROCEED); + handle, NavigationThrottle::PROCEED); std::vector<std::unique_ptr<NavigationThrottle>> vec; throttles_inserted_++; vec.push_back(std::move(throttle)); @@ -864,6 +865,172 @@ EXPECT_EQ(0, proceed_throttle->will_process_response_calls()); } +TEST_F(NavigationHandleImplTest, BlockRequestCustomNetError) { + TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle( + {NavigationThrottle::BLOCK_REQUEST, net::ERR_BLOCKED_BY_ADMINISTRATOR}); + EXPECT_EQ(0, blocked_throttle->will_start_calls()); + EXPECT_EQ(0, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); + + // Simulate WillRedirectRequest. The request should not be deferred. The + // callback should have been called. The second throttle should not have + // been notified. + SimulateWillStartRequest(); + EXPECT_FALSE(IsDeferringStart()); + EXPECT_FALSE(IsDeferringRedirect()); + EXPECT_FALSE(IsDeferringResponse()); + EXPECT_TRUE(was_callback_called()); + EXPECT_TRUE(IsCanceling()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result().action()); + EXPECT_EQ(net::ERR_BLOCKED_BY_ADMINISTRATOR, + callback_result().net_error_code()); + EXPECT_FALSE(callback_result().error_page_content().has_value()); + EXPECT_EQ(1, blocked_throttle->will_start_calls()); + EXPECT_EQ(0, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); +} + +TEST_F(NavigationHandleImplTest, BlockRequestCustomNetErrorAndErrorHTML) { + std::string expected_error_page_content("<html><body>test</body></html>"); + TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle( + {NavigationThrottle::BLOCK_REQUEST, net::ERR_BLOCKED_BY_ADMINISTRATOR, + expected_error_page_content}); + EXPECT_EQ(0, blocked_throttle->will_start_calls()); + EXPECT_EQ(0, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); + + // Simulate WillRedirectRequest. The request should not be deferred. The + // callback should have been called. The second throttle should not have + // been notified. + SimulateWillStartRequest(); + EXPECT_FALSE(IsDeferringStart()); + EXPECT_FALSE(IsDeferringRedirect()); + EXPECT_FALSE(IsDeferringResponse()); + EXPECT_TRUE(was_callback_called()); + EXPECT_TRUE(IsCanceling()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result()); + EXPECT_EQ(net::ERR_BLOCKED_BY_ADMINISTRATOR, + callback_result().net_error_code()); + EXPECT_TRUE(callback_result().error_page_content().has_value()); + EXPECT_EQ(expected_error_page_content, + callback_result().error_page_content().value()); + EXPECT_EQ(1, blocked_throttle->will_start_calls()); + EXPECT_EQ(0, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); +} + +TEST_F(NavigationHandleImplTest, BlockRequestCustomNetErrorInRedirect) { + // BLOCK_REQUEST on redirect requires PlzNavigate. + EnableBrowserSideNavigation(); + TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle( + {NavigationThrottle::BLOCK_REQUEST, net::ERR_FILE_NOT_FOUND}); + EXPECT_EQ(0, blocked_throttle->will_start_calls()); + EXPECT_EQ(0, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); + + // Simulate WillRedirectRequest. The request should not be deferred. The + // callback should have been called. The second throttle should not have + // been notified. + SimulateWillRedirectRequest(); + EXPECT_FALSE(IsDeferringStart()); + EXPECT_FALSE(IsDeferringRedirect()); + EXPECT_FALSE(IsDeferringResponse()); + EXPECT_TRUE(was_callback_called()); + EXPECT_TRUE(IsCanceling()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result().action()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, callback_result().net_error_code()); + EXPECT_FALSE(callback_result().error_page_content().has_value()); + EXPECT_EQ(0, blocked_throttle->will_start_calls()); + EXPECT_EQ(1, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); +} + +TEST_F(NavigationHandleImplTest, + BlockRequestCustomNetErrorAndErrorHTMLInRedirect) { + // BLOCK_REQUEST on redirect requires PlzNavigate. + EnableBrowserSideNavigation(); + std::string expected_error_page_content("<html><body>test</body></html>"); + TestNavigationThrottle* blocked_throttle = CreateTestNavigationThrottle( + {NavigationThrottle::BLOCK_REQUEST, net::ERR_FILE_NOT_FOUND, + expected_error_page_content}); + EXPECT_EQ(0, blocked_throttle->will_start_calls()); + EXPECT_EQ(0, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); + + // Simulate WillRedirectRequest. The request should not be deferred. The + // callback should have been called. The second throttle should not have + // been notified. + SimulateWillRedirectRequest(); + EXPECT_FALSE(IsDeferringStart()); + EXPECT_FALSE(IsDeferringRedirect()); + EXPECT_FALSE(IsDeferringResponse()); + EXPECT_TRUE(was_callback_called()); + EXPECT_TRUE(IsCanceling()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result()); + EXPECT_EQ(NavigationThrottle::BLOCK_REQUEST, callback_result().action()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, callback_result().net_error_code()); + EXPECT_TRUE(callback_result().error_page_content().has_value()); + EXPECT_EQ(expected_error_page_content, + callback_result().error_page_content().value()); + EXPECT_EQ(0, blocked_throttle->will_start_calls()); + EXPECT_EQ(1, blocked_throttle->will_redirect_calls()); + EXPECT_EQ(0, blocked_throttle->will_process_response_calls()); +} + +TEST_F(NavigationHandleImplTest, BlockResponseCustomNetError) { + TestNavigationThrottle* block_throttle = CreateTestNavigationThrottle( + {NavigationThrottle::BLOCK_RESPONSE, net::ERR_FILE_VIRUS_INFECTED}); + EXPECT_EQ(0, block_throttle->will_start_calls()); + EXPECT_EQ(0, block_throttle->will_redirect_calls()); + EXPECT_EQ(0, block_throttle->will_process_response_calls()); + // Simulate WillRedirectRequest. The request should not be deferred. The + // callback should have been called. The second throttle should not have + // been notified. + SimulateWillProcessResponse(); + EXPECT_FALSE(IsDeferringStart()); + EXPECT_FALSE(IsDeferringRedirect()); + EXPECT_FALSE(IsDeferringResponse()); + EXPECT_TRUE(was_callback_called()); + EXPECT_TRUE(IsCanceling()); + EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result()); + EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result().action()); + EXPECT_EQ(net::ERR_FILE_VIRUS_INFECTED, callback_result().net_error_code()); + EXPECT_FALSE(callback_result().error_page_content().has_value()); + EXPECT_EQ(0, block_throttle->will_start_calls()); + EXPECT_EQ(0, block_throttle->will_redirect_calls()); + EXPECT_EQ(1, block_throttle->will_process_response_calls()); +} + +TEST_F(NavigationHandleImplTest, BlockResponseCustomNetErrorAndErrorHTML) { + std::string expected_error_page_content("<html><body>test</body></html>"); + TestNavigationThrottle* block_throttle = CreateTestNavigationThrottle( + {NavigationThrottle::BLOCK_RESPONSE, net::ERR_FILE_VIRUS_INFECTED, + expected_error_page_content}); + EXPECT_EQ(0, block_throttle->will_start_calls()); + EXPECT_EQ(0, block_throttle->will_redirect_calls()); + EXPECT_EQ(0, block_throttle->will_process_response_calls()); + // Simulate WillRedirectRequest. The request should not be deferred. The + // callback should have been called. The second throttle should not have + // been notified. + SimulateWillProcessResponse(); + EXPECT_FALSE(IsDeferringStart()); + EXPECT_FALSE(IsDeferringRedirect()); + EXPECT_FALSE(IsDeferringResponse()); + EXPECT_TRUE(was_callback_called()); + EXPECT_TRUE(IsCanceling()); + EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result()); + EXPECT_EQ(NavigationThrottle::BLOCK_RESPONSE, callback_result().action()); + EXPECT_EQ(net::ERR_FILE_VIRUS_INFECTED, callback_result().net_error_code()); + EXPECT_TRUE(callback_result().error_page_content().has_value()); + EXPECT_EQ(expected_error_page_content, + callback_result().error_page_content().value()); + EXPECT_EQ(0, block_throttle->will_start_calls()); + EXPECT_EQ(0, block_throttle->will_redirect_calls()); + EXPECT_EQ(1, block_throttle->will_process_response_calls()); +} + // Checks that a NavigationHandle can be safely deleted by teh execution of one // of its NavigationThrottle. TEST_F(NavigationHandleImplTest, DeletionByNavigationThrottle) {
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index ccc28ea8..d108ff7 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -825,31 +825,32 @@ void NavigationRequest::OnStartChecksComplete( NavigationThrottle::ThrottleCheckResult result) { - DCHECK(result != NavigationThrottle::DEFER); - DCHECK(result != NavigationThrottle::BLOCK_RESPONSE); + DCHECK(result.action() != NavigationThrottle::DEFER); + DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE); if (on_start_checks_complete_closure_) on_start_checks_complete_closure_.Run(); // Abort the request if needed. This will destroy the NavigationRequest. - if (result == NavigationThrottle::CANCEL_AND_IGNORE || - result == NavigationThrottle::CANCEL || - result == NavigationThrottle::BLOCK_REQUEST || - result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { + if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE || + result.action() == NavigationThrottle::CANCEL || + result.action() == NavigationThrottle::BLOCK_REQUEST || + result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE. - int error_code = net::ERR_ABORTED; - if (result == NavigationThrottle::BLOCK_REQUEST || - result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { - error_code = net::ERR_BLOCKED_BY_CLIENT; - } + DCHECK_EQ((result.action() == NavigationThrottle::CANCEL || + result.action() == NavigationThrottle::CANCEL_AND_IGNORE) + ? net::ERR_ABORTED + : net::ERR_BLOCKED_BY_CLIENT, + result.net_error_code()); // If the start checks completed synchronously, which could happen if there // is no onbeforeunload handler or if a NavigationThrottle cancelled it, // then this could cause reentrancy into NavigationController. So use a // PostTask to avoid that. - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::BindOnce(&NavigationRequest::OnRequestFailed, - weak_factory_.GetWeakPtr(), false, - error_code, base::nullopt, false)); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&NavigationRequest::OnRequestFailed, + weak_factory_.GetWeakPtr(), false, + result.net_error_code(), base::nullopt, false)); // DO NOT ADD CODE after this. The previous call to OnRequestFailed has // destroyed the NavigationRequest. @@ -937,23 +938,25 @@ void NavigationRequest::OnRedirectChecksComplete( NavigationThrottle::ThrottleCheckResult result) { - DCHECK(result != NavigationThrottle::DEFER); - DCHECK(result != NavigationThrottle::BLOCK_RESPONSE); + DCHECK(result.action() != NavigationThrottle::DEFER); + DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE); // Abort the request if needed. This will destroy the NavigationRequest. - if (result == NavigationThrottle::CANCEL_AND_IGNORE || - result == NavigationThrottle::CANCEL) { + if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE || + result.action() == NavigationThrottle::CANCEL) { // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE if needed. - OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false); + DCHECK_EQ(net::ERR_ABORTED, result.net_error_code()); + OnRequestFailed(false, result.net_error_code(), base::nullopt, false); // DO NOT ADD CODE after this. The previous call to OnRequestFailed has // destroyed the NavigationRequest. return; } - if (result == NavigationThrottle::BLOCK_REQUEST || - result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { - OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT, base::nullopt, false); + if (result.action() == NavigationThrottle::BLOCK_REQUEST || + result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { + DCHECK_EQ(net::ERR_BLOCKED_BY_CLIENT, result.net_error_code()); + OnRequestFailed(false, result.net_error_code(), base::nullopt, false); // DO NOT ADD CODE after this. The previous call to OnRequestFailed has // destroyed the NavigationRequest. return; @@ -964,28 +967,34 @@ void NavigationRequest::OnWillProcessResponseChecksComplete( NavigationThrottle::ThrottleCheckResult result) { - DCHECK(result != NavigationThrottle::DEFER); + DCHECK(result.action() != NavigationThrottle::DEFER); // If the NavigationThrottles allowed the navigation to continue, have the // processing of the response resume in the network stack. - if (result == NavigationThrottle::PROCEED) + if (result.action() == NavigationThrottle::PROCEED) loader_->ProceedWithResponse(); // Abort the request if needed. This includes requests that were blocked by // NavigationThrottles and requests that should not commit (e.g. downloads, // 204/205s). This will destroy the NavigationRequest. - if (result == NavigationThrottle::CANCEL_AND_IGNORE || - result == NavigationThrottle::CANCEL || !response_should_be_rendered_) { + if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE || + result.action() == NavigationThrottle::CANCEL || + !response_should_be_rendered_) { + int net_error = result.net_error_code(); + if (!response_should_be_rendered_) + net_error = net::ERR_ABORTED; // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE. - OnRequestFailed(false, net::ERR_ABORTED, base::nullopt, false); + DCHECK_EQ(net::ERR_ABORTED, net_error); + OnRequestFailed(false, net_error, base::nullopt, false); // DO NOT ADD CODE after this. The previous call to OnRequestFailed has // destroyed the NavigationRequest. return; } - if (result == NavigationThrottle::BLOCK_RESPONSE) { - OnRequestFailed(false, net::ERR_BLOCKED_BY_RESPONSE, base::nullopt, false); + if (result.action() == NavigationThrottle::BLOCK_RESPONSE) { + DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code()); + OnRequestFailed(false, result.net_error_code(), base::nullopt, false); // DO NOT ADD CODE after this. The previous call to OnRequestFailed has // destroyed the NavigationRequest. return;
diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc index 5cfee32..825bae6 100644 --- a/content/browser/loader/navigation_resource_throttle.cc +++ b/content/browser/loader/navigation_resource_throttle.cc
@@ -48,7 +48,7 @@ void SendCheckResultToIOThread(UIChecksPerformedCallback callback, NavigationThrottle::ThrottleCheckResult result) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_NE(result, NavigationThrottle::DEFER); + DCHECK_NE(result.action(), NavigationThrottle::DEFER); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::BindOnce(callback, result)); } @@ -344,19 +344,20 @@ void NavigationResourceThrottle::OnUIChecksPerformed( NavigationThrottle::ThrottleCheckResult result) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK_NE(NavigationThrottle::DEFER, result); + DCHECK_NE(NavigationThrottle::DEFER, result.action()); if (in_cross_site_transition_) { on_transfer_done_result_ = result; return; } - if (result == NavigationThrottle::CANCEL_AND_IGNORE || - result == NavigationThrottle::CANCEL) { + if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE || + result.action() == NavigationThrottle::CANCEL) { Cancel(); - } else if (result == NavigationThrottle::BLOCK_REQUEST || - result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { + } else if (result.action() == NavigationThrottle::BLOCK_REQUEST || + result.action() == + NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { CancelWithError(net::ERR_BLOCKED_BY_CLIENT); - } else if (result == NavigationThrottle::BLOCK_RESPONSE) { + } else if (result.action() == NavigationThrottle::BLOCK_RESPONSE) { // TODO(mkwst): If we cancel the main frame request with anything other than // 'net::ERR_ABORTED', we'll trigger some special behavior that might not be // desirable here (non-POSTs will reload the page, while POST has some logic @@ -389,7 +390,7 @@ // If the results of the checks on the UI thread are known, unblock the // navigation. Otherwise, wait until the callback has executed. - if (on_transfer_done_result_ != NavigationThrottle::DEFER) { + if (on_transfer_done_result_.action() != NavigationThrottle::DEFER) { OnUIChecksPerformed(on_transfer_done_result_); on_transfer_done_result_ = NavigationThrottle::DEFER; }
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h index 47bcbfc8..7a27813f 100644 --- a/content/public/browser/browser_thread.h +++ b/content/public/browser/browser_thread.h
@@ -68,9 +68,6 @@ // The main thread in the browser. UI, - // This is the thread that interacts with the database. - DB, - // This is the thread that interacts with the file system. // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes // requiring a background file I/O task runner, i.e.: @@ -81,23 +78,11 @@ // is visible but non-blocking to the user. FILE, - // Used for file system operations that block user interactions. - // Responsiveness of this thread affect users. - // DEPRECATED: prefer base/task_scheduler/post_task.h for new classes - // requiring a user-blocking file I/O task runner, i.e.: - // base::CreateSequencedTaskRunnerWithTraits( - // {base::MayBlock(), base::TaskPriority::USER_BLOCKING}) - FILE_USER_BLOCKING, - // Used to launch and terminate Chrome processes. PROCESS_LAUNCHER, - // This is the thread to handle slow HTTP cache operations. - CACHE, - // This is the thread that processes non-blocking IO, i.e. IPC and network. - // Blocking IO should happen on other threads like DB, FILE, - // FILE_USER_BLOCKING and CACHE depending on the usage. + // Blocking IO should happen in TaskScheduler. IO, // NOTE: do not add new threads here that are only used by a small number of @@ -321,7 +306,6 @@ struct DeleteOnUIThread : public DeleteOnThread<UI> { }; struct DeleteOnIOThread : public DeleteOnThread<IO> { }; struct DeleteOnFileThread : public DeleteOnThread<FILE> { }; - struct DeleteOnDBThread : public DeleteOnThread<DB> { }; // Returns an appropriate error message for when DCHECK_CURRENTLY_ON() fails. static std::string GetDCheckCurrentlyOnErrorMessage(ID expected);
diff --git a/content/public/browser/navigation_throttle.cc b/content/public/browser/navigation_throttle.cc index 0e71b15..5b4e358 100644 --- a/content/public/browser/navigation_throttle.cc +++ b/content/public/browser/navigation_throttle.cc
@@ -8,6 +8,55 @@ namespace content { +namespace { + +net::Error DefaultNetErrorCode(NavigationThrottle::ThrottleAction action) { + switch (action) { + case NavigationThrottle::PROCEED: + case NavigationThrottle::DEFER: + return net::OK; + case NavigationThrottle::CANCEL: + case NavigationThrottle::CANCEL_AND_IGNORE: + return net::ERR_ABORTED; + case NavigationThrottle::BLOCK_REQUEST: + case NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE: + return net::ERR_BLOCKED_BY_CLIENT; + case NavigationThrottle::BLOCK_RESPONSE: + return net::ERR_BLOCKED_BY_RESPONSE; + default: + NOTREACHED(); + return net::ERR_UNEXPECTED; + } +} + +} // namespace + +NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult( + NavigationThrottle::ThrottleAction action) + : NavigationThrottle::ThrottleCheckResult(action, + DefaultNetErrorCode(action), + base::nullopt) {} + +NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult( + NavigationThrottle::ThrottleAction action, + net::Error net_error_code) + : NavigationThrottle::ThrottleCheckResult(action, + net_error_code, + base::nullopt) {} + +NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult( + NavigationThrottle::ThrottleAction action, + net::Error net_error_code, + base::Optional<std::string> error_page_content) + : action_(action), + net_error_code_(net_error_code), + error_page_content_(error_page_content) {} + +NavigationThrottle::ThrottleCheckResult::ThrottleCheckResult( + const ThrottleCheckResult& other) = default; + +NavigationThrottle::ThrottleCheckResult::~ThrottleCheckResult() {} + NavigationThrottle::NavigationThrottle(NavigationHandle* navigation_handle) : navigation_handle_(navigation_handle) {}
diff --git a/content/public/browser/navigation_throttle.h b/content/public/browser/navigation_throttle.h index bfc8062..6a77568 100644 --- a/content/public/browser/navigation_throttle.h +++ b/content/public/browser/navigation_throttle.h
@@ -5,7 +5,9 @@ #ifndef CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_ #define CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_ +#include "base/optional.h" #include "content/common/content_export.h" +#include "net/base/net_errors.h" namespace content { class NavigationHandle; @@ -14,30 +16,30 @@ // UI thread. class CONTENT_EXPORT NavigationThrottle { public: - // This is returned to the NavigationHandle to allow the navigation to - // proceed, or to cancel it. - enum ThrottleCheckResult { + // Represents what a NavigationThrottle can decide to do to a navigation. Note + // that this enum is implicitly convertable to ThrottleCheckResult. + enum ThrottleAction { // The navigation proceeds uninterrupted. PROCEED, // Defers the navigation until the NavigationThrottle calls - // NavigationHandle::Resume or NavigationHandle::CancelDeferredRequest. - // If the NavigationHandle is destroyed while the navigation is deferred, - // the navigation will be canceled in the network stack. + // NavigationHandle::Resume or NavigationHandle::CancelDeferredRequest. If + // the NavigationHandle is destroyed while the navigation is deferred, the + // navigation will be canceled in the network stack. DEFER, // Cancels the navigation. CANCEL, - // Cancels the navigation and makes the requester of the navigation acts + // Cancels the navigation and makes the requester of the navigation act // like the request was never made. CANCEL_AND_IGNORE, // Blocks a navigation due to rules asserted before the request is made. // This can only be returned from WillStartRequest and also from // WillRedirectRequest when PlzNavigate is enabled. This will result in an - // error page for net::ERR_BLOCKED_BY_CLIENT being loaded in the frame that - // is navigated. + // default net_error code of net::ERR_BLOCKED_BY_CLIENT being loaded in + // the frame that is navigated. BLOCK_REQUEST, // Blocks a navigation taking place in a subframe, and collapses the frame @@ -52,6 +54,70 @@ BLOCK_RESPONSE, }; + // ThrottleCheckResult, the return value for NavigationThrottle decision + // methods, is a ThrottleAction value with an attached net::Error and an + // optional attached error page HTML string. + // + // ThrottleCheckResult is implicitly convertible from ThrottleAction, allowing + // the following examples to work: + // + // ThrottleCheckResult WillStartRequest() override { + // // Uses default error for PROCEED (net::OK). + // return PROCEED; + // } + // + // ThrottleCheckResult WillStartRequest() override { + // // Uses default error for BLOCK_REQUEST (net::ERR_BLOCKED_BY_CLIENT). + // return BLOCK_REQUEST; + // } + // + // ThrottleCheckResult WillStartRequest() override { + // // Identical to previous example (net::ERR_BLOCKED_BY_CLIENT) + // return {BLOCK_REQUEST}; + // } + // + // ThrottleCheckResult WillStartRequest() override { + // // Uses a custom error code of ERR_FILE_NOT_FOUND. + // return {BLOCK_REQUEST, net::ERR_FILE_NOT_FOUND}; + // } + // + // ThrottleCheckResult WillStartRequest() override { + // // Uses a custom error code of ERR_FILE_NOT_FOUND and an error page + // string. + // return {BLOCK_REQUEST, + // net::ERR_FILE_NOT_FOUND, + // std::string("<html><body>Could not find.</body></html>")}; + // } + class CONTENT_EXPORT ThrottleCheckResult { + public: + // Construct with just a ThrottleAction, using the default net::Error for + // that action. + ThrottleCheckResult(ThrottleAction action); + + // Construct with an action and error. + ThrottleCheckResult(ThrottleAction action, net::Error net_error_code); + + // Construct with an action, error, and error page HTML. + ThrottleCheckResult(ThrottleAction action, + net::Error net_error_code, + base::Optional<std::string> error_page_content); + + ThrottleCheckResult(const ThrottleCheckResult& other); + + ~ThrottleCheckResult(); + + ThrottleAction action() const { return action_; } + net::Error net_error_code() const { return net_error_code_; } + base::Optional<std::string> error_page_content() { + return error_page_content_; + } + + private: + ThrottleAction action_; + net::Error net_error_code_; + base::Optional<std::string> error_page_content_; + }; + NavigationThrottle(NavigationHandle* navigation_handle); virtual ~NavigationThrottle(); @@ -111,6 +177,21 @@ NavigationHandle* navigation_handle_; }; +#if defined(UNIT_TEST) +// Test-only operator== to enable assertions like: +// EXPECT_EQ(NavigationThrottle::PROCEED, throttle->WillProcessResponse()) +inline bool operator==(NavigationThrottle::ThrottleAction lhs, + const NavigationThrottle::ThrottleCheckResult& rhs) { + return lhs == rhs.action(); +} +// Test-only operator!= to enable assertions like: +// EXPECT_NE(NavigationThrottle::PROCEED, throttle->WillProcessResponse()) +inline bool operator!=(NavigationThrottle::ThrottleAction lhs, + const NavigationThrottle::ThrottleCheckResult& rhs) { + return lhs != rhs.action(); +} +#endif + } // namespace content #endif // CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc index b579847..f2b69ba 100644 --- a/content/public/test/navigation_simulator.cc +++ b/content/public/test/navigation_simulator.cc
@@ -203,7 +203,7 @@ WaitForThrottleChecksComplete(); CHECK_EQ(1, num_did_start_navigation_called_); - if (GetLastThrottleCheckResult() == NavigationThrottle::PROCEED) { + if (GetLastThrottleCheckResult().action() == NavigationThrottle::PROCEED) { CHECK_EQ(1, num_will_start_request_called_); } else { FailFromThrottleCheck(GetLastThrottleCheckResult()); @@ -259,7 +259,7 @@ WaitForThrottleChecksComplete(); - if (GetLastThrottleCheckResult() == NavigationThrottle::PROCEED) { + if (GetLastThrottleCheckResult().action() == NavigationThrottle::PROCEED) { CHECK_EQ(previous_num_will_redirect_request_called + 1, num_will_redirect_request_called_); CHECK_EQ(previous_did_redirect_navigation_called + 1, @@ -330,7 +330,7 @@ IsURLHandledByNetworkStack(navigation_url_))) { WaitForThrottleChecksComplete(); - if (GetLastThrottleCheckResult() != NavigationThrottle::PROCEED) { + if (GetLastThrottleCheckResult().action() != NavigationThrottle::PROCEED) { FailFromThrottleCheck(GetLastThrottleCheckResult()); return; } @@ -849,38 +849,24 @@ void NavigationSimulator::FailFromThrottleCheck( NavigationThrottle::ThrottleCheckResult result) { - DCHECK_NE(result, NavigationThrottle::PROCEED); + DCHECK_NE(NavigationThrottle::PROCEED, result.action()); state_ = FAILED; // Special failure logic only needed for non-PlzNavigate case. if (IsBrowserSideNavigationEnabled()) return; - int error_code = net::OK; - switch (result) { - case NavigationThrottle::PROCEED: - case NavigationThrottle::DEFER: - NOTREACHED(); - break; - case NavigationThrottle::CANCEL: - case NavigationThrottle::CANCEL_AND_IGNORE: - error_code = net::ERR_ABORTED; - break; - case NavigationThrottle::BLOCK_REQUEST: - case NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE: - error_code = net::ERR_BLOCKED_BY_CLIENT; - break; - case NavigationThrottle::BLOCK_RESPONSE: - error_code = net::ERR_BLOCKED_BY_RESPONSE; - break; - }; + DCHECK_NE(NavigationThrottle::DEFER, result.action()); + DCHECK_NE(NavigationThrottle::PROCEED, result.action()); + DCHECK_NE(net::OK, result.net_error_code()); FrameHostMsg_DidFailProvisionalLoadWithError_Params error_params; - error_params.error_code = error_code; + error_params.error_code = result.net_error_code(); error_params.url = navigation_url_; render_frame_host_->OnMessageReceived( FrameHostMsg_DidFailProvisionalLoadWithError( render_frame_host_->GetRoutingID(), error_params)); - bool should_result_in_error_page = error_code != net::ERR_ABORTED; + bool should_result_in_error_page = + result.net_error_code() != net::ERR_ABORTED; if (!should_result_in_error_page) { render_frame_host_->OnMessageReceived( FrameHostMsg_DidStopLoading(render_frame_host_->GetRoutingID()));
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc index 461c80e..864e1b9 100644 --- a/content/public/test/test_browser_thread_bundle.cc +++ b/content/public/test/test_browser_thread_bundle.cc
@@ -45,16 +45,10 @@ base::RunLoop().RunUntilIdle(); io_thread_->Stop(); base::RunLoop().RunUntilIdle(); - cache_thread_->Stop(); - base::RunLoop().RunUntilIdle(); process_launcher_thread_->Stop(); base::RunLoop().RunUntilIdle(); - file_user_blocking_thread_->Stop(); - base::RunLoop().RunUntilIdle(); file_thread_->Stop(); base::RunLoop().RunUntilIdle(); - db_thread_->Stop(); - base::RunLoop().RunUntilIdle(); // This is the point at which we normally shut down the thread pool. So flush // it again in case any shutdown tasks have been posted to the pool from the // threads above. @@ -135,14 +129,6 @@ void TestBrowserThreadBundle::CreateBrowserThreads() { CHECK(!threads_created_); - if (options_ & REAL_DB_THREAD) { - db_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::DB); - db_thread_->Start(); - } else { - db_thread_ = base::MakeUnique<TestBrowserThread>( - BrowserThread::DB, base::MessageLoop::current()); - } - if (options_ & REAL_FILE_THREAD) { file_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::FILE); file_thread_->Start(); @@ -151,12 +137,8 @@ BrowserThread::FILE, base::MessageLoop::current()); } - file_user_blocking_thread_ = base::MakeUnique<TestBrowserThread>( - BrowserThread::FILE_USER_BLOCKING, base::MessageLoop::current()); process_launcher_thread_ = base::MakeUnique<TestBrowserThread>( BrowserThread::PROCESS_LAUNCHER, base::MessageLoop::current()); - cache_thread_ = base::MakeUnique<TestBrowserThread>( - BrowserThread::CACHE, base::MessageLoop::current()); if (options_ & REAL_IO_THREAD) { io_thread_ = base::MakeUnique<TestBrowserThread>(BrowserThread::IO);
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h index 079e339..dd33ee53 100644 --- a/content/public/test/test_browser_thread_bundle.h +++ b/content/public/test/test_browser_thread_bundle.h
@@ -113,10 +113,9 @@ enum Options { DEFAULT = 0, IO_MAINLOOP = 1 << 0, - REAL_DB_THREAD = 1 << 1, - REAL_FILE_THREAD = 1 << 2, - REAL_IO_THREAD = 1 << 3, - DONT_CREATE_BROWSER_THREADS = 1 << 4, + REAL_FILE_THREAD = 1 << 1, + REAL_IO_THREAD = 1 << 2, + DONT_CREATE_BROWSER_THREADS = 1 << 3, }; TestBrowserThreadBundle(); @@ -133,11 +132,8 @@ std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_; std::unique_ptr<TestBrowserThread> ui_thread_; - std::unique_ptr<TestBrowserThread> db_thread_; std::unique_ptr<TestBrowserThread> file_thread_; - std::unique_ptr<TestBrowserThread> file_user_blocking_thread_; std::unique_ptr<TestBrowserThread> process_launcher_thread_; - std::unique_ptr<TestBrowserThread> cache_thread_; std::unique_ptr<TestBrowserThread> io_thread_; int options_;
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 9a176ac3..925475a 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -59,6 +59,7 @@ #include "content/renderer/input/input_handler_manager.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "media/base/media_switches.h" #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" #include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h" #include "third_party/WebKit/public/platform/WebCompositorMutatorClient.h" @@ -350,6 +351,9 @@ bool is_threaded) { cc::LayerTreeSettings settings; + settings.resource_settings.use_r16_texture = + base::FeatureList::IsEnabled(media::kUseR16Texture); + settings.commit_to_active_tree = !is_threaded; settings.is_layer_tree_for_subframe = is_for_subframe;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index da67b9d5..60bba6f 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -6940,11 +6940,14 @@ const WebRect& selection_rect, bool final_status_update) { DCHECK_GE(ordinal, -1); + WebRect converted_rect = selection_rect; + + GetRenderWidget()->ConvertViewportToWindow(&converted_rect); Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, match_count, - selection_rect, + converted_rect, ordinal, final_status_update)); }
diff --git a/extensions/browser/extension_navigation_throttle.cc b/extensions/browser/extension_navigation_throttle.cc index 9f14c4d7f..0154a5ad 100644 --- a/extensions/browser/extension_navigation_throttle.cc +++ b/extensions/browser/extension_navigation_throttle.cc
@@ -191,7 +191,7 @@ content::NavigationThrottle::ThrottleCheckResult ExtensionNavigationThrottle::WillRedirectRequest() { ThrottleCheckResult result = WillStartOrRedirectRequest(); - if (result == BLOCK_REQUEST) { + if (result.action() == BLOCK_REQUEST) { // TODO(nick): https://crbug.com/695421 means that BLOCK_REQUEST does not // work here. Once PlzNavigate is enabled 100%, just return |result|. return CANCEL;
diff --git a/ios/chrome/browser/passwords/credential_manager.h b/ios/chrome/browser/passwords/credential_manager.h index 3b6c288..64dd23e 100644 --- a/ios/chrome/browser/passwords/credential_manager.h +++ b/ios/chrome/browser/passwords/credential_manager.h
@@ -7,6 +7,10 @@ #include "components/password_manager/core/browser/credential_manager_impl.h" +namespace web { +class WebState; +} + namespace credential_manager { // Owned by PasswordController. It is responsible for registering and handling @@ -25,7 +29,8 @@ // website. class CredentialManager { public: - explicit CredentialManager(password_manager::PasswordManagerClient* client); + CredentialManager(password_manager::PasswordManagerClient* client, + web::WebState* web_state); ~CredentialManager(); private: @@ -46,6 +51,7 @@ void SendStoreResponse(int promise_id); password_manager::CredentialManagerImpl impl_; + web::WebState* web_state_; DISALLOW_COPY_AND_ASSIGN(CredentialManager); };
diff --git a/ios/chrome/browser/passwords/credential_manager.mm b/ios/chrome/browser/passwords/credential_manager.mm index 3afea52..ea6baa9 100644 --- a/ios/chrome/browser/passwords/credential_manager.mm +++ b/ios/chrome/browser/passwords/credential_manager.mm
@@ -5,7 +5,10 @@ #import "ios/chrome/browser/passwords/credential_manager.h" #import "base/mac/bind_objc_block.h" +#include "base/strings/utf_string_conversions.h" #include "ios/chrome/browser/passwords/credential_manager_util.h" +#include "ios/chrome/browser/passwords/js_credential_manager.h" +#import "ios/web/public/web_state/web_state.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -18,46 +21,80 @@ namespace credential_manager { +namespace { + +// Script command prefix for CM API calls. Possible commands to be sent from +// injected JS are 'credentials.get', 'credentials.store' and +// 'credentials.preventSilentAccess'. +constexpr char kCommandPrefix[] = "credentials"; + +} // namespace + CredentialManager::CredentialManager( - password_manager::PasswordManagerClient* client) - : impl_(client) { - // TODO(crbug.com/435047): Register a script command callback for prefix - // "credentials" and HandleScriptCommand method. + password_manager::PasswordManagerClient* client, + web::WebState* web_state) + : impl_(client), web_state_(web_state) { + web_state_->AddScriptCommandCallback( + base::Bind(&CredentialManager::HandleScriptCommand, + base::Unretained(this)), + kCommandPrefix); } -CredentialManager::~CredentialManager() {} +CredentialManager::~CredentialManager() { + web_state_->RemoveScriptCommandCallback(kCommandPrefix); +} bool CredentialManager::HandleScriptCommand(const base::DictionaryValue& json, const GURL& origin_url, bool user_is_interacting) { - // TODO(crbug.com/435047): Check if context is secure. - std::string command; - if (!json.GetString("command", &command)) { - DLOG(ERROR) << "RECEIVED BAD json - NO VALID 'command' FIELD"; + double promise_id_double = -1; + // |promiseId| field should be an integer value, but since JavaScript has only + // one type for numbers (64-bit float), all numbers in the messages are sent + // as doubles. + if (!json.GetDouble("promiseId", &promise_id_double)) { + DLOG(ERROR) << "Received bad json - no valid 'promiseId' field"; return false; } + int promise_id = static_cast<int>(promise_id_double); - int promise_id; - if (!json.GetInteger("promiseId", &promise_id)) { - DLOG(ERROR) << "RECEIVED BAD json - NO VALID 'promiseId' FIELD"; + if (!WebStateContentIsSecureHtml(web_state_)) { + RejectPromiseWithInvalidStateError( + web_state_, promise_id, + base::ASCIIToUTF16( + "Credential Manager API called from insecure context")); + return true; + } + + std::string command; + if (!json.GetString("command", &command)) { + DLOG(ERROR) << "Received bad json - no valid 'command' field"; return false; } if (command == "credentials.get") { CredentialMediationRequirement mediation; if (!ParseMediationRequirement(json, &mediation)) { - // TODO(crbug.com/435047): Reject promise with a TypeError. - return false; + RejectPromiseWithTypeError( + web_state_, promise_id, + base::ASCIIToUTF16( + "CredentialRequestOptions: Invalid 'mediation' value.")); + return true; } bool include_passwords; if (!ParseIncludePasswords(json, &include_passwords)) { - // TODO(crbug.com/435047): Reject promise with a TypeError. - return false; + RejectPromiseWithTypeError( + web_state_, promise_id, + base::ASCIIToUTF16( + "CredentialRequestOptions: Invalid 'password' value.")); + return true; } std::vector<GURL> federations; if (!ParseFederations(json, &federations)) { - // TODO(crbug.com/435047): Reject promise with a TypeError. - return false; + RejectPromiseWithTypeError( + web_state_, promise_id, + base::ASCIIToUTF16( + "CredentialRequestOptions: invalid 'providers' value.")); + return true; } impl_.Get(mediation, include_passwords, federations, base::BindOnce(&CredentialManager::SendGetResponse, @@ -67,7 +104,11 @@ if (command == "credentials.store") { CredentialInfo credential; if (!ParseCredentialDictionary(json, &credential)) { - // TODO(crbug.com/435047): Reject promise with a TypeError. + // TODO(crbug.com/435047): Refactor ParseCredentialDictionary method to + // provide more meaningful error message. + RejectPromiseWithTypeError( + web_state_, promise_id, + base::ASCIIToUTF16("Invalid Credential object.")); return false; } impl_.Store(credential, @@ -87,10 +128,39 @@ void CredentialManager::SendGetResponse( int promise_id, CredentialManagerError error, - const base::Optional<CredentialInfo>& info) {} + const base::Optional<CredentialInfo>& info) { + switch (error) { + case CredentialManagerError::SUCCESS: + ResolvePromiseWithCredentialInfo(web_state_, promise_id, info); + break; + case CredentialManagerError::DISABLED: + RejectPromiseWithInvalidStateError( + web_state_, promise_id, + base::ASCIIToUTF16("Credential Manager is disabled.")); + break; + case CredentialManagerError::PENDINGREQUEST: + RejectPromiseWithInvalidStateError( + web_state_, promise_id, + base::ASCIIToUTF16("Pending 'get()' request.")); + break; + case CredentialManagerError::PASSWORDSTOREUNAVAILABLE: + RejectPromiseWithNotSupportedError( + web_state_, promise_id, + base::ASCIIToUTF16("Password store is unavailable.")); + break; + case CredentialManagerError::UNKNOWN: + RejectPromiseWithNotSupportedError( + web_state_, promise_id, + base::ASCIIToUTF16("Unknown error has occurred.")); + } +} -void CredentialManager::SendPreventSilentAccessResponse(int promise_id) {} +void CredentialManager::SendPreventSilentAccessResponse(int promise_id) { + ResolvePromiseWithUndefined(web_state_, promise_id); +} -void CredentialManager::SendStoreResponse(int promise_id) {} +void CredentialManager::SendStoreResponse(int promise_id) { + ResolvePromiseWithUndefined(web_state_, promise_id); +} } // namespace credential_manager
diff --git a/ios/chrome/browser/passwords/credential_manager_unittest.mm b/ios/chrome/browser/passwords/credential_manager_unittest.mm index f3380853..b8022a73 100644 --- a/ios/chrome/browser/passwords/credential_manager_unittest.mm +++ b/ios/chrome/browser/passwords/credential_manager_unittest.mm
@@ -5,20 +5,38 @@ #import "ios/chrome/browser/passwords/credential_manager.h" #include "base/mac/foundation_util.h" +#include "base/strings/utf_string_conversions.h" +#include "components/password_manager/core/browser/password_manager.h" +#include "components/password_manager/core/browser/stub_password_manager_client.h" +#include "components/password_manager/core/browser/test_password_store.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" #include "ios/chrome/browser/passwords/credential_manager_util.h" #include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h" #include "ios/web/public/navigation_item.h" #include "ios/web/public/navigation_manager.h" #include "ios/web/public/ssl_status.h" +#import "ios/web/public/test/web_js_test.h" #include "ios/web/public/test/web_test_with_web_state.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/test/cert_test_util.h" #include "net/test/test_data_directory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/origin.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +using password_manager::PasswordStore; +using password_manager::PasswordManager; +using password_manager::PasswordFormManager; +using password_manager::TestPasswordStore; +using testing::_; +using url::Origin; + namespace credential_manager { namespace { @@ -39,14 +57,109 @@ // SSL certificate to load for testing. constexpr char kCertFileName[] = "ok_cert.pem"; +// Mocks PasswordManagerClient, used indirectly by CredentialManager. +class MockPasswordManagerClient + : public password_manager::StubPasswordManagerClient { + public: + MockPasswordManagerClient() + : last_committed_url_(kHttpsWebOrigin), password_manager_(this) { + store_ = base::MakeRefCounted<TestPasswordStore>(); + store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr); + prefs_.registry()->RegisterBooleanPref( + password_manager::prefs::kCredentialsEnableAutosignin, true); + prefs_.registry()->RegisterBooleanPref( + password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, true); + } + + // PasswordManagerClient: + MOCK_METHOD0(OnCredentialManagerUsed, bool()); + + // PromptUserTo*Ptr functions allow to both override PromptUserTo* methods + // and expect calls. + MOCK_METHOD1(PromptUserToSavePasswordPtr, void(PasswordFormManager*)); + MOCK_METHOD3(PromptUserToChooseCredentialsPtr, + bool(const std::vector<autofill::PasswordForm*>& local_forms, + const GURL& origin, + const CredentialsCallback& callback)); + + scoped_refptr<TestPasswordStore> password_store() const { return store_; } + void set_password_store(scoped_refptr<TestPasswordStore> store) { + store_ = store; + } + + PasswordFormManager* pending_manager() const { return manager_.get(); } + + void set_current_url(const GURL& current_url) { + last_committed_url_ = current_url; + } + + private: + // PasswordManagerClient: + PrefService* GetPrefs() override { return &prefs_; } + PasswordStore* GetPasswordStore() const override { return store_.get(); } + const PasswordManager* GetPasswordManager() const override { + return &password_manager_; + } + const GURL& GetLastCommittedEntryURL() const override { + return last_committed_url_; + } + // Stores |manager| into |manager_|. Save() should be + // called manually in test. To put expectation on this function being called, + // use PromptUserToSavePasswordPtr. + bool PromptUserToSaveOrUpdatePassword( + std::unique_ptr<PasswordFormManager> manager, + bool update_password) override; + // Mocks choosing a credential by the user. To put expectation on this + // function being called, use PromptUserToChooseCredentialsPtr. + bool PromptUserToChooseCredentials( + std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms, + const GURL& origin, + const CredentialsCallback& callback) override; + + TestingPrefServiceSimple prefs_; + GURL last_committed_url_; + PasswordManager password_manager_; + std::unique_ptr<PasswordFormManager> manager_; + scoped_refptr<TestPasswordStore> store_; + + DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerClient); +}; + +bool MockPasswordManagerClient::PromptUserToSaveOrUpdatePassword( + std::unique_ptr<PasswordFormManager> manager, + bool update_password) { + EXPECT_FALSE(update_password); + manager_.swap(manager); + PromptUserToSavePasswordPtr(manager_.get()); + return true; +} + +bool MockPasswordManagerClient::PromptUserToChooseCredentials( + std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms, + const GURL& origin, + const CredentialsCallback& callback) { + EXPECT_FALSE(local_forms.empty()); + const autofill::PasswordForm* form = local_forms[0].get(); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(callback, base::Owned(new autofill::PasswordForm(*form)))); + std::vector<autofill::PasswordForm*> raw_forms(local_forms.size()); + std::transform(local_forms.begin(), local_forms.end(), raw_forms.begin(), + [](const std::unique_ptr<autofill::PasswordForm>& form) { + return form.get(); + }); + PromptUserToChooseCredentialsPtr(raw_forms, origin, callback); + return true; +} + } // namespace -// TODO(crbug.com/435048): once JSCredentialManager is implemented and used -// from CredentialManager methods, mock it and write unit tests for -// CredentialManager methods SendGetResponse, SendStoreResponse and -// SendPreventSilentAccessResponse. -class CredentialManagerTest : public web::WebTestWithWebState { +class CredentialManagerBaseTest + : public web::WebJsTest<web::WebTestWithWebState> { public: + CredentialManagerBaseTest() + : web::WebJsTest<web::WebTestWithWebState>(@[ @"credential_manager" ]) {} + void SetUp() override { WebTestWithWebState::SetUp(); @@ -74,7 +187,559 @@ } }; -class WebStateContentIsSecureHtmlTest : public CredentialManagerTest {}; +// Tests CredentialManager class. Tests are performed as follows: +// 1. CredentialManager is instantiated. In its constructor it registers a +// script command callback for 'credentials' prefix. +// 2. credential_manager.js is injected to the web page. +// 3. JavaScript code invoking one of exposed API methods is executed. +// 4. This results in CredentialManager::HandleScriptCommand being called. +// 5. Wait for background tasks to finish, optionally for returned Promise to be +// resolved or rejected. +// 6. Check values in JavaScript, stored in variables under 'test_*' prefix by +// resolver/rejecter functions. +// 7. Optionally expect PasswordManagerClient methods to be (not) called. +class CredentialManagerTest : public CredentialManagerBaseTest { + public: + void SetUp() override { + CredentialManagerBaseTest::SetUp(); + + client_ = base::MakeUnique<MockPasswordManagerClient>(); + manager_ = base::MakeUnique<CredentialManager>(client_.get(), web_state()); + + // Inject JavaScript and set up secure context. + LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin)); + LoadHtmlAndInject(@"<html></html>"); + UpdateSslStatus(net::CERT_STATUS_IS_EV, web::SECURITY_STYLE_AUTHENTICATED, + web::SSLStatus::NORMAL_CONTENT); + + ON_CALL(*client_, OnCredentialManagerUsed()) + .WillByDefault(testing::Return(true)); + + password_credential_form_1_.username_value = base::ASCIIToUTF16("id1"); + password_credential_form_1_.display_name = base::ASCIIToUTF16("Name One"); + password_credential_form_1_.icon_url = GURL("https://example.com/icon.png"); + password_credential_form_1_.password_value = base::ASCIIToUTF16("secret1"); + password_credential_form_1_.origin = GURL(kHttpsWebOrigin); + password_credential_form_1_.signon_realm = kHttpsWebOrigin; + password_credential_form_1_.scheme = autofill::PasswordForm::SCHEME_HTML; + + password_credential_form_2_.username_value = base::ASCIIToUTF16("id2"); + password_credential_form_2_.display_name = base::ASCIIToUTF16("Name Two"); + password_credential_form_2_.icon_url = GURL("https://example.com/icon.png"); + password_credential_form_2_.password_value = base::ASCIIToUTF16("secret2"); + password_credential_form_2_.origin = GURL(kHttpsWebOrigin); + password_credential_form_2_.signon_realm = kHttpsWebOrigin; + password_credential_form_2_.scheme = autofill::PasswordForm::SCHEME_HTML; + + federated_credential_form_.username_value = base::ASCIIToUTF16("id"); + federated_credential_form_.display_name = base::ASCIIToUTF16("name"); + federated_credential_form_.icon_url = + GURL("https://federation.com/icon.png"); + federated_credential_form_.federation_origin = + Origin(GURL("https://federation.com")); + federated_credential_form_.origin = GURL(kHttpsWebOrigin); + federated_credential_form_.signon_realm = + "federation://www.example.com/www.federation.com"; + federated_credential_form_.scheme = autofill::PasswordForm::SCHEME_HTML; + } + + void TearDown() override { + manager_.reset(); + + // Shutdown PasswordStore. + if (client_->password_store()) { + client_->password_store()->ShutdownOnUIThread(); + } + + CredentialManagerBaseTest::TearDown(); + } + + protected: + std::unique_ptr<MockPasswordManagerClient> client_; + std::unique_ptr<CredentialManager> manager_; + + autofill::PasswordForm password_credential_form_1_; + autofill::PasswordForm password_credential_form_2_; + autofill::PasswordForm federated_credential_form_; +}; + +// Tests storing a PasswordCredential. +TEST_F(CredentialManagerTest, StorePasswordCredential) { + // Call API method |store|. + ExecuteJavaScript( + @"var credential = new PasswordCredential({" + " id: 'id'," + " password: 'pencil'," + " name: 'name'," + " iconURL: 'https://example.com/icon.png'" + "});" + "navigator.credentials.store(credential).then(function(result) {" + " test_result_ = (result == undefined);" + " test_promise_resolved_ = true;" + "});"); + + // Wait for the Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Check that Promise was resolved with undefined. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_")); + + // Wait for credential to be stored. + WaitForBackgroundTasks(); + client_->pending_manager()->Save(); + WaitForBackgroundTasks(); + EXPECT_FALSE(client_->password_store()->IsEmpty()); + + // Get the stored credential and check its fields. + TestPasswordStore::PasswordMap passwords = + client_->password_store()->stored_passwords(); + EXPECT_EQ(1u, passwords.size()); + EXPECT_EQ(1u, passwords[kHttpsWebOrigin].size()); + autofill::PasswordForm form = passwords[kHttpsWebOrigin][0]; + EXPECT_EQ(base::ASCIIToUTF16("id"), form.username_value); + EXPECT_EQ(base::ASCIIToUTF16("name"), form.display_name); + EXPECT_EQ(base::ASCIIToUTF16("pencil"), form.password_value); + EXPECT_EQ(GURL("https://example.com/icon.png"), form.icon_url); + EXPECT_EQ(GURL(kHttpsWebOrigin), form.origin); + EXPECT_EQ(GURL(kHttpsWebOrigin), form.signon_realm); +} + +// Tests storing a FederatedCredential. +TEST_F(CredentialManagerTest, StoreFederatedCredential) { + // Call API method |store|. + ExecuteJavaScript( + @"var credential = new FederatedCredential({" + " id: 'id'," + " provider: 'https://www.federation.com/'," + " name: 'name'," + " iconURL: 'https://federation.com/icon.png'" + "});" + "navigator.credentials.store(credential).then(function(result) {" + " test_result_ = (result == undefined);" + " test_promise_resolved_ = true;" + "});"); + + // Wait for the Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Check that Promise was resolved with undefined. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_")); + + // Wait for credential to be stored. + WaitForBackgroundTasks(); + client_->pending_manager()->Save(); + WaitForBackgroundTasks(); + EXPECT_FALSE(client_->password_store()->IsEmpty()); + + // Get the stored credential and check its fields. + TestPasswordStore::PasswordMap passwords = + client_->password_store()->stored_passwords(); + EXPECT_EQ(1u, passwords.size()); + std::string federated_origin = + "federation://www.example.com/www.federation.com"; + EXPECT_EQ(1u, passwords[federated_origin].size()); + autofill::PasswordForm form = passwords[federated_origin][0]; + EXPECT_EQ(base::ASCIIToUTF16("id"), form.username_value); + EXPECT_EQ(base::ASCIIToUTF16("name"), form.display_name); + EXPECT_EQ(Origin(GURL("https://www.federation.com")), form.federation_origin); + EXPECT_EQ(GURL("https://federation.com/icon.png"), form.icon_url); + EXPECT_EQ(GURL("https://www.example.com"), form.origin); + EXPECT_EQ(federated_origin, form.signon_realm); +} + +// Tests that storing a credential from insecure context will not happen. +TEST_F(CredentialManagerTest, TryToStoreCredentialFromInsecureContext) { + // Inject JavaScript, set up WebState to have mixed content. + LoadHtml(@"<html></html>", GURL(kHttpsWebOrigin)); + LoadHtmlAndInject(@"<html></html>"); + UpdateSslStatus(net::CERT_STATUS_IS_EV, web::SECURITY_STYLE_AUTHENTICATED, + web::SSLStatus::DISPLAYED_INSECURE_CONTENT); + + // Expect that user will NOT be prompted to save or update password. + EXPECT_CALL(*client_, PromptUserToSavePasswordPtr(_)).Times(0); + + // Expect that PasswordManagerClient method used by + // CredentialManagerImpl::Store will not be called. + EXPECT_CALL(*client_, OnCredentialManagerUsed()).Times(0); + + // Call API method |store|. + ExecuteJavaScript( + @"var credential = new PasswordCredential({" + " id: 'id'," + " password: 'pencil'," + " name: 'name'," + " iconURL: 'https://example.com/icon.png'" + "});" + "navigator.credentials.store(credential).catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof DOMException && " + " reason.name == DOMException.INVALID_STATE_ERR);" + " test_promise_rejected_ = true;" + "});"); + WaitForBackgroundTasks(); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + // Check that Promise was rejected with InvalidStateError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); +} + +// Tests that Promise will be rejected with TypeError for invalid Credential. +TEST_F(CredentialManagerTest, RejectOnInvalidCredential) { + // Call |store| with invalid Credential: |iconURL| is not a valid URL. + ExecuteJavaScript( + @"var credential = new PasswordCredential({" + " id: 'id'," + " password: 'pencil'," + " name: 'name'," + " iconURL: 'https://'" + "});" + "navigator.credentials.store(credential).catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof TypeError);" + " test_promise_rejected_ = true;" + "});"); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + + // Check that Promise was rejected with TypeError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); +} + +// Tests retrieving a PasswordCredential. +TEST_F(CredentialManagerTest, GetPasswordCredential) { + // Manually store a PasswordForm in password store. + client_->password_store()->AddLogin(password_credential_form_1_); + + // Call API method |get|. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true," + " mediation: 'silent'" + "}).then(function(credential) {" + " test_credential_ = credential; " + " test_promise_resolved_ = true;" + "})"); + + // Wait for PasswordCredential to be obtained and for Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Check PasswordCredential fields. + ASSERT_NSEQ(@"password", ExecuteJavaScript(@"test_credential_.type")); + ASSERT_NSEQ(@"id1", ExecuteJavaScript(@"test_credential_.id")); + ASSERT_NSEQ(@"Name One", ExecuteJavaScript(@"test_credential_.name")); + ASSERT_NSEQ(@"secret1", ExecuteJavaScript(@"test_credential_.password")); + ASSERT_NSEQ(@"https://example.com/icon.png", + ExecuteJavaScript(@"test_credential_.iconURL")); +} + +// Tests retrieving a FederatedCredential. +TEST_F(CredentialManagerTest, GetFederatedCredential) { + // Manually store a PasswordForm in password store. + client_->password_store()->AddLogin(federated_credential_form_); + + // Call API method |get|. + ExecuteJavaScript( + @"navigator.credentials.get({" + " providers: ['https://federation.com'], " + " mediation: 'silent'" + "}).then(function(credential) {" + " test_credential_ = credential;" + " test_promise_resolved_ = true;" + "})"); + + // Wait for FederatedCredential to be obtained and for Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Check FederatedCredential fields. + ASSERT_NSEQ(@"federated", ExecuteJavaScript(@"test_credential_.type")); + ASSERT_NSEQ(@"id", ExecuteJavaScript(@"test_credential_.id")); + ASSERT_NSEQ(@"name", ExecuteJavaScript(@"test_credential_.name")); + ASSERT_NSEQ(@"https://federation.com", + ExecuteJavaScript(@"test_credential_.provider")); + ASSERT_NSEQ(@"https://federation.com/icon.png", + ExecuteJavaScript(@"test_credential_.iconURL")); +} + +// Tests that requesting a credential from insecure context will not happen. +TEST_F(CredentialManagerTest, TryToGetCredentialFromInsecureContext) { + // Set up WebState to have non-cryptographic scheme. + LoadHtml(@"<html></html>", GURL(kHttpWebOrigin)); + LoadHtmlAndInject(@"<html></html>"); + client_->set_current_url(GURL(kHttpWebOrigin)); + + // Expect that PasswordManagerClient method used by + // CredentialManagerImpl::Get will not be called. + EXPECT_CALL(*client_, OnCredentialManagerUsed()).Times(0); + + // Call API method |get|. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true," + " mediation: 'required'" + "}).catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof DOMException && " + " reason.name == DOMException.INVALID_STATE_ERR);" + " test_promise_rejected_ = true;" + "});"); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + // Check that Promise was rejected with InvalidStateError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); +} + +// Tests that when Credential is requested with required mediation, a prompt to +// choose credential will be shown to the user. +TEST_F(CredentialManagerTest, GetCredentialWithRequiredMediation) { + // Manually store a PasswordForm in password store. + client_->password_store()->AddLogin(password_credential_form_1_); + + // Expect that user will be prompted to choose credentials. + EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)); + + // Call API method |get|. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true," + " mediation: 'required'" + "}).then(function(credential) {" + " test_credential_ = credential; " + " test_promise_resolved_ = true;" + "})"); + // Wait for Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Expect that returned Credential is not null. + EXPECT_NSEQ(@"object", ExecuteJavaScript(@"typeof test_credential_")); +} + +// Tests that Promise returned by |navigator.credentials.get| will resolve with +// |null| if PasswordStore is empty. +TEST_F(CredentialManagerTest, NullCredentialFromEmptyPasswordStore) { + // Call API method |get|. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true," + " mediation: 'silent'" + "}).then(function(credential) {" + " test_credential_ = credential; " + " test_promise_resolved_ = true;" + "})"); + // Wait for Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Expect that returned Credential is null. + EXPECT_NSEQ(NULL, ExecuteJavaScript(@"test_credential_")); +} + +// Tests that if multiple credentials are stored for a website and mediation +// requirement is set to 'optional', user will be prompted to choose +// credentials. +TEST_F(CredentialManagerTest, PromptUserOnMultipleCredentials) { + // Manually store two PasswordForms in password store. + client_->password_store()->AddLogin(password_credential_form_1_); + client_->password_store()->AddLogin(password_credential_form_2_); + + // Expect that user will be prompted to choose credentials. + EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _)); + + // Call API method |get|. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true, " + " mediation: 'optional'" + "}).then(function(credential) {" + " test_credential_ = credential;" + " test_promise_resolved_ = true;" + "})"); + // Wait for Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Expect that returned Credential is not null. + EXPECT_NSEQ(@"object", ExecuteJavaScript(@"typeof test_credential_")); +} + +// Tests that Promise returned by |navigator.credentials.get| is rejected with +// TypeError if |mediation| value is invalid. +TEST_F(CredentialManagerTest, RejectOnInvalidMediationValue) { + // Call API method |get| with invalid |mediation| field. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true," + " mediation: 'maybe'" + "}).catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof TypeError);" + " test_promise_rejected_ = true;" + "})"); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + // Check that Promise was rejected with TypeError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); +} + +// Tests that Promise returned by |navigator.credentials.get| is rejected with +// TypeError if |providers| value is invalid. +TEST_F(CredentialManagerTest, RejectOnInvalidProvidersValue) { + // Call API method |get| with invalid |providers| field. + ExecuteJavaScript( + @"navigator.credentials.get({" + " providers: 'https://exampleprovider.com' /* not a list */" + "}).catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof TypeError);" + " test_promise_rejected_ = true;" + "})"); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + // Check that Promise was rejected with TypeError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); +} + +// Tests that Promise returned by |navigator.credentials.get| is rejected with +// NotSupportedError if password store is not available. +TEST_F(CredentialManagerTest, RejectOnPasswordStoreUnavailable) { + // Make password store unavailable. + client_->password_store()->ShutdownOnUIThread(); + client_->set_password_store(nullptr); + + // Call API method |get| with correct arguments, set up rejecter to store + // reason for failure in |test_*| variables. + ExecuteJavaScript( + @"navigator.credentials.get({" + " password: true," + "}).catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof DOMException) && " + " (reason.name == DOMException.NOT_SUPPORTED_ERR);" + " test_result_message_ = reason.message;" + " test_promise_rejected_ = true;" + "})"); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + + // Check that Promise was rejected with NotSupportedError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); + + // Check that Promise message says "Password store is unavailable." + EXPECT_NSEQ(@"Password store is unavailable.", + ExecuteJavaScript(@"test_result_message_")); +} + +// Test that calling |preventSilentAccess| from insecure context will not reach +// CredentialManagerImpl::PreventSilentAccess. +TEST_F(CredentialManagerTest, TryToPreventSilentAccessFromInsecureContext) { + // Inject JavaScript, set up WebState to have non-cryptographic scheme. + LoadHtml(@"<html></html>", GURL(kHttpWebOrigin)); + LoadHtmlAndInject(@"<html></html>"); + client_->set_current_url(GURL(kHttpWebOrigin)); + + // Manually store a PasswordForm in password store. + client_->password_store()->AddLogin(password_credential_form_1_); + + // Call API method |preventSilentAccess|. + ExecuteJavaScript( + @"navigator.credentials.preventSilentAccess().catch(function(reason) {" + " test_result_valid_type_ = (reason instanceof DOMException && " + " reason.name == DOMException.INVALID_STATE_ERR);" + " test_promise_rejected_ = true;" + "});"); + + // Wait for Promise to be rejected. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_rejected_") isEqual:@YES]); + }); + // Check that Promise was rejected with InvalidStateError. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_valid_type_")); + + // Check that credential in password store was not affected by the call. + WaitForBackgroundTasks(); + TestPasswordStore::PasswordMap passwords = + client_->password_store()->stored_passwords(); + EXPECT_EQ(1u, passwords.size()); + ASSERT_EQ(1u, passwords[kHttpsWebOrigin].size()); + autofill::PasswordForm form = passwords[kHttpsWebOrigin][0]; + EXPECT_EQ(false, form.skip_zero_click); +} + +// Tests that after |navigator.credentials.preventSilentAccess| is called, user +// will be prompted to choose credentials. +TEST_F(CredentialManagerTest, PreventSilentAccess) { + // Manually store two PasswordForms in password store. + password_credential_form_1_.skip_zero_click = false; + password_credential_form_2_.skip_zero_click = false; + client_->password_store()->AddLogin(password_credential_form_1_); + client_->password_store()->AddLogin(password_credential_form_2_); + + // Call API method |preventSilentAccess|. + ExecuteJavaScript( + @"navigator.credentials.preventSilentAccess()" + ".then(function(result) {" + " test_result_ = (result == undefined);" + " test_promise_resolved_ = true;" + "});"); + + // Wait for Promise to be resolved. + WaitForCondition(^{ + return static_cast<bool>( + [ExecuteJavaScript(@"test_promise_resolved_") isEqual:@YES]); + }); + + // Check that Promise was resolved with |undefined|. + EXPECT_NSEQ(@YES, ExecuteJavaScript(@"test_result_")); + + // Check that |preventSilentAccess| set a |skip_zero_click| flag on stored + // credential. + WaitForBackgroundTasks(); + TestPasswordStore::PasswordMap passwords = + client_->password_store()->stored_passwords(); + std::vector<autofill::PasswordForm> forms = passwords[kHttpsWebOrigin]; + ASSERT_EQ(2u, forms.size()); + EXPECT_TRUE(forms[0].skip_zero_click); + EXPECT_TRUE(forms[1].skip_zero_click); +} + +class WebStateContentIsSecureHtmlTest : public CredentialManagerBaseTest {}; // Tests that HTTPS websites with valid SSL certificate are recognized as // secure.
diff --git a/ios/chrome/browser/passwords/credential_manager_util.mm b/ios/chrome/browser/passwords/credential_manager_util.mm index a4e0f3c..32f283c 100644 --- a/ios/chrome/browser/passwords/credential_manager_util.mm +++ b/ios/chrome/browser/passwords/credential_manager_util.mm
@@ -40,20 +40,20 @@ } // namespace -const char kCredentialIdKey[] = "id"; -const char kCredentialTypeKey[] = "type"; -const char kCredentialNameKey[] = "name"; -const char kCredentialIconKey[] = "iconURL"; -const char kPasswordCredentialPasswordKey[] = "password"; -const char kFederatedCredentialProviderKey[] = "provider"; +const char kCredentialIdKey[] = "_id"; +const char kCredentialTypeKey[] = "_type"; +const char kCredentialNameKey[] = "_name"; +const char kCredentialIconKey[] = "_iconURL"; +const char kPasswordCredentialPasswordKey[] = "_password"; +const char kFederatedCredentialProviderKey[] = "_provider"; const char kCredentialRequestMediationKey[] = "mediation"; const char kCredentialRequestPasswordKey[] = "password"; const char kCredentialRequestProvidersKey[] = "providers"; const char kMediationRequirementSilent[] = "silent"; const char kMediationRequirementRequired[] = "required"; const char kMediationRequirementOptional[] = "optional"; -const char kCredentialTypePassword[] = "PasswordCredential"; -const char kCredentialTypeFederated[] = "FederatedCredential"; +const char kCredentialTypePassword[] = "password"; +const char kCredentialTypeFederated[] = "federated"; bool ParseMediationRequirement(const base::DictionaryValue& json, CredentialMediationRequirement* mediation) {
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h index 8323e9c1c..24c4a5f 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
@@ -31,6 +31,8 @@ @property(readonly, nonatomic) ios::ChromeBrowserState* browserState; +@property(readonly) password_manager::PasswordManager* passwordManager; + @property(readonly, nonatomic) const GURL& lastCommittedURL; @end @@ -62,6 +64,7 @@ std::unique_ptr<password_manager::PasswordFormManager> saved_form_manager) override; bool IsIncognito() const override; + const password_manager::PasswordManager* GetPasswordManager() const override; PrefService* GetPrefs() override; password_manager::PasswordStore* GetPasswordStore() const override; void NotifyUserAutoSignin(
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm index a7860bd1..42629d4 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
@@ -111,6 +111,11 @@ return (delegate_.browserState)->IsOffTheRecord(); } +const password_manager::PasswordManager* +IOSChromePasswordManagerClient::GetPasswordManager() const { + return delegate_.passwordManager; +} + PrefService* IOSChromePasswordManagerClient::GetPrefs() { return (delegate_.browserState)->GetPrefs(); }
diff --git a/ios/chrome/browser/passwords/js_credential_manager.mm b/ios/chrome/browser/passwords/js_credential_manager.mm index 9d2c77ee..1ff332f 100644 --- a/ios/chrome/browser/passwords/js_credential_manager.mm +++ b/ios/chrome/browser/passwords/js_credential_manager.mm
@@ -40,7 +40,7 @@ base::GetQuotedJSONString(info.icon.spec()).c_str(), base::GetQuotedJSONString(info.password).c_str()); } - NOTREACHED() << "Invalid CredentialType"; + /* if (info.type == CREDENTIAL_TYPE_EMPTY) */ return std::string(); }
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index 49ac664..e27eec0 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -66,9 +66,6 @@ // This is set to YES as soon as the associated WebState is destroyed. @property(readonly) BOOL isWebStateDestroyed; -// Accessor for property inside block. -@property(readonly) PasswordManager* passwordManager; - @end @interface PasswordController ()<FormSuggestionProvider, PasswordFormFiller>
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm index c8065af..1727942 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm
@@ -19,6 +19,7 @@ #import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h" #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h" #include "ios/chrome/grit/ios_strings.h" +#import "ios/third_party/material_components_ios/src/components/AppBar/src/MaterialAppBar.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -45,7 +46,8 @@ @interface ReadingListCollectionViewController ()< ReadingListCollectionViewItemAccessibilityDelegate, - ReadingListDataSink> { + ReadingListDataSink, + UIGestureRecognizerDelegate> { // Toolbar with the actions. ReadingListToolbar* _toolbar; // Action sheet presenting the subactions of the toolbar. @@ -199,7 +201,7 @@ [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; - longPressRecognizer.numberOfTouchesRequired = 1; + longPressRecognizer.delegate = self; [self.collectionView addGestureRecognizer:longPressRecognizer]; } @@ -224,7 +226,7 @@ [super collectionView:collectionView didDeselectItemAtIndexPath:indexPath]; if (self.editor.editing) { // When deselecting an item, if we are editing, we want to update the - // toolbar base on the selected items. + // toolbar based on the selected items. [self updateToolbarState]; } } @@ -361,6 +363,16 @@ } } +#pragma mark - UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer + shouldReceiveTouch:(UITouch*)touch { + // Prevent the context menu to be displayed if the long press is done on the + // App Bar. + CGPoint location = [touch locationInView:self.appBar.navigationBar]; + return !CGRectContainsPoint(self.appBar.navigationBar.frame, location); +} + #pragma mark - Private methods - (void)donePressed {
diff --git a/ios/chrome/browser/web/resources/credential_manager.js b/ios/chrome/browser/web/resources/credential_manager.js index 700d527..2c0d83d 100644 --- a/ios/chrome/browser/web/resources/credential_manager.js +++ b/ios/chrome/browser/web/resources/credential_manager.js
@@ -10,10 +10,6 @@ * the window.navigator.object. */ -// TODO(crbug.com/435046) This only contains method signatures. -// Implement the JavaScript API and types according to the spec: -// https://w3c.github.io/webappsec-credential-management - // TODO(crbug.com/435046) After get, store, preventSilentAccess are // implemented app-side, make sure that all tests at // https://w3c-test.org/credential-management/idl.https.html @@ -183,10 +179,10 @@ // Perform following steps: // https://w3c.github.io/webappsec-credential-management/#abstract-opdef-create-a-passwordcredential-from-passwordcredentialdata - if (!data.id) { + if (!data.id || typeof data.id != 'string') { throw new TypeError('id must be a non-empty string'); } - if (!data.password) { + if (!data.password || typeof data.password != 'string') { throw new TypeError('password must be a non-empty string'); } if (data.iconURL && !data.iconURL.startsWith('https://')) { @@ -260,10 +256,10 @@ * @constructor */ function FederatedCredential(init) { - if (!init.id) { + if (!init.id || typeof init.id != 'string') { throw new TypeError('id must be a non-empty string'); } - if (!init.provider) { + if (!init.provider || typeof init.provider != 'string') { throw new TypeError('provider must be a non-empty string'); } if (!init.provider.startsWith('https://') && @@ -410,7 +406,10 @@ * The CredentialCreationOptions dictionary, for more information see * https://w3c.github.io/webappsec-credential-management/#credentialcreationoptions-dictionary * @dict - * @typedef {Object} + * @typedef {{ + * password: ?PasswordCredentialInit, + * federated: ?FederatedCredentialInit + * }} */ var CredentialCreationOptions; @@ -474,7 +473,30 @@ * of the request. */ CredentialsContainer.prototype.create = function(options) { - // TODO(crbug.com/435046) Implement |create| as JS function + // According to + // https://w3c.github.io/webappsec-credential-management/#abstract-opdef-create-a-credential, + // we should also check for secure context. Instead it is done only in + // browser-side methods. Since public JS interface is exposed, user can create + // a Credential using a constructor anyway. + return new Promise(function(resolve, reject) { + try { + if (options && options.password && !options.federated) { + resolve(new PasswordCredential(options.password)); + return; + } + if (options && options.federated && !options.password) { + resolve(new FederatedCredential(options.federated)); + return; + } + } catch (err) { + reject(err); + return; + } + reject(Object.create(DOMException.prototype, { + name: {value: DOMException.NOT_SUPPORTED_ERR}, + message: {value: 'Invalid CredentialRequestOptions'} + })); + }); }; /**
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index 06f94ae..8f0edb9 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -202,11 +202,18 @@ chromeos::AudioDeviceList devices; GetAudioDevices(&devices); - // At this point, we know we have an ordinary input device, so we look up its - // device_name, which identifies which hardware device it belongs to. uint64_t device_id = 0; - if (!base::StringToUint64(input_device_id, &device_id)) - return ""; + if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) { + device_id = GetPrimaryActiveInputNode(); + } else { + // At this point, we know we have an ordinary input device id, so we parse + // the string for its device_id. + if (!base::StringToUint64(input_device_id, &device_id)) + return ""; + } + + // Find the device in the device list to get the device name (identifying the + // hardware device). const chromeos::AudioDevice* input_device = GetDeviceFromId(devices, device_id); if (!input_device) @@ -395,12 +402,41 @@ event->Signal(); } +uint64_t AudioManagerCras::GetPrimaryActiveInputNode() { + DCHECK(GetTaskRunner()->BelongsToCurrentThread()); + uint64_t device_id = 0; + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + if (main_task_runner_->BelongsToCurrentThread()) { + GetPrimaryActiveInputNodeOnMainThread(&device_id, &event); + } else { + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&AudioManagerCras::GetPrimaryActiveInputNodeOnMainThread, + weak_this_, &device_id, &event)); + } + WaitEventOrShutdown(&event); + return device_id; +} + +void AudioManagerCras::GetPrimaryActiveInputNodeOnMainThread( + uint64_t* active_input_node_id, + base::WaitableEvent* event) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (chromeos::CrasAudioHandler::IsInitialized()) { + *active_input_node_id = + chromeos::CrasAudioHandler::Get()->GetPrimaryActiveInputNode(); + } + event->Signal(); +} + void AudioManagerCras::GetPrimaryActiveOutputNodeOnMainThread( uint64_t* active_output_node_id, base::WaitableEvent* event) { DCHECK(main_task_runner_->BelongsToCurrentThread()); if (chromeos::CrasAudioHandler::IsInitialized()) { - chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode(); + *active_output_node_id = + chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode(); } event->Signal(); }
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h index 0807037..bf8a3dbf 100644 --- a/media/audio/cras/audio_manager_cras.h +++ b/media/audio/cras/audio_manager_cras.h
@@ -83,6 +83,9 @@ void GetAudioDevices(chromeos::AudioDeviceList* devices); void GetAudioDevicesOnMainThread(chromeos::AudioDeviceList* devices, base::WaitableEvent* event); + uint64_t GetPrimaryActiveInputNode(); + void GetPrimaryActiveInputNodeOnMainThread(uint64_t* active_input_node_id, + base::WaitableEvent* event); void GetPrimaryActiveOutputNodeOnMainThread(uint64_t* active_output_node_id, base::WaitableEvent* event); void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 2af246e..efcdc68 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -250,6 +250,10 @@ const base::Feature kUseNewMediaCache{"use-new-media-cache", base::FEATURE_ENABLED_BY_DEFAULT}; +// Use R16 texture for 9-16 bit channel instead of half-float conversion by CPU. +const base::Feature kUseR16Texture{"use-r16-texture", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Correct video colors based on output display? const base::Feature kVideoColorManagement{"video-color-management", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 2428343..4be332de 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -123,6 +123,7 @@ MEDIA_EXPORT extern const base::Feature kSupportExperimentalCdmInterface; MEDIA_EXPORT extern const base::Feature kUseAndroidOverlay; MEDIA_EXPORT extern const base::Feature kUseNewMediaCache; +MEDIA_EXPORT extern const base::Feature kUseR16Texture; MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy; MEDIA_EXPORT extern const base::Feature kVideoColorManagement; MEDIA_EXPORT extern const base::Feature kUseSurfaceLayerForVideo;
diff --git a/sandbox/win/src/acl.cc b/sandbox/win/src/acl.cc index f2f5ac4..be1079f8 100644 --- a/sandbox/win/src/acl.cc +++ b/sandbox/win/src/acl.cc
@@ -48,8 +48,7 @@ new_access.Trustee.pMultipleTrustee = NULL; new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID; - new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>( - const_cast<SID*>(sid.GetPSID())); + new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID()); if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl)) return false;
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc index b696a24b..63bc38c 100644 --- a/sandbox/win/src/restricted_token.cc +++ b/sandbox/win/src/restricted_token.cc
@@ -92,8 +92,7 @@ for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) { deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY; - deny_only_array[i].Sid = - const_cast<SID*>(sids_for_deny_only_[i].GetPSID()); + deny_only_array[i].Sid = sids_for_deny_only_[i].GetPSID(); } } @@ -103,8 +102,7 @@ for (unsigned int i = 0; i < restrict_size; ++i) { sids_to_restrict_array[i].Attributes = 0; - sids_to_restrict_array[i].Sid = - const_cast<SID*>(sids_to_restrict_[i].GetPSID()); + sids_to_restrict_array[i].Sid = sids_to_restrict_[i].GetPSID(); } } @@ -242,8 +240,8 @@ bool should_ignore = false; if (exceptions) { for (unsigned int j = 0; j < exceptions->size(); ++j) { - if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()), - token_groups->Groups[i].Sid)) { + if (::EqualSid((*exceptions)[j].GetPSID(), + token_groups->Groups[i].Sid)) { should_ignore = true; break; }
diff --git a/sandbox/win/src/sid.cc b/sandbox/win/src/sid.cc index 19c645b..5df1acf 100644 --- a/sandbox/win/src/sid.cc +++ b/sandbox/win/src/sid.cc
@@ -4,23 +4,123 @@ #include "sandbox/win/src/sid.h" +#include <sddl.h> + #include "base/logging.h" +#include "base/win/windows_version.h" namespace sandbox { -Sid::Sid(const SID *sid) { - ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid)); +namespace { + +typedef decltype( + ::DeriveCapabilitySidsFromName) DeriveCapabilitySidsFromNameFunc; + +class SidArray { + public: + SidArray() : count_(0), sids_(nullptr) {} + + ~SidArray() { + if (sids_) { + for (size_t index = 0; index < count_; ++index) { + ::LocalFree(sids_[index]); + } + ::LocalFree(sids_); + } + } + + DWORD count() { return count_; } + PSID* sids() { return sids_; } + PDWORD count_ptr() { return &count_; } + PSID** sids_ptr() { return &sids_; } + + private: + DWORD count_; + PSID* sids_; }; +const wchar_t* WellKnownCapabilityToName(WellKnownCapabilities capability) { + switch (capability) { + case kInternetClient: + return L"internetClient"; + case kInternetClientServer: + return L"internetClientServer"; + case kRegistryRead: + return L"registryRead"; + case kLpacCryptoServices: + return L"lpacCryptoServices"; + case kEnterpriseAuthentication: + return L"enterpriseAuthentication"; + case kPrivateNetworkClientServer: + return L"privateNetworkClientServer"; + default: + return nullptr; + } +} + +} // namespace + +Sid::Sid() : sid_() {} + +Sid::Sid(PSID sid) : sid_() { + ::CopySid(SECURITY_MAX_SID_SIZE, sid_, sid); +} + +Sid::Sid(const SID* sid) : sid_() { + ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid)); +} + Sid::Sid(WELL_KNOWN_SID_TYPE type) { DWORD size_sid = SECURITY_MAX_SID_SIZE; - BOOL result = ::CreateWellKnownSid(type, NULL, sid_, &size_sid); + BOOL result = ::CreateWellKnownSid(type, nullptr, sid_, &size_sid); DCHECK(result); (void)result; } -const SID *Sid::GetPSID() const { - return reinterpret_cast<SID*>(const_cast<BYTE*>(sid_)); +Sid Sid::FromKnownCapability(WellKnownCapabilities capability) { + return Sid::FromNamedCapability(WellKnownCapabilityToName(capability)); +} + +Sid Sid::FromNamedCapability(const wchar_t* capability_name) { + DeriveCapabilitySidsFromNameFunc* derive_capablity_sids = + (DeriveCapabilitySidsFromNameFunc*)GetProcAddress( + GetModuleHandle(L"kernelbase"), "DeriveCapabilitySidsFromName"); + if (!derive_capablity_sids) + return Sid(); + + if (capability_name == nullptr || ::wcslen(capability_name) == 0) + return Sid(); + + SidArray capability_group_sids; + SidArray capability_sids; + + if (!derive_capablity_sids(capability_name, capability_group_sids.sids_ptr(), + capability_group_sids.count_ptr(), + capability_sids.sids_ptr(), + capability_sids.count_ptr())) { + return Sid(); + } + + if (capability_sids.count() < 1) + return Sid(); + + return Sid(capability_sids.sids()[0]); +} + +Sid Sid::FromSddlString(const wchar_t* sddl_sid) { + PSID converted_sid; + if (!::ConvertStringSidToSid(sddl_sid, &converted_sid)) + return Sid(); + + return Sid(converted_sid); +} + +PSID Sid::GetPSID() const { + return const_cast<BYTE*>(sid_); +} + +bool Sid::IsValid() const { + return !!::IsValidSid(GetPSID()); } } // namespace sandbox
diff --git a/sandbox/win/src/sid.h b/sandbox/win/src/sid.h index 4656859..c415545 100644 --- a/sandbox/win/src/sid.h +++ b/sandbox/win/src/sid.h
@@ -9,18 +9,41 @@ namespace sandbox { +enum WellKnownCapabilities { + kInternetClient, + kInternetClientServer, + kRegistryRead, + kLpacCryptoServices, + kEnterpriseAuthentication, + kPrivateNetworkClientServer, + kMaxWellKnownCapability +}; + // This class is used to hold and generate SIDS. class Sid { public: // Constructors initializing the object with the SID passed. // This is a converting constructor. It is not explicit. - Sid(const SID *sid); + Sid(PSID sid); + Sid(const SID* sid); Sid(WELL_KNOWN_SID_TYPE type); + // Create a Sid from an AppContainer capability name. The name can be + // completely arbitrary. + static Sid FromNamedCapability(const wchar_t* capability_name); + // Create a Sid from a known capability enumeration value. + static Sid FromKnownCapability(WellKnownCapabilities capability); + // Create a Sid from a SDDL format string, such as S-1-1-0. + static Sid FromSddlString(const wchar_t* sddl_sid); + // Returns sid_. - const SID *GetPSID() const; + PSID GetPSID() const; + + // Gets whether the sid is valid. + bool IsValid() const; private: + Sid(); BYTE sid_[SECURITY_MAX_SID_SIZE]; };
diff --git a/sandbox/win/src/sid_unittest.cc b/sandbox/win/src/sid_unittest.cc index 76d61e82..b6c2f50 100644 --- a/sandbox/win/src/sid_unittest.cc +++ b/sandbox/win/src/sid_unittest.cc
@@ -7,65 +7,129 @@ #define _ATL_NO_EXCEPTIONS #include <atlbase.h> #include <atlsecurity.h> +#include <sddl.h> +#include "base/win/windows_version.h" #include "sandbox/win/src/sid.h" #include "testing/gtest/include/gtest/gtest.h" namespace sandbox { -// Calls ::EqualSid. This function exists only to simplify the calls to -// ::EqualSid by removing the need to cast the input params. -BOOL EqualSid(const SID *sid1, const SID *sid2) { - return ::EqualSid(const_cast<SID*>(sid1), const_cast<SID*>(sid2)); +namespace { + +bool EqualSid(const Sid& sid, const ATL::CSid& compare_sid) { + if (!sid.IsValid()) + return false; + return !!::EqualSid(sid.GetPSID(), const_cast<SID*>(compare_sid.GetPSID())); } -// Tests the creation if a Sid +bool EqualSid(const Sid& sid, const wchar_t* sddl_sid) { + PSID compare_sid; + if (!sid.IsValid()) + return false; + if (!::ConvertStringSidToSid(sddl_sid, &compare_sid)) + return false; + bool equal = !!::EqualSid(sid.GetPSID(), compare_sid); + ::LocalFree(compare_sid); + return equal; +} + +struct CapabilityTestEntry { + WellKnownCapabilities capability_; + const wchar_t* capability_name_; + const wchar_t* sddl_sid_; +}; +} + +// Tests the creation of a Sid. TEST(SidTest, Constructors) { ATL::CSid sid_world = ATL::Sids::World(); - SID *sid_world_pointer = const_cast<SID*>(sid_world.GetPSID()); + PSID sid_world_pointer = const_cast<SID*>(sid_world.GetPSID()); - // Check the SID* constructor + // Check the SID* constructor. Sid sid_sid_star(sid_world_pointer); - ASSERT_TRUE(EqualSid(sid_world_pointer, sid_sid_star.GetPSID())); + ASSERT_TRUE(EqualSid(sid_sid_star, sid_world)); - // Check the copy constructor + // Check the copy constructor. Sid sid_copy(sid_sid_star); - ASSERT_TRUE(EqualSid(sid_world_pointer, sid_copy.GetPSID())); + ASSERT_TRUE(EqualSid(sid_copy, sid_world)); + + Sid sid_sddl = Sid::FromSddlString(L"S-1-1-0"); + ASSERT_TRUE(sid_sddl.IsValid()); + ASSERT_TRUE(EqualSid(sid_sddl, sid_world)); + + Sid sid_sddl_invalid = Sid::FromSddlString(L"X-1-1-0"); + ASSERT_FALSE(sid_sddl_invalid.IsValid()); + + Sid sid_sddl_empty = Sid::FromSddlString(L""); + ASSERT_FALSE(sid_sddl_empty.IsValid()); // Note that the WELL_KNOWN_SID_TYPE constructor is tested in the GetPSID - // test. + // test. AppContainer related constructors are tested in AppContainer. } // Tests the method GetPSID TEST(SidTest, GetPSID) { // Check for non-null result; - ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinLocalSid).GetPSID()); - ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinCreatorOwnerSid).GetPSID()); - ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinBatchSid).GetPSID()); + ASSERT_NE(nullptr, Sid(::WinLocalSid).GetPSID()); + ASSERT_NE(nullptr, Sid(::WinCreatorOwnerSid).GetPSID()); + ASSERT_NE(nullptr, Sid(::WinBatchSid).GetPSID()); - ASSERT_TRUE(EqualSid(Sid(::WinNullSid).GetPSID(), - ATL::Sids::Null().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinNullSid), ATL::Sids::Null())); - ASSERT_TRUE(EqualSid(Sid(::WinWorldSid).GetPSID(), - ATL::Sids::World().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinWorldSid), ATL::Sids::World())); - ASSERT_TRUE(EqualSid(Sid(::WinDialupSid).GetPSID(), - ATL::Sids::Dialup().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinDialupSid), ATL::Sids::Dialup())); - ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid).GetPSID(), - ATL::Sids::Network().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid), ATL::Sids::Network())); - ASSERT_TRUE(EqualSid(Sid(::WinBuiltinAdministratorsSid).GetPSID(), - ATL::Sids::Admins().GetPSID())); + ASSERT_TRUE( + EqualSid(Sid(::WinBuiltinAdministratorsSid), ATL::Sids::Admins())); - ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid).GetPSID(), - ATL::Sids::Users().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid), ATL::Sids::Users())); - ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid).GetPSID(), - ATL::Sids::Guests().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid), ATL::Sids::Guests())); - ASSERT_TRUE(EqualSid(Sid(::WinProxySid).GetPSID(), - ATL::Sids::Proxy().GetPSID())); + ASSERT_TRUE(EqualSid(Sid(::WinProxySid), ATL::Sids::Proxy())); +} + +TEST(SidTest, AppContainer) { + const CapabilityTestEntry capabilities[] = { + {kInternetClient, L"internetClient", L"S-1-15-3-1"}, + {kInternetClientServer, L"internetClientServer", L"S-1-15-3-2"}, + {kRegistryRead, L"registryRead", + L"S-1-15-3-1024-1065365936-1281604716-3511738428-" + "1654721687-432734479-3232135806-4053264122-3456934681"}, + {kLpacCryptoServices, L"lpacCryptoServices", + L"S-1-15-3-1024-3203351429-2120443784-2872670797-" + "1918958302-2829055647-4275794519-765664414-2751773334"}, + {kEnterpriseAuthentication, L"enterpriseAuthentication", L"S-1-15-3-8"}, + {kPrivateNetworkClientServer, L"privateNetworkClientServer", + L"S-1-15-3-3"}}; + + // No support for AppContainer less than Win10 RS2. + if (base::win::GetVersion() < base::win::VERSION_WIN10_RS2) + return; + + Sid sid_nullptr = Sid::FromNamedCapability(nullptr); + EXPECT_FALSE(sid_nullptr.IsValid()); + + Sid sid_empty = Sid::FromNamedCapability(L""); + EXPECT_FALSE(sid_empty.IsValid()); + + WellKnownCapabilities invalid_well_known = + static_cast<WellKnownCapabilities>(kMaxWellKnownCapability + 1); + Sid sid_invalid_well_known = Sid::FromKnownCapability(invalid_well_known); + EXPECT_FALSE(sid_invalid_well_known.IsValid()); + + for (auto capability : capabilities) { + EXPECT_TRUE(EqualSid(Sid::FromNamedCapability(capability.capability_name_), + capability.sddl_sid_)) + << "Named Capability: " << capability.sddl_sid_; + EXPECT_TRUE(EqualSid(Sid::FromKnownCapability(capability.capability_), + capability.sddl_sid_)) + << "Known Capability: " << capability.sddl_sid_; + } } } // namespace sandbox
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 3603901e..7974930 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -261,8 +261,6 @@ crbug.com/591099 animations/interpolation/transform-interpolation-004.html [ Timeout ] crbug.com/591099 animations/interpolation/transform-interpolation-005.html [ Timeout ] crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Crash Pass Timeout ] -crbug.com/591099 animations/interpolation/webkit-column-count-interpolation.html [ Failure ] -crbug.com/591099 animations/interpolation/webkit-column-width-interpolation.html [ Failure ] crbug.com/591099 animations/keyframes-rule.html [ Failure Pass ] crbug.com/591099 animations/lazy-detached-animation-stop.html [ Failure ] crbug.com/591099 animations/play-state.html [ Failure Pass ] @@ -9287,7 +9285,6 @@ crbug.com/591099 fast/mediastream/enabled.html [ Failure Pass ] crbug.com/591099 fast/mediastream/getusermedia.html [ Failure Pass ] crbug.com/591099 fast/mediastream/no-interface-object.html [ Failure Pass ] -crbug.com/591099 fast/multicol/5-levels-of-nesting-crash.html [ Failure ] crbug.com/591099 fast/multicol/abspos-after-break-after.html [ Failure ] crbug.com/591099 fast/multicol/abspos-in-overflow-hidden-in-2nd-column.html [ Failure ] crbug.com/591099 fast/multicol/abspos-new-width-rebalance.html [ Failure ] @@ -9357,10 +9354,8 @@ crbug.com/591099 fast/multicol/composited-with-child-layer-in-next-column.html [ Failure ] crbug.com/591099 fast/multicol/composited-with-overflow-in-next-column.html [ Failure Timeout ] crbug.com/591099 fast/multicol/constrained-content-height-with-overflow-crash.html [ Failure Pass ] -crbug.com/591099 fast/multicol/content-change-same-height.html [ Failure ] crbug.com/591099 fast/multicol/content-height-zero-crash.html [ Failure Pass ] crbug.com/591099 fast/multicol/cssom-view.html [ Failure ] -crbug.com/591099 fast/multicol/doubly-nested-with-increasing-row-heights-crash.html [ Failure ] crbug.com/757767 fast/multicol/doubly-nested-with-insane-child-height-crash.html [ Timeout ] crbug.com/757767 fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Timeout ] crbug.com/591099 fast/multicol/dynamic/abspos-becomes-spanner.html [ Failure ] @@ -9486,11 +9481,9 @@ crbug.com/591099 fast/multicol/hit-test-gap-between-pages.html [ Failure ] crbug.com/757767 fast/multicol/huge-column-count.html [ Crash Timeout ] crbug.com/591099 fast/multicol/image-inside-nested-blocks-with-border.html [ Failure ] -crbug.com/591099 fast/multicol/image-loaded-before-layout-assert.html [ Failure ] crbug.com/757767 fast/multicol/infinite-height-causing-fractional-row-height-crash.html [ Timeout ] crbug.com/757767 fast/multicol/infinitely-tall-content-in-outer-crash.html [ Timeout ] crbug.com/591099 fast/multicol/inline-block-baseline.html [ Failure ] -crbug.com/591099 fast/multicol/inline-children-crash.html [ Failure ] crbug.com/591099 fast/multicol/inline-getclientrects.html [ Failure ] crbug.com/591099 fast/multicol/inner-multicol-in-second-column.html [ Failure ] crbug.com/591099 fast/multicol/inner-multicol-moved-into-continuation.html [ Failure Pass ] @@ -9517,7 +9510,6 @@ crbug.com/591099 fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure ] crbug.com/591099 fast/multicol/negative-margins-crash.html [ Failure Pass ] crbug.com/591099 fast/multicol/nested-3-multicols-fixed-height.html [ Failure ] -crbug.com/591099 fast/multicol/nested-after-composited-layer-crash.html [ Failure ] crbug.com/757767 fast/multicol/nested-and-unbreakable-crash.html [ Timeout ] crbug.com/591099 fast/multicol/nested-auto-height-extra-block-inbetween.html [ Failure ] crbug.com/591099 fast/multicol/nested-auto-height-short-first-row.html [ Failure ] @@ -9542,7 +9534,6 @@ crbug.com/591099 fast/multicol/nested-with-clipped-first-column.html [ Failure ] crbug.com/591099 fast/multicol/nested-with-composited-and-multicol-crash.html [ Failure Pass Timeout ] crbug.com/591099 fast/multicol/nested-with-forced-breaks-in-eariler-rows.html [ Failure Timeout ] -crbug.com/591099 fast/multicol/nested-with-line-taller-than-outer.html [ Failure ] crbug.com/591099 fast/multicol/nested-with-padding.html [ Failure ] crbug.com/591099 fast/multicol/nested-with-single-empty-block.html [ Failure Timeout ] crbug.com/591099 fast/multicol/nested-with-single-tall-line.html [ Failure ] @@ -9652,7 +9643,6 @@ crbug.com/591099 fast/multicol/span/fill-after-spanner-exact-fit.html [ Failure ] crbug.com/591099 fast/multicol/span/fill-after-spanner-extra-height.html [ Failure ] crbug.com/591099 fast/multicol/span/float.html [ Failure ] -crbug.com/591099 fast/multicol/span/foreignObject.html [ Failure ] crbug.com/591099 fast/multicol/span/height-decrease.html [ Failure ] crbug.com/591099 fast/multicol/span/height-increase.html [ Failure ] crbug.com/591099 fast/multicol/span/in-nested-multicol-with-hard-breaks.html [ Failure ] @@ -9661,7 +9651,6 @@ crbug.com/591099 fast/multicol/span/inside-abspos-crash.html [ Failure Pass ] crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height-crash.html [ Failure Pass ] crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height.html [ Failure ] -crbug.com/591099 fast/multicol/span/inside-float-crash.html [ Failure ] crbug.com/591099 fast/multicol/span/inside-overflow-hidden-crash.html [ Failure Pass ] crbug.com/591099 fast/multicol/span/invalid-span-1.html [ Failure Pass ] crbug.com/591099 fast/multicol/span/invalid-spanner-in-abspos.html [ Failure ] @@ -9722,10 +9711,8 @@ crbug.com/591099 fast/multicol/textarea-with-placeholder-as-multicol-crash.html [ Failure Pass ] crbug.com/591099 fast/multicol/three-inner-rows.html [ Failure Timeout ] crbug.com/591099 fast/multicol/transform-inside-opacity.html [ Failure ] -crbug.com/591099 fast/multicol/triply-nested-with-padding-crash.html [ Failure ] crbug.com/591099 fast/multicol/unbreakable-block-too-tall-at-column-start.html [ Failure ] crbug.com/591099 fast/multicol/unbreakable-block-too-tall-to-fit.html [ Failure ] -crbug.com/591099 fast/multicol/unbreakable-content-taller-than-height-crash.html [ Failure ] crbug.com/591099 fast/multicol/unforced-break-after-complex-margin-collapsing.html [ Failure ] crbug.com/591099 fast/multicol/unsplittable-inline-block.html [ Failure ] crbug.com/591099 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ] @@ -14669,10 +14656,8 @@ crbug.com/591099 printing/page-count-percentage-height.html [ Failure Pass ] crbug.com/591099 printing/page-count-relayout-shrink.html [ Failure ] crbug.com/591099 printing/page-format-data.html [ Failure Pass ] -crbug.com/591099 printing/page-height-zero.html [ Failure ] crbug.com/591099 printing/page-rule-selection.html [ Failure Pass Timeout ] crbug.com/591099 printing/pageNumerForElementById.html [ Failure Pass ] -crbug.com/591099 printing/pageProperty-with-multicol.html [ Failure ] crbug.com/591099 printing/pseudo-class-outside-page.html [ Failure Pass ] crbug.com/591099 printing/quirks-percentage-height-body.html [ Failure ] crbug.com/591099 printing/quirks-percentage-height.html [ Failure ] @@ -14687,7 +14672,6 @@ crbug.com/591099 printing/tfoot-repeats-at-bottom-of-each-page.html [ Failure ] crbug.com/591099 printing/thead-repeats-at-top-of-each-page-multiple-tables.html [ Failure ] crbug.com/591099 printing/thead-repeats-at-top-of-each-page.html [ Failure ] -crbug.com/591099 printing/viewport-size-dependant-iframe-with-multicol-crash.html [ Failure ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] crbug.com/591099 scrollbars/basic-scrollbar.html [ Failure ] crbug.com/591099 scrollbars/custom-scrollbar-enable-changes-thickness-with-iframe.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index 98ff27b..3dcb2eeb 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -288,13 +288,6 @@ # The revert keyword is not yet supported. external/wpt/css/css-cascade-4/revert-val-001.html [ WontFix ] -# WPT subdirectories without owners. -external/wpt/accelerometer [ WontFix ] -external/wpt/assumptions [ WontFix ] -external/wpt/gyroscope [ WontFix ] -external/wpt/magnetometer [ WontFix ] -external/wpt/upgrade-insecure-requests [ WontFix ] - # Temporary disabling of most encrypted-media WPT tests while enabling # https only. Once the switch is complete (and the WPT tests renamed so they # run using https), they can be re-enabled.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index cdc3ed4d..aef1ff8 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -486,22 +486,13 @@ crbug.com/635619 virtual/layout_ng/fast/block/float/032.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/034.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/035.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/add-float-back-to-anonymous-block.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/assert-when-moving-float.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/assert-when-moving-float-2.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-2.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-3.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-4.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-5.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top-6.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/avoid-floats-when-negative-margin-top.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/avoiding-float-centered.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/block-with-negative-margin-clears-float.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/br-with-clear-2.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/centered-float-avoidance-complexity.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/checkbox-and-radio-avoid-floats.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/clear-intruding-floats-when-moving-to-inline-parent-3.html [ Failure Crash Pass ] -crbug.com/635619 virtual/layout_ng/fast/block/float/crash-on-absolute-positioning.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/crash-replaced-display-block.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/element-clears-float-without-clearance.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-at-start-of-clean-lines-that-are-subsequently-dirtied-vertical-rl.html [ Failure ] @@ -513,10 +504,7 @@ crbug.com/635619 virtual/layout_ng/fast/block/float/float-inserted-into-clean-line.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-list-changed-before-layout-crash.html [ Crash Pass ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-first-letter.html [ Crash Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling-crash.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling4.html [ Crash Pass ] -crbug.com/635619 virtual/layout_ng/fast/block/float/float-not-removed-from-next-sibling5.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/float-on-empty-line.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-on-zero-height-line.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-overflow-hidden-containing-block-width.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/float-reparent-during-detach-crash.html [ Crash Pass ] @@ -534,7 +522,6 @@ crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-002.htm [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-003.htm [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/floats-wrap-inside-inline-004.htm [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/formatting-context-changes.html [ Failure Crash ] crbug.com/635619 virtual/layout_ng/fast/block/float/independent-align-positioning.html [ Failure ] crbug.com/635619 [ Mac ] virtual/layout_ng/fast/block/float/intruding-painted-twice.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/line-break-after-white-space-crash.html [ Pass Crash Timeout ] @@ -549,11 +536,8 @@ crbug.com/635619 virtual/layout_ng/fast/block/float/overhanging-float-remove-from-fixed-position-block2.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/overlapping-floats-paint-hittest-order-1.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/overlapping-floats-paint-hittest-order-2.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/override-property-float.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/remove-line-above-float-above-line-crash.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-made-inline-crash.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash-2.html [ Failure Crash ] -crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash.html [ Crash Failure ] +crbug.com/635619 virtual/layout_ng/fast/block/float/rubybase-children-moved-crash.html [ Crash Pass ] crbug.com/635619 virtual/layout_ng/fast/block/float/shrink-to-avoid-float-complexity.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/shrink-to-fit-width.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/float/trailing-float-with-columns.html [ Crash Failure ] @@ -565,7 +549,6 @@ crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/057.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/103.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/bfc-beside-float-complex-margin-collapsing.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/self-collapsing-block-with-overflow-hidden-and-float-child.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/self-collapsing-cols-creates-block-formatting-context.html [ Failure ] ### virtual/layout_ng/fast/block/margin-collapse/block-inside-inline @@ -578,9 +561,6 @@ ### virtual/layout_ng/fast/block/margin-collapse crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/empty-clear-blocks.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/line-beside-float-complex-margin-collapsing.html [ Failure Crash ] -crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/self-collapsing-with-floats.html [ Failure ] -crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/table-beside-float-complex-margin-collapsing.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-container.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-separate-position.html [ Failure ] crbug.com/635619 virtual/layout_ng/fast/block/margin-collapse/webkit-margin-collapse-siblings.html [ Failure ] @@ -1759,6 +1739,8 @@ crbug.com/751952 virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/budget-api-origin-trial-interfaces.html [ Pass Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/payment-request/change-shipping-option-manual.https.html [ Skip ] +crbug.com/626703 external/wpt/payment-request/shipping-address-changed-manual.https.html [ Skip ] crbug.com/626703 external/wpt/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/relevant-mutations.html [ Timeout ] @@ -3663,6 +3645,9 @@ # Sheriff failures 2017-09-08 crbug.com/763208 [ Linux ] virtual/mojo-loading/http/tests/devtools/sources/debugger-ui/source-frame-count.html [ Pass Failure ] +crbug.com/763666 [ Linux Win ] external/wpt/assumptions/ahem.html [ Failure ] +crbug.com/763667 external/wpt/upgrade-insecure-requests/iframe-redirect-upgrade.https.html [ Timeout ] + # Sheriff failures 2017-09-11 crbug.com/763809 [ Win7 Debug ] fast/multicol/nested-very-tall-inside-short-crash.html [ Pass Failure Timeout ] crbug.com/763810 [ Win7 Debug ] virtual/threaded/transitions/transition-end-event-nested.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index ed279db..c2016a8c 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -3,9 +3,8 @@ # This file acts as a blacklist; directories and files not listed here will # automatically be found and imported. # -# We may want to move towards importing but not running directories without -# owners, in order to make it easier to enable or run them in the future -- -# directories that are imported but not run are listed in NeverFixTests. +# Directories that are imported but not run are listed in NeverFixTests. This +# can be used to make it easier to work on getting them running and passing. # # Further documentation: # https://chromium.googlesource.com/chromium/src/+/master/docs/testing/layout_test_expectations.md
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 12819b3..731e1f4 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -3811,6 +3811,12 @@ {} ] ], + "payment-request/change-shipping-option-manual.https.html": [ + [ + "/payment-request/change-shipping-option-manual.https.html", + {} + ] + ], "payment-request/payment-response/complete-method-manual.https.html": [ [ "/payment-request/payment-response/complete-method-manual.https.html", @@ -3859,6 +3865,12 @@ {} ] ], + "payment-request/shipping-address-changed-manual.https.html": [ + [ + "/payment-request/shipping-address-changed-manual.https.html", + {} + ] + ], "payment-request/updateWith-method-pmi-handling-manual.https.html": [ [ "/payment-request/updateWith-method-pmi-handling-manual.https.html", @@ -92669,6 +92681,11 @@ {} ] ], + "css/css-ui-3/text-overflow-023-expected.txt": [ + [ + {} + ] + ], "css/css-ui-3/text-overflow-ref.html": [ [ {} @@ -115334,11 +115351,6 @@ {} ] ], - "payment-request/interfaces.https-expected.txt": [ - [ - {} - ] - ], "payment-request/payment-request-abort-method.https-expected.txt": [ [ {} @@ -115374,11 +115386,6 @@ {} ] ], - "performance-timeline/idlharness-expected.txt": [ - [ - {} - ] - ], "performance-timeline/performanceobservers.js": [ [ {} @@ -133526,12 +133533,24 @@ {} ] ], + "XMLHttpRequest/access-control-sandboxed-iframe-allow-origin-null.htm": [ + [ + "/XMLHttpRequest/access-control-sandboxed-iframe-allow-origin-null.htm", + {} + ] + ], "XMLHttpRequest/access-control-sandboxed-iframe-allow.htm": [ [ "/XMLHttpRequest/access-control-sandboxed-iframe-allow.htm", {} ] ], + "XMLHttpRequest/access-control-sandboxed-iframe-denied.htm": [ + [ + "/XMLHttpRequest/access-control-sandboxed-iframe-denied.htm", + {} + ] + ], "XMLHttpRequest/allow-lists-starting-with-comma.htm": [ [ "/XMLHttpRequest/allow-lists-starting-with-comma.htm", @@ -140082,6 +140101,12 @@ {} ] ], + "css/css-ui-3/text-overflow-023.html": [ + [ + "/css/css-ui-3/text-overflow-023.html", + {} + ] + ], "css/css-values-3/absolute-length-units-001.html": [ [ "/css/css-values-3/absolute-length-units-001.html", @@ -197621,10 +197646,18 @@ "9c4a5cf99e43f1315dfd73f543450e4056dcef36", "testharness" ], + "XMLHttpRequest/access-control-sandboxed-iframe-allow-origin-null.htm": [ + "2b507239c3e3fa6602068d6d92897c5d042a7a0d", + "testharness" + ], "XMLHttpRequest/access-control-sandboxed-iframe-allow.htm": [ "b1140eacc383af590578319b25ee803ba50c3fee", "testharness" ], + "XMLHttpRequest/access-control-sandboxed-iframe-denied.htm": [ + "32fcbfa28e93aad6e0040b5b1c9478ce76e7e06e", + "testharness" + ], "XMLHttpRequest/allow-lists-starting-with-comma.htm": [ "34a8d82f397f35902c73d9ced2f3cf900d04ae53", "testharness" @@ -237665,6 +237698,14 @@ "095f78700529b34397887722b57b56dd7dd97861", "reftest" ], + "css/css-ui-3/text-overflow-023-expected.txt": [ + "ca595dbd0053aa0bf73d0922a4de71a035eaec96", + "support" + ], + "css/css-ui-3/text-overflow-023.html": [ + "4fd38a517e41851216d12db8c6b732d96f76e325", + "testharness" + ], "css/css-ui-3/text-overflow-ref.html": [ "db55b0b95a7406e9c4f00081b3e2cbe6b07363f7", "support" @@ -254414,7 +254455,7 @@ "testharness" ], "hr-time/idlharness-expected.txt": [ - "f4a7fca22be8e2b8f6b53adb78f55bedcd710b42", + "e62291bdf6959ec7d9558211d3dc1ae365b2749d", "support" ], "hr-time/idlharness.html": [ @@ -274418,7 +274459,7 @@ "support" ], "navigation-timing/nav2_idlharness-expected.txt": [ - "8d6b069447dffdb7e215aa7553a8eb049640eefe", + "dfc2dd329de01d07ed99872bdb0b14c84359e948", "support" ], "navigation-timing/nav2_idlharness.html": [ @@ -281082,7 +281123,7 @@ "manual" ], "payment-request/algorithms-manual.https.html": [ - "5b603c95f9d356dc4e19888ed779c499acb915eb", + "a3d20d112af7ff8d18ddf0b9cb69d121a015f374", "manual" ], "payment-request/allowpaymentrequest/active-document-cross-origin.https.sub.html": [ @@ -281137,6 +281178,10 @@ "6e4028440fff617d6a0e9abb06625891eb53b28a", "testharness" ], + "payment-request/change-shipping-option-manual.https.html": [ + "46bc8b2f5512e7d40e46c4fb255f82def0e359d1", + "manual" + ], "payment-request/historical.https-expected.txt": [ "a98767fbf7d24f102e1546aafe4ed6276c2e79eb", "support" @@ -281145,10 +281190,6 @@ "6695acdcd1647fdd37702a7f63658dcd50f25596", "testharness" ], - "payment-request/interfaces.https-expected.txt": [ - "881a5f9ae1b5c21dd9fe47b99c437d41c90e31c0", - "support" - ], "payment-request/interfaces.https.html": [ "e531c0ceda2fa798e5e6df3c7131e6b80f342884", "testharness" @@ -281273,6 +281314,10 @@ "cb2d1d6dfb668a40bb0822ce2a097d327bf4dfe7", "manual" ], + "payment-request/shipping-address-changed-manual.https.html": [ + "a1784f0be2a7861480f663ac789eed67e08ddce8", + "manual" + ], "payment-request/updateWith-method-pmi-handling-manual.https.html": [ "5e254b412285a6154004aeff98357c6aa55e62c6", "manual" @@ -281289,10 +281334,6 @@ "9c6b6edf19800a2730de2dfe601a7cd2503cf87d", "testharness" ], - "performance-timeline/idlharness-expected.txt": [ - "652c9d061afde560a3195a1f75e7c779fc3df032", - "support" - ], "performance-timeline/idlharness.html": [ "b021a9528875942d44b33c3fc3f4cd643194fad5", "testharness" @@ -294778,7 +294819,7 @@ "support" ], "url/interfaces.any-expected.txt": [ - "59db06e13d086debd8520db45c039f779402df49", + "29c69c6078a772a3b88386c7924b5313dbc6176f", "support" ], "url/interfaces.any.js": [ @@ -294786,7 +294827,7 @@ "testharness" ], "url/interfaces.any.worker-expected.txt": [ - "59db06e13d086debd8520db45c039f779402df49", + "29c69c6078a772a3b88386c7924b5313dbc6176f", "support" ], "url/setters_tests.json": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt new file mode 100644 index 0000000..3376ab8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/Accelerometer.https-expected.txt
@@ -0,0 +1,13 @@ +This is a testharness.js-based test. +FAIL Accelerometer: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Accelerometer: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Accelerometer: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Accelerometer: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +PASS Accelerometer: sensor.start() returns undefined +PASS Accelerometer: no exception is thrown when calling start() on already started sensor +PASS Accelerometer: sensor.stop() returns undefined +PASS Accelerometer: no exception is thrown when calling stop() on already stopped sensor +PASS Accelerometer: throw a 'SecurityError' when constructing sensor object within iframe +FAIL Accelerometer: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023-expected.txt new file mode 100644 index 0000000..71be1ec --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Checks hit testing on the ellipsis assert_equals: the element targeted by a hit on the ellipsis is the elided inline. expected "target" but got "parent" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023.html new file mode 100644 index 0000000..ca3f8da --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-ui-3/text-overflow-023.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<meta charset="utf-8"> +<title>CSS Basic User Interface Test: interacting with the ellipsis</title> +<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/"> +<link rel="help" href="http://www.w3.org/TR/css3-ui/#text-overflow"> +<meta name="flags" content="ahem dom should"> +<meta name="assert" content="Pointer events on the ellipsis should be dispatched to the elided inline element if there's one, rather than directly to the block."> +<!-- This is tested indirectly, using elementFromPoint instead of actually triggering a pointer event, because: + * Actual pointer events can only be dispatched in an manual test, while elementFromPoint allows for an automated test + * These two methods are expected to give the same result + + This indirection and the slight risk of false positive or false negative it introduces + is preferable to a manual test which would hardly anyone would ever run. +--> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +#parent { + position: absolute; + top: 0; left: 0; + font: 50px / 1 ahem ; + overflow: hidden; + width: 3em; + text-overflow: ellipsis; +} +</style> +<div id=parent> <span id=target> </span></div> +<script> +test( + function() { + var e = document.elementFromPoint(125,25); + assert_equals(e.id,"target", "the element targeted by a hit on the ellipsis is the elided inline."); + }, "Checks hit testing on the ellipsis"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt new file mode 100644 index 0000000..3f63e93 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/Gyroscope.https-expected.txt
@@ -0,0 +1,13 @@ +This is a testharness.js-based test. +FAIL Gyroscope: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Gyroscope: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Gyroscope: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Gyroscope: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +PASS Gyroscope: sensor.start() returns undefined +PASS Gyroscope: no exception is thrown when calling start() on already started sensor +PASS Gyroscope: sensor.stop() returns undefined +PASS Gyroscope: no exception is thrown when calling stop() on already stopped sensor +PASS Gyroscope: throw a 'SecurityError' when constructing sensor object within iframe +FAIL Gyroscope: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt index f5beed26..072282c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt
@@ -8,10 +8,10 @@ PASS Performance interface: existence and properties of interface prototype object's "constructor" property PASS Performance interface: operation now() PASS Performance interface: operation toJSON() -FAIL Test default toJSON operation of Performance Illegal invocation PASS Performance must be primary interface of window.performance PASS Stringification of window.performance PASS Performance interface: window.performance must inherit property "now()" with the proper type PASS Performance interface: window.performance must inherit property "toJSON()" with the proper type +FAIL Test default toJSON operation of Performance assert_unreached: property "timing" should not be present in the output of Performance.prototype.toJSON() Reached unreachable code Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt new file mode 100644 index 0000000..0490c60 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/Magnetometer.https-expected.txt
@@ -0,0 +1,13 @@ +This is a testharness.js-based test. +FAIL Magnetometer: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Magnetometer: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Magnetometer: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL Magnetometer: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +PASS Magnetometer: sensor.start() returns undefined +PASS Magnetometer: no exception is thrown when calling start() on already started sensor +PASS Magnetometer: sensor.stop() returns undefined +PASS Magnetometer: no exception is thrown when calling stop() on already stopped sensor +PASS Magnetometer: throw a 'SecurityError' when constructing sensor object within iframe +FAIL Magnetometer: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt index 8c6a4e9..d7761ba0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/navigation-timing/nav2_idlharness-expected.txt
@@ -14,6 +14,6 @@ PASS PerformanceNavigationTiming interface: attribute loadEventEnd PASS PerformanceNavigationTiming interface: attribute type PASS PerformanceNavigationTiming interface: attribute redirectCount -FAIL PerformanceNavigationTiming interface: operation toJSON() undefined PerformanceEntry not found (inherited by PerformanceResourceTiming) +PASS PerformanceNavigationTiming interface: operation toJSON() Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html index af4c70ad8..bcb4b23 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/algorithms-manual.https.html
@@ -65,17 +65,10 @@ requestShipping: true, }; -test(() => { - const request = new PaymentRequest( - methods, - detailsNoShippingOptions, - options - ); -}, "Smoke test"); - function testFireEvent(button, details, eventName, expectRequestProps) { button.disabled = true; promise_test(async t => { + new PaymentRequest(methods, detailsNoShippingOptions, options); const request = new PaymentRequest(methods, details, options); const events = []; const p1 = new Promise(resolve => { @@ -97,12 +90,8 @@ resolve("listener-2"); }); }); - try { - const response = await request.show(); - response.complete("success"); - } catch (err) { - assert_unreached("Unexpected exception: " + err.message); - } + const response = await request.show(); + response.complete("success"); const [handler, listener1, listener2] = await Promise.all([p1, p2, p3]); assert_equals( handler, @@ -164,7 +153,7 @@ <h2 id="shipping-address-changed-algo">Shipping address changed algorithm</h2> <link rel="help" href="https://www.w3.org/TR/payment-request/#shipping-address-changed-algorithm"> <p> - When prompted, please enter or select "web platform test" as recipient, at address "1 wpt street" in "Kabul, Afghanistan", zip/postal code 1001. + When prompted, please change or enter a new shipping address and then select Pay. </p> <ol> <li> @@ -179,7 +168,7 @@ <h2 id="shipping-option-changed-algo">Shipping option changed algorithm</h2> <link rel="help" href="https://w3c.github.io/payment-request/#shipping-option-changed-algorithm"> <p> - When prompted, please select "shipping option 2". + Finally, when prompted, please select "shipping option 2" and then select Pay. </p> <ol> <li>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/change-shipping-option-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/change-shipping-option-manual.https.html new file mode 100644 index 0000000..e9141542 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/change-shipping-option-manual.https.html
@@ -0,0 +1,86 @@ +<!DOCTYPE html> +<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<meta charset="utf-8"> +<title>Test for PaymentRequest shippingOption attribute</title> +<link rel="help" href="https://w3c.github.io/payment-request/#shippingoption-attribute"> +<link rel="help" href="https://w3c.github.io/payment-request/#onshippingoptionchange-attribute"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ explicit_done: true, explicit_timeout: true }); +const validMethod = Object.freeze({ supportedMethods: "basic-card" }); +const validMethods = Object.freeze([validMethod]); +const validAmount = Object.freeze({ currency: "USD", value: "5.00" }); +const validTotal = Object.freeze({ + label: "label", + amount: validAmount, +}); +const validDetails = Object.freeze({ total: validTotal }); + +const validShippingOption1 = Object.freeze({ + id: "valid-1", + label: "PICK ME!", + amount: validAmount, + selected: false, +}); + +const validShippingOption2 = Object.freeze({ + id: "initially-selected", + label: "Valid shipping option 2", + amount: validAmount, + selected: true, +}); + +const requestShipping = Object.freeze({ + requestShipping: true, +}); + +function testShippingOptionChanged() { + promise_test(async t => { + const detailsWithShippingOptions = Object.assign({}, validDetails, { + shippingOptions: [validShippingOption1, validShippingOption2], + }); + const request = new PaymentRequest( + validMethods, + detailsWithShippingOptions, + requestShipping + ); + assert_equals( + request.shippingOption, + "initially-selected", + "Must be 'initially-selected', as the selected member is true" + ); + const listenerPromise = new Promise(resolve => { + request.addEventListener("shippingoptionchange", () => { + resolve(request.shippingOption); + }); + }); + const handlerPromise = new Promise(resolve => { + request.onshippingoptionchange = () => { + resolve(request.shippingOption); + }; + }); + request.show().catch(err => err); + + const results = await Promise.all([listenerPromise, handlerPromise]); + assert_true( + results.every(result => result === "valid-1"), + "Expected valid-1 as the shippingOption" + ); + await request.abort(); + }); + done(); +} +</script> + +<h2>PaymentRequest shippingOption attribute</h2> +<p> + When the payment sheet is presented, select "PICK ME!" as the shipping option. +</p> +<ol> + <li> + <button onclick="testShippingOptionChanged()"> + When the shipping option is manually changed, request.shippingOption represents the user's choice. + </button> + </li> +</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt deleted file mode 100644 index aeff47e..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt +++ /dev/null
@@ -1,68 +0,0 @@ -This is a testharness.js-based test. -PASS PaymentRequest interface: existence and properties of interface object -PASS PaymentRequest interface object length -PASS PaymentRequest interface object name -PASS PaymentRequest interface: existence and properties of interface prototype object -PASS PaymentRequest interface: existence and properties of interface prototype object's "constructor" property -PASS PaymentRequest interface: operation show() -PASS PaymentRequest interface: operation abort() -PASS PaymentRequest interface: operation canMakePayment() -PASS PaymentRequest interface: attribute id -PASS PaymentRequest interface: attribute shippingAddress -PASS PaymentRequest interface: attribute shippingOption -PASS PaymentRequest interface: attribute shippingType -PASS PaymentRequest interface: attribute onshippingaddresschange -PASS PaymentRequest interface: attribute onshippingoptionchange -PASS PaymentRequest must be primary interface of new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) -PASS Stringification of new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "show()" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "abort()" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "canMakePayment()" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "id" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "shippingAddress" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "shippingOption" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "shippingType" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "onshippingaddresschange" with the proper type -PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'BAZ', value: '0'}}}) must inherit property "onshippingoptionchange" with the proper type -PASS PaymentAddress interface: existence and properties of interface object -PASS PaymentAddress interface object length -PASS PaymentAddress interface object name -PASS PaymentAddress interface: existence and properties of interface prototype object -PASS PaymentAddress interface: existence and properties of interface prototype object's "constructor" property -PASS PaymentAddress interface: operation toJSON() -FAIL Test default toJSON operation of PaymentAddress Illegal invocation -PASS PaymentAddress interface: attribute country -PASS PaymentAddress interface: attribute addressLine -PASS PaymentAddress interface: attribute region -PASS PaymentAddress interface: attribute city -PASS PaymentAddress interface: attribute dependentLocality -PASS PaymentAddress interface: attribute postalCode -PASS PaymentAddress interface: attribute sortingCode -PASS PaymentAddress interface: attribute languageCode -PASS PaymentAddress interface: attribute organization -PASS PaymentAddress interface: attribute recipient -PASS PaymentAddress interface: attribute phone -PASS PaymentResponse interface: existence and properties of interface object -PASS PaymentResponse interface object length -PASS PaymentResponse interface object name -PASS PaymentResponse interface: existence and properties of interface prototype object -PASS PaymentResponse interface: existence and properties of interface prototype object's "constructor" property -PASS PaymentResponse interface: operation toJSON() -FAIL Test default toJSON operation of PaymentResponse Illegal invocation -PASS PaymentResponse interface: attribute requestId -PASS PaymentResponse interface: attribute methodName -PASS PaymentResponse interface: attribute details -PASS PaymentResponse interface: attribute shippingAddress -PASS PaymentResponse interface: attribute shippingOption -PASS PaymentResponse interface: attribute payerName -PASS PaymentResponse interface: attribute payerEmail -PASS PaymentResponse interface: attribute payerPhone -PASS PaymentResponse interface: operation complete(PaymentComplete) -PASS PaymentRequestUpdateEvent interface: existence and properties of interface object -PASS PaymentRequestUpdateEvent interface object length -PASS PaymentRequestUpdateEvent interface object name -PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object -PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object's "constructor" property -PASS PaymentRequestUpdateEvent interface: operation updateWith([object Object]) -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/shipping-address-changed-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/shipping-address-changed-manual.https.html new file mode 100644 index 0000000..787af96b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/shipping-address-changed-manual.https.html
@@ -0,0 +1,77 @@ +<!DOCTYPE html> +<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<meta charset="utf-8"> +<title>Test for PaymentRequest shippingAddress attribute</title> +<link rel="help" href="https://w3c.github.io/payment-request/#shippingaddress-attribute"> +<link rel="help" href="https://w3c.github.io/payment-request/#onshippingaddresschange-attribute"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ explicit_done: true, explicit_timeout: true }); +const validMethod = Object.freeze({ supportedMethods: "basic-card" }); +const validMethods = Object.freeze([validMethod]); +const validAmount = Object.freeze({ currency: "USD", value: "5.00" }); +const validTotal = Object.freeze({ + label: "label", + amount: validAmount, +}); +const validShippingOption = Object.freeze({ + id: "valid", + label: "Shipping Option", + amount: validAmount, + selected: false, +}); +const validDetails = Object.freeze({ + total: validTotal, + shippingOptions: [validShippingOption], +}); +const requestShipping = Object.freeze({ + requestShipping: true, +}); + +function testShippingAddressChange() { + promise_test(async t => { + const request = new PaymentRequest( + validMethods, + validDetails, + requestShipping + ); + assert_equals( + request.shippingAddress, + null, + "request.shippingAddress must initially be null" + ); + const listenerPromise = new Promise(resolve => { + request.addEventListener("shippingaddresschange", () => { + resolve(request.shippingAddress); + }); + }); + const handlerPromise = new Promise(resolve => { + request.onshippingaddresschange = () => { + resolve(request.shippingAddress); + }; + }); + request.show().catch(err => err); + const results = await Promise.all([listenerPromise, handlerPromise]); + assert_true( + results.every(obj => obj instanceof PaymentAddress), + "Expected instances of PaymentAddress" + ); + await request.abort(); + }); + done(); +} + +</script> + +<h2>PaymentRequest shippingAddress attribute</h2> +<p> + When the payment sheet is presented, enter or select a shipping address. +</p> +<ol> + <li> + <button onclick="testShippingAddressChange()"> + When the shipping address is manually changed, request.shippingAddress is a PaymentAddress. + </button> + </li> +</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness-expected.txt deleted file mode 100644 index bc8ea6c..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness-expected.txt +++ /dev/null
@@ -1,37 +0,0 @@ -This is a testharness.js-based test. -PASS Performance interface: operation getEntries(PerformanceEntryFilterOptions) -PASS Performance interface: operation getEntriesByType(DOMString) -PASS Performance interface: operation getEntriesByName(DOMString, DOMString) -PASS Performance interface: window.performance must inherit property "getEntries(PerformanceEntryFilterOptions)" with the proper type -PASS Performance interface: calling getEntries(PerformanceEntryFilterOptions) on window.performance with too few arguments must throw TypeError -PASS Performance interface: window.performance must inherit property "getEntriesByType(DOMString)" with the proper type -PASS Performance interface: calling getEntriesByType(DOMString) on window.performance with too few arguments must throw TypeError -PASS Performance interface: window.performance must inherit property "getEntriesByName(DOMString, DOMString)" with the proper type -PASS Performance interface: calling getEntriesByName(DOMString, DOMString) on window.performance with too few arguments must throw TypeError -PASS PerformanceEntry interface: existence and properties of interface object -PASS PerformanceEntry interface object length -PASS PerformanceEntry interface object name -PASS PerformanceEntry interface: existence and properties of interface prototype object -PASS PerformanceEntry interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceEntry interface: attribute name -PASS PerformanceEntry interface: attribute entryType -PASS PerformanceEntry interface: attribute startTime -PASS PerformanceEntry interface: attribute duration -FAIL PerformanceEntry interface: operation toJSON() Type DOMHighResTimeStamp not found -PASS PerformanceObserverEntryList interface: existence and properties of interface object -PASS PerformanceObserverEntryList interface object length -PASS PerformanceObserverEntryList interface object name -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object -PASS PerformanceObserverEntryList interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserverEntryList interface: operation getEntries(PerformanceEntryFilterOptions) -PASS PerformanceObserverEntryList interface: operation getEntriesByType(DOMString) -PASS PerformanceObserverEntryList interface: operation getEntriesByName(DOMString, DOMString) -PASS PerformanceObserver interface: existence and properties of interface object -PASS PerformanceObserver interface object length -PASS PerformanceObserver interface object name -PASS PerformanceObserver interface: existence and properties of interface prototype object -PASS PerformanceObserver interface: existence and properties of interface prototype object's "constructor" property -PASS PerformanceObserver interface: operation observe(PerformanceObserverInit) -PASS PerformanceObserver interface: operation disconnect() -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js index 5ba69890f..a3bc373b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -332,7 +332,7 @@ */ var idlType = type.idlType; - + if (type.generic == "Promise") { return false; } // nullable and annotated types don't need to be handled separately, @@ -392,9 +392,12 @@ default: var thing = this.members[idlType]; if (!thing) { throw new Error("Type " + idlType + " not found"); } - if (thing instanceof IdlEnum) { return true; } + if (thing instanceof IdlTypedef) { + return this.is_json_type(thing.idlType); + } + // dictionaries where all of their members are JSON types if (thing instanceof IdlDictionary) { var stack = thing.get_inheritance_stack(); @@ -407,7 +410,7 @@ } return Array.from(map.values()).every(this.is_json_type, this); } - + // interface types that have a toJSON operation declared on themselves or // one of their inherited or consequential interfaces. if (thing instanceof IdlInterface) { @@ -930,7 +933,7 @@ * and B.get_inheritance_stack() should return [B, C]. * * Note: as dictionary inheritance is expressed identically by the AST, - * this works just as well for getting a stack of inherited dictionaries. + * this works just as well for getting a stack of inherited dictionaries. */ var stack = [this]; @@ -1788,10 +1791,6 @@ })), "property has wrong .length"); - if (member.is_to_json_regular_operation()) { - this.test_to_json_operation(memberHolderObject, member); - } - // Make some suitable arguments var args = member.arguments.map(function(arg) { return create_suitable_object(arg.idlType); @@ -1854,7 +1853,7 @@ test(function() { var json = memberHolderObject.toJSON(); map.forEach(function(type, k) { - assert_true(k in json, "property " + k + " should be present in the output of " + this.name + ".prototype.toJSON()"); + assert_true(k in json, "property " + JSON.stringify(k) + " should be present in the output of " + this.name + ".prototype.toJSON()"); var descriptor = Object.getOwnPropertyDescriptor(json, k); assert_true(descriptor.writable, "property " + k + " should be writable"); assert_true(descriptor.configurable, "property " + k + " should be configurable"); @@ -1863,7 +1862,7 @@ delete json[k]; }, this); for (var k in json) { - assert_unreached("property " + k + " should not be present in the output of " + this.name + ".prototype.toJSON()"); + assert_unreached("property " + JSON.stringify(k) + " should not be present in the output of " + this.name + ".prototype.toJSON()"); } }.bind(this), "Test default toJSON operation of " + this.name); } else { @@ -2065,6 +2064,7 @@ : "object"; this.test_primary_interface_of(desc, obj, exception, expected_typeof); + var current_interface = this; while (current_interface) { @@ -2281,6 +2281,10 @@ } }.bind(this)); } + + if (member.is_to_json_regular_operation()) { + this.test_to_json_operation(obj, member); + } } };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html index 57f714b..42f9dd52 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlArray/is_json_type.html
@@ -179,6 +179,16 @@ idl.add_untested_idls('interface Foo : Bar { };'); assert_throws(new Error(), _ => idl.is_json_type(typeFrom("Foo"))); }, "should throw for interfaces which inherit from another interface which wasn't added to the IdlArray"); + + test(function() { + var idl = new IdlArray(); + assert_true(idl.is_json_type(typedefFrom("typedef double DOMHighResTimeStamp;").idlType)); + }, 'should return true for typedefs whose source type is a JSON type'); + + test(function() { + var idl = new IdlArray(); + assert_false(idl.is_json_type(typedefFrom("typedef DataView DOMHighResTimeStamp;").idlType)); + }, 'should return false for typedefs whose source type is not a JSON type'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html index b91f3ee..2dd9371 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
@@ -13,11 +13,15 @@ <script> "use strict"; function wrap(obj) { - return { - toJSON: function() { - return obj; - } + function F(obj) { + this._obj = obj; } + + F.prototype.toJSON = function() { + return this._obj; + } + + return new F(obj); } var i, obj; @@ -113,21 +117,21 @@ "status_string": "FAIL" }, { - "message": "assert_unreached: property bar should not be present in the output of C.prototype.toJSON() Reached unreachable code", + "message": "assert_unreached: property \"bar\" should not be present in the output of C.prototype.toJSON() Reached unreachable code", "name": "Test default toJSON operation of C", "properties": {}, "stack": "(implementation-defined)", "status_string": "FAIL" }, { - "message": "assert_true: property foo should be present in the output of D.prototype.toJSON() expected true got false", + "message": "assert_true: property \"foo\" should be present in the output of D.prototype.toJSON() expected true got false", "name": "Test default toJSON operation of D", "properties": {}, "stack": "(implementation-defined)", "status_string": "FAIL" }, { - "message": "assert_unreached: property baz should not be present in the output of E.prototype.toJSON() Reached unreachable code", + "message": "assert_unreached: property \"baz\" should not be present in the output of E.prototype.toJSON() Reached unreachable code", "name": "Test default toJSON operation of E", "properties": {}, "stack": "(implementation-defined)",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js index a8484af..2b73527f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/test/tests/idlharness/helper.js
@@ -1,5 +1,6 @@ "use strict"; +var typedefFrom = interfaceFrom; var dictionaryFrom = interfaceFrom; function interfaceFrom(i) { var idl = new IdlArray();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt new file mode 100644 index 0000000..ea6241c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt
@@ -0,0 +1,51 @@ +This is a testharness.js-based test. +FAIL insecure/same-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/same-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/same-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS insecure/same-origin => secure/same-origin image +PASS insecure/same-origin => secure/same-origin image in <iframe srcdoc> +PASS insecure/same-origin => secure/same-origin image in <iframe> +FAIL insecure/same-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/same-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/same-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS insecure/same-origin => secure/cross-origin image +PASS insecure/same-origin => secure/cross-origin image in <iframe srcdoc> +PASS insecure/same-origin => secure/cross-origin image in <iframe> +FAIL secure/same-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/same-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/same-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS secure/same-origin => secure/same-origin image +PASS secure/same-origin => secure/same-origin image in <iframe srcdoc> +PASS secure/same-origin => secure/same-origin image in <iframe> +FAIL secure/same-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/same-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/same-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS secure/same-origin => secure/cross-origin image +PASS secure/same-origin => secure/cross-origin image in <iframe srcdoc> +PASS secure/same-origin => secure/cross-origin image in <iframe> +FAIL insecure/cross-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/cross-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/cross-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS insecure/cross-origin => secure/same-origin image +PASS insecure/cross-origin => secure/same-origin image in <iframe srcdoc> +PASS insecure/cross-origin => secure/same-origin image in <iframe> +FAIL insecure/cross-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/cross-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL insecure/cross-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS insecure/cross-origin => secure/cross-origin image +PASS insecure/cross-origin => secure/cross-origin image in <iframe srcdoc> +PASS insecure/cross-origin => secure/cross-origin image in <iframe> +FAIL secure/cross-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/cross-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/cross-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS secure/cross-origin => secure/same-origin image +PASS secure/cross-origin => secure/same-origin image in <iframe srcdoc> +PASS secure/cross-origin => secure/same-origin image in <iframe> +FAIL secure/cross-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/cross-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +FAIL secure/cross-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code +PASS secure/cross-origin => secure/cross-origin image +PASS secure/cross-origin => secure/cross-origin image in <iframe srcdoc> +PASS secure/cross-origin => secure/cross-origin image in <iframe> +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt index b4b01b2..0540d48 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 74 tests; 72 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 75 tests; 72 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS URL interface: existence and properties of interface object PASS URL interface object length PASS URL interface object name @@ -35,6 +35,7 @@ PASS URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type FAIL URL interface: new URL("http://foo") must inherit property "toJSON()" with the proper type assert_inherits: property "toJSON" not found in prototype chain +FAIL Test toJSON operation of URL memberHolderObject.toJSON is not a function PASS URLSearchParams interface: existence and properties of interface object PASS URLSearchParams interface object length PASS URLSearchParams interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt index b4b01b2..0540d48 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 74 tests; 72 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 75 tests; 72 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS URL interface: existence and properties of interface object PASS URL interface object length PASS URL interface object name @@ -35,6 +35,7 @@ PASS URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type FAIL URL interface: new URL("http://foo") must inherit property "toJSON()" with the proper type assert_inherits: property "toJSON" not found in prototype chain +FAIL Test toJSON operation of URL memberHolderObject.toJSON is not a function PASS URLSearchParams interface: existence and properties of interface object PASS URLSearchParams interface object length PASS URLSearchParams interface object name
diff --git a/third_party/WebKit/Source/core/css/StyleElement.cpp b/third_party/WebKit/Source/core/css/StyleElement.cpp index ac92b62..484203e 100644 --- a/third_party/WebKit/Source/core/css/StyleElement.cpp +++ b/third_party/WebKit/Source/core/css/StyleElement.cpp
@@ -50,9 +50,11 @@ registered_as_candidate_(false), start_position_(TextPosition::BelowRangePosition()) { if (created_by_parser && document && - document->GetScriptableDocumentParser() && !document->IsInDocumentWrite()) + document->GetScriptableDocumentParser() && + !document->IsInDocumentWrite()) { start_position_ = document->GetScriptableDocumentParser()->GetTextPosition(); + } } StyleElement::~StyleElement() {} @@ -110,9 +112,10 @@ void StyleElement::ClearSheet(Element& owner_element) { DCHECK(sheet_); - if (sheet_->IsLoading()) + if (sheet_->IsLoading()) { owner_element.GetDocument().GetStyleEngine().RemovePendingSheet( owner_element, style_engine_context_); + } sheet_.Release()->ClearOwnerNode(); }
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.cpp b/third_party/WebKit/Source/core/css/StyleEngine.cpp index 1e23da0..4f6ad2e6 100644 --- a/third_party/WebKit/Source/core/css/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/css/StyleEngine.cpp
@@ -100,9 +100,10 @@ StyleSheetCollectionMap::AddResult result = style_sheet_collection_map_.insert(&tree_scope, nullptr); - if (result.is_new_entry) + if (result.is_new_entry) { result.stored_value->value = new ShadowTreeStyleSheetCollection(ToShadowRoot(tree_scope)); + } return *result.stored_value->value.Get(); } @@ -607,13 +608,15 @@ void StyleEngine::CollectScopedStyleFeaturesTo(RuleFeatureSet& features) const { HeapHashSet<Member<const StyleSheetContents>> visited_shared_style_sheet_contents; - if (GetDocument().GetScopedStyleResolver()) + if (GetDocument().GetScopedStyleResolver()) { GetDocument().GetScopedStyleResolver()->CollectFeaturesTo( features, visited_shared_style_sheet_contents); + } for (TreeScope* tree_scope : active_tree_scopes_) { - if (ScopedStyleResolver* resolver = tree_scope->GetScopedStyleResolver()) + if (ScopedStyleResolver* resolver = tree_scope->GetScopedStyleResolver()) { resolver->CollectFeaturesTo(features, visited_shared_style_sheet_contents); + } } } @@ -780,14 +783,16 @@ if (element.HasClass()) { const SpaceSplitString& class_names = element.ClassNames(); - for (size_t i = 0; i < class_names.size(); i++) + for (size_t i = 0; i < class_names.size(); i++) { features.CollectSiblingInvalidationSetForClass( invalidation_lists, element, class_names[i], min_direct_adjacent); + } } - for (const Attribute& attribute : element.Attributes()) + for (const Attribute& attribute : element.Attributes()) { features.CollectSiblingInvalidationSetForAttribute( invalidation_lists, element, attribute.GetName(), min_direct_adjacent); + } features.CollectUniversalSiblingInvalidationSet(invalidation_lists, min_direct_adjacent); @@ -813,9 +818,11 @@ 1); for (unsigned i = 1; before_element && i <= affected_siblings; - i++, before_element = ElementTraversal::PreviousSibling(*before_element)) + i++, before_element = + ElementTraversal::PreviousSibling(*before_element)) { ScheduleSiblingInvalidationsForElement(*before_element, *scheduling_parent, i); + } } void StyleEngine::ScheduleInvalidationsForRemovedSibling( @@ -835,9 +842,11 @@ 1); for (unsigned i = 1; before_element && i <= affected_siblings; - i++, before_element = ElementTraversal::PreviousSibling(*before_element)) + i++, before_element = + ElementTraversal::PreviousSibling(*before_element)) { ScheduleSiblingInvalidationsForElement(*before_element, *scheduling_parent, i); + } } void StyleEngine::ScheduleNthPseudoInvalidations(ContainerNode& nth_parent) { @@ -860,18 +869,21 @@ InvalidationLists invalidation_lists; for (const auto& rule_set : rule_sets) { - if (!id.IsNull()) + if (!id.IsNull()) { rule_set->Features().CollectInvalidationSetsForId(invalidation_lists, element, id); + } if (class_names) { unsigned class_name_count = class_names->size(); - for (size_t i = 0; i < class_name_count; i++) + for (size_t i = 0; i < class_name_count; i++) { rule_set->Features().CollectInvalidationSetsForClass( invalidation_lists, element, (*class_names)[i]); + } } - for (const Attribute& attribute : element.Attributes()) + for (const Attribute& attribute : element.Attributes()) { rule_set->Features().CollectInvalidationSetsForAttribute( invalidation_lists, element, attribute.GetName()); + } } style_invalidator_.ScheduleInvalidationSetsForNode(invalidation_lists, element); @@ -881,9 +893,10 @@ ContainerNode& node, const HeapHashSet<Member<RuleSet>>& rule_sets) { InvalidationLists invalidation_lists; - for (const auto& rule_set : rule_sets) + for (const auto& rule_set : rule_sets) { rule_set->Features().CollectTypeRuleInvalidationSet(invalidation_lists, node); + } DCHECK(invalidation_lists.siblings.IsEmpty()); style_invalidator_.ScheduleInvalidationSetsForNode(invalidation_lists, node); @@ -906,10 +919,11 @@ void StyleEngine::InvalidateSlottedElements(HTMLSlotElement& slot) { for (auto& node : slot.GetDistributedNodes()) { - if (node->IsElementNode()) + if (node->IsElementNode()) { node->SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create( StyleChangeReason::kStyleSheetChange)); + } } } @@ -1163,11 +1177,12 @@ const MediaQueryEvaluator& StyleEngine::EnsureMediaQueryEvaluator() { if (!media_query_evaluator_) { - if (GetDocument().GetFrame()) + if (GetDocument().GetFrame()) { media_query_evaluator_ = new MediaQueryEvaluator(GetDocument().GetFrame()); - else + } else { media_query_evaluator_ = new MediaQueryEvaluator("all"); + } } return *media_query_evaluator_; }
diff --git a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp index 7ea6d68..356cf4e 100644 --- a/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp +++ b/third_party/WebKit/Source/core/dom/FirstLetterPseudoElement.cpp
@@ -109,11 +109,12 @@ // If we are looking at a first letter element then we need to find the // first letter text layoutObject from the parent node, and not ourselves. - if (element.IsFirstLetterPseudoElement()) + if (element.IsFirstLetterPseudoElement()) { parent_layout_object = element.ParentOrShadowHostElement()->GetLayoutObject(); - else + } else { parent_layout_object = element.GetLayoutObject(); + } if (!parent_layout_object || !parent_layout_object->Style()->HasPseudoStyle(kPseudoIdFirstLetter) || @@ -240,10 +241,11 @@ // The text fragment we get our content from is being destroyed. We need // to tell our parent element to recalcStyle so we can get cleaned up // as well. - if (!fragment) + if (!fragment) { SetNeedsStyleRecalc( kLocalStyleChange, StyleChangeReasonForTracing::Create(StyleChangeReason::kPseudoClass)); + } remaining_text_layout_object_ = fragment; }