Home | History | Annotate | Download | only in inspector
      1 /*
      2  * Copyright (C) 2011 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/inspector/PageRuntimeAgent.h"
     33 
     34 #include "bindings/v8/DOMWrapperWorld.h"
     35 #include "bindings/v8/ScriptController.h"
     36 #include "core/inspector/InjectedScript.h"
     37 #include "core/inspector/InjectedScriptManager.h"
     38 #include "core/inspector/InspectorPageAgent.h"
     39 #include "core/inspector/InspectorState.h"
     40 #include "core/inspector/InstrumentingAgents.h"
     41 #include "core/frame/Frame.h"
     42 #include "core/page/Page.h"
     43 #include "core/page/PageConsole.h"
     44 #include "platform/weborigin/SecurityOrigin.h"
     45 
     46 using WebCore::TypeBuilder::Runtime::ExecutionContextDescription;
     47 
     48 namespace WebCore {
     49 
     50 namespace PageRuntimeAgentState {
     51 static const char runtimeEnabled[] = "runtimeEnabled";
     52 };
     53 
     54 PageRuntimeAgent::PageRuntimeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, ScriptDebugServer* scriptDebugServer, Page* page, InspectorPageAgent* pageAgent)
     55     : InspectorRuntimeAgent(instrumentingAgents, state, injectedScriptManager, scriptDebugServer)
     56     , m_inspectedPage(page)
     57     , m_pageAgent(pageAgent)
     58     , m_frontend(0)
     59     , m_mainWorldContextCreated(false)
     60 {
     61     m_instrumentingAgents->setPageRuntimeAgent(this);
     62 }
     63 
     64 PageRuntimeAgent::~PageRuntimeAgent()
     65 {
     66     m_instrumentingAgents->setPageRuntimeAgent(0);
     67 }
     68 
     69 void PageRuntimeAgent::setFrontend(InspectorFrontend* frontend)
     70 {
     71     m_frontend = frontend->runtime();
     72 }
     73 
     74 void PageRuntimeAgent::clearFrontend()
     75 {
     76     m_frontend = 0;
     77     String errorString;
     78     disable(&errorString);
     79 }
     80 
     81 void PageRuntimeAgent::restore()
     82 {
     83     if (m_state->getBoolean(PageRuntimeAgentState::runtimeEnabled)) {
     84         String error;
     85         enable(&error);
     86     }
     87 }
     88 
     89 void PageRuntimeAgent::enable(ErrorString* errorString)
     90 {
     91     if (m_enabled)
     92         return;
     93 
     94     InspectorRuntimeAgent::enable(errorString);
     95     m_state->setBoolean(PageRuntimeAgentState::runtimeEnabled, true);
     96     // Only report existing contexts if the page did commit load, otherwise we may
     97     // unintentionally initialize contexts in the frames which may trigger some listeners
     98     // that are expected to be triggered only after the load is committed, see http://crbug.com/131623
     99     if (m_mainWorldContextCreated)
    100         reportExecutionContextCreation();
    101 }
    102 
    103 void PageRuntimeAgent::disable(ErrorString* errorString)
    104 {
    105     if (!m_enabled)
    106         return;
    107 
    108     InspectorRuntimeAgent::disable(errorString);
    109     m_state->setBoolean(PageRuntimeAgentState::runtimeEnabled, false);
    110 }
    111 
    112 void PageRuntimeAgent::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
    113 {
    114     if (world != mainThreadNormalWorld())
    115         return;
    116 
    117     m_mainWorldContextCreated = true;
    118 
    119     if (!m_enabled)
    120         return;
    121     ASSERT(m_frontend);
    122     String frameId = m_pageAgent->frameId(frame);
    123     ScriptState* scriptState = mainWorldScriptState(frame);
    124     notifyContextCreated(frameId, scriptState, 0, true);
    125 }
    126 
    127 void PageRuntimeAgent::didCreateIsolatedContext(Frame* frame, ScriptState* scriptState, SecurityOrigin* origin)
    128 {
    129     if (!m_enabled)
    130         return;
    131     ASSERT(m_frontend);
    132     String frameId = m_pageAgent->frameId(frame);
    133     notifyContextCreated(frameId, scriptState, origin, false);
    134 }
    135 
    136 InjectedScript PageRuntimeAgent::injectedScriptForEval(ErrorString* errorString, const int* executionContextId)
    137 {
    138     if (!executionContextId) {
    139         ScriptState* scriptState = mainWorldScriptState(m_inspectedPage->mainFrame());
    140         InjectedScript result = injectedScriptManager()->injectedScriptFor(scriptState);
    141         if (result.hasNoValue())
    142             *errorString = "Internal error: main world execution context not found.";
    143         return result;
    144     }
    145     InjectedScript injectedScript = injectedScriptManager()->injectedScriptForId(*executionContextId);
    146     if (injectedScript.hasNoValue())
    147         *errorString = "Execution context with given id not found.";
    148     return injectedScript;
    149 }
    150 
    151 void PageRuntimeAgent::muteConsole()
    152 {
    153     PageConsole::mute();
    154 }
    155 
    156 void PageRuntimeAgent::unmuteConsole()
    157 {
    158     PageConsole::unmute();
    159 }
    160 
    161 void PageRuntimeAgent::reportExecutionContextCreation()
    162 {
    163     Vector<std::pair<ScriptState*, SecurityOrigin*> > isolatedContexts;
    164     for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree().traverseNext()) {
    165         if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
    166             continue;
    167         String frameId = m_pageAgent->frameId(frame);
    168 
    169         ScriptState* scriptState = mainWorldScriptState(frame);
    170         notifyContextCreated(frameId, scriptState, 0, true);
    171         frame->script().collectIsolatedContexts(isolatedContexts);
    172         if (isolatedContexts.isEmpty())
    173             continue;
    174         for (size_t i = 0; i< isolatedContexts.size(); i++)
    175             notifyContextCreated(frameId, isolatedContexts[i].first, isolatedContexts[i].second, false);
    176         isolatedContexts.clear();
    177     }
    178 }
    179 
    180 void PageRuntimeAgent::notifyContextCreated(const String& frameId, ScriptState* scriptState, SecurityOrigin* securityOrigin, bool isPageContext)
    181 {
    182     ASSERT(securityOrigin || isPageContext);
    183     int executionContextId = injectedScriptManager()->injectedScriptIdFor(scriptState);
    184     String name = securityOrigin ? securityOrigin->toRawString() : "";
    185     m_frontend->executionContextCreated(ExecutionContextDescription::create()
    186         .setId(executionContextId)
    187         .setIsPageContext(isPageContext)
    188         .setName(name)
    189         .setFrameId(frameId)
    190         .release());
    191 }
    192 
    193 } // namespace WebCore
    194 
    195