• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 #include "config.h"
28 #include "ScriptExecutionContext.h"
29 
30 #include "ActiveDOMObject.h"
31 #include "Document.h"
32 #include "MessagePort.h"
33 #include "SecurityOrigin.h"
34 #include "WorkerContext.h"
35 #include "WorkerThread.h"
36 #include <wtf/MainThread.h>
37 #include <wtf/PassRefPtr.h>
38 
39 namespace WebCore {
40 
41 class ProcessMessagesSoonTask : public ScriptExecutionContext::Task {
42 public:
create()43     static PassRefPtr<ProcessMessagesSoonTask> create()
44     {
45         return adoptRef(new ProcessMessagesSoonTask);
46     }
47 
performTask(ScriptExecutionContext * context)48     virtual void performTask(ScriptExecutionContext* context)
49     {
50         context->dispatchMessagePortEvents();
51     }
52 };
53 
ScriptExecutionContext()54 ScriptExecutionContext::ScriptExecutionContext()
55 {
56 }
57 
~ScriptExecutionContext()58 ScriptExecutionContext::~ScriptExecutionContext()
59 {
60     HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
61     for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
62         ASSERT(iter->first->scriptExecutionContext() == this);
63         iter->first->contextDestroyed();
64     }
65 
66     HashSet<MessagePort*>::iterator messagePortsEnd = m_messagePorts.end();
67     for (HashSet<MessagePort*>::iterator iter = m_messagePorts.begin(); iter != messagePortsEnd; ++iter) {
68         ASSERT((*iter)->scriptExecutionContext() == this);
69         (*iter)->contextDestroyed();
70     }
71 }
72 
processMessagePortMessagesSoon()73 void ScriptExecutionContext::processMessagePortMessagesSoon()
74 {
75     postTask(ProcessMessagesSoonTask::create());
76 }
77 
dispatchMessagePortEvents()78 void ScriptExecutionContext::dispatchMessagePortEvents()
79 {
80     RefPtr<ScriptExecutionContext> protect(this);
81 
82     // Make a frozen copy.
83     Vector<MessagePort*> ports;
84     copyToVector(m_messagePorts, ports);
85 
86     unsigned portCount = ports.size();
87     for (unsigned i = 0; i < portCount; ++i) {
88         MessagePort* port = ports[i];
89         // The port may be destroyed, and another one created at the same address, but this is safe, as the worst that can happen
90         // as a result is that dispatchMessages() will be called needlessly.
91         if (m_messagePorts.contains(port) && port->queueIsOpen())
92             port->dispatchMessages();
93     }
94 }
95 
createdMessagePort(MessagePort * port)96 void ScriptExecutionContext::createdMessagePort(MessagePort* port)
97 {
98     ASSERT(port);
99 #if ENABLE(WORKERS)
100     ASSERT((isDocument() && isMainThread())
101         || (isWorkerContext() && currentThread() == static_cast<WorkerContext*>(this)->thread()->threadID()));
102 #endif
103 
104     m_messagePorts.add(port);
105 }
106 
destroyedMessagePort(MessagePort * port)107 void ScriptExecutionContext::destroyedMessagePort(MessagePort* port)
108 {
109     ASSERT(port);
110 #if ENABLE(WORKERS)
111     ASSERT((isDocument() && isMainThread())
112         || (isWorkerContext() && currentThread() == static_cast<WorkerContext*>(this)->thread()->threadID()));
113 #endif
114 
115     m_messagePorts.remove(port);
116 }
117 
canSuspendActiveDOMObjects()118 bool ScriptExecutionContext::canSuspendActiveDOMObjects()
119 {
120     // No protection against m_activeDOMObjects changing during iteration: canSuspend() shouldn't execute arbitrary JS.
121     HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
122     for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
123         ASSERT(iter->first->scriptExecutionContext() == this);
124         if (!iter->first->canSuspend())
125             return false;
126     }
127     return true;
128 }
129 
suspendActiveDOMObjects()130 void ScriptExecutionContext::suspendActiveDOMObjects()
131 {
132     // No protection against m_activeDOMObjects changing during iteration: suspend() shouldn't execute arbitrary JS.
133     HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
134     for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
135         ASSERT(iter->first->scriptExecutionContext() == this);
136         iter->first->suspend();
137     }
138 }
139 
resumeActiveDOMObjects()140 void ScriptExecutionContext::resumeActiveDOMObjects()
141 {
142     // No protection against m_activeDOMObjects changing during iteration: resume() shouldn't execute arbitrary JS.
143     HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
144     for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
145         ASSERT(iter->first->scriptExecutionContext() == this);
146         iter->first->resume();
147     }
148 }
149 
stopActiveDOMObjects()150 void ScriptExecutionContext::stopActiveDOMObjects()
151 {
152     // No protection against m_activeDOMObjects changing during iteration: stop() shouldn't execute arbitrary JS.
153     HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end();
154     for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) {
155         ASSERT(iter->first->scriptExecutionContext() == this);
156         iter->first->stop();
157     }
158 }
159 
createdActiveDOMObject(ActiveDOMObject * object,void * upcastPointer)160 void ScriptExecutionContext::createdActiveDOMObject(ActiveDOMObject* object, void* upcastPointer)
161 {
162     ASSERT(object);
163     ASSERT(upcastPointer);
164     m_activeDOMObjects.add(object, upcastPointer);
165 }
166 
destroyedActiveDOMObject(ActiveDOMObject * object)167 void ScriptExecutionContext::destroyedActiveDOMObject(ActiveDOMObject* object)
168 {
169     ASSERT(object);
170     m_activeDOMObjects.remove(object);
171 }
172 
setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)173 void ScriptExecutionContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
174 {
175     m_securityOrigin = securityOrigin;
176 }
177 
~Task()178 ScriptExecutionContext::Task::~Task()
179 {
180 }
181 
182 } // namespace WebCore
183