17a1094d9f7e952df83b20cd94da657b08deb8b2
[WebKit.git] / WebKit2 / WebProcess / WebProcess.cpp
1 /*
2  * Copyright (C) 2009, 2010 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 INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "WebProcess.h"
27
28 #include "InjectedBundle.h"
29 #if PLATFORM(MAC)
30 #include "MachPort.h"
31 #endif
32 #include "RunLoop.h"
33 #include "WebCoreArgumentCoders.h"
34 #include "WebFrame.h"
35 #include "WebPage.h"
36 #include "WebPlatformStrategies.h"
37 #include "WebPreferencesStore.h"
38 #include "WebProcessMessageKinds.h"
39 #include <wtf/PassRefPtr.h>
40
41 #ifndef NDEBUG
42 #include <WebCore/Cache.h>
43 #include <WebCore/GCController.h>
44 #endif
45
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 WebProcess& WebProcess::shared()
51 {
52     static WebProcess& process = *new WebProcess;
53     return process;
54 }
55
56 WebProcess::WebProcess()
57     : m_inDidClose(false)
58 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
59     , m_compositingRenderServerPort(MACH_PORT_NULL)
60 #endif
61 {
62 #if USE(PLATFORM_STRATEGIES)
63     // Initialize our platform strategies.
64     WebPlatformStrategies::initialize();
65 #endif // USE(PLATFORM_STRATEGIES)
66 }
67
68 void WebProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop)
69 {
70     ASSERT(!m_connection);
71
72     m_connection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop);
73     m_connection->open();
74
75     m_runLoop = runLoop;
76 }
77
78 void WebProcess::loadInjectedBundle(const String& path)
79 {
80     ASSERT(m_pageMap.isEmpty());
81     ASSERT(!path.isEmpty());
82
83     m_injectedBundle = InjectedBundle::create(path);
84     if (!m_injectedBundle->load()) {
85         // Don't keep around the InjectedBundle reference if the load fails.
86         m_injectedBundle.clear();
87     }
88 }
89
90 void WebProcess::forwardMessageToInjectedBundle(const String& message)
91 {
92     if (!m_injectedBundle)
93         return;
94
95     m_injectedBundle->didRecieveMessage(message);
96 }
97
98 WebPage* WebProcess::webPage(uint64_t pageID) const
99 {
100     return m_pageMap.get(pageID).get();
101 }
102
103 WebPage* WebProcess::createWebPage(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, DrawingArea::Type drawingAreaType)
104 {
105     // It is necessary to check for page existence here since during a window.open() (or targeted
106     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
107     std::pair<HashMap<uint64_t, RefPtr<WebPage> >::iterator, bool> result = m_pageMap.add(pageID, 0);
108     if (result.second) {
109         ASSERT(!result.first->second);
110         result.first->second = WebPage::create(pageID, viewSize, store, drawingAreaType);
111     }
112
113     ASSERT(result.first->second);
114     return result.first->second.get();
115 }
116
117 void WebProcess::removeWebPage(uint64_t pageID)
118 {
119     m_pageMap.remove(pageID);
120
121     // If we don't have any pages left, shut down.
122     if (m_pageMap.isEmpty() && !m_inDidClose)
123         shutdown();
124 }
125
126 bool WebProcess::isSeparateProcess() const
127 {
128     // If we're running on the main run loop, we assume that we're in a separate process.
129     return m_runLoop == RunLoop::main();
130 }
131  
132 void WebProcess::shutdown()
133 {
134     // Keep running forever if we're running in the same process.
135     if (!isSeparateProcess())
136         return;
137
138 #ifndef NDEBUG
139     gcController().garbageCollectNow();
140     cache()->setDisabled(true);
141 #endif
142
143     // Invalidate our connection.
144     m_connection->invalidate();
145     m_connection = 0;
146
147     m_runLoop->stop();
148 }
149
150 void WebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
151 {
152     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
153         switch (messageID.get<WebProcessMessage::Kind>()) {
154             case WebProcessMessage::LoadInjectedBundle: {
155                 String path;
156                 if (!arguments->decode(CoreIPC::Out(path)))
157                     return;
158
159                 loadInjectedBundle(path);
160                 return;
161             }
162             case WebProcessMessage::Create: {
163                 uint64_t pageID = arguments->destinationID();
164                 IntSize viewSize;
165                 WebPreferencesStore store;
166                 uint32_t drawingAreaType;
167                 if (!arguments->decode(CoreIPC::Out(viewSize, store, drawingAreaType)))
168                     return;
169
170                 createWebPage(pageID, viewSize, store, static_cast<DrawingArea::Type>(drawingAreaType));
171                 return;
172             }
173             case WebProcessMessage::PostMessage: {
174                 String message;
175                 if (!arguments->decode(CoreIPC::Out(message)))
176                     return;
177
178                 forwardMessageToInjectedBundle(message);
179                 return;
180             }
181 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
182             case WebProcessMessage::SetupAcceleratedCompositingPort: {
183                 CoreIPC::MachPort port;
184                 if (!arguments->decode(port))
185                     return;
186
187                 m_compositingRenderServerPort = port.port();
188                 return;
189             }
190 #endif
191         }
192     }
193
194     uint64_t pageID = arguments->destinationID();
195     if (!pageID)
196         return;
197     
198     WebPage* page = webPage(pageID);
199     if (!page)
200         return;
201     
202     page->didReceiveMessage(connection, messageID, *arguments);    
203 }
204
205 void WebProcess::didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*)
206 {
207     // The web process should never ever get sync messages.
208     ASSERT_NOT_REACHED();
209 }
210
211 void WebProcess::didClose(CoreIPC::Connection*)
212 {
213     // When running in the same process the connection will never be closed.
214     ASSERT(isSeparateProcess());
215
216 #ifndef NDEBUG
217     m_inDidClose = true;
218
219     // Close all the live pages.
220     Vector<RefPtr<WebPage> > pages;
221     copyValuesToVector(m_pageMap, pages);
222     for (size_t i = 0; i < pages.size(); ++i)
223         pages[i]->close();
224     pages.clear();
225
226     gcController().garbageCollectNow();
227     cache()->setDisabled(true);
228 #endif    
229
230     // The UI process closed this connection, shut down.
231     m_runLoop->stop();
232 }
233
234 } // namespace WebKit