• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/WaitUntilObserver.h"
7 
8 #include "bindings/core/v8/ScriptFunction.h"
9 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptValue.h"
11 #include "bindings/core/v8/V8Binding.h"
12 #include "core/dom/ExecutionContext.h"
13 #include "platform/NotImplemented.h"
14 #include "public/platform/WebServiceWorkerEventResult.h"
15 #include "wtf/Assertions.h"
16 #include "wtf/RefCounted.h"
17 #include "wtf/RefPtr.h"
18 #include <v8.h>
19 
20 namespace blink {
21 
22 class WaitUntilObserver::ThenFunction FINAL : public ScriptFunction {
23 public:
24     enum ResolveType {
25         Fulfilled,
26         Rejected,
27     };
28 
createFunction(ScriptState * scriptState,WaitUntilObserver * observer,ResolveType type)29     static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, WaitUntilObserver* observer, ResolveType type)
30     {
31         ThenFunction* self = new ThenFunction(scriptState, observer, type);
32         return self->bindToV8Function();
33     }
34 
trace(Visitor * visitor)35     virtual void trace(Visitor* visitor) OVERRIDE
36     {
37         visitor->trace(m_observer);
38         ScriptFunction::trace(visitor);
39     }
40 
41 private:
ThenFunction(ScriptState * scriptState,WaitUntilObserver * observer,ResolveType type)42     ThenFunction(ScriptState* scriptState, WaitUntilObserver* observer, ResolveType type)
43         : ScriptFunction(scriptState)
44         , m_observer(observer)
45         , m_resolveType(type)
46     {
47     }
48 
call(ScriptValue value)49     virtual ScriptValue call(ScriptValue value) OVERRIDE
50     {
51         ASSERT(m_observer);
52         ASSERT(m_resolveType == Fulfilled || m_resolveType == Rejected);
53         if (m_resolveType == Rejected)
54             m_observer->reportError(value);
55         m_observer->decrementPendingActivity();
56         m_observer = nullptr;
57         return value;
58     }
59 
60     Member<WaitUntilObserver> m_observer;
61     ResolveType m_resolveType;
62 };
63 
create(ExecutionContext * context,EventType type,int eventID)64 WaitUntilObserver* WaitUntilObserver::create(ExecutionContext* context, EventType type, int eventID)
65 {
66     return new WaitUntilObserver(context, type, eventID);
67 }
68 
willDispatchEvent()69 void WaitUntilObserver::willDispatchEvent()
70 {
71     incrementPendingActivity();
72 }
73 
didDispatchEvent()74 void WaitUntilObserver::didDispatchEvent()
75 {
76     decrementPendingActivity();
77 }
78 
waitUntil(ScriptState * scriptState,const ScriptValue & value)79 void WaitUntilObserver::waitUntil(ScriptState* scriptState, const ScriptValue& value)
80 {
81     incrementPendingActivity();
82     ScriptPromise::cast(scriptState, value).then(
83         ThenFunction::createFunction(scriptState, this, ThenFunction::Fulfilled),
84         ThenFunction::createFunction(scriptState, this, ThenFunction::Rejected));
85 }
86 
WaitUntilObserver(ExecutionContext * context,EventType type,int eventID)87 WaitUntilObserver::WaitUntilObserver(ExecutionContext* context, EventType type, int eventID)
88     : ContextLifecycleObserver(context)
89     , m_type(type)
90     , m_eventID(eventID)
91     , m_pendingActivity(0)
92     , m_hasError(false)
93 {
94 }
95 
reportError(const ScriptValue & value)96 void WaitUntilObserver::reportError(const ScriptValue& value)
97 {
98     // FIXME: Propagate error message to the client for onerror handling.
99     notImplemented();
100 
101     m_hasError = true;
102 }
103 
incrementPendingActivity()104 void WaitUntilObserver::incrementPendingActivity()
105 {
106     ++m_pendingActivity;
107 }
108 
decrementPendingActivity()109 void WaitUntilObserver::decrementPendingActivity()
110 {
111     ASSERT(m_pendingActivity > 0);
112     if (!executionContext() || (!m_hasError && --m_pendingActivity))
113         return;
114 
115     ServiceWorkerGlobalScopeClient* client = ServiceWorkerGlobalScopeClient::from(executionContext());
116     WebServiceWorkerEventResult result = m_hasError ? WebServiceWorkerEventResultRejected : WebServiceWorkerEventResultCompleted;
117     switch (m_type) {
118     case Activate:
119         client->didHandleActivateEvent(m_eventID, result);
120         break;
121     case Install:
122         client->didHandleInstallEvent(m_eventID, result);
123         break;
124     }
125     observeContext(0);
126 }
127 
128 } // namespace blink
129