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
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
32 #include "InspectorClientQt.h"
35 #include "InspectorBackendDispatcher.h"
36 #include "InspectorController.h"
37 #include "InspectorFrontend.h"
38 #include "InspectorServerQt.h"
39 #include "NotImplemented.h"
41 #include "PlatformString.h"
42 #include "ScriptDebugServer.h"
43 #include "qwebinspector.h"
44 #include "qwebinspector_p.h"
46 #include "qwebpage_p.h"
48 #include <QtCore/QCoreApplication>
49 #include <QtCore/QFile>
50 #include <QtCore/QSettings>
51 #include <QtCore/QVariant>
55 static const QLatin1String settingStoragePrefix("Qt/QtWebKit/QWebInspector/");
56 static const QLatin1String settingStorageTypeSuffix(".type");
58 static String variantToSetting(const QVariant& qvariant);
59 static QVariant settingToVariant(const String& value);
61 class InspectorClientWebPage : public QWebPage {
63 friend class InspectorClientQt;
65 InspectorClientWebPage(QObject* parent = 0)
68 connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), SLOT(javaScriptWindowObjectCleared()));
71 QWebPage* createWindow(QWebPage::WebWindowType)
73 QWebView* view = new QWebView;
74 QWebPage* page = new QWebPage;
76 view->setAttribute(Qt::WA_DeleteOnClose);
81 void javaScriptWindowObjectCleared()
83 #ifndef QT_NO_PROPERTIES
84 QVariant inspectorJavaScriptWindowObjects = property("_q_inspectorJavaScriptWindowObjects");
85 if (!inspectorJavaScriptWindowObjects.isValid())
87 QMap<QString, QVariant> javaScriptNameObjectMap = inspectorJavaScriptWindowObjects.toMap();
88 QWebFrame* frame = mainFrame();
89 QMap<QString, QVariant>::const_iterator it = javaScriptNameObjectMap.constBegin();
90 for ( ; it != javaScriptNameObjectMap.constEnd(); ++it) {
91 QString name = it.key();
92 QVariant value = it.value();
93 QObject* obj = value.value<QObject*>();
94 frame->addToJavaScriptWindowObject(name, obj);
101 static void ensureDebuggerScriptLoaded()
103 static bool scriptLoaded = false;
107 QFile debuggerScriptFile(":/webkit/inspector/DebuggerScript.js");
108 if (debuggerScriptFile.open(QIODevice::ReadOnly)) {
109 QByteArray ba = debuggerScriptFile.readAll();
110 ScriptDebugServer::shared().setDebuggerScriptSource(String(ba.constData(), ba.length()));
116 InspectorClientQt::InspectorClientQt(QWebPage* page)
117 : m_inspectedWebPage(page)
118 , m_frontendWebPage(0)
119 , m_frontendClient(0)
121 InspectorServerQt* webInspectorServer = InspectorServerQt::server();
122 if (webInspectorServer)
123 webInspectorServer->registerClient(this);
126 void InspectorClientQt::inspectorDestroyed()
128 #if ENABLE(INSPECTOR)
129 if (m_frontendClient)
130 m_frontendClient->inspectorClientDestroyed();
132 InspectorServerQt* webInspectorServer = InspectorServerQt::server();
133 if (webInspectorServer)
134 webInspectorServer->unregisterClient(this);
141 void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController* inspectorController)
143 #if ENABLE(INSPECTOR)
145 ensureDebuggerScriptLoaded();
148 QWebView* inspectorView = new QWebView;
149 InspectorClientWebPage* inspectorPage = new InspectorClientWebPage(inspectorView);
150 inspectorView->setPage(inspectorPage);
152 QWebInspector* inspector = m_inspectedWebPage->d->getOrCreateInspector();
153 // Remote frontend was attached.
154 if (m_inspectedWebPage->d->inspector->d->remoteFrontend)
157 // This is a known hook that allows changing the default URL for the
158 // Web inspector. This is used for SDK purposes. Please keep this hook
159 // around and don't remove it.
160 // https://bugs.webkit.org/show_bug.cgi?id=35340
162 #ifndef QT_NO_PROPERTIES
163 inspectorUrl = inspector->property("_q_inspectorUrl").toUrl();
165 if (!inspectorUrl.isValid())
166 inspectorUrl = QUrl("qrc:/webkit/inspector/inspector.html");
168 #ifndef QT_NO_PROPERTIES
169 QVariant inspectorJavaScriptWindowObjects = inspector->property("_q_inspectorJavaScriptWindowObjects");
170 if (inspectorJavaScriptWindowObjects.isValid())
171 inspectorPage->setProperty("_q_inspectorJavaScriptWindowObjects", inspectorJavaScriptWindowObjects);
173 inspectorView->page()->mainFrame()->load(inspectorUrl);
174 m_inspectedWebPage->d->inspectorFrontend = inspectorView;
175 inspector->d->setFrontend(inspectorView);
177 m_frontendClient = new InspectorFrontendClientQt(m_inspectedWebPage, inspectorView, this);
178 inspectorView->page()->d->page->inspectorController()->setInspectorFrontendClient(m_frontendClient);
179 m_frontendWebPage = inspectorPage;
183 void InspectorClientQt::releaseFrontendPage()
185 m_frontendWebPage = 0;
186 m_frontendClient = 0;
189 void InspectorClientQt::attachAndReplaceRemoteFrontend(RemoteFrontendChannel* channel)
191 #if ENABLE(INSPECTOR)
192 // Channel was allocated by InspectorServerQt. Here we transfer ownership to inspector.
193 m_inspectedWebPage->d->inspector->d->attachAndReplaceRemoteFrontend(channel);
194 m_inspectedWebPage->d->inspectorController()->connectFrontend();
198 void InspectorClientQt::detachRemoteFrontend()
200 #if ENABLE(INSPECTOR)
201 m_inspectedWebPage->d->inspector->d->detachRemoteFrontend();
202 m_inspectedWebPage->d->inspectorController()->disconnectFrontend();
206 void InspectorClientQt::highlight(Node*)
211 void InspectorClientQt::hideHighlight()
216 void InspectorClientQt::populateSetting(const String& key, String* setting)
218 #ifdef QT_NO_SETTINGS
221 qWarning("QWebInspector: QSettings is not supported by Qt.");
224 if (qsettings.status() == QSettings::AccessError) {
225 // QCoreApplication::setOrganizationName and QCoreApplication::setApplicationName haven't been called
226 qWarning("QWebInspector: QSettings couldn't read configuration setting [%s].",
227 qPrintable(static_cast<QString>(key)));
231 QString settingKey(settingStoragePrefix + QString(key));
232 QString storedValueType = qsettings.value(settingKey + settingStorageTypeSuffix).toString();
233 QVariant storedValue = qsettings.value(settingKey);
234 storedValue.convert(QVariant::nameToType(storedValueType.toAscii().data()));
235 *setting = variantToSetting(storedValue);
236 #endif // QT_NO_SETTINGS
239 void InspectorClientQt::storeSetting(const String& key, const String& setting)
241 #ifdef QT_NO_SETTINGS
244 qWarning("QWebInspector: QSettings is not supported by Qt.");
247 if (qsettings.status() == QSettings::AccessError) {
248 qWarning("QWebInspector: QSettings couldn't persist configuration setting [%s].",
249 qPrintable(static_cast<QString>(key)));
253 QVariant valueToStore = settingToVariant(setting);
254 QString settingKey(settingStoragePrefix + QString(key));
255 qsettings.setValue(settingKey, valueToStore);
256 qsettings.setValue(settingKey + settingStorageTypeSuffix, QVariant::typeToName(valueToStore.type()));
257 #endif // QT_NO_SETTINGS
260 bool InspectorClientQt::sendMessageToFrontend(const String& message)
262 #if ENABLE(INSPECTOR)
263 if (m_inspectedWebPage->d->inspector->d->remoteFrontend) {
264 RemoteFrontendChannel* session = qobject_cast<RemoteFrontendChannel*>(m_inspectedWebPage->d->inspector->d->remoteFrontend);
266 session->sendMessageToFrontend(message);
269 if (!m_frontendWebPage)
272 Page* frontendPage = QWebPagePrivate::core(m_frontendWebPage);
273 return doDispatchMessageOnFrontendPage(frontendPage, message);
279 static String variantToSetting(const QVariant& qvariant)
283 switch (qvariant.type()) {
285 retVal = qvariant.toBool() ? "true" : "false";
286 case QVariant::String:
287 retVal = qvariant.toString();
295 static QVariant settingToVariant(const String& setting)
298 retVal.setValue(static_cast<QString>(setting));
302 #if ENABLE(INSPECTOR)
303 InspectorFrontendClientQt::InspectorFrontendClientQt(QWebPage* inspectedWebPage, PassOwnPtr<QWebView> inspectorView, InspectorClientQt* inspectorClient)
304 : InspectorFrontendClientLocal(inspectedWebPage->d->page->inspectorController(), inspectorView->page()->d->page)
305 , m_inspectedWebPage(inspectedWebPage)
306 , m_inspectorView(inspectorView)
307 , m_destroyingInspectorView(false)
308 , m_inspectorClient(inspectorClient)
312 InspectorFrontendClientQt::~InspectorFrontendClientQt()
314 ASSERT(m_destroyingInspectorView);
315 if (m_inspectorClient)
316 m_inspectorClient->releaseFrontendPage();
319 void InspectorFrontendClientQt::frontendLoaded()
321 InspectorFrontendClientLocal::frontendLoaded();
322 setAttachedWindow(true);
325 String InspectorFrontendClientQt::localizedStringsURL()
331 String InspectorFrontendClientQt::hiddenPanels()
337 void InspectorFrontendClientQt::bringToFront()
342 void InspectorFrontendClientQt::closeWindow()
344 destroyInspectorView(true);
347 void InspectorFrontendClientQt::disconnectFromBackend()
349 destroyInspectorView(false);
352 void InspectorFrontendClientQt::attachWindow()
357 void InspectorFrontendClientQt::detachWindow()
362 void InspectorFrontendClientQt::setAttachedWindowHeight(unsigned)
367 void InspectorFrontendClientQt::inspectedURLChanged(const String& newURL)
369 m_inspectedURL = newURL;
373 void InspectorFrontendClientQt::updateWindowTitle()
375 if (m_inspectedWebPage->d->inspector) {
376 QString caption = QCoreApplication::translate("QWebPage", "Web Inspector - %2").arg(m_inspectedURL);
377 m_inspectedWebPage->d->inspector->setWindowTitle(caption);
381 void InspectorFrontendClientQt::destroyInspectorView(bool notifyInspectorController)
383 if (m_destroyingInspectorView)
385 m_destroyingInspectorView = true;
387 // Inspected page may have already been destroyed.
388 if (m_inspectedWebPage) {
389 // Clear reference from QWebInspector to the frontend view.
390 m_inspectedWebPage->d->getOrCreateInspector()->d->setFrontend(0);
393 #if ENABLE(INSPECTOR)
394 if (notifyInspectorController)
395 m_inspectedWebPage->d->inspectorController()->disconnectFrontend();
397 if (m_inspectorClient)
398 m_inspectorClient->releaseFrontendPage();
400 // Clear pointer before deleting WebView to avoid recursive calls to its destructor.
401 OwnPtr<QWebView> inspectorView = m_inspectorView.release();
404 void InspectorFrontendClientQt::inspectorClientDestroyed()
406 m_inspectorClient = 0;
407 m_inspectedWebPage = 0;
412 #include "InspectorClientQt.moc"