2011-03-29 Ilya Tikhonovsky <loislo@chromium.org>
[WebKit-https.git] / Source / WebCore / inspector / InspectorAgent.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 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 #include "InspectorAgent.h"
32
33 #if ENABLE(INSPECTOR)
34
35 #include "CachedResourceLoader.h"
36 #include "CookieJar.h"
37 #include "Document.h"
38 #include "DocumentLoader.h"
39 #include "Frame.h"
40 #include "FrameLoadRequest.h"
41 #include "GraphicsContext.h"
42 #include "InjectedScriptHost.h"
43 #include "InjectedScriptManager.h"
44 #include "InspectorBrowserDebuggerAgent.h"
45 #include "InspectorCSSAgent.h"
46 #include "InspectorClient.h"
47 #include "InspectorConsoleAgent.h"
48 #include "InspectorController.h"
49 #include "InspectorDOMAgent.h"
50 #include "InspectorDebuggerAgent.h"
51 #include "InspectorFrontend.h"
52 #include "InspectorInstrumentation.h"
53 #include "InspectorProfilerAgent.h"
54 #include "InspectorResourceAgent.h"
55 #include "InspectorRuntimeAgent.h"
56 #include "InspectorState.h"
57 #include "InspectorTimelineAgent.h"
58 #include "InspectorValues.h"
59 #include "InspectorWorkerResource.h"
60 #include "InstrumentingAgents.h"
61 #include "Page.h"
62 #include "ResourceRequest.h"
63 #include "ScriptFunctionCall.h"
64 #include "ScriptObject.h"
65 #include "ScriptState.h"
66 #include "Settings.h"
67 #include "UserGestureIndicator.h"
68 #include "WindowFeatures.h"
69 #include <wtf/CurrentTime.h>
70
71 #if ENABLE(DATABASE)
72 #include "InspectorDatabaseAgent.h"
73 #endif
74
75 #if ENABLE(DOM_STORAGE)
76 #include "InspectorDOMStorageAgent.h"
77 #endif
78
79 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
80 #include "InspectorApplicationCacheAgent.h"
81 #endif
82
83 using namespace std;
84
85 namespace WebCore {
86
87 namespace InspectorAgentState {
88 static const char timelineProfilerEnabled[] = "timelineProfilerEnabled";
89 static const char debuggerEnabled[] = "debuggerEnabled";
90 }
91
92 static const char scriptsPanelName[] = "scripts";
93 static const char consolePanelName[] = "console";
94 static const char profilesPanelName[] = "profiles";
95
96 InspectorAgent::InspectorAgent(Page* page, InspectorClient* client, InjectedScriptManager* injectedScriptManager)
97     : m_inspectedPage(page)
98     , m_client(client)
99     , m_frontend(0)
100     , m_instrumentingAgents(new InstrumentingAgents())
101     , m_injectedScriptManager(injectedScriptManager)
102     , m_state(new InspectorState(client))
103     , m_domAgent(InspectorDOMAgent::create(m_instrumentingAgents.get(), page, m_client, m_state.get(), injectedScriptManager))
104     , m_cssAgent(new InspectorCSSAgent(m_instrumentingAgents.get(), m_domAgent.get()))
105 #if ENABLE(DATABASE)
106     , m_databaseAgent(InspectorDatabaseAgent::create(m_instrumentingAgents.get()))
107 #endif
108 #if ENABLE(DOM_STORAGE)
109     , m_domStorageAgent(InspectorDOMStorageAgent::create(m_instrumentingAgents.get()))
110 #endif
111     , m_timelineAgent(InspectorTimelineAgent::create(m_instrumentingAgents.get(), m_state.get()))
112 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
113     , m_applicationCacheAgent(new InspectorApplicationCacheAgent(m_instrumentingAgents.get(), page))
114 #endif
115     , m_resourceAgent(InspectorResourceAgent::create(m_instrumentingAgents.get(), page, m_state.get()))
116     , m_consoleAgent(new InspectorConsoleAgent(m_instrumentingAgents.get(), this, m_state.get(), injectedScriptManager, m_domAgent.get()))
117 #if ENABLE(JAVASCRIPT_DEBUGGER)
118     , m_debuggerAgent(InspectorDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), page, injectedScriptManager))
119     , m_browserDebuggerAgent(InspectorBrowserDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent.get(), m_debuggerAgent.get(), this))
120     , m_profilerAgent(InspectorProfilerAgent::create(m_instrumentingAgents.get(), m_consoleAgent.get(), page, m_state.get()))
121 #endif
122     , m_canIssueEvaluateForTestInFrontend(false)
123 {
124     ASSERT_ARG(page, page);
125     ASSERT_ARG(client, client);
126     InspectorInstrumentation::bindInspectorAgent(m_inspectedPage, this);
127     m_instrumentingAgents->setInspectorAgent(this);
128
129     m_injectedScriptManager->injectedScriptHost()->init(this
130         , m_consoleAgent.get()
131 #if ENABLE(DATABASE)
132         , m_databaseAgent.get()
133 #endif
134 #if ENABLE(DOM_STORAGE)
135         , m_domStorageAgent.get()
136 #endif
137     );
138 }
139
140 InspectorAgent::~InspectorAgent()
141 {
142     m_instrumentingAgents->setInspectorAgent(0);
143
144     // These should have been cleared in inspectedPageDestroyed().
145     ASSERT(!m_client);
146     ASSERT(!m_inspectedPage);
147 }
148
149 void InspectorAgent::inspectedPageDestroyed()
150 {
151     if (m_frontend) {
152         m_frontend->inspector()->disconnectFromBackend();
153         disconnectFrontend();
154     }
155
156 #if ENABLE(JAVASCRIPT_DEBUGGER)
157     m_browserDebuggerAgent.clear();
158     m_debuggerAgent.clear();
159 #endif
160
161     ASSERT(m_inspectedPage);
162     InspectorInstrumentation::unbindInspectorAgent(m_inspectedPage);
163     m_inspectedPage = 0;
164
165     releaseFrontendLifetimeAgents();
166     m_injectedScriptManager->disconnect();
167
168     m_client->inspectorDestroyed();
169     m_client = 0;
170 }
171
172 void InspectorAgent::restoreInspectorStateFromCookie(const String& inspectorStateCookie)
173 {
174     m_state->loadFromCookie(inspectorStateCookie);
175
176     m_frontend->inspector()->frontendReused();
177     m_frontend->inspector()->inspectedURLChanged(inspectedURL().string());
178
179     m_domAgent->restore();
180     m_resourceAgent->restore();
181     m_timelineAgent->restore();
182
183 #if ENABLE(JAVASCRIPT_DEBUGGER)
184     m_debuggerAgent->restore();
185     m_profilerAgent->restore();
186 #endif
187 }
188
189 void InspectorAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
190 {
191     if (world != mainThreadNormalWorld())
192         return;
193
194     if (enabled()) {
195         if (m_frontend && frame == m_inspectedPage->mainFrame())
196             m_injectedScriptManager->discardInjectedScripts();
197
198         if (m_scriptsToEvaluateOnLoad.size()) {
199             ScriptState* scriptState = mainWorldScriptState(frame);
200             for (Vector<String>::iterator it = m_scriptsToEvaluateOnLoad.begin();
201                   it != m_scriptsToEvaluateOnLoad.end(); ++it) {
202                 m_injectedScriptManager->injectScript(*it, scriptState);
203             }
204         }
205     }
206
207     if (!m_inspectorExtensionAPI.isEmpty())
208         m_injectedScriptManager->injectScript(m_inspectorExtensionAPI, mainWorldScriptState(frame));
209 }
210
211 void InspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
212 {
213     // We can reconnect to existing front-end -> unmute state.
214     m_state->unmute();
215
216     m_frontend = inspectorFrontend;
217     createFrontendLifetimeAgents();
218
219 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
220     m_applicationCacheAgent->setFrontend(m_frontend);
221 #endif
222     m_domAgent->setFrontend(m_frontend);
223     m_consoleAgent->setFrontend(m_frontend);
224     m_timelineAgent->setFrontend(m_frontend);
225     m_resourceAgent->setFrontend(m_frontend);
226 #if ENABLE(JAVASCRIPT_DEBUGGER)
227     m_debuggerAgent->setFrontend(m_frontend);
228     m_profilerAgent->setFrontend(m_frontend);
229 #endif
230 #if ENABLE(DATABASE)
231     m_databaseAgent->setFrontend(m_frontend);
232 #endif
233 #if ENABLE(DOM_STORAGE)
234     m_domStorageAgent->setFrontend(m_frontend);
235 #endif
236     // Initialize Web Inspector title.
237     m_frontend->inspector()->inspectedURLChanged(inspectedURL().string());
238
239     if (!m_showPanelAfterVisible.isEmpty()) {
240         m_frontend->inspector()->showPanel(m_showPanelAfterVisible);
241         m_showPanelAfterVisible = String();
242     }
243 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
244     WorkersMap::iterator workersEnd = m_workers.end();
245     for (WorkersMap::iterator it = m_workers.begin(); it != workersEnd; ++it) {
246         InspectorWorkerResource* worker = it->second.get();
247         m_frontend->inspector()->didCreateWorker(worker->id(), worker->url(), worker->isSharedWorker());
248     }
249 #endif
250     // Dispatch pending frontend commands
251     issueEvaluateForTestCommands();
252 }
253
254 void InspectorAgent::disconnectFrontend()
255 {
256     if (!m_frontend)
257         return;
258
259     m_canIssueEvaluateForTestInFrontend = false;
260     m_pendingEvaluateTestCommands.clear();
261
262     // Destroying agents would change the state, but we don't want that.
263     // Pre-disconnect state will be used to restore inspector agents.
264     m_state->mute();
265
266     m_frontend = 0;
267
268 #if ENABLE(JAVASCRIPT_DEBUGGER)
269     m_debuggerAgent->clearFrontend();
270     m_browserDebuggerAgent->clearFrontend();
271     m_profilerAgent->clearFrontend();
272 #endif
273
274 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
275     m_applicationCacheAgent->clearFrontend();
276 #endif
277
278     m_consoleAgent->clearFrontend();
279     m_domAgent->clearFrontend();
280     m_timelineAgent->clearFrontend();
281     m_resourceAgent->clearFrontend();
282 #if ENABLE(DATABASE)
283     m_databaseAgent->clearFrontend();
284 #endif
285 #if ENABLE(DOM_STORAGE)
286     m_domStorageAgent->clearFrontend();
287 #endif
288
289     releaseFrontendLifetimeAgents();
290     m_userAgentOverride = "";
291 }
292
293 void InspectorAgent::createFrontendLifetimeAgents()
294 {
295     m_runtimeAgent = InspectorRuntimeAgent::create(m_injectedScriptManager, m_inspectedPage);
296 }
297
298 void InspectorAgent::releaseFrontendLifetimeAgents()
299 {
300     m_runtimeAgent.clear();
301 }
302
303 void InspectorAgent::didCommitLoad(DocumentLoader* loader)
304 {
305     if (m_frontend) {
306         m_frontend->inspector()->inspectedURLChanged(loader->url().string());
307         m_frontend->inspector()->reset();
308     }
309     m_injectedScriptManager->discardInjectedScripts();
310 #if ENABLE(WORKERS)
311     m_workers.clear();
312 #endif
313 }
314
315 void InspectorAgent::domContentLoadedEventFired(DocumentLoader* loader, const KURL& url)
316 {
317     if (!enabled() || !isMainResourceLoader(loader, url))
318         return;
319
320     m_injectedScriptManager->injectedScriptHost()->clearInspectedNodes();
321     if (InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent())
322         domAgent->mainFrameDOMContentLoaded();
323     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
324         timelineAgent->didMarkDOMContentEvent();
325     if (m_frontend)
326         m_frontend->inspector()->domContentEventFired(currentTime());
327 }
328
329 void InspectorAgent::loadEventFired(DocumentLoader* loader, const KURL& url)
330 {
331     if (!enabled())
332         return;
333
334     if (InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent())
335         domAgent->loadEventFired(loader->frame()->document());
336
337     if (!isMainResourceLoader(loader, url))
338         return;
339
340     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
341         timelineAgent->didMarkLoadEvent();
342     if (m_frontend)
343         m_frontend->inspector()->loadEventFired(currentTime());
344 }
345
346 bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
347 {
348     return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
349 }
350
351 void InspectorAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
352 {
353     m_userAgentOverride = userAgent;
354 }
355
356 void InspectorAgent::applyUserAgentOverride(String* userAgent) const
357 {
358     if (!m_userAgentOverride.isEmpty())
359         *userAgent = m_userAgentOverride;
360 }
361
362 #if ENABLE(WORKERS)
363 class PostWorkerNotificationToFrontendTask : public ScriptExecutionContext::Task {
364 public:
365     static PassOwnPtr<PostWorkerNotificationToFrontendTask> create(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
366     {
367         return new PostWorkerNotificationToFrontendTask(worker, action);
368     }
369
370 private:
371     PostWorkerNotificationToFrontendTask(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
372         : m_worker(worker)
373         , m_action(action)
374     {
375     }
376
377     virtual void performTask(ScriptExecutionContext* scriptContext)
378     {
379         if (scriptContext->isDocument()) {
380             if (InspectorAgent* inspectorAgent = static_cast<Document*>(scriptContext)->page()->inspectorController()->m_inspectorAgent.get())
381                 inspectorAgent->postWorkerNotificationToFrontend(*m_worker, m_action);
382         }
383     }
384
385 private:
386     RefPtr<InspectorWorkerResource> m_worker;
387     InspectorAgent::WorkerAction m_action;
388 };
389
390 void InspectorAgent::postWorkerNotificationToFrontend(const InspectorWorkerResource& worker, InspectorAgent::WorkerAction action)
391 {
392     if (!m_frontend)
393         return;
394 #if ENABLE(JAVASCRIPT_DEBUGGER)
395     switch (action) {
396     case InspectorAgent::WorkerCreated:
397         m_frontend->inspector()->didCreateWorker(worker.id(), worker.url(), worker.isSharedWorker());
398         break;
399     case InspectorAgent::WorkerDestroyed:
400         m_frontend->inspector()->didDestroyWorker(worker.id());
401         break;
402     }
403 #endif
404 }
405
406 void InspectorAgent::didCreateWorker(intptr_t id, const String& url, bool isSharedWorker)
407 {
408     if (!enabled())
409         return;
410
411     RefPtr<InspectorWorkerResource> workerResource(InspectorWorkerResource::create(id, url, isSharedWorker));
412     m_workers.set(id, workerResource);
413     if (m_inspectedPage && m_frontend)
414         m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource, InspectorAgent::WorkerCreated));
415 }
416
417 void InspectorAgent::didDestroyWorker(intptr_t id)
418 {
419     if (!enabled())
420         return;
421
422     WorkersMap::iterator workerResource = m_workers.find(id);
423     if (workerResource == m_workers.end())
424         return;
425     if (m_inspectedPage && m_frontend)
426         m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource->second, InspectorAgent::WorkerDestroyed));
427     m_workers.remove(workerResource);
428 }
429 #endif // ENABLE(WORKERS)
430
431 void InspectorAgent::getCookies(ErrorString*, RefPtr<InspectorArray>* cookies, WTF::String* cookiesString)
432 {
433     // If we can get raw cookies.
434     ListHashSet<Cookie> rawCookiesList;
435
436     // If we can't get raw cookies - fall back to String representation
437     String stringCookiesList;
438
439     // Return value to getRawCookies should be the same for every call because
440     // the return value is platform/network backend specific, and the call will
441     // always return the same true/false value.
442     bool rawCookiesImplemented = false;
443
444     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
445         Document* document = frame->document();
446         const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources();
447         CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
448         for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
449             Vector<Cookie> docCookiesList;
450             rawCookiesImplemented = getRawCookies(document, KURL(ParsedURLString, it->second->url()), docCookiesList);
451
452             if (!rawCookiesImplemented) {
453                 // FIXME: We need duplication checking for the String representation of cookies.
454                 ExceptionCode ec = 0;
455                 stringCookiesList += document->cookie(ec);
456                 // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here
457                 // because "document" is the document of the main frame of the page.
458                 ASSERT(!ec);
459             } else {
460                 int cookiesSize = docCookiesList.size();
461                 for (int i = 0; i < cookiesSize; i++) {
462                     if (!rawCookiesList.contains(docCookiesList[i]))
463                         rawCookiesList.add(docCookiesList[i]);
464                 }
465             }
466         }
467     }
468
469     if (rawCookiesImplemented)
470         *cookies = buildArrayForCookies(rawCookiesList);
471     else
472         *cookiesString = stringCookiesList;
473 }
474
475 PassRefPtr<InspectorArray> InspectorAgent::buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
476 {
477     RefPtr<InspectorArray> cookies = InspectorArray::create();
478
479     ListHashSet<Cookie>::iterator end = cookiesList.end();
480     ListHashSet<Cookie>::iterator it = cookiesList.begin();
481     for (int i = 0; it != end; ++it, i++)
482         cookies->pushObject(buildObjectForCookie(*it));
483
484     return cookies;
485 }
486
487 PassRefPtr<InspectorObject> InspectorAgent::buildObjectForCookie(const Cookie& cookie)
488 {
489     RefPtr<InspectorObject> value = InspectorObject::create();
490     value->setString("name", cookie.name);
491     value->setString("value", cookie.value);
492     value->setString("domain", cookie.domain);
493     value->setString("path", cookie.path);
494     value->setNumber("expires", cookie.expires);
495     value->setNumber("size", (cookie.name.length() + cookie.value.length()));
496     value->setBoolean("httpOnly", cookie.httpOnly);
497     value->setBoolean("secure", cookie.secure);
498     value->setBoolean("session", cookie.session);
499     return value;
500 }
501
502 void InspectorAgent::deleteCookie(ErrorString*, const String& cookieName, const String& domain)
503 {
504     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
505         Document* document = frame->document();
506         if (document->url().host() != domain)
507             continue;
508         const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources();
509         CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
510         for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it)
511             WebCore::deleteCookie(document, KURL(ParsedURLString, it->second->url()), cookieName);
512     }
513 }
514
515 #if ENABLE(JAVASCRIPT_DEBUGGER)
516 void InspectorAgent::showProfilesPanel()
517 {
518     showPanel(profilesPanelName);
519 }
520 #endif
521
522 void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
523 {
524     m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
525     if (m_canIssueEvaluateForTestInFrontend)
526         issueEvaluateForTestCommands();
527 }
528
529 void InspectorAgent::didEvaluateForTestInFrontend(ErrorString*, long callId, const String& jsonResult)
530 {
531     ScriptState* scriptState = scriptStateFromPage(debuggerWorld(), m_inspectedPage);
532     ScriptObject window;
533     ScriptGlobalObject::get(scriptState, "window", window);
534     ScriptFunctionCall function(window, "didEvaluateForTestInFrontend");
535     function.appendArgument(callId);
536     function.appendArgument(jsonResult);
537     function.call();
538 }
539
540 void InspectorAgent::openInInspectedWindow(ErrorString*, const String& url)
541 {
542     Frame* mainFrame = m_inspectedPage->mainFrame();
543
544     FrameLoadRequest request(mainFrame->document()->securityOrigin(), ResourceRequest(), "_blank");
545
546     bool created;
547     WindowFeatures windowFeatures;
548     Frame* newFrame = WebCore::createWindow(mainFrame, mainFrame, request, windowFeatures, created);
549     if (!newFrame)
550         return;
551
552     UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
553     newFrame->loader()->setOpener(mainFrame);
554     newFrame->page()->setOpenedByDOM();
555     newFrame->loader()->changeLocation(mainFrame->document()->securityOrigin(), newFrame->loader()->completeURL(url), "", false, false);
556 }
557
558 void InspectorAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source)
559 {
560     m_scriptsToEvaluateOnLoad.append(source);
561 }
562
563 void InspectorAgent::removeAllScriptsToEvaluateOnLoad(ErrorString*)
564 {
565     m_scriptsToEvaluateOnLoad.clear();
566 }
567
568 void InspectorAgent::setInspectorExtensionAPI(const String& source)
569 {
570     m_inspectorExtensionAPI = source;
571 }
572
573 KURL InspectorAgent::inspectedURL() const
574 {
575     return m_inspectedPage->mainFrame()->document()->url();
576 }
577
578 KURL InspectorAgent::inspectedURLWithoutFragment() const
579 {
580     KURL url = inspectedURL();
581     url.removeFragmentIdentifier();
582     return url;
583 }
584
585 void InspectorAgent::reloadPage(ErrorString*, bool ignoreCache)
586 {
587     m_inspectedPage->mainFrame()->loader()->reload(ignoreCache);
588 }
589
590 bool InspectorAgent::enabled() const
591 {
592     if (!m_inspectedPage)
593         return false;
594     return m_inspectedPage->settings()->developerExtrasEnabled();
595 }
596
597 void InspectorAgent::showConsole()
598 {
599     showPanel(consolePanelName);
600 }
601
602 void InspectorAgent::showPanel(const String& panel)
603 {
604     if (!m_frontend) {
605         m_showPanelAfterVisible = panel;
606         return;
607     }
608     m_frontend->inspector()->showPanel(panel);
609 }
610
611 void InspectorAgent::issueEvaluateForTestCommands()
612 {
613     if (m_frontend) {
614         Vector<pair<long, String> > copy = m_pendingEvaluateTestCommands;
615         m_pendingEvaluateTestCommands.clear();
616         for (Vector<pair<long, String> >::iterator it = copy.begin(); m_frontend && it != copy.end(); ++it)
617             m_frontend->inspector()->evaluateForTestInFrontend((*it).first, (*it).second);
618         m_canIssueEvaluateForTestInFrontend = true;
619     }
620 }
621
622 } // namespace WebCore
623
624 #endif // ENABLE(INSPECTOR)