3d5566335a05abec01ecb8a24d043a96afeca7cb
[WebKit-https.git] / Source / WebCore / inspector / InspectorFrontendHost.cpp
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31
32 #if ENABLE(INSPECTOR)
33
34 #include "InspectorFrontendHost.h"
35
36 #include "ContextMenu.h"
37 #include "ContextMenuItem.h"
38 #include "ContextMenuController.h"
39 #include "ContextMenuProvider.h"
40 #include "DOMFileSystem.h"
41 #include "DOMWrapperWorld.h"
42 #include "Element.h"
43 #include "Frame.h"
44 #include "FrameLoader.h"
45 #include "HitTestResult.h"
46 #include "HTMLFrameOwnerElement.h"
47 #include "InspectorAgent.h"
48 #include "InspectorController.h"
49 #include "InspectorFrontendClient.h"
50 #include "Page.h"
51 #include "Pasteboard.h"
52 #include "ResourceError.h"
53 #include "ResourceRequest.h"
54 #include "ResourceResponse.h"
55 #include "ScriptFunctionCall.h"
56 #include "UserGestureIndicator.h"
57 #include <wtf/StdLibExtras.h>
58
59 using namespace std;
60
61 namespace WebCore {
62
63 #if ENABLE(CONTEXT_MENUS)
64 class FrontendMenuProvider : public ContextMenuProvider {
65 public:
66     static PassRefPtr<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
67     {
68         return adoptRef(new FrontendMenuProvider(frontendHost, frontendApiObject, items));
69     }
70     
71     void disconnect()
72     {
73         m_frontendApiObject = ScriptObject();
74         m_frontendHost = 0;
75     }
76     
77 private:
78     FrontendMenuProvider(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items)
79         : m_frontendHost(frontendHost)
80         , m_frontendApiObject(frontendApiObject)
81         , m_items(items)
82     {
83     }
84
85     virtual ~FrontendMenuProvider()
86     {
87         contextMenuCleared();
88     }
89     
90     virtual void populateContextMenu(ContextMenu* menu)
91     {
92         for (size_t i = 0; i < m_items.size(); ++i)
93             menu->appendItem(m_items[i]);
94     }
95     
96     virtual void contextMenuItemSelected(ContextMenuItem* item)
97     {
98         if (m_frontendHost) {
99             UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture);
100             int itemNumber = item->action() - ContextMenuItemBaseCustomTag;
101
102             ScriptFunctionCall function(m_frontendApiObject, "contextMenuItemSelected");
103             function.appendArgument(itemNumber);
104             function.call();
105         }
106     }
107     
108     virtual void contextMenuCleared()
109     {
110         if (m_frontendHost) {
111             ScriptFunctionCall function(m_frontendApiObject, "contextMenuCleared");
112             function.call();
113
114             m_frontendHost->m_menuProvider = 0;
115         }
116         m_items.clear();
117     }
118
119     InspectorFrontendHost* m_frontendHost;
120     ScriptObject m_frontendApiObject;
121     Vector<ContextMenuItem> m_items;
122 };
123 #endif
124
125 InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage)
126     : m_client(client)
127     , m_frontendPage(frontendPage)
128 #if ENABLE(CONTEXT_MENUS)
129     , m_menuProvider(0)
130 #endif
131 {
132 }
133
134 InspectorFrontendHost::~InspectorFrontendHost()
135 {
136     ASSERT(!m_client);
137 }
138
139 void InspectorFrontendHost::disconnectClient()
140 {
141     m_client = 0;
142 #if ENABLE(CONTEXT_MENUS)
143     if (m_menuProvider)
144         m_menuProvider->disconnect();
145 #endif
146     m_frontendPage = 0;
147 }
148
149 void InspectorFrontendHost::loaded()
150 {
151     if (m_client)
152         m_client->frontendLoaded();
153 }
154
155 void InspectorFrontendHost::requestSetDockSide(const String& side)
156 {
157     if (!m_client)
158         return;
159     if (side == "undocked")
160         m_client->requestSetDockSide(InspectorFrontendClient::UNDOCKED);
161     else if (side == "right")
162         m_client->requestSetDockSide(InspectorFrontendClient::DOCKED_TO_RIGHT);
163     else if (side == "bottom")
164         m_client->requestSetDockSide(InspectorFrontendClient::DOCKED_TO_BOTTOM);
165 }
166
167 void InspectorFrontendHost::closeWindow()
168 {
169     if (m_client) {
170         m_client->closeWindow();
171         disconnectClient(); // Disconnect from client.
172     }
173 }
174
175 void InspectorFrontendHost::bringToFront()
176 {
177     if (m_client)
178         m_client->bringToFront();
179 }
180
181 void InspectorFrontendHost::setZoomFactor(float zoom)
182 {
183     m_frontendPage->mainFrame()->setPageAndTextZoomFactors(zoom, 1);
184 }
185
186 void InspectorFrontendHost::inspectedURLChanged(const String& newURL)
187 {
188     if (m_client)
189         m_client->inspectedURLChanged(newURL);
190 }
191
192 void InspectorFrontendHost::setAttachedWindowHeight(unsigned height)
193 {
194     if (m_client)
195         m_client->changeAttachedWindowHeight(height);
196 }
197
198 void InspectorFrontendHost::setAttachedWindowWidth(unsigned width)
199 {
200     if (m_client)
201         m_client->changeAttachedWindowWidth(width);
202 }
203
204 void InspectorFrontendHost::setToolbarHeight(unsigned height)
205 {
206     if (m_client)
207         m_client->setToolbarHeight(height);
208 }
209
210 void InspectorFrontendHost::moveWindowBy(float x, float y) const
211 {
212     if (m_client)
213         m_client->moveWindowBy(x, y);
214 }
215
216 void InspectorFrontendHost::setInjectedScriptForOrigin(const String& origin, const String& script)
217 {
218     ASSERT(m_frontendPage->inspectorController());
219     m_frontendPage->inspectorController()->setInjectedScriptForOrigin(origin, script);
220 }
221
222 String InspectorFrontendHost::localizedStringsURL()
223 {
224     return m_client ? m_client->localizedStringsURL() : "";
225 }
226
227 void InspectorFrontendHost::copyText(const String& text)
228 {
229     Pasteboard::generalPasteboard()->writePlainText(text, Pasteboard::CannotSmartReplace);
230 }
231
232 void InspectorFrontendHost::openInNewTab(const String& url)
233 {
234     if (m_client)
235         m_client->openInNewTab(url);
236 }
237
238 bool InspectorFrontendHost::canSave()
239 {
240     if (m_client)
241         return m_client->canSave();
242     return false;
243 }
244
245 void InspectorFrontendHost::save(const String& url, const String& content, bool forceSaveAs)
246 {
247     if (m_client)
248         m_client->save(url, content, forceSaveAs);
249 }
250
251 void InspectorFrontendHost::append(const String& url, const String& content)
252 {
253     if (m_client)
254         m_client->append(url, content);
255 }
256
257 void InspectorFrontendHost::close(const String&)
258 {
259 }
260
261 void InspectorFrontendHost::sendMessageToBackend(const String& message)
262 {
263     if (m_client)
264         m_client->sendMessageToBackend(message);
265 }
266
267 #if ENABLE(CONTEXT_MENUS)
268 void InspectorFrontendHost::showContextMenu(Event* event, const Vector<ContextMenuItem>& items)
269 {
270     if (!event)
271         return;
272
273     ASSERT(m_frontendPage);
274     ScriptState* frontendScriptState = scriptStateFromPage(debuggerWorld(), m_frontendPage);
275     ScriptObject frontendApiObject;
276     if (!ScriptGlobalObject::get(frontendScriptState, "InspectorFrontendAPI", frontendApiObject)) {
277         ASSERT_NOT_REACHED();
278         return;
279     }
280     RefPtr<FrontendMenuProvider> menuProvider = FrontendMenuProvider::create(this, frontendApiObject, items);
281     ContextMenuController* menuController = m_frontendPage->contextMenuController();
282     menuController->showContextMenu(event, menuProvider);
283     m_menuProvider = menuProvider.get();
284 }
285 #endif
286
287 String InspectorFrontendHost::loadResourceSynchronously(const String& url)
288 {
289     ResourceRequest request(url);
290     request.setHTTPMethod("GET");
291
292     Vector<char> data;
293     ResourceError error;
294     ResourceResponse response;
295     m_frontendPage->mainFrame()->loader()->loadResourceSynchronously(request, DoNotAllowStoredCredentials, DoNotAskClientForCrossOriginCredentials, error, response, data);
296     return String::fromUTF8(data.data(), data.size());
297 }
298
299 bool InspectorFrontendHost::supportsFileSystems()
300 {
301     if (m_client)
302         return m_client->supportsFileSystems();
303     return false;
304 }
305
306 void InspectorFrontendHost::requestFileSystems()
307 {
308     if (m_client)
309         m_client->requestFileSystems();
310 }
311
312 void InspectorFrontendHost::addFileSystem()
313 {
314     if (m_client)
315         m_client->addFileSystem();
316 }
317
318 void InspectorFrontendHost::removeFileSystem(const String& fileSystemPath)
319 {
320     if (m_client)
321         m_client->removeFileSystem(fileSystemPath);
322 }
323
324 #if ENABLE(FILE_SYSTEM)
325 PassRefPtr<DOMFileSystem> InspectorFrontendHost::isolatedFileSystem(const String& fileSystemName, const String& rootURL)
326 {
327     ScriptExecutionContext* context = m_frontendPage->mainFrame()->document();
328     return DOMFileSystem::create(context, fileSystemName, FileSystemTypeIsolated, KURL(ParsedURLString, rootURL), AsyncFileSystem::create());
329 }
330 #endif
331
332 bool InspectorFrontendHost::isUnderTest()
333 {
334     return m_client && m_client->isUnderTest();
335 }
336
337 bool InspectorFrontendHost::canSaveAs()
338 {
339     return false;
340 }
341
342 bool InspectorFrontendHost::canInspectWorkers()
343 {
344     return false;
345 }
346
347 } // namespace WebCore
348
349 #endif // ENABLE(INSPECTOR)