Home | History | Annotate | Download | only in inspector
      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