1/*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef WorkerThreadableLoader_h
32#define WorkerThreadableLoader_h
33
34#include "core/loader/ThreadableLoader.h"
35#include "core/loader/ThreadableLoaderClient.h"
36#include "core/loader/ThreadableLoaderClientWrapper.h"
37#include "platform/heap/Handle.h"
38#include "wtf/PassOwnPtr.h"
39#include "wtf/PassRefPtr.h"
40#include "wtf/RefPtr.h"
41#include "wtf/Threading.h"
42#include "wtf/text/WTFString.h"
43
44namespace blink {
45
46    class ResourceError;
47    class ResourceRequest;
48    class WorkerGlobalScope;
49    class WorkerLoaderProxy;
50    struct CrossThreadResourceRequestData;
51
52    class WorkerThreadableLoader FINAL : public ThreadableLoader {
53        WTF_MAKE_FAST_ALLOCATED;
54    public:
55        static void loadResourceSynchronously(WorkerGlobalScope&, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&, const ResourceLoaderOptions&);
56        static PassRefPtr<WorkerThreadableLoader> create(WorkerGlobalScope& workerGlobalScope, PassRefPtr<ThreadableLoaderClientWrapper> clientWrapper, PassOwnPtr<ThreadableLoaderClient> clientBridge, const ResourceRequest& request, const ThreadableLoaderOptions& options, const ResourceLoaderOptions& resourceLoaderOptions)
57        {
58            return adoptRef(new WorkerThreadableLoader(workerGlobalScope, clientWrapper, clientBridge, request, options, resourceLoaderOptions));
59        }
60
61        virtual ~WorkerThreadableLoader();
62
63        virtual void overrideTimeout(unsigned long timeout) OVERRIDE;
64
65        virtual void cancel() OVERRIDE;
66
67    private:
68        // Creates a loader on the main thread and bridges communication between
69        // the main thread and the worker context's thread where WorkerThreadableLoader runs.
70        //
71        // Regarding the bridge and lifetimes of items used in callbacks, there are a few cases:
72        //
73        // all cases. All tasks posted from the worker context's thread are ok because
74        //    the last task posted always is "mainThreadDestroy", so MainThreadBridge is
75        //    around for all tasks that use it on the main thread.
76        //
77        // case 1. worker.terminate is called.
78        //    In this case, no more tasks are posted from the worker object's thread to the worker
79        //    context's thread -- WorkerGlobalScopeProxy implementation enforces this.
80        //
81        // case 2. xhr gets aborted and the worker context continues running.
82        //    The ThreadableLoaderClientWrapper has the underlying client cleared, so no more calls
83        //    go through it.  All tasks posted from the worker object's thread to the worker context's
84        //    thread do "ThreadableLoaderClientWrapper::ref" (automatically inside of the cross thread copy
85        //    done in createCrossThreadTask), so the ThreadableLoaderClientWrapper instance is there until all
86        //    tasks are executed.
87        class MainThreadBridge FINAL : public ThreadableLoaderClient {
88        public:
89            // All executed on the worker context's thread.
90            MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, PassOwnPtr<ThreadableLoaderClient>, WorkerLoaderProxy&, const ResourceRequest&, const ThreadableLoaderOptions&, const ResourceLoaderOptions&, const String& outgoingReferrer);
91            void overrideTimeout(unsigned long timeoutMilliseconds);
92            void cancel();
93            void destroy();
94
95        private:
96            // Executed on the worker context's thread.
97            void clearClientWrapper();
98
99            // All executed on the main thread.
100            static void mainThreadDestroy(ExecutionContext*, MainThreadBridge*);
101            virtual ~MainThreadBridge();
102
103            static void mainThreadCreateLoader(ExecutionContext*, MainThreadBridge*, PassOwnPtr<CrossThreadResourceRequestData>, ThreadableLoaderOptions, ResourceLoaderOptions, const String& outgoingReferrer);
104            static void mainThreadOverrideTimeout(ExecutionContext*, MainThreadBridge*, unsigned long timeoutMilliseconds);
105            static void mainThreadCancel(ExecutionContext*, MainThreadBridge*);
106            virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) OVERRIDE;
107            virtual void didReceiveResponse(unsigned long identifier, const ResourceResponse&) OVERRIDE;
108            virtual void didReceiveData(const char*, int dataLength) OVERRIDE;
109            virtual void didDownloadData(int dataLength) OVERRIDE;
110            virtual void didReceiveCachedMetadata(const char*, int dataLength) OVERRIDE;
111            virtual void didFinishLoading(unsigned long identifier, double finishTime) OVERRIDE;
112            virtual void didFail(const ResourceError&) OVERRIDE;
113            virtual void didFailAccessControlCheck(const ResourceError&) OVERRIDE;
114            virtual void didFailRedirectCheck() OVERRIDE;
115
116            // Only to be used on the main thread.
117            RefPtr<ThreadableLoader> m_mainThreadLoader;
118            OwnPtr<ThreadableLoaderClient> m_clientBridge;
119
120            // ThreadableLoaderClientWrapper is to be used on the worker context thread.
121            // The ref counting is done on either thread.
122            RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
123
124            // Used on the worker context thread.
125            WorkerLoaderProxy& m_loaderProxy;
126        };
127
128        WorkerThreadableLoader(WorkerGlobalScope&, PassRefPtr<ThreadableLoaderClientWrapper>, PassOwnPtr<ThreadableLoaderClient>, const ResourceRequest&, const ThreadableLoaderOptions&, const ResourceLoaderOptions&);
129
130        RefPtrWillBePersistent<WorkerGlobalScope> m_workerGlobalScope;
131        RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
132        MainThreadBridge& m_bridge;
133    };
134
135} // namespace blink
136
137#endif // WorkerThreadableLoader_h
138