Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / serviceworkers / RespondWithObserver.cpp
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
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "modules/serviceworkers/RespondWithObserver.h"
7
8 #include "V8Response.h"
9 #include "bindings/v8/ScriptFunction.h"
10 #include "bindings/v8/ScriptPromise.h"
11 #include "bindings/v8/ScriptValue.h"
12 #include "bindings/v8/V8Binding.h"
13 #include "core/dom/ExecutionContext.h"
14 #include "modules/serviceworkers/ServiceWorkerGlobalScopeClient.h"
15 #include "wtf/Assertions.h"
16 #include "wtf/RefPtr.h"
17 #include <v8.h>
18
19 namespace WebCore {
20
21 class RespondWithObserver::ThenFunction FINAL : public ScriptFunction {
22 public:
23     enum ResolveType {
24         Fulfilled,
25         Rejected,
26     };
27
28     static PassOwnPtr<ScriptFunction> create(PassRefPtr<RespondWithObserver> observer, ResolveType type)
29     {
30         ExecutionContext* executionContext = observer->executionContext();
31         return adoptPtr(new ThenFunction(toIsolate(executionContext), observer, type));
32     }
33
34 private:
35     ThenFunction(v8::Isolate* isolate, PassRefPtr<RespondWithObserver> observer, ResolveType type)
36         : ScriptFunction(isolate)
37         , m_observer(observer)
38         , m_resolveType(type)
39     {
40     }
41
42     virtual ScriptValue call(ScriptValue value) OVERRIDE
43     {
44         ASSERT(m_observer);
45         ASSERT(m_resolveType == Fulfilled || m_resolveType == Rejected);
46         if (m_resolveType == Rejected)
47             m_observer->responseWasRejected();
48         else
49             m_observer->responseWasFulfilled(value);
50         m_observer = nullptr;
51         return value;
52     }
53
54     RefPtr<RespondWithObserver> m_observer;
55     ResolveType m_resolveType;
56 };
57
58 PassRefPtr<RespondWithObserver> RespondWithObserver::create(ExecutionContext* context, int eventID)
59 {
60     return adoptRef(new RespondWithObserver(context, eventID));
61 }
62
63 RespondWithObserver::~RespondWithObserver()
64 {
65     ASSERT(m_state == Done);
66 }
67
68 void RespondWithObserver::contextDestroyed()
69 {
70     ContextLifecycleObserver::contextDestroyed();
71     m_state = Done;
72 }
73
74 void RespondWithObserver::didDispatchEvent()
75 {
76     if (m_state == Initial)
77         sendResponse(nullptr);
78 }
79
80 void RespondWithObserver::respondWith(ScriptState* scriptState, const ScriptValue& value)
81 {
82     if (m_state != Initial)
83         return;
84
85     m_state = Pending;
86     ScriptPromise::cast(scriptState, value).then(
87         ThenFunction::create(this, ThenFunction::Fulfilled),
88         ThenFunction::create(this, ThenFunction::Rejected));
89 }
90
91 void RespondWithObserver::sendResponse(PassRefPtr<Response> response)
92 {
93     if (!executionContext())
94         return;
95     ServiceWorkerGlobalScopeClient::from(executionContext())->didHandleFetchEvent(m_eventID, response);
96     m_state = Done;
97 }
98
99 void RespondWithObserver::responseWasRejected()
100 {
101     // FIXME: Throw a NetworkError to service worker's execution context.
102     sendResponse(nullptr);
103 }
104
105 void RespondWithObserver::responseWasFulfilled(const ScriptValue& value)
106 {
107     if (!executionContext())
108         return;
109     if (!V8Response::hasInstance(value.v8Value(), toIsolate(executionContext()))) {
110         responseWasRejected();
111         return;
112     }
113     v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value.v8Value());
114     sendResponse(V8Response::toNative(object));
115 }
116
117 RespondWithObserver::RespondWithObserver(ExecutionContext* context, int eventID)
118     : ContextLifecycleObserver(context)
119     , m_eventID(eventID)
120     , m_state(Initial)
121 {
122 }
123
124 } // namespace WebCore