1/* 2 * Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> 4 * Copyright (C) 2012 Google Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "InjectedScriptManager.h" 33 34#if ENABLE(INSPECTOR) 35 36#include "Completion.h" 37#include "InjectedScriptHost.h" 38#include "InjectedScriptSource.h" 39#include "InspectorValues.h" 40#include "JSInjectedScriptHost.h" 41#include "JSLock.h" 42#include "ScriptObject.h" 43#include "SourceCode.h" 44 45using namespace JSC; 46 47namespace Inspector { 48 49InjectedScriptManager::InjectedScriptManager(InspectorEnvironment& environment, PassRefPtr<InjectedScriptHost> injectedScriptHost) 50 : m_environment(environment) 51 , m_injectedScriptHost(injectedScriptHost) 52 , m_nextInjectedScriptId(1) 53{ 54} 55 56InjectedScriptManager::~InjectedScriptManager() 57{ 58} 59 60void InjectedScriptManager::disconnect() 61{ 62 discardInjectedScripts(); 63} 64 65InjectedScriptHost* InjectedScriptManager::injectedScriptHost() 66{ 67 return m_injectedScriptHost.get(); 68} 69 70InjectedScript InjectedScriptManager::injectedScriptForId(int id) 71{ 72 auto it = m_idToInjectedScript.find(id); 73 if (it != m_idToInjectedScript.end()) 74 return it->value; 75 76 for (auto it = m_scriptStateToId.begin(); it != m_scriptStateToId.end(); ++it) { 77 if (it->value == id) 78 return injectedScriptFor(it->key); 79 } 80 81 return InjectedScript(); 82} 83 84int InjectedScriptManager::injectedScriptIdFor(ExecState* scriptState) 85{ 86 auto it = m_scriptStateToId.find(scriptState); 87 if (it != m_scriptStateToId.end()) 88 return it->value; 89 90 int id = m_nextInjectedScriptId++; 91 m_scriptStateToId.set(scriptState, id); 92 return id; 93} 94 95InjectedScript InjectedScriptManager::injectedScriptForObjectId(const String& objectId) 96{ 97 RefPtr<InspectorValue> parsedObjectId = InspectorValue::parseJSON(objectId); 98 if (parsedObjectId && parsedObjectId->type() == InspectorValue::TypeObject) { 99 long injectedScriptId = 0; 100 bool success = parsedObjectId->asObject()->getNumber(ASCIILiteral("injectedScriptId"), &injectedScriptId); 101 if (success) 102 return m_idToInjectedScript.get(injectedScriptId); 103 } 104 105 return InjectedScript(); 106} 107 108void InjectedScriptManager::discardInjectedScripts() 109{ 110 m_injectedScriptHost->clearAllWrappers(); 111 m_idToInjectedScript.clear(); 112 m_scriptStateToId.clear(); 113} 114 115void InjectedScriptManager::releaseObjectGroup(const String& objectGroup) 116{ 117 for (auto it = m_idToInjectedScript.begin(); it != m_idToInjectedScript.end(); ++it) 118 it->value.releaseObjectGroup(objectGroup); 119} 120 121String InjectedScriptManager::injectedScriptSource() 122{ 123 return String(reinterpret_cast<const char*>(InjectedScriptSource_js), sizeof(InjectedScriptSource_js)); 124} 125 126Deprecated::ScriptObject InjectedScriptManager::createInjectedScript(const String& source, ExecState* scriptState, int id) 127{ 128 JSLockHolder lock(scriptState); 129 130 SourceCode sourceCode = makeSource(source); 131 JSGlobalObject* globalObject = scriptState->lexicalGlobalObject(); 132 JSValue globalThisValue = scriptState->globalThisValue(); 133 134 JSValue evaluationException; 135 InspectorEvaluateHandler evaluateHandler = m_environment.evaluateHandler(); 136 JSValue functionValue = evaluateHandler(scriptState, sourceCode, globalThisValue, &evaluationException); 137 if (evaluationException) 138 return Deprecated::ScriptObject(); 139 140 CallData callData; 141 CallType callType = getCallData(functionValue, callData); 142 if (callType == CallTypeNone) 143 return Deprecated::ScriptObject(); 144 145 MarkedArgumentBuffer args; 146 args.append(m_injectedScriptHost->jsWrapper(scriptState, globalObject)); 147 args.append(globalThisValue); 148 args.append(jsNumber(id)); 149 150 JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); 151 if (result.isObject()) 152 return Deprecated::ScriptObject(scriptState, result.getObject()); 153 154 return Deprecated::ScriptObject(); 155} 156 157InjectedScript InjectedScriptManager::injectedScriptFor(ExecState* inspectedExecState) 158{ 159 auto it = m_scriptStateToId.find(inspectedExecState); 160 if (it != m_scriptStateToId.end()) { 161 auto it1 = m_idToInjectedScript.find(it->value); 162 if (it1 != m_idToInjectedScript.end()) 163 return it1->value; 164 } 165 166 if (!m_environment.canAccessInspectedScriptState(inspectedExecState)) 167 return InjectedScript(); 168 169 int id = injectedScriptIdFor(inspectedExecState); 170 Deprecated::ScriptObject injectedScriptObject = createInjectedScript(injectedScriptSource(), inspectedExecState, id); 171 InjectedScript result(injectedScriptObject, &m_environment); 172 m_idToInjectedScript.set(id, result); 173 didCreateInjectedScript(result); 174 return result; 175} 176 177void InjectedScriptManager::didCreateInjectedScript(InjectedScript) 178{ 179 // Intentionally empty. This allows for subclasses to inject additional scripts. 180} 181 182} // namespace Inspector 183 184#endif // ENABLE(INSPECTOR) 185