2 * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
4 * Copyright (C) 2011 Google Inc. All rights reserved.
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 "InspectorAgent.h"
37 #include "DocumentLoader.h"
39 #include "GraphicsContext.h"
40 #include "InjectedScriptHost.h"
41 #include "InjectedScriptManager.h"
42 #include "InspectorController.h"
43 #include "InspectorFrontend.h"
44 #include "InspectorInstrumentation.h"
45 #include "InspectorValues.h"
46 #include "InspectorWorkerResource.h"
47 #include "InstrumentingAgents.h"
49 #include "ResourceRequest.h"
50 #include "ScriptFunctionCall.h"
51 #include "ScriptObject.h"
53 #include <wtf/PassRefPtr.h>
54 #include <wtf/RefPtr.h>
60 static const char scriptsPanelName[] = "scripts";
61 static const char consolePanelName[] = "console";
62 static const char profilesPanelName[] = "profiles";
64 InspectorAgent::InspectorAgent(Page* page, InjectedScriptManager* injectedScriptManager, InstrumentingAgents* instrumentingAgents)
65 : m_inspectedPage(page)
67 , m_instrumentingAgents(instrumentingAgents)
68 , m_injectedScriptManager(injectedScriptManager)
69 , m_canIssueEvaluateForTestInFrontend(false)
70 , m_didCommitLoadFired(false)
72 ASSERT_ARG(page, page);
73 m_instrumentingAgents->setInspectorAgent(this);
76 InspectorAgent::~InspectorAgent()
78 m_instrumentingAgents->setInspectorAgent(0);
80 // These should have been cleared in inspectedPageDestroyed().
81 ASSERT(!m_inspectedPage);
84 void InspectorAgent::inspectedPageDestroyed()
87 m_frontend->inspector()->disconnectFromBackend();
88 ASSERT(m_inspectedPage);
92 void InspectorAgent::restore()
94 if (m_didCommitLoadFired)
95 m_frontend->inspector()->frontendReused();
98 void InspectorAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
100 if (world != mainThreadNormalWorld())
103 if (!m_inspectorExtensionAPI.isEmpty())
104 m_injectedScriptManager->injectScript(m_inspectorExtensionAPI, mainWorldScriptState(frame));
107 void InspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
109 m_frontend = inspectorFrontend;
111 if (!m_showPanelAfterVisible.isEmpty()) {
112 m_frontend->inspector()->showPanel(m_showPanelAfterVisible);
113 m_showPanelAfterVisible = String();
115 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
116 WorkersMap::iterator workersEnd = m_workers.end();
117 for (WorkersMap::iterator it = m_workers.begin(); it != workersEnd; ++it) {
118 InspectorWorkerResource* worker = it->second.get();
119 m_frontend->inspector()->didCreateWorker(worker->id(), worker->url(), worker->isSharedWorker());
123 // Dispatch pending frontend commands
124 issueEvaluateForTestCommands();
127 void InspectorAgent::clearFrontend()
129 m_canIssueEvaluateForTestInFrontend = false;
130 m_pendingEvaluateTestCommands.clear();
132 m_didCommitLoadFired = false;
135 void InspectorAgent::didCommitLoad()
137 m_didCommitLoadFired = true;
139 m_frontend->inspector()->reset();
141 m_injectedScriptManager->discardInjectedScripts();
147 void InspectorAgent::domContentLoadedEventFired()
149 m_injectedScriptManager->injectedScriptHost()->clearInspectedNodes();
152 bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
154 return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
158 class PostWorkerNotificationToFrontendTask : public ScriptExecutionContext::Task {
160 static PassOwnPtr<PostWorkerNotificationToFrontendTask> create(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
162 return adoptPtr(new PostWorkerNotificationToFrontendTask(worker, action));
166 PostWorkerNotificationToFrontendTask(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
172 virtual void performTask(ScriptExecutionContext* scriptContext)
174 if (scriptContext->isDocument()) {
175 if (InspectorAgent* inspectorAgent = static_cast<Document*>(scriptContext)->page()->inspectorController()->m_inspectorAgent.get())
176 inspectorAgent->postWorkerNotificationToFrontend(*m_worker, m_action);
181 RefPtr<InspectorWorkerResource> m_worker;
182 InspectorAgent::WorkerAction m_action;
185 void InspectorAgent::postWorkerNotificationToFrontend(const InspectorWorkerResource& worker, InspectorAgent::WorkerAction action)
189 #if ENABLE(JAVASCRIPT_DEBUGGER)
191 case InspectorAgent::WorkerCreated:
192 m_frontend->inspector()->didCreateWorker(worker.id(), worker.url(), worker.isSharedWorker());
194 case InspectorAgent::WorkerDestroyed:
195 m_frontend->inspector()->didDestroyWorker(worker.id());
201 void InspectorAgent::didCreateWorker(intptr_t id, const String& url, bool isSharedWorker)
206 RefPtr<InspectorWorkerResource> workerResource(InspectorWorkerResource::create(id, url, isSharedWorker));
207 m_workers.set(id, workerResource);
208 if (m_inspectedPage && m_frontend)
209 m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource, InspectorAgent::WorkerCreated));
212 void InspectorAgent::didDestroyWorker(intptr_t id)
217 WorkersMap::iterator workerResource = m_workers.find(id);
218 if (workerResource == m_workers.end())
220 if (m_inspectedPage && m_frontend)
221 m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource->second, InspectorAgent::WorkerDestroyed));
222 m_workers.remove(workerResource);
224 #endif // ENABLE(WORKERS)
226 #if ENABLE(JAVASCRIPT_DEBUGGER)
227 void InspectorAgent::showProfilesPanel()
229 showPanel(profilesPanelName);
233 void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
235 m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
236 if (m_canIssueEvaluateForTestInFrontend)
237 issueEvaluateForTestCommands();
240 void InspectorAgent::setInspectorExtensionAPI(const String& source)
242 m_inspectorExtensionAPI = source;
245 KURL InspectorAgent::inspectedURL() const
247 return m_inspectedPage->mainFrame()->document()->url();
250 KURL InspectorAgent::inspectedURLWithoutFragment() const
252 KURL url = inspectedURL();
253 url.removeFragmentIdentifier();
257 bool InspectorAgent::enabled() const
259 if (!m_inspectedPage)
261 return m_inspectedPage->settings()->developerExtrasEnabled();
264 void InspectorAgent::showConsole()
266 showPanel(consolePanelName);
269 void InspectorAgent::showPanel(const String& panel)
272 m_showPanelAfterVisible = panel;
275 m_frontend->inspector()->showPanel(panel);
278 void InspectorAgent::issueEvaluateForTestCommands()
281 Vector<pair<long, String> > copy = m_pendingEvaluateTestCommands;
282 m_pendingEvaluateTestCommands.clear();
283 for (Vector<pair<long, String> >::iterator it = copy.begin(); m_frontend && it != copy.end(); ++it)
284 m_frontend->inspector()->evaluateForTestInFrontend((*it).first, (*it).second);
285 m_canIssueEvaluateForTestInFrontend = true;
289 } // namespace WebCore
291 #endif // ENABLE(INSPECTOR)