Changeset 47078 in webkit
- Timestamp:
- Aug 11, 2009 6:05:22 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r47076 r47078 1 2009-08-11 Drew Wilson <atwilson@google.com> 2 3 Reviewed by David Levin. 4 5 SharedWorkers do not exit when the last parent document exits. 6 https://bugs.webkit.org/show_bug.cgi?id=28170 7 8 Added more tests to check that previous incarnations of the SharedWorker "name" are shut down. 9 10 * fast/workers/shared-worker-replace-global-constructor.html-disabled: 11 Fixed incorrect path to common script. 12 * fast/workers/shared-worker-shared-expected.txt: 13 * fast/workers/shared-worker-shared.html-disabled: 14 Added more tests for sharing, including initial test to make sure previous incarnations of shared worker were closed. 15 * fast/workers/worker-replace-global-constructor.html: 16 Removed extraneous closing HTML tag. 17 1 18 2009-08-11 Chris Fleizach <cfleizach@apple.com> 2 19 -
trunk/LayoutTests/fast/workers/shared-worker-replace-global-constructor.html-disabled
r46852 r47078 3 3 <div id=result></div> 4 4 <script src="resources/shared-worker-create-common.js"></script> 5 <script src=" worker-replace-global-constructor.js">5 <script src="resources/worker-replace-global-constructor.js"> 6 6 </script> 7 7 </body> -
trunk/LayoutTests/fast/workers/shared-worker-shared-expected.txt
r46925 r47078 2 2 3 3 PASS: Exception thrown when creating SharedWorker with different URLs but same name: Error: URL_MISMATCH_ERR: DOM Exception 21 4 PASS: Accessing new instance of shared worker: self.foo: undefined 4 5 PASS: Setting global variable in shared worker: self.foo = 1234: 1234 5 6 PASS: Accessing simultaneously-loaded instance of shared worker: self.foo: 1234 -
trunk/LayoutTests/fast/workers/shared-worker-shared.html-disabled
r46925 r47078 14 14 15 15 // Load two workers simultaneously, to ensure that simultaneous loads also yield the same instance. 16 // Loading a worker named "name" tests that workers shutdown when the parent document exits, because other tests also create workers with that same name but with different URLs. 16 17 var worker = new SharedWorker('resources/shared-worker-common.js', 'name'); 17 18 var worker2 = new SharedWorker('resources/shared-worker-common.js', 'name'); … … 26 27 27 28 // Set something in global context in one worker, read value back on other worker, to make sure they are truly shared. 28 worker.port.postMessage("eval self.foo = 1234"); 29 29 worker.port.postMessage("eval self.foo"); 30 30 worker.port.onmessage = function(event) 31 31 { 32 log((event.data == "self.foo = 1234: 1234" ? "PASS: " : "FAIL: ") + "Setting global variable inshared worker: " + event.data);33 worker 2.port.postMessage("eval self.foo");34 worker 2.port.onmessage = function(event)32 log((event.data == "self.foo: undefined" ? "PASS: " : "FAIL: ") + "Accessing new instance of shared worker: " + event.data); 33 worker.port.postMessage("eval self.foo = 1234"); 34 worker.port.onmessage = function(event) 35 35 { 36 log((event.data == "self.foo: 1234" ? "PASS: " : "FAIL: ") + "Accessing simultaneously-loaded instance of shared worker: " + event.data); 37 testNewWorker(); 36 log((event.data == "self.foo = 1234: 1234" ? "PASS: " : "FAIL: ") + "Setting global variable in shared worker: " + event.data); 37 worker2.port.postMessage("eval self.foo"); 38 worker2.port.onmessage = function(event) 39 { 40 log((event.data == "self.foo: 1234" ? "PASS: " : "FAIL: ") + "Accessing simultaneously-loaded instance of shared worker: " + event.data); 41 testNewWorker(); 42 } 38 43 } 39 44 } -
trunk/LayoutTests/fast/workers/worker-replace-global-constructor.html
r46852 r47078 6 6 </script> 7 7 </body> 8 </html> -
trunk/WebCore/ChangeLog
r47076 r47078 1 2009-08-11 Drew Wilson <atwilson@google.com> 2 3 Reviewed by David Levin. 4 5 SharedWorkers do not exit when the last parent document exits 6 https://bugs.webkit.org/show_bug.cgi?id=28170 7 8 Prevents Documents from being suspended/placed in the page cache if they are associated with shared workers. 9 10 Added vector cache instead of nested hash tables for SharedWorker repository. 11 12 Added SharedWorkerRepository::documentDetached API. 13 14 * dom/Document.cpp: 15 (WebCore::Document::detach): 16 Notifies SharedWorkerRepository when the document is closing. 17 * loader/FrameLoader.cpp: 18 Updated FrameLoader to not cache the Document if it is associated with a SharedWorker (since we can't suspend workers yet, we need to shut them down). 19 (WebCore::FrameLoader::canCachePageContainingThisFrame): 20 (WebCore::FrameLoader::logCanCacheFrameDecision): 21 * workers/DefaultSharedWorkerRepository.cpp: 22 (WebCore::SharedWorkerProxy::create): 23 (WebCore::SharedWorkerProxy::isClosing): 24 Renamed from closing(). 25 (WebCore::SharedWorkerProxy::matches): 26 Added manual equality function to replace old hash lookup. 27 (WebCore::SharedWorkerProxy::isDocumentInWorkerDocuments): 28 Checks to see if a document is in the worker's list of documents. Used to determine if page is suspendable. 29 (WebCore::SharedWorkerProxy::SharedWorkerProxy): 30 (WebCore::SharedWorkerProxy::addToWorkerDocuments): 31 Added tracking of the worker's list of documents for lifecycle purposes. 32 (WebCore::SharedWorkerProxy::documentDetached): 33 Shuts down the proxy when the last associated document is detached. 34 (WebCore::SharedWorkerProxy::close): 35 Marks the proxy as closed so it is no longer shared with new instances. 36 (WebCore::SharedWorkerProxy::workerContextDestroyed): 37 Removes the proxy from the repository/frees the proxy when the associated SharedWorkerContext is destroyed. 38 (WebCore::DefaultSharedWorkerRepository::workerScriptLoaded): 39 closing()->isClosing() 40 (WebCore::SharedWorkerRepository::documentDetached): 41 (WebCore::SharedWorkerRepository::hasSharedWorkers): 42 Used by FrameLoader to determine if a page has shared workers and so cannot be suspended/cached. 43 (WebCore::DefaultSharedWorkerRepository::hasSharedWorkers): 44 (WebCore::DefaultSharedWorkerRepository::removeProxy): 45 Invoked by workerContextDestroyed() to remove a SharedWorkerProxy from the repository. 46 (WebCore::DefaultSharedWorkerRepository::documentDetached): 47 (WebCore::DefaultSharedWorkerRepository::connectToWorker): 48 (WebCore::DefaultSharedWorkerRepository::getProxy): 49 * workers/DefaultSharedWorkerRepository.h: 50 * workers/SharedWorkerRepository.h: 51 1 52 2009-08-11 Chris Fleizach <cfleizach@apple.com> 2 53 -
trunk/WebCore/dom/Document.cpp
r46592 r47078 109 109 #include "SelectionController.h" 110 110 #include "Settings.h" 111 #include "SharedWorkerRepository.h" 111 112 #include "StyleSheetList.h" 112 113 #include "TextEvent.h" … … 1349 1350 // in order to stop media elements 1350 1351 documentWillBecomeInactive(); 1351 1352 1353 #if ENABLE(SHARED_WORKERS) 1354 SharedWorkerRepository::documentDetached(this); 1355 #endif 1356 1352 1357 if (m_frame) { 1353 1358 FrameView* view = m_frame->view(); -
trunk/WebCore/loader/FrameLoader.cpp
r46978 r47078 88 88 #include "SegmentedString.h" 89 89 #include "Settings.h" 90 #include "SharedWorkerRepository.h" 90 91 #include "TextResourceDecoder.h" 91 92 #include "WindowFeatures.h" … … 1813 1814 && !m_frame->document()->hasOpenDatabases() 1814 1815 #endif 1816 #if ENABLE(SHARED_WORKERS) 1817 && !SharedWorkerRepository::hasSharedWorkers(m_frame->document()) 1818 #endif 1815 1819 && !m_frame->document()->usingGeolocation() 1816 1820 && m_currentHistoryItem … … 1958 1962 if (m_frame->document()->hasOpenDatabases()) 1959 1963 { PCLOG(" -Frame has open database handles"); cannotCache = true; } 1964 #endif 1965 #if ENABLE(SHARED_WORKERS) 1966 if (SharedWorkerRepository::hasSharedWorkers(m_frame->document())) 1967 { PCLOG(" -Frame has associated SharedWorkers"); cannotCache = true; } 1960 1968 #endif 1961 1969 if (m_frame->document()->usingGeolocation()) -
trunk/WebCore/workers/DefaultSharedWorkerRepository.cpp
r47036 r47078 36 36 37 37 #include "ActiveDOMObject.h" 38 #include "Document.h" 38 39 #include "MessagePort.h" 39 40 #include "NotImplemented.h" … … 43 44 #include "SharedWorker.h" 44 45 #include "SharedWorkerContext.h" 46 #include "SharedWorkerRepository.h" 45 47 #include "SharedWorkerThread.h" 46 48 #include "WorkerLoaderProxy.h" … … 48 50 #include "WorkerScriptLoader.h" 49 51 #include "WorkerScriptLoaderClient.h" 50 52 #include <wtf/HashSet.h> 51 53 #include <wtf/Threading.h> 52 54 … … 55 57 class SharedWorkerProxy : public ThreadSafeShared<SharedWorkerProxy>, public WorkerLoaderProxy, public WorkerReportingProxy { 56 58 public: 57 static PassRefPtr<SharedWorkerProxy> create(const String& name, const KURL& url ) { return adoptRef(new SharedWorkerProxy(name, url)); }59 static PassRefPtr<SharedWorkerProxy> create(const String& name, const KURL& url, PassRefPtr<SecurityOrigin> origin) { return adoptRef(new SharedWorkerProxy(name, url, origin)); } 58 60 59 61 void setThread(PassRefPtr<SharedWorkerThread> thread) { m_thread = thread; } 60 62 SharedWorkerThread* thread() { return m_thread.get(); } 61 bool closing() const { return m_closing; } 63 bool isClosing() const { return m_closing; } 64 void close(); 62 65 KURL url() const { return m_url.copy(); } 63 66 String name() const { return m_name.copy(); } 67 bool matches(const String& name, PassRefPtr<SecurityOrigin> origin) const { return name == m_name && origin->equal(m_origin.get()); } 64 68 65 69 // WorkerLoaderProxy … … 77 81 void addToWorkerDocuments(ScriptExecutionContext*); 78 82 83 bool isInWorkerDocuments(Document* document) { return m_workerDocuments.contains(document); } 84 85 // Removes a detached document from the list of worker's documents. May set the closing flag if this is the last document in the list. 86 void documentDetached(Document*); 87 79 88 private: 80 SharedWorkerProxy(const String& name, const KURL& );89 SharedWorkerProxy(const String& name, const KURL&, PassRefPtr<SecurityOrigin>); 81 90 bool m_closing; 82 91 String m_name; 83 92 KURL m_url; 93 // The thread is freed when the proxy is destroyed, so we need to make sure that the proxy stays around until the SharedWorkerContext exits. 84 94 RefPtr<SharedWorkerThread> m_thread; 95 RefPtr<SecurityOrigin> m_origin; 96 HashSet<Document*> m_workerDocuments; 85 97 }; 86 98 87 SharedWorkerProxy::SharedWorkerProxy(const String& name, const KURL& url )99 SharedWorkerProxy::SharedWorkerProxy(const String& name, const KURL& url, PassRefPtr<SecurityOrigin> origin) 88 100 : m_closing(false) 89 101 , m_name(name.copy()) 90 102 , m_url(url.copy()) 91 { 103 , m_origin(origin) 104 { 105 // We should be the sole owner of the SecurityOrigin, as we will free it on another thread. 106 ASSERT(m_origin->hasOneRef()); 92 107 } 93 108 … … 119 134 // Nested workers are not yet supported, so passed-in context should always be a Document. 120 135 ASSERT(context->isDocument()); 121 // FIXME: track referring documents so we can shutdown the thread when the last one exits and remove the proxy from the cache. 136 ASSERT(!isClosing()); 137 Document* document = static_cast<Document*>(context); 138 m_workerDocuments.add(document); 139 } 140 141 void SharedWorkerProxy::documentDetached(Document* document) 142 { 143 if (isClosing()) 144 return; 145 // Remove the document from our set (if it's there) and if that was the last document in the set, mark the proxy as closed. 146 m_workerDocuments.remove(document); 147 if (!m_workerDocuments.size()) 148 close(); 149 } 150 151 void SharedWorkerProxy::close() 152 { 153 ASSERT(!isClosing()); 154 m_closing = true; 155 // Stop the worker thread - the proxy will stay around until we get workerThreadExited() notification. 156 if (m_thread) 157 m_thread->stop(); 158 } 159 160 void SharedWorkerProxy::postExceptionToWorkerObject(const String&, int, const String&) 161 { 162 // FIXME: Log exceptions to all parent documents. 163 notImplemented(); 164 } 165 166 void SharedWorkerProxy::postConsoleMessageToWorkerObject(MessageDestination, MessageSource, MessageType, MessageLevel, const String&, int, const String&) 167 { 168 // FIXME: Log console messages to all parent documents. 169 notImplemented(); 170 } 171 172 // When close() is invoked, mark the proxy as closing so we don't share it with any new requests. 173 void SharedWorkerProxy::workerContextClosed() 174 { 175 m_closing = true; 176 } 177 178 void SharedWorkerProxy::workerContextDestroyed() 179 { 180 // The proxy may be freed by this call, so do not reference it any further. 181 DefaultSharedWorkerRepository::instance().removeProxy(this); 122 182 } 123 183 … … 204 264 { 205 265 MutexLocker lock(m_lock); 206 if (proxy. closing())266 if (proxy.isClosing()) 207 267 return; 208 268 … … 219 279 { 220 280 DefaultSharedWorkerRepository::instance().connectToWorker(worker, port, url, name, ec); 281 } 282 283 void SharedWorkerRepository::documentDetached(Document* document) 284 { 285 DefaultSharedWorkerRepository::instance().documentDetached(document); 286 } 287 288 bool SharedWorkerRepository::hasSharedWorkers(Document* document) 289 { 290 return DefaultSharedWorkerRepository::instance().hasSharedWorkers(document); 291 } 292 293 bool DefaultSharedWorkerRepository::hasSharedWorkers(Document* document) 294 { 295 MutexLocker lock(m_lock); 296 for (unsigned i = 0; i < m_proxies.size(); i++) { 297 if (m_proxies[i]->isInWorkerDocuments(document)) 298 return true; 299 } 300 return false; 301 } 302 303 void DefaultSharedWorkerRepository::removeProxy(SharedWorkerProxy* proxy) 304 { 305 MutexLocker lock(m_lock); 306 for (unsigned i = 0; i < m_proxies.size(); i++) { 307 if (proxy == m_proxies[i].get()) { 308 m_proxies.remove(i); 309 return; 310 } 311 } 312 } 313 314 void DefaultSharedWorkerRepository::documentDetached(Document* document) 315 { 316 MutexLocker lock(m_lock); 317 for (unsigned i = 0; i < m_proxies.size(); i++) 318 m_proxies[i]->documentDetached(document); 221 319 } 222 320 … … 248 346 // Items in the cache are freed on another thread, so copy the URL before creating the origin, to make sure no references to external strings linger. 249 347 RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url.copy()); 250 SharedWorkerNameMap* nameMap = m_cache.get(origin); 251 if (!nameMap) { 252 nameMap = new SharedWorkerNameMap(); 253 m_cache.set(origin, nameMap); 254 } 255 256 RefPtr<SharedWorkerProxy> proxy = nameMap->get(name); 257 if (!proxy.get()) { 258 proxy = SharedWorkerProxy::create(name, url); 259 nameMap->set(proxy->name(), proxy); 260 } 261 return proxy; 348 for (unsigned i = 0; i < m_proxies.size(); i++) { 349 if (!m_proxies[i]->isClosing() && m_proxies[i]->matches(name, origin)) 350 return m_proxies[i]; 351 } 352 // Proxy is not in the repository currently - create a new one. 353 RefPtr<SharedWorkerProxy> proxy = SharedWorkerProxy::create(name, url, origin.release()); 354 m_proxies.append(proxy); 355 return proxy.release(); 262 356 } 263 357 -
trunk/WebCore/workers/DefaultSharedWorkerRepository.h
r46925 r47078 34 34 #if ENABLE(SHARED_WORKERS) 35 35 36 #include " SharedWorkerRepository.h"36 #include "ExceptionCode.h" 37 37 #include "StringHash.h" 38 38 #include <wtf/HashMap.h> 39 39 #include <wtf/Noncopyable.h> 40 #include <wtf/PassOwnPtr.h> 41 #include <wtf/PassRefPtr.h> 40 42 #include <wtf/RefPtr.h> 41 43 #include <wtf/Threading.h> … … 43 45 namespace WebCore { 44 46 47 class Document; 45 48 class KURL; 49 class MessagePortChannel; 46 50 class ScriptExecutionContext; 47 class S ecurityOrigin;51 class SharedWorker; 48 52 class SharedWorkerProxy; 49 50 struct SecurityOriginHash; 51 struct SecurityOriginTraits; 53 class String; 52 54 53 55 // Platform-specific implementation of the SharedWorkerRepository static interface. … … 60 62 void connectToWorker(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortChannel>, const KURL&, const String& name, ExceptionCode&); 61 63 64 // Notification that a document has been detached. 65 void documentDetached(Document*); 66 67 // Removes the passed SharedWorkerProxy from the repository. 68 void removeProxy(SharedWorkerProxy*); 69 70 bool hasSharedWorkers(Document*); 71 62 72 static DefaultSharedWorkerRepository& instance(); 63 73 private: … … 69 79 Mutex m_lock; 70 80 71 typedef HashMap<String, RefPtr<SharedWorkerProxy> > SharedWorkerNameMap; 72 typedef HashMap<RefPtr<SecurityOrigin>, SharedWorkerNameMap*, SecurityOriginHash> SharedWorkerProxyCache; 73 74 // Items in this cache may be freed on another thread, so all keys and values must be either copied before insertion or thread safe. 75 SharedWorkerProxyCache m_cache; 81 // List of shared workers. Expectation is that there will be a limited number of shared workers, and so tracking them in a Vector is more efficient than nested HashMaps. 82 typedef Vector<RefPtr<SharedWorkerProxy> > SharedWorkerProxyRepository; 83 SharedWorkerProxyRepository m_proxies; 76 84 }; 77 85 -
trunk/WebCore/workers/SharedWorkerRepository.h
r46925 r47078 35 35 36 36 #include "ExceptionCode.h" 37 38 37 #include <wtf/PassOwnPtr.h> 39 38 #include <wtf/PassRefPtr.h> … … 41 40 namespace WebCore { 42 41 42 class Document; 43 43 class KURL; 44 44 class MessagePortChannel; … … 51 51 // Connects the passed SharedWorker object with the specified worker thread, creating a new thread if necessary. 52 52 static void connect(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortChannel>, const KURL&, const String& name, ExceptionCode&); 53 54 // Invoked when a document has been detached. 55 static void documentDetached(Document*); 56 57 // Returns true if the passed document is associated with any SharedWorkers. 58 static bool hasSharedWorkers(Document*); 53 59 private: 54 60 SharedWorkerRepository() { }
Note: See TracChangeset
for help on using the changeset viewer.