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 "PlatformString.h" 34 #include "ScriptState.h" 35 #include "StringHash.h" 36 #include "Timer.h" 37 38 #include <wtf/HashMap.h> 39 #include <wtf/HashSet.h> 40 #include <wtf/RefCounted.h> 41 #include <wtf/Vector.h> 42 43 #if ENABLE(JAVASCRIPT_DEBUGGER) 44 #include "JavaScriptDebugListener.h" 45 46 namespace JSC { 47 class Profile; 48 class UString; 49 } 50 #endif 51 52 namespace WebCore { 53 54 class CachedResource; 55 class Database; 56 class Document; 57 class DocumentLoader; 58 class GraphicsContext; 59 class HitTestResult; 60 class InspectorClient; 61 class InspectorDOMAgent; 62 class JavaScriptCallFrame; 63 class StorageArea; 64 class KURL; 65 class Node; 66 class Page; 67 struct ResourceRequest; 68 class ResourceResponse; 69 class ResourceError; 70 class ScriptCallStack; 71 class ScriptObject; 72 class ScriptString; 73 class SharedBuffer; 74 75 class ConsoleMessage; 76 class InspectorDatabaseResource; 77 class InspectorDOMStorageResource; 78 class InspectorResource; 79 80 #if !PLATFORM(ANDROID) 81 class InspectorBackend; 82 class InspectorFrontend; 83 #endif 84 85 class InspectorController 86 #if ENABLE(JAVASCRIPT_DEBUGGER) 87 : JavaScriptDebugListener 88 #endif 89 { 90 public: 91 typedef HashMap<long long, RefPtr<InspectorResource> > ResourcesMap; 92 typedef HashMap<RefPtr<Frame>, ResourcesMap*> FrameResourcesMap; 93 typedef HashSet<RefPtr<InspectorDatabaseResource> > DatabaseResourcesSet; 94 typedef HashSet<RefPtr<InspectorDOMStorageResource> > DOMStorageResourcesSet; 95 96 typedef enum { 97 CurrentPanel, 98 ConsolePanel, 99 DatabasesPanel, 100 ElementsPanel, 101 ProfilesPanel, 102 ResourcesPanel, 103 ScriptsPanel 104 } SpecialPanels; 105 106 struct Setting { 107 enum Type { 108 NoType, StringType, StringVectorType, DoubleType, IntegerType, BooleanType 109 }; 110 SettingSetting111 Setting() 112 : m_type(NoType) 113 { 114 } 115 SettingSetting116 explicit Setting(bool value) 117 : m_type(BooleanType) 118 { 119 m_simpleContent.m_boolean = value; 120 } 121 SettingSetting122 explicit Setting(unsigned value) 123 : m_type(IntegerType) 124 { 125 m_simpleContent.m_integer = value; 126 } 127 SettingSetting128 explicit Setting(const String& value) 129 : m_type(StringType) 130 { 131 m_string = value; 132 } 133 typeSetting134 Type type() const { return m_type; } 135 stringSetting136 String string() const { ASSERT(m_type == StringType); return m_string; } stringVectorSetting137 const Vector<String>& stringVector() const { ASSERT(m_type == StringVectorType); return m_stringVector; } doubleValueSetting138 double doubleValue() const { ASSERT(m_type == DoubleType); return m_simpleContent.m_double; } integerValueSetting139 long integerValue() const { ASSERT(m_type == IntegerType); return m_simpleContent.m_integer; } booleanValueSetting140 bool booleanValue() const { ASSERT(m_type == BooleanType); return m_simpleContent.m_boolean; } 141 setSetting142 void set(const String& value) { m_type = StringType; m_string = value; } setSetting143 void set(const Vector<String>& value) { m_type = StringVectorType; m_stringVector = value; } setSetting144 void set(double value) { m_type = DoubleType; m_simpleContent.m_double = value; } setSetting145 void set(long value) { m_type = IntegerType; m_simpleContent.m_integer = value; } setSetting146 void set(bool value) { m_type = BooleanType; m_simpleContent.m_boolean = value; } 147 148 private: 149 Type m_type; 150 151 String m_string; 152 Vector<String> m_stringVector; 153 154 union { 155 double m_double; 156 long m_integer; 157 bool m_boolean; 158 } m_simpleContent; 159 }; 160 InspectorController(Page*, InspectorClient*); 161 ~InspectorController(); 162 163 #if !PLATFORM(ANDROID) inspectorBackend()164 InspectorBackend* inspectorBackend() { return m_inspectorBackend.get(); } 165 #endif 166 167 void inspectedPageDestroyed(); pageDestroyed()168 void pageDestroyed() { m_page = 0; } 169 170 bool enabled() const; 171 inspectedPage()172 Page* inspectedPage() const { return m_inspectedPage; } 173 174 const Setting& setting(const String& key) const; 175 void setSetting(const String& key, const Setting&); 176 177 void inspect(Node*); 178 void highlight(Node*); 179 void hideHighlight(); 180 181 void show(); 182 void showPanel(SpecialPanels); 183 void close(); 184 185 bool windowVisible(); 186 void setWindowVisible(bool visible = true, bool attached = false); 187 188 void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*); 189 void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID); 190 void clearConsoleMessages(); consoleMessages()191 const Vector<ConsoleMessage*>& consoleMessages() const { return m_consoleMessages; } 192 193 void attachWindow(); 194 void detachWindow(); 195 196 void toggleSearchForNodeInPage(); searchingForNodeInPage()197 bool searchingForNodeInPage() { return m_searchingForNode; }; 198 void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); 199 void handleMousePressOnNode(Node*); 200 201 void inspectedWindowScriptObjectCleared(Frame*); 202 void windowScriptObjectAvailable(); 203 204 void setFrontendProxyObject(ScriptState* state, ScriptObject object); 205 206 void populateScriptObjects(); 207 void resetScriptObjects(); 208 209 void didCommitLoad(DocumentLoader*); 210 void frameDetachedFromParent(Frame*); 211 212 void didLoadResourceFromMemoryCache(DocumentLoader*, const CachedResource*); 213 214 void identifierForInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); 215 void willSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); 216 void didReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); 217 void didReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived); 218 void didFinishLoading(DocumentLoader*, unsigned long identifier); 219 void didFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&); 220 void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString); 221 void scriptImported(unsigned long identifier, const String& sourceString); 222 223 void enableResourceTracking(bool always = false); 224 void disableResourceTracking(bool always = false); resourceTrackingEnabled()225 bool resourceTrackingEnabled() const { return m_resourceTrackingEnabled; } 226 void ensureResourceTrackingSettingsLoaded(); 227 228 #if ENABLE(DATABASE) 229 void didOpenDatabase(Database*, const String& domain, const String& name, const String& version); 230 #endif 231 #if ENABLE(DOM_STORAGE) 232 void didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame); 233 #endif 234 resources()235 const ResourcesMap& resources() const { return m_resources; } 236 237 void drawNodeHighlight(GraphicsContext&) const; 238 239 void count(const String& title, unsigned lineNumber, const String& sourceID); 240 241 void startTiming(const String& title); 242 bool stopTiming(const String& title, double& elapsed); 243 244 void startGroup(MessageSource source, ScriptCallStack* callFrame); 245 void endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL); 246 247 #if ENABLE(JAVASCRIPT_DEBUGGER) 248 void addProfile(PassRefPtr<JSC::Profile>, unsigned lineNumber, const JSC::UString& sourceURL); 249 void addProfileFinishedMessageToConsole(PassRefPtr<JSC::Profile>, unsigned lineNumber, const JSC::UString& sourceURL); 250 void addStartProfilingMessageToConsole(const JSC::UString& title, unsigned lineNumber, const JSC::UString& sourceURL); 251 void addScriptProfile(JSC::Profile*); profiles()252 const ProfilesArray& profiles() const { return m_profiles; } 253 isRecordingUserInitiatedProfile()254 bool isRecordingUserInitiatedProfile() const { return m_recordingUserInitiatedProfile; } 255 256 JSC::UString getCurrentUserInitiatedProfileName(bool incrementProfileNumber); 257 void startUserInitiatedProfiling(Timer<InspectorController>* = 0); 258 void stopUserInitiatedProfiling(); 259 260 void enableProfiler(bool always = false, bool skipRecompile = false); 261 void disableProfiler(bool always = false); profilerEnabled()262 bool profilerEnabled() const { return enabled() && m_profilerEnabled; } 263 264 void enableDebugger(); 265 void disableDebugger(bool always = false); debuggerEnabled()266 bool debuggerEnabled() const { return m_debuggerEnabled; } 267 268 void resumeDebugger(); 269 270 virtual void didParseSource(JSC::ExecState*, const JSC::SourceCode&); 271 virtual void failedToParseSource(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMessage); 272 virtual void didPause(); 273 virtual void didContinue(); 274 #endif 275 276 private: 277 #if !PLATFORM(ANDROID) 278 friend class InspectorBackend; 279 #endif 280 281 // Following are used from InspectorBackend and internally. 282 void scriptObjectReady(bool enableDOMAgent); 283 void moveWindowBy(float x, float y) const; 284 void setAttachedWindow(bool); 285 void setAttachedWindowHeight(unsigned height); 286 void storeLastActivePanel(const String& panelName); 287 void closeWindow(); domAgent()288 InspectorDOMAgent* domAgent() { return m_domAgent.get(); } 289 290 #if ENABLE(JAVASCRIPT_DEBUGGER) 291 void startUserInitiatedProfilingSoon(); 292 void toggleRecordButton(bool); 293 void enableDebuggerFromFrontend(bool always); 294 #endif 295 296 void focusNode(); 297 298 void addConsoleMessage(ScriptState*, ConsoleMessage*); 299 300 void addResource(InspectorResource*); 301 void removeResource(InspectorResource*); 302 InspectorResource* getTrackedResource(long long identifier); 303 304 void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0); removeAllResources(ResourcesMap * map)305 void removeAllResources(ResourcesMap* map) { pruneResources(map); } 306 307 void showWindow(); 308 309 bool isMainResourceLoader(DocumentLoader* loader, const KURL& requestUrl); 310 311 SpecialPanels specialPanelForJSName(const String& panelName); 312 313 Page* m_inspectedPage; 314 InspectorClient* m_client; 315 316 RefPtr<InspectorDOMAgent> m_domAgent; 317 Page* m_page; 318 RefPtr<Node> m_nodeToFocus; 319 RefPtr<InspectorResource> m_mainResource; 320 ResourcesMap m_resources; 321 HashSet<String> m_knownResources; 322 FrameResourcesMap m_frameResources; 323 Vector<ConsoleMessage*> m_consoleMessages; 324 HashMap<String, double> m_times; 325 HashMap<String, unsigned> m_counts; 326 #if ENABLE(DATABASE) 327 DatabaseResourcesSet m_databaseResources; 328 #endif 329 #if ENABLE(DOM_STORAGE) 330 DOMStorageResourcesSet m_domStorageResources; 331 #endif 332 ScriptState* m_scriptState; 333 bool m_windowVisible; 334 SpecialPanels m_showAfterVisible; 335 long long m_nextIdentifier; 336 RefPtr<Node> m_highlightedNode; 337 unsigned m_groupLevel; 338 bool m_searchingForNode; 339 ConsoleMessage* m_previousMessage; 340 bool m_resourceTrackingEnabled; 341 bool m_resourceTrackingSettingsLoaded; 342 #if !PLATFORM(ANDROID) 343 OwnPtr<InspectorFrontend> m_frontend; 344 RefPtr<InspectorBackend> m_inspectorBackend; 345 #endif 346 #if ENABLE(JAVASCRIPT_DEBUGGER) 347 bool m_debuggerEnabled; 348 bool m_attachDebuggerWhenShown; 349 bool m_profilerEnabled; 350 bool m_recordingUserInitiatedProfile; 351 int m_currentUserInitiatedProfileNumber; 352 unsigned m_nextUserInitiatedProfileNumber; 353 Timer<InspectorController> m_startProfiling; 354 ProfilesArray m_profiles; 355 #endif 356 }; 357 358 } // namespace WebCore 359 360 #endif // !defined(InspectorController_h) 361