WebKit2 does not have application cache
[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 <WebCore/ApplicationCacheStorage.h>
40 #include <wtf/PassRefPtr.h>
41
42 #ifndef NDEBUG
43 #include <WebCore/Cache.h>
44 #include <WebCore/GCController.h>
45 #endif
46
47 using namespace WebCore;
48
49 namespace WebKit {
50
51 WebProcess& WebProcess::shared()
52 {
53     static WebProcess& process = *new WebProcess;
54     return process;
55 }
56
57 WebProcess::WebProcess()
58     : m_inDidClose(false)
59 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
60     , m_compositingRenderServerPort(MACH_PORT_NULL)
61 #endif
62 {
63 #if USE(PLATFORM_STRATEGIES)
64     // Initialize our platform strategies.
65     WebPlatformStrategies::initialize();
66 #endif // USE(PLATFORM_STRATEGIES)
67 }
68
69 void WebProcess::initialize(CoreIPC::Connection::Identifier serverIdentifier, RunLoop* runLoop)
70 {
71     ASSERT(!m_connection);
72
73     m_connection = CoreIPC::Connection::createClientConnection(serverIdentifier, this, runLoop);
74     m_connection->open();
75
76     m_runLoop = runLoop;
77 }
78
79 void WebProcess::loadInjectedBundle(const String& path)
80 {
81     ASSERT(m_pageMap.isEmpty());
82     ASSERT(!path.isEmpty());
83
84     m_injectedBundle = InjectedBundle::create(path);
85     if (!m_injectedBundle->load()) {
86         // Don't keep around the InjectedBundle reference if the load fails.
87         m_injectedBundle.clear();
88     }
89 }
90
91 void WebProcess::setApplicationCacheDirectory(const String& directory)
92 {
93     cacheStorage().setCacheDirectory(directory);
94 }
95
96 void WebProcess::forwardMessageToInjectedBundle(const String& message)
97 {
98     if (!m_injectedBundle)
99         return;
100
101     m_injectedBundle->didRecieveMessage(message);
102 }
103
104 WebPage* WebProcess::webPage(uint64_t pageID) const
105 {
106     return m_pageMap.get(pageID).get();
107 }
108
109 WebPage* WebProcess::createWebPage(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, DrawingArea::Type drawingAreaType)
110 {
111     // It is necessary to check for page existence here since during a window.open() (or targeted
112     // link) the WebPage gets created both in the synchronous handler and through the normal way. 
113     std::pair<HashMap<uint64_t, RefPtr<WebPage> >::iterator, bool> result = m_pageMap.add(pageID, 0);
114     if (result.second) {
115         ASSERT(!result.first->second);
116         result.first->second = WebPage::create(pageID, viewSize, store, drawingAreaType);
117     }
118
119     ASSERT(result.first->second);
120     return result.first->second.get();
121 }
122
123 void WebProcess::removeWebPage(uint64_t pageID)
124 {
125     m_pageMap.remove(pageID);
126
127     // If we don't have any pages left, shut down.
128     if (m_pageMap.isEmpty() && !m_inDidClose)
129         shutdown();
130 }
131
132 bool WebProcess::isSeparateProcess() const
133 {
134     // If we're running on the main run loop, we assume that we're in a separate process.
135     return m_runLoop == RunLoop::main();
136 }
137  
138 void WebProcess::shutdown()
139 {
140     // Keep running forever if we're running in the same process.
141     if (!isSeparateProcess())
142         return;
143
144 #ifndef NDEBUG
145     gcController().garbageCollectNow();
146     cache()->setDisabled(true);
147 #endif
148
149     // Invalidate our connection.
150     m_connection->invalidate();
151     m_connection = 0;
152
153     m_runLoop->stop();
154 }
155
156 void WebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
157 {
158     if (messageID.is<CoreIPC::MessageClassWebProcess>()) {
159         switch (messageID.get<WebProcessMessage::Kind>()) {
160             case WebProcessMessage::LoadInjectedBundle: {
161                 String path;
162                 if (!arguments->decode(CoreIPC::Out(path)))
163                     return;
164
165                 loadInjectedBundle(path);
166                 return;
167             }
168             case WebProcessMessage::SetApplicationCacheDirectory: {
169                 String directory;
170                 if (!arguments->decode(CoreIPC::Out(directory)))
171                     return;
172                 
173                 setApplicationCacheDirectory(directory);
174                 return;
175             }
176             case WebProcessMessage::Create: {
177                 uint64_t pageID = arguments->destinationID();
178                 IntSize viewSize;
179                 WebPreferencesStore store;
180                 uint32_t drawingAreaType;
181                 if (!arguments->decode(CoreIPC::Out(viewSize, store, drawingAreaType)))
182                     return;
183
184                 createWebPage(pageID, viewSize, store, static_cast<DrawingArea::Type>(drawingAreaType));
185                 return;
186             }
187             case WebProcessMessage::PostMessage: {
188                 String message;
189                 if (!arguments->decode(CoreIPC::Out(message)))
190                     return;
191
192                 forwardMessageToInjectedBundle(message);
193                 return;
194             }
195 #if USE(ACCELERATED_COMPOSITING) && PLATFORM(MAC)
196             case WebProcessMessage::SetupAcceleratedCompositingPort: {
197                 CoreIPC::MachPort port;
198                 if (!arguments->decode(port))
199                     return;
200
201                 m_compositingRenderServerPort = port.port();
202                 return;
203             }
204 #endif
205         }
206     }
207
208     uint64_t pageID = arguments->destinationID();
209     if (!pageID)
210         return;
211     
212     WebPage* page = webPage(pageID);
213     if (!page)
214         return;
215     
216     page->didReceiveMessage(connection, messageID, *arguments);    
217 }
218
219 void WebProcess::didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*)
220 {
221     // The web process should never ever get sync messages.
222     ASSERT_NOT_REACHED();
223 }
224
225 void WebProcess::didClose(CoreIPC::Connection*)
226 {
227     // When running in the same process the connection will never be closed.
228     ASSERT(isSeparateProcess());
229
230 #ifndef NDEBUG
231     m_inDidClose = true;
232
233     // Close all the live pages.
234     Vector<RefPtr<WebPage> > pages;
235     copyValuesToVector(m_pageMap, pages);
236     for (size_t i = 0; i < pages.size(); ++i)
237         pages[i]->close();
238     pages.clear();
239
240     gcController().garbageCollectNow();
241     cache()->setDisabled(true);
242 #endif    
243
244     // The UI process closed this connection, shut down.
245     m_runLoop->stop();
246 }
247
248 } // namespace WebKit