1 /* 2 * Copyright (C) 2010 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 WorkerFileWriterCallbacksBridge_h 32 #define WorkerFileWriterCallbacksBridge_h 33 34 #if ENABLE(FILE_SYSTEM) 35 36 #include "WebFileError.h" 37 #include "WebFileWriterClient.h" 38 #include "WorkerContext.h" 39 #include <wtf/PassOwnPtr.h> 40 #include <wtf/PassRefPtr.h> 41 #include <wtf/ThreadSafeRefCounted.h> 42 43 namespace WebCore { 44 class AsyncFileWriterClient; 45 class KURL; 46 class WorkerLoaderProxy; 47 } 48 49 namespace WTF { 50 class String; 51 } 52 using WTF::String; 53 54 namespace WebKit { 55 56 class WebFileSystem; 57 class WebFileWriter; 58 class WebFileWriterClient; 59 class WebWorkerBase; 60 61 // This class is used as a mechanism to bridge calls between threads. 62 // Calls to a WebFileWriter must happen on the main thread, but they come from 63 // the context thread. The responses through the WebFileWriterClient interface 64 // start on the main thread, but must be sent via the worker context thread. 65 // 66 // A typical flow for write would look like this: 67 // Bridge::postWriteToMainThread() on WorkerThread 68 // --> Bridge::writeOnMainThread() is called on MainThread 69 // --> WebFileWriter::write() 70 // This makes an IPC; the actual operation is down in the browser. 71 // --> Bridge::didWrite is called on MainThread 72 // --> Bridge::didWriteOnWorkerThread is called on WorkerThread 73 // This calls the original client (m_clientOnWorkerThread). 74 // 75 // The bridge object is refcounted, so that it doesn't get deleted while there 76 // are cross-thread calls in flight. Each CrossThreadTask carries a reference 77 // to the bridge, which guarantees that the bridge will still be valid when the 78 // task is executed. In order to shut down the bridge, the WebFileWriterClient 79 // should call postShutdownToMainThread before dropping its reference to the 80 // bridge. This ensures that the WebFileWriter will be cleared on the main 81 // thread and that no further calls to the WebFileWriterClient will be made. 82 class WorkerFileWriterCallbacksBridge : public ThreadSafeRefCounted<WorkerFileWriterCallbacksBridge>, public WebCore::WorkerContext::Observer, public WebFileWriterClient { 83 public: 84 ~WorkerFileWriterCallbacksBridge(); 85 86 // WorkerContext::Observer method. 87 virtual void notifyStop(); 88 create(const String & path,WebCore::WorkerLoaderProxy * proxy,WebCore::ScriptExecutionContext * workerContext,WebCore::AsyncFileWriterClient * client)89 static PassRefPtr<WorkerFileWriterCallbacksBridge> create(const String& path, WebCore::WorkerLoaderProxy* proxy, WebCore::ScriptExecutionContext* workerContext, WebCore::AsyncFileWriterClient* client) 90 { 91 return adoptRef(new WorkerFileWriterCallbacksBridge(path, proxy, workerContext, client)); 92 } 93 94 // Methods that create an instance and post an initial request task to the main thread. They must be called on the worker thread. 95 void postWriteToMainThread(long long position, const WebCore::KURL& data); 96 void postTruncateToMainThread(long long length); 97 void postAbortToMainThread(); 98 99 // The owning WorkerAsyncFileWriterChromium should call this method before dropping its last reference to the bridge, on the context thread. 100 // The actual deletion of the WorkerFileWriterCallbacksBridge may happen on either the main or context thread, depending on where the last reference goes away; that's safe as long as this is called first. 101 void postShutdownToMainThread(PassRefPtr<WorkerFileWriterCallbacksBridge>); 102 103 // Callback methods that are called on the main thread. 104 // These are the implementation of WebKit::WebFileWriterClient. 105 void didWrite(long long bytes, bool complete); 106 void didFail(WebFileError); 107 void didTruncate(); 108 109 // Call this on the context thread to wait for the current operation to complete. 110 bool waitForOperationToComplete(); 111 112 private: 113 WorkerFileWriterCallbacksBridge(const String& path, WebCore::WorkerLoaderProxy*, WebCore::ScriptExecutionContext*, WebCore::AsyncFileWriterClient*); 114 115 void postInitToMainThread(const String& path); 116 117 // Methods that are to be called on the main thread. 118 static void writeOnMainThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, long long position, const WebCore::KURL& data); 119 static void truncateOnMainThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, long long length); 120 static void abortOnMainThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>); 121 static void initOnMainThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, const String& path); 122 static void shutdownOnMainThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>); 123 124 // Methods that dispatch to AsyncFileWriterClient on the worker threads. 125 static void didWriteOnWorkerThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, long long length, bool complete); 126 static void didFailOnWorkerThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, WebFileError); 127 static void didTruncateOnWorkerThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>); 128 129 // Called on the main thread to run the supplied task. 130 static void runTaskOnMainThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, PassOwnPtr<WebCore::ScriptExecutionContext::Task>); 131 // Called on the worker thread to run the supplied task. 132 static void runTaskOnWorkerThread(WebCore::ScriptExecutionContext*, PassRefPtr<WorkerFileWriterCallbacksBridge>, PassOwnPtr<WebCore::ScriptExecutionContext::Task>); 133 134 // Called on the worker thread to dispatch to the main thread. 135 void dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task>); 136 // Called on the main thread to dispatch to the worker thread. 137 void dispatchTaskToWorkerThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task>); 138 139 // Used from the main thread to post tasks to the context thread. 140 WebCore::WorkerLoaderProxy* m_proxy; 141 142 // Used on the context thread, only to check that we're running on the context thread. 143 WebCore::ScriptExecutionContext* m_workerContext; 144 145 // Created and destroyed from the main thread. 146 OwnPtr<WebKit::WebFileWriter> m_writer; 147 148 // Used on the context thread to call back into the client. 149 WebCore::AsyncFileWriterClient* m_clientOnWorkerThread; 150 151 // Used to indicate that shutdown has started on the main thread, and hence the writer has been deleted. 152 bool m_writerDeleted; 153 154 // Used by waitForOperationToComplete. 155 bool m_operationInProgress; 156 157 // Used by postTaskForModeToWorkerContext and runInMode. 158 String m_mode; 159 }; 160 161 } // namespace WebCore 162 163 #endif 164 165 #endif // WorkerFileWriterCallbacksBridge_h 166