caaae3d38746552a300a13876471df4949da8153
[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_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::inspect(Node* node)
190 {
191     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
192         node = node->parentNode();
193     m_nodeToFocus = node;
194
195     if (!m_frontend)
196         return;
197
198     focusNode();
199 }
200
201 void InspectorAgent::focusNode()
202 {
203     if (!enabled())
204         return;
205
206     ASSERT(m_frontend);
207     ASSERT(m_nodeToFocus);
208
209     RefPtr<Node> node = m_nodeToFocus.get();
210     m_nodeToFocus = 0;
211
212     Document* document = node->ownerDocument();
213     if (!document)
214         return;
215     Frame* frame = document->frame();
216     if (!frame)
217         return;
218
219     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
220     if (injectedScript.hasNoValue())
221         return;
222
223     injectedScript.inspectNode(node.get());
224 }
225
226 void InspectorAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
227 {
228     if (world != mainThreadNormalWorld())
229         return;
230
231     if (enabled()) {
232         if (m_frontend && frame == m_inspectedPage->mainFrame())
233             m_injectedScriptManager->discardInjectedScripts();
234
235         if (m_scriptsToEvaluateOnLoad.size()) {
236             ScriptState* scriptState = mainWorldScriptState(frame);
237             for (Vector<String>::iterator it = m_scriptsToEvaluateOnLoad.begin();
238                   it != m_scriptsToEvaluateOnLoad.end(); ++it) {
239                 m_injectedScriptManager->injectScript(*it, scriptState);
240             }
241         }
242     }
243
244     if (!m_inspectorExtensionAPI.isEmpty())
245         m_injectedScriptManager->injectScript(m_inspectorExtensionAPI, mainWorldScriptState(frame));
246 }
247
248 void InspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
249 {
250     // We can reconnect to existing front-end -> unmute state.
251     m_state->unmute();
252
253     m_frontend = inspectorFrontend;
254     createFrontendLifetimeAgents();
255
256 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
257     m_applicationCacheAgent->setFrontend(m_frontend);
258 #endif
259     m_domAgent->setFrontend(m_frontend);
260     m_consoleAgent->setFrontend(m_frontend);
261     m_timelineAgent->setFrontend(m_frontend);
262     m_resourceAgent->setFrontend(m_frontend);
263 #if ENABLE(JAVASCRIPT_DEBUGGER)
264     m_debuggerAgent->setFrontend(m_frontend);
265     m_profilerAgent->setFrontend(m_frontend);
266 #endif
267 #if ENABLE(DATABASE)
268     m_databaseAgent->setFrontend(m_frontend);
269 #endif
270 #if ENABLE(DOM_STORAGE)
271     m_domStorageAgent->setFrontend(m_frontend);
272 #endif
273     // Initialize Web Inspector title.
274     m_frontend->inspector()->inspectedURLChanged(inspectedURL().string());
275
276     if (!m_showPanelAfterVisible.isEmpty()) {
277         m_frontend->inspector()->showPanel(m_showPanelAfterVisible);
278         m_showPanelAfterVisible = String();
279     }
280     if (m_nodeToFocus)
281         focusNode();
282 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
283     WorkersMap::iterator workersEnd = m_workers.end();
284     for (WorkersMap::iterator it = m_workers.begin(); it != workersEnd; ++it) {
285         InspectorWorkerResource* worker = it->second.get();
286         m_frontend->inspector()->didCreateWorker(worker->id(), worker->url(), worker->isSharedWorker());
287     }
288 #endif
289     // Dispatch pending frontend commands
290     issueEvaluateForTestCommands();
291 }
292
293 void InspectorAgent::disconnectFrontend()
294 {
295     if (!m_frontend)
296         return;
297
298     m_canIssueEvaluateForTestInFrontend = false;
299     m_pendingEvaluateTestCommands.clear();
300
301     // Destroying agents would change the state, but we don't want that.
302     // Pre-disconnect state will be used to restore inspector agents.
303     m_state->mute();
304
305     m_frontend = 0;
306
307 #if ENABLE(JAVASCRIPT_DEBUGGER)
308     m_debuggerAgent->clearFrontend();
309     m_browserDebuggerAgent->clearFrontend();
310     m_profilerAgent->clearFrontend();
311 #endif
312
313 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
314     m_applicationCacheAgent->clearFrontend();
315 #endif
316
317     m_consoleAgent->clearFrontend();
318     m_domAgent->clearFrontend();
319     m_timelineAgent->clearFrontend();
320     m_resourceAgent->clearFrontend();
321 #if ENABLE(DATABASE)
322     m_databaseAgent->clearFrontend();
323 #endif
324 #if ENABLE(DOM_STORAGE)
325     m_domStorageAgent->clearFrontend();
326 #endif
327
328     releaseFrontendLifetimeAgents();
329     m_userAgentOverride = "";
330 }
331
332 void InspectorAgent::createFrontendLifetimeAgents()
333 {
334     m_runtimeAgent = InspectorRuntimeAgent::create(m_injectedScriptManager, m_inspectedPage);
335 }
336
337 void InspectorAgent::releaseFrontendLifetimeAgents()
338 {
339     m_runtimeAgent.clear();
340 }
341
342 void InspectorAgent::didCommitLoad(DocumentLoader* loader)
343 {
344     if (m_frontend) {
345         m_frontend->inspector()->inspectedURLChanged(loader->url().string());
346         m_frontend->inspector()->reset();
347     }
348     m_injectedScriptManager->discardInjectedScripts();
349 #if ENABLE(WORKERS)
350     m_workers.clear();
351 #endif
352 }
353
354 void InspectorAgent::domContentLoadedEventFired(DocumentLoader* loader, const KURL& url)
355 {
356     if (!enabled() || !isMainResourceLoader(loader, url))
357         return;
358
359     m_injectedScriptManager->injectedScriptHost()->clearInspectedNodes();
360     if (InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent())
361         domAgent->mainFrameDOMContentLoaded();
362     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
363         timelineAgent->didMarkDOMContentEvent();
364     if (m_frontend)
365         m_frontend->inspector()->domContentEventFired(currentTime());
366 }
367
368 void InspectorAgent::loadEventFired(DocumentLoader* loader, const KURL& url)
369 {
370     if (!enabled())
371         return;
372
373     if (InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent())
374         domAgent->loadEventFired(loader->frame()->document());
375
376     if (!isMainResourceLoader(loader, url))
377         return;
378
379     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
380         timelineAgent->didMarkLoadEvent();
381     if (m_frontend)
382         m_frontend->inspector()->loadEventFired(currentTime());
383 }
384
385 bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
386 {
387     return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
388 }
389
390 void InspectorAgent::setUserAgentOverride(ErrorString*, const String& userAgent)
391 {
392     m_userAgentOverride = userAgent;
393 }
394
395 void InspectorAgent::applyUserAgentOverride(String* userAgent) const
396 {
397     if (!m_userAgentOverride.isEmpty())
398         *userAgent = m_userAgentOverride;
399 }
400
401 #if ENABLE(WORKERS)
402 class PostWorkerNotificationToFrontendTask : public ScriptExecutionContext::Task {
403 public:
404     static PassOwnPtr<PostWorkerNotificationToFrontendTask> create(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
405     {
406         return new PostWorkerNotificationToFrontendTask(worker, action);
407     }
408
409 private:
410     PostWorkerNotificationToFrontendTask(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
411         : m_worker(worker)
412         , m_action(action)
413     {
414     }
415
416     virtual void performTask(ScriptExecutionContext* scriptContext)
417     {
418         if (scriptContext->isDocument()) {
419             if (InspectorAgent* inspectorAgent = static_cast<Document*>(scriptContext)->page()->inspectorController()->m_inspectorAgent.get())
420                 inspectorAgent->postWorkerNotificationToFrontend(*m_worker, m_action);
421         }
422     }
423
424 private:
425     RefPtr<InspectorWorkerResource> m_worker;
426     InspectorAgent::WorkerAction m_action;
427 };
428
429 void InspectorAgent::postWorkerNotificationToFrontend(const InspectorWorkerResource& worker, InspectorAgent::WorkerAction action)
430 {
431     if (!m_frontend)
432         return;
433 #if ENABLE(JAVASCRIPT_DEBUGGER)
434     switch (action) {
435     case InspectorAgent::WorkerCreated:
436         m_frontend->inspector()->didCreateWorker(worker.id(), worker.url(), worker.isSharedWorker());
437         break;
438     case InspectorAgent::WorkerDestroyed:
439         m_frontend->inspector()->didDestroyWorker(worker.id());
440         break;
441     }
442 #endif
443 }
444
445 void InspectorAgent::didCreateWorker(intptr_t id, const String& url, bool isSharedWorker)
446 {
447     if (!enabled())
448         return;
449
450     RefPtr<InspectorWorkerResource> workerResource(InspectorWorkerResource::create(id, url, isSharedWorker));
451     m_workers.set(id, workerResource);
452     if (m_inspectedPage && m_frontend)
453         m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource, InspectorAgent::WorkerCreated));
454 }
455
456 void InspectorAgent::didDestroyWorker(intptr_t id)
457 {
458     if (!enabled())
459         return;
460
461     WorkersMap::iterator workerResource = m_workers.find(id);
462     if (workerResource == m_workers.end())
463         return;
464     if (m_inspectedPage && m_frontend)
465         m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource->second, InspectorAgent::WorkerDestroyed));
466     m_workers.remove(workerResource);
467 }
468 #endif // ENABLE(WORKERS)
469
470 void InspectorAgent::getCookies(ErrorString*, RefPtr<InspectorArray>* cookies, WTF::String* cookiesString)
471 {
472     // If we can get raw cookies.
473     ListHashSet<Cookie> rawCookiesList;
474
475     // If we can't get raw cookies - fall back to String representation
476     String stringCookiesList;
477
478     // Return value to getRawCookies should be the same for every call because
479     // the return value is platform/network backend specific, and the call will
480     // always return the same true/false value.
481     bool rawCookiesImplemented = false;
482
483     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
484         Document* document = frame->document();
485         const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources();
486         CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
487         for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
488             Vector<Cookie> docCookiesList;
489             rawCookiesImplemented = getRawCookies(document, KURL(ParsedURLString, it->second->url()), docCookiesList);
490
491             if (!rawCookiesImplemented) {
492                 // FIXME: We need duplication checking for the String representation of cookies.
493                 ExceptionCode ec = 0;
494                 stringCookiesList += document->cookie(ec);
495                 // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here
496                 // because "document" is the document of the main frame of the page.
497                 ASSERT(!ec);
498             } else {
499                 int cookiesSize = docCookiesList.size();
500                 for (int i = 0; i < cookiesSize; i++) {
501                     if (!rawCookiesList.contains(docCookiesList[i]))
502                         rawCookiesList.add(docCookiesList[i]);
503                 }
504             }
505         }
506     }
507
508     if (rawCookiesImplemented)
509         *cookies = buildArrayForCookies(rawCookiesList);
510     else
511         *cookiesString = stringCookiesList;
512 }
513
514 PassRefPtr<InspectorArray> InspectorAgent::buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
515 {
516     RefPtr<InspectorArray> cookies = InspectorArray::create();
517
518     ListHashSet<Cookie>::iterator end = cookiesList.end();
519     ListHashSet<Cookie>::iterator it = cookiesList.begin();
520     for (int i = 0; it != end; ++it, i++)
521         cookies->pushObject(buildObjectForCookie(*it));
522
523     return cookies;
524 }
525
526 PassRefPtr<InspectorObject> InspectorAgent::buildObjectForCookie(const Cookie& cookie)
527 {
528     RefPtr<InspectorObject> value = InspectorObject::create();
529     value->setString("name", cookie.name);
530     value->setString("value", cookie.value);
531     value->setString("domain", cookie.domain);
532     value->setString("path", cookie.path);
533     value->setNumber("expires", cookie.expires);
534     value->setNumber("size", (cookie.name.length() + cookie.value.length()));
535     value->setBoolean("httpOnly", cookie.httpOnly);
536     value->setBoolean("secure", cookie.secure);
537     value->setBoolean("session", cookie.session);
538     return value;
539 }
540
541 void InspectorAgent::deleteCookie(ErrorString*, const String& cookieName, const String& domain)
542 {
543     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
544         Document* document = frame->document();
545         if (document->url().host() != domain)
546             continue;
547         const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources();
548         CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
549         for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it)
550             WebCore::deleteCookie(document, KURL(ParsedURLString, it->second->url()), cookieName);
551     }
552 }
553
554 #if ENABLE(JAVASCRIPT_DEBUGGER)
555 void InspectorAgent::showProfilesPanel()
556 {
557     showPanel(profilesPanelName);
558 }
559 #endif
560
561 void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
562 {
563     m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
564     if (m_canIssueEvaluateForTestInFrontend)
565         issueEvaluateForTestCommands();
566 }
567
568 void InspectorAgent::didEvaluateForTestInFrontend(ErrorString*, long callId, const String& jsonResult)
569 {
570     ScriptState* scriptState = scriptStateFromPage(debuggerWorld(), m_inspectedPage);
571     ScriptObject window;
572     ScriptGlobalObject::get(scriptState, "window", window);
573     ScriptFunctionCall function(window, "didEvaluateForTestInFrontend");
574     function.appendArgument(callId);
575     function.appendArgument(jsonResult);
576     function.call();
577 }
578
579 void InspectorAgent::openInInspectedWindow(ErrorString*, const String& url)
580 {
581     Frame* mainFrame = m_inspectedPage->mainFrame();
582
583     FrameLoadRequest request(mainFrame->document()->securityOrigin(), ResourceRequest(), "_blank");
584
585     bool created;
586     WindowFeatures windowFeatures;
587     Frame* newFrame = WebCore::createWindow(mainFrame, mainFrame, request, windowFeatures, created);
588     if (!newFrame)
589         return;
590
591     UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
592     newFrame->loader()->setOpener(mainFrame);
593     newFrame->page()->setOpenedByDOM();
594     newFrame->loader()->changeLocation(mainFrame->document()->securityOrigin(), newFrame->loader()->completeURL(url), "", false, false);
595 }
596
597 void InspectorAgent::addScriptToEvaluateOnLoad(ErrorString*, const String& source)
598 {
599     m_scriptsToEvaluateOnLoad.append(source);
600 }
601
602 void InspectorAgent::removeAllScriptsToEvaluateOnLoad(ErrorString*)
603 {
604     m_scriptsToEvaluateOnLoad.clear();
605 }
606
607 void InspectorAgent::setInspectorExtensionAPI(const String& source)
608 {
609     m_inspectorExtensionAPI = source;
610 }
611
612 KURL InspectorAgent::inspectedURL() const
613 {
614     return m_inspectedPage->mainFrame()->document()->url();
615 }
616
617 KURL InspectorAgent::inspectedURLWithoutFragment() const
618 {
619     KURL url = inspectedURL();
620     url.removeFragmentIdentifier();
621     return url;
622 }
623
624 void InspectorAgent::reloadPage(ErrorString*, bool ignoreCache)
625 {
626     m_inspectedPage->mainFrame()->loader()->reload(ignoreCache);
627 }
628
629 bool InspectorAgent::enabled() const
630 {
631     if (!m_inspectedPage)
632         return false;
633     return m_inspectedPage->settings()->developerExtrasEnabled();
634 }
635
636 void InspectorAgent::showConsole()
637 {
638     showPanel(consolePanelName);
639 }
640
641 void InspectorAgent::showPanel(const String& panel)
642 {
643     if (!m_frontend) {
644         m_showPanelAfterVisible = panel;
645         return;
646     }
647     m_frontend->inspector()->showPanel(panel);
648 }
649
650 void InspectorAgent::issueEvaluateForTestCommands()
651 {
652     if (m_frontend) {
653         Vector<pair<long, String> > copy = m_pendingEvaluateTestCommands;
654         m_pendingEvaluateTestCommands.clear();
655         for (Vector<pair<long, String> >::iterator it = copy.begin(); m_frontend && it != copy.end(); ++it)
656             m_frontend->inspector()->evaluateForTestInFrontend((*it).first, (*it).second);
657         m_canIssueEvaluateForTestInFrontend = true;
658     }
659 }
660
661 } // namespace WebCore
662
663 #endif // ENABLE(INSPECTOR)