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 119 InspectorBackend* inspectorBackend() { return m_inspectorBackend.get(); } 120 InspectorFrontendHost* inspectorFrontendHost() { return m_inspectorFrontendHost.get(); } 121 InjectedScriptHost* injectedScriptHost() { return m_injectedScriptHost.get(); } 122 123 void inspectedPageDestroyed(); 124 void pageDestroyed() { m_page = 0; } 125 126 bool enabled() const; 127 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(); 147 const Vector<ConsoleMessage*>& consoleMessages() const { return m_consoleMessages; } 148 149 void attachWindow(); 150 void detachWindow(); 151 152 void toggleSearchForNodeInPage(); 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()); 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); 182 bool resourceTrackingEnabled() const { return m_resourceTrackingEnabled; } 183 void ensureResourceTrackingSettingsLoaded(); 184 185 void startTimelineProfiler(); 186 void stopTimelineProfiler(); 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 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 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); 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); 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(); 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); 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 365 inline void InspectorController::didInsertDOMNode(Node* node) 366 { 367 if (m_domAgent) 368 m_domAgent->didInsertDOMNode(node); 369 } 370 371 inline void InspectorController::didRemoveDOMNode(Node* node) 372 { 373 if (m_domAgent) 374 m_domAgent->didRemoveDOMNode(node); 375 } 376 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