summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/html/parser
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/html/parser')
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/background_html_parser.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h23
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h56
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc256
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_options.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_options.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h17
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_view_source_parser_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/parser_scripting_flag_policy.h16
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.h39
36 files changed, 889 insertions, 253 deletions
diff --git a/chromium/third_party/blink/renderer/core/html/parser/BUILD.gn b/chromium/third_party/blink/renderer/core/html/parser/BUILD.gn
index 83e917e1e90..43eb9f797d7 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/html/parser/BUILD.gn
@@ -35,6 +35,8 @@ blink_core_sources("parser") {
"html_meta_charset_parser.h",
"html_parser_idioms.cc",
"html_parser_idioms.h",
+ "html_parser_metrics.cc",
+ "html_parser_metrics.h",
"html_parser_options.cc",
"html_parser_options.h",
"html_parser_reentry_permit.cc",
@@ -62,6 +64,7 @@ blink_core_sources("parser") {
"input_stream_preprocessor.h",
"markup_tokenizer_inlines.h",
"nesting_level_incrementer.h",
+ "parser_scripting_flag_policy.h",
"parser_synchronization_policy.h",
"preload_request.cc",
"preload_request.h",
@@ -85,9 +88,7 @@ blink_core_sources("parser") {
}
fuzzer_test("blink_html_tokenizer_fuzzer") {
- sources = [
- "html_tokenizer_fuzzer.cc",
- ]
+ sources = [ "html_tokenizer_fuzzer.cc" ]
deps = [
"../../:core",
"../../../platform:blink_fuzzer_test_support",
diff --git a/chromium/third_party/blink/renderer/core/html/parser/OWNERS b/chromium/third_party/blink/renderer/core/html/parser/OWNERS
index 23b641cfa1f..2812e39384d 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/OWNERS
+++ b/chromium/third_party/blink/renderer/core/html/parser/OWNERS
@@ -1,6 +1,7 @@
+csharrison@chromium.org
kouhei@chromium.org
+masonfreed@chromium.org
yoavweiss@chromium.org
-csharrison@chromium.org
# TEAM: loading-dev@chromium.org
# COMPONENT: Blink>HTML>Parser
diff --git a/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.cc b/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.cc
index 83c6e31cef2..6bc906f027b 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.cc
@@ -33,7 +33,6 @@
#include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -164,6 +163,7 @@ void BackgroundHTMLParser::Finish() {
}
void BackgroundHTMLParser::Stop() {
+ ClearParser();
delete this;
}
@@ -175,6 +175,10 @@ void BackgroundHTMLParser::ForcePlaintextForTextDocument() {
tokenizer_->SetState(HTMLTokenizer::kPLAINTEXTState);
}
+void BackgroundHTMLParser::ClearParser() {
+ parser_.Clear();
+}
+
void BackgroundHTMLParser::MarkEndOfFile() {
DCHECK(!input_.Current().IsClosed());
input_.Append(String(&kEndOfFileMarker, 1));
diff --git a/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h b/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h
index 5b94d6ebf6a..de2b5d96511 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/background_html_parser.h
@@ -56,7 +56,7 @@ class BackgroundHTMLParser {
public:
Configuration();
HTMLParserOptions options;
- base::WeakPtr<HTMLDocumentParser> parser;
+ WeakPersistent<HTMLDocumentParser> parser;
std::unique_ptr<TextResourceDecoder> decoder;
};
@@ -74,7 +74,7 @@ class BackgroundHTMLParser {
USING_FAST_MALLOC(Checkpoint);
public:
- base::WeakPtr<HTMLDocumentParser> parser;
+ WeakPersistent<HTMLDocumentParser> parser;
std::unique_ptr<HTMLToken> token;
std::unique_ptr<HTMLTokenizer> tokenizer;
HTMLTreeBuilderSimulator::State tree_builder_state;
@@ -93,6 +93,8 @@ class BackgroundHTMLParser {
void ForcePlaintextForTextDocument();
+ void ClearParser();
+
private:
BackgroundHTMLParser(std::unique_ptr<Configuration>,
scoped_refptr<base::SingleThreadTaskRunner>);
@@ -111,7 +113,7 @@ class BackgroundHTMLParser {
std::unique_ptr<HTMLTokenizer> tokenizer_;
HTMLTreeBuilderSimulator tree_builder_simulator_;
HTMLParserOptions options_;
- base::WeakPtr<HTMLDocumentParser> parser_;
+ WeakPersistent<HTMLDocumentParser> parser_;
CompactHTMLTokenStream pending_tokens_;
PreloadRequestStream pending_preloads_;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc b/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
index 1dd67036707..279776cb0b0 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
@@ -236,7 +236,7 @@ static String ParseCSSStringOrURL(const String& string) {
}
void CSSPreloadScanner::EmitRule(const SegmentedString& source) {
- if (DeprecatedEqualIgnoringCase(rule_, "import")) {
+ if (EqualIgnoringASCIICase(rule_, "import")) {
String url = ParseCSSStringOrURL(rule_value_.ToString());
TextPosition position =
TextPosition(source.CurrentLine(), source.CurrentColumn());
@@ -250,7 +250,7 @@ void CSSPreloadScanner::EmitRule(const SegmentedString& source) {
requests_->push_back(std::move(request));
}
state_ = kInitial;
- } else if (DeprecatedEqualIgnoringCase(rule_, "charset"))
+ } else if (EqualIgnoringASCIICase(rule_, "charset"))
state_ = kInitial;
else
state_ = kDoneParsingImportRules;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
index e5b8596cb60..88bf8c170a1 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -300,7 +300,7 @@ void HTMLConstructionSite::AttachLater(ContainerNode* parent,
DCHECK(ScriptingContentIsAllowed(parser_content_policy_) || !element ||
!element->IsScriptElement());
DCHECK(PluginContentIsAllowed(parser_content_policy_) ||
- !IsHTMLPlugInElement(child));
+ !IsA<HTMLPlugInElement>(child));
HTMLConstructionSiteTask task(HTMLConstructionSiteTask::kInsert);
task.parent = parent;
@@ -572,16 +572,15 @@ void HTMLConstructionSite::SetCompatibilityModeFromDoctype(
"-//W3C//DTD HTML Experimental 970421//") ||
public_id.StartsWithIgnoringASCIICase("-//W3C//DTD W3 HTML//") ||
public_id.StartsWithIgnoringASCIICase("-//W3O//DTD W3 HTML 3.0//") ||
- DeprecatedEqualIgnoringCase(public_id,
- "-//W3O//DTD W3 HTML Strict 3.0//EN//") ||
+ EqualIgnoringASCIICase(public_id,
+ "-//W3O//DTD W3 HTML Strict 3.0//EN//") ||
public_id.StartsWithIgnoringASCIICase(
"-//WebTechs//DTD Mozilla HTML 2.0//") ||
public_id.StartsWithIgnoringASCIICase(
"-//WebTechs//DTD Mozilla HTML//") ||
- DeprecatedEqualIgnoringCase(public_id,
- "-/W3C/DTD HTML 4.0 Transitional/EN") ||
- DeprecatedEqualIgnoringCase(public_id, "HTML") ||
- DeprecatedEqualIgnoringCase(
+ EqualIgnoringASCIICase(public_id, "-/W3C/DTD HTML 4.0 Transitional/EN") ||
+ EqualIgnoringASCIICase(public_id, "HTML") ||
+ EqualIgnoringASCIICase(
system_id,
"http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") ||
(system_id.IsEmpty() && public_id.StartsWithIgnoringASCIICase(
@@ -844,7 +843,7 @@ CreateElementFlags HTMLConstructionSite::GetCreateElementFlags() const {
: CreateElementFlags::ByParser();
}
-inline Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() {
+Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() {
if (auto* template_element = DynamicTo<HTMLTemplateElement>(*CurrentNode()))
return template_element->content()->GetDocument();
return CurrentNode()->GetDocument();
@@ -919,8 +918,15 @@ Element* HTMLConstructionSite::CreateElement(
// reactions stack."
CEReactionsScope reactions;
- // 7.
- element = definition->CreateAutonomousCustomElementSync(document, tag_name);
+ // "7. Let element be the result of creating an element given document,
+ // localName, given namespace, null, and is. If will execute script is true,
+ // set the synchronous custom elements flag; otherwise, leave it unset."
+ // TODO(crbug.com/1080673): We clear the CreatedbyParser flag here, so that
+ // elements get fully constructed. Some elements (e.g. HTMLInputElement)
+ // only partially construct themselves when created by the parser, but since
+ // this is a custom element, we need a fully-constructed element here.
+ element = definition->CreateElement(
+ document, tag_name, GetCreateElementFlags().SetCreatedByParser(false));
// "8. Append each attribute in the given token to element." We don't use
// setAttributes here because the custom element constructor may have
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 81914e59108..eb81ef312c7 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -43,6 +43,7 @@
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/parser/atomic_html_token.h"
#include "third_party/blink/renderer/core/html/parser/background_html_parser.h"
+#include "third_party/blink/renderer/core/html/parser/html_parser_metrics.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_scheduler.h"
#include "third_party/blink/renderer/core/html/parser/html_resource_preloader.h"
#include "third_party/blink/renderer/core/html/parser/html_tree_builder.h"
@@ -58,7 +59,6 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -70,6 +70,16 @@
namespace blink {
+static size_t g_discarded_token_count_for_testing = 0;
+
+void ResetDiscardedTokenCountForTesting() {
+ g_discarded_token_count_for_testing = 0;
+}
+
+size_t GetDiscardedTokenCountForTesting() {
+ return g_discarded_token_count_for_testing;
+}
+
// This is a direct transcription of step 4 from:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
static HTMLTokenizer::State TokenizerStateForContextElement(
@@ -89,7 +99,7 @@ static HTMLTokenizer::State TokenizerStateForContextElement(
context_tag.Matches(html_names::kIFrameTag) ||
context_tag.Matches(html_names::kNoembedTag) ||
(context_tag.Matches(html_names::kNoscriptTag) &&
- options.script_enabled) ||
+ options.scripting_flag) ||
context_tag.Matches(html_names::kNoframesTag))
return report_errors ? HTMLTokenizer::kRAWTEXTState
: HTMLTokenizer::kPLAINTEXTState;
@@ -101,6 +111,32 @@ static HTMLTokenizer::State TokenizerStateForContextElement(
return HTMLTokenizer::kDataState;
}
+class ScopedYieldTimer {
+ public:
+ // This object is created at the start of a block of parsing, and will
+ // report the time since the last block yielded if known.
+ ScopedYieldTimer(std::unique_ptr<base::ElapsedTimer>* timer,
+ HTMLParserMetrics* metrics_reporter)
+ : timer_(timer), reporting_metrics_(metrics_reporter) {
+ if (!reporting_metrics_ || !(*timer_))
+ return;
+
+ metrics_reporter->AddYieldInterval((*timer_)->Elapsed());
+ timer_->reset();
+ }
+
+ // The destructor creates a new timer, which will keep track of time until
+ // the next block starts.
+ ~ScopedYieldTimer() {
+ if (reporting_metrics_)
+ *timer_ = std::make_unique<base::ElapsedTimer>();
+ }
+
+ private:
+ std::unique_ptr<base::ElapsedTimer>* timer_;
+ bool reporting_metrics_;
+};
+
HTMLDocumentParser::HTMLDocumentParser(HTMLDocument& document,
ParserSynchronizationPolicy sync_policy)
: HTMLDocumentParser(document, kAllowScriptingContent, sync_policy) {
@@ -131,7 +167,6 @@ HTMLDocumentParser::HTMLDocumentParser(Document& document,
ParserContentPolicy content_policy,
ParserSynchronizationPolicy sync_policy)
: ScriptableDocumentParser(document, content_policy),
- ContextLifecycleStateObserver(&document),
options_(&document),
reentry_permit_(HTMLParserReentryPermit::Create()),
token_(sync_policy == kForceSynchronousParsing
@@ -160,7 +195,15 @@ HTMLDocumentParser::HTMLDocumentParser(Document& document,
// Threading is not allowed in prefetch mode.
DCHECK(!document.IsPrefetchOnly() || !ShouldUseThreading());
- UpdateStateIfNeeded();
+ // Report metrics for async document parsing only. The document
+ // must be main frame to meet UKM requirements, and must have a high
+ // resolution clock for high quality data.
+ if (sync_policy == kAllowAsynchronousParsing && document.GetFrame() &&
+ document.GetFrame()->IsMainFrame() &&
+ base::TimeTicks::IsHighResolution()) {
+ metrics_reporter_ = std::make_unique<HTMLParserMetrics>(
+ document.UkmSourceID(), document.UkmRecorder());
+ }
// Don't create preloader for parsing clipboard content.
if (content_policy == kDisallowScriptingAndPluginContent)
@@ -194,7 +237,6 @@ void HTMLDocumentParser::Trace(Visitor* visitor) {
visitor->Trace(script_runner_);
visitor->Trace(preloader_);
ScriptableDocumentParser::Trace(visitor);
- ContextLifecycleStateObserver::Trace(visitor);
HTMLParserScriptRunnerHost::Trace(visitor);
}
@@ -269,7 +311,7 @@ bool HTMLDocumentParser::IsParsingFragment() const {
}
void HTMLDocumentParser::PumpTokenizerIfPossible() {
- CheckIfBodyStylesheetAdded();
+ CheckIfBlockingStylesheetAdded();
if (IsStopped() || IsPaused())
return;
@@ -285,7 +327,9 @@ void HTMLDocumentParser::ResumeParsingAfterYield() {
DCHECK(ShouldUseThreading());
DCHECK(have_background_parser_);
- CheckIfBodyStylesheetAdded();
+ ScopedYieldTimer(&yield_timer_, metrics_reporter_.get());
+
+ CheckIfBlockingStylesheetAdded();
if (IsStopped() || IsPaused())
return;
@@ -301,7 +345,7 @@ void HTMLDocumentParser::RunScriptsForPausedTreeBuilder() {
// We will not have a scriptRunner when parsing a DocumentFragment.
if (script_runner_)
script_runner_->ProcessScriptElement(script_element, script_start_position);
- CheckIfBodyStylesheetAdded();
+ CheckIfBlockingStylesheetAdded();
}
bool HTMLDocumentParser::CanTakeNextToken() {
@@ -335,7 +379,8 @@ void HTMLDocumentParser::EnqueueTokenizedChunk(
// Note that on commit, the loader dispatched preloads for all the non-media
// links.
GetDocument()->Loader()->DispatchLinkHeaderPreloads(
- chunk->viewport, PreloadHelper::kOnlyLoadMedia);
+ base::OptionalOrNullptr(chunk->viewport),
+ PreloadHelper::kOnlyLoadMedia);
tried_loading_link_headers_ = true;
if (GetDocument()->Loader()->GetPrefetchedSignedExchangeManager()) {
// Link header preloads for prefetched signed exchanges won't be started
@@ -390,12 +435,8 @@ void HTMLDocumentParser::EnqueueTokenizedChunk(
speculations_.push_back(std::move(chunk));
- if (!IsPaused() && !IsScheduledForUnpause()) {
- if (GetDocument()->IsContextPaused())
- parser_scheduler_->ForceUnpauseAfterYield();
- else
- parser_scheduler_->ScheduleForUnpause();
- }
+ if (!IsPaused() && !IsScheduledForUnpause())
+ parser_scheduler_->ScheduleForUnpause();
}
void HTMLDocumentParser::DidReceiveEncodingDataFromBackgroundParser(
@@ -453,16 +494,14 @@ void HTMLDocumentParser::DiscardSpeculationsAndResumeFrom(
std::unique_ptr<TokenizedChunk> last_chunk_before_script,
std::unique_ptr<HTMLToken> token,
std::unique_ptr<HTMLTokenizer> tokenizer) {
- weak_factory_.InvalidateWeakPtrs();
+ // Clear back ref.
+ background_parser_->ClearParser();
size_t discarded_token_count = 0;
for (const auto& speculation : speculations_) {
discarded_token_count += speculation->tokens.size();
}
- DEFINE_STATIC_LOCAL(CustomCountHistogram, discarded_token_count_histogram,
- ("Parser.DiscardedTokenCount", 1, 100000, 50));
- discarded_token_count_histogram.Count(
- base::saturated_cast<base::Histogram::Sample>(discarded_token_count));
+ g_discarded_token_count_for_testing += discarded_token_count;
speculations_.clear();
pending_csp_meta_token_ = nullptr;
@@ -470,7 +509,7 @@ void HTMLDocumentParser::DiscardSpeculationsAndResumeFrom(
std::unique_ptr<BackgroundHTMLParser::Checkpoint> checkpoint =
std::make_unique<BackgroundHTMLParser::Checkpoint>();
- checkpoint->parser = weak_factory_.GetWeakPtr();
+ checkpoint->parser = this;
checkpoint->token = std::move(token);
checkpoint->tokenizer = std::move(tokenizer);
checkpoint->tree_builder_state =
@@ -490,7 +529,8 @@ void HTMLDocumentParser::DiscardSpeculationsAndResumeFrom(
}
size_t HTMLDocumentParser::ProcessTokenizedChunkFromBackgroundParser(
- std::unique_ptr<TokenizedChunk> pop_chunk) {
+ std::unique_ptr<TokenizedChunk> pop_chunk,
+ bool* reached_end_of_file) {
TRACE_EVENT_WITH_FLOW0(
"blink,loading",
"HTMLDocumentParser::processTokenizedChunkFromBackgroundParser",
@@ -551,6 +591,7 @@ size_t HTMLDocumentParser::ProcessTokenizedChunkFromBackgroundParser(
// There should never be any chunks after the EOF.
DCHECK(speculations_.IsEmpty());
PrepareToStopParsing();
+ *reached_end_of_file = true;
break;
}
@@ -595,17 +636,18 @@ void HTMLDocumentParser::PumpPendingSpeculations() {
probe::ParseHTML probe(GetDocument(), this);
SpeculationsPumpSession session(pump_speculations_session_nesting_level_);
+ bool reached_end_of_file = false;
while (!speculations_.IsEmpty()) {
DCHECK(!IsScheduledForUnpause());
- size_t element_token_count =
- ProcessTokenizedChunkFromBackgroundParser(speculations_.TakeFirst());
+ size_t element_token_count = ProcessTokenizedChunkFromBackgroundParser(
+ speculations_.TakeFirst(), &reached_end_of_file);
session.AddedElementTokens(element_token_count);
// Always check IsParsing first as document_ may be null. Surprisingly,
// IsScheduledForUnpause() may be set here as a result of
// ProcessTokenizedChunkFromBackgroundParser running arbitrary javascript
// which invokes nested event loops. (e.g. inspector breakpoints)
- CheckIfBodyStylesheetAdded();
+ CheckIfBlockingStylesheetAdded();
if (!IsParsing() || IsPaused() || IsScheduledForUnpause())
break;
@@ -614,6 +656,13 @@ void HTMLDocumentParser::PumpPendingSpeculations() {
session, speculations_.front()->starting_script))
break;
}
+
+ if (metrics_reporter_) {
+ metrics_reporter_->AddChunk(session.ElapsedTime(),
+ session.ProcessedElementTokens());
+ if (reached_end_of_file)
+ metrics_reporter_->ReportMetricsAtParseEnd();
+ }
}
void HTMLDocumentParser::ForcePlaintextForTextDocument() {
@@ -697,7 +746,7 @@ void HTMLDocumentParser::ConstructTreeFromHTMLToken() {
Token().Clear();
tree_builder_->ConstructTree(&atomic_token);
- CheckIfBodyStylesheetAdded();
+ CheckIfBlockingStylesheetAdded();
// FIXME: ConstructTree may synchronously cause Document to be detached.
if (!token_)
@@ -714,7 +763,7 @@ void HTMLDocumentParser::ConstructTreeFromCompactHTMLToken(
DCHECK(!GetDocument()->IsPrefetchOnly());
AtomicHTMLToken token(compact_token);
tree_builder_->ConstructTree(&token);
- CheckIfBodyStylesheetAdded();
+ CheckIfBlockingStylesheetAdded();
}
bool HTMLDocumentParser::HasInsertionPoint() {
@@ -775,7 +824,7 @@ void HTMLDocumentParser::StartBackgroundParser() {
std::unique_ptr<BackgroundHTMLParser::Configuration> config =
std::make_unique<BackgroundHTMLParser::Configuration>();
config->options = options_;
- config->parser = weak_factory_.GetWeakPtr();
+ config->parser = this;
config->decoder = TakeDecoder();
// The background parser is created on the main thread, but may otherwise
@@ -808,7 +857,6 @@ void HTMLDocumentParser::StopBackgroundParser() {
// Make this sync, as lsan triggers on some unittests if the task runner is
// used.
background_parser_->Stop();
- weak_factory_.InvalidateWeakPtrs();
}
void HTMLDocumentParser::Append(const String& input_source) {
@@ -1010,7 +1058,7 @@ void HTMLDocumentParser::ResumeParsingAfterPause() {
DCHECK(!IsExecutingScript());
DCHECK(!IsPaused());
- CheckIfBodyStylesheetAdded();
+ CheckIfBlockingStylesheetAdded();
if (IsStopped() || IsPaused())
return;
@@ -1099,7 +1147,7 @@ void HTMLDocumentParser::DidLoadAllPendingParserBlockingStylesheets() {
added_pending_parser_blocking_stylesheet_ = false;
}
-void HTMLDocumentParser::CheckIfBodyStylesheetAdded() {
+void HTMLDocumentParser::CheckIfBlockingStylesheetAdded() {
if (added_pending_parser_blocking_stylesheet_) {
added_pending_parser_blocking_stylesheet_ = false;
is_waiting_for_stylesheets_ = true;
@@ -1119,16 +1167,6 @@ void HTMLDocumentParser::ParseDocumentFragment(
parser->Detach();
}
-void HTMLDocumentParser::ContextLifecycleStateChanged(
- mojom::FrameLifecycleState state) {
- if (!parser_scheduler_)
- return;
- if (state == mojom::FrameLifecycleState::kRunning)
- parser_scheduler_->Unpause();
- else
- parser_scheduler_->Pause();
-}
-
void HTMLDocumentParser::AppendBytes(const char* data, size_t length) {
if (!length || IsStopped())
return;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h
index 9e98f0fe52f..ac73abc6eeb 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -32,7 +32,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/parser_content_policy.h"
#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
-#include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h"
#include "third_party/blink/renderer/core/html/parser/background_html_input_stream.h"
#include "third_party/blink/renderer/core/html/parser/html_input_stream.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_options.h"
@@ -59,14 +58,20 @@ class DocumentEncodingData;
class DocumentFragment;
class Element;
class HTMLDocument;
+class HTMLParserMetrics;
class HTMLParserScheduler;
class HTMLParserScriptRunner;
class HTMLPreloadScanner;
class HTMLResourcePreloader;
class HTMLTreeBuilder;
+// TODO(https://crbug.com/1049898): These are only exposed to make it possible
+// to delete an expired histogram. The test should be rewritten to test at a
+// different level, so it won't have to make assertions about internal state.
+void CORE_EXPORT ResetDiscardedTokenCountForTesting();
+size_t CORE_EXPORT GetDiscardedTokenCountForTesting();
+
class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
- public ContextLifecycleStateObserver,
private HTMLParserScriptRunnerHost {
USING_GARBAGE_COLLECTED_MIXIN(HTMLDocumentParser);
USING_PRE_FINALIZER(HTMLDocumentParser, Dispose);
@@ -102,8 +107,6 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
bool IsParsingAtLineNumber() const final;
OrdinalNumber LineNumber() const final;
- void ContextLifecycleStateChanged(mojom::FrameLifecycleState) final;
-
HTMLParserReentryPermit* ReentryPermit() { return reentry_permit_.get(); }
struct TokenizedChunk {
@@ -159,7 +162,7 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
void ExecuteScriptsWaitingForResources() final;
void DidAddPendingParserBlockingStylesheet() final;
void DidLoadAllPendingParserBlockingStylesheets() final;
- void CheckIfBodyStylesheetAdded();
+ void CheckIfBlockingStylesheetAdded();
void DocumentElementAvailable() override;
// HTMLParserScriptRunnerHost
@@ -178,7 +181,8 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
std::unique_ptr<HTMLToken>,
std::unique_ptr<HTMLTokenizer>);
size_t ProcessTokenizedChunkFromBackgroundParser(
- std::unique_ptr<TokenizedChunk>);
+ std::unique_ptr<TokenizedChunk>,
+ bool*);
void PumpPendingSpeculations();
bool CanTakeNextToken();
@@ -245,6 +249,11 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
Member<HTMLResourcePreloader> preloader_;
PreloadRequestStream queued_preloads_;
+ // Metrics gathering and reporting
+ std::unique_ptr<HTMLParserMetrics> metrics_reporter_;
+ // A timer for how long we are inactive after yielding
+ std::unique_ptr<base::ElapsedTimer> yield_timer_;
+
// If this is non-null, then there is a meta CSP token somewhere in the
// speculation buffer. Preloads will be deferred until a token matching this
// pointer is parsed and the CSP policy is applied. Note that this pointer
@@ -264,8 +273,6 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
bool tried_loading_link_headers_;
bool added_pending_parser_blocking_stylesheet_;
bool is_waiting_for_stylesheets_;
-
- base::WeakPtrFactory<HTMLDocumentParser> weak_factory_{this};
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc
index cf1a4f2c9a9..54ec8d65eb3 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_loading_test.cc
@@ -8,7 +8,6 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
-#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
@@ -16,9 +15,9 @@ namespace blink {
class HTMLDocumentParserSimTest : public SimTest {
protected:
HTMLDocumentParserSimTest() {
+ ResetDiscardedTokenCountForTesting();
Document::SetThreadedParsingEnabledForTesting(true);
}
- HistogramTester histogram_;
};
class HTMLDocumentParserLoadingTest : public HTMLDocumentParserSimTest,
@@ -432,7 +431,7 @@ TEST_F(HTMLDocumentParserSimTest, NoRewindNoDocWrite) {
)HTML");
test::RunPendingTasks();
- histogram_.ExpectTotalCount("Parser.DiscardedTokenCount", 0);
+ EXPECT_EQ(0U, GetDiscardedTokenCountForTesting());
}
TEST_F(HTMLDocumentParserSimTest, RewindBrokenToken) {
@@ -447,7 +446,7 @@ TEST_F(HTMLDocumentParserSimTest, RewindBrokenToken) {
)HTML");
test::RunPendingTasks();
- histogram_.ExpectTotalCount("Parser.DiscardedTokenCount", 1);
+ EXPECT_EQ(2U, GetDiscardedTokenCountForTesting());
}
TEST_F(HTMLDocumentParserSimTest, RewindDifferentNamespace) {
@@ -462,7 +461,7 @@ TEST_F(HTMLDocumentParserSimTest, RewindDifferentNamespace) {
)HTML");
test::RunPendingTasks();
- histogram_.ExpectTotalCount("Parser.DiscardedTokenCount", 1);
+ EXPECT_EQ(2U, GetDiscardedTokenCountForTesting());
}
TEST_F(HTMLDocumentParserSimTest, NoRewindSaneDocWrite1) {
@@ -476,7 +475,7 @@ TEST_F(HTMLDocumentParserSimTest, NoRewindSaneDocWrite1) {
"</script>");
test::RunPendingTasks();
- histogram_.ExpectTotalCount("Parser.DiscardedTokenCount", 0);
+ EXPECT_EQ(0U, GetDiscardedTokenCountForTesting());
}
TEST_F(HTMLDocumentParserSimTest, NoRewindSaneDocWrite2) {
@@ -491,7 +490,7 @@ TEST_F(HTMLDocumentParserSimTest, NoRewindSaneDocWrite2) {
)HTML");
test::RunPendingTasks();
- histogram_.ExpectTotalCount("Parser.DiscardedTokenCount", 0);
+ EXPECT_EQ(0U, GetDiscardedTokenCountForTesting());
}
TEST_F(HTMLDocumentParserSimTest, NoRewindSaneDocWriteWithTitle) {
@@ -511,7 +510,7 @@ TEST_F(HTMLDocumentParserSimTest, NoRewindSaneDocWriteWithTitle) {
)HTML");
test::RunPendingTasks();
- histogram_.ExpectTotalCount("Parser.DiscardedTokenCount", 0);
+ EXPECT_EQ(0U, GetDiscardedTokenCountForTesting());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc
index 33750cefc73..d74f07df6a4 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser_test.cc
@@ -6,7 +6,6 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_prerendering_support.h"
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/loader/prerenderer_client.h"
@@ -24,27 +23,11 @@ class MockPrerendererClient : public PrerendererClient {
: PrerendererClient(page, nullptr), is_prefetch_only_(is_prefetch_only) {}
private:
- void WillAddPrerender(Prerender*) override {}
bool IsPrefetchOnly() override { return is_prefetch_only_; }
bool is_prefetch_only_;
};
-class MockWebPrerenderingSupport : public WebPrerenderingSupport {
- public:
- MockWebPrerenderingSupport() { Initialize(this); }
-
- void Add(const WebPrerender&) override {}
- void Cancel(const WebPrerender&) override {}
- void Abandon(const WebPrerender&) override {}
- void PrefetchFinished() override { prefetch_finished_ = true; }
-
- bool IsPrefetchFinished() const { return prefetch_finished_; }
-
- private:
- bool prefetch_finished_ = false;
-};
-
class HTMLDocumentParserTest : public PageTestBase {
protected:
void SetUp() override {
@@ -60,19 +43,12 @@ class HTMLDocumentParserTest : public PageTestBase {
parser->SetDecoder(std::move(decoder));
return parser;
}
-
- bool PrefetchFinishedCleanly() {
- return prerendering_support_.IsPrefetchFinished();
- }
-
- private:
- MockWebPrerenderingSupport prerendering_support_;
};
} // namespace
TEST_F(HTMLDocumentParserTest, AppendPrefetch) {
- HTMLDocument& document = ToHTMLDocument(GetDocument());
+ auto& document = To<HTMLDocument>(GetDocument());
ProvidePrerendererClientTo(
*document.GetPage(),
MakeGarbageCollected<MockPrerendererClient>(*document.GetPage(), true));
@@ -90,11 +66,10 @@ TEST_F(HTMLDocumentParserTest, AppendPrefetch) {
// DCHECK).
static_cast<DocumentParser*>(parser)->Finish();
EXPECT_EQ(HTMLTokenizer::kDataState, parser->Tokenizer()->GetState());
- EXPECT_TRUE(PrefetchFinishedCleanly());
}
TEST_F(HTMLDocumentParserTest, AppendNoPrefetch) {
- HTMLDocument& document = ToHTMLDocument(GetDocument());
+ auto& document = To<HTMLDocument>(GetDocument());
EXPECT_FALSE(document.IsPrefetchOnly());
// Use ForceSynchronousParsing to allow calling append().
HTMLDocumentParser* parser = CreateParser(document);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc
index 598ed12a677..a4a13996c81 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc
@@ -134,8 +134,6 @@ HTMLElementStack::HTMLElementStack()
body_element_(nullptr),
stack_depth_(0) {}
-HTMLElementStack::~HTMLElementStack() = default;
-
bool HTMLElementStack::HasOnlyOneElement() const {
return !TopRecord()->Next();
}
@@ -251,8 +249,8 @@ bool HTMLElementStack::IsHTMLIntegrationPoint(HTMLStackItem* item) {
item->GetAttributeItem(mathml_names::kEncodingAttr);
if (encoding_attr) {
const String& encoding = encoding_attr->Value();
- return DeprecatedEqualIgnoringCase(encoding, "text/html") ||
- DeprecatedEqualIgnoringCase(encoding, "application/xhtml+xml");
+ return EqualIgnoringASCIICase(encoding, "text/html") ||
+ EqualIgnoringASCIICase(encoding, "application/xhtml+xml");
}
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h
index bafb57a8d25..a433c82874c 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.h
@@ -45,7 +45,6 @@ class HTMLElementStack {
public:
HTMLElementStack();
- ~HTMLElementStack();
class ElementRecord final : public GarbageCollected<ElementRecord> {
public:
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.cc b/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.cc
index 9741293150a..8ade3c166af 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.cc
@@ -39,8 +39,6 @@ static const size_t kNoahsArkCapacity = 3;
HTMLFormattingElementList::HTMLFormattingElementList() = default;
-HTMLFormattingElementList::~HTMLFormattingElementList() = default;
-
Element* HTMLFormattingElementList::ClosestElementInScopeWithName(
const AtomicString& target_name) {
for (wtf_size_t i = 1; i <= entries_.size(); ++i) {
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h b/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h
index 7d8e16b883e..f9c4f2a13cb 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_formatting_element_list.h
@@ -42,7 +42,6 @@ class HTMLFormattingElementList {
public:
HTMLFormattingElementList();
- ~HTMLFormattingElementList();
// Ideally Entry would be private, but HTMLTreeBuilder has to coordinate
// between the HTMLFormattingElementList and HTMLElementStack and needs access
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.cc
index fed483dae45..85a7b67b3c4 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.cc
@@ -379,7 +379,7 @@ WTF::TextEncoding EncodingFromMetaAttributes(
const AtomicString& attribute_value = AtomicString(html_attribute.second);
if (ThreadSafeMatch(attribute_name, html_names::kHttpEquivAttr)) {
- if (DeprecatedEqualIgnoringCase(attribute_value, "content-type"))
+ if (EqualIgnoringASCIICase(attribute_value, "content-type"))
got_pragma = true;
} else if (ThreadSafeMatch(attribute_name, html_names::kCharsetAttr)) {
has_charset = true;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc
new file mode 100644
index 00000000000..997ff68addd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.cc
@@ -0,0 +1,104 @@
+// Copyright 2020 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/html/parser/html_parser_metrics.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+
+namespace blink {
+
+HTMLParserMetrics::HTMLParserMetrics(int64_t source_id,
+ ukm::UkmRecorder* recorder)
+ : source_id_(source_id), recorder_(recorder) {}
+
+void HTMLParserMetrics::AddChunk(base::TimeDelta elapsed_time,
+ unsigned tokens_parsed) {
+ DCHECK(base::TimeTicks::IsHighResolution());
+
+ ++chunk_count_;
+
+ accumulated_parsing_time_ += elapsed_time;
+ if (elapsed_time < min_parsing_time_)
+ min_parsing_time_ = elapsed_time;
+ if (elapsed_time > max_parsing_time_)
+ max_parsing_time_ = elapsed_time;
+
+ total_tokens_parsed_ += tokens_parsed;
+ if (tokens_parsed < min_tokens_parsed_)
+ min_tokens_parsed_ = tokens_parsed;
+ if (tokens_parsed > max_tokens_parsed_)
+ max_tokens_parsed_ = tokens_parsed;
+}
+
+void HTMLParserMetrics::AddYieldInterval(base::TimeDelta elapsed_time) {
+ DCHECK(base::TimeTicks::IsHighResolution());
+
+ yield_count_++;
+
+ accumulated_yield_intervals_ += elapsed_time;
+ if (elapsed_time < min_yield_interval_)
+ min_yield_interval_ = elapsed_time;
+ if (elapsed_time > max_yield_interval_)
+ max_yield_interval_ = elapsed_time;
+}
+
+void HTMLParserMetrics::ReportMetricsAtParseEnd() {
+ // The various histogram limits were chosen based on initial UKM data.
+ UMA_HISTOGRAM_COUNTS_1000("Blink.HTMLParsing.ChunkCount", chunk_count_);
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Blink.HTMLParsing.ParsingTimeMax", max_parsing_time_,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(100),
+ 1000);
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES("Blink.HTMLParsing.ParsingTimeMin",
+ min_parsing_time_,
+ base::TimeDelta::FromMicroseconds(1),
+ base::TimeDelta::FromSeconds(1), 100);
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Blink.HTMLParsing.ParsingTimeTotal", accumulated_parsing_time_,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(100),
+ 1000);
+ UMA_HISTOGRAM_COUNTS_1M("Blink.HTMLParsing.TokensParsedMax",
+ max_tokens_parsed_);
+ UMA_HISTOGRAM_COUNTS_10000("Blink.HTMLParsing.TokensParsedMin",
+ min_tokens_parsed_);
+ UMA_HISTOGRAM_COUNTS_1M("Blink.HTMLParsing.TokensParsedAverage",
+ total_tokens_parsed_ / chunk_count_);
+
+ // Only report yield data if we actually yielded.
+ if (max_yield_interval_ != base::TimeDelta()) {
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Blink.HTMLParsing.YieldedTimeMax", max_yield_interval_,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(100),
+ 1000);
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Blink.HTMLParsing.YieldedTimeMin", min_yield_interval_,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 100);
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Blink.HTMLParsing.YieldedTimeAverage",
+ accumulated_yield_intervals_ / yield_count_,
+ base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
+ 100);
+ }
+
+ // Build and report UKM
+ ukm::builders::Blink_HTMLParsing builder(source_id_);
+ builder.SetChunkCount(chunk_count_);
+ builder.SetParsingTimeMax(max_parsing_time_.InMicroseconds());
+ builder.SetParsingTimeMin(min_parsing_time_.InMicroseconds());
+ builder.SetParsingTimeTotal(accumulated_parsing_time_.InMicroseconds());
+ builder.SetTokensParsedMax(max_tokens_parsed_);
+ builder.SetTokensParsedMin(min_tokens_parsed_);
+ builder.SetTokensParsedAverage(total_tokens_parsed_ / chunk_count_);
+ if (accumulated_yield_intervals_ != base::TimeDelta()) {
+ builder.SetYieldedTimeMax(max_yield_interval_.InMicroseconds());
+ builder.SetYieldedTimeMin(min_yield_interval_.InMicroseconds());
+ builder.SetYieldedTimeAverage(
+ accumulated_yield_intervals_.InMicroseconds() / yield_count_);
+ }
+ builder.Record(recorder_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h
new file mode 100644
index 00000000000..e6c84aa70e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics.h
@@ -0,0 +1,56 @@
+// Copyright 2020 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_HTML_PARSER_HTML_PARSER_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_PARSER_METRICS_H_
+
+#include "base/time/time.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
+
+namespace ukm {
+class UkmRecorder;
+}
+
+namespace blink {
+
+// Store and report metrics data for the HTMLDocumentParser.
+class CORE_EXPORT HTMLParserMetrics {
+ public:
+ HTMLParserMetrics(int64_t source_id, ukm::UkmRecorder*);
+ ~HTMLParserMetrics() = default;
+
+ void AddChunk(base::TimeDelta elapsed_time, unsigned tokens_parsed);
+
+ void AddYieldInterval(base::TimeDelta elapsed_time);
+
+ void ReportMetricsAtParseEnd();
+
+ private:
+ // UKM System data.
+ const int64_t source_id_;
+ ukm::UkmRecorder* const recorder_;
+
+ // Metrics data.
+ unsigned chunk_count_ = 0; // For computing averages.
+ base::TimeDelta accumulated_parsing_time_; // Constructed with 0 value
+ base::TimeDelta min_parsing_time_ = base::TimeDelta::Max();
+ base::TimeDelta max_parsing_time_; // Constructed with 0 value
+ unsigned total_tokens_parsed_ = 0;
+ unsigned min_tokens_parsed_ = UINT_MAX;
+ unsigned max_tokens_parsed_ = 0;
+
+ // Yield count may not equal chunk count - 1. That is, there is not
+ // always one yield between every pair of chunks.
+ unsigned yield_count_ = 0;
+ base::TimeDelta accumulated_yield_intervals_; // Constructed with 0 value
+ base::TimeDelta min_yield_interval_ = base::TimeDelta::Max();
+ base::TimeDelta max_yield_interval_; // Constructed with 0 value
+
+ DISALLOW_COPY_AND_ASSIGN(HTMLParserMetrics);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_HTML_PARSER_METRICS_H_
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc
new file mode 100644
index 00000000000..7f797d2b3f9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_metrics_test.cc
@@ -0,0 +1,256 @@
+// Copyright 2020 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/html/parser/html_parser_metrics.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+
+namespace blink {
+
+class HTMLParserMetricsTest : public testing::Test {
+ public:
+ HTMLParserMetricsTest() {
+ helper_.Initialize(nullptr, nullptr, nullptr, nullptr);
+ }
+
+ ~HTMLParserMetricsTest() override = default;
+
+ void SetUp() override {}
+
+ void TearDown() override {}
+
+ void LoadHTML(const std::string& html) {
+ frame_test_helpers::LoadHTMLString(helper_.GetWebView()->MainFrameImpl(),
+ html,
+ url_test_helpers::ToKURL("about:blank"));
+ }
+
+ protected:
+ frame_test_helpers::WebViewHelper helper_;
+};
+
+TEST_F(HTMLParserMetricsTest, ReportSingleChunk) {
+ // Although the tests use a mock clock, the metrics recorder checks if the
+ // system has a high resolution clock before recording results. As a result,
+ // the tests will fail if the system does not have a high resolution clock.
+ if (!base::TimeTicks::IsHighResolution())
+ return;
+
+ base::HistogramTester histogram_tester;
+ LoadHTML(R"HTML(
+ <div></div>
+ )HTML");
+
+ // Should have one of each metric, except the yield times because with
+ // a single chunk they should not report.
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ChunkCount", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeMax", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeMin", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeTotal", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMax", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMin", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedAverage", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMax", 0);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMin", 0);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeAverage", 0);
+
+ // Expect specific values for the chunks and tokens counts
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.ChunkCount", 1, 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMax", 2,
+ 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMin", 2,
+ 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedAverage",
+ 2, 1);
+
+ // Expect that the times have moved from the default and the max and min
+ // and total are all the same (within the same bucket)
+ std::vector<base::Bucket> parsing_time_max_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.ParsingTimeMax");
+ std::vector<base::Bucket> parsing_time_min_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.ParsingTimeMin");
+ std::vector<base::Bucket> parsing_time_total_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.ParsingTimeTotal");
+ EXPECT_EQ(parsing_time_max_buckets.size(), 1u);
+ EXPECT_EQ(parsing_time_min_buckets.size(), 1u);
+ EXPECT_EQ(parsing_time_total_buckets.size(), 1u);
+ EXPECT_GT(parsing_time_max_buckets[0].min, 0);
+ EXPECT_GT(parsing_time_min_buckets[0].min, 0);
+ EXPECT_GT(parsing_time_total_buckets[0].min, 0);
+}
+
+TEST_F(HTMLParserMetricsTest, HistogramReportsTwoChunks) {
+ // Although the tests use a mock clock, the metrics recorder checks if the
+ // system has a high resolution clock before recording results. As a result,
+ // the tests will fail if the system does not have a high resolution clock.
+ if (!base::TimeTicks::IsHighResolution())
+ return;
+
+ base::HistogramTester histogram_tester;
+
+ // This content exceeds the number of tokens before a script tag used as
+ // the yield threshold. If the yield threshold changes, this test will fail
+ // and/or need changing. See the HTMLParserScheduler::ShouldYield method for
+ // the current value of the constant.
+ LoadHTML(R"HTML(
+ <head></head>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <div></div><div></div><div></div><div></div><div></div><div></div>
+ <script>document.offsetTop</script>
+ )HTML");
+
+ // Should have one of each metric.
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ChunkCount", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeMax", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeMin", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.ParsingTimeTotal", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMax", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedMin", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.TokensParsedAverage", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMax", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeMin", 1);
+ histogram_tester.ExpectTotalCount("Blink.HTMLParsing.YieldedTimeAverage", 1);
+
+ // Expect specific values for the chunks and tokens counts
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.ChunkCount", 2, 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMax", 110,
+ 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedMin", 0,
+ 1);
+ histogram_tester.ExpectUniqueSample("Blink.HTMLParsing.TokensParsedAverage",
+ 55, 1);
+
+ // For parse times, expect that the times have moved from the default.
+ std::vector<base::Bucket> parsing_time_max_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.ParsingTimeMax");
+ std::vector<base::Bucket> parsing_time_min_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.ParsingTimeMin");
+ std::vector<base::Bucket> parsing_time_total_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.ParsingTimeTotal");
+ EXPECT_EQ(parsing_time_max_buckets.size(), 1u);
+ EXPECT_EQ(parsing_time_min_buckets.size(), 1u);
+ EXPECT_EQ(parsing_time_total_buckets.size(), 1u);
+ EXPECT_GT(parsing_time_max_buckets[0].min, 0);
+ EXPECT_GT(parsing_time_min_buckets[0].min, 0);
+ EXPECT_GT(parsing_time_total_buckets[0].min, 0);
+
+ // For yields, the values should be the same because there was only one yield,
+ // but due to different histogram sizes we can't directly compare them.
+ std::vector<base::Bucket> yield_time_max_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.YieldedTimeMax");
+ std::vector<base::Bucket> yield_time_min_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.YieldedTimeMin");
+ std::vector<base::Bucket> yield_time_average_buckets =
+ histogram_tester.GetAllSamples("Blink.HTMLParsing.YieldedTimeAverage");
+ EXPECT_EQ(yield_time_max_buckets.size(), 1u);
+ EXPECT_EQ(yield_time_min_buckets.size(), 1u);
+ EXPECT_EQ(yield_time_average_buckets.size(), 1u);
+ EXPECT_GT(yield_time_max_buckets[0].min, 0);
+ EXPECT_GT(yield_time_min_buckets[0].min, 0);
+ EXPECT_GT(yield_time_average_buckets[0].min, 0);
+}
+
+TEST_F(HTMLParserMetricsTest, UkmStoresValuesCorrectly) {
+ // Although the tests use a mock clock, the metrics recorder checks if the
+ // system has a high resolution clock before recording results. As a result,
+ // the tests will fail if the system does not have a high resolution clock.
+ if (!base::TimeTicks::IsHighResolution())
+ return;
+
+ ukm::TestUkmRecorder recorder;
+ HTMLParserMetrics reporter(ukm::UkmRecorder::GetNewSourceID(), &recorder);
+
+ // Start with empty metrics
+ auto entries = recorder.GetEntriesByName("Blink.HTMLParsing");
+ EXPECT_EQ(entries.size(), 0u);
+
+ // Run a fictional sequence of calls
+ base::TimeDelta first_parse_time = base::TimeDelta::FromMicroseconds(20);
+ base::TimeDelta second_parse_time = base::TimeDelta::FromMicroseconds(10);
+ base::TimeDelta third_parse_time = base::TimeDelta::FromMicroseconds(30);
+ unsigned first_tokens_parsed = 50u;
+ unsigned second_tokens_parsed = 40u;
+ unsigned third_tokens_parsed = 60u;
+ base::TimeDelta first_yield_time = base::TimeDelta::FromMicroseconds(80);
+ base::TimeDelta second_yield_time = base::TimeDelta::FromMicroseconds(70);
+
+ reporter.AddChunk(first_parse_time, first_tokens_parsed);
+ reporter.AddYieldInterval(first_yield_time);
+ reporter.AddChunk(second_parse_time, second_tokens_parsed);
+ reporter.AddYieldInterval(second_yield_time);
+ reporter.AddChunk(third_parse_time, third_tokens_parsed);
+ reporter.ReportMetricsAtParseEnd();
+
+ // Check we have a single entry
+ entries = recorder.GetEntriesByName("Blink.HTMLParsing");
+ EXPECT_EQ(entries.size(), 1u);
+ auto* entry = entries[0];
+
+ // Verify all the values
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "ChunkCount"));
+ const int64_t* metric_value =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, "ChunkCount");
+ EXPECT_EQ(*metric_value, 3);
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "ParsingTimeMax"));
+ metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "ParsingTimeMax");
+ EXPECT_EQ(*metric_value, third_parse_time.InMicroseconds());
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "ParsingTimeMin"));
+ metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "ParsingTimeMin");
+ EXPECT_EQ(*metric_value, second_parse_time.InMicroseconds());
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "ParsingTimeTotal"));
+ metric_value =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, "ParsingTimeTotal");
+ EXPECT_EQ(*metric_value,
+ (first_parse_time + second_parse_time + third_parse_time)
+ .InMicroseconds());
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "TokensParsedMax"));
+ metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "TokensParsedMax");
+ EXPECT_EQ(*metric_value, third_tokens_parsed);
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "TokensParsedMin"));
+ metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "TokensParsedMin");
+ EXPECT_EQ(*metric_value, second_tokens_parsed);
+
+ EXPECT_TRUE(
+ ukm::TestUkmRecorder::EntryHasMetric(entry, "TokensParsedAverage"));
+ metric_value =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, "TokensParsedAverage");
+ EXPECT_EQ(
+ *metric_value,
+ (first_tokens_parsed + second_tokens_parsed + third_tokens_parsed) / 3);
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "YieldedTimeMax"));
+ metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "YieldedTimeMax");
+ EXPECT_EQ(*metric_value, first_yield_time.InMicroseconds());
+
+ EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entry, "YieldedTimeMin"));
+ metric_value = ukm::TestUkmRecorder::GetEntryMetric(entry, "YieldedTimeMin");
+ EXPECT_EQ(*metric_value, second_yield_time.InMicroseconds());
+
+ EXPECT_TRUE(
+ ukm::TestUkmRecorder::EntryHasMetric(entry, "YieldedTimeAverage"));
+ metric_value =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, "YieldedTimeAverage");
+ EXPECT_EQ(*metric_value,
+ ((first_yield_time + second_yield_time) / 2).InMicroseconds());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.cc
index 494d91f99cf..a5c4119348f 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.cc
@@ -26,19 +26,20 @@
#include "third_party/blink/renderer/core/html/parser/html_parser_options.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
HTMLParserOptions::HTMLParserOptions(Document* document) {
- if (!document)
+ if (!document || !document->GetFrame())
return;
- if (document->GetFrame()) {
- script_enabled = document->CanExecuteScripts(kNotAboutToExecuteScript);
- priority_hints_origin_trial_enabled =
- RuntimeEnabledFeatures::PriorityHintsEnabled(document);
- }
+ scripting_flag = (document->GetSettings()->GetParserScriptingFlagPolicy() ==
+ ParserScriptingFlagPolicy::kEnabled) ||
+ document->CanExecuteScripts(kNotAboutToExecuteScript);
+ priority_hints_origin_trial_enabled =
+ RuntimeEnabledFeatures::PriorityHintsEnabled(document);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.h
index 50011d16d10..267d50f5383 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_options.h
@@ -37,7 +37,8 @@ class CORE_EXPORT HTMLParserOptions {
DISALLOW_NEW();
public:
- bool script_enabled = false;
+ // https://html.spec.whatwg.org/#scripting-flag
+ bool scripting_flag = false;
// TODO(domfarolino): Remove this when Priority Hints is no longer in an
// Origin Trial. See https://crbug.com/821464.
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc
index 601f0eb325c..1559a1624ba 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.cc
@@ -40,10 +40,6 @@ SpeculationsPumpSession::SpeculationsPumpSession(unsigned& nesting_level)
SpeculationsPumpSession::~SpeculationsPumpSession() = default;
-inline base::TimeDelta SpeculationsPumpSession::ElapsedTime() const {
- return start_time_.Elapsed();
-}
-
void SpeculationsPumpSession::AddedElementTokens(size_t count) {
processed_element_tokens_ += count;
}
@@ -51,9 +47,7 @@ void SpeculationsPumpSession::AddedElementTokens(size_t count) {
HTMLParserScheduler::HTMLParserScheduler(
HTMLDocumentParser* parser,
scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner)
- : parser_(parser),
- loading_task_runner_(std::move(loading_task_runner)),
- is_paused_with_active_timer_(false) {}
+ : parser_(parser), loading_task_runner_(std::move(loading_task_runner)) {}
HTMLParserScheduler::~HTMLParserScheduler() = default;
@@ -62,37 +56,18 @@ void HTMLParserScheduler::Trace(Visitor* visitor) {
}
bool HTMLParserScheduler::IsScheduledForUnpause() const {
- return is_paused_with_active_timer_ ||
- cancellable_continue_parse_task_handle_.IsActive();
+ return cancellable_continue_parse_task_handle_.IsActive();
}
void HTMLParserScheduler::ScheduleForUnpause() {
- DCHECK(!is_paused_with_active_timer_);
cancellable_continue_parse_task_handle_ =
PostCancellableTask(*loading_task_runner_, FROM_HERE,
WTF::Bind(&HTMLParserScheduler::ContinueParsing,
WrapWeakPersistent(this)));
}
-void HTMLParserScheduler::Pause() {
- DCHECK(!is_paused_with_active_timer_);
- if (!cancellable_continue_parse_task_handle_.IsActive())
- return;
- is_paused_with_active_timer_ = true;
- cancellable_continue_parse_task_handle_.Cancel();
-}
-
-void HTMLParserScheduler::Unpause() {
- DCHECK(!cancellable_continue_parse_task_handle_.IsActive());
- if (!is_paused_with_active_timer_)
- return;
- is_paused_with_active_timer_ = false;
- ScheduleForUnpause();
-}
-
void HTMLParserScheduler::Detach() {
cancellable_continue_parse_task_handle_.Cancel();
- is_paused_with_active_timer_ = false;
}
inline bool HTMLParserScheduler::ShouldYield(
@@ -131,11 +106,6 @@ bool HTMLParserScheduler::YieldIfNeeded(const SpeculationsPumpSession& session,
return false;
}
-void HTMLParserScheduler::ForceUnpauseAfterYield() {
- DCHECK(!cancellable_continue_parse_task_handle_.IsActive());
- is_paused_with_active_timer_ = true;
-}
-
void HTMLParserScheduler::ContinueParsing() {
parser_->ResumeParsingAfterYield();
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h
index 9c63198537a..87d35d4a9f8 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h
@@ -42,10 +42,10 @@ class SpeculationsPumpSession : public NestingLevelIncrementer {
STACK_ALLOCATED();
public:
- SpeculationsPumpSession(unsigned& nesting_level);
+ explicit SpeculationsPumpSession(unsigned& nesting_level);
~SpeculationsPumpSession();
- base::TimeDelta ElapsedTime() const;
+ base::TimeDelta ElapsedTime() const { return start_time_.Elapsed(); }
void AddedElementTokens(size_t count);
size_t ProcessedElementTokens() const { return processed_element_tokens_; }
@@ -64,18 +64,6 @@ class HTMLParserScheduler final : public GarbageCollected<HTMLParserScheduler> {
void ScheduleForUnpause();
bool YieldIfNeeded(const SpeculationsPumpSession&, bool starting_script);
- /**
- * Can only be called if this scheduler is paused. If this is called,
- * then after the scheduler is resumed by calling resume(), this call
- * ensures that HTMLDocumentParser::resumeAfterYield will be called. Used to
- * signal this scheduler that the background html parser sent chunks to
- * HTMLDocumentParser while it was paused.
- */
- void ForceUnpauseAfterYield();
-
- void Pause();
- void Unpause();
-
void Detach(); // Clear active tasks if any.
void Trace(Visitor*);
@@ -88,7 +76,6 @@ class HTMLParserScheduler final : public GarbageCollected<HTMLParserScheduler> {
scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
TaskHandle cancellable_continue_parse_task_handle_;
- bool is_paused_with_active_timer_;
DISALLOW_COPY_AND_ASSIGN(HTMLParserScheduler);
};
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index 0d4a5339a14..c2410ab5a27 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -58,7 +58,6 @@
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
-#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -114,8 +113,10 @@ static String InitiatorFor(const StringImpl* tag_impl) {
static bool MediaAttributeMatches(const MediaValuesCached& media_values,
const String& attribute_value) {
+ // Since this is for preload scanning only, ExecutionContext-based origin
+ // trials for media queries are not needed.
scoped_refptr<MediaQuerySet> media_queries =
- MediaQuerySet::Create(attribute_value);
+ MediaQuerySet::Create(attribute_value, nullptr);
MediaQueryEvaluator media_query_evaluator(media_values);
return media_query_evaluator.Eval(*media_queries);
}
@@ -162,7 +163,8 @@ class TokenPreloadScanner::StartTagScanner {
if (Match(tag_impl_, html_names::kImgTag) ||
Match(tag_impl_, html_names::kSourceTag) ||
Match(tag_impl_, html_names::kLinkTag)) {
- source_size_ = SizesAttributeParser(media_values_, String()).length();
+ source_size_ =
+ SizesAttributeParser(media_values_, String(), nullptr).length();
return;
}
if (!Match(tag_impl_, html_names::kInputTag) &&
@@ -470,9 +472,10 @@ class TokenPreloadScanner::StartTagScanner {
img_src_url_ = attribute_value;
} else if (Match(attribute_name, html_names::kRelAttr)) {
LinkRelAttribute rel(attribute_value);
- link_is_style_sheet_ = rel.IsStyleSheet() && !rel.IsAlternate() &&
- rel.GetIconType() == kInvalidIcon &&
- !rel.IsDNSPrefetch();
+ link_is_style_sheet_ =
+ rel.IsStyleSheet() && !rel.IsAlternate() &&
+ rel.GetIconType() == mojom::blink::FaviconIconType::kInvalid &&
+ !rel.IsDNSPrefetch();
link_is_preconnect_ = rel.IsPreconnect();
link_is_preload_ = rel.IsLinkPreload();
link_is_modulepreload_ = rel.IsModulePreload();
@@ -517,8 +520,8 @@ class TokenPreloadScanner::StartTagScanner {
if (Match(attribute_name, html_names::kSrcAttr)) {
SetUrlToLoad(attribute_value, kDisallowURLReplacement);
} else if (Match(attribute_name, html_names::kTypeAttr)) {
- input_is_image_ = DeprecatedEqualIgnoringCase(attribute_value,
- input_type_names::kImage);
+ input_is_image_ =
+ EqualIgnoringASCIICase(attribute_value, input_type_names::kImage);
}
}
@@ -693,7 +696,7 @@ class TokenPreloadScanner::StartTagScanner {
void ParseSourceSize(const String& attribute_value) {
source_size_ =
- SizesAttributeParser(media_values_, attribute_value).length();
+ SizesAttributeParser(media_values_, attribute_value, nullptr).length();
source_size_set_ = true;
}
@@ -745,7 +748,7 @@ class TokenPreloadScanner::StartTagScanner {
mojom::FetchImportanceMode importance_;
bool importance_mode_set_;
String nonce_;
- Member<MediaValuesCached> media_values_;
+ MediaValuesCached* media_values_;
bool referrer_policy_set_;
network::mojom::ReferrerPolicy referrer_policy_;
bool integrity_attr_set_;
@@ -878,13 +881,13 @@ static void HandleMetaNameAttribute(
return;
String content_attribute_value(content_attribute->Value());
- if (DeprecatedEqualIgnoringCase(name_attribute_value, "viewport")) {
+ if (EqualIgnoringASCIICase(name_attribute_value, "viewport")) {
HandleMetaViewport(content_attribute_value, document_parameters,
media_values, viewport);
return;
}
- if (DeprecatedEqualIgnoringCase(name_attribute_value, "referrer")) {
+ if (EqualIgnoringASCIICase(name_attribute_value, "referrer")) {
HandleMetaReferrer(content_attribute_value, document_parameters,
css_scanner);
}
@@ -960,11 +963,11 @@ void TokenPreloadScanner::ScanCommon(
token.GetAttributeItem(html_names::kHttpEquivAttr);
if (equiv_attribute) {
String equiv_attribute_value(equiv_attribute->Value());
- if (DeprecatedEqualIgnoringCase(equiv_attribute_value,
- "content-security-policy")) {
+ if (EqualIgnoringASCIICase(equiv_attribute_value,
+ "content-security-policy")) {
*is_csp_meta_tag = true;
- } else if (DeprecatedEqualIgnoringCase(equiv_attribute_value,
- "accept-ch")) {
+ } else if (EqualIgnoringASCIICase(equiv_attribute_value,
+ "accept-ch")) {
const typename Token::Attribute* content_attribute =
token.GetAttributeItem(html_names::kContentAttr);
if (content_attribute) {
@@ -1097,7 +1100,8 @@ CachedDocumentParameters::CachedDocumentParameters(Document* document) {
viewport_meta_enabled = document->GetSettings() &&
document->GetSettings()->GetViewportMetaEnabled();
referrer_policy = document->GetReferrerPolicy();
- integrity_features = SubresourceIntegrityHelper::GetFeatures(document);
+ integrity_features =
+ SubresourceIntegrityHelper::GetFeatures(document->GetExecutionContext());
lazyload_policy_enforced = document->IsLazyLoadPolicyEnforced();
if (document->Loader() && document->Loader()->GetFrame()) {
lazy_load_image_setting =
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
index 7247ddc7857..1929b81aacd 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
@@ -40,7 +40,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
HTMLParserOptions options;
- options.script_enabled = fuzzed_data.ConsumeBool();
+ options.scripting_flag = fuzzed_data.ConsumeBool();
std::unique_ptr<CachedDocumentParameters> document_parameters =
CachedDocumentParametersForFuzzing(fuzzed_data);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
index b4699156f62..9ac9b6412bf 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -146,7 +146,8 @@ class HTMLMockHTMLResourcePreloader : public ResourcePreloader {
PreloadRequestVerification(type, url, base_url, width, referrer_policy);
Resource* resource = preload_request_->Start(document);
ASSERT_TRUE(resource);
- EXPECT_EQ(expected_referrer, resource->GetResourceRequest().HttpReferrer());
+ EXPECT_EQ(expected_referrer,
+ resource->GetResourceRequest().ReferrerString());
}
void PreconnectRequestVerification(const String& host,
@@ -633,11 +634,11 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCH) {
"640w'>",
"blabla.gif", "http://example.test/", ResourceType::kImage, 0},
{"http://example.test",
- "<meta http-equiv='accept-ch' content='dpr \t'><img srcset='bla.gif "
+ "<meta http-equiv='accept-ch' content='dpr '><img srcset='bla.gif "
"320w, blabla.gif 640w'>",
"blabla.gif", "http://example.test/", ResourceType::kImage, 0, dpr},
{"http://example.test",
- "<meta http-equiv='accept-ch' content='bla,dpr \t'><img srcset='bla.gif "
+ "<meta http-equiv='accept-ch' content='bla,dpr '><img srcset='bla.gif "
"320w, blabla.gif 640w'>",
"blabla.gif", "http://example.test/", ResourceType::kImage, 0, dpr},
{"http://example.test",
@@ -662,7 +663,7 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCH) {
viewport_width},
{"http://example.test",
"<meta http-equiv='accept-ch' content=' viewport-width ,width, "
- "wutever, dpr \t'><img sizes='90vw' srcset='bla.gif 320w, blabla.gif "
+ "wutever, dpr '><img sizes='90vw' srcset='bla.gif 320w, blabla.gif "
"640w'>",
"blabla.gif", "http://example.test/", ResourceType::kImage, 450, all},
};
@@ -684,7 +685,7 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCHInsecureDocument) {
const PreloadScannerTestCase expect_no_client_hint = {
"http://example.test",
"<meta http-equiv='accept-ch' content=' viewport-width ,width, "
- "wutever, dpr \t'><img sizes='90vw' srcset='bla.gif 320w, blabla.gif "
+ "wutever, dpr '><img sizes='90vw' srcset='bla.gif 320w, blabla.gif "
"640w'>",
"blabla.gif",
"http://example.test/",
@@ -694,7 +695,7 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCHInsecureDocument) {
const PreloadScannerTestCase expect_client_hint = {
"http://example.test",
"<meta http-equiv='accept-ch' content=' viewport-width ,width, "
- "wutever, dpr \t'><img sizes='90vw' srcset='bla.gif 320w, blabla.gif "
+ "wutever, dpr '><img sizes='90vw' srcset='bla.gif 320w, blabla.gif "
"640w'>",
"blabla.gif",
"http://example.test/",
@@ -871,9 +872,7 @@ TEST_F(HTMLPreloadScannerTest, testReferrerPolicy) {
"referrerpolicy='strict-origin-when-cross-origin' "
"href='bla.gif'/>",
"bla.gif", "http://example.test/", ResourceType::kImage, 0,
- network::mojom::ReferrerPolicy::
- kNoReferrerWhenDowngradeOriginWhenCrossOrigin,
- nullptr},
+ network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin, nullptr},
{"http://example.test",
"<link rel='stylesheet' href='sheet.css' type='text/css'>", "sheet.css",
"http://example.test/", ResourceType::kCSSStyleSheet, 0,
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc
index 4a040fb80b0..7d3025bbee5 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc
@@ -32,12 +32,16 @@
#include "third_party/blink/renderer/core/html/parser/html_srcset_parser.h"
#include <algorithm>
+
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/platform/web_network_state_notifier.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
@@ -197,9 +201,10 @@ static void SrcsetError(Document* document, String message) {
StringBuilder error_message;
error_message.Append("Failed parsing 'srcset' attribute value since ");
error_message.Append(message);
- document->GetFrame()->Console().AddMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kOther, mojom::ConsoleMessageLevel::kError,
- error_message.ToString()));
+ document->GetFrame()->Console().AddMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::ConsoleMessageSource::kOther,
+ mojom::ConsoleMessageLevel::kError, error_message.ToString()));
}
}
@@ -328,14 +333,15 @@ static void ParseImageCandidatesFromSrcsetAttribute(
if (document) {
UseCounter::Count(document, WebFeature::kSrcsetDroppedCandidate);
if (document->GetFrame()) {
- document->GetFrame()->Console().AddMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kOther,
- mojom::ConsoleMessageLevel::kError,
- String("Dropped srcset candidate ") +
- JSONValue::QuoteString(
- String(image_url_start,
- static_cast<wtf_size_t>(image_url_end -
- image_url_start)))));
+ document->GetFrame()->Console().AddMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::ConsoleMessageSource::kOther,
+ mojom::ConsoleMessageLevel::kError,
+ String("Dropped srcset candidate ") +
+ JSONValue::QuoteString(
+ String(image_url_start,
+ static_cast<wtf_size_t>(image_url_end -
+ image_url_start)))));
}
}
continue;
@@ -444,8 +450,12 @@ static ImageCandidate PickBestImageCandidate(
de_duped_image_candidates.push_back(&image);
prev_density = image.Density();
}
+
unsigned winner =
- SelectionLogic(de_duped_image_candidates, device_scale_factor);
+ blink::WebNetworkStateNotifier::SaveDataEnabled() &&
+ base::FeatureList::IsEnabled(blink::features::kSaveDataImgSrcset)
+ ? 0
+ : SelectionLogic(de_duped_image_candidates, device_scale_factor);
DCHECK_LT(winner, de_duped_image_candidates.size());
winner = AvoidDownloadIfHigherDensityResourceIsInCache(
de_duped_image_candidates, winner, document);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.h b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.h
index 1270664c288..9af275482ca 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser.h
@@ -41,7 +41,7 @@ namespace blink {
class Document;
-enum { kUninitializedDescriptor = -1 };
+constexpr int kUninitializedDescriptor = -1;
class DescriptorParsingResult {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc
index cc3aed6a9fe..9b8791ad9db 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_srcset_parser_test.cc
@@ -4,9 +4,13 @@
#include "third_party/blink/renderer/core/html/parser/html_srcset_parser.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include <limits.h>
+#include "base/test/scoped_feature_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/platform/web_network_state_notifier.h"
+
namespace blink {
typedef struct {
@@ -173,4 +177,150 @@ TEST(HTMLSrcsetParserTest, Basic) {
}
}
+TEST(HTMLSrcsetParserTest, SaveDataEnabledBasic) {
+ SrcsetParserTestCase test_cases[] = {
+ // 0
+ {2.0, 0.5, "", "data:,a 1w, data:,b 2x", "data:,a", 2.0, 1},
+ {2.0, 1, "", "data:,a 2w, data:,b 2x", "data:,a", 2.0, 2},
+ {2.0, -1, "", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1},
+ {2.0, -1, "", "1x.gif 1q, 2x.gif 2x", "2x.gif", 2.0, -1},
+ {1.0, -1, "", "1x.gif 1q, 2x.gif 2x", "2x.gif", 2.0, -1},
+ {1.0, -1, "", "1x.gif 1x 100h, 2x.gif 2x", "2x.gif", 2.0, -1}, // 5
+ {1.0, -1, "", "1x.gif 1x 100w, 2x.gif 2x", "2x.gif", 2.0, -1},
+ {1.0, -1, "", "1x.gif 1x 100h 100w, 2x.gif 2x", "2x.gif", 2.0, -1},
+ {2.0, -1, "", "1x.gif 1x, 2x.gif -2x", "1x.gif", 1.0, -1},
+ {2.0, -1, "", "0x.gif 0x", "0x.gif", 0.0, -1},
+ {2.0, -1, "", "0x.gif -0x", "0x.gif", 0.0, -1}, // 10
+ {2.0, -1, "", "neg.gif -2x", "", 1.0, -1},
+ {2.0, -1, "", "1x.gif 1x, 2x.gif 2q", "1x.gif", 1.0, -1},
+ {2.0, -1, "", "1x.gif, 2x.gif 2q", "1x.gif", 1.0, -1},
+ {2.0, -1, "", "1x.gif , 2x.gif 2q", "1x.gif", 1.0, -1},
+ {2.0, -1, "1x.gif 1x, 2x.gif 2x", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0,
+ -1}, // 15
+ {1.0, -1, "1x.gif 1x, 2x.gif 2x", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0,
+ -1},
+ {1.0, -1, "1x.gif 1x, 2x.gif 2x", "", "1x.gif 1x, 2x.gif 2x", 1.0, -1},
+ {2.0, -1, "src.gif", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1},
+ {1.0, -1, "src.gif", "1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1},
+ {1.0, -1, "src.gif", "2x.gif 2x", "src.gif", 1.0, -1}, // 20
+ {2.0, -1, "src.gif", "2x.gif 2x", "src.gif", 1.0, -1},
+ {2.0, -1, "src.gif", "2x.gif 2px", "src.gif", 1.0, -1},
+ {2.0, -1, "src.gif", "2x.gif 2ex", "src.gif", 1.0, -1},
+ {10.0, -1, "src.gif", "2x.gif 2e1x", "src.gif", 1.0, -1},
+ {2.0, -1, "src.gif", "2x.gif 2e1x", "src.gif", 1.0, -1}, // 25
+ {2.0, -1, "src.gif", "2x.gif +2x", "src.gif", 1.0, -1},
+ {1.5, -1, "src.gif", "2x.gif 2x", "src.gif", 1.0, -1},
+ {2.5, -1, "src.gif", "2x.gif 2x", "src.gif", 1.0, -1},
+ {2.5, -1, "src.gif", "2x.gif 2x, 3x.gif 3x", "src.gif", 1.0, -1},
+ {2.0, -1, "", "1x,, , x ,2x ", "1x", 1.0, -1}, // 30
+ {2.0, -1, "", "1x,, , x ,2x ", "1x", 1.0, -1},
+ {2.0, -1, "", ",,1x,, , x ,2x ", "1x", 1.0, -1},
+ {2.0, -1, "", ",,1x,,", "1x", 1.0, -1},
+ {2.0, -1, "", ",1x,", "1x", 1.0, -1},
+ {2.0, -1, "",
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg 1x, 2x.gif 2x",
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg", 1.0, -1}, // 35
+ {2.0, -1, "",
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg 2x, 1x.gif 1x", "1x.gif",
+ 1.0, -1},
+ {2.0, -1, "",
+ "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, "
+ "2x.gif 2x ,",
+ "1x", 1.0, -1},
+ {4.0, -1, "",
+ "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100h, 5x.gif 5, dx.gif dx, "
+ "2x.gif 2x ,",
+ "1x", 1.0, -1},
+ {4.0, -1, "",
+ "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, "
+ "2x.gif 2x ,",
+ "1x", 1.0, -1},
+ {1.0, -1, "",
+ "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, "
+ "2x.gif 2x ,",
+ "1x", 1.0, -1}, // 40
+ {5.0, -1, "",
+ "1x,, , x ,2x , 1x.gif, 3x, 4x.gif 4x 100z, 5x.gif 5, dx.gif dx, "
+ "2x.gif 2x ,",
+ "1x", 1.0, -1},
+ {2.0, -1, "",
+ "1x.gif 1x, "
+ "data:image/"
+ "svg+xml;base64,"
+ "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGh"
+ "laWdodD0iMTAwIj4KCTxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJncm"
+ "VlbiIvPgo8L3N2Zz4K 2x",
+ "1x.gif", 1.0, -1},
+ {2.0, -1, "1x.gif",
+ "data:image/"
+ "svg+xml;base64,"
+ "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGh"
+ "laWdodD0iMTAwIj4KCTxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJncm"
+ "VlbiIvPgo8L3N2Zz4K 2x",
+ "1x.gif", 1.0, -1},
+ {2.0, -1, "1x.svg#red", "1x.svg#green 2x", "1x.svg#red", 1.0, -1},
+ {2.0, -1, "", "1x.svg#red 1x, 1x.svg#green 2x", "1x.svg#red", 1.0,
+ -1}, // 45
+ {1.0, 400, "", "400.gif 400w, 6000.gif 6000w", "400.gif", 1.0, 400},
+ {1.0, 400, "", "400.gif 400pw, 6000.gif 6000w", "6000.gif", 15.0, 6000},
+ {1.0, 400, "fallback.gif", "400.gif 400pw", "fallback.gif", 1.0, -1},
+ {1.0, 400, "fallback.gif", "400.gif +400w", "fallback.gif", 1.0, -1},
+ {1.0, 400, "", "400.gif 400w 400h, 6000.gif 6000w", "400.gif", 1.0,
+ 400}, // 50
+ {4.0, 400, "", "400.gif 400w, 6000.gif 6000w", "400.gif", 1.0, 400},
+ {3.8, 400, "", "400.gif 400w, 6000.gif 6000w", "400.gif", 1.0, 400},
+ {0.9, 800, "src.gif", "400.gif 400w", "400.gif", 0.5, 400},
+ {0.9, 800, "src.gif", "1x.gif 1x, 400.gif 400w", "400.gif", 0.5, 400},
+ {0.9, 800, "src.gif", "1x.gif 0.6x, 400.gif 400w", "400.gif", 0.5,
+ 400}, // 55
+ {0.9, 800, "src.gif", "1x.gif 1x, 400.gif 720w", "400.gif", 0.9, 720},
+ {0.9, 800, "src.gif", "1x.gif 1x, 400.gif 719w", "400.gif", 719.0 / 800.0,
+ 719},
+ {2.0, 800, "src.gif", "400.gif 400w", "400.gif", 0.5, 400},
+ {1.0, 400, "src.gif", "800.gif 800w", "800.gif", 2.0, 800},
+ {1.0, 400, "src.gif", "0.gif 0w, 800.gif 800w", "800.gif", 2.0,
+ 800}, // 60
+ {1.0, 400, "src.gif", "0.gif 0w, 2x.gif 2x", "src.gif", 1.0, -1},
+ {1.0, 400, "src.gif", "800.gif 2x, 1600.gif 1600w", "800.gif", 2.0, -1},
+ {1.0, 400, "", "400.gif 400w, 2x.gif 2x", "400.gif", 1.0, 400},
+ {2.0, 400, "", "400.gif 400w, 2x.gif 2x", "400.gif", 1.0, 400},
+ {1.0, 0, "", "400.gif 400w, 6000.gif 6000w", "400.gif",
+ std::numeric_limits<float>::infinity(), 400}, // 65
+ {2.0, -1, "", ", 1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1},
+ {1.0, -1, "", ",1x.gif 1x, 2x.gif 2x", "1x.gif", 1.0, -1},
+ {1.0, -1, "", ",1x.gif 1.x , 2x.gif 2x", "2x.gif", 2.0, -1},
+ {1.2, -1, "", ",1x.gif 1x, 1.4x.gif 1.4x, 2x.gif 2x", "1x.gif", 1.0, -1},
+ {1.0, -1, "", "inf.gif 0.00000000001x", "inf.gif", 1e-11, -1}, // 70
+ {1.0, -1, "", "data:,a ( , data:,b 1x, ), data:,c", "data:,c", 1.0, -1},
+ {1.0, 1, "", "data:,a 1w 1h", "data:,a", 1.0, 1},
+ {1.0, -1, "", ",1x.gif 1x future-descriptor(3x, 4h, whatever), 2x.gif 2x",
+ "2x.gif", 2.0, -1},
+ {2.0, -1, "", ",1x.gif 1x future-descriptor(3x, 4h, whatever), 2x.gif 2x",
+ "2x.gif", 2.0, -1},
+ {1.0, -1, "", "data:,a 1 w", "", 1.0, -1}, // 75
+ {1.0, -1, "", "data:,a 1 w", "", 1.0, -1},
+ {1.0, -1, "", "data:,a +1x", "", 1.0, -1},
+ {1.0, -1, "", "data:,a +1x", "", 1.0, -1},
+ {1.0, -1, "", "data:,a 1.0x", "data:,a", 1.0, -1},
+ {1.0, -1, "", "1%20and%202.gif 1x", "1%20and%202.gif", 1.0, -1}, // 80
+ {1.0, 700, "", "data:,a 0.5x, data:,b 1400w", "data:,a", 0.5, -1},
+ {0, 0, nullptr, nullptr, nullptr,
+ 0} // Do not remove the terminator line.
+ };
+
+ blink::WebNetworkStateNotifier::SetSaveDataEnabled(true);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures({blink::features::kSaveDataImgSrcset},
+ {});
+ for (unsigned i = 0; test_cases[i].src_input; ++i) {
+ SrcsetParserTestCase test = test_cases[i];
+ ImageCandidate candidate = BestFitSourceForImageAttributes(
+ test.device_scale_factor, test.effective_size, test.src_input,
+ test.srcset_input);
+ ASSERT_EQ(test.output_density, candidate.Density());
+ ASSERT_EQ(test.output_resource_width, candidate.GetResourceWidth());
+ ASSERT_EQ(test.output_url, candidate.ToString().Ascii());
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
index 5340cb22bab..241efc1df37 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer.cc
@@ -1465,7 +1465,7 @@ void HTMLTokenizer::UpdateStateFor(const String& tag_name) {
ThreadSafeMatch(tag_name, html_names::kNoembedTag) ||
ThreadSafeMatch(tag_name, html_names::kNoframesTag) ||
(ThreadSafeMatch(tag_name, html_names::kNoscriptTag) &&
- options_.script_enabled))
+ options_.scripting_flag))
SetState(HTMLTokenizer::kRAWTEXTState);
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc
index e0fb488daa7..a21c158d304 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc
@@ -20,7 +20,7 @@ int FuzzTokenizer(const uint8_t* data, size_t size) {
// Use the first byte of fuzz data to randomize the tokenizer options.
HTMLParserOptions options;
- options.script_enabled = fuzzed_data_provider.ConsumeBool();
+ options.scripting_flag = fuzzed_data_provider.ConsumeBool();
std::unique_ptr<HTMLTokenizer> tokenizer =
std::make_unique<HTMLTokenizer>(options);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index a33e0b6aca0..24f19c4dc6e 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
@@ -43,6 +44,7 @@
#include "third_party/blink/renderer/core/html/parser/html_token.h"
#include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/core/xlink_names.h"
@@ -765,7 +767,7 @@ void HTMLTreeBuilder::ProcessStartTagForInBody(AtomicHTMLToken* token) {
Attribute* type_attribute = token->GetAttributeItem(html_names::kTypeAttr);
bool disable_frameset =
!type_attribute ||
- !DeprecatedEqualIgnoringCase(type_attribute->Value(), "hidden");
+ !EqualIgnoringASCIICase(type_attribute->Value(), "hidden");
tree_.ReconstructTheActiveFormattingElements();
tree_.InsertSelfClosingHTMLElementDestroyingToken(token);
@@ -812,7 +814,7 @@ void HTMLTreeBuilder::ProcessStartTagForInBody(AtomicHTMLToken* token) {
ProcessGenericRawTextStartTag(token);
return;
}
- if (token->GetName() == html_names::kNoscriptTag && options_.script_enabled) {
+ if (token->GetName() == html_names::kNoscriptTag && options_.scripting_flag) {
ProcessGenericRawTextStartTag(token);
return;
}
@@ -909,10 +911,50 @@ bool HTMLTreeBuilder::ProcessTemplateEndTag(AtomicHTMLToken* token) {
tree_.GenerateImpliedEndTags();
if (!tree_.CurrentStackItem()->HasTagName(html_names::kTemplateTag))
ParseError(token);
- tree_.OpenElements()->PopUntilPopped(html_names::kTemplateTag);
+ tree_.OpenElements()->PopUntil(html_names::kTemplateTag.LocalName());
+ HTMLStackItem* template_stack_item =
+ tree_.OpenElements()->TopRecord()->StackItem();
+ tree_.OpenElements()->Pop();
+ HTMLStackItem* shadow_host_stack_item =
+ tree_.OpenElements()->TopRecord()->StackItem();
tree_.ActiveFormattingElements()->ClearToLastMarker();
template_insertion_modes_.pop_back();
ResetInsertionModeAppropriately();
+ // Check for a declarative shadow root.
+ if (RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled() &&
+ template_stack_item) {
+ if (Attribute* type_attribute = template_stack_item->GetAttributeItem(
+ html_names::kShadowrootAttr)) {
+ String shadow_mode = type_attribute->Value();
+ bool is_open = EqualIgnoringASCIICase(shadow_mode, "open");
+ if (is_open || EqualIgnoringASCIICase(shadow_mode, "closed")) {
+ DCHECK(template_stack_item->IsElementNode());
+ DCHECK(shadow_host_stack_item);
+ DCHECK(shadow_host_stack_item->IsElementNode());
+ UseCounter::Count(shadow_host_stack_item->GetElement()->GetDocument(),
+ WebFeature::kDeclarativeShadowRoot);
+ bool delegates_focus = template_stack_item->GetAttributeItem(
+ html_names::kShadowrootdelegatesfocusAttr);
+ // TODO(1063157): Add an attribute for imperative slot assignment.
+ bool manual_slotting = false;
+ shadow_host_stack_item->GetElement()->AttachDeclarativeShadowRoot(
+ DynamicTo<HTMLTemplateElement>(template_stack_item->GetElement()),
+ is_open ? ShadowRootType::kOpen : ShadowRootType::kClosed,
+ delegates_focus ? FocusDelegation::kDelegateFocus
+ : FocusDelegation::kNone,
+ manual_slotting ? SlotAssignmentMode::kManual
+ : SlotAssignmentMode::kAuto);
+ } else {
+ tree_.OwnerDocumentForCurrentNode().AddConsoleMessage(
+ MakeGarbageCollected<ConsoleMessage>(
+ mojom::blink::ConsoleMessageSource::kOther,
+ mojom::blink::ConsoleMessageLevel::kWarning,
+ "Invalid declarative shadowroot attribute value \"" +
+ shadow_mode +
+ "\". Valid values include \"open\" and \"closed\"."));
+ }
+ }
+ }
return true;
}
@@ -1012,7 +1054,7 @@ void HTMLTreeBuilder::ProcessStartTagForInTable(AtomicHTMLToken* token) {
if (token->GetName() == html_names::kInputTag) {
Attribute* type_attribute = token->GetAttributeItem(html_names::kTypeAttr);
if (type_attribute &&
- DeprecatedEqualIgnoringCase(type_attribute->Value(), "hidden")) {
+ EqualIgnoringASCIICase(type_attribute->Value(), "hidden")) {
ParseError(token);
tree_.InsertSelfClosingHTMLElementDestroyingToken(token);
return;
@@ -2628,7 +2670,7 @@ bool HTMLTreeBuilder::ProcessStartTagForInHead(AtomicHTMLToken* token) {
return true;
}
if (token->GetName() == html_names::kNoscriptTag) {
- if (options_.script_enabled) {
+ if (options_.scripting_flag) {
ProcessGenericRawTextStartTag(token);
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc
index 3da53b045b1..ea11a426b6c 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator.cc
@@ -191,7 +191,7 @@ HTMLTreeBuilderSimulator::SimulatedToken HTMLTreeBuilderSimulator::Simulate(
ThreadSafeMatch(tag_name, html_names::kNoembedTag) ||
ThreadSafeMatch(tag_name, html_names::kNoframesTag) ||
(ThreadSafeMatch(tag_name, html_names::kNoscriptTag) &&
- options_.script_enabled)) {
+ options_.scripting_flag)) {
tokenizer->SetState(HTMLTokenizer::kRAWTEXTState);
}
}
@@ -270,9 +270,9 @@ bool HTMLTreeBuilderSimulator::IsHTMLIntegrationPointForStartTag(
}
} else if (tokens_ns == SVG) {
// FIXME: It's very fragile that we special case foreignObject here to be
- // case-insensitive.
- if (DeprecatedEqualIgnoringCase(tag_name,
- svg_names::kForeignObjectTag.LocalName()))
+ // ASCII case-insensitive.
+ if (EqualIgnoringASCIICase(tag_name,
+ svg_names::kForeignObjectTag.LocalName()))
return true;
return ThreadSafeMatch(tag_name, svg_names::kDescTag) ||
ThreadSafeMatch(tag_name, svg_names::kTitleTag);
@@ -299,9 +299,9 @@ bool HTMLTreeBuilderSimulator::IsHTMLIntegrationPointForEndTag(
return ThreadSafeMatch(tag_name, mathml_names::kAnnotationXmlTag);
if (tokens_ns == SVG) {
// FIXME: It's very fragile that we special case foreignObject here to be
- // case-insensitive.
- if (DeprecatedEqualIgnoringCase(tag_name,
- svg_names::kForeignObjectTag.LocalName()))
+ // ASCII case-insensitive.
+ if (EqualIgnoringASCIICase(tag_name,
+ svg_names::kForeignObjectTag.LocalName()))
return true;
return ThreadSafeMatch(tag_name, svg_names::kDescTag) ||
ThreadSafeMatch(tag_name, svg_names::kTitleTag);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_view_source_parser_test.cc b/chromium/third_party/blink/renderer/core/html/parser/html_view_source_parser_test.cc
index 2e98f7e4ad8..3bd21514f75 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_view_source_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_view_source_parser_test.cc
@@ -17,7 +17,7 @@ namespace blink {
TEST(HTMLViewSourceParserTest, DetachThenFinish_ShouldNotCrash) {
String mime_type("text/html");
auto* document = MakeGarbageCollected<HTMLViewSourceDocument>(
- DocumentInit::Create(), mime_type);
+ DocumentInit::Create().WithTypeFrom(mime_type));
auto* parser =
MakeGarbageCollected<HTMLViewSourceParser>(*document, mime_type);
// A client may detach the parser from the document.
diff --git a/chromium/third_party/blink/renderer/core/html/parser/parser_scripting_flag_policy.h b/chromium/third_party/blink/renderer/core/html/parser/parser_scripting_flag_policy.h
new file mode 100644
index 00000000000..48d44e856e0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/parser/parser_scripting_flag_policy.h
@@ -0,0 +1,16 @@
+// Copyright 2020 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_HTML_PARSER_PARSER_SCRIPTING_FLAG_POLICY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_PARSER_SCRIPTING_FLAG_POLICY_H_
+
+namespace blink {
+
+// Decides whether the scripting flag of the parser should be set to enabled.
+// https://html.spec.whatwg.org/#scripting-flag
+enum class ParserScriptingFlagPolicy { kOnlyIfScriptIsEnabled, kEnabled };
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PARSER_PARSER_SCRIPTING_FLAG_POLICY_H_
diff --git a/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc b/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
index b90b9f0936b..a355cb13d0b 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -28,6 +28,33 @@ KURL PreloadRequest::CompleteURL(Document* document) {
return document->CompleteURL(resource_url_);
}
+// static
+std::unique_ptr<PreloadRequest> PreloadRequest::CreateIfNeeded(
+ const String& initiator_name,
+ const TextPosition& initiator_position,
+ const String& resource_url,
+ const KURL& base_url,
+ ResourceType resource_type,
+ const network::mojom::ReferrerPolicy referrer_policy,
+ ReferrerSource referrer_source,
+ ResourceFetcher::IsImageSet is_image_set,
+ const FetchParameters::ResourceWidth& resource_width,
+ const ClientHintsPreferences& client_hints_preferences,
+ RequestType request_type) {
+ // Never preload data URLs. We also disallow relative ref URLs which become
+ // data URLs if the document's URL is a data URL. We don't want to create
+ // extra resource requests with data URLs to avoid copy / initialization
+ // overhead, which can be significant for large URLs.
+ if (resource_url.IsEmpty() || resource_url.StartsWith("#") ||
+ ProtocolIs(resource_url, "data")) {
+ return nullptr;
+ }
+ return base::WrapUnique(new PreloadRequest(
+ initiator_name, initiator_position, resource_url, base_url, resource_type,
+ resource_width, client_hints_preferences, request_type, referrer_policy,
+ referrer_source, is_image_set));
+}
+
Resource* PreloadRequest::Start(Document* document) {
DCHECK(IsMainThread());
@@ -47,6 +74,8 @@ Resource* PreloadRequest::Start(Document* document) {
resource_request.SetRequestContext(
ResourceFetcher::DetermineRequestContext(resource_type_, is_image_set_));
+ resource_request.SetRequestDestination(
+ ResourceFetcher::DetermineRequestDestination(resource_type_));
resource_request.SetFetchImportanceMode(importance_);
@@ -59,7 +88,7 @@ Resource* PreloadRequest::Start(Document* document) {
ResourceLoaderOptions options;
options.initiator_info = initiator_info;
- FetchParameters params(resource_request, options);
+ FetchParameters params(std::move(resource_request), options);
if (resource_type_ == ResourceType::kImportResource) {
const SecurityOrigin* security_origin =
@@ -116,8 +145,7 @@ Resource* PreloadRequest::Start(Document* document) {
params.SetLazyImagePlaceholder();
}
- return PreloadHelper::StartPreload(resource_type_, params,
- document->Fetcher());
+ return PreloadHelper::StartPreload(resource_type_, params, *document);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/parser/preload_request.h b/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
index afb88f92b21..761f071fa3f 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
@@ -39,8 +39,6 @@ class CORE_EXPORT PreloadRequest {
enum ReferrerSource { kDocumentIsReferrer, kBaseUrlIsReferrer };
- // TODO(csharrison): Move the implementation to the cpp file when core/html
- // gets its own testing source set in html/BUILD.gn.
static std::unique_ptr<PreloadRequest> CreateIfNeeded(
const String& initiator_name,
const TextPosition& initiator_position,
@@ -54,20 +52,7 @@ class CORE_EXPORT PreloadRequest {
FetchParameters::ResourceWidth(),
const ClientHintsPreferences& client_hints_preferences =
ClientHintsPreferences(),
- RequestType request_type = kRequestTypePreload) {
- // Never preload data URLs. We also disallow relative ref URLs which become
- // data URLs if the document's URL is a data URL. We don't want to create
- // extra resource requests with data URLs to avoid copy / initialization
- // overhead, which can be significant for large URLs.
- if (resource_url.IsEmpty() || resource_url.StartsWith("#") ||
- ProtocolIs(resource_url, "data")) {
- return nullptr;
- }
- return base::WrapUnique(new PreloadRequest(
- initiator_name, initiator_position, resource_url, base_url,
- resource_type, resource_width, client_hints_preferences, request_type,
- referrer_policy, referrer_source, is_image_set));
- }
+ RequestType request_type = kRequestTypePreload);
Resource* Start(Document*);
@@ -167,25 +152,25 @@ class CORE_EXPORT PreloadRequest {
KURL CompleteURL(Document*);
- String initiator_name_;
- TextPosition initiator_position_;
- String resource_url_;
- KURL base_url_;
+ const String initiator_name_;
+ const TextPosition initiator_position_;
+ const String resource_url_;
+ const KURL base_url_;
String charset_;
- ResourceType resource_type_;
+ const ResourceType resource_type_;
mojom::ScriptType script_type_;
CrossOriginAttributeValue cross_origin_;
mojom::FetchImportanceMode importance_;
String nonce_;
FetchParameters::DeferOption defer_;
- FetchParameters::ResourceWidth resource_width_;
- ClientHintsPreferences client_hints_preferences_;
- RequestType request_type_;
- network::mojom::ReferrerPolicy referrer_policy_;
- ReferrerSource referrer_source_;
+ const FetchParameters::ResourceWidth resource_width_;
+ const ClientHintsPreferences client_hints_preferences_;
+ const RequestType request_type_;
+ const network::mojom::ReferrerPolicy referrer_policy_;
+ const ReferrerSource referrer_source_;
IntegrityMetadataSet integrity_metadata_;
bool from_insertion_scanner_;
- ResourceFetcher::IsImageSet is_image_set_;
+ const ResourceFetcher::IsImageSet is_image_set_;
bool is_lazy_load_image_enabled_;
};