summaryrefslogtreecommitdiff
path: root/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc')
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc195
1 files changed, 155 insertions, 40 deletions
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index dad6fba12ce..c08f2659c7b 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -4,16 +4,20 @@
#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
+#include <string>
#include <utility>
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
+#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_utils.h"
namespace content {
namespace {
+
using EventType = ServiceWorkerMetrics::EventType;
EventType ResourceTypeToEventType(ResourceType resource_type) {
switch (resource_type) {
@@ -31,22 +35,96 @@ EventType ResourceTypeToEventType(ResourceType resource_type) {
return EventType::FETCH_SUB_RESOURCE;
}
}
+
+std::unique_ptr<base::Value> NetLogServiceWorkerStatusCallback(
+ ServiceWorkerStatusCode status,
+ net::NetLogCaptureMode) {
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ dict->SetString("status", ServiceWorkerStatusToString(status));
+ return std::move(dict);
+}
+
+std::unique_ptr<base::Value> NetLogFetchEventCallback(
+ ServiceWorkerStatusCode status,
+ ServiceWorkerFetchEventResult result,
+ net::NetLogCaptureMode) {
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ dict->SetString("status", ServiceWorkerStatusToString(status));
+ dict->SetBoolean("has_response",
+ result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
+ return std::move(dict);
+}
+
+void EndNetLogEventWithServiceWorkerStatus(const net::BoundNetLog& net_log,
+ net::NetLog::EventType type,
+ ServiceWorkerStatusCode status) {
+ net_log.EndEvent(type,
+ base::Bind(&NetLogServiceWorkerStatusCallback, status));
+}
+
+ServiceWorkerMetrics::EventType FetchTypeToWaitUntilEventType(
+ ServiceWorkerFetchType type) {
+ if (type == ServiceWorkerFetchType::FOREIGN_FETCH)
+ return ServiceWorkerMetrics::EventType::FOREIGN_FETCH_WAITUNTIL;
+ return ServiceWorkerMetrics::EventType::FETCH_WAITUNTIL;
+}
+
} // namespace
+// Helper to receive the fetch event response even if
+// ServiceWorkerFetchDispatcher has been destroyed.
+class ServiceWorkerFetchDispatcher::ResponseCallback {
+ public:
+ ResponseCallback(base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
+ ServiceWorkerVersion* version)
+ : fetch_dispatcher_(fetch_dispatcher), version_(version) {}
+
+ void Run(int request_id,
+ ServiceWorkerFetchEventResult fetch_result,
+ const ServiceWorkerResponse& response) {
+ const bool handled =
+ (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
+ if (!version_->FinishRequest(request_id, handled))
+ NOTREACHED() << "Should only receive one reply per event";
+
+ // |fetch_dispatcher| is null if the URLRequest was killed.
+ if (fetch_dispatcher_)
+ fetch_dispatcher_->DidFinish(request_id, fetch_result, response);
+ }
+
+ private:
+ base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
+ // Owns |this|.
+ ServiceWorkerVersion* version_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResponseCallback);
+};
+
ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
std::unique_ptr<ServiceWorkerFetchRequest> request,
ServiceWorkerVersion* version,
ResourceType resource_type,
+ const net::BoundNetLog& net_log,
const base::Closure& prepare_callback,
const FetchCallback& fetch_callback)
: version_(version),
+ net_log_(net_log),
prepare_callback_(prepare_callback),
fetch_callback_(fetch_callback),
request_(std::move(request)),
resource_type_(resource_type),
- weak_factory_(this) {}
+ did_complete_(false),
+ weak_factory_(this) {
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_DISPATCH_FETCH_EVENT,
+ net::NetLog::StringCallback(
+ "event_type", ServiceWorkerMetrics::EventTypeToString(
+ GetEventType())));
+}
-ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {}
+ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {
+ if (!did_complete_)
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_DISPATCH_FETCH_EVENT);
+}
void ServiceWorkerFetchDispatcher::Run() {
DCHECK(version_->status() == ServiceWorkerVersion::ACTIVATING ||
@@ -54,82 +132,119 @@ void ServiceWorkerFetchDispatcher::Run() {
<< version_->status();
if (version_->status() == ServiceWorkerVersion::ACTIVATING) {
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_WAIT_FOR_ACTIVATION);
version_->RegisterStatusChangeCallback(
- base::Bind(&ServiceWorkerFetchDispatcher::DidWaitActivation,
+ base::Bind(&ServiceWorkerFetchDispatcher::DidWaitForActivation,
weak_factory_.GetWeakPtr()));
return;
}
- DidWaitActivation();
+ StartWorker();
+}
+
+void ServiceWorkerFetchDispatcher::DidWaitForActivation() {
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_WAIT_FOR_ACTIVATION);
+ StartWorker();
}
-void ServiceWorkerFetchDispatcher::DidWaitActivation() {
+void ServiceWorkerFetchDispatcher::StartWorker() {
+ // We might be REDUNDANT if a new worker started activating and kicked us out
+ // before we could finish activation.
if (version_->status() != ServiceWorkerVersion::ACTIVATED) {
- DCHECK_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
- DidFailActivation();
+ DCHECK_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
+ DidFail(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
return;
}
+
+ if (version_->running_status() == EmbeddedWorkerStatus::RUNNING) {
+ DispatchFetchEvent();
+ return;
+ }
+
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_START_WORKER);
version_->RunAfterStartWorker(
- GetEventType(),
- base::Bind(&ServiceWorkerFetchDispatcher::DispatchFetchEvent,
- weak_factory_.GetWeakPtr()),
- base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
+ GetEventType(), base::Bind(&ServiceWorkerFetchDispatcher::DidStartWorker,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&ServiceWorkerFetchDispatcher::DidFailToStartWorker,
weak_factory_.GetWeakPtr()));
}
-void ServiceWorkerFetchDispatcher::DidFailActivation() {
- // The previous activation seems to have failed, abort the step
- // with activate error. (The error should be separately reported
- // to the associated documents and association must be dropped
- // at this point)
- DidFinish(SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED,
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse());
+void ServiceWorkerFetchDispatcher::DidStartWorker() {
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_START_WORKER);
+ DispatchFetchEvent();
+}
+
+void ServiceWorkerFetchDispatcher::DidFailToStartWorker(
+ ServiceWorkerStatusCode status) {
+ EndNetLogEventWithServiceWorkerStatus(
+ net_log_, net::NetLog::TYPE_SERVICE_WORKER_START_WORKER, status);
+ DidFail(status);
}
void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
- DCHECK_EQ(ServiceWorkerVersion::RUNNING, version_->running_status())
+ DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
<< "Worker stopped too soon after it was started.";
DCHECK(!prepare_callback_.is_null());
base::Closure prepare_callback = prepare_callback_;
prepare_callback.Run();
- int request_id = version_->StartRequest(
- GetEventType(), base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
- weak_factory_.GetWeakPtr()));
- version_->DispatchEvent<ServiceWorkerHostMsg_FetchEventFinished>(
- request_id, ServiceWorkerMsg_FetchEvent(request_id, *request_.get()),
- base::Bind(&ServiceWorkerFetchDispatcher::DidFinish,
+ net_log_.BeginEvent(net::NetLog::TYPE_SERVICE_WORKER_FETCH_EVENT);
+ int response_id = version_->StartRequest(
+ GetEventType(),
+ base::Bind(&ServiceWorkerFetchDispatcher::DidFailToDispatch,
weak_factory_.GetWeakPtr()));
+ int event_finish_id = version_->StartRequest(
+ FetchTypeToWaitUntilEventType(request_->fetch_type),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ ResponseCallback* response_callback =
+ new ResponseCallback(weak_factory_.GetWeakPtr(), version_.get());
+ version_->RegisterRequestCallback<ServiceWorkerHostMsg_FetchEventResponse>(
+ response_id,
+ base::Bind(&ServiceWorkerFetchDispatcher::ResponseCallback::Run,
+ base::Owned(response_callback)));
+ version_->RegisterSimpleRequest<ServiceWorkerHostMsg_FetchEventFinished>(
+ event_finish_id);
+ version_->DispatchEvent({response_id, event_finish_id},
+ ServiceWorkerMsg_FetchEvent(
+ response_id, event_finish_id, *request_.get()));
}
-void ServiceWorkerFetchDispatcher::DidPrepare() {
- DCHECK(!prepare_callback_.is_null());
- base::Closure prepare_callback = prepare_callback_;
- prepare_callback.Run();
+void ServiceWorkerFetchDispatcher::DidFailToDispatch(
+ ServiceWorkerStatusCode status) {
+ EndNetLogEventWithServiceWorkerStatus(
+ net_log_, net::NetLog::TYPE_SERVICE_WORKER_FETCH_EVENT, status);
+ DidFail(status);
}
void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) {
- DCHECK(!fetch_callback_.is_null());
- FetchCallback fetch_callback = fetch_callback_;
- scoped_refptr<ServiceWorkerVersion> version = version_;
- fetch_callback.Run(status, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse(), version);
+ DCHECK_NE(SERVICE_WORKER_OK, status);
+ Complete(status, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
+ ServiceWorkerResponse());
}
void ServiceWorkerFetchDispatcher::DidFinish(
int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response) {
- const bool handled =
- (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
- if (!version_->FinishRequest(request_id, handled))
- NOTREACHED() << "Should only receive one reply per event";
+ net_log_.EndEvent(net::NetLog::TYPE_SERVICE_WORKER_FETCH_EVENT);
+ Complete(SERVICE_WORKER_OK, fetch_result, response);
+}
+void ServiceWorkerFetchDispatcher::Complete(
+ ServiceWorkerStatusCode status,
+ ServiceWorkerFetchEventResult fetch_result,
+ const ServiceWorkerResponse& response) {
DCHECK(!fetch_callback_.is_null());
+
+ did_complete_ = true;
+ net_log_.EndEvent(
+ net::NetLog::TYPE_SERVICE_WORKER_DISPATCH_FETCH_EVENT,
+ base::Bind(&NetLogFetchEventCallback, status, fetch_result));
+
FetchCallback fetch_callback = fetch_callback_;
scoped_refptr<ServiceWorkerVersion> version = version_;
- fetch_callback.Run(SERVICE_WORKER_OK, fetch_result, response, version);
+ fetch_callback.Run(status, fetch_result, response, version);
}
ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType()