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 "bindings/v8/ScriptState.h" 37 #include "core/frame/FrameConsole.h" 38 #include "core/frame/LocalFrame.h" 39 #include "core/inspector/InjectedScript.h" 40 #include "core/inspector/InjectedScriptManager.h" 41 #include "core/inspector/InspectorPageAgent.h" 42 #include "core/inspector/InstrumentingAgents.h" 43 #include "core/page/Page.h" 44 #include "platform/weborigin/SecurityOrigin.h" 45 46 namespace WebCore { 47 48 PageRuntimeAgent::PageRuntimeAgent(InjectedScriptManager* injectedScriptManager, ScriptDebugServer* scriptDebugServer, Page* page, InspectorPageAgent* pageAgent) 49 : InspectorRuntimeAgent(injectedScriptManager, scriptDebugServer) 50 , m_inspectedPage(page) 51 , m_pageAgent(pageAgent) 52 , m_mainWorldContextCreated(false) 53 { 54 } 55 56 PageRuntimeAgent::~PageRuntimeAgent() 57 { 58 m_instrumentingAgents->setPageRuntimeAgent(0); 59 } 60 61 void PageRuntimeAgent::init() 62 { 63 m_instrumentingAgents->setPageRuntimeAgent(this); 64 } 65 66 void PageRuntimeAgent::enable(ErrorString* errorString) 67 { 68 if (m_enabled) 69 return; 70 71 InspectorRuntimeAgent::enable(errorString); 72 73 // Only report existing contexts if the page did commit load, otherwise we may 74 // unintentionally initialize contexts in the frames which may trigger some listeners 75 // that are expected to be triggered only after the load is committed, see http://crbug.com/131623 76 if (m_mainWorldContextCreated) 77 reportExecutionContextCreation(); 78 } 79 80 void PageRuntimeAgent::didClearDocumentOfWindowObject(LocalFrame* frame) 81 { 82 m_mainWorldContextCreated = true; 83 84 if (!m_enabled) 85 return; 86 ASSERT(m_frontend); 87 88 if (frame == m_inspectedPage->mainFrame()) { 89 m_scriptStateToId.clear(); 90 m_frontend->executionContextsCleared(); 91 } 92 String frameId = m_pageAgent->frameId(frame); 93 addExecutionContextToFrontend(ScriptState::forMainWorld(frame), true, "", frameId); 94 } 95 96 void PageRuntimeAgent::didCreateIsolatedContext(LocalFrame* frame, ScriptState* scriptState, SecurityOrigin* origin) 97 { 98 if (!m_enabled) 99 return; 100 ASSERT(m_frontend); 101 String frameId = m_pageAgent->frameId(frame); 102 addExecutionContextToFrontend(scriptState, false, origin->toRawString(), frameId); 103 } 104 105 InjectedScript PageRuntimeAgent::injectedScriptForEval(ErrorString* errorString, const int* executionContextId) 106 { 107 if (!executionContextId) { 108 ScriptState* scriptState = ScriptState::forMainWorld(m_inspectedPage->deprecatedLocalMainFrame()); 109 InjectedScript result = injectedScriptManager()->injectedScriptFor(scriptState); 110 if (result.isEmpty()) 111 *errorString = "Internal error: main world execution context not found."; 112 return result; 113 } 114 InjectedScript injectedScript = injectedScriptManager()->injectedScriptForId(*executionContextId); 115 if (injectedScript.isEmpty()) 116 *errorString = "Execution context with given id not found."; 117 return injectedScript; 118 } 119 120 void PageRuntimeAgent::muteConsole() 121 { 122 FrameConsole::mute(); 123 } 124 125 void PageRuntimeAgent::unmuteConsole() 126 { 127 FrameConsole::unmute(); 128 } 129 130 void PageRuntimeAgent::reportExecutionContextCreation() 131 { 132 Vector<std::pair<ScriptState*, SecurityOrigin*> > isolatedContexts; 133 for (Frame* frame = m_inspectedPage->mainFrame(); frame; frame = frame->tree().traverseNext()) { 134 if (!frame->isLocalFrame()) 135 continue; 136 LocalFrame* localFrame = toLocalFrame(frame); 137 if (!localFrame->script().canExecuteScripts(NotAboutToExecuteScript)) 138 continue; 139 String frameId = m_pageAgent->frameId(localFrame); 140 141 ScriptState* scriptState = ScriptState::forMainWorld(localFrame); 142 addExecutionContextToFrontend(scriptState, true, "", frameId); 143 localFrame->script().collectIsolatedContexts(isolatedContexts); 144 if (isolatedContexts.isEmpty()) 145 continue; 146 for (size_t i = 0; i< isolatedContexts.size(); i++) 147 addExecutionContextToFrontend(isolatedContexts[i].first, false, isolatedContexts[i].second->toRawString(), frameId); 148 isolatedContexts.clear(); 149 } 150 } 151 152 void PageRuntimeAgent::frameWindowDiscarded(LocalDOMWindow* window) 153 { 154 Vector<RefPtr<ScriptState> > scriptStatesToRemove; 155 for (ScriptStateToId::iterator it = m_scriptStateToId.begin(); it != m_scriptStateToId.end(); ++it) { 156 RefPtr<ScriptState> scriptState = it->key; 157 if (scriptState->contextIsEmpty() || window == scriptState->domWindow()) { 158 scriptStatesToRemove.append(scriptState); 159 m_frontend->executionContextDestroyed(it->value); 160 } 161 } 162 m_scriptStateToId.removeAll(scriptStatesToRemove); 163 } 164 165 } // namespace WebCore 166 167