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