diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/blink/renderer/core/loader/resource | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/loader/resource')
19 files changed, 249 insertions, 457 deletions
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc index 9a89f9b5747..238f528f9dc 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc @@ -88,7 +88,7 @@ void CSSStyleSheetResource::SetParsedStyleSheetCache( UpdateDecodedSize(); } -void CSSStyleSheetResource::Trace(Visitor* visitor) { +void CSSStyleSheetResource::Trace(Visitor* visitor) const { visitor->Trace(parsed_style_sheet_cache_); TextResource::Trace(visitor); } diff --git a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h index c863f63f94b..d72509a4df8 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h @@ -55,7 +55,7 @@ class CORE_EXPORT CSSStyleSheetResource final : public TextResource { const TextResourceDecoderOptions&); ~CSSStyleSheetResource() override; - void Trace(Visitor*) override; + void Trace(Visitor*) const override; void OnMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) const override; diff --git a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc index cc2a29ff02a..f558a840c2f 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc @@ -151,7 +151,8 @@ TEST_F(CSSStyleSheetResourceTest, contents->CheckLoaded(); EXPECT_TRUE(contents->IsCacheableForResource()); - contents->EnsureRuleSet(MediaQueryEvaluator(), kRuleHasNoSpecialState); + contents->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame()), + kRuleHasNoSpecialState); EXPECT_TRUE(contents->HasRuleSet()); css_resource->SaveParsedStyleSheet(contents); diff --git a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc index 53320e7669b..5f4a0f2d1cf 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc @@ -117,10 +117,16 @@ scoped_refptr<FontCustomPlatformData> FontResource::GetCustomFontData() { if (Data()) font_data_ = FontCustomPlatformData::Create(Data(), ots_parsing_message_); - if (!font_data_) + if (!font_data_) { SetStatus(ResourceStatus::kDecodeError); - else + } else { + // Call observers once and remove them. + HeapHashSet<WeakMember<FontResourceClearDataObserver>> observers; + observers.swap(clear_data_observers_); + for (const auto& observer : observers) + observer->FontResourceDataWillBeCleared(); ClearData(); + } } return font_data_; } @@ -206,4 +212,14 @@ void FontResource::OnMemoryDump(WebMemoryDumpLevelOfDetail level, memory_dump->AddSuballocation(dump->Guid(), "malloc"); } +void FontResource::AddClearDataObserver( + FontResourceClearDataObserver* observer) const { + clear_data_observers_.insert(observer); +} + +void FontResource::Trace(Visitor* visitor) const { + visitor->Trace(clear_data_observers_); + Resource::Trace(visitor); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h index 713dc38d4c0..b2f096bba34 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.h @@ -42,6 +42,16 @@ class ResourceFetcher; class FontCustomPlatformData; class FontResourceClient; +// An observer that will be notified when original data is cleared +// from the resource. Inspector may collect this data and store it for +// future inspection. +class CORE_EXPORT FontResourceClearDataObserver : public GarbageCollectedMixin { + public: + // Called before the original data is cleared. Only called once, + // and observer is automatically removed. + virtual void FontResourceDataWillBeCleared() = 0; +}; + class CORE_EXPORT FontResource final : public Resource { public: static FontResource* Fetch(FetchParameters&, @@ -50,6 +60,7 @@ class CORE_EXPORT FontResource final : public Resource { FontResource(const ResourceRequest&, const ResourceLoaderOptions&); ~FontResource() override; + void Trace(Visitor*) const override; void DidAddClient(ResourceClient*) override; @@ -71,6 +82,8 @@ class CORE_EXPORT FontResource final : public Resource { void OnMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) const override; + void AddClearDataObserver(FontResourceClearDataObserver* observer) const; + private: class FontResourceFactory : public NonTextResourceFactory { public: @@ -103,6 +116,8 @@ class CORE_EXPORT FontResource final : public Resource { bool cors_failed_; TaskHandle font_load_short_limit_; TaskHandle font_load_long_limit_; + mutable HeapHashSet<WeakMember<FontResourceClearDataObserver>> + clear_data_observers_; friend class MemoryCache; FRIEND_TEST_ALL_PREFIXES(CacheAwareFontResourceTest, CacheAwareFontLoading); diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc index 96def6caf44..878dcb69bbe 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc @@ -78,7 +78,7 @@ class ImageResource::ImageResourceInfoImpl final : resource_(resource) { DCHECK(resource_); } - void Trace(Visitor* visitor) override { + void Trace(Visitor* visitor) const override { visitor->Trace(resource_); ImageResourceInfo::Trace(visitor); } @@ -230,7 +230,7 @@ void ImageResource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail, dump->AddScalar("size", "bytes", content_->GetImage()->Data()->size()); } -void ImageResource::Trace(Visitor* visitor) { +void ImageResource::Trace(Visitor* visitor) const { visitor->Trace(multipart_parser_); visitor->Trace(content_); Resource::Trace(visitor); diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h index 557800e494d..ca847b311a3 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.h @@ -102,7 +102,7 @@ class CORE_EXPORT ImageResource final void OnMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) const override; - void Trace(Visitor*) override; + void Trace(Visitor*) const override; private: enum class MultipartParsingState : uint8_t { diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc index 3f5e21f8f29..efa24670f1a 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc @@ -36,7 +36,9 @@ class NullImageResourceInfo final public: NullImageResourceInfo() = default; - void Trace(Visitor* visitor) override { ImageResourceInfo::Trace(visitor); } + void Trace(Visitor* visitor) const override { + ImageResourceInfo::Trace(visitor); + } private: const KURL& Url() const override { return url_; } @@ -103,7 +105,7 @@ void ImageResourceContent::SetImageResourceInfo(ImageResourceInfo* info) { info_ = info; } -void ImageResourceContent::Trace(Visitor* visitor) { +void ImageResourceContent::Trace(Visitor* visitor) const { visitor->Trace(info_); ImageObserver::Trace(visitor); } diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h index 72db3c60520..f041f4441e6 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h @@ -39,8 +39,6 @@ class ResourceResponse; // https://docs.google.com/document/d/1O-fB83mrE0B_V8gzXNqHgmRLCvstTB4MMi3RnVLr8bE/edit?usp=sharing // TODO(hiroshige): Make ImageResourceContent ResourceClient and remove the // word 'observer' from ImageResource. -// TODO(hiroshige): Rename local variables of type ImageResourceContent to -// e.g. |imageContent|. Currently they have Resource-like names. class CORE_EXPORT ImageResourceContent final : public GarbageCollected<ImageResourceContent>, public ImageObserver { @@ -84,7 +82,7 @@ class CORE_EXPORT ImageResourceContent final return size_available_ != Image::kSizeUnavailable; } - void Trace(Visitor*) override; + void Trace(Visitor*) const override; // Content status and deriving predicates. // https://docs.google.com/document/d/1O-fB83mrE0B_V8gzXNqHgmRLCvstTB4MMi3RnVLr8bE/edit#heading=h.6cyqmir0f30h diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h index b3a105a6b7c..dd3b101afc4 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_info.h @@ -58,7 +58,7 @@ class CORE_EXPORT ImageResourceInfo : public GarbageCollectedMixin { virtual bool IsAdResource() const = 0; - void Trace(Visitor* visitor) override {} + void Trace(Visitor* visitor) const override {} }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc index a960dd7d1d6..814e5fd4bfe 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc @@ -379,7 +379,7 @@ class MockFinishObserver : public ResourceFinishObserver { MOCK_METHOD0(NotifyFinished, void()); String DebugName() const override { return "MockFinishObserver"; } - void Trace(Visitor* visitor) override { + void Trace(Visitor* visitor) const override { blink::ResourceFinishObserver::Trace(visitor); } diff --git a/chromium/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc deleted file mode 100644 index 8baa208a419..00000000000 --- a/chromium/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/loader/resource/link_fetch_resource.h" - -#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h" -#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" - -namespace blink { - -Resource* LinkFetchResource::Fetch(ResourceType type, - FetchParameters& params, - ResourceFetcher* fetcher) { - DCHECK_EQ(type, ResourceType::kLinkPrefetch); - return fetcher->RequestResource(params, LinkResourceFactory(type), nullptr); -} - -LinkFetchResource::LinkFetchResource(const ResourceRequest& request, - ResourceType type, - const ResourceLoaderOptions& options) - : Resource(request, type, options) {} - -LinkFetchResource::~LinkFetchResource() = default; - -} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/loader/resource/link_fetch_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/link_fetch_resource.h deleted file mode 100644 index 0b190ff4b6b..00000000000 --- a/chromium/third_party/blink/renderer/core/loader/resource/link_fetch_resource.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LINK_FETCH_RESOURCE_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LINK_FETCH_RESOURCE_H_ - -#include "third_party/blink/renderer/platform/loader/fetch/resource.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h" - -namespace blink { - -class FetchParameters; -class ResourceFetcher; - -class LinkFetchResource final : public Resource { - public: - static Resource* Fetch(ResourceType, FetchParameters&, ResourceFetcher*); - - LinkFetchResource(const ResourceRequest&, - ResourceType, - const ResourceLoaderOptions&); - ~LinkFetchResource() override; - - private: - class LinkResourceFactory : public NonTextResourceFactory { - public: - explicit LinkResourceFactory(ResourceType type) - : NonTextResourceFactory(type) {} - - Resource* Create(const ResourceRequest& request, - const ResourceLoaderOptions& options) const override { - return MakeGarbageCollected<LinkFetchResource>(request, GetType(), - options); - } - }; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LINK_FETCH_RESOURCE_H_ diff --git a/chromium/third_party/blink/renderer/core/loader/resource/link_prefetch_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/link_prefetch_resource.cc new file mode 100644 index 00000000000..6f03e210cbd --- /dev/null +++ b/chromium/third_party/blink/renderer/core/loader/resource/link_prefetch_resource.cc @@ -0,0 +1,33 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/loader/resource/link_prefetch_resource.h" + +#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" + +namespace blink { + +Resource* LinkPrefetchResource::Fetch(FetchParameters& params, + ResourceFetcher* fetcher) { + return fetcher->RequestResource(params, Factory(), nullptr); +} + +LinkPrefetchResource::LinkPrefetchResource(const ResourceRequest& request, + const ResourceLoaderOptions& options) + : Resource(request, ResourceType::kLinkPrefetch, options) {} + +LinkPrefetchResource::~LinkPrefetchResource() = default; + +LinkPrefetchResource::Factory::Factory() + : NonTextResourceFactory(ResourceType::kLinkPrefetch) {} + +Resource* LinkPrefetchResource::Factory::Create( + const ResourceRequest& request, + const ResourceLoaderOptions& options) const { + return MakeGarbageCollected<LinkPrefetchResource>(request, options); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/loader/resource/link_prefetch_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/link_prefetch_resource.h new file mode 100644 index 00000000000..04ca1b72645 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/loader/resource/link_prefetch_resource.h @@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LINK_PREFETCH_RESOURCE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LINK_PREFETCH_RESOURCE_H_ + +#include "third_party/blink/renderer/platform/loader/fetch/resource.h" + +namespace blink { + +class FetchParameters; +class ResourceFetcher; + +// This is the implementation of Resource for <link rel='prefetch'>. +class LinkPrefetchResource final : public Resource { + public: + static Resource* Fetch(FetchParameters&, ResourceFetcher*); + + LinkPrefetchResource(const ResourceRequest&, const ResourceLoaderOptions&); + ~LinkPrefetchResource() override; + + private: + class Factory final : public NonTextResourceFactory { + public: + Factory(); + + Resource* Create(const ResourceRequest& request, + const ResourceLoaderOptions& options) const override; + }; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LINK_PREFETCH_RESOURCE_H_ diff --git a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.cc b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.cc index 385afece9ba..b4cc463f97e 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.cc @@ -184,7 +184,7 @@ wtf_size_t MultipartImageResourceParser::FindBoundary(const Vector<char>& data, return boundary_position; } -void MultipartImageResourceParser::Trace(Visitor* visitor) { +void MultipartImageResourceParser::Trace(Visitor* visitor) const { visitor->Trace(client_); } diff --git a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h index b41f34b18c3..94ef1df10dd 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h @@ -58,7 +58,7 @@ class CORE_EXPORT MultipartImageResourceParser final virtual ~Client() = default; virtual void OnePartInMultipartReceived(const ResourceResponse&) = 0; virtual void MultipartDataReceived(const char* bytes, size_t) = 0; - void Trace(Visitor* visitor) override {} + void Trace(Visitor* visitor) const override {} }; MultipartImageResourceParser(const ResourceResponse&, @@ -68,7 +68,7 @@ class CORE_EXPORT MultipartImageResourceParser final void Finish(); void Cancel() { is_cancelled_ = true; } - void Trace(Visitor*); + void Trace(Visitor*) const; static wtf_size_t SkippableLengthForTest(const Vector<char>& data, wtf_size_t size) { diff --git a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc index 4b30c7c7ede..ac30a12e584 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc +++ b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc @@ -80,29 +80,8 @@ ScriptResource* ScriptResource::Fetch(FetchParameters& params, StreamingAllowed streaming_allowed) { DCHECK(IsRequestContextSupported( params.GetResourceRequest().GetRequestContext())); - ScriptResource* resource = ToScriptResource( - fetcher->RequestResource(params, ScriptResourceFactory(), client)); - - if (streaming_allowed == kAllowStreaming) { - // Start streaming the script as soon as we get it. - resource->StartStreaming(fetcher->GetTaskRunner()); - } else { - // Advance the |streaming_state_| to kStreamingNotAllowed by calling - // SetClientIsWaitingForFinished unless it is explicitly allowed.' - // - // Do this in a task rather than directly to make sure that we don't call - // the finished callbacks of other clients synchronously. - - // TODO(leszeks): Previous behaviour, without script streaming, was to - // synchronously notify the given client, with the assumption that other - // clients were already finished. If this behaviour becomes necessary, we - // would have to either check that streaming wasn't started (if that would - // be a logic error), or cancel any existing streaming. - fetcher->GetTaskRunner()->PostTask( - FROM_HERE, WTF::Bind(&ScriptResource::SetClientIsWaitingForFinished, - WrapWeakPersistent(resource))); - } - + ScriptResource* resource = ToScriptResource(fetcher->RequestResource( + params, ScriptResourceFactory(streaming_allowed), client)); return resource; } @@ -114,32 +93,36 @@ ScriptResource* ScriptResource::CreateForTest( ResourceLoaderOptions options; TextResourceDecoderOptions decoder_options( TextResourceDecoderOptions::kPlainTextContent, encoding); - return MakeGarbageCollected<ScriptResource>(request, options, - decoder_options); + return MakeGarbageCollected<ScriptResource>(request, options, decoder_options, + kNoStreaming); } ScriptResource::ScriptResource( const ResourceRequest& resource_request, const ResourceLoaderOptions& options, - const TextResourceDecoderOptions& decoder_options) + const TextResourceDecoderOptions& decoder_options, + StreamingAllowed streaming_allowed) : TextResource(resource_request, ResourceType::kScript, options, - decoder_options) {} - -ScriptResource::~ScriptResource() = default; + decoder_options) { + static bool script_streaming_enabled = + base::FeatureList::IsEnabled(features::kScriptStreaming); -void ScriptResource::Prefinalize() { - // Reset and cancel the watcher. This has to be called in the prefinalizer, - // rather than relying on the destructor, as accesses by the watcher of the - // script resource between prefinalization and destruction are invalid. See - // https://crbug.com/905975#c34 for more details. - watcher_.reset(); + if (!script_streaming_enabled) { + DisableStreaming( + ScriptStreamer::NotStreamingReason::kDisabledByFeatureList); + } else if (streaming_allowed == kNoStreaming) { + DisableStreaming(ScriptStreamer::NotStreamingReason::kStreamingDisabled); + } else if (!Url().ProtocolIsInHTTPFamily()) { + DisableStreaming(ScriptStreamer::NotStreamingReason::kNotHTTP); + } } -void ScriptResource::Trace(Visitor* visitor) { +ScriptResource::~ScriptResource() = default; + +void ScriptResource::Trace(Visitor* visitor) const { visitor->Trace(streamer_); - visitor->Trace(response_body_loader_client_); TextResource::Trace(visitor); } @@ -151,7 +134,7 @@ void ScriptResource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail, } const ParkableString& ScriptResource::SourceText() { - CHECK(IsFinishedInternal()); + CHECK(IsLoaded()); if (source_text_.IsNull() && Data()) { String source_text = DecodedText(); @@ -180,19 +163,10 @@ String ScriptResource::TextForInspector() const { } // 2. We have finished loading with no data received, so no streaming ever - // happened or streaming was suppressed. Note that the finished - // notification may not have come through yet because of task posting, so - // NotifyFinished may not have been called yet. Regardless, there was no - // data, so the text should be empty. - // - // TODO(crbug/909858) Currently this CHECK can occasionally fail, but this - // doesn't seem to cause real issues immediately. For now, we suppress the - // crashes on release builds by making this a DCHECK and continue baking the - // script streamer control (crbug/865098) on beta, while investigating the - // failure reason on canary. - DCHECK(!IsFinishedInternal() || !streamer_ || + // happened or streaming was suppressed. + DCHECK(!streamer_ || streamer_->StreamingSuppressedReason() == - ScriptStreamer::kScriptTooSmall); + ScriptStreamer::NotStreamingReason::kScriptTooSmall); return ""; } @@ -225,22 +199,20 @@ void ScriptResource::DestroyDecodedDataForFailedRevalidation() { source_text_ = ParkableString(); // Make sure there's no streaming. DCHECK(!streamer_); - DCHECK_EQ(streaming_state_, StreamingState::kStreamingNotAllowed); + DCHECK_EQ(streaming_state_, StreamingState::kStreamingDisabled); SetDecodedSize(0); } void ScriptResource::SetRevalidatingRequest( const ResourceRequestHead& request) { - CHECK_EQ(streaming_state_, StreamingState::kFinishedNotificationSent); + CHECK(IsLoaded()); if (streamer_) { - CHECK(streamer_->IsStreamingFinished()); + CHECK(streamer_->IsFinished()); streamer_ = nullptr; } // Revalidation requests don't actually load the current Resource, so disable // streaming. - not_streaming_reason_ = ScriptStreamer::kRevalidate; - streaming_state_ = StreamingState::kStreamingNotAllowed; - CheckStreamingState(); + DisableStreaming(ScriptStreamer::NotStreamingReason::kRevalidate); TextResource::SetRevalidatingRequest(request); } @@ -253,7 +225,7 @@ bool ScriptResource::CanUseCacheValidator() const { return false; // Do not revalidate until streaming is complete. - if (!IsFinishedInternal()) + if (!IsLoaded()) return false; return Resource::CanUseCacheValidator(); @@ -262,264 +234,103 @@ bool ScriptResource::CanUseCacheValidator() const { void ScriptResource::ResponseBodyReceived( ResponseBodyLoaderDrainableInterface& body_loader, scoped_refptr<base::SingleThreadTaskRunner> loader_task_runner) { - ResponseBodyLoaderClient* response_body_loader_client; - CHECK(!data_pipe_); - data_pipe_ = body_loader.DrainAsDataPipe(&response_body_loader_client); - if (!data_pipe_) + if (streaming_state_ == StreamingState::kStreamingDisabled) return; - response_body_loader_client_ = response_body_loader_client; - watcher_ = std::make_unique<mojo::SimpleWatcher>( - FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, loader_task_runner); + CHECK_EQ(streaming_state_, StreamingState::kWaitingForDataPipe); - watcher_->Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, - MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, - WTF::BindRepeating(&ScriptResource::OnDataPipeReadable, - WrapWeakPersistent(this))); - CHECK(data_pipe_); + // Checked in the constructor. + CHECK(Url().ProtocolIsInHTTPFamily()); + CHECK(base::FeatureList::IsEnabled(features::kScriptStreaming)); - MojoResult ready_result; - mojo::HandleSignalsState ready_state; - MojoResult rv = watcher_->Arm(&ready_result, &ready_state); - if (rv == MOJO_RESULT_OK) + ResponseBodyLoaderClient* response_body_loader_client; + mojo::ScopedDataPipeConsumerHandle data_pipe = + body_loader.DrainAsDataPipe(&response_body_loader_client); + if (!data_pipe) { + DisableStreaming(ScriptStreamer::NotStreamingReason::kNoDataPipe); return; - - DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); - OnDataPipeReadable(ready_result, ready_state); -} - -void ScriptResource::OnDataPipeReadable(MojoResult result, - const mojo::HandleSignalsState& state) { - switch (result) { - case MOJO_RESULT_OK: - // All good, so read the data that we were notified that we received. - break; - - case MOJO_RESULT_CANCELLED: - // The consumer handle got closed, which means this script resource is - // done loading, and did so without streaming (otherwise the watcher - // wouldn't have been armed, and the handle ownership would have passed to - // the streamer). - CHECK(streaming_state_ == StreamingState::kFinishedNotificationSent || - streaming_state_ == StreamingState::kStreamingNotAllowed); - return; - - case MOJO_RESULT_FAILED_PRECONDITION: - // This means the producer finished and streamed to completion. - watcher_.reset(); - response_body_loader_client_->DidFinishLoadingBody(); - response_body_loader_client_ = nullptr; - return; - - case MOJO_RESULT_SHOULD_WAIT: - NOTREACHED(); - return; - - default: - // Some other error occurred. - watcher_.reset(); - response_body_loader_client_->DidFailLoadingBody(); - response_body_loader_client_ = nullptr; - return; } - CHECK(state.readable()); - CHECK(data_pipe_); - - const void* data; - uint32_t data_size; - MojoReadDataFlags flags_to_pass = MOJO_READ_DATA_FLAG_NONE; - MojoResult begin_read_result = - data_pipe_->BeginReadData(&data, &data_size, flags_to_pass); - // There should be data, so this read should succeed. - CHECK_EQ(begin_read_result, MOJO_RESULT_OK); - - response_body_loader_client_->DidReceiveData( - base::make_span(reinterpret_cast<const char*>(data), data_size)); - - MojoResult end_read_result = data_pipe_->EndReadData(data_size); - - CHECK_EQ(end_read_result, MOJO_RESULT_OK); CheckStreamingState(); - if (streamer_) { - DCHECK_EQ(streaming_state_, StreamingState::kStreaming); - if (streamer_->TryStartStreaming(&data_pipe_, - response_body_loader_client_.Get())) { - CHECK(!data_pipe_); - // This reset will also cancel the watcher. - watcher_.reset(); - return; - } - } + CHECK(!ErrorOccurred()); - // TODO(leszeks): Depending on how small the chunks are, we may want to - // loop until a certain number of bytes are synchronously read rather than - // going back to the scheduler. - watcher_->ArmOrNotify(); + streamer_ = MakeGarbageCollected<ScriptStreamer>( + this, std::move(data_pipe), response_body_loader_client, + v8::ScriptCompiler::kNoCompileOptions, loader_task_runner); + CHECK_EQ(no_streamer_reason_, ScriptStreamer::NotStreamingReason::kInvalid); + AdvanceStreamingState(StreamingState::kStreaming); } void ScriptResource::NotifyFinished() { DCHECK(IsLoaded()); switch (streaming_state_) { - case StreamingState::kCanStartStreaming: - // Do nothing, expect either a StartStreaming() call to transition us to - // kStreaming, or an SetClientIsWaitingForFinished() call to transition us - // into kStreamingNotAllowed. These will then transition again since - // IsLoaded will be true. + case StreamingState::kWaitingForDataPipe: + // We never received a response body, otherwise the state would be + // one of kStreaming or kNoStreaming. So, either there was an error, or + // there was no response body loader (thus no data pipe) at all. Either + // way, we want to disable streaming. + if (ErrorOccurred()) { + DisableStreaming(ScriptStreamer::NotStreamingReason::kErrorOccurred); + } else { + DisableStreaming(ScriptStreamer::NotStreamingReason::kNoDataPipe); + } break; + case StreamingState::kStreaming: - AdvanceStreamingState(StreamingState::kWaitingForStreamingToEnd); DCHECK(streamer_); - streamer_->NotifyFinished(); - // Don't call the base NotifyFinished until streaming finishes too (which - // might happen immediately in the above ScriptStreamer::NotifyFinished - // call) - break; - case StreamingState::kStreamingNotAllowed: - watcher_.reset(); - data_pipe_.reset(); - response_body_loader_client_ = nullptr; - AdvanceStreamingState(StreamingState::kFinishedNotificationSent); - TextResource::NotifyFinished(); + if (!streamer_->IsFinished()) { + // This notification didn't come from the streaming finishing, so it + // must be an external error (e.g. cancelling the resource). + CHECK(ErrorOccurred()); + streamer_->Cancel(); + streamer_.Release(); + DisableStreaming(ScriptStreamer::NotStreamingReason::kErrorOccurred); + } break; - case StreamingState::kWaitingForStreamingToEnd: - case StreamingState::kFinishedNotificationSent: - // Not possible. - CHECK(false); + + case StreamingState::kStreamingDisabled: + // If streaming is already disabled, we can just continue as before. break; } -} - -bool ScriptResource::IsFinishedInternal() const { CheckStreamingState(); - return streaming_state_ == StreamingState::kFinishedNotificationSent; -} - -void ScriptResource::StreamingFinished() { - CHECK(streamer_); - CHECK_EQ(streaming_state_, StreamingState::kWaitingForStreamingToEnd); - CHECK(!data_pipe_ || streamer_->StreamingSuppressed()); - // We may still have a watcher if a) streaming never started (e.g. script too - // small) and b) an external error triggered the finished notification. - watcher_.reset(); - data_pipe_.reset(); - response_body_loader_client_ = nullptr; - AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); } -void ScriptResource::StartStreaming( - scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner) { - CheckStreamingState(); - - if (streamer_) { - return; - } - - if (streaming_state_ != StreamingState::kCanStartStreaming) { - return; - } - - // Don't bother streaming if there was an error, it won't work anyway. - if (ErrorOccurred()) { - return; - } - - static const bool script_streaming_enabled = - base::FeatureList::IsEnabled(features::kScriptStreaming); - if (!script_streaming_enabled) { - return; - } - - CHECK(!IsCacheValidator()); - - streamer_ = - ScriptStreamer::Create(this, loading_task_runner, ¬_streaming_reason_); - if (streamer_) { - AdvanceStreamingState(StreamingState::kStreaming); - - // If there is any data already, send it to the streamer. - if (Data()) { - // Note that we don't need to iterate through the segments of the data, as - // the streamer will do that itself. - CHECK_GT(Data()->size(), 0u); - if (data_pipe_) { - if (streamer_->TryStartStreaming(&data_pipe_, - response_body_loader_client_.Get())) { - CHECK(!data_pipe_); - // This reset will also cancel the watcher. - watcher_.reset(); - } else { - CHECK(data_pipe_); - } - } - } - // If the we're is already loaded, notify the streamer about that too. - if (IsLoaded()) { - AdvanceStreamingState(StreamingState::kWaitingForStreamingToEnd); - - // Do this in a task rather than directly to make sure that we don't call - // the finished callback in the same stack as starting streaming -- this - // can cause issues with the client expecting to be not finished when - // starting streaming (e.g. ClassicPendingScript::IsReady == false), but - // ending up finished by the end of this method. - loading_task_runner->PostTask(FROM_HERE, - WTF::Bind(&ScriptStreamer::NotifyFinished, - WrapPersistent(streamer_.Get()))); - } - } - - CheckStreamingState(); - return; -} - -void ScriptResource::SetClientIsWaitingForFinished() { - // No-op if streaming already started or finished. - CheckStreamingState(); - if (streaming_state_ != StreamingState::kCanStartStreaming) - return; - - AdvanceStreamingState(StreamingState::kStreamingNotAllowed); - not_streaming_reason_ = ScriptStreamer::kStreamingDisabled; - // Trigger the finished notification if needed. - if (IsLoaded()) { - watcher_.reset(); - data_pipe_.reset(); - response_body_loader_client_ = nullptr; - AdvanceStreamingState(StreamingState::kFinishedNotificationSent); - TextResource::NotifyFinished(); - } -} - ScriptStreamer* ScriptResource::TakeStreamer() { - CHECK(IsFinishedInternal()); + CHECK(IsLoaded()); if (!streamer_) return nullptr; ScriptStreamer* streamer = streamer_; + // A second use of the streamer is not possible, so we null it out and disable + // streaming for subsequent uses. streamer_ = nullptr; - not_streaming_reason_ = ScriptStreamer::kSecondScriptResourceUse; + DisableStreaming( + ScriptStreamer::NotStreamingReason::kSecondScriptResourceUse); return streamer; } +void ScriptResource::DisableStreaming( + ScriptStreamer::NotStreamingReason no_streamer_reason) { + CHECK_NE(no_streamer_reason, ScriptStreamer::NotStreamingReason::kInvalid); + if (no_streamer_reason_ != ScriptStreamer::NotStreamingReason::kInvalid) { + // Streaming is already disabled, no need to disable it again. + return; + } + no_streamer_reason_ = no_streamer_reason; + AdvanceStreamingState(StreamingState::kStreamingDisabled); +} + void ScriptResource::AdvanceStreamingState(StreamingState new_state) { switch (streaming_state_) { - case StreamingState::kCanStartStreaming: + case StreamingState::kWaitingForDataPipe: CHECK(new_state == StreamingState::kStreaming || - new_state == StreamingState::kStreamingNotAllowed); + new_state == StreamingState::kStreamingDisabled); break; case StreamingState::kStreaming: - CHECK(streamer_); - CHECK_EQ(new_state, StreamingState::kWaitingForStreamingToEnd); - break; - case StreamingState::kWaitingForStreamingToEnd: - CHECK(streamer_); - CHECK_EQ(new_state, StreamingState::kFinishedNotificationSent); - break; - case StreamingState::kStreamingNotAllowed: - CHECK_EQ(new_state, StreamingState::kFinishedNotificationSent); + CHECK_EQ(new_state, StreamingState::kStreamingDisabled); break; - case StreamingState::kFinishedNotificationSent: + case StreamingState::kStreamingDisabled: CHECK(false); break; } @@ -532,35 +343,21 @@ void ScriptResource::CheckStreamingState() const { // TODO(leszeks): Eventually convert these CHECKs into DCHECKs once the logic // is a bit more baked in. switch (streaming_state_) { - case StreamingState::kCanStartStreaming: + case StreamingState::kWaitingForDataPipe: CHECK(!streamer_); + CHECK_EQ(no_streamer_reason_, + ScriptStreamer::NotStreamingReason::kInvalid); break; case StreamingState::kStreaming: CHECK(streamer_); - CHECK(!streamer_->IsFinished()); - // kStreaming can be entered both when loading (if streaming is started - // before load completes) or when loaded (if streaming is started after - // load completes). In the latter case, the state will almost immediately - // advance to kWaitingForStreamingToEnd. - CHECK(IsLoaded() || IsLoading()); + CHECK(streamer_->CanStartStreaming() || streamer_->IsStreamingStarted() || + streamer_->IsStreamingSuppressed()); + CHECK(IsLoading() || streamer_->IsFinished()); break; - case StreamingState::kWaitingForStreamingToEnd: - CHECK(streamer_); - CHECK(!streamer_->IsFinished()); - CHECK(IsLoaded()); - break; - case StreamingState::kStreamingNotAllowed: + case StreamingState::kStreamingDisabled: CHECK(!streamer_); - // TODO(leszeks): We could CHECK(!IsLoaded()) if not for the immediate - // kCanStartStreaming -> kStreamingNotAllowed -> kFinishedNotificationSent - // transition in SetClientIsWaitingForFinished when IsLoaded. - break; - case StreamingState::kFinishedNotificationSent: - CHECK(!streamer_ || streamer_->IsFinished()); - CHECK(!watcher_ || !watcher_->IsWatching()); - CHECK(!data_pipe_); - CHECK(!response_body_loader_client_); - CHECK(IsLoaded()); + CHECK_NE(no_streamer_reason_, + ScriptStreamer::NotStreamingReason::kInvalid); break; } } diff --git a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h index 791b32f9ac2..1c951a901e7 100644 --- a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h +++ b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h @@ -37,16 +37,11 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h" -namespace mojo { -class SimpleWatcher; -} - namespace blink { class FetchParameters; class KURL; class ResourceFetcher; -class ResponseBodyLoaderClient; class SingleCachedMetadataHandler; // ScriptResource is a resource representing a JavaScript script. It is only @@ -60,19 +55,9 @@ class SingleCachedMetadataHandler; // See also: // https://docs.google.com/document/d/143GOPl_XVgLPFfO-31b_MdBcnjklLEX2OIg_6eN6fQ4 class CORE_EXPORT ScriptResource final : public TextResource { - USING_PRE_FINALIZER(ScriptResource, Prefinalize); - public: - // For scripts fetched with kAllowStreaming, the ScriptResource expects users - // to call StartStreaming to start streaming the loaded data, and - // SetClientIsWaitingForFinished when they actually want the data to be - // available for execute. Note that StartStreaming can fail, so the client of - // an unfinished resource has to call SetClientIsWaitingForFinished to - // guarantee that it receives a finished callback. - // - // Scripts fetched with kNoStreaming will (asynchronously) call - // SetClientIsWaitingForFinished on the resource, so the user does not have to - // call it again. This is effectively the "legacy" behaviour. + // The script resource will always try to start streaming if kAllowStreaming + // is passed in. enum StreamingAllowed { kNoStreaming, kAllowStreaming }; static ScriptResource* Fetch(FetchParameters&, @@ -86,48 +71,21 @@ class CORE_EXPORT ScriptResource final : public TextResource { ScriptResource(const ResourceRequest&, const ResourceLoaderOptions&, - const TextResourceDecoderOptions&); + const TextResourceDecoderOptions&, + StreamingAllowed); ~ScriptResource() override; void ResponseBodyReceived( ResponseBodyLoaderDrainableInterface& body_loader, scoped_refptr<base::SingleThreadTaskRunner> loader_task_runner) override; - void Trace(Visitor*) override; + void Trace(Visitor*) const override; void OnMemoryDump(WebMemoryDumpLevelOfDetail, WebProcessMemoryDump*) const override; void SetSerializedCachedMetadata(mojo_base::BigBuffer data) override; - void StartStreaming( - scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner); - - // State that a client of the script resource will no longer try to start - // streaming, and is now waiting for the resource to call the client's finish - // callback (regardless of whether the resource is finished loading or - // finished streaming). Specifically, it causes the kCanStartStreaming to - // kStreamingNotAllowed transition. Streaming cannot be started after this is - // called. - // - // If the resource is already streaming, this will be a no-op, and the client - // will still only get the finished notification when the streaming completes. - // - // This function should never be called synchronously (except by - // NotifyFinished) as it can trigger all clients' finished callbacks, which in - // turn can invoke JavaScript execution. - // - // TODO(leszeks): Eventually Fetch (with streaming allowed) will be the only - // way of starting streaming, and SetClientIsWaitingForFinished will not be - // part of the public interface. - void SetClientIsWaitingForFinished(); - - // Called (only) by ScriptStreamer when streaming completes. - // - // This function should never be called synchronously as it can trigger all - // clients' finished callbacks, which in turn can invoke JavaScript execution. - void StreamingFinished(); - const ParkableString& SourceText(); // Get the resource's current text. This can return partial data, so should @@ -141,7 +99,7 @@ class CORE_EXPORT ScriptResource final : public TextResource { ScriptStreamer* TakeStreamer(); ScriptStreamer::NotStreamingReason NoStreamerReason() const { - return not_streaming_reason_; + return no_streamer_reason_; } // Used in DCHECKs @@ -160,44 +118,53 @@ class CORE_EXPORT ScriptResource final : public TextResource { // ScriptResources are considered finished when either: // 1. Loading + streaming completes, or - // 2. Loading completes + streaming was never started + someone called - // "SetClientIsWaitingForFinished" to block streaming from ever starting. + // 2. Loading completes + streaming is disabled. void NotifyFinished() override; - bool IsFinishedInternal() const override; private: // Valid state transitions: // - // kCanStartStreaming -> kStreaming -> kWaitingForStreamingToEnd - // -> kFinishedNotificationSent - // kCanStartStreaming -> kStreamingNotAllowed -> kFinishedNotificationSent + // kWaitingForDataPipe DisableStreaming() + // |---------------------------. + // | | + // v v + // kStreaming -----------------> kStreamingDisabled + // enum class StreamingState { - kCanStartStreaming, // Streaming can be started. - kStreamingNotAllowed, // Streaming can no longer be started. - kStreaming, // Both loading the resource and streaming. - kWaitingForStreamingToEnd, // Resource loaded but streaming not complete. - kFinishedNotificationSent // Everything complete and finish sent. + // Streaming is allowed on this resource, but we're waiting to receive a + // data pipe. + kWaitingForDataPipe, + // The script streamer is active, and has the data pipe. + kStreaming, + + // Streaming was disabled, either manually or because we got a body with + // no data-pipe. + kStreamingDisabled, }; class ScriptResourceFactory : public ResourceFactory { public: - ScriptResourceFactory() + explicit ScriptResourceFactory(StreamingAllowed streaming_allowed) : ResourceFactory(ResourceType::kScript, - TextResourceDecoderOptions::kPlainTextContent) {} + TextResourceDecoderOptions::kPlainTextContent), + streaming_allowed_(streaming_allowed) {} Resource* Create( const ResourceRequest& request, const ResourceLoaderOptions& options, const TextResourceDecoderOptions& decoder_options) const override { - return MakeGarbageCollected<ScriptResource>(request, options, - decoder_options); + return MakeGarbageCollected<ScriptResource>( + request, options, decoder_options, streaming_allowed_); } - }; - void Prefinalize(); + private: + StreamingAllowed streaming_allowed_; + }; bool CanUseCacheValidator() const override; + void DisableStreaming(ScriptStreamer::NotStreamingReason no_streamer_reason); + void AdvanceStreamingState(StreamingState new_state); // Check that invariants for the state hold. @@ -208,14 +175,10 @@ class CORE_EXPORT ScriptResource final : public TextResource { ParkableString source_text_; - mojo::ScopedDataPipeConsumerHandle data_pipe_; - std::unique_ptr<mojo::SimpleWatcher> watcher_; - Member<ResponseBodyLoaderClient> response_body_loader_client_; - Member<ScriptStreamer> streamer_; - ScriptStreamer::NotStreamingReason not_streaming_reason_ = - ScriptStreamer::kDidntTryToStartStreaming; - StreamingState streaming_state_ = StreamingState::kCanStartStreaming; + ScriptStreamer::NotStreamingReason no_streamer_reason_ = + ScriptStreamer::NotStreamingReason::kInvalid; + StreamingState streaming_state_ = StreamingState::kWaitingForDataPipe; }; DEFINE_RESOURCE_TYPE_CASTS(Script); |