[go: nahoru, domu]

blob: a1a9b6edd598876b7e6f4fe2b976c3e3d9092caf [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/loader/speculation_rule_loader.h"
#include "base/metrics/histogram_macros.h"
#include "services/network/public/cpp/header_util.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/resource/speculation_rules_resource.h"
#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h"
#include "third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h"
#include "third_party/blink/renderer/core/speculation_rules/speculation_rules_metrics.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
SpeculationRuleLoader::SpeculationRuleLoader(Document& document)
: document_(document) {}
SpeculationRuleLoader::~SpeculationRuleLoader() = default;
void SpeculationRuleLoader::LoadResource(SpeculationRulesResource* resource) {
DCHECK(!resource_);
resource_ = resource;
resource_->AddFinishObserver(
this, document_->GetTaskRunner(TaskType::kNetworking).get());
start_time_ = base::TimeTicks::Now();
DocumentSpeculationRules::From(*document_).AddSpeculationRuleLoader(this);
}
void SpeculationRuleLoader::NotifyFinished() {
DCHECK(resource_);
UMA_HISTOGRAM_MEDIUM_TIMES("Blink.SpeculationRules.FetchTime",
base::TimeTicks::Now() - start_time_);
const ResourceResponse& response = resource_->GetResponse();
if (resource_->LoadFailedOrCanceled()) {
StringBuilder message;
message.Append("Load failed or canceled (");
message.Append(resource_->GetResourceError().LocalizedDescription());
if (int response_code = response.HttpStatusCode()) {
message.AppendFormat("; HTTP status %d", response_code);
}
message.Append(String(") for rule set requested from \"" +
resource_->GetResourceRequest().Url().ElidedString() +
"\" found in Speculation-Rules header."));
CountSpeculationRulesLoadOutcome(
SpeculationRulesLoadOutcome::kLoadFailedOrCanceled);
document_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kWarning, message.ToString()));
return;
}
if (!EqualIgnoringASCIICase(resource_->HttpContentType(),
"application/speculationrules+json")) {
CountSpeculationRulesLoadOutcome(
SpeculationRulesLoadOutcome::kInvalidMimeType);
document_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kWarning,
"Received a response with invalid MIME type \"" +
resource_->HttpContentType() +
"\" for the rule set requested from \"" +
resource_->GetResourceRequest().Url().ElidedString() +
"\" found in the Speculation-Rules header."));
return;
}
if (!resource_->HasData()) {
CountSpeculationRulesLoadOutcome(
SpeculationRulesLoadOutcome::kEmptyResponseBody);
document_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kWarning,
"Received a response with no data for rule set \"" +
resource_->GetResourceRequest().Url().ElidedString() +
"\" found in Speculation-Rules "
"header."));
return;
}
String source_text = resource_->DecodedText();
auto* source = SpeculationRuleSet::Source::FromRequest(
source_text, response.ResponseUrl(), resource_->InspectorId());
auto* rule_set =
SpeculationRuleSet::Parse(source, document_->GetExecutionContext());
CHECK(rule_set);
DocumentSpeculationRules::From(*document_).AddRuleSet(rule_set);
rule_set->AddConsoleMessageForValidation(*document_, *resource_);
resource_->RemoveFinishObserver(this);
resource_ = nullptr;
DocumentSpeculationRules::From(*document_).RemoveSpeculationRuleLoader(this);
}
void SpeculationRuleLoader::Trace(Visitor* visitor) const {
visitor->Trace(document_);
visitor->Trace(resource_);
ResourceFinishObserver::Trace(visitor);
}
} // namespace blink