blob: 2ab54d8e40faa25f3ce18ee106c26dfa4ed4674b [file] [log] [blame]
// Copyright 2014 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 "core/fetch/GlobalFetch.h"
#include "core/fetch/FetchManager.h"
#include "core/fetch/Request.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/UseCounter.h"
#include "core/probe/CoreProbes.h"
#include "core/workers/WorkerGlobalScope.h"
#include "platform/Supplementable.h"
#include "platform/heap/Handle.h"
namespace blink {
namespace {
template <typename T>
class GlobalFetchImpl final
: public GarbageCollectedFinalized<GlobalFetchImpl<T>>,
public GlobalFetch::ScopedFetcher,
public Supplement<T> {
USING_GARBAGE_COLLECTED_MIXIN(GlobalFetchImpl);
public:
static ScopedFetcher* From(T& supplementable,
ExecutionContext* execution_context) {
GlobalFetchImpl* supplement = static_cast<GlobalFetchImpl*>(
Supplement<T>::From(supplementable, SupplementName()));
if (!supplement) {
supplement = new GlobalFetchImpl(execution_context);
Supplement<T>::ProvideTo(supplementable, SupplementName(), supplement);
}
return supplement;
}
ScriptPromise Fetch(ScriptState* script_state,
const RequestInfo& input,
const Dictionary& init,
ExceptionState& exception_state) override {
ExecutionContext* execution_context = fetch_manager_->GetExecutionContext();
if (!script_state->ContextIsValid() || !execution_context) {
// TODO(yhirano): Should this be moved to bindings?
exception_state.ThrowTypeError("The global scope is shutting down.");
return ScriptPromise();
}
// "Let |r| be the associated request of the result of invoking the
// initial value of Request as constructor with |input| and |init| as
// arguments. If this throws an exception, reject |p| with it."
Request* r = Request::Create(script_state, input, init, exception_state);
if (exception_state.HadException())
return ScriptPromise();
probe::willSendXMLHttpOrFetchNetworkRequest(execution_context, r->url());
return fetch_manager_->Fetch(script_state,
r->PassRequestData(script_state));
}
virtual void Trace(blink::Visitor* visitor) {
visitor->Trace(fetch_manager_);
ScopedFetcher::Trace(visitor);
Supplement<T>::Trace(visitor);
}
private:
explicit GlobalFetchImpl(ExecutionContext* execution_context)
: fetch_manager_(FetchManager::Create(execution_context)) {}
static const char* SupplementName() { return "GlobalFetch"; }
Member<FetchManager> fetch_manager_;
};
} // namespace
GlobalFetch::ScopedFetcher::~ScopedFetcher() {}
GlobalFetch::ScopedFetcher* GlobalFetch::ScopedFetcher::From(
LocalDOMWindow& window) {
return GlobalFetchImpl<LocalDOMWindow>::From(window,
window.GetExecutionContext());
}
GlobalFetch::ScopedFetcher* GlobalFetch::ScopedFetcher::From(
WorkerGlobalScope& worker) {
return GlobalFetchImpl<WorkerGlobalScope>::From(worker,
worker.GetExecutionContext());
}
void GlobalFetch::ScopedFetcher::Trace(blink::Visitor* visitor) {}
ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
LocalDOMWindow& window,
const RequestInfo& input,
const Dictionary& init,
ExceptionState& exception_state) {
UseCounter::Count(window.GetExecutionContext(), WebFeature::kFetch);
if (!window.GetFrame()) {
exception_state.ThrowTypeError("The global scope is shutting down.");
return ScriptPromise();
}
return ScopedFetcher::From(window)->Fetch(script_state, input, init,
exception_state);
}
ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
WorkerGlobalScope& worker,
const RequestInfo& input,
const Dictionary& init,
ExceptionState& exception_state) {
UseCounter::Count(worker.GetExecutionContext(), WebFeature::kFetch);
return ScopedFetcher::From(worker)->Fetch(script_state, input, init,
exception_state);
}
} // namespace blink