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/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