1 /* 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Matt Lilek <webkit (at) 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 Computer, 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 "core/inspector/InjectedScriptManager.h" 33 34 #include "InjectedScriptSource.h" 35 #include "bindings/v8/ScriptObject.h" 36 #include "core/inspector/InjectedScript.h" 37 #include "core/inspector/InjectedScriptHost.h" 38 #include "core/inspector/JSONParser.h" 39 #include "platform/JSONValues.h" 40 #include "wtf/PassOwnPtr.h" 41 42 namespace WebCore { 43 44 PassOwnPtr<InjectedScriptManager> InjectedScriptManager::createForPage() 45 { 46 return adoptPtr(new InjectedScriptManager(&InjectedScriptManager::canAccessInspectedWindow)); 47 } 48 49 PassOwnPtr<InjectedScriptManager> InjectedScriptManager::createForWorker() 50 { 51 return adoptPtr(new InjectedScriptManager(&InjectedScriptManager::canAccessInspectedWorkerGlobalScope)); 52 } 53 54 InjectedScriptManager::InjectedScriptManager(InspectedStateAccessCheck accessCheck) 55 : m_nextInjectedScriptId(1) 56 , m_injectedScriptHost(InjectedScriptHost::create()) 57 , m_inspectedStateAccessCheck(accessCheck) 58 { 59 } 60 61 InjectedScriptManager::~InjectedScriptManager() 62 { 63 } 64 65 void InjectedScriptManager::disconnect() 66 { 67 m_injectedScriptHost->disconnect(); 68 m_injectedScriptHost.clear(); 69 } 70 71 InjectedScriptHost* InjectedScriptManager::injectedScriptHost() 72 { 73 return m_injectedScriptHost.get(); 74 } 75 76 InjectedScript InjectedScriptManager::injectedScriptForId(int id) 77 { 78 IdToInjectedScriptMap::iterator it = m_idToInjectedScript.find(id); 79 if (it != m_idToInjectedScript.end()) 80 return it->value; 81 for (ScriptStateToId::iterator it = m_scriptStateToId.begin(); it != m_scriptStateToId.end(); ++it) { 82 if (it->value == id) 83 return injectedScriptFor(it->key); 84 } 85 return InjectedScript(); 86 } 87 88 int InjectedScriptManager::injectedScriptIdFor(ScriptState* scriptState) 89 { 90 ScriptStateToId::iterator it = m_scriptStateToId.find(scriptState); 91 if (it != m_scriptStateToId.end()) 92 return it->value; 93 int id = m_nextInjectedScriptId++; 94 m_scriptStateToId.set(scriptState, id); 95 return id; 96 } 97 98 InjectedScript InjectedScriptManager::injectedScriptForObjectId(const String& objectId) 99 { 100 RefPtr<JSONValue> parsedObjectId = parseJSON(objectId); 101 if (parsedObjectId && parsedObjectId->type() == JSONValue::TypeObject) { 102 long injectedScriptId = 0; 103 bool success = parsedObjectId->asObject()->getNumber("injectedScriptId", &injectedScriptId); 104 if (success) 105 return m_idToInjectedScript.get(injectedScriptId); 106 } 107 return InjectedScript(); 108 } 109 110 void InjectedScriptManager::discardInjectedScripts() 111 { 112 m_idToInjectedScript.clear(); 113 m_scriptStateToId.clear(); 114 } 115 116 void InjectedScriptManager::discardInjectedScriptsFor(DOMWindow* window) 117 { 118 if (m_scriptStateToId.isEmpty()) 119 return; 120 121 Vector<long> idsToRemove; 122 IdToInjectedScriptMap::iterator end = m_idToInjectedScript.end(); 123 for (IdToInjectedScriptMap::iterator it = m_idToInjectedScript.begin(); it != end; ++it) { 124 ScriptState* scriptState = it->value.scriptState(); 125 if (window != scriptState->domWindow()) 126 continue; 127 m_scriptStateToId.remove(scriptState); 128 idsToRemove.append(it->key); 129 } 130 131 for (size_t i = 0; i < idsToRemove.size(); i++) 132 m_idToInjectedScript.remove(idsToRemove[i]); 133 134 // Now remove script states that have id but no injected script. 135 Vector<ScriptState*> scriptStatesToRemove; 136 for (ScriptStateToId::iterator it = m_scriptStateToId.begin(); it != m_scriptStateToId.end(); ++it) { 137 ScriptState* scriptState = it->key; 138 if (window == scriptState->domWindow()) 139 scriptStatesToRemove.append(scriptState); 140 } 141 for (size_t i = 0; i < scriptStatesToRemove.size(); i++) 142 m_scriptStateToId.remove(scriptStatesToRemove[i]); 143 } 144 145 bool InjectedScriptManager::canAccessInspectedWorkerGlobalScope(ScriptState*) 146 { 147 return true; 148 } 149 150 void InjectedScriptManager::releaseObjectGroup(const String& objectGroup) 151 { 152 Vector<int> keys; 153 keys.appendRange(m_idToInjectedScript.keys().begin(), m_idToInjectedScript.keys().end()); 154 for (Vector<int>::iterator k = keys.begin(); k != keys.end(); ++k) { 155 IdToInjectedScriptMap::iterator s = m_idToInjectedScript.find(*k); 156 if (s != m_idToInjectedScript.end()) 157 s->value.releaseObjectGroup(objectGroup); // m_idToInjectedScript may change here. 158 } 159 } 160 161 String InjectedScriptManager::injectedScriptSource() 162 { 163 return String(reinterpret_cast<const char*>(InjectedScriptSource_js), sizeof(InjectedScriptSource_js)); 164 } 165 166 InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* inspectedScriptState) 167 { 168 ScriptStateToId::iterator it = m_scriptStateToId.find(inspectedScriptState); 169 if (it != m_scriptStateToId.end()) { 170 IdToInjectedScriptMap::iterator it1 = m_idToInjectedScript.find(it->value); 171 if (it1 != m_idToInjectedScript.end()) 172 return it1->value; 173 } 174 175 if (!m_inspectedStateAccessCheck(inspectedScriptState)) 176 return InjectedScript(); 177 178 int id = injectedScriptIdFor(inspectedScriptState); 179 ScriptObject injectedScriptObject = createInjectedScript(injectedScriptSource(), inspectedScriptState, id); 180 InjectedScript result(injectedScriptObject, m_inspectedStateAccessCheck); 181 m_idToInjectedScript.set(id, result); 182 return result; 183 } 184 185 } // namespace WebCore 186 187