diff options
Diffstat (limited to 'WebCore/inspector/InspectorController.cpp')
-rw-r--r-- | WebCore/inspector/InspectorController.cpp | 670 |
1 files changed, 357 insertions, 313 deletions
diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp index b487ad8..c54ee5b 100644 --- a/WebCore/inspector/InspectorController.cpp +++ b/WebCore/inspector/InspectorController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> * * Redistribution and use in source and binary forms, with or without @@ -32,7 +32,6 @@ #if ENABLE(INSPECTOR) -#include "CString.h" #include "CachedResource.h" #include "Chrome.h" #include "Console.h" @@ -57,12 +56,12 @@ #include "InjectedScriptHost.h" #include "InspectorBackend.h" #include "InspectorClient.h" -#include "InspectorDOMAgent.h" +#include "InspectorFrontendClient.h" #include "InspectorDOMStorageResource.h" #include "InspectorDatabaseResource.h" #include "InspectorFrontend.h" -#include "InspectorFrontendHost.h" #include "InspectorResource.h" +#include "InspectorWorkerResource.h" #include "InspectorTimelineAgent.h" #include "Page.h" #include "ProgressTracker.h" @@ -70,18 +69,20 @@ #include "RenderInline.h" #include "ResourceRequest.h" #include "ResourceResponse.h" +#include "ScriptBreakpoint.h" #include "ScriptCallStack.h" -#include "ScriptDebugServer.h" #include "ScriptFunctionCall.h" #include "ScriptObject.h" #include "ScriptProfile.h" #include "ScriptProfiler.h" +#include "ScriptSourceCode.h" #include "ScriptString.h" #include "SecurityOrigin.h" #include "Settings.h" #include "SharedBuffer.h" #include "TextEncoding.h" #include "TextIterator.h" +#include <wtf/text/CString.h> #include <wtf/CurrentTime.h> #include <wtf/ListHashSet.h> #include <wtf/RefCounted.h> @@ -96,17 +97,17 @@ #include "StorageArea.h" #endif -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) -#include "JSJavaScriptCallFrame.h" -#include "JavaScriptCallFrame.h" -#include "JavaScriptDebugServer.h" -#include "JavaScriptProfile.h" - +#if ENABLE(JAVASCRIPT_DEBUGGER) +#include "ScriptDebugServer.h" +#if USE(JSC) #include <runtime/JSLock.h> #include <runtime/UString.h> - -using namespace JSC; +#include "JSScriptProfile.h" +#else +#include "V8ScriptProfile.h" +#endif #endif + using namespace std; namespace WebCore { @@ -118,7 +119,18 @@ static const char* const debuggerEnabledSettingName = "debuggerEnabled"; static const char* const profilerEnabledSettingName = "profilerEnabled"; static const char* const inspectorAttachedHeightName = "inspectorAttachedHeight"; static const char* const lastActivePanelSettingName = "lastActivePanel"; -const char* const InspectorController::FrontendSettingsSettingName = "frontendSettings"; + +const String& InspectorController::frontendSettingsSettingName() +{ + DEFINE_STATIC_LOCAL(String, settingName, ("frontendSettings")); + return settingName; +} + +const String& InspectorController::inspectorStartsAttachedSettingName() +{ + DEFINE_STATIC_LOCAL(String, settingName, ("inspectorStartsAttached")); + return settingName; +} static const unsigned defaultAttachedHeight = 300; static const float minimumAttachedHeight = 250.0f; @@ -131,10 +143,8 @@ static unsigned s_inspectorControllerCount; InspectorController::InspectorController(Page* page, InspectorClient* client) : m_inspectedPage(page) , m_client(client) - , m_page(0) + , m_openingFrontend(false) , m_expiredConsoleMessageCount(0) - , m_frontendScriptState(0) - , m_windowVisible(false) , m_showAfterVisible(CurrentPanel) , m_groupLevel(0) , m_searchingForNode(false) @@ -142,9 +152,8 @@ InspectorController::InspectorController(Page* page, InspectorClient* client) , m_resourceTrackingEnabled(false) , m_resourceTrackingSettingsLoaded(false) , m_inspectorBackend(InspectorBackend::create(this)) - , m_inspectorFrontendHost(InspectorFrontendHost::create(this, client)) , m_injectedScriptHost(InjectedScriptHost::create(this)) -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) , m_debuggerEnabled(false) , m_attachDebuggerWhenShown(false) #endif @@ -165,9 +174,7 @@ InspectorController::~InspectorController() { // These should have been cleared in inspectedPageDestroyed(). ASSERT(!m_client); - ASSERT(!m_frontendScriptState); ASSERT(!m_inspectedPage); - ASSERT(!m_page || (m_page && !m_page->parentInspectorController())); deleteAllValues(m_frameResources); deleteAllValues(m_consoleMessages); @@ -178,18 +185,14 @@ InspectorController::~InspectorController() releaseDOMAgent(); m_inspectorBackend->disconnectController(); - m_inspectorFrontendHost->disconnectController(); m_injectedScriptHost->disconnectController(); } void InspectorController::inspectedPageDestroyed() { - close(); + if (m_frontend) + m_frontend->inspectedPageDestroyed(); - if (m_frontendScriptState) { - ScriptGlobalObject::remove(m_frontendScriptState, "InspectorBackend"); - ScriptGlobalObject::remove(m_frontendScriptState, "InspectorFrontendHost"); - } ASSERT(m_inspectedPage); m_inspectedPage = 0; @@ -222,20 +225,9 @@ void InspectorController::setSetting(const String& key, const String& value) m_client->storeSetting(key, value); } -// Trying to inspect something in a frame with JavaScript disabled would later lead to -// crashes trying to create JavaScript wrappers. Some day we could fix this issue, but -// for now prevent crashes here by never targeting a node in such a frame. -static bool canPassNodeToJavaScript(Node* node) -{ - if (!node) - return false; - Frame* frame = node->document()->frame(); - return frame && frame->script()->canExecuteScripts(); -} - void InspectorController::inspect(Node* node) { - if (!canPassNodeToJavaScript(node) || !enabled()) + if (!enabled()) return; show(); @@ -284,48 +276,7 @@ void InspectorController::hideHighlight() bool InspectorController::windowVisible() { - return m_windowVisible; -} - -void InspectorController::setWindowVisible(bool visible, bool attached) -{ - if (visible == m_windowVisible || !m_frontend) - return; - - m_windowVisible = visible; - - if (m_windowVisible) { - setAttachedWindow(attached); - populateScriptObjects(); - - if (m_showAfterVisible == CurrentPanel) { - String lastActivePanelSetting = setting(lastActivePanelSettingName); - m_showAfterVisible = specialPanelForJSName(lastActivePanelSetting); - } - - if (m_nodeToFocus) - focusNode(); -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) - if (m_attachDebuggerWhenShown) - enableDebugger(); -#endif - showPanel(m_showAfterVisible); - } else { -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) - // If the window is being closed with the debugger enabled, - // remember this state to re-enable debugger on the next window - // opening. - bool debuggerWasEnabled = m_debuggerEnabled; - disableDebugger(); - if (debuggerWasEnabled) - m_attachDebuggerWhenShown = true; -#endif - if (m_searchingForNode) - toggleSearchForNodeInPage(); - resetScriptObjects(); - stopTimelineProfiler(); - } - m_showAfterVisible = CurrentPanel; + return m_frontend; } void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, ScriptCallStack* callStack) @@ -352,16 +303,16 @@ void InspectorController::addConsoleMessage(ScriptState* scriptState, ConsoleMes if (m_previousMessage && m_previousMessage->isEqual(scriptState, consoleMessage)) { m_previousMessage->incrementCount(); delete consoleMessage; - if (windowVisible()) + if (m_frontend) m_previousMessage->updateRepeatCountInConsole(m_frontend.get()); } else { m_previousMessage = consoleMessage; m_consoleMessages.append(consoleMessage); - if (windowVisible()) - m_previousMessage->addToConsole(m_frontend.get()); + if (m_frontend) + m_previousMessage->addToFrontend(m_frontend.get(), m_injectedScriptHost.get()); } - if (!windowVisible() && m_consoleMessages.size() >= maximumConsoleMessages) { + if (!m_frontend && m_consoleMessages.size() >= maximumConsoleMessages) { m_expiredConsoleMessageCount += expireConsoleMessagesStep; for (size_t i = 0; i < expireConsoleMessagesStep; ++i) delete m_consoleMessages[i]; @@ -406,127 +357,79 @@ void InspectorController::markTimeline(const String& message) timelineAgent()->didMarkTimeline(message); } -static unsigned constrainedAttachedWindowHeight(unsigned preferredHeight, unsigned totalWindowHeight) -{ - return roundf(max(minimumAttachedHeight, min<float>(preferredHeight, totalWindowHeight * maximumAttachedHeightRatio))); -} - -void InspectorController::attachWindow() -{ - if (!enabled()) - return; - - unsigned inspectedPageHeight = m_inspectedPage->mainFrame()->view()->visibleHeight(); - - m_client->attachWindow(); - - String attachedHeight = setting(inspectorAttachedHeightName); - bool success = true; - int height = attachedHeight.toInt(&success); - unsigned preferredHeight = success ? height : defaultAttachedHeight; - - // We need to constrain the window height here in case the user has resized the inspected page's window so that - // the user's preferred height would be too big to display. - m_client->setAttachedWindowHeight(constrainedAttachedWindowHeight(preferredHeight, inspectedPageHeight)); -} - -void InspectorController::detachWindow() -{ - if (!enabled()) - return; - m_client->detachWindow(); -} - -void InspectorController::setAttachedWindow(bool attached) -{ - if (!enabled() || !m_frontend) - return; - - m_frontend->setAttachedWindow(attached); -} - -void InspectorController::setAttachedWindowHeight(unsigned height) -{ - if (!enabled()) - return; - - unsigned totalHeight = m_page->mainFrame()->view()->visibleHeight() + m_inspectedPage->mainFrame()->view()->visibleHeight(); - unsigned attachedHeight = constrainedAttachedWindowHeight(height, totalHeight); - - setSetting(inspectorAttachedHeightName, String::number(attachedHeight)); - - m_client->setAttachedWindowHeight(attachedHeight); -} - void InspectorController::storeLastActivePanel(const String& panelName) { setSetting(lastActivePanelSettingName, panelName); } -void InspectorController::toggleSearchForNodeInPage() -{ - if (!enabled()) - return; - - m_searchingForNode = !m_searchingForNode; - if (!m_searchingForNode) - hideHighlight(); -} - void InspectorController::mouseDidMoveOverElement(const HitTestResult& result, unsigned) { if (!enabled() || !m_searchingForNode) return; Node* node = result.innerNode(); + while (node && node->nodeType() == Node::TEXT_NODE) + node = node->parentNode(); if (node) highlight(node); } -void InspectorController::handleMousePressOnNode(Node* node) +void InspectorController::handleMousePress() { if (!enabled()) return; ASSERT(m_searchingForNode); - ASSERT(node); - if (!node) + if (!m_highlightedNode) return; - // inspect() will implicitly call ElementsPanel's focusedNodeChanged() and the hover feedback will be stopped there. - inspect(node); + RefPtr<Node> node = m_highlightedNode; + setSearchingForNode(false); + inspect(node.get()); +} + +void InspectorController::setInspectorFrontendClient(PassOwnPtr<InspectorFrontendClient> client) +{ + ASSERT(!m_inspectorFrontendClient); + m_inspectorFrontendClient = client; } void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) { + // If the page is supposed to serve as InspectorFrontend notify inspetor frontend + // client that it's cleared so that the client can expose inspector bindings. + if (m_inspectorFrontendClient && frame == m_inspectedPage->mainFrame()) + m_inspectorFrontendClient->windowObjectCleared(); + if (!enabled() || !m_frontend || frame != m_inspectedPage->mainFrame()) return; m_injectedScriptHost->discardInjectedScripts(); } -void InspectorController::windowScriptObjectAvailable() +void InspectorController::setSearchingForNode(bool enabled) { - if (!m_page || !enabled()) + if (m_searchingForNode == enabled) return; - - // Grant the inspector the ability to script the inspected page. - m_page->mainFrame()->document()->securityOrigin()->grantUniversalAccess(); - m_frontendScriptState = scriptStateFromPage(debuggerWorld(), m_page); - ScriptGlobalObject::set(m_frontendScriptState, "InspectorBackend", m_inspectorBackend.get()); - ScriptGlobalObject::set(m_frontendScriptState, "InspectorFrontendHost", m_inspectorFrontendHost.get()); + m_searchingForNode = enabled; + if (!m_searchingForNode) + hideHighlight(); + if (m_frontend) { + if (enabled) + m_frontend->searchingForNodeWasEnabled(); + else + m_frontend->searchingForNodeWasDisabled(); + } } -void InspectorController::scriptObjectReady() +void InspectorController::setFrontend(PassOwnPtr<InspectorFrontend> frontend) { - ASSERT(m_frontendScriptState); - if (!m_frontendScriptState) - return; - - ScriptObject webInspectorObj; - if (!ScriptGlobalObject::get(m_frontendScriptState, "WebInspector", webInspectorObj)) - return; - setFrontendProxyObject(m_frontendScriptState, webInspectorObj); - + ASSERT(frontend); + m_openingFrontend = false; + m_frontend = frontend; + releaseDOMAgent(); + m_domAgent = InspectorDOMAgent::create(m_frontend.get()); + if (m_timelineAgent) + m_timelineAgent->resetFrontendProxyObject(m_frontend.get()); #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) String debuggerEnabled = setting(debuggerEnabledSettingName); if (debuggerEnabled == "true") @@ -536,41 +439,39 @@ void InspectorController::scriptObjectReady() enableProfiler(); #endif - // Make sure our window is visible now that the page loaded - showWindow(); - - m_client->inspectorWindowObjectCleared(); -} + // Initialize Web Inspector title. + m_frontend->inspectedURLChanged(m_inspectedPage->mainFrame()->loader()->url().string()); -void InspectorController::setFrontendProxyObject(ScriptState* scriptState, ScriptObject webInspectorObj, ScriptObject) -{ - m_frontendScriptState = scriptState; - m_frontend.set(new InspectorFrontend(this, webInspectorObj)); - releaseDOMAgent(); - m_domAgent = InspectorDOMAgent::create(m_frontend.get()); - if (m_timelineAgent) - m_timelineAgent->resetFrontendProxyObject(m_frontend.get()); + populateScriptObjects(); + + if (m_showAfterVisible == CurrentPanel) { + String lastActivePanelSetting = setting(lastActivePanelSettingName); + m_showAfterVisible = specialPanelForJSName(lastActivePanelSetting); + } + + if (m_nodeToFocus) + focusNode(); +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (m_attachDebuggerWhenShown) + enableDebugger(); +#endif + showPanel(m_showAfterVisible); } void InspectorController::show() { if (!enabled()) return; - - if (!m_page) { - if (m_frontend) - return; // We are using custom frontend - no need to create page. - m_page = m_client->createPage(); - if (!m_page) - return; - m_page->setParentInspectorController(this); - - // showWindow() will be called after the page loads in scriptObjectReady() + if (m_openingFrontend) return; + + if (m_frontend) + m_frontend->bringToFront(); + else { + m_openingFrontend = true; + m_client->openInspectorFrontend(this); } - - showWindow(); } void InspectorController::showPanel(SpecialPanels panel) @@ -593,49 +494,40 @@ void InspectorController::showPanel(SpecialPanels panel) void InspectorController::close() { - if (!enabled()) + if (!m_frontend) return; - -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) - stopUserInitiatedProfiling(); - disableDebugger(); -#endif - closeWindow(); - - releaseDOMAgent(); - m_frontend.set(0); - m_timelineAgent = 0; - m_frontendScriptState = 0; - if (m_page) { - if (!m_page->mainFrame() || !m_page->mainFrame()->loader() || !m_page->mainFrame()->loader()->isLoading()) { - m_page->setParentInspectorController(0); - m_page = 0; - } - } + m_frontend->close(); } -void InspectorController::showWindow() +void InspectorController::disconnectFrontend() { - ASSERT(enabled()); + if (!m_frontend) + return; + m_frontend.clear(); - unsigned inspectedPageHeight = m_inspectedPage->mainFrame()->view()->visibleHeight(); +#if ENABLE(JAVASCRIPT_DEBUGGER) + // If the window is being closed with the debugger enabled, + // remember this state to re-enable debugger on the next window + // opening. + bool debuggerWasEnabled = m_debuggerEnabled; + disableDebugger(); + if (debuggerWasEnabled) + m_attachDebuggerWhenShown = true; +#endif + setSearchingForNode(false); + unbindAllResources(); + stopTimelineProfiler(); - m_client->showWindow(); + m_showAfterVisible = CurrentPanel; - String attachedHeight = setting(inspectorAttachedHeightName); - bool success = true; - int height = attachedHeight.toInt(&success); - unsigned preferredHeight = success ? height : defaultAttachedHeight; + hideHighlight(); - // This call might not go through (if the window starts out detached), but if the window is initially created attached, - // InspectorController::attachWindow is never called, so we need to make sure to set the attachedWindowHeight. - // FIXME: Clean up code so we only have to call setAttachedWindowHeight in InspectorController::attachWindow - m_client->setAttachedWindowHeight(constrainedAttachedWindowHeight(preferredHeight, inspectedPageHeight)); -} +#if ENABLE(JAVASCRIPT_DEBUGGER) + stopUserInitiatedProfiling(); +#endif -void InspectorController::closeWindow() -{ - m_client->closeWindow(); + releaseDOMAgent(); + m_timelineAgent.clear(); } void InspectorController::releaseDOMAgent() @@ -644,7 +536,7 @@ void InspectorController::releaseDOMAgent() // no references to the DOM agent from the DOM tree. if (m_domAgent) m_domAgent->reset(); - m_domAgent = 0; + m_domAgent.clear(); } void InspectorController::populateScriptObjects() @@ -653,7 +545,20 @@ void InspectorController::populateScriptObjects() if (!m_frontend) return; - m_frontend->populateFrontendSettings(setting(FrontendSettingsSettingName)); + m_frontend->populateFrontendSettings(setting(frontendSettingsSettingName())); + + if (m_resourceTrackingEnabled) + m_frontend->resourceTrackingWasEnabled(); + + if (m_searchingForNode) + m_frontend->searchingForNodeWasEnabled(); + else + m_frontend->searchingForNodeWasDisabled(); + +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (m_profilerEnabled) + m_frontend->profilerWasEnabled(); +#endif ResourcesMap::iterator resourcesEnd = m_resources.end(); for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) @@ -665,8 +570,12 @@ void InspectorController::populateScriptObjects() m_frontend->updateConsoleMessageExpiredCount(m_expiredConsoleMessageCount); unsigned messageCount = m_consoleMessages.size(); for (unsigned i = 0; i < messageCount; ++i) - m_consoleMessages[i]->addToConsole(m_frontend.get()); + m_consoleMessages[i]->addToFrontend(m_frontend.get(), m_injectedScriptHost.get()); +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (m_debuggerEnabled) + m_frontend->updatePauseOnExceptionsState(ScriptDebugServer::shared().pauseOnExceptionsState()); +#endif #if ENABLE(DATABASE) DatabaseResourcesMap::iterator databasesEnd = m_databaseResources.end(); for (DatabaseResourcesMap::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it) @@ -677,6 +586,11 @@ void InspectorController::populateScriptObjects() for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it) it->second->bind(m_frontend.get()); #endif +#if ENABLE(WORKERS) + WorkersMap::iterator workersEnd = m_workers.end(); + for (WorkersMap::iterator it = m_workers.begin(); it != workersEnd; ++it) + m_frontend->didCreateWorker(*it->second); +#endif m_frontend->populateInterface(); @@ -686,15 +600,12 @@ void InspectorController::populateScriptObjects() m_pendingEvaluateTestCommands.clear(); } -void InspectorController::resetScriptObjects() +void InspectorController::unbindAllResources() { - if (!m_frontend) - return; - - ResourcesMap::iterator resourcesEnd = m_resources.end(); - for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) - it->second->releaseScriptObject(m_frontend.get(), false); - + ResourcesMap::iterator resourcesEnd = m_resources.end(); + for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) + it->second->releaseScriptObject(0); + #if ENABLE(DATABASE) DatabaseResourcesMap::iterator databasesEnd = m_databaseResources.end(); for (DatabaseResourcesMap::iterator it = m_databaseResources.begin(); it != databasesEnd; ++it) @@ -705,12 +616,8 @@ void InspectorController::resetScriptObjects() for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it) it->second->unbind(); #endif - if (m_timelineAgent) m_timelineAgent->reset(); - - m_frontend->reset(); - m_domAgent->reset(); } void InspectorController::pruneResources(ResourcesMap* resourceMap, DocumentLoader* loaderToKeep) @@ -726,8 +633,8 @@ void InspectorController::pruneResources(ResourcesMap* resourceMap, DocumentLoad if (!loaderToKeep || !resource->isSameLoader(loaderToKeep)) { removeResource(resource); - if (windowVisible()) - resource->releaseScriptObject(m_frontend.get(), true); + if (m_frontend) + resource->releaseScriptObject(m_frontend.get()); } } } @@ -740,13 +647,17 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) ASSERT(m_inspectedPage); if (loader->frame() == m_inspectedPage->mainFrame()) { - m_client->inspectedURLChanged(loader->url().string()); + if (m_frontend) + m_frontend->inspectedURLChanged(loader->url().string()); m_injectedScriptHost->discardInjectedScripts(); clearConsoleMessages(); m_times.clear(); m_counts.clear(); +#if ENABLE(JAVASCRIPT_DEBUGGER) + m_sourceIDToURL.clear(); +#endif #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) m_profiles.clear(); m_currentUserInitiatedProfileNumber = 1; @@ -754,8 +665,13 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) #endif // resetScriptObjects should be called before database and DOM storage // resources are cleared so that it has a chance to unbind them. - resetScriptObjects(); - + if (m_frontend) { + m_frontend->reset(); + m_domAgent->reset(); + } +#if ENABLE(WORKERS) + m_workers.clear(); +#endif #if ENABLE(DATABASE) m_databaseResources.clear(); #endif @@ -769,8 +685,7 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) // We don't add the main resource until its load is committed. This is // needed to keep the load for a user-entered URL from showing up in the // list of resources for the page they are navigating away from. - if (windowVisible()) - m_mainResource->updateScriptObject(m_frontend.get()); + m_mainResource->updateScriptObject(m_frontend.get()); } else { // Pages loaded from the page cache are committed before // m_mainResource is the right resource for this load, so we @@ -778,16 +693,22 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) // identifierForInitialRequest. m_mainResource = 0; } - if (windowVisible()) { - m_frontend->didCommitLoad(); - m_domAgent->setDocument(m_inspectedPage->mainFrame()->document()); - } + m_frontend->didCommitLoad(); + m_domAgent->setDocument(m_inspectedPage->mainFrame()->document()); } } for (Frame* frame = loader->frame(); frame; frame = frame->tree()->traverseNext(loader->frame())) if (ResourcesMap* resourceMap = m_frameResources.get(frame)) pruneResources(resourceMap, loader); + + if (m_scriptsToEvaluateOnLoad.size()) { + ScriptState* scriptState = mainWorldScriptState(loader->frame()); + for (Vector<String>::iterator it = m_scriptsToEvaluateOnLoad.begin(); + it != m_scriptsToEvaluateOnLoad.end(); ++it) { + m_injectedScriptHost->injectScript(*it, scriptState); + } + } } void InspectorController::frameDetachedFromParent(Frame* frame) @@ -874,7 +795,7 @@ void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader* loader, addResource(resource.get()); - if (windowVisible()) + if (m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -898,7 +819,7 @@ void InspectorController::identifierForInitialRequest(unsigned long identifier, addResource(resource.get()); - if (windowVisible() && loader->frameLoader()->isLoadingFromCachedPage() && resource == m_mainResource) + if (m_frontend && loader->frameLoader()->isLoadingFromCachedPage() && resource == m_mainResource) resource->updateScriptObject(m_frontend.get()); } @@ -909,7 +830,9 @@ void InspectorController::mainResourceFiredDOMContentEvent(DocumentLoader* loade if (m_mainResource) { m_mainResource->markDOMContentEventTime(); - if (windowVisible()) + if (m_timelineAgent) + m_timelineAgent->didMarkDOMContentEvent(); + if (m_frontend) m_mainResource->updateScriptObject(m_frontend.get()); } } @@ -921,7 +844,9 @@ void InspectorController::mainResourceFiredLoadEvent(DocumentLoader* loader, con if (m_mainResource) { m_mainResource->markLoadEventTime(); - if (windowVisible()) + if (m_timelineAgent) + m_timelineAgent->didMarkLoadEvent(); + if (m_frontend) m_mainResource->updateScriptObject(m_frontend.get()); } } @@ -961,15 +886,12 @@ void InspectorController::willSendRequest(unsigned long identifier, const Resour resource->startTiming(); resource->updateRequest(request); - if (resource != m_mainResource && windowVisible()) + if (resource != m_mainResource && m_frontend) resource->updateScriptObject(m_frontend.get()); } void InspectorController::didReceiveResponse(unsigned long identifier, const ResourceResponse& response) { - if (m_timelineAgent) - m_timelineAgent->didReceiveResourceResponse(identifier, response); - RefPtr<InspectorResource> resource = getTrackedResource(identifier); if (!resource) return; @@ -977,7 +899,7 @@ void InspectorController::didReceiveResponse(unsigned long identifier, const Res resource->updateResponse(response); resource->markResponseReceivedTime(); - if (resource != m_mainResource && windowVisible()) + if (resource != m_mainResource && m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -989,7 +911,7 @@ void InspectorController::didReceiveContentLength(unsigned long identifier, int resource->addLength(lengthReceived); - if (resource != m_mainResource && windowVisible()) + if (resource != m_mainResource && m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -1004,7 +926,8 @@ void InspectorController::didFinishLoading(unsigned long identifier) resource->endTiming(); - if (resource != m_mainResource && windowVisible()) + // No need to mute this event for main resource since it happens after did commit load. + if (m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -1020,7 +943,8 @@ void InspectorController::didFailLoading(unsigned long identifier, const Resourc resource->markFailed(); resource->endTiming(); - if (resource != m_mainResource && windowVisible()) + // No need to mute this event for main resource since it happens after did commit load. + if (m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -1033,9 +957,9 @@ void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identi if (!resource) return; - resource->setXMLHttpResponseText(sourceString); + resource->setOverrideContent(sourceString, InspectorResource::XHR); - if (windowVisible()) + if (m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -1048,11 +972,9 @@ void InspectorController::scriptImported(unsigned long identifier, const String& if (!resource) return; - // FIXME: imported script and XHR response are currently viewed as the same - // thing by the Inspector. They should be made into distinct types. - resource->setXMLHttpResponseText(ScriptString(sourceString)); + resource->setOverrideContent(ScriptString(sourceString), InspectorResource::Script); - if (windowVisible()) + if (m_frontend) resource->updateScriptObject(m_frontend.get()); } @@ -1073,7 +995,7 @@ void InspectorController::enableResourceTracking(bool always, bool reload) m_frontend->resourceTrackingWasEnabled(); if (reload) - m_inspectedPage->mainFrame()->loader()->reload(); + m_inspectedPage->mainFrame()->redirectScheduler()->scheduleRefresh(true); } void InspectorController::disableResourceTracking(bool always) @@ -1127,6 +1049,71 @@ void InspectorController::stopTimelineProfiler() m_frontend->timelineProfilerWasStopped(); } +#if ENABLE(WORKERS) +class PostWorkerNotificationToFrontendTask : public ScriptExecutionContext::Task { +public: + static PassOwnPtr<PostWorkerNotificationToFrontendTask> create(PassRefPtr<InspectorWorkerResource> worker, InspectorController::WorkerAction action) + { + return new PostWorkerNotificationToFrontendTask(worker, action); + } + +private: + PostWorkerNotificationToFrontendTask(PassRefPtr<InspectorWorkerResource> worker, InspectorController::WorkerAction action) + : m_worker(worker) + , m_action(action) + { + } + + virtual void performTask(ScriptExecutionContext* scriptContext) + { + if (InspectorController* inspector = scriptContext->inspectorController()) + inspector->postWorkerNotificationToFrontend(*m_worker, m_action); + } + +private: + RefPtr<InspectorWorkerResource> m_worker; + InspectorController::WorkerAction m_action; +}; + +void InspectorController::postWorkerNotificationToFrontend(const InspectorWorkerResource& worker, InspectorController::WorkerAction action) +{ + if (!m_frontend) + return; + switch (action) { + case InspectorController::WorkerCreated: + m_frontend->didCreateWorker(worker); + break; + case InspectorController::WorkerDestroyed: + m_frontend->didDestroyWorker(worker); + break; + } +} + +void InspectorController::didCreateWorker(intptr_t id, const String& url, bool isSharedWorker) +{ + if (!enabled()) + return; + + RefPtr<InspectorWorkerResource> workerResource(InspectorWorkerResource::create(id, url, isSharedWorker)); + m_workers.set(id, workerResource); + if (m_inspectedPage && m_frontend) + m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource, InspectorController::WorkerCreated)); +} + +void InspectorController::didDestroyWorker(intptr_t id) +{ + if (!enabled()) + return; + + WorkersMap::iterator workerResource = m_workers.find(id); + if (workerResource == m_workers.end()) + return; + if (m_inspectedPage && m_frontend) + m_inspectedPage->mainFrame()->document()->postTask(PostWorkerNotificationToFrontendTask::create(workerResource->second, InspectorController::WorkerDestroyed)); + m_workers.remove(workerResource); +} +#endif // ENABLE(WORKERS) + #if ENABLE(DATABASE) void InspectorController::selectDatabase(Database* database) { @@ -1141,7 +1128,7 @@ void InspectorController::selectDatabase(Database* database) } } -Database* InspectorController::databaseForId(int databaseId) +Database* InspectorController::databaseForId(long databaseId) { DatabaseResourcesMap::iterator it = m_databaseResources.find(databaseId); if (it == m_databaseResources.end()) @@ -1159,7 +1146,7 @@ void InspectorController::didOpenDatabase(Database* database, const String& doma m_databaseResources.set(resource->id(), resource); // Resources are only bound while visible. - if (windowVisible()) + if (m_frontend) resource->bind(m_frontend.get()); } #endif @@ -1252,7 +1239,7 @@ void InspectorController::didUseDOMStorage(StorageArea* storageArea, bool isLoca m_domStorageResources.set(resource->id(), resource); // Resources are only bound while visible. - if (windowVisible()) + if (m_frontend) resource->bind(m_frontend.get()); } @@ -1263,8 +1250,9 @@ void InspectorController::selectDOMStorage(Storage* storage) return; Frame* frame = storage->frame(); - bool isLocalStorage = (frame->domWindow()->localStorage() == storage); - int storageResourceId = 0; + ExceptionCode ec = 0; + bool isLocalStorage = (frame->domWindow()->localStorage(ec) == storage && !ec); + long storageResourceId = 0; DOMStorageResourcesMap::iterator domStorageEnd = m_domStorageResources.end(); for (DOMStorageResourcesMap::iterator it = m_domStorageResources.begin(); it != domStorageEnd; ++it) { if (it->second->isSameHostAndType(frame, isLocalStorage)) { @@ -1276,7 +1264,7 @@ void InspectorController::selectDOMStorage(Storage* storage) m_frontend->selectDOMStorage(storageResourceId); } -void InspectorController::getDOMStorageEntries(int callId, int storageId) +void InspectorController::getDOMStorageEntries(long callId, long storageId) { if (!m_frontend) return; @@ -1327,7 +1315,7 @@ void InspectorController::removeDOMStorageItem(long callId, long storageId, cons m_frontend->didRemoveDOMStorageItem(callId, success); } -InspectorDOMStorageResource* InspectorController::getDOMStorageResourceForId(int storageId) +InspectorDOMStorageResource* InspectorController::getDOMStorageResourceForId(long storageId) { DOMStorageResourcesMap::iterator it = m_domStorageResources.find(storageId); if (it == m_domStorageResources.end()) @@ -1336,16 +1324,6 @@ InspectorDOMStorageResource* InspectorController::getDOMStorageResourceForId(int } #endif -void InspectorController::moveWindowBy(float x, float y) const -{ - if (!m_page || !enabled()) - return; - - FloatRect frameRect = m_page->chrome()->windowRect(); - frameRect.move(x, y); - m_page->chrome()->setWindowRect(frameRect); -} - #if ENABLE(JAVASCRIPT_DEBUGGER) void InspectorController::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL) { @@ -1357,7 +1335,7 @@ void InspectorController::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsig if (m_frontend) { #if USE(JSC) - JSLock lock(SilenceAssertionsOnly); + JSC::JSLock lock(JSC::SilenceAssertionsOnly); #endif m_frontend->addProfileHeader(createProfileHeader(*profile)); } @@ -1369,7 +1347,12 @@ void InspectorController::addProfileFinishedMessageToConsole(PassRefPtr<ScriptPr { RefPtr<ScriptProfile> profile = prpProfile; - String message = String::format("Profile \"webkit-profile://%s/%s#%d\" finished.", CPUProfileType, encodeWithURLEscapeSequences(profile->title()).utf8().data(), profile->uid()); +#if USE(JSC) + String title = ustringToString(profile->title()); +#else + String title = profile->title(); +#endif + String message = String::format("Profile \"webkit-profile://%s/%s#%d\" finished.", CPUProfileType, encodeWithURLEscapeSequences(title).utf8().data(), profile->uid()); addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL); } @@ -1396,16 +1379,24 @@ void InspectorController::getProfile(long callId, unsigned uid) if (!m_frontend) return; ProfilesMap::iterator it = m_profiles.find(uid); -#if USE(JSC) if (it != m_profiles.end()) - m_frontend->didGetProfile(callId, toJS(m_frontendScriptState, it->second.get())); +#if USE(JSC) + m_frontend->didGetProfile(callId, toJS(m_frontend->scriptState(), it->second.get())); +#else + m_frontend->didGetProfile(callId, toV8(it->second.get())); #endif } ScriptObject InspectorController::createProfileHeader(const ScriptProfile& profile) { +#if USE(JSC) + String title = ustringToString(profile.title()); +#else + String title = profile.title(); +#endif + ScriptObject header = m_frontend->newScriptObject(); - header.set("title", profile.title()); + header.set("title", title); header.set("uid", profile.uid()); header.set("typeId", String(CPUProfileType)); return header; @@ -1431,7 +1422,7 @@ void InspectorController::startUserInitiatedProfiling(Timer<InspectorController> if (!profilerEnabled()) { enableProfiler(false, true); - ScriptDebugServer::recompileAllJSFunctions(); + ScriptDebugServer::shared().recompileAllJSFunctions(); } m_recordingUserInitiatedProfile = true; @@ -1439,7 +1430,7 @@ void InspectorController::startUserInitiatedProfiling(Timer<InspectorController> String title = getCurrentUserInitiatedProfileName(true); #if USE(JSC) - ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec(); + JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec(); #else ScriptState* scriptState = 0; #endif @@ -1460,7 +1451,7 @@ void InspectorController::stopUserInitiatedProfiling() String title = getCurrentUserInitiatedProfileName(); #if USE(JSC) - ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec(); + JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec(); #else ScriptState* scriptState = 0; #endif @@ -1489,7 +1480,7 @@ void InspectorController::enableProfiler(bool always, bool skipRecompile) m_profilerEnabled = true; if (!skipRecompile) - ScriptDebugServer::recompileAllJSFunctionsSoon(); + ScriptDebugServer::shared().recompileAllJSFunctionsSoon(); if (m_frontend) m_frontend->profilerWasEnabled(); @@ -1505,14 +1496,14 @@ void InspectorController::disableProfiler(bool always) m_profilerEnabled = false; - ScriptDebugServer::recompileAllJSFunctionsSoon(); + ScriptDebugServer::shared().recompileAllJSFunctionsSoon(); if (m_frontend) m_frontend->profilerWasDisabled(); } #endif -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) void InspectorController::enableDebuggerFromFrontend(bool always) { if (always) @@ -1520,8 +1511,8 @@ void InspectorController::enableDebuggerFromFrontend(bool always) ASSERT(m_inspectedPage); - JavaScriptDebugServer::shared().addListener(this, m_inspectedPage); - JavaScriptDebugServer::shared().clearBreakpoints(); + ScriptDebugServer::shared().addListener(this, m_inspectedPage); + ScriptDebugServer::shared().clearBreakpoints(); m_debuggerEnabled = true; m_frontend->debuggerWasEnabled(); @@ -1535,7 +1526,7 @@ void InspectorController::enableDebugger() if (m_debuggerEnabled) return; - if (!m_frontendScriptState || !m_frontend) + if (!m_frontend) m_attachDebuggerWhenShown = true; else { m_frontend->attachDebuggerWhenShown(); @@ -1553,7 +1544,7 @@ void InspectorController::disableDebugger(bool always) ASSERT(m_inspectedPage); - JavaScriptDebugServer::shared().removeListener(this, m_inspectedPage); + ScriptDebugServer::shared().removeListener(this, m_inspectedPage); m_debuggerEnabled = false; m_attachDebuggerWhenShown = false; @@ -1566,25 +1557,66 @@ void InspectorController::resumeDebugger() { if (!m_debuggerEnabled) return; - JavaScriptDebugServer::shared().continueProgram(); + ScriptDebugServer::shared().continueProgram(); +} + +void InspectorController::setBreakpoint(const String& sourceID, unsigned lineNumber, bool enabled, const String& condition) +{ + ScriptBreakpoint breakpoint(enabled, condition); + ScriptDebugServer::shared().setBreakpoint(sourceID, lineNumber, breakpoint); + String url = m_sourceIDToURL.get(sourceID); + if (url.isEmpty()) + return; + + HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(url); + if (it == m_stickyBreakpoints.end()) + it = m_stickyBreakpoints.set(url, SourceBreakpoints()).first; + it->second.set(lineNumber, breakpoint); +} + +void InspectorController::removeBreakpoint(const String& sourceID, unsigned lineNumber) +{ + ScriptDebugServer::shared().removeBreakpoint(sourceID, lineNumber); + + String url = m_sourceIDToURL.get(sourceID); + if (url.isEmpty()) + return; + + HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(url); + if (it != m_stickyBreakpoints.end()) + it->second.remove(lineNumber); } // JavaScriptDebugListener functions -void InspectorController::didParseSource(ExecState*, const SourceCode& source) +void InspectorController::didParseSource(const String& sourceID, const String& url, const String& data, int firstLine) { - m_frontend->parsedScriptSource(source); + m_frontend->parsedScriptSource(sourceID, url, data, firstLine); + + if (url.isEmpty()) + return; + + HashMap<String, SourceBreakpoints>::iterator it = m_stickyBreakpoints.find(url); + if (it != m_stickyBreakpoints.end()) { + for (SourceBreakpoints::iterator breakpointIt = it->second.begin(); breakpointIt != it->second.end(); ++breakpointIt) { + if (firstLine <= breakpointIt->first) { + ScriptDebugServer::shared().setBreakpoint(sourceID, breakpointIt->first, breakpointIt->second); + m_frontend->restoredBreakpoint(sourceID, url, breakpointIt->first, breakpointIt->second.enabled, breakpointIt->second.condition); + } + } + } + + m_sourceIDToURL.set(sourceID, url); } -void InspectorController::failedToParseSource(ExecState*, const SourceCode& source, int errorLine, const UString& errorMessage) +void InspectorController::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) { - m_frontend->failedToParseScriptSource(source, errorLine, errorMessage); + m_frontend->failedToParseScriptSource(url, data, firstLine, errorLine, errorMessage); } void InspectorController::didPause() { - JavaScriptCallFrame* callFrame = m_injectedScriptHost->currentCallFrame(); - ScriptState* scriptState = callFrame->scopeChain()->globalObject->globalExec(); + ScriptState* scriptState = ScriptDebugServer::shared().currentCallFrameState(); ASSERT(scriptState); InjectedScript injectedScript = m_injectedScriptHost->injectedScriptFor(scriptState); RefPtr<SerializedScriptValue> callFrames = injectedScript.callFrames(); @@ -1809,6 +1841,8 @@ InspectorController::SpecialPanels InspectorController::specialPanelForJSName(co return ProfilesPanel; if (panelName == "storage" || panelName == "databases") return StoragePanel; + if (panelName == "audits") + return AuditsPanel; if (panelName == "console") return ConsolePanel; return ElementsPanel; @@ -1845,6 +1879,16 @@ InjectedScript InspectorController::injectedScriptForNodeId(long id) return InjectedScript(); } +void InspectorController::addScriptToEvaluateOnLoad(const String& source) +{ + m_scriptsToEvaluateOnLoad.append(source); +} + +void InspectorController::removeAllScriptsToEvaluateOnLoad() +{ + m_scriptsToEvaluateOnLoad.clear(); +} + } // namespace WebCore #endif // ENABLE(INSPECTOR) |