• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef InspectorController_h
30 #define InspectorController_h
31 
32 #include "Console.h"
33 #include "Cookie.h"
34 #include "InspectorDOMAgent.h"
35 #include "PlatformString.h"
36 #include "ScriptArray.h"
37 #include "ScriptObject.h"
38 #include "ScriptProfile.h"
39 #include "ScriptState.h"
40 #include "ScriptValue.h"
41 #include "StringHash.h"
42 #include "Timer.h"
43 
44 #include <wtf/HashMap.h>
45 #include <wtf/HashSet.h>
46 #include <wtf/ListHashSet.h>
47 #include <wtf/RefCounted.h>
48 #include <wtf/Vector.h>
49 
50 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
51 #include "JavaScriptDebugListener.h"
52 
53 namespace JSC {
54 class UString;
55 }
56 #endif
57 
58 namespace WebCore {
59 
60 class CachedResource;
61 class Database;
62 class Document;
63 class DocumentLoader;
64 class Element;
65 class GraphicsContext;
66 class HitTestResult;
67 class InjectedScript;
68 class InjectedScriptHost;
69 class InspectorBackend;
70 class InspectorClient;
71 class InspectorFrontend;
72 class InspectorFrontendHost;
73 class InspectorTimelineAgent;
74 class JavaScriptCallFrame;
75 class KURL;
76 class Node;
77 class Page;
78 class ResourceRequest;
79 class ResourceResponse;
80 class ResourceError;
81 class ScriptCallStack;
82 class ScriptString;
83 class SharedBuffer;
84 class Storage;
85 class StorageArea;
86 
87 class ConsoleMessage;
88 class InspectorDatabaseResource;
89 class InspectorDOMStorageResource;
90 class InspectorResource;
91 
92 class InspectorController
93 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
94                           : JavaScriptDebugListener, public Noncopyable
95 #else
96                           : public Noncopyable
97 #endif
98                                                     {
99 public:
100     typedef HashMap<unsigned long, RefPtr<InspectorResource> > ResourcesMap;
101     typedef HashMap<RefPtr<Frame>, ResourcesMap*> FrameResourcesMap;
102     typedef HashMap<int, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
103     typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
104 
105     typedef enum {
106         CurrentPanel,
107         ConsolePanel,
108         ElementsPanel,
109         ResourcesPanel,
110         ScriptsPanel,
111         TimelinePanel,
112         ProfilesPanel,
113         StoragePanel
114     } SpecialPanels;
115 
116     InspectorController(Page*, InspectorClient*);
117     ~InspectorController();
118 
inspectorBackend()119     InspectorBackend* inspectorBackend() { return m_inspectorBackend.get(); }
inspectorFrontendHost()120     InspectorFrontendHost* inspectorFrontendHost() { return m_inspectorFrontendHost.get(); }
injectedScriptHost()121     InjectedScriptHost* injectedScriptHost() { return m_injectedScriptHost.get(); }
122 
123     void inspectedPageDestroyed();
pageDestroyed()124     void pageDestroyed() { m_page = 0; }
125 
126     bool enabled() const;
127 
inspectedPage()128     Page* inspectedPage() const { return m_inspectedPage; }
129 
130     String setting(const String& key) const;
131     void setSetting(const String& key, const String& value);
132 
133     void inspect(Node*);
134     void highlight(Node*);
135     void hideHighlight();
136 
137     void show();
138     void showPanel(SpecialPanels);
139     void close();
140 
141     bool windowVisible();
142     void setWindowVisible(bool visible = true, bool attached = false);
143 
144     void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*);
145     void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
146     void clearConsoleMessages();
consoleMessages()147     const Vector<ConsoleMessage*>& consoleMessages() const { return m_consoleMessages; }
148 
149     void attachWindow();
150     void detachWindow();
151 
152     void toggleSearchForNodeInPage();
searchingForNodeInPage()153     bool searchingForNodeInPage() const { return m_searchingForNode; }
154     void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
155     void handleMousePressOnNode(Node*);
156 
157     void inspectedWindowScriptObjectCleared(Frame*);
158     void windowScriptObjectAvailable();
159 
160     void setFrontendProxyObject(ScriptState* state, ScriptObject webInspectorObj, ScriptObject injectedScriptObj = ScriptObject());
frontendScriptState()161     ScriptState* frontendScriptState() const { return m_frontendScriptState; }
162 
163     void populateScriptObjects();
164     void resetScriptObjects();
165 
166     void didCommitLoad(DocumentLoader*);
167     void frameDetachedFromParent(Frame*);
168 
169     void didLoadResourceFromMemoryCache(DocumentLoader*, const CachedResource*);
170 
171     void identifierForInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&);
172     void willSendRequest(unsigned long identifier, const ResourceRequest&, const ResourceResponse& redirectResponse);
173     void didReceiveResponse(unsigned long identifier, const ResourceResponse&);
174     void didReceiveContentLength(unsigned long identifier, int lengthReceived);
175     void didFinishLoading(unsigned long identifier);
176     void didFailLoading(unsigned long identifier, const ResourceError&);
177     void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString);
178     void scriptImported(unsigned long identifier, const String& sourceString);
179 
180     void enableResourceTracking(bool always = false, bool reload = true);
181     void disableResourceTracking(bool always = false);
resourceTrackingEnabled()182     bool resourceTrackingEnabled() const { return m_resourceTrackingEnabled; }
183     void ensureResourceTrackingSettingsLoaded();
184 
185     void startTimelineProfiler();
186     void stopTimelineProfiler();
timelineAgent()187     InspectorTimelineAgent* timelineAgent() { return m_timelineAgent.get(); }
188 
189     void mainResourceFiredLoadEvent(DocumentLoader*, const KURL&);
190     void mainResourceFiredDOMContentEvent(DocumentLoader*, const KURL&);
191 
192     void didInsertDOMNode(Node*);
193     void didRemoveDOMNode(Node*);
194     void didModifyDOMAttr(Element*);
195 
196     void getCookies(long callId);
197 
198 #if ENABLE(DATABASE)
199     void didOpenDatabase(Database*, const String& domain, const String& name, const String& version);
200 #endif
201 #if ENABLE(DOM_STORAGE)
202     void didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame);
203     void selectDOMStorage(Storage* storage);
204     void getDOMStorageEntries(int callId, int storageId);
205     void setDOMStorageItem(long callId, long storageId, const String& key, const String& value);
206     void removeDOMStorageItem(long callId, long storageId, const String& key);
207 #endif
208 
resources()209     const ResourcesMap& resources() const { return m_resources; }
210 
211     void drawNodeHighlight(GraphicsContext&) const;
212 
213     void count(const String& title, unsigned lineNumber, const String& sourceID);
214 
215     void startTiming(const String& title);
216     bool stopTiming(const String& title, double& elapsed);
217 
218     void startGroup(MessageSource source, ScriptCallStack* callFrame);
219     void endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL);
220 
221     void markTimeline(const String& message);
222 
223 #if ENABLE(JAVASCRIPT_DEBUGGER)
224     void addProfile(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
225     void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
226     void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
227 
isRecordingUserInitiatedProfile()228     bool isRecordingUserInitiatedProfile() const { return m_recordingUserInitiatedProfile; }
229 
230     String getCurrentUserInitiatedProfileName(bool incrementProfileNumber);
231     void startUserInitiatedProfiling(Timer<InspectorController>* = 0);
232     void stopUserInitiatedProfiling();
233 
234     void enableProfiler(bool always = false, bool skipRecompile = false);
235     void disableProfiler(bool always = false);
profilerEnabled()236     bool profilerEnabled() const { return enabled() && m_profilerEnabled; }
237 #endif
238 
239 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
240     void enableDebugger();
241     void disableDebugger(bool always = false);
debuggerEnabled()242     bool debuggerEnabled() const { return m_debuggerEnabled; }
243 
244     void resumeDebugger();
245 
246     virtual void didParseSource(JSC::ExecState*, const JSC::SourceCode&);
247     virtual void failedToParseSource(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMessage);
248     virtual void didPause();
249     virtual void didContinue();
250 #endif
251 
252     void evaluateForTestInFrontend(long callId, const String& script);
253 
254     InjectedScript injectedScriptForNodeId(long id);
255 
256 private:
257     static const char* const FrontendSettingsSettingName;
258     friend class InspectorBackend;
259     friend class InspectorFrontendHost;
260     friend class InjectedScriptHost;
261     // Following are used from InspectorBackend and internally.
262     void scriptObjectReady();
263     void moveWindowBy(float x, float y) const;
264     void setAttachedWindow(bool);
265     void setAttachedWindowHeight(unsigned height);
266     void storeLastActivePanel(const String& panelName);
267     void closeWindow();
domAgent()268     InspectorDOMAgent* domAgent() { return m_domAgent.get(); }
269     void releaseDOMAgent();
270 
271     void deleteCookie(const String& cookieName, const String& domain);
272 
273 #if ENABLE(JAVASCRIPT_DEBUGGER)
274     typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
275 
276     void startUserInitiatedProfilingSoon();
277     void toggleRecordButton(bool);
278     void enableDebuggerFromFrontend(bool always);
279     void getProfileHeaders(long callId);
280     void getProfile(long callId, unsigned uid);
281     ScriptObject createProfileHeader(const ScriptProfile& profile);
282 #endif
283 #if ENABLE(DATABASE)
284     void selectDatabase(Database* database);
285     Database* databaseForId(int databaseId);
286 #endif
287 #if ENABLE(DOM_STORAGE)
288     InspectorDOMStorageResource* getDOMStorageResourceForId(int storageId);
289 #endif
290 
291     ScriptObject buildObjectForCookie(const Cookie&);
292     ScriptArray buildArrayForCookies(ListHashSet<Cookie>&);
293 
294     void focusNode();
295 
296     void addConsoleMessage(ScriptState*, ConsoleMessage*);
297 
298     void addResource(InspectorResource*);
299     void removeResource(InspectorResource*);
300     InspectorResource* getTrackedResource(unsigned long identifier);
301 
302     void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0);
removeAllResources(ResourcesMap * map)303     void removeAllResources(ResourcesMap* map) { pruneResources(map); }
304 
305     void showWindow();
306 
307     bool isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl);
308 
309     SpecialPanels specialPanelForJSName(const String& panelName);
310 
311     void didEvaluateForTestInFrontend(long callId, const String& jsonResult);
312 
313     Page* m_inspectedPage;
314     InspectorClient* m_client;
315     OwnPtr<InspectorFrontend> m_frontend;
316     RefPtr<InspectorDOMAgent> m_domAgent;
317     OwnPtr<InspectorTimelineAgent> m_timelineAgent;
318     Page* m_page;
319     RefPtr<Node> m_nodeToFocus;
320     RefPtr<InspectorResource> m_mainResource;
321     ResourcesMap m_resources;
322     HashSet<String> m_knownResources;
323     FrameResourcesMap m_frameResources;
324     Vector<ConsoleMessage*> m_consoleMessages;
325     unsigned m_expiredConsoleMessageCount;
326     HashMap<String, double> m_times;
327     HashMap<String, unsigned> m_counts;
328 #if ENABLE(DATABASE)
329     DatabaseResourcesMap m_databaseResources;
330 #endif
331 #if ENABLE(DOM_STORAGE)
332     DOMStorageResourcesMap m_domStorageResources;
333 #endif
334     ScriptState* m_frontendScriptState;
335     bool m_windowVisible;
336     SpecialPanels m_showAfterVisible;
337     RefPtr<Node> m_highlightedNode;
338     unsigned m_groupLevel;
339     bool m_searchingForNode;
340     ConsoleMessage* m_previousMessage;
341     bool m_resourceTrackingEnabled;
342     bool m_resourceTrackingSettingsLoaded;
343     RefPtr<InspectorBackend> m_inspectorBackend;
344     RefPtr<InspectorFrontendHost> m_inspectorFrontendHost;
345     RefPtr<InjectedScriptHost> m_injectedScriptHost;
346 
347     typedef HashMap<String, String> Settings;
348     mutable Settings m_settings;
349 
350     Vector<pair<long, String> > m_pendingEvaluateTestCommands;
351 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC)
352     bool m_debuggerEnabled;
353     bool m_attachDebuggerWhenShown;
354 #endif
355 #if ENABLE(JAVASCRIPT_DEBUGGER)
356     bool m_profilerEnabled;
357     bool m_recordingUserInitiatedProfile;
358     int m_currentUserInitiatedProfileNumber;
359     unsigned m_nextUserInitiatedProfileNumber;
360     Timer<InspectorController> m_startProfiling;
361     ProfilesMap m_profiles;
362 #endif
363 };
364 
didInsertDOMNode(Node * node)365 inline void InspectorController::didInsertDOMNode(Node* node)
366 {
367     if (m_domAgent)
368         m_domAgent->didInsertDOMNode(node);
369 }
370 
didRemoveDOMNode(Node * node)371 inline void InspectorController::didRemoveDOMNode(Node* node)
372 {
373     if (m_domAgent)
374         m_domAgent->didRemoveDOMNode(node);
375 }
376 
didModifyDOMAttr(Element * element)377 inline void InspectorController::didModifyDOMAttr(Element* element)
378 {
379     if (m_domAgent)
380         m_domAgent->didModifyDOMAttr(element);
381 }
382 
383 } // namespace WebCore
384 
385 #endif // !defined(InspectorController_h)
386