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 "StringHash.h" 35 #include "Timer.h" 36 #include <JavaScriptCore/JSContextRef.h> 37 #include <wtf/HashMap.h> 38 #include <wtf/HashSet.h> 39 #include <wtf/Vector.h> 40 41 #if ENABLE(JAVASCRIPT_DEBUGGER) 42 #include "JavaScriptDebugListener.h" 43 #endif 44 45 46 namespace JSC { 47 class Profile; 48 class UString; 49 } 50 51 namespace WebCore { 52 53 class CachedResource; 54 class Database; 55 class DocumentLoader; 56 class GraphicsContext; 57 class HitTestResult; 58 class InspectorClient; 59 class JavaScriptCallFrame; 60 class Node; 61 class Page; 62 class ResourceRequest; 63 class ResourceResponse; 64 class ResourceError; 65 class ScriptCallStack; 66 class SharedBuffer; 67 68 struct ConsoleMessage; 69 struct InspectorDatabaseResource; 70 struct InspectorResource; 71 72 class InspectorController 73 #if ENABLE(JAVASCRIPT_DEBUGGER) 74 : JavaScriptDebugListener 75 #endif 76 { 77 public: 78 typedef HashMap<long long, RefPtr<InspectorResource> > ResourcesMap; 79 typedef HashMap<RefPtr<Frame>, ResourcesMap*> FrameResourcesMap; 80 typedef HashSet<RefPtr<InspectorDatabaseResource> > DatabaseResourcesSet; 81 82 typedef enum { 83 CurrentPanel, 84 ConsolePanel, 85 DatabasesPanel, 86 ElementsPanel, 87 ProfilesPanel, 88 ResourcesPanel, 89 ScriptsPanel 90 } SpecialPanels; 91 92 struct Setting { 93 enum Type { 94 NoType, StringType, StringVectorType, DoubleType, IntegerType, BooleanType 95 }; 96 SettingSetting97 Setting() 98 : m_type(NoType) 99 { 100 } 101 typeSetting102 Type type() const { return m_type; } 103 stringSetting104 String string() const { ASSERT(m_type == StringType); return m_string; } stringVectorSetting105 const Vector<String>& stringVector() const { ASSERT(m_type == StringVectorType); return m_stringVector; } doubleValueSetting106 double doubleValue() const { ASSERT(m_type == DoubleType); return m_simpleContent.m_double; } integerValueSetting107 long integerValue() const { ASSERT(m_type == IntegerType); return m_simpleContent.m_integer; } booleanValueSetting108 bool booleanValue() const { ASSERT(m_type == BooleanType); return m_simpleContent.m_boolean; } 109 setSetting110 void set(const String& value) { m_type = StringType; m_string = value; } setSetting111 void set(const Vector<String>& value) { m_type = StringVectorType; m_stringVector = value; } setSetting112 void set(double value) { m_type = DoubleType; m_simpleContent.m_double = value; } setSetting113 void set(long value) { m_type = IntegerType; m_simpleContent.m_integer = value; } setSetting114 void set(bool value) { m_type = BooleanType; m_simpleContent.m_boolean = value; } 115 116 private: 117 Type m_type; 118 119 String m_string; 120 Vector<String> m_stringVector; 121 122 union { 123 double m_double; 124 long m_integer; 125 bool m_boolean; 126 } m_simpleContent; 127 }; 128 129 InspectorController(Page*, InspectorClient*); 130 ~InspectorController(); 131 132 void inspectedPageDestroyed(); pageDestroyed()133 void pageDestroyed() { m_page = 0; } 134 135 bool enabled() const; 136 inspectedPage()137 Page* inspectedPage() const { return m_inspectedPage; } 138 139 const Setting& setting(const String& key) const; 140 void setSetting(const String& key, const Setting&); 141 142 String localizedStringsURL(); 143 144 void inspect(Node*); 145 void highlight(Node*); 146 void hideHighlight(); 147 148 void show(); 149 void showPanel(SpecialPanels); 150 void close(); 151 isRecordingUserInitiatedProfile()152 bool isRecordingUserInitiatedProfile() const { return m_recordingUserInitiatedProfile; } 153 void startUserInitiatedProfilingSoon(); 154 void startUserInitiatedProfiling(Timer<InspectorController>* = 0); 155 void stopUserInitiatedProfiling(); 156 157 void enableProfiler(bool skipRecompile = false); 158 void disableProfiler(); profilerEnabled()159 bool profilerEnabled() const { return enabled() && m_profilerEnabled; } 160 161 bool windowVisible(); 162 void setWindowVisible(bool visible = true, bool attached = false); 163 164 void addMessageToConsole(MessageSource, MessageLevel, ScriptCallStack*); 165 void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID); 166 void clearConsoleMessages(); 167 void toggleRecordButton(bool); 168 169 void addProfile(PassRefPtr<JSC::Profile>, unsigned lineNumber, const JSC::UString& sourceURL); 170 void addProfileMessageToConsole(PassRefPtr<JSC::Profile> prpProfile, unsigned lineNumber, const JSC::UString& sourceURL); 171 void addScriptProfile(JSC::Profile* profile); profiles()172 const ProfilesArray& profiles() const { return m_profiles; } 173 174 void attachWindow(); 175 void detachWindow(); 176 177 void setAttachedWindow(bool); 178 void setAttachedWindowHeight(unsigned height); 179 180 void toggleSearchForNodeInPage(); searchingForNodeInPage()181 bool searchingForNodeInPage() { return m_searchingForNode; }; 182 void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); 183 void handleMousePressOnNode(Node*); 184 scriptContext()185 JSContextRef scriptContext() const { return m_scriptContext; }; setScriptContext(JSContextRef context)186 void setScriptContext(JSContextRef context) { m_scriptContext = context; }; 187 188 void inspectedWindowScriptObjectCleared(Frame*); 189 void windowScriptObjectAvailable(); 190 191 void scriptObjectReady(); 192 193 void populateScriptObjects(); 194 void resetScriptObjects(); 195 196 void didCommitLoad(DocumentLoader*); 197 void frameDetachedFromParent(Frame*); 198 199 void didLoadResourceFromMemoryCache(DocumentLoader*, const CachedResource*); 200 201 void identifierForInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); 202 void willSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); 203 void didReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); 204 void didReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived); 205 void didFinishLoading(DocumentLoader*, unsigned long identifier); 206 void didFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&); 207 void resourceRetrievedByXMLHttpRequest(unsigned long identifier, const JSC::UString& sourceString); 208 209 #if ENABLE(DATABASE) 210 void didOpenDatabase(Database*, const String& domain, const String& name, const String& version); 211 #endif 212 resources()213 const ResourcesMap& resources() const { return m_resources; } 214 215 void moveWindowBy(float x, float y) const; 216 void closeWindow(); 217 218 #if ENABLE(JAVASCRIPT_DEBUGGER) 219 void enableDebugger(); 220 void disableDebugger(); debuggerEnabled()221 bool debuggerEnabled() const { return m_debuggerEnabled; } 222 223 JavaScriptCallFrame* currentCallFrame() const; 224 225 void addBreakpoint(intptr_t sourceID, unsigned lineNumber); 226 void removeBreakpoint(intptr_t sourceID, unsigned lineNumber); 227 228 bool pauseOnExceptions(); 229 void setPauseOnExceptions(bool pause); 230 231 void pauseInDebugger(); 232 void resumeDebugger(); 233 234 void stepOverStatementInDebugger(); 235 void stepIntoStatementInDebugger(); 236 void stepOutOfFunctionInDebugger(); 237 #endif 238 239 void drawNodeHighlight(GraphicsContext&) const; 240 241 void count(const String& title, unsigned lineNumber, const String& sourceID); 242 243 void startTiming(const String& title); 244 bool stopTiming(const String& title, double& elapsed); 245 246 void startGroup(MessageSource source, ScriptCallStack* callFrame); 247 void endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL); 248 249 private: 250 void focusNode(); 251 252 void addConsoleMessage(JSC::ExecState*, ConsoleMessage*); 253 void addScriptConsoleMessage(const ConsoleMessage*); 254 255 void addResource(InspectorResource*); 256 void removeResource(InspectorResource*); 257 258 JSObjectRef addScriptResource(InspectorResource*); 259 void removeScriptResource(InspectorResource*); 260 261 JSObjectRef addAndUpdateScriptResource(InspectorResource*); 262 void updateScriptResourceRequest(InspectorResource*); 263 void updateScriptResourceResponse(InspectorResource*); 264 void updateScriptResourceType(InspectorResource*); 265 void updateScriptResource(InspectorResource*, int length); 266 void updateScriptResource(InspectorResource*, bool finished, bool failed = false); 267 void updateScriptResource(InspectorResource*, double startTime, double responseReceivedTime, double endTime); 268 269 void pruneResources(ResourcesMap*, DocumentLoader* loaderToKeep = 0); removeAllResources(ResourcesMap * map)270 void removeAllResources(ResourcesMap* map) { pruneResources(map); } 271 272 #if ENABLE(DATABASE) 273 JSObjectRef addDatabaseScriptResource(InspectorDatabaseResource*); 274 void removeDatabaseScriptResource(InspectorDatabaseResource*); 275 #endif 276 277 JSValueRef callSimpleFunction(JSContextRef, JSObjectRef thisObject, const char* functionName) const; 278 JSValueRef callFunction(JSContextRef, JSObjectRef thisObject, const char* functionName, size_t argumentCount, const JSValueRef arguments[], JSValueRef& exception) const; 279 280 bool handleException(JSContextRef, JSValueRef exception, unsigned lineNumber) const; 281 282 void showWindow(); 283 284 #if ENABLE(JAVASCRIPT_DEBUGGER) 285 virtual void didParseSource(JSC::ExecState*, const JSC::SourceCode&); 286 virtual void failedToParseSource(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMessage); 287 virtual void didPause(); 288 #endif 289 290 Page* m_inspectedPage; 291 InspectorClient* m_client; 292 Page* m_page; 293 RefPtr<Node> m_nodeToFocus; 294 RefPtr<InspectorResource> m_mainResource; 295 ResourcesMap m_resources; 296 HashSet<String> m_knownResources; 297 FrameResourcesMap m_frameResources; 298 Vector<ConsoleMessage*> m_consoleMessages; 299 ProfilesArray m_profiles; 300 HashMap<String, double> m_times; 301 HashMap<String, unsigned> m_counts; 302 #if ENABLE(DATABASE) 303 DatabaseResourcesSet m_databaseResources; 304 #endif 305 JSObjectRef m_scriptObject; 306 JSObjectRef m_controllerScriptObject; 307 JSContextRef m_scriptContext; 308 bool m_windowVisible; 309 #if ENABLE(JAVASCRIPT_DEBUGGER) 310 bool m_debuggerEnabled; 311 bool m_attachDebuggerWhenShown; 312 #endif 313 bool m_profilerEnabled; 314 bool m_recordingUserInitiatedProfile; 315 SpecialPanels m_showAfterVisible; 316 long long m_nextIdentifier; 317 RefPtr<Node> m_highlightedNode; 318 unsigned m_groupLevel; 319 bool m_searchingForNode; 320 int m_currentUserInitiatedProfileNumber; 321 unsigned m_nextUserInitiatedProfileNumber; 322 ConsoleMessage* m_previousMessage; 323 Timer<InspectorController> m_startProfiling; 324 }; 325 326 } // namespace WebCore 327 328 #endif // !defined(InspectorController_h) 329