Home | History | Annotate | Download | only in serviceworkers
      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 
     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 
     35     virtual void trace(Visitor* visitor) OVERRIDE
     36     {
     37         visitor->trace(m_observer);
     38         ScriptFunction::trace(visitor);
     39     }
     40 
     41 private:
     42     ThenFunction(ScriptState* scriptState, WaitUntilObserver* observer, ResolveType type)
     43         : ScriptFunction(scriptState)
     44         , m_observer(observer)
     45         , m_resolveType(type)
     46     {
     47     }
     48 
     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 
     64 WaitUntilObserver* WaitUntilObserver::create(ExecutionContext* context, EventType type, int eventID)
     65 {
     66     return new WaitUntilObserver(context, type, eventID);
     67 }
     68 
     69 void WaitUntilObserver::willDispatchEvent()
     70 {
     71     incrementPendingActivity();
     72 }
     73 
     74 void WaitUntilObserver::didDispatchEvent()
     75 {
     76     decrementPendingActivity();
     77 }
     78 
     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 
     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 
     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 
    104 void WaitUntilObserver::incrementPendingActivity()
    105 {
    106     ++m_pendingActivity;
    107 }
    108 
    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