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