WebCore/loader/WorkerThreadableLoader.h
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/loader/WorkerThreadableLoader.h	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkerThreadableLoader_h
+#define WorkerThreadableLoader_h
+
+#if ENABLE(WORKERS)
+
+#include "PlatformString.h"
+#include "ThreadableLoader.h"
+#include "ThreadableLoaderClient.h"
+#include "ThreadableLoaderClientWrapper.h"
+
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+    class ResourceError;
+    class ResourceRequest;
+    class WorkerContext;
+    class WorkerLoaderProxy;
+    struct CrossThreadResourceResponseData;
+    struct CrossThreadResourceRequestData;
+
+    class WorkerThreadableLoader : public RefCounted<WorkerThreadableLoader>, public ThreadableLoader {
+    public:
+        static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
+        static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options)
+        {
+            return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, options));
+        }
+
+        ~WorkerThreadableLoader();
+
+        virtual void cancel();
+
+        bool done() const { return m_workerClientWrapper->done(); }
+
+        using RefCounted<WorkerThreadableLoader>::ref;
+        using RefCounted<WorkerThreadableLoader>::deref;
+
+    protected:
+        virtual void refThreadableLoader() { ref(); }
+        virtual void derefThreadableLoader() { deref(); }
+
+    private:
+        // Creates a loader on the main thread and bridges communication between
+        // the main thread and the worker context's thread where WorkerThreadableLoader runs.
+        //
+        // Regarding the bridge and lifetimes of items used in callbacks, there are a few cases:
+        //
+        // all cases. All tasks posted from the worker context's thread are ok because
+        //    the last task posted always is "mainThreadDestroy", so MainThreadBridge is
+        //    around for all tasks that use it on the main thread.
+        //
+        // case 1. worker.terminate is called.
+        //    In this case, no more tasks are posted from the worker object's thread to the worker
+        //    context's thread -- WorkerContextProxy implementation enforces this.
+        //
+        // case 2. xhr gets aborted and the worker context continues running.
+        //    The ThreadableLoaderClientWrapper has the underlying client cleared, so no more calls
+        //    go through it.  All tasks posted from the worker object's thread to the worker context's
+        //    thread do "ThreadableLoaderClientWrapper::ref" (automatically inside of the cross thread copy
+        //    done in createCallbackTask), so the ThreadableLoaderClientWrapper instance is there until all
+        //    tasks are executed.
+        class MainThreadBridge : public ThreadableLoaderClient {
+        public:
+            // All executed on the worker context's thread.
+            MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&);
+            void cancel();
+            void destroy();
+
+        private:
+            // Executed on the worker context's thread.
+            void clearClientWrapper();
+
+            // All executed on the main thread.
+            static void mainThreadDestroy(ScriptExecutionContext*, MainThreadBridge*);
+            ~MainThreadBridge();
+
+            static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, PassOwnPtr<CrossThreadResourceRequestData>, ThreadableLoaderOptions);
+            static void mainThreadCancel(ScriptExecutionContext*, MainThreadBridge*);
+            virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
+            virtual void didReceiveResponse(const ResourceResponse&);
+            virtual void didReceiveData(const char*, int lengthReceived);
+            virtual void didFinishLoading(unsigned long identifier);
+            virtual void didFail(const ResourceError&);
+            virtual void didFailRedirectCheck();
+            virtual void didReceiveAuthenticationCancellation(const ResourceResponse&);
+
+            // Only to be used on the main thread.
+            RefPtr<ThreadableLoader> m_mainThreadLoader;
+
+            // ThreadableLoaderClientWrapper is to be used on the worker context thread.
+            // The ref counting is done on either thread.
+            RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
+
+            // May be used on either thread.
+            WorkerLoaderProxy& m_loaderProxy;
+
+            // For use on the main thread.
+            String m_taskMode;
+        };
+
+        WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&);
+
+        RefPtr<WorkerContext> m_workerContext;
+        RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
+        MainThreadBridge& m_bridge;
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerThreadableLoader_h