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 33#if ENABLE(INSPECTOR) 34 35#include "PageRuntimeAgent.h" 36 37#include "Document.h" 38#include "InjectedScript.h" 39#include "InjectedScriptManager.h" 40#include "InspectorPageAgent.h" 41#include "InspectorState.h" 42#include "InstrumentingAgents.h" 43#include "Page.h" 44#include "PageConsole.h" 45#include "ScriptController.h" 46#include "SecurityOrigin.h" 47 48using WebCore::TypeBuilder::Runtime::ExecutionContextDescription; 49 50namespace WebCore { 51 52namespace PageRuntimeAgentState { 53static const char runtimeEnabled[] = "runtimeEnabled"; 54}; 55 56PageRuntimeAgent::PageRuntimeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InjectedScriptManager* injectedScriptManager, Page* page, InspectorPageAgent* pageAgent) 57 : InspectorRuntimeAgent(instrumentingAgents, state, injectedScriptManager) 58 , m_inspectedPage(page) 59 , m_pageAgent(pageAgent) 60 , m_frontend(0) 61 , m_mainWorldContextCreated(false) 62{ 63 m_instrumentingAgents->setPageRuntimeAgent(this); 64} 65 66PageRuntimeAgent::~PageRuntimeAgent() 67{ 68 m_instrumentingAgents->setPageRuntimeAgent(0); 69} 70 71void PageRuntimeAgent::setFrontend(InspectorFrontend* frontend) 72{ 73 m_frontend = frontend->runtime(); 74} 75 76void PageRuntimeAgent::clearFrontend() 77{ 78 m_frontend = 0; 79 String errorString; 80 disable(&errorString); 81} 82 83void PageRuntimeAgent::restore() 84{ 85 if (m_state->getBoolean(PageRuntimeAgentState::runtimeEnabled)) { 86 String error; 87 enable(&error); 88 } 89} 90 91void PageRuntimeAgent::enable(ErrorString* errorString) 92{ 93 if (m_enabled) 94 return; 95 96 InspectorRuntimeAgent::enable(errorString); 97 m_state->setBoolean(PageRuntimeAgentState::runtimeEnabled, true); 98 // Only report existing contexts if the page did commit load, otherwise we may 99 // unintentionally initialize contexts in the frames which may trigger some listeners 100 // that are expected to be triggered only after the load is committed, see http://crbug.com/131623 101 if (m_mainWorldContextCreated) 102 reportExecutionContextCreation(); 103} 104 105void PageRuntimeAgent::disable(ErrorString* errorString) 106{ 107 if (!m_enabled) 108 return; 109 110 InspectorRuntimeAgent::disable(errorString); 111 m_state->setBoolean(PageRuntimeAgentState::runtimeEnabled, false); 112} 113 114void PageRuntimeAgent::didCreateMainWorldContext(Frame* frame) 115{ 116 m_mainWorldContextCreated = true; 117 118 if (!m_enabled) 119 return; 120 ASSERT(m_frontend); 121 String frameId = m_pageAgent->frameId(frame); 122 ScriptState* scriptState = mainWorldScriptState(frame); 123 notifyContextCreated(frameId, scriptState, 0, true); 124} 125 126void PageRuntimeAgent::didCreateIsolatedContext(Frame* frame, ScriptState* scriptState, SecurityOrigin* origin) 127{ 128 if (!m_enabled) 129 return; 130 ASSERT(m_frontend); 131 String frameId = m_pageAgent->frameId(frame); 132 notifyContextCreated(frameId, scriptState, origin, false); 133} 134 135InjectedScript PageRuntimeAgent::injectedScriptForEval(ErrorString* errorString, const int* executionContextId) 136{ 137 if (!executionContextId) { 138 ScriptState* scriptState = mainWorldScriptState(m_inspectedPage->mainFrame()); 139 InjectedScript result = injectedScriptManager()->injectedScriptFor(scriptState); 140 if (result.hasNoValue()) 141 *errorString = "Internal error: main world execution context not found."; 142 return result; 143 } 144 InjectedScript injectedScript = injectedScriptManager()->injectedScriptForId(*executionContextId); 145 if (injectedScript.hasNoValue()) 146 *errorString = "Execution context with given id not found."; 147 return injectedScript; 148} 149 150void PageRuntimeAgent::muteConsole() 151{ 152 PageConsole::mute(); 153} 154 155void PageRuntimeAgent::unmuteConsole() 156{ 157 PageConsole::unmute(); 158} 159 160void PageRuntimeAgent::reportExecutionContextCreation() 161{ 162 Vector<std::pair<ScriptState*, SecurityOrigin*> > isolatedContexts; 163 for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) { 164 if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript)) 165 continue; 166 String frameId = m_pageAgent->frameId(frame); 167 168 ScriptState* scriptState = mainWorldScriptState(frame); 169 notifyContextCreated(frameId, scriptState, 0, true); 170 frame->script()->collectIsolatedContexts(isolatedContexts); 171 if (isolatedContexts.isEmpty()) 172 continue; 173 for (size_t i = 0; i< isolatedContexts.size(); i++) 174 notifyContextCreated(frameId, isolatedContexts[i].first, isolatedContexts[i].second, false); 175 isolatedContexts.clear(); 176 } 177} 178 179void PageRuntimeAgent::notifyContextCreated(const String& frameId, ScriptState* scriptState, SecurityOrigin* securityOrigin, bool isPageContext) 180{ 181 ASSERT(securityOrigin || isPageContext); 182 int executionContextId = injectedScriptManager()->injectedScriptIdFor(scriptState); 183 String name = securityOrigin ? securityOrigin->toRawString() : ""; 184 m_frontend->executionContextCreated(ExecutionContextDescription::create() 185 .setId(executionContextId) 186 .setIsPageContext(isPageContext) 187 .setName(name) 188 .setFrameId(frameId) 189 .release()); 190} 191 192} // namespace WebCore 193 194#endif // ENABLE(INSPECTOR) 195