2011-02-14 Pavel Feldman <pfeldman@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 "CachedResource.h"
36 #include "CachedResourceLoader.h"
37 #include "Chrome.h"
38 #include "Cookie.h"
39 #include "CookieJar.h"
40 #include "DOMWindow.h"
41 #include "DOMWrapperWorld.h"
42 #include "Document.h"
43 #include "DocumentLoader.h"
44 #include "Element.h"
45 #include "FloatConversion.h"
46 #include "FloatQuad.h"
47 #include "FloatRect.h"
48 #include "Frame.h"
49 #include "FrameLoadRequest.h"
50 #include "FrameLoader.h"
51 #include "FrameTree.h"
52 #include "FrameView.h"
53 #include "GraphicsContext.h"
54 #include "HTMLFrameOwnerElement.h"
55 #include "HTTPHeaderMap.h"
56 #include "HitTestResult.h"
57 #include "InjectedScript.h"
58 #include "InjectedScriptHost.h"
59 #include "InspectorBrowserDebuggerAgent.h"
60 #include "InspectorCSSAgent.h"
61 #include "InspectorClient.h"
62 #include "InspectorConsoleAgent.h"
63 #include "InspectorController.h"
64 #include "InspectorDOMAgent.h"
65 #include "InspectorDOMStorageResource.h"
66 #include "InspectorDatabaseResource.h"
67 #include "InspectorDebuggerAgent.h"
68 #include "InspectorFrontend.h"
69 #include "InspectorFrontendClient.h"
70 #include "InspectorInstrumentation.h"
71 #include "InspectorProfilerAgent.h"
72 #include "InspectorResourceAgent.h"
73 #include "InspectorRuntimeAgent.h"
74 #include "InspectorState.h"
75 #include "InspectorTimelineAgent.h"
76 #include "InspectorValues.h"
77 #include "InspectorWorkerResource.h"
78 #include "IntRect.h"
79 #include "Page.h"
80 #include "ProgressTracker.h"
81 #include "Range.h"
82 #include "RenderInline.h"
83 #include "ResourceRequest.h"
84 #include "ResourceResponse.h"
85 #include "ScriptArguments.h"
86 #include "ScriptCallStack.h"
87 #include "ScriptFunctionCall.h"
88 #include "ScriptObject.h"
89 #include "ScriptProfile.h"
90 #include "ScriptProfiler.h"
91 #include "ScriptSourceCode.h"
92 #include "ScriptState.h"
93 #include "SecurityOrigin.h"
94 #include "Settings.h"
95 #include "SharedBuffer.h"
96 #include "TextEncoding.h"
97 #include "TextIterator.h"
98 #include "TextRun.h"
99 #include "UserGestureIndicator.h"
100 #include "WindowFeatures.h"
101 #include <wtf/CurrentTime.h>
102 #include <wtf/ListHashSet.h>
103 #include <wtf/RefCounted.h>
104 #include <wtf/StdLibExtras.h>
105 #include <wtf/UnusedParam.h>
106 #include <wtf/text/StringConcatenate.h>
107
108 #if ENABLE(DATABASE)
109 #include "Database.h"
110 #include "InspectorDatabaseAgent.h"
111 #endif
112
113 #if ENABLE(DOM_STORAGE)
114 #include "InspectorDOMStorageAgent.h"
115 #include "Storage.h"
116 #include "StorageArea.h"
117 #endif
118
119 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
120 #include "InspectorApplicationCacheAgent.h"
121 #endif
122
123 using namespace std;
124
125 namespace WebCore {
126
127 namespace InspectorAgentState {
128 static const char searchingForNode[] = "searchingForNode";
129 static const char timelineProfilerEnabled[] = "timelineProfilerEnabled";
130 static const char userInitiatedProfiling[] = "userInitiatedProfiling";
131 static const char debuggerEnabled[] = "debuggerEnabled";
132 static const char profilerEnabled[] = "profilerEnabled";
133 }
134
135 static const char scriptsPanelName[] = "scripts";
136 static const char consolePanelName[] = "console";
137 static const char profilesPanelName[] = "profiles";
138
139 InspectorAgent::InspectorAgent(Page* page, InspectorClient* client)
140     : m_inspectedPage(page)
141     , m_client(client)
142     , m_frontend(0)
143     , m_cssAgent(new InspectorCSSAgent())
144     , m_state(new InspectorState(client))
145     , m_injectedScriptHost(InjectedScriptHost::create(this))
146     , m_consoleAgent(new InspectorConsoleAgent(this))
147 #if ENABLE(JAVASCRIPT_DEBUGGER)
148     , m_profilerAgent(InspectorProfilerAgent::create(this))
149 #endif
150 {
151     ASSERT_ARG(page, page);
152     ASSERT_ARG(client, client);
153     InspectorInstrumentation::bindInspectorAgent(m_inspectedPage, this);
154 }
155
156 InspectorAgent::~InspectorAgent()
157 {
158     // These should have been cleared in inspectedPageDestroyed().
159     ASSERT(!m_client);
160     ASSERT(!m_inspectedPage);
161     ASSERT(!m_highlightedNode);
162 }
163
164 void InspectorAgent::inspectedPageDestroyed()
165 {
166     if (m_frontend)
167         m_frontend->disconnectFromBackend();
168
169     hideHighlight();
170
171 #if ENABLE(JAVASCRIPT_DEBUGGER)
172     m_debuggerAgent.clear();
173     m_browserDebuggerAgent.clear();
174 #endif
175
176     ASSERT(m_inspectedPage);
177     InspectorInstrumentation::unbindInspectorAgent(m_inspectedPage);
178     m_inspectedPage = 0;
179
180     releaseFrontendLifetimeAgents();
181     m_injectedScriptHost->disconnectController();
182
183     m_client->inspectorDestroyed();
184     m_client = 0;
185 }
186
187 bool InspectorAgent::searchingForNodeInPage() const
188 {
189     return m_state->getBoolean(InspectorAgentState::searchingForNode);
190 }
191
192 void InspectorAgent::restoreInspectorStateFromCookie(const String& inspectorStateCookie)
193 {
194     m_state = new InspectorState(m_client, inspectorStateCookie);
195
196     m_frontend->frontendReused();
197     m_frontend->inspectedURLChanged(inspectedURL().string());
198     pushDataCollectedOffline();
199
200     m_resourceAgent = InspectorResourceAgent::restore(m_inspectedPage, m_state.get(), m_frontend);
201     m_timelineAgent = InspectorTimelineAgent::restore(m_state.get(), m_frontend);
202
203 #if ENABLE(JAVASCRIPT_DEBUGGER)
204     restoreDebugger(false);
205     restoreProfiler(ProfilerRestoreResetAgent);
206     if (m_state->getBoolean(InspectorAgentState::userInitiatedProfiling))
207         startUserInitiatedProfiling();
208 #endif
209 }
210
211 void InspectorAgent::inspect(Node* node)
212 {
213     if (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)
214         node = node->parentNode();
215     m_nodeToFocus = node;
216
217     if (!m_frontend)
218         return;
219
220     focusNode();
221 }
222
223 void InspectorAgent::focusNode()
224 {
225     if (!enabled())
226         return;
227
228     ASSERT(m_frontend);
229     ASSERT(m_nodeToFocus);
230
231     long id = m_domAgent->pushNodePathToFrontend(m_nodeToFocus.get());
232     m_frontend->updateFocusedNode(id);
233     m_nodeToFocus = 0;
234 }
235
236 void InspectorAgent::highlight(Node* node)
237 {
238     if (!enabled())
239         return;
240     ASSERT_ARG(node, node);
241     m_highlightedNode = node;
242     m_client->highlight(node);
243 }
244
245 void InspectorAgent::highlightDOMNode(long nodeId)
246 {
247     Node* node = 0;
248     if (m_domAgent && (node = m_domAgent->nodeForId(nodeId)))
249         highlight(node);
250 }
251
252 void InspectorAgent::highlightFrame(unsigned long frameId)
253 {
254     Frame* mainFrame = m_inspectedPage->mainFrame();
255     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext(mainFrame)) {
256         if (reinterpret_cast<uintptr_t>(frame) == frameId && frame->ownerElement()) {
257             highlight(frame->ownerElement());
258             return;
259         }
260     }
261 }
262
263 void InspectorAgent::hideHighlight()
264 {
265     if (!enabled())
266         return;
267     m_highlightedNode = 0;
268     m_client->hideHighlight();
269 }
270
271 void InspectorAgent::mouseDidMoveOverElement(const HitTestResult& result, unsigned)
272 {
273     if (!enabled() || !searchingForNodeInPage())
274         return;
275
276     Node* node = result.innerNode();
277     while (node && node->nodeType() == Node::TEXT_NODE)
278         node = node->parentNode();
279     if (node)
280         highlight(node);
281 }
282
283 bool InspectorAgent::handleMousePress()
284 {
285     if (!enabled() || !searchingForNodeInPage())
286         return false;
287
288     if (m_highlightedNode) {
289         RefPtr<Node> node = m_highlightedNode;
290         setSearchingForNode(false);
291         inspect(node.get());
292     }
293     return true;
294 }
295
296 void InspectorAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
297 {
298     if (world != mainThreadNormalWorld())
299         return;
300
301     if (enabled()) {
302         if (m_frontend && frame == m_inspectedPage->mainFrame())
303             m_injectedScriptHost->discardInjectedScripts();
304
305         if (m_scriptsToEvaluateOnLoad.size()) {
306             ScriptState* scriptState = mainWorldScriptState(frame);
307             for (Vector<String>::iterator it = m_scriptsToEvaluateOnLoad.begin();
308                   it != m_scriptsToEvaluateOnLoad.end(); ++it) {
309                 m_injectedScriptHost->injectScript(*it, scriptState);
310             }
311         }
312     }
313
314     if (!m_inspectorExtensionAPI.isEmpty())
315         m_injectedScriptHost->injectScript(m_inspectorExtensionAPI, mainWorldScriptState(frame));
316 }
317
318 void InspectorAgent::setSearchingForNode(bool enabled)
319 {
320     if (searchingForNodeInPage() == enabled)
321         return;
322     m_state->setBoolean(InspectorAgentState::searchingForNode, enabled);
323     if (!enabled)
324         hideHighlight();
325 }
326
327 void InspectorAgent::setSearchingForNode(bool enabled, bool* newState)
328 {
329     *newState = enabled;
330     setSearchingForNode(enabled);
331 }
332
333 void InspectorAgent::setFrontend(InspectorFrontend* inspectorFrontend)
334 {
335     m_frontend = inspectorFrontend;
336     createFrontendLifetimeAgents();
337
338     m_cssAgent->setDOMAgent(m_domAgent.get());
339     m_consoleAgent->setFrontend(m_frontend);
340
341     // Initialize Web Inspector title.
342     m_frontend->inspectedURLChanged(inspectedURL().string());
343 }
344
345 void InspectorAgent::disconnectFrontend()
346 {
347     if (!m_frontend)
348         return;
349
350     // Destroying agents would change the state, but we don't want that.
351     // Pre-disconnect state will be used to restore inspector agents.
352     m_state->mute();
353
354     m_frontend = 0;
355
356 #if ENABLE(JAVASCRIPT_DEBUGGER)
357     // If the window is being closed with the debugger enabled,
358     // remember this state to re-enable debugger on the next window
359     // opening.
360     disableDebugger();
361 #endif
362     setSearchingForNode(false);
363
364     hideHighlight();
365
366 #if ENABLE(JAVASCRIPT_DEBUGGER)
367     m_profilerAgent->setFrontend(0);
368     m_profilerAgent->stopUserInitiatedProfiling(true);
369 #endif
370
371     m_consoleAgent->setFrontend(0);
372
373     releaseFrontendLifetimeAgents();
374     m_userAgentOverride = "";
375 }
376
377 InspectorResourceAgent* InspectorAgent::resourceAgent()
378 {
379     if (!m_resourceAgent && m_frontend)
380         m_resourceAgent = InspectorResourceAgent::create(m_inspectedPage, m_state.get(), m_frontend);
381     return m_resourceAgent.get();
382 }
383
384 void InspectorAgent::createFrontendLifetimeAgents()
385 {
386     m_domAgent = InspectorDOMAgent::create(m_injectedScriptHost.get(), m_frontend);
387     m_runtimeAgent = InspectorRuntimeAgent::create(m_injectedScriptHost.get());
388
389 #if ENABLE(DATABASE)
390     m_databaseAgent = InspectorDatabaseAgent::create(&m_databaseResources, m_frontend);
391 #endif
392
393 #if ENABLE(DOM_STORAGE)
394     m_domStorageAgent = InspectorDOMStorageAgent::create(&m_domStorageResources, m_frontend);
395 #endif
396
397 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
398     m_applicationCacheAgent = new InspectorApplicationCacheAgent(m_inspectedPage->mainFrame()->loader()->documentLoader(), m_frontend);
399 #endif
400 }
401
402 void InspectorAgent::releaseFrontendLifetimeAgents()
403 {
404     m_resourceAgent.clear();
405     m_runtimeAgent.clear();
406     m_timelineAgent.clear();
407
408 #if ENABLE(DATABASE)
409     m_databaseAgent.clear();
410 #endif
411
412 #if ENABLE(DOM_STORAGE)
413     m_domStorageAgent.clear();
414 #endif
415
416 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
417     m_applicationCacheAgent.clear();
418 #endif
419
420     // This should be invoked prior to m_domAgent destruction.
421     m_cssAgent->setDOMAgent(0);
422     m_domAgent.clear();
423 }
424
425 void InspectorAgent::populateScriptObjects()
426 {
427     ASSERT(m_frontend);
428     if (!m_frontend)
429         return;
430
431 #if ENABLE(JAVASCRIPT_DEBUGGER)
432     if (m_profilerAgent->enabled())
433         m_frontend->profilerWasEnabled();
434 #endif
435
436     pushDataCollectedOffline();
437
438     if (m_nodeToFocus)
439         focusNode();
440
441     if (!m_showPanelAfterVisible.isEmpty()) {
442         m_frontend->showPanel(m_showPanelAfterVisible);
443         m_showPanelAfterVisible = "";
444     }
445
446     restoreDebugger(true);
447     restoreProfiler(ProfilerRestoreNoAction);
448
449     // Dispatch pending frontend commands
450     for (Vector<pair<long, String> >::iterator it = m_pendingEvaluateTestCommands.begin(); it != m_pendingEvaluateTestCommands.end(); ++it)
451         m_frontend->evaluateForTestInFrontend((*it).first, (*it).second);
452     m_pendingEvaluateTestCommands.clear();
453 }
454
455 void InspectorAgent::pushDataCollectedOffline()
456 {
457     m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
458
459 #if ENABLE(DATABASE)
460     DatabaseResourcesMap::iterator databasesEnd = m_databaseResources.end();
461     for (DatabaseResourcesMap::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it)
462         it->second->bind(m_frontend);
463 #endif
464 #if ENABLE(DOM_STORAGE)
465     DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources.end();
466     for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it)
467         it->second->bind(m_frontend);
468 #endif
469 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
470     WorkersMap::iterator workersEnd = m_workers.end();
471     for (WorkersMap::iterator it = m_workers.begin(); it != workersEnd; ++it) {
472         InspectorWorkerResource* worker = it->second.get();
473         m_frontend->didCreateWorker(worker->id(), worker->url(), worker->isSharedWorker());
474     }
475 #endif
476 }
477
478 void InspectorAgent::restoreDebugger(bool eraseStickyBreakpoints)
479 {
480     ASSERT(m_frontend);
481 #if ENABLE(JAVASCRIPT_DEBUGGER)
482     if (m_state->getBoolean(InspectorAgentState::debuggerEnabled))
483         enableDebugger(eraseStickyBreakpoints);
484 #endif
485 }
486
487 void InspectorAgent::restoreProfiler(ProfilerRestoreAction action)
488 {
489     ASSERT(m_frontend);
490 #if ENABLE(JAVASCRIPT_DEBUGGER)
491     m_profilerAgent->setFrontend(m_frontend);
492     if (m_state->getBoolean(InspectorAgentState::profilerEnabled))
493         enableProfiler();
494     if (action == ProfilerRestoreResetAgent)
495         m_profilerAgent->resetFrontendProfiles();
496 #endif
497 }
498
499 void InspectorAgent::didCommitLoad(DocumentLoader* loader)
500 {
501     if (!enabled())
502         return;
503
504     if (m_resourceAgent)
505         m_resourceAgent->didCommitLoad(loader);
506
507     ASSERT(m_inspectedPage);
508
509     if (loader->frame() == m_inspectedPage->mainFrame()) {
510         if (m_frontend)
511             m_frontend->inspectedURLChanged(loader->url().string());
512
513         m_injectedScriptHost->discardInjectedScripts();
514         m_consoleAgent->reset();
515
516         if (m_timelineAgent)
517             m_timelineAgent->didCommitLoad();
518
519 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
520         if (m_applicationCacheAgent)
521             m_applicationCacheAgent->didCommitLoad(loader);
522 #endif
523
524 #if ENABLE(JAVASCRIPT_DEBUGGER)
525         if (m_debuggerAgent) {
526             KURL url = inspectedURLWithoutFragment();
527             m_debuggerAgent->inspectedURLChanged(url);
528             if (m_browserDebuggerAgent)
529                 m_browserDebuggerAgent->inspectedURLChanged(url);
530         }
531 #endif
532
533 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
534         m_profilerAgent->stopUserInitiatedProfiling(true);
535         m_profilerAgent->resetState();
536 #endif
537
538         if (m_frontend) {
539             m_frontend->reset();
540             m_domAgent->reset();
541             m_cssAgent->reset();
542         }
543 #if ENABLE(WORKERS)
544         m_workers.clear();
545 #endif
546 #if ENABLE(DATABASE)
547         m_databaseResources.clear();
548 #endif
549 #if ENABLE(DOM_STORAGE)
550         m_domStorageResources.clear();
551 #endif
552
553         if (m_frontend)
554             m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
555     }
556 }
557
558 void InspectorAgent::domContentLoadedEventFired(DocumentLoader* loader, const KURL& url)
559 {
560     if (!enabled() || !isMainResourceLoader(loader, url))
561         return;
562
563     if (m_domAgent)
564         m_domAgent->mainFrameDOMContentLoaded();
565     if (m_timelineAgent)
566         m_timelineAgent->didMarkDOMContentEvent();
567     if (m_frontend)
568         m_frontend->domContentEventFired(currentTime());
569 }
570
571 void InspectorAgent::loadEventFired(DocumentLoader* loader, const KURL& url)
572 {
573     if (!enabled())
574         return;
575
576     if (m_domAgent)
577         m_domAgent->loadEventFired(loader->frame()->document());
578
579     if (!isMainResourceLoader(loader, url))
580         return;
581
582     if (m_timelineAgent)
583         m_timelineAgent->didMarkLoadEvent();
584     if (m_frontend)
585         m_frontend->loadEventFired(currentTime());
586 }
587
588 bool InspectorAgent::isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl)
589 {
590     return loader->frame() == m_inspectedPage->mainFrame() && requestUrl == loader->requestURL();
591 }
592
593 void InspectorAgent::setUserAgentOverride(const String& userAgent)
594 {
595     m_userAgentOverride = userAgent;
596 }
597
598 void InspectorAgent::applyUserAgentOverride(String* userAgent) const
599 {
600     if (!m_userAgentOverride.isEmpty())
601         *userAgent = m_userAgentOverride;
602 }
603
604 void InspectorAgent::startTimelineProfiler()
605 {
606     if (m_timelineAgent || !enabled() || !m_frontend)
607         return;
608
609     m_timelineAgent = InspectorTimelineAgent::create(m_state.get(), m_frontend);
610 }
611
612 void InspectorAgent::stopTimelineProfiler()
613 {
614     m_timelineAgent.clear();
615 }
616
617 #if ENABLE(WORKERS)
618 class PostWorkerNotificationToFrontendTask : public ScriptExecutionContext::Task {
619 public:
620     static PassOwnPtr<PostWorkerNotificationToFrontendTask> create(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
621     {
622         return new PostWorkerNotificationToFrontendTask(worker, action);
623     }
624
625 private:
626     PostWorkerNotificationToFrontendTask(PassRefPtr<InspectorWorkerResource> worker, InspectorAgent::WorkerAction action)
627         : m_worker(worker)
628         , m_action(action)
629     {
630     }
631
632     virtual void performTask(ScriptExecutionContext* scriptContext)
633     {
634         if (scriptContext->isDocument()) {
635             if (InspectorAgent* inspectorAgent = static_cast<Document*>(scriptContext)->page()->inspectorController()->m_inspectorAgent.get())
636                 inspectorAgent->postWorkerNotificationToFrontend(*m_worker, m_action);
637         }
638     }
639
640 private:
641     RefPtr<InspectorWorkerResource> m_worker;
642     InspectorAgent::WorkerAction m_action;
643 };
644
645 void InspectorAgent::postWorkerNotificationToFrontend(const InspectorWorkerResource& worker, InspectorAgent::WorkerAction action)
646 {
647     if (!m_frontend)
648         return;
649 #if ENABLE(JAVASCRIPT_DEBUGGER)
650     switch (action) {
651     case InspectorAgent::WorkerCreated:
652         m_frontend->didCreateWorker(worker.id(), worker.url(), worker.isSharedWorker());
653         break;
654     case InspectorAgent::WorkerDestroyed:
655         m_frontend->didDestroyWorker(worker.id());
656         break;
657     }
658 #endif
659 }
660
661 void InspectorAgent::didCreateWorker(intptr_t id, const String& url, bool isSharedWorker)
662 {
663     if (!enabled())
664         return;
665
666     RefPtr<InspectorWorkerResource> workerResource(InspectorWorkerResource::create(id, url, isSharedWorker));
667     m_workers.set(id, workerResource);
668     if (m_inspectedPage && m_frontend)
669         m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource, InspectorAgent::WorkerCreated));
670 }
671
672 void InspectorAgent::didDestroyWorker(intptr_t id)
673 {
674     if (!enabled())
675         return;
676
677     WorkersMap::iterator workerResource = m_workers.find(id);
678     if (workerResource == m_workers.end())
679         return;
680     if (m_inspectedPage && m_frontend)
681         m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource->second, InspectorAgent::WorkerDestroyed));
682     m_workers.remove(workerResource);
683 }
684 #endif // ENABLE(WORKERS)
685
686 #if ENABLE(DATABASE)
687 void InspectorAgent::didOpenDatabase(PassRefPtr<Database> database, const String& domain, const String& name, const String& version)
688 {
689     if (!enabled())
690         return;
691
692     RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version);
693
694     m_databaseResources.set(resource->id(), resource);
695
696     // Resources are only bound while visible.
697     if (m_frontend)
698         resource->bind(m_frontend);
699 }
700 #endif
701
702 void InspectorAgent::getCookies(RefPtr<InspectorArray>* cookies, WTF::String* cookiesString)
703 {
704     // If we can get raw cookies.
705     ListHashSet<Cookie> rawCookiesList;
706
707     // If we can't get raw cookies - fall back to String representation
708     String stringCookiesList;
709
710     // Return value to getRawCookies should be the same for every call because
711     // the return value is platform/network backend specific, and the call will
712     // always return the same true/false value.
713     bool rawCookiesImplemented = false;
714
715     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
716         Document* document = frame->document();
717         const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources();
718         CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
719         for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
720             Vector<Cookie> docCookiesList;
721             rawCookiesImplemented = getRawCookies(document, KURL(ParsedURLString, it->second->url()), docCookiesList);
722
723             if (!rawCookiesImplemented) {
724                 // FIXME: We need duplication checking for the String representation of cookies.
725                 ExceptionCode ec = 0;
726                 stringCookiesList += document->cookie(ec);
727                 // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here
728                 // because "document" is the document of the main frame of the page.
729                 ASSERT(!ec);
730             } else {
731                 int cookiesSize = docCookiesList.size();
732                 for (int i = 0; i < cookiesSize; i++) {
733                     if (!rawCookiesList.contains(docCookiesList[i]))
734                         rawCookiesList.add(docCookiesList[i]);
735                 }
736             }
737         }
738     }
739
740     if (rawCookiesImplemented)
741         *cookies = buildArrayForCookies(rawCookiesList);
742     else
743         *cookiesString = stringCookiesList;
744 }
745
746 PassRefPtr<InspectorArray> InspectorAgent::buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
747 {
748     RefPtr<InspectorArray> cookies = InspectorArray::create();
749
750     ListHashSet<Cookie>::iterator end = cookiesList.end();
751     ListHashSet<Cookie>::iterator it = cookiesList.begin();
752     for (int i = 0; it != end; ++it, i++)
753         cookies->pushObject(buildObjectForCookie(*it));
754
755     return cookies;
756 }
757
758 PassRefPtr<InspectorObject> InspectorAgent::buildObjectForCookie(const Cookie& cookie)
759 {
760     RefPtr<InspectorObject> value = InspectorObject::create();
761     value->setString("name", cookie.name);
762     value->setString("value", cookie.value);
763     value->setString("domain", cookie.domain);
764     value->setString("path", cookie.path);
765     value->setNumber("expires", cookie.expires);
766     value->setNumber("size", (cookie.name.length() + cookie.value.length()));
767     value->setBoolean("httpOnly", cookie.httpOnly);
768     value->setBoolean("secure", cookie.secure);
769     value->setBoolean("session", cookie.session);
770     return value;
771 }
772
773 void InspectorAgent::deleteCookie(const String& cookieName, const String& domain)
774 {
775     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext(m_inspectedPage->mainFrame())) {
776         Document* document = frame->document();
777         if (document->url().host() != domain)
778             continue;
779         const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources();
780         CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end();
781         for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it)
782             WebCore::deleteCookie(document, KURL(ParsedURLString, it->second->url()), cookieName);
783     }
784 }
785
786 #if ENABLE(DOM_STORAGE)
787 void InspectorAgent::didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame)
788 {
789     if (!enabled())
790         return;
791
792     DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources.end();
793     for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it)
794         if (it->second->isSameHostAndType(frame, isLocalStorage))
795             return;
796
797     RefPtr<Storage> domStorage = Storage::create(frame, storageArea);
798     RefPtr<InspectorDOMStorageResource> resource = InspectorDOMStorageResource::create(domStorage.get(), isLocalStorage, frame);
799
800     m_domStorageResources.set(resource->id(), resource);
801
802     // Resources are only bound while visible.
803     if (m_frontend)
804         resource->bind(m_frontend);
805 }
806 #endif
807
808 #if ENABLE(WEB_SOCKETS)
809 void InspectorAgent::didCreateWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL)
810 {
811     if (!enabled())
812         return;
813     ASSERT(m_inspectedPage);
814
815     if (m_resourceAgent)
816         m_resourceAgent->didCreateWebSocket(identifier, requestURL);
817     UNUSED_PARAM(documentURL);
818 }
819
820 void InspectorAgent::willSendWebSocketHandshakeRequest(unsigned long identifier, const WebSocketHandshakeRequest& request)
821 {
822     if (m_resourceAgent)
823         m_resourceAgent->willSendWebSocketHandshakeRequest(identifier, request);
824 }
825
826 void InspectorAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const WebSocketHandshakeResponse& response)
827 {
828     if (m_resourceAgent)
829         m_resourceAgent->didReceiveWebSocketHandshakeResponse(identifier, response);
830 }
831
832 void InspectorAgent::didCloseWebSocket(unsigned long identifier)
833 {
834     if (m_resourceAgent)
835         m_resourceAgent->didCloseWebSocket(identifier);
836 }
837 #endif // ENABLE(WEB_SOCKETS)
838
839 #if ENABLE(JAVASCRIPT_DEBUGGER)
840 bool InspectorAgent::isRecordingUserInitiatedProfile() const
841 {
842     return m_profilerAgent->isRecordingUserInitiatedProfile();
843 }
844
845 void InspectorAgent::startUserInitiatedProfiling()
846 {
847     if (!enabled())
848         return;
849     m_profilerAgent->startUserInitiatedProfiling();
850     m_state->setBoolean(InspectorAgentState::userInitiatedProfiling, true);
851 }
852
853 void InspectorAgent::stopUserInitiatedProfiling()
854 {
855     m_profilerAgent->stopUserInitiatedProfiling();
856     m_state->setBoolean(InspectorAgentState::userInitiatedProfiling, false);
857     showPanel(profilesPanelName);
858 }
859
860 bool InspectorAgent::profilerEnabled() const
861 {
862     return enabled() && m_profilerAgent->enabled();
863 }
864
865 void InspectorAgent::enableProfiler()
866 {
867     if (profilerEnabled())
868         return;
869     m_state->setBoolean(InspectorAgentState::profilerEnabled, true);
870     m_profilerAgent->enable(false);
871 }
872
873 void InspectorAgent::disableProfiler()
874 {
875     m_state->setBoolean(InspectorAgentState::profilerEnabled, false);
876     m_profilerAgent->disable();
877 }
878 #endif
879
880 #if ENABLE(JAVASCRIPT_DEBUGGER)
881 void InspectorAgent::startUserInitiatedDebugging()
882 {
883     if (debuggerEnabled())
884         return;
885
886     showPanel(scriptsPanelName);
887     if (!m_frontend) {
888         // We are called after show(), set the debuggerEnabled flag so that it was enabled
889         // upon frontend opening.
890         m_state->setBoolean(InspectorAgentState::debuggerEnabled, true);
891     } else
892         enableDebugger(true);
893 }
894
895 void InspectorAgent::enableDebugger(bool eraseStickyBreakpoints)
896 {
897     if (debuggerEnabled())
898         return;
899     m_state->setBoolean(InspectorAgentState::debuggerEnabled, true);
900     ASSERT(m_inspectedPage);
901
902     m_debuggerAgent = InspectorDebuggerAgent::create(this, m_frontend, eraseStickyBreakpoints);
903     m_browserDebuggerAgent = InspectorBrowserDebuggerAgent::create(this, eraseStickyBreakpoints);
904
905     m_frontend->debuggerWasEnabled();
906 }
907
908 void InspectorAgent::disableDebugger()
909 {
910     if (!enabled())
911         return;
912     ASSERT(m_inspectedPage);
913     m_debuggerAgent.clear();
914     m_browserDebuggerAgent.clear();
915
916     if (m_frontend) {
917         m_frontend->debuggerWasDisabled();
918         m_state->setBoolean(InspectorAgentState::debuggerEnabled, false);
919     }
920 }
921
922 void InspectorAgent::resume()
923 {
924     if (m_debuggerAgent)
925         m_debuggerAgent->resume();
926 }
927 #endif
928
929 void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
930 {
931     if (m_frontend)
932         m_frontend->evaluateForTestInFrontend(callId, script);
933     else
934         m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
935 }
936
937 void InspectorAgent::didEvaluateForTestInFrontend(long callId, const String& jsonResult)
938 {
939     ScriptState* scriptState = scriptStateFromPage(debuggerWorld(), m_inspectedPage);
940     ScriptObject window;
941     ScriptGlobalObject::get(scriptState, "window", window);
942     ScriptFunctionCall function(window, "didEvaluateForTestInFrontend");
943     function.appendArgument(callId);
944     function.appendArgument(jsonResult);
945     function.call();
946 }
947
948 static Path quadToPath(const FloatQuad& quad)
949 {
950     Path quadPath;
951     quadPath.moveTo(quad.p1());
952     quadPath.addLineTo(quad.p2());
953     quadPath.addLineTo(quad.p3());
954     quadPath.addLineTo(quad.p4());
955     quadPath.closeSubpath();
956     return quadPath;
957 }
958
959 static void drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, const Color& fillColor)
960 {
961     static const int outlineThickness = 2;
962     static const Color outlineColor(62, 86, 180, 228);
963
964     Path quadPath = quadToPath(quad);
965
966     // Clip out the quad, then draw with a 2px stroke to get a pixel
967     // of outline (because inflating a quad is hard)
968     {
969         context.save();
970         context.clipOut(quadPath);
971
972         context.setStrokeThickness(outlineThickness);
973         context.setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
974         context.strokePath(quadPath);
975
976         context.restore();
977     }
978
979     // Now do the fill
980     context.setFillColor(fillColor, ColorSpaceDeviceRGB);
981     context.fillPath(quadPath);
982 }
983
984 static void drawOutlinedQuadWithClip(GraphicsContext& context, const FloatQuad& quad, const FloatQuad& clipQuad, const Color& fillColor)
985 {
986     context.save();
987     Path clipQuadPath = quadToPath(clipQuad);
988     context.clipOut(clipQuadPath);
989     drawOutlinedQuad(context, quad, fillColor);
990     context.restore();
991 }
992
993 static void drawHighlightForBox(GraphicsContext& context, const FloatQuad& contentQuad, const FloatQuad& paddingQuad, const FloatQuad& borderQuad, const FloatQuad& marginQuad)
994 {
995     static const Color contentBoxColor(125, 173, 217, 128);
996     static const Color paddingBoxColor(125, 173, 217, 160);
997     static const Color borderBoxColor(125, 173, 217, 192);
998     static const Color marginBoxColor(125, 173, 217, 228);
999
1000     if (marginQuad != borderQuad)
1001         drawOutlinedQuadWithClip(context, marginQuad, borderQuad, marginBoxColor);
1002     if (borderQuad != paddingQuad)
1003         drawOutlinedQuadWithClip(context, borderQuad, paddingQuad, borderBoxColor);
1004     if (paddingQuad != contentQuad)
1005         drawOutlinedQuadWithClip(context, paddingQuad, contentQuad, paddingBoxColor);
1006
1007     drawOutlinedQuad(context, contentQuad, contentBoxColor);
1008 }
1009
1010 static void drawHighlightForLineBoxesOrSVGRenderer(GraphicsContext& context, const Vector<FloatQuad>& lineBoxQuads)
1011 {
1012     static const Color lineBoxColor(125, 173, 217, 128);
1013
1014     for (size_t i = 0; i < lineBoxQuads.size(); ++i)
1015         drawOutlinedQuad(context, lineBoxQuads[i], lineBoxColor);
1016 }
1017
1018 static inline void convertFromFrameToMainFrame(Frame* frame, IntRect& rect)
1019 {
1020     rect = frame->page()->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(rect));
1021 }
1022
1023 static inline IntSize frameToMainFrameOffset(Frame* frame)
1024 {
1025     IntPoint mainFramePoint = frame->page()->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(IntPoint()));
1026     return mainFramePoint - IntPoint();
1027 }
1028
1029 void InspectorAgent::drawNodeHighlight(GraphicsContext& context) const
1030 {
1031     if (!m_highlightedNode)
1032         return;
1033
1034     RenderObject* renderer = m_highlightedNode->renderer();
1035     Frame* containingFrame = m_highlightedNode->document()->frame();
1036     if (!renderer || !containingFrame)
1037         return;
1038
1039     IntSize mainFrameOffset = frameToMainFrameOffset(containingFrame);
1040     IntRect boundingBox = renderer->absoluteBoundingBoxRect(true);
1041     boundingBox.move(mainFrameOffset);
1042
1043     IntRect titleReferenceBox = boundingBox;
1044
1045     ASSERT(m_inspectedPage);
1046
1047     FrameView* view = m_inspectedPage->mainFrame()->view();
1048     FloatRect overlayRect = view->visibleContentRect();
1049     if (!overlayRect.contains(boundingBox) && !boundingBox.contains(enclosingIntRect(overlayRect)))
1050         overlayRect = view->visibleContentRect();
1051     context.translate(-overlayRect.x(), -overlayRect.y());
1052
1053     // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
1054 #if ENABLE(SVG)
1055     bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
1056 #else
1057     bool isSVGRenderer = false;
1058 #endif
1059
1060     if (renderer->isBox() && !isSVGRenderer) {
1061         RenderBox* renderBox = toRenderBox(renderer);
1062
1063         IntRect contentBox = renderBox->contentBoxRect();
1064
1065         IntRect paddingBox(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
1066                            contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
1067         IntRect borderBox(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
1068                           paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
1069         IntRect marginBox(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
1070                           borderBox.width() + renderBox->marginLeft() + renderBox->marginRight(), borderBox.height() + renderBox->marginTop() + renderBox->marginBottom());
1071
1072         titleReferenceBox = marginBox;
1073         titleReferenceBox.move(mainFrameOffset);
1074         titleReferenceBox.move(boundingBox.x(), boundingBox.y());
1075
1076         FloatQuad absContentQuad = renderBox->localToAbsoluteQuad(FloatRect(contentBox));
1077         FloatQuad absPaddingQuad = renderBox->localToAbsoluteQuad(FloatRect(paddingBox));
1078         FloatQuad absBorderQuad = renderBox->localToAbsoluteQuad(FloatRect(borderBox));
1079         FloatQuad absMarginQuad = renderBox->localToAbsoluteQuad(FloatRect(marginBox));
1080
1081         absContentQuad.move(mainFrameOffset);
1082         absPaddingQuad.move(mainFrameOffset);
1083         absBorderQuad.move(mainFrameOffset);
1084         absMarginQuad.move(mainFrameOffset);
1085
1086         drawHighlightForBox(context, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad);
1087     } else if (renderer->isRenderInline() || isSVGRenderer) {
1088         // FIXME: We should show margins/padding/border for inlines.
1089         Vector<FloatQuad> lineBoxQuads;
1090         renderer->absoluteQuads(lineBoxQuads);
1091         for (unsigned i = 0; i < lineBoxQuads.size(); ++i)
1092             lineBoxQuads[i] += mainFrameOffset;
1093
1094         drawHighlightForLineBoxesOrSVGRenderer(context, lineBoxQuads);
1095     }
1096
1097     // Draw node title if necessary.
1098
1099     if (!m_highlightedNode->isElementNode())
1100         return;
1101
1102     WebCore::Settings* settings = containingFrame->settings();
1103     drawElementTitle(context, titleReferenceBox, overlayRect, settings);
1104 }
1105
1106 void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& boundingBox, const FloatRect& overlayRect, WebCore::Settings* settings) const
1107 {
1108     static const int rectInflatePx = 4;
1109     static const int fontHeightPx = 12;
1110     static const int borderWidthPx = 1;
1111     static const Color tooltipBackgroundColor(255, 255, 194, 255);
1112     static const Color tooltipBorderColor(Color::black);
1113     static const Color tooltipFontColor(Color::black);
1114
1115     Element* element = static_cast<Element*>(m_highlightedNode.get());
1116     bool isXHTML = element->document()->isXHTMLDocument();
1117     String nodeTitle = isXHTML ? element->nodeName() : element->nodeName().lower();
1118     const AtomicString& idValue = element->getIdAttribute();
1119     if (!idValue.isNull() && !idValue.isEmpty()) {
1120         nodeTitle += "#";
1121         nodeTitle += idValue;
1122     }
1123     if (element->hasClass() && element->isStyledElement()) {
1124         const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
1125         size_t classNameCount = classNamesString.size();
1126         if (classNameCount) {
1127             HashSet<AtomicString> usedClassNames;
1128             for (size_t i = 0; i < classNameCount; ++i) {
1129                 const AtomicString& className = classNamesString[i];
1130                 if (usedClassNames.contains(className))
1131                     continue;
1132                 usedClassNames.add(className);
1133                 nodeTitle += ".";
1134                 nodeTitle += className;
1135             }
1136         }
1137     }
1138
1139     Element* highlightedElement = m_highlightedNode->isElementNode() ? static_cast<Element*>(m_highlightedNode.get()) : 0;
1140     nodeTitle += " [";
1141     nodeTitle += String::number(highlightedElement ? highlightedElement->offsetWidth() : boundingBox.width());
1142     nodeTitle.append(static_cast<UChar>(0x00D7)); // &times;
1143     nodeTitle += String::number(highlightedElement ? highlightedElement->offsetHeight() : boundingBox.height());
1144     nodeTitle += "]";
1145
1146     FontDescription desc;
1147     FontFamily family;
1148     family.setFamily(settings->fixedFontFamily());
1149     desc.setFamily(family);
1150     desc.setComputedSize(fontHeightPx);
1151     Font font = Font(desc, 0, 0);
1152     font.update(0);
1153
1154     TextRun nodeTitleRun(nodeTitle);
1155     IntPoint titleBasePoint = IntPoint(boundingBox.x(), boundingBox.maxY() - 1);
1156     titleBasePoint.move(rectInflatePx, rectInflatePx);
1157     IntRect titleRect = enclosingIntRect(font.selectionRectForText(nodeTitleRun, titleBasePoint, fontHeightPx));
1158     titleRect.inflate(rectInflatePx);
1159
1160     // The initial offsets needed to compensate for a 1px-thick border stroke (which is not a part of the rectangle).
1161     int dx = -borderWidthPx;
1162     int dy = borderWidthPx;
1163
1164     // If the tip sticks beyond the right of overlayRect, right-align the tip with the said boundary.
1165     if (titleRect.maxX() > overlayRect.maxX())
1166         dx = overlayRect.maxX() - titleRect.maxX();
1167
1168     // If the tip sticks beyond the left of overlayRect, left-align the tip with the said boundary.
1169     if (titleRect.x() + dx < overlayRect.x())
1170         dx = overlayRect.x() - titleRect.x() - borderWidthPx;
1171
1172     // If the tip sticks beyond the bottom of overlayRect, show the tip at top of bounding box.
1173     if (titleRect.maxY() > overlayRect.maxY()) {
1174         dy = boundingBox.y() - titleRect.maxY() - borderWidthPx;
1175         // If the tip still sticks beyond the bottom of overlayRect, bottom-align the tip with the said boundary.
1176         if (titleRect.maxY() + dy > overlayRect.maxY())
1177             dy = overlayRect.maxY() - titleRect.maxY();
1178     }
1179
1180     // If the tip sticks beyond the top of overlayRect, show the tip at top of overlayRect.
1181     if (titleRect.y() + dy < overlayRect.y())
1182         dy = overlayRect.y() - titleRect.y() + borderWidthPx;
1183
1184     titleRect.move(dx, dy);
1185     context.setStrokeColor(tooltipBorderColor, ColorSpaceDeviceRGB);
1186     context.setStrokeThickness(borderWidthPx);
1187     context.setFillColor(tooltipBackgroundColor, ColorSpaceDeviceRGB);
1188     context.drawRect(titleRect);
1189     context.setFillColor(tooltipFontColor, ColorSpaceDeviceRGB);
1190     context.drawText(font, nodeTitleRun, IntPoint(titleRect.x() + rectInflatePx, titleRect.y() + font.fontMetrics().height()));
1191 }
1192
1193 void InspectorAgent::openInInspectedWindow(const String& url)
1194 {
1195     Frame* mainFrame = m_inspectedPage->mainFrame();
1196
1197     FrameLoadRequest request(mainFrame->document()->securityOrigin(), ResourceRequest(), "_blank");
1198
1199     bool created;
1200     WindowFeatures windowFeatures;
1201     Frame* newFrame = WebCore::createWindow(mainFrame, mainFrame, request, windowFeatures, created);
1202     if (!newFrame)
1203         return;
1204
1205     UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
1206     newFrame->loader()->setOpener(mainFrame);
1207     newFrame->page()->setOpenedByDOM();
1208     newFrame->loader()->changeLocation(mainFrame->document()->securityOrigin(), newFrame->loader()->completeURL(url), "", false, false);
1209 }
1210
1211 void InspectorAgent::addScriptToEvaluateOnLoad(const String& source)
1212 {
1213     m_scriptsToEvaluateOnLoad.append(source);
1214 }
1215
1216 void InspectorAgent::removeAllScriptsToEvaluateOnLoad()
1217 {
1218     m_scriptsToEvaluateOnLoad.clear();
1219 }
1220
1221 void InspectorAgent::setInspectorExtensionAPI(const String& source)
1222 {
1223     m_inspectorExtensionAPI = source;
1224 }
1225
1226 KURL InspectorAgent::inspectedURL() const
1227 {
1228     return m_inspectedPage->mainFrame()->document()->url();
1229 }
1230
1231 KURL InspectorAgent::inspectedURLWithoutFragment() const
1232 {
1233     KURL url = inspectedURL();
1234     url.removeFragmentIdentifier();
1235     return url;
1236 }
1237
1238 void InspectorAgent::reloadPage(bool ignoreCache)
1239 {
1240     m_inspectedPage->mainFrame()->loader()->reload(ignoreCache);
1241 }
1242
1243 bool InspectorAgent::enabled() const
1244 {
1245     if (!m_inspectedPage)
1246         return false;
1247     return m_inspectedPage->settings()->developerExtrasEnabled();
1248 }
1249
1250 void InspectorAgent::showConsole()
1251 {
1252     showPanel(consolePanelName);
1253 }
1254
1255 void InspectorAgent::showPanel(const String& panel)
1256 {
1257     if (!m_frontend) {
1258         m_showPanelAfterVisible = panel;
1259         return;
1260     }
1261     m_frontend->showPanel(panel);
1262 }
1263
1264 } // namespace WebCore
1265
1266 #endif // ENABLE(INSPECTOR)