1f416a006d3d5bf0d4b94778288b239d7012925c
[WebKit-https.git] / WebCore / inspector / InspectorController.h
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 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 "ScriptBreakpoint.h"
38 #include "ScriptObject.h"
39 #include "ScriptProfile.h"
40 #include "ScriptState.h"
41 #include "ScriptValue.h"
42 #include "StringHash.h"
43 #include "Timer.h"
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)
51 #include "ScriptDebugListener.h"
52 #endif
53
54 namespace WebCore {
55
56 class CachedResource;
57 class ConsoleMessage;
58 class Database;
59 class Document;
60 class DocumentLoader;
61 class Element;
62 class GraphicsContext;
63 class HitTestResult;
64 class InjectedScript;
65 class InjectedScriptHost;
66 class InspectorBackend;
67 class InspectorClient;
68 class InspectorCSSStore;
69 class InspectorDOMStorageResource;
70 class InspectorDatabaseResource;
71 class InspectorFrontend;
72 class InspectorFrontend2;
73 class InspectorFrontendClient;
74 class InspectorResource;
75 class InspectorTimelineAgent;
76 class InspectorValue;
77 class InspectorWorkerResource;
78 class KURL;
79 class Node;
80 class Page;
81 class ResourceRequest;
82 class ResourceResponse;
83 class ResourceError;
84 class ScriptCallStack;
85 class ScriptString;
86 class SharedBuffer;
87 class Storage;
88 class StorageArea;
89
90 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
91 class InspectorApplicationCacheAgent;
92 #endif
93
94 class InspectorController
95 #if ENABLE(JAVASCRIPT_DEBUGGER)
96                           : ScriptDebugListener, public Noncopyable
97 #else
98                           : public Noncopyable
99 #endif
100                                                     {
101 public:
102     typedef HashMap<unsigned long, RefPtr<InspectorResource> > ResourcesMap;
103     typedef HashMap<RefPtr<Frame>, ResourcesMap*> FrameResourcesMap;
104     typedef HashMap<int, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap;
105     typedef HashMap<int, RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesMap;
106
107     typedef enum {
108         AuditsPanel,
109         CurrentPanel,
110         ConsolePanel,
111         ElementsPanel,
112         ResourcesPanel,
113         ScriptsPanel,
114         TimelinePanel,
115         ProfilesPanel,
116         StoragePanel
117     } SpecialPanels;
118
119     InspectorController(Page*, InspectorClient*);
120     ~InspectorController();
121
122     InspectorBackend* inspectorBackend() { return m_inspectorBackend.get(); }
123     InjectedScriptHost* injectedScriptHost() { return m_injectedScriptHost.get(); }
124
125     void inspectedPageDestroyed();
126
127     bool enabled() const;
128
129     Page* inspectedPage() const { return m_inspectedPage; }
130
131     String setting(const String& key) const;
132     void setSetting(const String& key, const String& value);
133     void setSessionSettings(const String&);
134
135     void inspect(Node*);
136     void highlight(Node*);
137     void hideHighlight();
138
139     void show();
140     void showPanel(SpecialPanels);
141     void close();
142
143     // We are in transition from JS transport via webInspector to native
144     // transport via InspectorClient. After migration, webInspector parameter should
145     // be removed.
146     void connectFrontend(const ScriptObject& webInspector);
147     void disconnectFrontend();
148
149     void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*);
150     void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
151     void clearConsoleMessages();
152     const Vector<ConsoleMessage*>& consoleMessages() const { return m_consoleMessages; }
153
154     bool searchingForNodeInPage() const { return m_searchingForNode; }
155     void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
156     void handleMousePress();
157
158     void setInspectorFrontendClient(PassOwnPtr<InspectorFrontendClient> client);
159     bool hasInspectorFrontendClient() const { return m_inspectorFrontendClient; }
160
161     void inspectedWindowScriptObjectCleared(Frame*);
162
163     bool windowVisible();
164
165     void didCommitLoad(DocumentLoader*);
166     void frameDetachedFromParent(Frame*);
167     void didLoadResourceFromMemoryCache(DocumentLoader*, const CachedResource*);
168
169     void identifierForInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&);
170     void willSendRequest(unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse);
171     void didReceiveResponse(unsigned long identifier, const ResourceResponse&);
172     void didReceiveContentLength(unsigned long identifier, int lengthReceived);
173     void didFinishLoading(unsigned long identifier);
174     void didFailLoading(unsigned long identifier, const ResourceError&);
175     void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString, const String& url, const String& sendURL, unsigned sendLineNumber);
176     void scriptImported(unsigned long identifier, const String& sourceString);
177
178     void enableResourceTracking(bool always = false, bool reload = true);
179     void disableResourceTracking(bool always = false);
180     bool resourceTrackingEnabled() const { return m_resourceTrackingEnabled; }
181
182     void ensureSettingsLoaded();
183
184     void startTimelineProfiler();
185     void stopTimelineProfiler();
186     InspectorTimelineAgent* timelineAgent() { return m_timelineAgent.get(); }
187
188     void getCookies(long callId);
189     void deleteCookie(const String& cookieName, const String& domain);
190
191 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
192     InspectorApplicationCacheAgent* applicationCacheAgent() { return m_applicationCacheAgent.get(); }
193 #endif
194
195     void mainResourceFiredLoadEvent(DocumentLoader*, const KURL&);
196     void mainResourceFiredDOMContentEvent(DocumentLoader*, const KURL&);
197
198     void didInsertDOMNode(Node*);
199     void didRemoveDOMNode(Node*);
200     void didModifyDOMAttr(Element*);
201 #if ENABLE(WORKERS)
202     enum WorkerAction { WorkerCreated, WorkerDestroyed };
203
204     void postWorkerNotificationToFrontend(const InspectorWorkerResource&, WorkerAction);
205     void didCreateWorker(intptr_t, const String& url, bool isSharedWorker);
206     void didDestroyWorker(intptr_t);
207 #endif
208
209 #if ENABLE(DATABASE)
210     void didOpenDatabase(Database*, const String& domain, const String& name, const String& version);
211 #endif
212 #if ENABLE(DOM_STORAGE)
213     void didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame);
214     void selectDOMStorage(Storage* storage);
215     void getDOMStorageEntries(long callId, long storageId);
216     void setDOMStorageItem(long callId, long storageId, const String& key, const String& value);
217     void removeDOMStorageItem(long callId, long storageId, const String& key);
218 #endif
219
220     const ResourcesMap& resources() const { return m_resources; }
221     InspectorResource* resourceForURL(const String& url);
222     InspectorFrontend* inspectorFrontend() { return m_frontend.get(); }
223     InspectorFrontend2* inspectorFrontend2() { return m_frontend2.get(); }
224
225     void drawNodeHighlight(GraphicsContext&) const;
226
227     void count(const String& title, unsigned lineNumber, const String& sourceID);
228
229     void startTiming(const String& title);
230     bool stopTiming(const String& title, double& elapsed);
231
232     void startGroup(MessageSource source, ScriptCallStack* callFrame, bool collapsed = false);
233     void endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL);
234
235     void markTimeline(const String& message);
236
237 #if ENABLE(JAVASCRIPT_DEBUGGER)
238     void addProfile(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
239     void addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile>, unsigned lineNumber, const String& sourceURL);
240     void addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL);
241     void removeProfile(unsigned);
242     void clearProfiles();
243
244     bool isRecordingUserInitiatedProfile() const { return m_recordingUserInitiatedProfile; }
245
246     String getCurrentUserInitiatedProfileName(bool incrementProfileNumber);
247     void startUserInitiatedProfiling(Timer<InspectorController>* = 0);
248     void stopUserInitiatedProfiling();
249
250     void enableProfiler(bool always = false, bool skipRecompile = false);
251     void disableProfiler(bool always = false);
252     bool profilerEnabled() const { return enabled() && m_profilerEnabled; }
253
254     void takeHeapSnapshot();
255
256     void enableDebugger();
257     void disableDebugger(bool always = false);
258     bool debuggerEnabled() const { return m_debuggerEnabled; }
259
260     void editScriptSource(long callId, const String& sourceID, const String& newContent);
261     void getScriptSource(long callId, const String& sourceID);
262
263     void resumeDebugger();
264     PassRefPtr<SerializedScriptValue> currentCallFrames();
265
266     virtual void didParseSource(const String& sourceID, const String& url, const String& data, int firstLine, ScriptWorldType);
267     virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage);
268     virtual void didPause(ScriptState*);
269     virtual void didContinue();
270 #endif
271
272     void evaluateForTestInFrontend(long callId, const String& script);
273
274     InjectedScript injectedScriptForNodeId(long id);
275     void addScriptToEvaluateOnLoad(const String& source);
276     void removeAllScriptsToEvaluateOnLoad();
277
278     static const String& inspectorStartsAttachedSettingName();
279
280 private:
281     static const String& frontendSettingsSettingName();
282
283     friend class InspectorBackend;
284     friend class InjectedScriptHost;
285
286     void populateScriptObjects();
287     void unbindAllResources();
288
289     // Following are used from InspectorBackend and internally.
290     void setSearchingForNode(bool enabled);
291     void setMonitoringXHR(bool enabled);
292     void storeLastActivePanel(const String& panelName);
293     InspectorDOMAgent* domAgent() { return m_domAgent.get(); }
294     void releaseFrontendLifetimeAgents();
295
296 #if ENABLE(JAVASCRIPT_DEBUGGER)
297     void setBreakpoint(long callId, const String& sourceID, unsigned lineNumber, bool enabled, const String& condition);
298     void removeBreakpoint(const String& sourceID, unsigned lineNumber);
299
300     typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
301
302     void startUserInitiatedProfilingSoon();
303     void toggleRecordButton(bool);
304     void enableDebuggerFromFrontend(bool always);
305     void getProfileHeaders(long callId);
306     void getProfile(long callId, unsigned uid);
307     ScriptObject createProfileHeader(const ScriptProfile& profile);
308 #endif
309 #if ENABLE(DATABASE)
310     void selectDatabase(Database* database);
311     Database* databaseForId(long databaseId);
312 #endif
313 #if ENABLE(DOM_STORAGE)
314     InspectorDOMStorageResource* getDOMStorageResourceForId(long storageId);
315 #endif
316
317     ScriptObject buildObjectForCookie(const Cookie&);
318     ScriptArray buildArrayForCookies(ListHashSet<Cookie>&);
319
320     void focusNode();
321
322     void addConsoleMessage(ScriptState*, ConsoleMessage*);
323
324     void addResource(InspectorResource*);
325     void removeResource(InspectorResource*);
326     InspectorResource* getTrackedResource(unsigned long identifier);
327
328     void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0);
329     void removeAllResources(ResourcesMap* map) { pruneResources(map); }
330
331     bool isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl);
332
333     SpecialPanels specialPanelForJSName(const String& panelName);
334
335     void didEvaluateForTestInFrontend(long callId, const String& jsonResult);
336
337 #if ENABLE(JAVASCRIPT_DEBUGGER)
338     String breakpointsSettingKey();
339     void loadBreakpoints();
340     void saveBreakpoints();
341 #endif
342
343     Page* m_inspectedPage;
344     InspectorClient* m_client;
345     OwnPtr<InspectorFrontendClient> m_inspectorFrontendClient;
346     bool m_openingFrontend;
347     OwnPtr<InspectorFrontend> m_frontend;
348     OwnPtr<InspectorFrontend2> m_frontend2;
349     RefPtr<InspectorDOMAgent> m_domAgent;
350     OwnPtr<InspectorCSSStore> m_cssStore;
351     OwnPtr<InspectorTimelineAgent> m_timelineAgent;
352
353 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
354     OwnPtr<InspectorApplicationCacheAgent> m_applicationCacheAgent;
355 #endif
356
357     RefPtr<Node> m_nodeToFocus;
358     RefPtr<InspectorResource> m_mainResource;
359     ResourcesMap m_resources;
360     HashSet<String> m_knownResources;
361     FrameResourcesMap m_frameResources;
362     Vector<ConsoleMessage*> m_consoleMessages;
363     unsigned m_expiredConsoleMessageCount;
364     HashMap<String, double> m_times;
365     HashMap<String, unsigned> m_counts;
366 #if ENABLE(DATABASE)
367     DatabaseResourcesMap m_databaseResources;
368 #endif
369 #if ENABLE(DOM_STORAGE)
370     DOMStorageResourcesMap m_domStorageResources;
371 #endif
372     SpecialPanels m_showAfterVisible;
373     RefPtr<Node> m_highlightedNode;
374 #if ENABLE(INSPECTOR)
375     RefPtr<InspectorValue> m_sessionSettings;
376 #endif
377     unsigned m_groupLevel;
378     bool m_searchingForNode;
379     bool m_monitoringXHR;
380     ConsoleMessage* m_previousMessage;
381     bool m_resourceTrackingEnabled;
382     bool m_settingsLoaded;
383     RefPtr<InspectorBackend> m_inspectorBackend;
384     RefPtr<InjectedScriptHost> m_injectedScriptHost;
385
386     typedef HashMap<String, String> Settings;
387     mutable Settings m_settings;
388
389     Vector<pair<long, String> > m_pendingEvaluateTestCommands;
390     Vector<String> m_scriptsToEvaluateOnLoad;
391 #if ENABLE(JAVASCRIPT_DEBUGGER)
392     bool m_debuggerEnabled;
393     bool m_attachDebuggerWhenShown;
394     ScriptState* m_pausedScriptState;
395     HashMap<String, String> m_sourceIDToURL;
396     HashMap<String, String> m_scriptIDToContent;
397     HashMap<String, SourceBreakpoints> m_stickyBreakpoints;
398     HashMap<String, unsigned> m_breakpointsMapping;
399     bool m_breakpointsLoaded;
400
401     bool m_profilerEnabled;
402     bool m_recordingUserInitiatedProfile;
403     int m_currentUserInitiatedProfileNumber;
404     unsigned m_nextUserInitiatedProfileNumber;
405     Timer<InspectorController> m_startProfiling;
406     ProfilesMap m_profiles;
407 #endif
408 #if ENABLE(WORKERS)
409     typedef HashMap<intptr_t, RefPtr<InspectorWorkerResource> > WorkersMap;
410
411     WorkersMap m_workers;
412 #endif
413 };
414
415 inline void InspectorController::didInsertDOMNode(Node* node)
416 {
417     if (m_domAgent)
418         m_domAgent->didInsertDOMNode(node);
419 }
420
421 inline void InspectorController::didRemoveDOMNode(Node* node)
422 {
423     if (m_domAgent)
424         m_domAgent->didRemoveDOMNode(node);
425 }
426
427 inline void InspectorController::didModifyDOMAttr(Element* element)
428 {
429     if (m_domAgent)
430         m_domAgent->didModifyDOMAttr(element);
431 }
432
433 } // namespace WebCore
434
435 #endif // !defined(InspectorController_h)