Index: extensions/renderer/user_script_injection_list.cc |
diff --git a/extensions/renderer/user_script_injection_list.cc b/extensions/renderer/user_script_injection_list.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b46dc78e818818cfd93d00e25f87128518125b2d |
--- /dev/null |
+++ b/extensions/renderer/user_script_injection_list.cc |
@@ -0,0 +1,221 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "extensions/renderer/user_script_injection_list.h" |
+ |
+#include "content/public/common/url_constants.h" |
+#include "content/public/renderer/render_thread.h" |
+#include "extensions/common/extension.h" |
+#include "extensions/common/extension_messages.h" |
+#include "extensions/common/extension_set.h" |
+#include "extensions/common/permissions/permissions_data.h" |
+#include "extensions/renderer/extensions_renderer_client.h" |
+#include "extensions/renderer/script_context.h" |
+#include "extensions/renderer/user_script_injection.h" |
+#include "third_party/WebKit/public/web/WebDocument.h" |
+#include "third_party/WebKit/public/web/WebFrame.h" |
+#include "url/gurl.h" |
+ |
+namespace extensions { |
+ |
+// static |
+GURL UserScriptInjectionList::GetDocumentUrlForFrame(blink::WebFrame* frame) { |
+ GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame); |
+ if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) { |
+ data_source_url = GURL(content::kViewSourceScheme + std::string(":") + |
+ data_source_url.spec()); |
+ } |
+ |
+ return data_source_url; |
+} |
+ |
+UserScriptInjectionList::UserScriptInjectionList() { |
+ content::RenderThread::Get()->AddObserver(this); |
+} |
+ |
+UserScriptInjectionList::~UserScriptInjectionList() { |
+} |
+ |
+void UserScriptInjectionList::AddObserver(Observer* observer) { |
+ observers_.AddObserver(observer); |
+} |
+ |
+void UserScriptInjectionList::RemoveObserver(Observer* observer) { |
+ observers_.RemoveObserver(observer); |
+} |
+ |
+void UserScriptInjectionList::GetActiveExtensionIds( |
+ std::set<std::string>* ids) const { |
+ for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin(); |
+ iter != scripts_.end(); |
+ ++iter) { |
+ DCHECK(!(*iter)->extension_id().empty()); |
+ ids->insert((*iter)->extension_id()); |
+ } |
+} |
+ |
+void UserScriptInjectionList::GetInjections( |
+ ScopedVector<ScriptInjection>* injections, |
+ blink::WebFrame* web_frame, |
+ int tab_id, |
+ UserScript::RunLocation run_location, |
+ const GURL& document_url, |
+ const ExtensionSet* extensions) { |
+ for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin(); |
+ iter != scripts_.end(); |
+ ++iter) { |
+ const Extension* extension = extensions->GetByID((*iter)->extension_id()); |
+ if (!extension) |
+ continue; |
+ scoped_ptr<ScriptInjection> injection = GetInjectionForScript( |
+ *iter, web_frame, tab_id, run_location, document_url, extension); |
+ if (injection.get()) |
+ injections->push_back(injection.release()); |
+ } |
+} |
+ |
+bool UserScriptInjectionList::OnControlMessageReceived( |
+ const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(UserScriptInjectionList, message) |
+ IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+} |
+ |
+void UserScriptInjectionList::OnUpdateUserScripts( |
+ base::SharedMemoryHandle shared_memory, |
+ const std::set<std::string>& changed_extensions) { |
+ if (!base::SharedMemory::IsHandleValid(shared_memory)) { |
+ NOTREACHED() << "Bad scripts handle"; |
+ return; |
+ } |
+ |
+ for (std::set<std::string>::const_iterator iter = changed_extensions.begin(); |
+ iter != changed_extensions.end(); |
+ ++iter) { |
+ if (!Extension::IdIsValid(*iter)) { |
+ NOTREACHED() << "Invalid extension id: " << *iter; |
+ return; |
+ } |
+ } |
+ |
+ if (UpdateScripts(shared_memory)) { |
+ FOR_EACH_OBSERVER(Observer, |
+ observers_, |
+ OnUserScriptsUpdated(changed_extensions, scripts_.get())); |
+ } |
+} |
+ |
+bool UserScriptInjectionList::UpdateScripts( |
+ base::SharedMemoryHandle shared_memory) { |
+ bool only_inject_incognito = |
+ ExtensionsRendererClient::Get()->IsIncognitoProcess(); |
+ |
+ // Create the shared memory object (read only). |
+ shared_memory_.reset(new base::SharedMemory(shared_memory, true)); |
+ if (!shared_memory_.get()) |
+ return false; |
+ |
+ // First get the size of the memory block. |
+ if (!shared_memory_->Map(sizeof(Pickle::Header))) |
+ return false; |
+ Pickle::Header* pickle_header = |
+ reinterpret_cast<Pickle::Header*>(shared_memory_->memory()); |
+ |
+ // Now map in the rest of the block. |
+ int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size; |
+ shared_memory_->Unmap(); |
+ if (!shared_memory_->Map(pickle_size)) |
+ return false; |
+ |
+ // Unpickle scripts. |
+ uint64 num_scripts = 0; |
+ Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size); |
+ PickleIterator iter(pickle); |
+ CHECK(pickle.ReadUInt64(&iter, &num_scripts)); |
+ |
+ scripts_.clear(); |
+ scripts_.reserve(num_scripts); |
+ for (uint64 i = 0; i < num_scripts; ++i) { |
+ scoped_ptr<UserScript> script(new UserScript()); |
+ script->Unpickle(pickle, &iter); |
+ |
+ // Note that this is a pointer into shared memory. We don't own it. It gets |
+ // cleared up when the last renderer or browser process drops their |
+ // reference to the shared memory. |
+ for (size_t j = 0; j < script->js_scripts().size(); ++j) { |
+ const char* body = NULL; |
+ int body_length = 0; |
+ CHECK(pickle.ReadData(&iter, &body, &body_length)); |
+ script->js_scripts()[j].set_external_content( |
+ base::StringPiece(body, body_length)); |
+ } |
+ for (size_t j = 0; j < script->css_scripts().size(); ++j) { |
+ const char* body = NULL; |
+ int body_length = 0; |
+ CHECK(pickle.ReadData(&iter, &body, &body_length)); |
+ script->css_scripts()[j].set_external_content( |
+ base::StringPiece(body, body_length)); |
+ } |
+ |
+ if (only_inject_incognito && !script->is_incognito_enabled()) |
+ continue; // This script shouldn't run in an incognito tab. |
+ |
+ scripts_.push_back(script.release()); |
+ } |
+ |
+ return true; |
+} |
not at google - send to devlin
2014/06/15 23:53:38
blank line
Devlin
2014/06/16 18:11:17
Done.
|
+scoped_ptr<ScriptInjection> UserScriptInjectionList::GetInjectionForScript( |
+ UserScript* script, |
+ blink::WebFrame* web_frame, |
+ int tab_id, |
+ UserScript::RunLocation run_location, |
+ const GURL& document_url, |
+ const Extension* extension) { |
+ scoped_ptr<ScriptInjection> injection; |
+ if (web_frame->parent() && !script->match_all_frames()) |
+ return injection.Pass(); // Only match subframes if the script declared it. |
+ |
+ // Content scripts are not tab-specific. |
+ static const int kNoTabId = -1; |
+ // We don't have a process id in this context. |
+ static const int kNoProcessId = -1; |
+ |
+ GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( |
+ web_frame, document_url, script->match_about_blank()); |
+ |
+ if (!script->MatchesURL(effective_document_url)) |
+ return injection.Pass(); |
+ |
+ if (!extension->permissions_data()->CanRunContentScriptOnPage( |
+ extension, |
+ effective_document_url, |
+ web_frame->top()->document().url(), |
+ kNoTabId, |
+ kNoProcessId, |
not at google - send to devlin
2014/06/15 23:53:38
inling -1 with those comments "Content scripts are
Devlin
2014/06/16 18:11:17
Done.
|
+ NULL /* ignore error */)) { |
+ return injection.Pass(); |
+ } |
+ |
+ bool inject_css = !script->css_scripts().empty() && |
+ run_location == UserScript::DOCUMENT_START; |
+ bool inject_js = |
+ !script->js_scripts().empty() && script->run_location() == run_location; |
not at google - send to devlin
2014/06/15 23:53:38
this mixing of UserScriptInjection getting its pro
Devlin
2014/06/16 18:11:17
Caching script id is done because when we need to
|
+ if (inject_css || inject_js) { |
+ injection.reset(new UserScriptInjection(web_frame, |
+ extension->id(), |
+ run_location, |
+ tab_id, |
+ this, |
+ script, |
+ inject_js, |
+ inject_css)); |
+ } |
+ return injection.Pass(); |
+} |
+ |
+} // namespace extensions |