Remove an unneeded argument from FrameLoaderClient::download
[WebKit-https.git] / Source / WebKit / qt / WebCoreSupport / InspectorClientQt.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2008 Holger Hans Peter Freyther
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer. 
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution. 
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission. 
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "InspectorClientQt.h"
33
34 #include "Frame.h"
35 #include "FrameView.h"
36 #include "InspectorController.h"
37 #include "InspectorFrontend.h"
38 #include "InspectorServerQt.h"
39 #include "NotImplemented.h"
40 #include "Page.h"
41 #include "PlatformString.h"
42 #include "ScriptDebugServer.h"
43 #include "qwebinspector.h"
44 #include "qwebinspector_p.h"
45 #include "qwebpage.h"
46 #include "qwebpage_p.h"
47 #include "qwebview.h"
48 #include <wtf/text/CString.h>
49 #include <QtCore/QCoreApplication>
50 #include <QtCore/QFile>
51 #include <QtCore/QSettings>
52 #include <QtCore/QVariant>
53
54 namespace WebCore {
55
56 static const QLatin1String settingStoragePrefix("Qt/QtWebKit/QWebInspector/");
57 static const QLatin1String settingStorageTypeSuffix(".type");
58
59 class InspectorClientWebPage : public QWebPage {
60     Q_OBJECT
61     friend class InspectorClientQt;
62 public:
63     InspectorClientWebPage(QObject* parent = 0)
64         : QWebPage(parent)
65     {
66         connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), SLOT(javaScriptWindowObjectCleared()));
67     }
68
69     QWebPage* createWindow(QWebPage::WebWindowType)
70     {
71         QWebView* view = new QWebView;
72         QWebPage* page = new QWebPage;
73         view->setPage(page);
74         view->setAttribute(Qt::WA_DeleteOnClose);
75         return page;
76     }
77
78 public slots:
79     void javaScriptWindowObjectCleared() 
80     {
81 #ifndef QT_NO_PROPERTIES
82         QVariant inspectorJavaScriptWindowObjects = property("_q_inspectorJavaScriptWindowObjects");
83         if (!inspectorJavaScriptWindowObjects.isValid())
84             return;
85         QMap<QString, QVariant> javaScriptNameObjectMap = inspectorJavaScriptWindowObjects.toMap();
86         QWebFrame* frame = mainFrame();
87         QMap<QString, QVariant>::const_iterator it = javaScriptNameObjectMap.constBegin();
88         for ( ; it != javaScriptNameObjectMap.constEnd(); ++it) {
89             QString name = it.key();
90             QVariant value = it.value();
91             QObject* obj = value.value<QObject*>();
92             frame->addToJavaScriptWindowObject(name, obj);
93         }
94 #endif
95     }
96 };
97
98 namespace {
99
100 #if ENABLE(INSPECTOR)
101 class InspectorFrontendSettingsQt : public InspectorFrontendClientLocal::Settings {
102 public:
103     virtual ~InspectorFrontendSettingsQt() { }
104     virtual String getProperty(const String& name)
105     {
106 #ifdef QT_NO_SETTINGS
107         Q_UNUSED(name)
108         Q_UNUSED(value)
109         qWarning("QWebInspector: QSettings is not supported by Qt.");
110         return String();
111 #else
112         QSettings qsettings;
113         if (qsettings.status() == QSettings::AccessError) {
114             // QCoreApplication::setOrganizationName and QCoreApplication::setApplicationName haven't been called
115             qWarning("QWebInspector: QSettings couldn't read configuration setting [%s].",
116                      qPrintable(static_cast<QString>(name)));
117             return String();
118         }
119
120         QString settingKey(settingStoragePrefix + QString(name));
121         QString storedValueType = qsettings.value(settingKey + settingStorageTypeSuffix).toString();
122         QVariant storedValue = qsettings.value(settingKey);
123         storedValue.convert(QVariant::nameToType(storedValueType.toAscii().data()));
124         return variantToSetting(storedValue);
125 #endif // QT_NO_SETTINGS
126     }
127
128     virtual void setProperty(const String& name, const String& value)
129     {
130 #ifdef QT_NO_SETTINGS
131         Q_UNUSED(name)
132         Q_UNUSED(value)
133         qWarning("QWebInspector: QSettings is not supported by Qt.");
134 #else
135         QSettings qsettings;
136         if (qsettings.status() == QSettings::AccessError) {
137             qWarning("QWebInspector: QSettings couldn't persist configuration setting [%s].",
138                      qPrintable(static_cast<QString>(name)));
139             return;
140         }
141
142         QVariant valueToStore = settingToVariant(value);
143         QString settingKey(settingStoragePrefix + QString(name));
144         qsettings.setValue(settingKey, valueToStore);
145         qsettings.setValue(settingKey + settingStorageTypeSuffix, QLatin1String(QVariant::typeToName(valueToStore.type())));
146 #endif // QT_NO_SETTINGS
147     }
148
149 private:
150     static String variantToSetting(const QVariant& qvariant)
151     {
152         String retVal;
153
154         switch (qvariant.type()) {
155         case QVariant::Bool:
156             retVal = qvariant.toBool() ? "true" : "false";
157             break;
158         case QVariant::String:
159             retVal = qvariant.toString();
160             break;
161         default:
162             break;
163         }
164
165         return retVal;
166     }
167
168     static QVariant settingToVariant(const String& setting)
169     {
170         QVariant retVal;
171         retVal.setValue(static_cast<QString>(setting));
172         return retVal;
173     }
174 };
175 #endif // ENABLE(INSPECTOR)
176
177 }
178
179 InspectorClientQt::InspectorClientQt(QWebPage* page)
180     : m_inspectedWebPage(page)
181     , m_frontendWebPage(0)
182     , m_frontendClient(0)
183     , m_remoteFrontEndChannel(0)
184 {
185     InspectorServerQt* webInspectorServer = InspectorServerQt::server();
186     if (webInspectorServer)
187         webInspectorServer->registerClient(this);
188 }
189
190 void InspectorClientQt::inspectorDestroyed()
191 {
192 #if ENABLE(INSPECTOR)
193     closeInspectorFrontend();
194
195     InspectorServerQt* webInspectorServer = InspectorServerQt::server();
196     if (webInspectorServer)
197         webInspectorServer->unregisterClient(this);
198
199     delete this;
200 #endif
201 }
202
203     
204 void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController* inspectorController)
205 {
206 #if ENABLE(INSPECTOR)
207     OwnPtr<QWebView> inspectorView = adoptPtr(new QWebView);
208     // FIXME: Where does inspectorPage get deleted?
209     InspectorClientWebPage* inspectorPage = new InspectorClientWebPage(inspectorView.get());
210     inspectorView->setPage(inspectorPage);
211
212     QWebInspector* inspector = m_inspectedWebPage->d->getOrCreateInspector();
213     // Remote frontend was attached.
214     if (m_remoteFrontEndChannel)
215         return;
216
217     // This is a known hook that allows changing the default URL for the
218     // Web inspector. This is used for SDK purposes. Please keep this hook
219     // around and don't remove it.
220     // https://bugs.webkit.org/show_bug.cgi?id=35340
221     QUrl inspectorUrl;
222 #ifndef QT_NO_PROPERTIES
223     inspectorUrl = inspector->property("_q_inspectorUrl").toUrl();
224 #endif
225     if (!inspectorUrl.isValid())
226         inspectorUrl = QUrl(QLatin1String("qrc:/webkit/inspector/inspector.html"));
227
228 #ifndef QT_NO_PROPERTIES
229     QVariant inspectorJavaScriptWindowObjects = inspector->property("_q_inspectorJavaScriptWindowObjects");
230     if (inspectorJavaScriptWindowObjects.isValid())
231         inspectorPage->setProperty("_q_inspectorJavaScriptWindowObjects", inspectorJavaScriptWindowObjects);
232 #endif
233     inspectorView->page()->mainFrame()->load(inspectorUrl);
234     m_inspectedWebPage->d->inspectorFrontend = inspectorView.get();
235     inspector->d->setFrontend(inspectorView.get());
236
237     // Is 'controller' the same object as 'inspectorController' (which appears to be unused)?
238     InspectorController* controller = inspectorView->page()->d->page->inspectorController();
239     OwnPtr<InspectorFrontendClientQt> frontendClient = adoptPtr(new InspectorFrontendClientQt(m_inspectedWebPage, inspectorView.release(), this));
240     m_frontendClient = frontendClient.get();
241     controller->setInspectorFrontendClient(frontendClient.release());
242     m_frontendWebPage = inspectorPage;
243 #endif
244 }
245
246 void InspectorClientQt::closeInspectorFrontend()
247 {
248 #if ENABLE(INSPECTOR)
249     if (m_frontendClient)
250         m_frontendClient->inspectorClientDestroyed();
251 #endif
252 }
253
254 void InspectorClientQt::bringFrontendToFront()
255 {
256 #if ENABLE(INSPECTOR)
257     m_frontendClient->bringToFront();
258 #endif
259 }
260
261 void InspectorClientQt::releaseFrontendPage()
262 {
263     m_frontendWebPage = 0;
264     m_frontendClient = 0;
265 }
266
267 void InspectorClientQt::attachAndReplaceRemoteFrontend(InspectorServerRequestHandlerQt* channel)
268 {
269 #if ENABLE(INSPECTOR)
270     m_remoteFrontEndChannel = channel;
271     m_inspectedWebPage->d->inspectorController()->connectFrontend();
272 #endif
273 }
274
275 void InspectorClientQt::detachRemoteFrontend()
276 {
277 #if ENABLE(INSPECTOR)
278     m_remoteFrontEndChannel = 0;
279     m_inspectedWebPage->d->inspectorController()->disconnectFrontend();
280 #endif
281 }
282
283 void InspectorClientQt::highlight()
284 {
285     hideHighlight();
286 }
287
288 void InspectorClientQt::hideHighlight()
289 {
290     WebCore::Frame* frame = m_inspectedWebPage->d->page->mainFrame();
291     if (frame) {
292         QRect rect = m_inspectedWebPage->mainFrame()->geometry();
293         if (!rect.isEmpty())
294             frame->view()->invalidateRect(rect);
295     }
296 }
297
298 bool InspectorClientQt::sendMessageToFrontend(const String& message)
299 {
300 #if ENABLE(INSPECTOR)
301     if (m_remoteFrontEndChannel) {
302         WTF::CString msg = message.utf8();
303         m_remoteFrontEndChannel->webSocketSend(msg.data(), msg.length());
304         return true;
305     }
306     if (!m_frontendWebPage)
307         return false;
308
309     Page* frontendPage = QWebPagePrivate::core(m_frontendWebPage);
310     return doDispatchMessageOnFrontendPage(frontendPage, message);
311 #else
312     return false;
313 #endif
314 }
315
316 #if ENABLE(INSPECTOR)
317 InspectorFrontendClientQt::InspectorFrontendClientQt(QWebPage* inspectedWebPage, PassOwnPtr<QWebView> inspectorView, InspectorClientQt* inspectorClient)
318     : InspectorFrontendClientLocal(inspectedWebPage->d->page->inspectorController(), inspectorView->page()->d->page, adoptPtr(new InspectorFrontendSettingsQt()))
319     , m_inspectedWebPage(inspectedWebPage)
320     , m_inspectorView(inspectorView)
321     , m_destroyingInspectorView(false)
322     , m_inspectorClient(inspectorClient)
323 {
324 }
325
326 InspectorFrontendClientQt::~InspectorFrontendClientQt()
327 {
328     ASSERT(m_destroyingInspectorView);
329     if (m_inspectorClient)
330         m_inspectorClient->releaseFrontendPage();
331 }
332
333 void InspectorFrontendClientQt::frontendLoaded()
334 {
335     InspectorFrontendClientLocal::frontendLoaded();
336     setAttachedWindow(true);
337 }
338
339 String InspectorFrontendClientQt::localizedStringsURL()
340 {
341     notImplemented();
342     return String();
343 }
344
345 String InspectorFrontendClientQt::hiddenPanels()
346 {
347     notImplemented();
348     return String();
349 }
350
351 void InspectorFrontendClientQt::bringToFront()
352 {
353     updateWindowTitle();
354 }
355
356 void InspectorFrontendClientQt::closeWindow()
357 {
358     destroyInspectorView(true);
359 }
360
361 void InspectorFrontendClientQt::attachWindow()
362 {
363     notImplemented();
364 }
365
366 void InspectorFrontendClientQt::detachWindow()
367 {
368     notImplemented();
369 }
370
371 void InspectorFrontendClientQt::setAttachedWindowHeight(unsigned)
372 {
373     notImplemented();
374 }
375
376 void InspectorFrontendClientQt::inspectedURLChanged(const String& newURL)
377 {
378     m_inspectedURL = newURL;
379     updateWindowTitle();
380 }
381
382 void InspectorFrontendClientQt::updateWindowTitle()
383 {
384     if (m_inspectedWebPage->d->inspector) {
385         QString caption = QCoreApplication::translate("QWebPage", "Web Inspector - %2").arg(m_inspectedURL);
386         m_inspectedWebPage->d->inspector->setWindowTitle(caption);
387     }
388 }
389
390 void InspectorFrontendClientQt::destroyInspectorView(bool notifyInspectorController)
391 {
392     if (m_destroyingInspectorView)
393         return;
394     m_destroyingInspectorView = true;
395
396     // Inspected page may have already been destroyed.
397     if (m_inspectedWebPage) {
398         // Clear reference from QWebInspector to the frontend view.
399         m_inspectedWebPage->d->getOrCreateInspector()->d->setFrontend(0);
400     }
401
402 #if ENABLE(INSPECTOR)
403     if (notifyInspectorController)
404         m_inspectedWebPage->d->inspectorController()->disconnectFrontend();
405 #endif
406     if (m_inspectorClient)
407         m_inspectorClient->releaseFrontendPage();
408
409     // Clear pointer before deleting WebView to avoid recursive calls to its destructor.
410     OwnPtr<QWebView> inspectorView = m_inspectorView.release();
411 }
412
413 void InspectorFrontendClientQt::inspectorClientDestroyed()
414 {
415     destroyInspectorView(false);
416     m_inspectorClient = 0;
417     m_inspectedWebPage = 0;
418 }
419 #endif
420 }
421
422 #include "InspectorClientQt.moc"