cdad8f70517b7cc260847712acd8b0cb712a345e
[WebKit-https.git] / Source / WebKit / gtk / WebCoreSupport / InspectorClientGtk.cpp
1 /*
2  * Copyright (C) 2008, 2012 Gustavo Noronha Silva
3  * Copyright (C) 2010 Collabora Ltd.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "config.h"
21 #include "InspectorClientGtk.h"
22
23 #include "FileSystem.h"
24 #include "Frame.h"
25 #include "InspectorController.h"
26 #include "NotImplemented.h"
27 #include "Page.h"
28 #include "webkitversion.h"
29 #include "webkitwebinspector.h"
30 #include "webkitwebinspectorprivate.h"
31 #include "webkitwebview.h"
32 #include "webkitwebviewprivate.h"
33 #include <wtf/text/CString.h>
34 #include <wtf/text/WTFString.h>
35
36 using namespace WebCore;
37
38 namespace WebKit {
39
40 static void notifyWebViewDestroyed(WebKitWebView* webView, InspectorFrontendClient* inspectorFrontendClient)
41 {
42     inspectorFrontendClient->destroyInspectorWindow(true);
43 }
44
45 namespace {
46
47 class InspectorFrontendSettingsGtk : public InspectorFrontendClientLocal::Settings {
48 public:
49     virtual ~InspectorFrontendSettingsGtk() { }
50
51 private:
52     virtual String getProperty(const String& name)
53     {
54         notImplemented();
55         return String();
56     }
57
58     virtual void setProperty(const String& name, const String& value)
59     {
60         notImplemented();
61     }
62 };
63
64 } // namespace
65
66 InspectorClient::InspectorClient(WebKitWebView* webView)
67     : m_inspectedWebView(webView)
68     , m_frontendPage(0)
69     , m_frontendClient(0)
70 {}
71
72 InspectorClient::~InspectorClient()
73 {
74     if (m_frontendClient) {
75         m_frontendClient->disconnectInspectorClient();
76         m_frontendClient = 0;
77     }
78 }
79
80 void InspectorClient::inspectorDestroyed()
81 {
82     closeInspectorFrontend();
83     delete this;
84 }
85
86 InspectorFrontendChannel* InspectorClient::openInspectorFrontend(InspectorController* controller)
87 {
88     // This g_object_get will ref the inspector. We're not doing an
89     // unref if this method succeeds because the inspector object must
90     // be alive even after the inspected WebView is destroyed - the
91     // close-window and destroy signals still need to be
92     // emitted.
93     WebKitWebInspector* webInspector = 0;
94     g_object_get(m_inspectedWebView, "web-inspector", &webInspector, NULL);
95     ASSERT(webInspector);
96
97     WebKitWebView* inspectorWebView = 0;
98     g_signal_emit_by_name(webInspector, "inspect-web-view", m_inspectedWebView, &inspectorWebView);
99
100     if (!inspectorWebView) {
101         g_object_unref(webInspector);
102         return 0;
103     }
104
105     webkit_web_inspector_set_web_view(webInspector, inspectorWebView);
106  
107     webkit_web_view_load_uri(inspectorWebView, "resource:///org/webkitgtk/inspector/UserInterface/Main.html");
108
109     gtk_widget_show(GTK_WIDGET(inspectorWebView));
110
111     m_frontendPage = core(inspectorWebView);
112     auto frontendClient = std::make_unique<InspectorFrontendClient>(m_inspectedWebView, inspectorWebView, webInspector, m_frontendPage, this);
113     m_frontendClient = frontendClient.get();
114     m_frontendPage->inspectorController().setInspectorFrontendClient(std::move(frontendClient));
115
116     // The inspector must be in it's own PageGroup to avoid deadlock while debugging.
117     m_frontendPage->setGroupName("");
118     
119     return this;
120 }
121
122 void InspectorClient::closeInspectorFrontend()
123 {
124     if (m_frontendClient)
125         m_frontendClient->destroyInspectorWindow(false);
126 }
127
128 void InspectorClient::bringFrontendToFront()
129 {
130     m_frontendClient->bringToFront();
131 }
132
133 void InspectorClient::releaseFrontendPage()
134 {
135     m_frontendPage = 0;
136     m_frontendClient = 0;
137 }
138
139 void InspectorClient::highlight()
140 {
141     hideHighlight();
142 }
143
144 void InspectorClient::hideHighlight()
145 {
146     // FIXME: we should be able to only invalidate the actual rects of
147     // the new and old nodes. We need to track the nodes, and take the
148     // actual highlight size into account when calculating the damage
149     // rect.
150     gtk_widget_queue_draw(GTK_WIDGET(m_inspectedWebView));
151 }
152
153 bool InspectorClient::sendMessageToFrontend(const String& message)
154 {
155     return doDispatchMessageOnFrontendPage(m_frontendPage, message);
156 }
157
158 InspectorFrontendClient::InspectorFrontendClient(WebKitWebView* inspectedWebView, WebKitWebView* inspectorWebView, WebKitWebInspector* webInspector, Page* inspectorPage, InspectorClient* inspectorClient)
159     : InspectorFrontendClientLocal(&core(inspectedWebView)->inspectorController(), inspectorPage, adoptPtr(new InspectorFrontendSettingsGtk()))
160     , m_inspectorWebView(inspectorWebView)
161     , m_inspectedWebView(inspectedWebView)
162     , m_webInspector(webInspector)
163     , m_inspectorClient(inspectorClient)
164 {
165     g_signal_connect(m_inspectorWebView, "destroy",
166                      G_CALLBACK(notifyWebViewDestroyed), (gpointer)this);
167 }
168
169 InspectorFrontendClient::~InspectorFrontendClient()
170 {
171     if (m_inspectorClient) {
172         m_inspectorClient->releaseFrontendPage();
173         m_inspectorClient = 0;
174     }
175
176     ASSERT(!m_webInspector);
177 }
178
179 void InspectorFrontendClient::destroyInspectorWindow(bool notifyInspectorController)
180 {
181     if (!m_webInspector)
182         return;
183
184     GRefPtr<WebKitWebInspector> webInspector = adoptGRef(m_webInspector.leakRef());
185
186     if (m_inspectorWebView) {
187         g_signal_handlers_disconnect_by_func(m_inspectorWebView, reinterpret_cast<gpointer>(notifyWebViewDestroyed), this);
188         m_inspectorWebView = 0;
189     }
190
191     if (notifyInspectorController)
192         core(m_inspectedWebView)->inspectorController().disconnectFrontend();
193
194     if (m_inspectorClient)
195         m_inspectorClient->releaseFrontendPage();
196
197     gboolean handled = FALSE;
198     g_signal_emit_by_name(webInspector.get(), "close-window", &handled);
199     ASSERT(handled);
200
201     // Please do not use member variables here because InspectorFrontendClient object pointed by 'this'
202     // has been implicitly deleted by "close-window" function.
203 }
204
205 String InspectorFrontendClient::localizedStringsURL()
206 {
207     // FIXME: support l10n of localizedStrings.js
208     return String("resource:///org/webkitgtk/inspector/Localizations/en.lproj/localizedStrings.js");
209 }
210
211 void InspectorFrontendClient::bringToFront()
212 {
213     if (!m_inspectorWebView)
214         return;
215
216     gboolean handled = FALSE;
217     g_signal_emit_by_name(m_webInspector.get(), "show-window", &handled);
218 }
219
220 void InspectorFrontendClient::closeWindow()
221 {
222     destroyInspectorWindow(true);
223 }
224
225 void InspectorFrontendClient::attachWindow(DockSide)
226 {
227     if (!m_inspectorWebView)
228         return;
229
230     gboolean handled = FALSE;
231     g_signal_emit_by_name(m_webInspector.get(), "attach-window", &handled);
232 }
233
234 void InspectorFrontendClient::detachWindow()
235 {
236     if (!m_inspectorWebView)
237         return;
238
239     gboolean handled = FALSE;
240     g_signal_emit_by_name(m_webInspector.get(), "detach-window", &handled);
241 }
242
243 void InspectorFrontendClient::setAttachedWindowHeight(unsigned height)
244 {
245     notImplemented();
246 }
247
248 void InspectorFrontendClient::setAttachedWindowWidth(unsigned width)
249 {
250     notImplemented();
251 }
252
253 void InspectorFrontendClient::setToolbarHeight(unsigned height)
254 {
255     notImplemented();
256 }
257
258 void InspectorFrontendClient::inspectedURLChanged(const String& newURL)
259 {
260     if (!m_inspectorWebView)
261         return;
262
263     webkit_web_inspector_set_inspected_uri(m_webInspector.get(), newURL.utf8().data());
264 }
265
266 }
267