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