1/*
2 * Copyright (C) 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 "config.h"
27#include "WebInspector.h"
28
29#if ENABLE(INSPECTOR)
30#include "WebFrame.h"
31#include "WebInspectorFrontendClient.h"
32#include "WebInspectorProxyMessages.h"
33#include "WebPage.h"
34#include "WebPageCreationParameters.h"
35#include "WebProcess.h"
36#include <WebCore/Frame.h>
37#include <WebCore/InspectorController.h>
38#include <WebCore/InspectorFrontendChannel.h>
39#include <WebCore/InspectorFrontendClient.h>
40#include <WebCore/Page.h>
41#include <WebCore/ScriptController.h>
42#include <WebCore/ScriptValue.h>
43#include <wtf/text/StringConcatenate.h>
44
45using namespace WebCore;
46
47namespace WebKit {
48
49PassRefPtr<WebInspector> WebInspector::create(WebPage* page, InspectorFrontendChannel* frontendChannel)
50{
51    return adoptRef(new WebInspector(page, frontendChannel));
52}
53
54WebInspector::WebInspector(WebPage* page, InspectorFrontendChannel* frontendChannel)
55    : m_page(page)
56    , m_inspectorPage(0)
57    , m_frontendClient(0)
58    , m_frontendChannel(frontendChannel)
59#if PLATFORM(MAC)
60    , m_hasLocalizedStringsURL(false)
61    , m_usesWebKitUserInterface(false)
62#endif
63#if ENABLE(INSPECTOR_SERVER)
64    , m_remoteFrontendConnected(false)
65#endif
66{
67}
68
69// Called from WebInspectorClient
70WebPage* WebInspector::createInspectorPage()
71{
72    if (!m_page)
73        return 0;
74
75    ASSERT(!m_inspectorPage);
76    ASSERT(!m_frontendClient);
77
78    uint64_t inspectorPageID = 0;
79    WebPageCreationParameters parameters;
80
81    if (!WebProcess::shared().parentProcessConnection()->sendSync(Messages::WebInspectorProxy::CreateInspectorPage(),
82            Messages::WebInspectorProxy::CreateInspectorPage::Reply(inspectorPageID, parameters),
83            m_page->pageID(), CoreIPC::Connection::NoTimeout)) {
84        return 0;
85    }
86
87    if (!inspectorPageID)
88        return 0;
89
90    WebProcess::shared().createWebPage(inspectorPageID, parameters);
91    m_inspectorPage = WebProcess::shared().webPage(inspectorPageID);
92    ASSERT(m_inspectorPage);
93
94    OwnPtr<WebInspectorFrontendClient> frontendClient = adoptPtr(new WebInspectorFrontendClient(m_page, m_inspectorPage));
95    m_frontendClient = frontendClient.get();
96    m_inspectorPage->corePage()->inspectorController()->setInspectorFrontendClient(frontendClient.release());
97    return m_inspectorPage;
98}
99
100void WebInspector::destroyInspectorPage()
101{
102    m_inspectorPage = 0;
103    m_frontendClient = 0;
104    m_frontendChannel = 0;
105}
106
107// Called from WebInspectorFrontendClient
108void WebInspector::didClose()
109{
110    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_page->pageID());
111    destroyInspectorPage();
112}
113
114void WebInspector::bringToFront()
115{
116    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_page->pageID());
117}
118
119void WebInspector::inspectedURLChanged(const String& urlString)
120{
121    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::InspectedURLChanged(urlString), m_page->pageID());
122}
123
124void WebInspector::save(const String& filename, const String& content, bool forceSaveAs)
125{
126    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::Save(filename, content, forceSaveAs), m_page->pageID());
127}
128
129void WebInspector::append(const String& filename, const String& content)
130{
131    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::Append(filename, content), m_page->pageID());
132}
133
134void WebInspector::attachBottom()
135{
136    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachBottom(), m_page->pageID());
137}
138
139void WebInspector::attachRight()
140{
141    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachRight(), m_page->pageID());
142}
143
144void WebInspector::detach()
145{
146    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::Detach(), m_page->pageID());
147}
148
149void WebInspector::setAttachedWindowHeight(unsigned height)
150{
151    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::SetAttachedWindowHeight(height), m_page->pageID());
152}
153
154void WebInspector::setAttachedWindowWidth(unsigned width)
155{
156    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::SetAttachedWindowWidth(width), m_page->pageID());
157}
158
159void WebInspector::setToolbarHeight(unsigned height)
160{
161    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::SetToolbarHeight(height), m_page->pageID());
162}
163
164// Called by WebInspector messages
165void WebInspector::show()
166{
167    m_page->corePage()->inspectorController()->show();
168}
169
170void WebInspector::close()
171{
172    m_page->corePage()->inspectorController()->close();
173}
174
175void WebInspector::didSave(const String& url)
176{
177    ASSERT(m_inspectorPage);
178    m_inspectorPage->corePage()->mainFrame()->script()->executeScript(makeString("InspectorFrontendAPI.savedURL(\"", url, "\")"));
179}
180
181void WebInspector::didAppend(const String& url)
182{
183    ASSERT(m_inspectorPage);
184    m_inspectorPage->corePage()->mainFrame()->script()->executeScript(makeString("InspectorFrontendAPI.appendedToURL(\"", url, "\")"));
185}
186
187void WebInspector::attachedBottom()
188{
189    if (m_frontendClient)
190        m_frontendClient->setAttachedWindow(InspectorFrontendClient::DOCKED_TO_BOTTOM);
191}
192
193void WebInspector::attachedRight()
194{
195    if (m_frontendClient)
196        m_frontendClient->setAttachedWindow(InspectorFrontendClient::DOCKED_TO_RIGHT);
197}
198
199void WebInspector::detached()
200{
201    if (m_frontendClient)
202        m_frontendClient->setAttachedWindow(InspectorFrontendClient::UNDOCKED);
203}
204
205void WebInspector::evaluateScriptForTest(long callID, const String& script)
206{
207    m_page->corePage()->inspectorController()->evaluateForTestInFrontend(callID, script);
208}
209
210void WebInspector::showConsole()
211{
212    m_page->corePage()->inspectorController()->show();
213    if (m_frontendClient)
214        m_frontendClient->showConsole();
215}
216
217void WebInspector::showResources()
218{
219    m_page->corePage()->inspectorController()->show();
220    if (m_frontendClient)
221        m_frontendClient->showResources();
222}
223
224void WebInspector::showMainResourceForFrame(uint64_t frameID)
225{
226    WebFrame* frame = WebProcess::shared().webFrame(frameID);
227    if (!frame)
228        return;
229
230    m_page->corePage()->inspectorController()->show();
231    if (m_frontendClient)
232        m_frontendClient->showMainResourceForFrame(frame->coreFrame());
233}
234
235void WebInspector::startJavaScriptDebugging()
236{
237#if ENABLE(JAVASCRIPT_DEBUGGER)
238    m_page->corePage()->inspectorController()->show();
239    if (m_frontendClient)
240        m_frontendClient->setDebuggingEnabled(true);
241#endif
242}
243
244void WebInspector::stopJavaScriptDebugging()
245{
246#if ENABLE(JAVASCRIPT_DEBUGGER)
247    m_page->corePage()->inspectorController()->show();
248    if (m_frontendClient)
249        m_frontendClient->setDebuggingEnabled(false);
250#endif
251}
252
253void WebInspector::setJavaScriptProfilingEnabled(bool enabled)
254{
255#if ENABLE(JAVASCRIPT_DEBUGGER)
256    m_page->corePage()->inspectorController()->show();
257    if (!m_frontendClient)
258        return;
259
260    m_page->corePage()->inspectorController()->setProfilerEnabled(enabled);
261#endif
262}
263
264void WebInspector::startJavaScriptProfiling()
265{
266#if ENABLE(JAVASCRIPT_DEBUGGER)
267    m_page->corePage()->inspectorController()->show();
268    if (m_frontendClient)
269        m_frontendClient->startProfilingJavaScript();
270#endif
271}
272
273void WebInspector::stopJavaScriptProfiling()
274{
275#if ENABLE(JAVASCRIPT_DEBUGGER)
276    m_page->corePage()->inspectorController()->show();
277    if (m_frontendClient)
278        m_frontendClient->stopProfilingJavaScript();
279#endif
280}
281
282void WebInspector::startPageProfiling()
283{
284    m_page->corePage()->inspectorController()->show();
285    if (m_frontendClient)
286        m_frontendClient->setTimelineProfilingEnabled(true);
287}
288
289void WebInspector::stopPageProfiling()
290{
291    m_page->corePage()->inspectorController()->show();
292    if (m_frontendClient)
293        m_frontendClient->setTimelineProfilingEnabled(false);
294}
295
296void WebInspector::updateDockingAvailability()
297{
298    if (!m_frontendClient)
299        return;
300
301    bool canAttachWindow = m_frontendClient->canAttachWindow();
302    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachAvailabilityChanged(canAttachWindow), m_page->pageID());
303    m_frontendClient->setDockingUnavailable(!canAttachWindow);
304}
305
306#if ENABLE(INSPECTOR_SERVER)
307void WebInspector::sendMessageToRemoteFrontend(const String& message)
308{
309    ASSERT(m_remoteFrontendConnected);
310    WebProcess::shared().parentProcessConnection()->send(Messages::WebInspectorProxy::SendMessageToRemoteFrontend(message), m_page->pageID());
311}
312
313void WebInspector::dispatchMessageFromRemoteFrontend(const String& message)
314{
315    m_page->corePage()->inspectorController()->dispatchMessageFromFrontend(message);
316}
317
318void WebInspector::remoteFrontendConnected()
319{
320    ASSERT(!m_remoteFrontendConnected);
321    // Switching between in-process and remote inspectors isn't supported yet.
322    ASSERT(!m_inspectorPage);
323
324    m_page->corePage()->inspectorController()->connectFrontend(m_frontendChannel);
325    m_remoteFrontendConnected = true;
326}
327
328void WebInspector::remoteFrontendDisconnected()
329{
330    ASSERT(m_remoteFrontendConnected);
331    m_page->corePage()->inspectorController()->disconnectFrontend();
332    m_remoteFrontendConnected = false;
333}
334#endif
335
336} // namespace WebKit
337
338#endif // ENABLE(INSPECTOR)
339