OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/serviceworkers/FetchEvent.h" | 5 #include "modules/serviceworkers/FetchEvent.h" |
6 | 6 |
| 7 #include "bindings/core/v8/ScriptState.h" |
7 #include "bindings/core/v8/ToV8.h" | 8 #include "bindings/core/v8/ToV8.h" |
8 #include "bindings/core/v8/V8HiddenValue.h" | 9 #include "bindings/core/v8/V8HiddenValue.h" |
| 10 #include "modules/fetch/BytesConsumerForDataConsumerHandle.h" |
9 #include "modules/fetch/Request.h" | 11 #include "modules/fetch/Request.h" |
| 12 #include "modules/fetch/Response.h" |
| 13 #include "modules/serviceworkers/ServiceWorkerError.h" |
10 #include "modules/serviceworkers/ServiceWorkerGlobalScope.h" | 14 #include "modules/serviceworkers/ServiceWorkerGlobalScope.h" |
| 15 #include "public/platform/modules/serviceworker/WebServiceWorkerError.h" |
| 16 #include "public/platform/modules/serviceworker/WebServiceWorkerResponse.h" |
| 17 #include "wtf/PtrUtil.h" |
11 #include "wtf/RefPtr.h" | 18 #include "wtf/RefPtr.h" |
12 | 19 |
13 namespace blink { | 20 namespace blink { |
14 | 21 |
15 FetchEvent* FetchEvent::create(ScriptState* scriptState, | 22 FetchEvent* FetchEvent::create(ScriptState* scriptState, |
16 const AtomicString& type, | 23 const AtomicString& type, |
17 const FetchEventInit& initializer) { | 24 const FetchEventInit& initializer) { |
18 return new FetchEvent(scriptState, type, initializer, nullptr, nullptr); | 25 return new FetchEvent(scriptState, type, initializer, nullptr, nullptr, |
| 26 false); |
19 } | 27 } |
20 | 28 |
21 FetchEvent* FetchEvent::create(ScriptState* scriptState, | 29 FetchEvent* FetchEvent::create(ScriptState* scriptState, |
22 const AtomicString& type, | 30 const AtomicString& type, |
23 const FetchEventInit& initializer, | 31 const FetchEventInit& initializer, |
24 RespondWithObserver* respondWithObserver, | 32 RespondWithObserver* respondWithObserver, |
25 WaitUntilObserver* waitUntilObserver) { | 33 WaitUntilObserver* waitUntilObserver, |
| 34 bool navigationPreloadSent) { |
26 return new FetchEvent(scriptState, type, initializer, respondWithObserver, | 35 return new FetchEvent(scriptState, type, initializer, respondWithObserver, |
27 waitUntilObserver); | 36 waitUntilObserver, navigationPreloadSent); |
28 } | 37 } |
29 | 38 |
30 Request* FetchEvent::request() const { | 39 Request* FetchEvent::request() const { |
31 return m_request; | 40 return m_request; |
32 } | 41 } |
33 | 42 |
34 String FetchEvent::clientId() const { | 43 String FetchEvent::clientId() const { |
35 return m_clientId; | 44 return m_clientId; |
36 } | 45 } |
37 | 46 |
38 bool FetchEvent::isReload() const { | 47 bool FetchEvent::isReload() const { |
39 return m_isReload; | 48 return m_isReload; |
40 } | 49 } |
41 | 50 |
42 void FetchEvent::respondWith(ScriptState* scriptState, | 51 void FetchEvent::respondWith(ScriptState* scriptState, |
43 ScriptPromise scriptPromise, | 52 ScriptPromise scriptPromise, |
44 ExceptionState& exceptionState) { | 53 ExceptionState& exceptionState) { |
45 stopImmediatePropagation(); | 54 stopImmediatePropagation(); |
46 if (m_observer) | 55 if (m_observer) |
47 m_observer->respondWith(scriptState, scriptPromise, exceptionState); | 56 m_observer->respondWith(scriptState, scriptPromise, exceptionState); |
48 } | 57 } |
49 | 58 |
| 59 ScriptPromise FetchEvent::navigationPreload(ScriptState* scriptState) { |
| 60 return m_navigationPreloadProperty->promise(scriptState->world()); |
| 61 } |
| 62 |
50 const AtomicString& FetchEvent::interfaceName() const { | 63 const AtomicString& FetchEvent::interfaceName() const { |
51 return EventNames::FetchEvent; | 64 return EventNames::FetchEvent; |
52 } | 65 } |
53 | 66 |
54 FetchEvent::FetchEvent(ScriptState* scriptState, | 67 FetchEvent::FetchEvent(ScriptState* scriptState, |
55 const AtomicString& type, | 68 const AtomicString& type, |
56 const FetchEventInit& initializer, | 69 const FetchEventInit& initializer, |
57 RespondWithObserver* respondWithObserver, | 70 RespondWithObserver* respondWithObserver, |
58 WaitUntilObserver* waitUntilObserver) | 71 WaitUntilObserver* waitUntilObserver, |
| 72 bool navigationPreloadSent) |
59 : ExtendableEvent(type, initializer, waitUntilObserver), | 73 : ExtendableEvent(type, initializer, waitUntilObserver), |
60 m_observer(respondWithObserver) { | 74 m_scriptState(scriptState), |
| 75 m_observer(respondWithObserver), |
| 76 m_navigationPreloadProperty(new PreloadResponseProperty( |
| 77 scriptState->getExecutionContext(), |
| 78 this, |
| 79 PreloadResponseProperty::PreloadResponse)) { |
| 80 if (!navigationPreloadSent) { |
| 81 // TODO(horo): This behavior is still under the spec discussion. |
| 82 // https://github.com/w3c/ServiceWorker/issues/920#issuecomment-255874864 |
| 83 m_navigationPreloadProperty->resolve(nullptr); |
| 84 } |
| 85 |
61 m_clientId = initializer.clientId(); | 86 m_clientId = initializer.clientId(); |
62 m_isReload = initializer.isReload(); | 87 m_isReload = initializer.isReload(); |
63 if (initializer.hasRequest()) { | 88 if (initializer.hasRequest()) { |
64 ScriptState::Scope scope(scriptState); | 89 ScriptState::Scope scope(scriptState); |
65 m_request = initializer.request(); | 90 m_request = initializer.request(); |
66 v8::Local<v8::Value> request = toV8(m_request, scriptState); | 91 v8::Local<v8::Value> request = toV8(m_request, scriptState); |
67 v8::Local<v8::Value> event = toV8(this, scriptState); | 92 v8::Local<v8::Value> event = toV8(this, scriptState); |
68 if (event.IsEmpty()) { | 93 if (event.IsEmpty()) { |
69 // |toV8| can return an empty handle when the worker is terminating. | 94 // |toV8| can return an empty handle when the worker is terminating. |
70 // We don't want the renderer to crash in such cases. | 95 // We don't want the renderer to crash in such cases. |
71 // TODO(yhirano): Replace this branch with an assertion when the | 96 // TODO(yhirano): Replace this branch with an assertion when the |
72 // graceful shutdown mechanism is introduced. | 97 // graceful shutdown mechanism is introduced. |
73 return; | 98 return; |
74 } | 99 } |
75 DCHECK(event->IsObject()); | 100 DCHECK(event->IsObject()); |
76 // Sets a hidden value in order to teach V8 the dependency from | 101 // Sets a hidden value in order to teach V8 the dependency from |
77 // the event to the request. | 102 // the event to the request. |
78 V8HiddenValue::setHiddenValue( | 103 V8HiddenValue::setHiddenValue( |
79 scriptState, event.As<v8::Object>(), | 104 scriptState, event.As<v8::Object>(), |
80 V8HiddenValue::requestInFetchEvent(scriptState->isolate()), request); | 105 V8HiddenValue::requestInFetchEvent(scriptState->isolate()), request); |
81 // From the same reason as above, setHiddenValue can return false. | 106 // From the same reason as above, setHiddenValue can return false. |
82 // TODO(yhirano): Add an assertion that it returns true once the | 107 // TODO(yhirano): Add an assertion that it returns true once the |
83 // graceful shutdown mechanism is introduced. | 108 // graceful shutdown mechanism is introduced. |
84 } | 109 } |
85 } | 110 } |
86 | 111 |
| 112 void FetchEvent::onNavigationPreloadResponse( |
| 113 std::unique_ptr<WebServiceWorkerResponse> response, |
| 114 std::unique_ptr<WebDataConsumerHandle> dataConsumeHandle) { |
| 115 if (!m_scriptState->contextIsValid()) |
| 116 return; |
| 117 DCHECK(m_navigationPreloadProperty); |
| 118 ScriptState::Scope scope(m_scriptState.get()); |
| 119 FetchResponseData* responseData = |
| 120 FetchResponseData::createWithBuffer(new BodyStreamBuffer( |
| 121 m_scriptState.get(), new BytesConsumerForDataConsumerHandle( |
| 122 m_scriptState->getExecutionContext(), |
| 123 std::move(dataConsumeHandle)))); |
| 124 responseData->setURL(response->url()); |
| 125 responseData->setStatus(response->status()); |
| 126 responseData->setStatusMessage(response->statusText()); |
| 127 responseData->setResponseTime(response->responseTime()); |
| 128 for (const auto& header : response->headers()) |
| 129 responseData->headerList()->append(header.key, header.value); |
| 130 FetchResponseData* taintedResponse = |
| 131 responseData->createBasicFilteredResponse(); |
| 132 m_navigationPreloadProperty->resolve( |
| 133 Response::create(m_scriptState->getExecutionContext(), taintedResponse)); |
| 134 } |
| 135 |
| 136 void FetchEvent::onNavigationPreloadError( |
| 137 std::unique_ptr<WebServiceWorkerError> error) { |
| 138 if (!m_scriptState->contextIsValid()) |
| 139 return; |
| 140 DCHECK(m_navigationPreloadProperty); |
| 141 m_navigationPreloadProperty->reject( |
| 142 ServiceWorkerError::take(nullptr, *error.get())); |
| 143 } |
| 144 |
87 DEFINE_TRACE(FetchEvent) { | 145 DEFINE_TRACE(FetchEvent) { |
88 visitor->trace(m_observer); | 146 visitor->trace(m_observer); |
89 visitor->trace(m_request); | 147 visitor->trace(m_request); |
| 148 visitor->trace(m_navigationPreloadProperty); |
90 ExtendableEvent::trace(visitor); | 149 ExtendableEvent::trace(visitor); |
91 } | 150 } |
92 | 151 |
93 } // namespace blink | 152 } // namespace blink |
OLD | NEW |