95590999e579c1a591cf0d3a753f6e019eb651de
[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_requiredPanel.isEmpty()) {
442         m_frontend->showPanel(m_requiredPanel);
443         m_requiredPanel = "";
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     if (!enabled())
856         return;
857     m_profilerAgent->stopUserInitiatedProfiling();
858     m_state->setBoolean(InspectorAgentState::userInitiatedProfiling, false);
859     showPanel(profilesPanelName);
860 }
861
862 bool InspectorAgent::profilerEnabled() const
863 {
864     return enabled() && m_profilerAgent->enabled();
865 }
866
867 void InspectorAgent::enableProfiler()
868 {
869     if (profilerEnabled())
870         return;
871     m_state->setBoolean(InspectorAgentState::profilerEnabled, true);
872     m_profilerAgent->enable(false);
873 }
874
875 void InspectorAgent::disableProfiler()
876 {
877     m_state->setBoolean(InspectorAgentState::profilerEnabled, false);
878     m_profilerAgent->disable();
879 }
880 #endif
881
882 #if ENABLE(JAVASCRIPT_DEBUGGER)
883 void InspectorAgent::showAndEnableDebugger()
884 {
885     if (!enabled())
886         return;
887
888     if (debuggerEnabled())
889         return;
890
891     if (!m_frontend) {
892         m_state->setBoolean(InspectorAgentState::debuggerEnabled, true);
893         showPanel(scriptsPanelName);
894     } else
895         enableDebugger(true);
896 }
897
898 void InspectorAgent::enableDebugger(bool eraseStickyBreakpoints)
899 {
900     if (debuggerEnabled())
901         return;
902     m_state->setBoolean(InspectorAgentState::debuggerEnabled, true);
903     ASSERT(m_inspectedPage);
904
905     m_debuggerAgent = InspectorDebuggerAgent::create(this, m_frontend, eraseStickyBreakpoints);
906     m_browserDebuggerAgent = InspectorBrowserDebuggerAgent::create(this, eraseStickyBreakpoints);
907
908     m_frontend->debuggerWasEnabled();
909 }
910
911 void InspectorAgent::disableDebugger()
912 {
913     if (!enabled())
914         return;
915     ASSERT(m_inspectedPage);
916     m_debuggerAgent.clear();
917     m_browserDebuggerAgent.clear();
918
919     if (m_frontend) {
920         m_frontend->debuggerWasDisabled();
921         m_state->setBoolean(InspectorAgentState::debuggerEnabled, false);
922     }
923 }
924
925 void InspectorAgent::resume()
926 {
927     if (m_debuggerAgent)
928         m_debuggerAgent->resume();
929 }
930 #endif
931
932 void InspectorAgent::evaluateForTestInFrontend(long callId, const String& script)
933 {
934     if (m_frontend)
935         m_frontend->evaluateForTestInFrontend(callId, script);
936     else
937         m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
938 }
939
940 void InspectorAgent::didEvaluateForTestInFrontend(long callId, const String& jsonResult)
941 {
942     ScriptState* scriptState = scriptStateFromPage(debuggerWorld(), m_inspectedPage);
943     ScriptObject window;
944     ScriptGlobalObject::get(scriptState, "window", window);
945     ScriptFunctionCall function(window, "didEvaluateForTestInFrontend");
946     function.appendArgument(callId);
947     function.appendArgument(jsonResult);
948     function.call();
949 }
950
951 static Path quadToPath(const FloatQuad& quad)
952 {
953     Path quadPath;
954     quadPath.moveTo(quad.p1());
955     quadPath.addLineTo(quad.p2());
956     quadPath.addLineTo(quad.p3());
957     quadPath.addLineTo(quad.p4());
958     quadPath.closeSubpath();
959     return quadPath;
960 }
961
962 static void drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, const Color& fillColor)
963 {
964     static const int outlineThickness = 2;
965     static const Color outlineColor(62, 86, 180, 228);
966
967     Path quadPath = quadToPath(quad);
968
969     // Clip out the quad, then draw with a 2px stroke to get a pixel
970     // of outline (because inflating a quad is hard)
971     {
972         context.save();
973         context.clipOut(quadPath);
974
975         context.setStrokeThickness(outlineThickness);
976         context.setStrokeColor(outlineColor, ColorSpaceDeviceRGB);
977         context.strokePath(quadPath);
978
979         context.restore();
980     }
981
982     // Now do the fill
983     context.setFillColor(fillColor, ColorSpaceDeviceRGB);
984     context.fillPath(quadPath);
985 }
986
987 static void drawOutlinedQuadWithClip(GraphicsContext& context, const FloatQuad& quad, const FloatQuad& clipQuad, const Color& fillColor)
988 {
989     context.save();
990     Path clipQuadPath = quadToPath(clipQuad);
991     context.clipOut(clipQuadPath);
992     drawOutlinedQuad(context, quad, fillColor);
993     context.restore();
994 }
995
996 static void drawHighlightForBox(GraphicsContext& context, const FloatQuad& contentQuad, const FloatQuad& paddingQuad, const FloatQuad& borderQuad, const FloatQuad& marginQuad)
997 {
998     static const Color contentBoxColor(125, 173, 217, 128);
999     static const Color paddingBoxColor(125, 173, 217, 160);
1000     static const Color borderBoxColor(125, 173, 217, 192);
1001     static const Color marginBoxColor(125, 173, 217, 228);
1002
1003     if (marginQuad != borderQuad)
1004         drawOutlinedQuadWithClip(context, marginQuad, borderQuad, marginBoxColor);
1005     if (borderQuad != paddingQuad)
1006         drawOutlinedQuadWithClip(context, borderQuad, paddingQuad, borderBoxColor);
1007     if (paddingQuad != contentQuad)
1008         drawOutlinedQuadWithClip(context, paddingQuad, contentQuad, paddingBoxColor);
1009
1010     drawOutlinedQuad(context, contentQuad, contentBoxColor);
1011 }
1012
1013 static void drawHighlightForLineBoxesOrSVGRenderer(GraphicsContext& context, const Vector<FloatQuad>& lineBoxQuads)
1014 {
1015     static const Color lineBoxColor(125, 173, 217, 128);
1016
1017     for (size_t i = 0; i < lineBoxQuads.size(); ++i)
1018         drawOutlinedQuad(context, lineBoxQuads[i], lineBoxColor);
1019 }
1020
1021 static inline void convertFromFrameToMainFrame(Frame* frame, IntRect& rect)
1022 {
1023     rect = frame->page()->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(rect));
1024 }
1025
1026 static inline IntSize frameToMainFrameOffset(Frame* frame)
1027 {
1028     IntPoint mainFramePoint = frame->page()->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(IntPoint()));
1029     return mainFramePoint - IntPoint();
1030 }
1031
1032 void InspectorAgent::drawNodeHighlight(GraphicsContext& context) const
1033 {
1034     if (!m_highlightedNode)
1035         return;
1036
1037     RenderObject* renderer = m_highlightedNode->renderer();
1038     Frame* containingFrame = m_highlightedNode->document()->frame();
1039     if (!renderer || !containingFrame)
1040         return;
1041
1042     IntSize mainFrameOffset = frameToMainFrameOffset(containingFrame);
1043     IntRect boundingBox = renderer->absoluteBoundingBoxRect(true);
1044     boundingBox.move(mainFrameOffset);
1045
1046     IntRect titleReferenceBox = boundingBox;
1047
1048     ASSERT(m_inspectedPage);
1049
1050     FrameView* view = m_inspectedPage->mainFrame()->view();
1051     FloatRect overlayRect = view->visibleContentRect();
1052     if (!overlayRect.contains(boundingBox) && !boundingBox.contains(enclosingIntRect(overlayRect)))
1053         overlayRect = view->visibleContentRect();
1054     context.translate(-overlayRect.x(), -overlayRect.y());
1055
1056     // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads().
1057 #if ENABLE(SVG)
1058     bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot();
1059 #else
1060     bool isSVGRenderer = false;
1061 #endif
1062
1063     if (renderer->isBox() && !isSVGRenderer) {
1064         RenderBox* renderBox = toRenderBox(renderer);
1065
1066         IntRect contentBox = renderBox->contentBoxRect();
1067
1068         IntRect paddingBox(contentBox.x() - renderBox->paddingLeft(), contentBox.y() - renderBox->paddingTop(),
1069                            contentBox.width() + renderBox->paddingLeft() + renderBox->paddingRight(), contentBox.height() + renderBox->paddingTop() + renderBox->paddingBottom());
1070         IntRect borderBox(paddingBox.x() - renderBox->borderLeft(), paddingBox.y() - renderBox->borderTop(),
1071                           paddingBox.width() + renderBox->borderLeft() + renderBox->borderRight(), paddingBox.height() + renderBox->borderTop() + renderBox->borderBottom());
1072         IntRect marginBox(borderBox.x() - renderBox->marginLeft(), borderBox.y() - renderBox->marginTop(),
1073                           borderBox.width() + renderBox->marginLeft() + renderBox->marginRight(), borderBox.height() + renderBox->marginTop() + renderBox->marginBottom());
1074
1075         titleReferenceBox = marginBox;
1076         titleReferenceBox.move(mainFrameOffset);
1077         titleReferenceBox.move(boundingBox.x(), boundingBox.y());
1078
1079         FloatQuad absContentQuad = renderBox->localToAbsoluteQuad(FloatRect(contentBox));
1080         FloatQuad absPaddingQuad = renderBox->localToAbsoluteQuad(FloatRect(paddingBox));
1081         FloatQuad absBorderQuad = renderBox->localToAbsoluteQuad(FloatRect(borderBox));
1082         FloatQuad absMarginQuad = renderBox->localToAbsoluteQuad(FloatRect(marginBox));
1083
1084         absContentQuad.move(mainFrameOffset);
1085         absPaddingQuad.move(mainFrameOffset);
1086         absBorderQuad.move(mainFrameOffset);
1087         absMarginQuad.move(mainFrameOffset);
1088
1089         drawHighlightForBox(context, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad);
1090     } else if (renderer->isRenderInline() || isSVGRenderer) {
1091         // FIXME: We should show margins/padding/border for inlines.
1092         Vector<FloatQuad> lineBoxQuads;
1093         renderer->absoluteQuads(lineBoxQuads);
1094         for (unsigned i = 0; i < lineBoxQuads.size(); ++i)
1095             lineBoxQuads[i] += mainFrameOffset;
1096
1097         drawHighlightForLineBoxesOrSVGRenderer(context, lineBoxQuads);
1098     }
1099
1100     // Draw node title if necessary.
1101
1102     if (!m_highlightedNode->isElementNode())
1103         return;
1104
1105     WebCore::Settings* settings = containingFrame->settings();
1106     drawElementTitle(context, titleReferenceBox, overlayRect, settings);
1107 }
1108
1109 void InspectorAgent::drawElementTitle(GraphicsContext& context, const IntRect& boundingBox, const FloatRect& overlayRect, WebCore::Settings* settings) const
1110 {
1111     static const int rectInflatePx = 4;
1112     static const int fontHeightPx = 12;
1113     static const int borderWidthPx = 1;
1114     static const Color tooltipBackgroundColor(255, 255, 194, 255);
1115     static const Color tooltipBorderColor(Color::black);
1116     static const Color tooltipFontColor(Color::black);
1117
1118     Element* element = static_cast<Element*>(m_highlightedNode.get());
1119     bool isXHTML = element->document()->isXHTMLDocument();
1120     String nodeTitle = isXHTML ? element->nodeName() : element->nodeName().lower();
1121     const AtomicString& idValue = element->getIdAttribute();
1122     if (!idValue.isNull() && !idValue.isEmpty()) {
1123         nodeTitle += "#";
1124         nodeTitle += idValue;
1125     }
1126     if (element->hasClass() && element->isStyledElement()) {
1127         const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
1128         size_t classNameCount = classNamesString.size();
1129         if (classNameCount) {
1130             HashSet<AtomicString> usedClassNames;
1131             for (size_t i = 0; i < classNameCount; ++i) {
1132                 const AtomicString& className = classNamesString[i];
1133                 if (usedClassNames.contains(className))
1134                     continue;
1135                 usedClassNames.add(className);
1136                 nodeTitle += ".";
1137                 nodeTitle += className;
1138             }
1139         }
1140     }
1141
1142     Element* highlightedElement = m_highlightedNode->isElementNode() ? static_cast<Element*>(m_highlightedNode.get()) : 0;
1143     nodeTitle += " [";
1144     nodeTitle += String::number(highlightedElement ? highlightedElement->offsetWidth() : boundingBox.width());
1145     nodeTitle.append(static_cast<UChar>(0x00D7)); // &times;
1146     nodeTitle += String::number(highlightedElement ? highlightedElement->offsetHeight() : boundingBox.height());
1147     nodeTitle += "]";
1148
1149     FontDescription desc;
1150     FontFamily family;
1151     family.setFamily(settings->fixedFontFamily());
1152     desc.setFamily(family);
1153     desc.setComputedSize(fontHeightPx);
1154     Font font = Font(desc, 0, 0);
1155     font.update(0);
1156
1157     TextRun nodeTitleRun(nodeTitle);
1158     IntPoint titleBasePoint = IntPoint(boundingBox.x(), boundingBox.maxY() - 1);
1159     titleBasePoint.move(rectInflatePx, rectInflatePx);
1160     IntRect titleRect = enclosingIntRect(font.selectionRectForText(nodeTitleRun, titleBasePoint, fontHeightPx));
1161     titleRect.inflate(rectInflatePx);
1162
1163     // The initial offsets needed to compensate for a 1px-thick border stroke (which is not a part of the rectangle).
1164     int dx = -borderWidthPx;
1165     int dy = borderWidthPx;
1166
1167     // If the tip sticks beyond the right of overlayRect, right-align the tip with the said boundary.
1168     if (titleRect.maxX() > overlayRect.maxX())
1169         dx = overlayRect.maxX() - titleRect.maxX();
1170
1171     // If the tip sticks beyond the left of overlayRect, left-align the tip with the said boundary.
1172     if (titleRect.x() + dx < overlayRect.x())
1173         dx = overlayRect.x() - titleRect.x() - borderWidthPx;
1174
1175     // If the tip sticks beyond the bottom of overlayRect, show the tip at top of bounding box.
1176     if (titleRect.maxY() > overlayRect.maxY()) {
1177         dy = boundingBox.y() - titleRect.maxY() - borderWidthPx;
1178         // If the tip still sticks beyond the bottom of overlayRect, bottom-align the tip with the said boundary.
1179         if (titleRect.maxY() + dy > overlayRect.maxY())
1180             dy = overlayRect.maxY() - titleRect.maxY();
1181     }
1182
1183     // If the tip sticks beyond the top of overlayRect, show the tip at top of overlayRect.
1184     if (titleRect.y() + dy < overlayRect.y())
1185         dy = overlayRect.y() - titleRect.y() + borderWidthPx;
1186
1187     titleRect.move(dx, dy);
1188     context.setStrokeColor(tooltipBorderColor, ColorSpaceDeviceRGB);
1189     context.setStrokeThickness(borderWidthPx);
1190     context.setFillColor(tooltipBackgroundColor, ColorSpaceDeviceRGB);
1191     context.drawRect(titleRect);
1192     context.setFillColor(tooltipFontColor, ColorSpaceDeviceRGB);
1193     context.drawText(font, nodeTitleRun, IntPoint(titleRect.x() + rectInflatePx, titleRect.y() + font.fontMetrics().height()));
1194 }
1195
1196 void InspectorAgent::openInInspectedWindow(const String& url)
1197 {
1198     Frame* mainFrame = m_inspectedPage->mainFrame();
1199
1200     FrameLoadRequest request(mainFrame->document()->securityOrigin(), ResourceRequest(), "_blank");
1201
1202     bool created;
1203     WindowFeatures windowFeatures;
1204     Frame* newFrame = WebCore::createWindow(mainFrame, mainFrame, request, windowFeatures, created);
1205     if (!newFrame)
1206         return;
1207
1208     UserGestureIndicator indicator(DefinitelyProcessingUserGesture);
1209     newFrame->loader()->setOpener(mainFrame);
1210     newFrame->page()->setOpenedByDOM();
1211     newFrame->loader()->changeLocation(mainFrame->document()->securityOrigin(), newFrame->loader()->completeURL(url), "", false, false);
1212 }
1213
1214 void InspectorAgent::addScriptToEvaluateOnLoad(const String& source)
1215 {
1216     m_scriptsToEvaluateOnLoad.append(source);
1217 }
1218
1219 void InspectorAgent::removeAllScriptsToEvaluateOnLoad()
1220 {
1221     m_scriptsToEvaluateOnLoad.clear();
1222 }
1223
1224 void InspectorAgent::setInspectorExtensionAPI(const String& source)
1225 {
1226     m_inspectorExtensionAPI = source;
1227 }
1228
1229 KURL InspectorAgent::inspectedURL() const
1230 {
1231     return m_inspectedPage->mainFrame()->document()->url();
1232 }
1233
1234 KURL InspectorAgent::inspectedURLWithoutFragment() const
1235 {
1236     KURL url = inspectedURL();
1237     url.removeFragmentIdentifier();
1238     return url;
1239 }
1240
1241 void InspectorAgent::reloadPage(bool ignoreCache)
1242 {
1243     m_inspectedPage->mainFrame()->loader()->reload(ignoreCache);
1244 }
1245
1246 bool InspectorAgent::enabled() const
1247 {
1248     if (!m_inspectedPage)
1249         return false;
1250     return m_inspectedPage->settings()->developerExtrasEnabled();
1251 }
1252
1253 void InspectorAgent::showConsole()
1254 {
1255     showPanel(consolePanelName);
1256 }
1257
1258 void InspectorAgent::showPanel(const String& panel)
1259 {
1260     if (!m_frontend) {
1261         m_requiredPanel = panel;
1262         return;
1263     }
1264     m_frontend->showPanel(panel);
1265 }
1266
1267 } // namespace WebCore
1268
1269 #endif // ENABLE(INSPECTOR)