| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/user_script_slave.h" | 5 #include "chrome/renderer/user_script_slave.h" |
| 6 | 6 |
| 7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/histogram.h" | 9 #include "base/histogram.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/perftimer.h" | 11 #include "base/perftimer.h" |
| 12 #include "base/pickle.h" | 12 #include "base/pickle.h" |
| 13 #include "base/shared_memory.h" | 13 #include "base/shared_memory.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "chrome/common/chrome_switches.h" | 15 #include "chrome/common/chrome_switches.h" |
| 16 #include "chrome/common/extensions/extension.h" | 16 #include "chrome/common/extensions/extension.h" |
| 17 #include "chrome/common/extensions/extension_constants.h" | 17 #include "chrome/common/extensions/extension_constants.h" |
| 18 #include "chrome/common/extensions/extension_message_bundle.h" |
| 19 #include "chrome/common/render_messages.h" |
| 18 #include "chrome/renderer/extension_groups.h" | 20 #include "chrome/renderer/extension_groups.h" |
| 19 #include "chrome/renderer/render_thread.h" | 21 #include "chrome/renderer/render_thread.h" |
| 20 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
| 21 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" | 23 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" |
| 22 | 24 |
| 23 #include "grit/renderer_resources.h" | 25 #include "grit/renderer_resources.h" |
| 24 | 26 |
| 25 using WebKit::WebFrame; | 27 using WebKit::WebFrame; |
| 26 using WebKit::WebString; | 28 using WebKit::WebString; |
| 27 | 29 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 48 | 50 |
| 49 int new_id = g_next_isolated_world_id; | 51 int new_id = g_next_isolated_world_id; |
| 50 ++g_next_isolated_world_id; | 52 ++g_next_isolated_world_id; |
| 51 | 53 |
| 52 // This map will tend to pile up over time, but realistically, you're never | 54 // This map will tend to pile up over time, but realistically, you're never |
| 53 // going to have enough extensions for it to matter. | 55 // going to have enough extensions for it to matter. |
| 54 g_isolated_world_ids[extension_id] = new_id; | 56 g_isolated_world_ids[extension_id] = new_id; |
| 55 return new_id; | 57 return new_id; |
| 56 } | 58 } |
| 57 | 59 |
| 58 UserScriptSlave::UserScriptSlave() | 60 UserScriptSlave::UserScriptSlave(RenderThreadBase* message_sender) |
| 59 : shared_memory_(NULL), | 61 : shared_memory_(NULL), |
| 60 script_deleter_(&scripts_) { | 62 script_deleter_(&scripts_), |
| 63 render_thread_(message_sender) { |
| 61 api_js_ = ResourceBundle::GetSharedInstance().GetRawDataResource( | 64 api_js_ = ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 62 IDR_GREASEMONKEY_API_JS); | 65 IDR_GREASEMONKEY_API_JS); |
| 63 } | 66 } |
| 64 | 67 |
| 65 void UserScriptSlave::GetActiveExtensions(std::set<std::string>* extension_ids)
{ | 68 void UserScriptSlave::GetActiveExtensions(std::set<std::string>* extension_ids)
{ |
| 66 for (size_t i = 0; i < scripts_.size(); ++i) { | 69 for (size_t i = 0; i < scripts_.size(); ++i) { |
| 67 DCHECK(!scripts_[i]->extension_id().empty()); | 70 DCHECK(!scripts_[i]->extension_id().empty()); |
| 68 extension_ids->insert(scripts_[i]->extension_id()); | 71 extension_ids->insert(scripts_[i]->extension_id()); |
| 69 } | 72 } |
| 70 } | 73 } |
| 71 | 74 |
| 72 bool UserScriptSlave::UpdateScripts(base::SharedMemoryHandle shared_memory) { | 75 // Fetches l10n messages from browser, and populates the map. |
| 76 // Returns empty map if extension_id is empty or content script doesn't have |
| 77 // css scripts. |
| 78 static void GetL10nMessagesForExtension( |
| 79 const UserScript* script, |
| 80 RenderThreadBase* message_sender, |
| 81 L10nMessagesMap* messages) { |
| 82 DCHECK(script); |
| 83 DCHECK(message_sender); |
| 84 DCHECK(messages); |
| 85 const std::string extension_id = script->extension_id(); |
| 86 if (!extension_id.empty() && !script->css_scripts().empty()) { |
| 87 // Always fetch messages, since files were updated. We don't want to have |
| 88 // stale content. |
| 89 message_sender->Send(new ViewHostMsg_GetExtensionMessageBundle( |
| 90 extension_id, messages)); |
| 91 } |
| 92 } |
| 93 |
| 94 // Sets external content for each js/css script file. |
| 95 // Message placeholders are replaced in scripts if localization catalog is |
| 96 // available and should_localize is true. |
| 97 static void SetExternalContent(const Pickle& pickle, |
| 98 void** iter, |
| 99 const L10nMessagesMap& l10n_messages, |
| 100 UserScript::File* script, |
| 101 bool should_localize) { |
| 102 const char* body = NULL; |
| 103 int body_length = 0; |
| 104 CHECK(pickle.ReadData(iter, &body, &body_length)); |
| 105 std::string localized_body(body, body_length); |
| 106 std::string error; |
| 107 if (!l10n_messages.empty() && should_localize) { |
| 108 ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary( |
| 109 l10n_messages, &localized_body, &error); |
| 110 } |
| 111 script->set_external_content( |
| 112 base::StringPiece(localized_body.data(), localized_body.length())); |
| 113 } |
| 114 |
| 115 bool UserScriptSlave::UpdateScripts(base::SharedMemoryHandle shared_memory, |
| 116 bool is_incognito_process) { |
| 73 scripts_.clear(); | 117 scripts_.clear(); |
| 74 | 118 |
| 75 bool only_inject_incognito = RenderThread::current()->is_incognito_process(); | |
| 76 | |
| 77 // Create the shared memory object (read only). | 119 // Create the shared memory object (read only). |
| 78 shared_memory_.reset(new base::SharedMemory(shared_memory, true)); | 120 shared_memory_.reset(new base::SharedMemory(shared_memory, true)); |
| 79 if (!shared_memory_.get()) | 121 if (!shared_memory_.get()) |
| 80 return false; | 122 return false; |
| 81 | 123 |
| 82 // First get the size of the memory block. | 124 // First get the size of the memory block. |
| 83 if (!shared_memory_->Map(sizeof(Pickle::Header))) | 125 if (!shared_memory_->Map(sizeof(Pickle::Header))) |
| 84 return false; | 126 return false; |
| 85 Pickle::Header* pickle_header = | 127 Pickle::Header* pickle_header = |
| 86 reinterpret_cast<Pickle::Header*>(shared_memory_->memory()); | 128 reinterpret_cast<Pickle::Header*>(shared_memory_->memory()); |
| 87 | 129 |
| 88 // Now map in the rest of the block. | 130 // Now map in the rest of the block. |
| 89 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size; | 131 int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size; |
| 90 shared_memory_->Unmap(); | 132 shared_memory_->Unmap(); |
| 91 if (!shared_memory_->Map(pickle_size)) | 133 if (!shared_memory_->Map(pickle_size)) |
| 92 return false; | 134 return false; |
| 93 | 135 |
| 94 // Unpickle scripts. | 136 // Unpickle scripts. |
| 95 void* iter = NULL; | 137 void* iter = NULL; |
| 96 size_t num_scripts = 0; | 138 size_t num_scripts = 0; |
| 97 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), | 139 Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), |
| 98 pickle_size); | 140 pickle_size); |
| 99 pickle.ReadSize(&iter, &num_scripts); | 141 pickle.ReadSize(&iter, &num_scripts); |
| 100 | |
| 101 scripts_.reserve(num_scripts); | 142 scripts_.reserve(num_scripts); |
| 102 for (size_t i = 0; i < num_scripts; ++i) { | 143 for (size_t i = 0; i < num_scripts; ++i) { |
| 103 scripts_.push_back(new UserScript()); | 144 scripts_.push_back(new UserScript()); |
| 104 UserScript* script = scripts_.back(); | 145 UserScript* script = scripts_.back(); |
| 105 script->Unpickle(pickle, &iter); | 146 script->Unpickle(pickle, &iter); |
| 106 | 147 |
| 148 // We need to fetch message catalogs for each script that has extension id |
| 149 // and at least one css script. |
| 150 L10nMessagesMap l10n_messages; |
| 151 GetL10nMessagesForExtension(script, render_thread_, &l10n_messages); |
| 152 |
| 107 // Note that this is a pointer into shared memory. We don't own it. It gets | 153 // Note that this is a pointer into shared memory. We don't own it. It gets |
| 108 // cleared up when the last renderer or browser process drops their | 154 // cleared up when the last renderer or browser process drops their |
| 109 // reference to the shared memory. | 155 // reference to the shared memory. |
| 110 for (size_t j = 0; j < script->js_scripts().size(); ++j) { | 156 for (size_t j = 0; j < script->js_scripts().size(); ++j) { |
| 111 const char* body = NULL; | 157 SetExternalContent( |
| 112 int body_length = 0; | 158 pickle, &iter, l10n_messages, &script->js_scripts()[j], false); |
| 113 CHECK(pickle.ReadData(&iter, &body, &body_length)); | |
| 114 script->js_scripts()[j].set_external_content( | |
| 115 base::StringPiece(body, body_length)); | |
| 116 } | 159 } |
| 117 for (size_t j = 0; j < script->css_scripts().size(); ++j) { | 160 for (size_t j = 0; j < script->css_scripts().size(); ++j) { |
| 118 const char* body = NULL; | 161 SetExternalContent( |
| 119 int body_length = 0; | 162 pickle, &iter, l10n_messages, &script->css_scripts()[j], true); |
| 120 CHECK(pickle.ReadData(&iter, &body, &body_length)); | |
| 121 script->css_scripts()[j].set_external_content( | |
| 122 base::StringPiece(body, body_length)); | |
| 123 } | 163 } |
| 124 | 164 |
| 125 if (only_inject_incognito && !script->is_incognito_enabled()) { | 165 if (is_incognito_process && !script->is_incognito_enabled()) { |
| 126 // This script shouldn't run in an incognito tab. | 166 // This script shouldn't run in an incognito tab. |
| 127 delete script; | 167 delete script; |
| 128 scripts_.pop_back(); | 168 scripts_.pop_back(); |
| 129 } | 169 } |
| 130 } | 170 } |
| 131 | 171 |
| 132 return true; | 172 return true; |
| 133 } | 173 } |
| 134 | 174 |
| 135 // static | 175 // static |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 if (num_scripts) | 276 if (num_scripts) |
| 237 UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", timer.Elapsed()); | 277 UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", timer.Elapsed()); |
| 238 } else { | 278 } else { |
| 239 NOTREACHED(); | 279 NOTREACHED(); |
| 240 } | 280 } |
| 241 | 281 |
| 242 LOG(INFO) << "Injected " << num_scripts << " scripts and " << num_css << | 282 LOG(INFO) << "Injected " << num_scripts << " scripts and " << num_css << |
| 243 "css files into " << frame->url().spec().data(); | 283 "css files into " << frame->url().spec().data(); |
| 244 return true; | 284 return true; |
| 245 } | 285 } |
| OLD | NEW |