2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
28 #include "WebInspectorProxy.h"
32 #include "WebFramePolicyListenerProxy.h"
33 #include "WebFrameProxy.h"
34 #include "WebInspectorMessages.h"
35 #include "WebPageCreationParameters.h"
36 #include "WebPageGroup.h"
37 #include "WebPageProxy.h"
38 #include "WebPreferences.h"
39 #include "WebProcessProxy.h"
40 #include "WebURLRequest.h"
42 #if ENABLE(INSPECTOR_SERVER)
43 #include "WebInspectorServer.h"
49 using namespace WebCore;
53 static PassRefPtr<WebPageGroup> createInspectorPageGroup()
55 RefPtr<WebPageGroup> pageGroup = WebPageGroup::create("__WebInspectorPageGroup__", false, false);
58 // Allow developers to inspect the Web Inspector in debug builds.
59 pageGroup->preferences()->setDeveloperExtrasEnabled(true);
62 pageGroup->preferences()->setApplicationChromeModeEnabled(true);
63 pageGroup->preferences()->setSuppressesIncrementalRendering(true);
65 return pageGroup.release();
68 WebPageGroup* WebInspectorProxy::inspectorPageGroup()
70 static WebPageGroup* pageGroup = createInspectorPageGroup().leakRef();
74 WebInspectorProxy::WebInspectorProxy(WebPageProxy* page)
78 , m_isDebuggingJavaScript(false)
79 , m_isProfilingJavaScript(false)
80 , m_isProfilingPage(false)
82 , m_inspectorWindow(0)
83 #elif PLATFORM(GTK) || PLATFORM(EFL)
85 , m_inspectorWindow(0)
87 #if ENABLE(INSPECTOR_SERVER)
88 , m_remoteInspectionPageId(0)
93 WebInspectorProxy::~WebInspectorProxy()
97 void WebInspectorProxy::invalidate()
99 #if ENABLE(INSPECTOR_SERVER)
100 if (m_remoteInspectionPageId)
101 WebInspectorServer::shared().unregisterPage(m_remoteInspectionPageId);
110 m_isDebuggingJavaScript = false;
111 m_isProfilingJavaScript = false;
112 m_isProfilingPage = false;
116 bool WebInspectorProxy::isFront()
121 return platformIsFront();
124 void WebInspectorProxy::show()
129 m_page->process()->send(Messages::WebInspector::Show(), m_page->pageID());
132 void WebInspectorProxy::close()
137 m_page->process()->send(Messages::WebInspector::Close(), m_page->pageID());
140 void WebInspectorProxy::showConsole()
145 m_page->process()->send(Messages::WebInspector::ShowConsole(), m_page->pageID());
148 void WebInspectorProxy::showResources()
153 m_page->process()->send(Messages::WebInspector::ShowResources(), m_page->pageID());
156 void WebInspectorProxy::showMainResourceForFrame(WebFrameProxy* frame)
161 m_page->process()->send(Messages::WebInspector::ShowMainResourceForFrame(frame->frameID()), m_page->pageID());
164 void WebInspectorProxy::attach()
172 inspectorPageGroup()->preferences()->setInspectorStartsAttached(true);
177 void WebInspectorProxy::detach()
179 m_isAttached = false;
182 inspectorPageGroup()->preferences()->setInspectorStartsAttached(false);
187 void WebInspectorProxy::setAttachedWindowHeight(unsigned height)
189 inspectorPageGroup()->preferences()->setInspectorAttachedHeight(height);
190 platformSetAttachedWindowHeight(height);
193 void WebInspectorProxy::toggleJavaScriptDebugging()
198 if (m_isDebuggingJavaScript)
199 m_page->process()->send(Messages::WebInspector::StopJavaScriptDebugging(), m_page->pageID());
201 m_page->process()->send(Messages::WebInspector::StartJavaScriptDebugging(), m_page->pageID());
203 // FIXME: have the WebProcess notify us on state changes.
204 m_isDebuggingJavaScript = !m_isDebuggingJavaScript;
207 void WebInspectorProxy::toggleJavaScriptProfiling()
212 if (m_isProfilingJavaScript)
213 m_page->process()->send(Messages::WebInspector::StopJavaScriptProfiling(), m_page->pageID());
215 m_page->process()->send(Messages::WebInspector::StartJavaScriptProfiling(), m_page->pageID());
217 // FIXME: have the WebProcess notify us on state changes.
218 m_isProfilingJavaScript = !m_isProfilingJavaScript;
221 void WebInspectorProxy::togglePageProfiling()
226 if (m_isProfilingPage)
227 m_page->process()->send(Messages::WebInspector::StopPageProfiling(), m_page->pageID());
229 m_page->process()->send(Messages::WebInspector::StartPageProfiling(), m_page->pageID());
231 // FIXME: have the WebProcess notify us on state changes.
232 m_isProfilingPage = !m_isProfilingPage;
235 bool WebInspectorProxy::isInspectorPage(WebPageProxy* page)
237 return page->pageGroup() == inspectorPageGroup();
240 static void decidePolicyForNavigationAction(WKPageRef, WKFrameRef frameRef, WKFrameNavigationType, WKEventModifiers, WKEventMouseButton, WKURLRequestRef requestRef, WKFramePolicyListenerRef listenerRef, WKTypeRef, const void* clientInfo)
242 // Allow non-main frames to navigate anywhere.
243 if (!toImpl(frameRef)->isMainFrame()) {
244 toImpl(listenerRef)->use();
248 const WebInspectorProxy* webInspectorProxy = static_cast<const WebInspectorProxy*>(clientInfo);
249 ASSERT(webInspectorProxy);
251 // Use KURL so we can compare just the fileSystemPaths.
252 KURL inspectorURL(KURL(), webInspectorProxy->inspectorPageURL());
253 KURL requestURL(KURL(), toImpl(requestRef)->url());
255 ASSERT(inspectorURL.isLocalFile());
257 // Allow loading of the main inspector file.
258 if (requestURL.isLocalFile() && requestURL.fileSystemPath() == inspectorURL.fileSystemPath()) {
259 toImpl(listenerRef)->use();
263 // Prevent everything else from loading in the inspector's page.
264 toImpl(listenerRef)->ignore();
266 // And instead load it in the inspected page.
267 webInspectorProxy->page()->loadURLRequest(toImpl(requestRef));
270 #if ENABLE(INSPECTOR_SERVER)
271 void WebInspectorProxy::enableRemoteInspection()
273 if (!m_remoteInspectionPageId)
274 m_remoteInspectionPageId = WebInspectorServer::shared().registerPage(this);
277 void WebInspectorProxy::remoteFrontendConnected()
279 m_page->process()->send(Messages::WebInspector::RemoteFrontendConnected(), m_page->pageID());
282 void WebInspectorProxy::remoteFrontendDisconnected()
284 m_page->process()->send(Messages::WebInspector::RemoteFrontendDisconnected(), m_page->pageID());
287 void WebInspectorProxy::dispatchMessageFromRemoteFrontend(const String& message)
289 m_page->process()->send(Messages::WebInspector::DispatchMessageFromRemoteFrontend(message), m_page->pageID());
293 // Called by WebInspectorProxy messages
294 void WebInspectorProxy::createInspectorPage(uint64_t& inspectorPageID, WebPageCreationParameters& inspectorPageParameters)
301 m_isAttached = shouldOpenAttached();
303 WebPageProxy* inspectorPage = platformCreateInspectorPage();
304 ASSERT(inspectorPage);
308 inspectorPageID = inspectorPage->pageID();
309 inspectorPageParameters = inspectorPage->creationParameters();
311 WKPagePolicyClient policyClient = {
312 kWKPagePolicyClientCurrentVersion,
313 this, /* clientInfo */
314 decidePolicyForNavigationAction,
315 0, /* decidePolicyForNewWindowAction */
316 0, /* decidePolicyForResponse */
317 0 /* unableToImplementPolicy */
320 inspectorPage->initializePolicyClient(&policyClient);
322 String url = inspectorPageURL();
324 url += "?docked=true";
326 m_page->process()->assumeReadAccessToBaseURL(inspectorBaseURL());
328 inspectorPage->loadURL(url);
331 void WebInspectorProxy::didLoadInspectorPage()
335 // platformOpen is responsible for rendering attached mode depending on m_isAttached.
339 void WebInspectorProxy::didClose()
342 m_isDebuggingJavaScript = false;
343 m_isProfilingJavaScript = false;
344 m_isProfilingPage = false;
347 // Detach here so we only need to have one code path that is responsible for cleaning up the inspector
355 void WebInspectorProxy::bringToFront()
357 platformBringToFront();
360 void WebInspectorProxy::inspectedURLChanged(const String& urlString)
362 platformInspectedURLChanged(urlString);
365 bool WebInspectorProxy::canAttach()
367 // Keep this in sync with InspectorFrontendClientLocal::canAttachWindow. There are two implementations
368 // to make life easier in the multi-process world we have. WebInspectorProxy uses canAttach to decide if
369 // we can attach on open (on the UI process side). And InspectorFrontendClientLocal::canAttachWindow is
370 // used to decide if we can attach when the attach button is pressed (on the WebProcess side).
372 // Don't allow the attach if the window would be too small to accommodate the minimum inspector height.
373 // Also don't allow attaching to another inspector -- two inspectors in one window is too much!
374 bool isInspectorPage = m_page->pageGroup() == inspectorPageGroup();
375 unsigned inspectedPageHeight = platformInspectedWindowHeight();
376 unsigned maximumAttachedHeight = inspectedPageHeight * 3 / 4;
377 return minimumAttachedHeight <= maximumAttachedHeight && !isInspectorPage;
380 bool WebInspectorProxy::shouldOpenAttached()
382 return inspectorPageGroup()->preferences()->inspectorStartsAttached() && canAttach();
385 #if ENABLE(INSPECTOR_SERVER)
386 void WebInspectorProxy::sendMessageToRemoteFrontend(const String& message)
388 ASSERT(m_remoteInspectionPageId);
389 WebInspectorServer::shared().sendMessageOverConnection(m_remoteInspectionPageId, message);
393 } // namespace WebKit
395 #endif // ENABLE(INSPECTOR)