Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(431)

Side by Side Diff: Source/WebCore/workers/DefaultSharedWorkerRepository.cpp

Issue 14262015: Removed unused files (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Patch Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "config.h"
32
33 #if ENABLE(SHARED_WORKERS)
34
35 #include "DefaultSharedWorkerRepository.h"
36
37 #include "ActiveDOMObject.h"
38 #include "CrossThreadTask.h"
39 #include "Document.h"
40 #include "ExceptionCode.h"
41 #include "InspectorInstrumentation.h"
42 #include "MessageEvent.h"
43 #include "MessagePort.h"
44 #include "NotImplemented.h"
45 #include "PageGroup.h"
46 #include "ScriptCallStack.h"
47 #include "SecurityOrigin.h"
48 #include "SecurityOriginHash.h"
49 #include "SharedWorker.h"
50 #include "SharedWorkerContext.h"
51 #include "SharedWorkerRepository.h"
52 #include "SharedWorkerThread.h"
53 #include "WorkerLoaderProxy.h"
54 #include "WorkerReportingProxy.h"
55 #include "WorkerScriptLoader.h"
56 #include "WorkerScriptLoaderClient.h"
57 #include <wtf/HashSet.h>
58 #include <wtf/Threading.h>
59 #include <wtf/text/WTFString.h>
60
61 namespace WebCore {
62
63 class SharedWorkerProxy : public ThreadSafeRefCounted<SharedWorkerProxy>, public WorkerLoaderProxy, public WorkerReportingProxy {
64 public:
65 static PassRefPtr<SharedWorkerProxy> create(const String& name, const KURL& url, PassRefPtr<SecurityOrigin> origin) { return adoptRef(new SharedWorkerProxy( name, url, origin)); }
66
67 void setThread(PassRefPtr<SharedWorkerThread> thread) { m_thread = thread; }
68 SharedWorkerThread* thread() { return m_thread.get(); }
69 bool isClosing() const { return m_closing; }
70 KURL url() const
71 {
72 // Don't use m_url.copy() because it isn't a threadsafe method.
73 return KURL(ParsedURLString, m_url.string().isolatedCopy());
74 }
75
76 String name() const { return m_name.isolatedCopy(); }
77 bool matches(const String& name, PassRefPtr<SecurityOrigin> origin, const KU RL& urlToMatch) const;
78
79 // WorkerLoaderProxy
80 virtual void postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task>);
81 virtual bool postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutionContex t::Task>, const String&);
82
83 // WorkerReportingProxy
84 virtual void postExceptionToWorkerObject(const String& errorMessage, int lin eNumber, const String& sourceURL);
85 virtual void postConsoleMessageToWorkerObject(MessageSource, MessageLevel, c onst String& message, int lineNumber, const String& sourceURL);
86 virtual void postMessageToPageInspector(const String&);
87 virtual void updateInspectorStateCookie(const String&);
88 virtual void workerContextClosed();
89 virtual void workerContextDestroyed();
90
91 // Updates the list of the worker's documents, per section 4.5 of the WebWor kers spec.
92 void addToWorkerDocuments(ScriptExecutionContext*);
93
94 bool isInWorkerDocuments(Document* document) { return m_workerDocuments.cont ains(document); }
95
96 // 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.
97 void documentDetached(Document*);
98
99 GroupSettings* groupSettings() const; // Page GroupSettings used by worker t hread.
100
101 private:
102 SharedWorkerProxy(const String& name, const KURL&, PassRefPtr<SecurityOrigin >);
103 void close();
104
105 bool m_closing;
106 String m_name;
107 KURL m_url;
108 // The thread is freed when the proxy is destroyed, so we need to make sure that the proxy stays around until the SharedWorkerContext exits.
109 RefPtr<SharedWorkerThread> m_thread;
110 RefPtr<SecurityOrigin> m_origin;
111 HashSet<Document*> m_workerDocuments;
112 // Ensures exclusive access to the worker documents. Must not grab any other locks (such as the DefaultSharedWorkerRepository lock) while holding this one.
113 Mutex m_workerDocumentsLock;
114 };
115
116 SharedWorkerProxy::SharedWorkerProxy(const String& name, const KURL& url, PassRe fPtr<SecurityOrigin> origin)
117 : m_closing(false)
118 , m_name(name.isolatedCopy())
119 , m_url(url.copy())
120 , m_origin(origin)
121 {
122 // We should be the sole owner of the SecurityOrigin, as we will free it on another thread.
123 ASSERT(m_origin->hasOneRef());
124 }
125
126 bool SharedWorkerProxy::matches(const String& name, PassRefPtr<SecurityOrigin> o rigin, const KURL& urlToMatch) const
127 {
128 // If the origins don't match, or the names don't match, then this is not th e proxy we are looking for.
129 if (!origin->equal(m_origin.get()))
130 return false;
131
132 // If the names are both empty, compares the URLs instead per the Web Worker s spec.
133 if (name.isEmpty() && m_name.isEmpty())
134 return urlToMatch == url();
135
136 return name == m_name;
137 }
138
139 void SharedWorkerProxy::postTaskToLoader(PassOwnPtr<ScriptExecutionContext::Task > task)
140 {
141 MutexLocker lock(m_workerDocumentsLock);
142
143 if (isClosing())
144 return;
145
146 // If we aren't closing, then we must have at least one document.
147 ASSERT(m_workerDocuments.size());
148
149 // Just pick an arbitrary active document from the HashSet and pass load req uests to it.
150 // FIXME: Do we need to deal with the case where the user closes the documen t mid-load, via a shadow document or some other solution?
151 Document* document = *(m_workerDocuments.begin());
152 document->postTask(task);
153 }
154
155 bool SharedWorkerProxy::postTaskForModeToWorkerContext(PassOwnPtr<ScriptExecutio nContext::Task> task, const String& mode)
156 {
157 if (isClosing())
158 return false;
159 ASSERT(m_thread);
160 m_thread->runLoop().postTaskForMode(task, mode);
161 return true;
162 }
163
164 GroupSettings* SharedWorkerProxy::groupSettings() const
165 {
166 if (isClosing())
167 return 0;
168 ASSERT(m_workerDocuments.size());
169 // Just pick the first active document, and use the groupsettings of that pa ge.
170 Document* document = *(m_workerDocuments.begin());
171 if (document->page())
172 return document->page()->group().groupSettings();
173
174 return 0;
175 }
176
177 static void postExceptionTask(ScriptExecutionContext* context, const String& err orMessage, int lineNumber, const String& sourceURL)
178 {
179 context->reportException(errorMessage, lineNumber, sourceURL, 0);
180 }
181
182 void SharedWorkerProxy::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL)
183 {
184 MutexLocker lock(m_workerDocumentsLock);
185 for (HashSet<Document*>::iterator iter = m_workerDocuments.begin(); iter != m_workerDocuments.end(); ++iter)
186 (*iter)->postTask(createCallbackTask(&postExceptionTask, errorMessage, l ineNumber, sourceURL));
187 }
188
189 static void postConsoleMessageTask(ScriptExecutionContext* document, MessageSour ce source, MessageLevel level, const String& message, const String& sourceURL, u nsigned lineNumber)
190 {
191 document->addConsoleMessage(source, level, message, sourceURL, lineNumber);
192 }
193
194 void SharedWorkerProxy::postConsoleMessageToWorkerObject(MessageSource source, M essageLevel level, const String& message, int lineNumber, const String& sourceUR L)
195 {
196 MutexLocker lock(m_workerDocumentsLock);
197 for (HashSet<Document*>::iterator iter = m_workerDocuments.begin(); iter != m_workerDocuments.end(); ++iter)
198 (*iter)->postTask(createCallbackTask(&postConsoleMessageTask, source, le vel, message, sourceURL, lineNumber));
199 }
200
201 void SharedWorkerProxy::postMessageToPageInspector(const String&)
202 {
203 notImplemented();
204 }
205
206 void SharedWorkerProxy::updateInspectorStateCookie(const String&)
207 {
208 notImplemented();
209 }
210
211 void SharedWorkerProxy::workerContextClosed()
212 {
213 if (isClosing())
214 return;
215 close();
216 }
217
218 void SharedWorkerProxy::workerContextDestroyed()
219 {
220 // The proxy may be freed by this call, so do not reference it any further.
221 DefaultSharedWorkerRepository::instance().removeProxy(this);
222 }
223
224 void SharedWorkerProxy::addToWorkerDocuments(ScriptExecutionContext* context)
225 {
226 // Nested workers are not yet supported, so passed-in context should always be a Document.
227 ASSERT_WITH_SECURITY_IMPLICATION(context->isDocument());
228 ASSERT(!isClosing());
229 MutexLocker lock(m_workerDocumentsLock);
230 Document* document = static_cast<Document*>(context);
231 m_workerDocuments.add(document);
232 }
233
234 void SharedWorkerProxy::documentDetached(Document* document)
235 {
236 if (isClosing())
237 return;
238 // 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.
239 MutexLocker lock(m_workerDocumentsLock);
240 m_workerDocuments.remove(document);
241 if (!m_workerDocuments.size())
242 close();
243 }
244
245 void SharedWorkerProxy::close()
246 {
247 ASSERT(!isClosing());
248 m_closing = true;
249 // Stop the worker thread - the proxy will stay around until we get workerTh readExited() notification.
250 if (m_thread)
251 m_thread->stop();
252 }
253
254 class SharedWorkerConnectTask : public ScriptExecutionContext::Task {
255 public:
256 static PassOwnPtr<SharedWorkerConnectTask> create(PassOwnPtr<MessagePortChan nel> channel)
257 {
258 return adoptPtr(new SharedWorkerConnectTask(channel));
259 }
260
261 private:
262 SharedWorkerConnectTask(PassOwnPtr<MessagePortChannel> channel)
263 : m_channel(channel)
264 {
265 }
266
267 virtual void performTask(ScriptExecutionContext* scriptContext)
268 {
269 RefPtr<MessagePort> port = MessagePort::create(*scriptContext);
270 port->entangle(m_channel.release());
271 ASSERT_WITH_SECURITY_IMPLICATION(scriptContext->isWorkerContext());
272 WorkerContext* workerContext = static_cast<WorkerContext*>(scriptContext );
273 // Since close() stops the thread event loop, this should not ever get c alled while closing.
274 ASSERT(!workerContext->isClosing());
275 ASSERT_WITH_SECURITY_IMPLICATION(workerContext->isSharedWorkerContext()) ;
276 workerContext->dispatchEvent(createConnectEvent(port));
277 }
278
279 OwnPtr<MessagePortChannel> m_channel;
280 };
281
282 // Loads the script on behalf of a worker.
283 class SharedWorkerScriptLoader : public RefCounted<SharedWorkerScriptLoader>, pr ivate WorkerScriptLoaderClient {
284 public:
285 SharedWorkerScriptLoader(PassRefPtr<SharedWorker>, PassOwnPtr<MessagePortCha nnel>, PassRefPtr<SharedWorkerProxy>);
286 void load(const KURL&);
287
288 private:
289 // WorkerScriptLoaderClient callbacks
290 virtual void didReceiveResponse(unsigned long identifier, const ResourceResp onse&);
291 virtual void notifyFinished();
292
293 RefPtr<SharedWorker> m_worker;
294 OwnPtr<MessagePortChannel> m_port;
295 RefPtr<SharedWorkerProxy> m_proxy;
296 RefPtr<WorkerScriptLoader> m_scriptLoader;
297 };
298
299 SharedWorkerScriptLoader::SharedWorkerScriptLoader(PassRefPtr<SharedWorker> work er, PassOwnPtr<MessagePortChannel> port, PassRefPtr<SharedWorkerProxy> proxy)
300 : m_worker(worker)
301 , m_port(port)
302 , m_proxy(proxy)
303 {
304 }
305
306 void SharedWorkerScriptLoader::load(const KURL& url)
307 {
308 // Stay alive (and keep the SharedWorker and JS wrapper alive) until the loa d finishes.
309 this->ref();
310 m_worker->setPendingActivity(m_worker.get());
311
312 // Mark this object as active for the duration of the load.
313 m_scriptLoader = WorkerScriptLoader::create();
314 m_scriptLoader->loadAsynchronously(m_worker->scriptExecutionContext(), url, DenyCrossOriginRequests, this);
315 }
316
317 void SharedWorkerScriptLoader::didReceiveResponse(unsigned long identifier, cons t ResourceResponse&)
318 {
319 InspectorInstrumentation::didReceiveScriptResponse(m_worker->scriptExecution Context(), identifier);
320 }
321
322 void SharedWorkerScriptLoader::notifyFinished()
323 {
324 // FIXME: This method is not guaranteed to be invoked if we are loading from WorkerContext (see comment for WorkerScriptLoaderClient::notifyFinished()).
325 // We need to address this before supporting nested workers.
326
327 // Hand off the just-loaded code to the repository to start up the worker th read.
328 if (m_scriptLoader->failed())
329 m_worker->dispatchEvent(Event::create(eventNames().errorEvent, false, tr ue));
330 else {
331 InspectorInstrumentation::scriptImported(m_worker->scriptExecutionContex t(), m_scriptLoader->identifier(), m_scriptLoader->script());
332 DefaultSharedWorkerRepository::instance().workerScriptLoaded(*m_proxy, m _worker->scriptExecutionContext()->userAgent(m_scriptLoader->url()),
333 m_scriptLoa der->script(), m_port.release(),
334 m_worker->s criptExecutionContext()->contentSecurityPolicy()->deprecatedHeader(),
335 m_worker->s criptExecutionContext()->contentSecurityPolicy()->deprecatedHeaderType());
336 }
337 m_worker->unsetPendingActivity(m_worker.get());
338 this->deref(); // This frees this object - must be the last action in this f unction.
339 }
340
341 DefaultSharedWorkerRepository& DefaultSharedWorkerRepository::instance()
342 {
343 AtomicallyInitializedStatic(DefaultSharedWorkerRepository*, instance = new D efaultSharedWorkerRepository);
344 return *instance;
345 }
346
347 void DefaultSharedWorkerRepository::workerScriptLoaded(SharedWorkerProxy& proxy, const String& userAgent, const String& workerScript, PassOwnPtr<MessagePortChan nel> port, const String& contentSecurityPolicy, ContentSecurityPolicy::HeaderTyp e contentSecurityPolicyType)
348 {
349 MutexLocker lock(m_lock);
350 if (proxy.isClosing())
351 return;
352
353 // Another loader may have already started up a thread for this proxy - if s o, just send a connect to the pre-existing thread.
354 if (!proxy.thread()) {
355 RefPtr<SharedWorkerThread> thread = SharedWorkerThread::create(proxy.nam e(), proxy.url(), userAgent, proxy.groupSettings(), workerScript, proxy, proxy, DontPauseWorkerContextOnStart, contentSecurityPolicy, contentSecurityPolicyType) ;
356 proxy.setThread(thread);
357 thread->start();
358 }
359 proxy.thread()->runLoop().postTask(SharedWorkerConnectTask::create(port));
360 }
361
362 bool DefaultSharedWorkerRepository::hasSharedWorkers(Document* document)
363 {
364 MutexLocker lock(m_lock);
365 for (unsigned i = 0; i < m_proxies.size(); i++) {
366 if (m_proxies[i]->isInWorkerDocuments(document))
367 return true;
368 }
369 return false;
370 }
371
372 void DefaultSharedWorkerRepository::removeProxy(SharedWorkerProxy* proxy)
373 {
374 MutexLocker lock(m_lock);
375 for (unsigned i = 0; i < m_proxies.size(); i++) {
376 if (proxy == m_proxies[i].get()) {
377 m_proxies.remove(i);
378 return;
379 }
380 }
381 }
382
383 void DefaultSharedWorkerRepository::documentDetached(Document* document)
384 {
385 MutexLocker lock(m_lock);
386 for (unsigned i = 0; i < m_proxies.size(); i++)
387 m_proxies[i]->documentDetached(document);
388 }
389
390 void DefaultSharedWorkerRepository::connectToWorker(PassRefPtr<SharedWorker> wor ker, PassOwnPtr<MessagePortChannel> port, const KURL& url, const String& name, E xceptionCode& ec)
391 {
392 MutexLocker lock(m_lock);
393 ASSERT(worker->scriptExecutionContext()->securityOrigin()->canAccess(Securit yOrigin::create(url).get()));
394 // Fetch a proxy corresponding to this SharedWorker.
395 RefPtr<SharedWorkerProxy> proxy = getProxy(name, url);
396
397 // FIXME: Why is this done even if we are raising an exception below?
398 proxy->addToWorkerDocuments(worker->scriptExecutionContext());
399
400 if (proxy->url() != url) {
401 // Proxy already existed under alternate URL - return an error.
402 ec = URL_MISMATCH_ERR;
403 return;
404 }
405 // If proxy is already running, just connect to it - otherwise, kick off a l oader to load the script.
406 if (proxy->thread())
407 proxy->thread()->runLoop().postTask(SharedWorkerConnectTask::create(port ));
408 else {
409 RefPtr<SharedWorkerScriptLoader> loader = adoptRef(new SharedWorkerScrip tLoader(worker, port, proxy.release()));
410 loader->load(url);
411 }
412 }
413
414 // Creates a new SharedWorkerProxy or returns an existing one from the repositor y. Must only be called while the repository mutex is held.
415 PassRefPtr<SharedWorkerProxy> DefaultSharedWorkerRepository::getProxy(const Stri ng& name, const KURL& url)
416 {
417 // Look for an existing worker, and create one if it doesn't exist.
418 // Items in the cache are freed on another thread, so do a threadsafe copy o f the URL before creating the origin,
419 // to make sure no references to external strings linger.
420 RefPtr<SecurityOrigin> origin = SecurityOrigin::create(KURL(ParsedURLString, url.string().isolatedCopy()));
421 for (unsigned i = 0; i < m_proxies.size(); i++) {
422 if (!m_proxies[i]->isClosing() && m_proxies[i]->matches(name, origin, ur l))
423 return m_proxies[i];
424 }
425 // Proxy is not in the repository currently - create a new one.
426 RefPtr<SharedWorkerProxy> proxy = SharedWorkerProxy::create(name, url, origi n.release());
427 m_proxies.append(proxy);
428 return proxy.release();
429 }
430
431 DefaultSharedWorkerRepository::DefaultSharedWorkerRepository()
432 {
433 }
434
435 DefaultSharedWorkerRepository::~DefaultSharedWorkerRepository()
436 {
437 }
438
439 } // namespace WebCore
440
441 #endif // ENABLE(SHARED_WORKERS)
OLDNEW
« no previous file with comments | « Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.cpp ('k') | Source/WebCore/workers/SharedWorkerRepository.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698