| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/browser/extensions/api/tabs/execute_code_in_tab_function.h" | 5 #include "chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/extensions/api/tabs/tabs.h" | 10 #include "chrome/browser/extensions/api/tabs/tabs.h" |
| 11 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" | 11 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
| 12 #include "chrome/browser/extensions/extension_service.h" | 12 #include "chrome/browser/extensions/extension_service.h" |
| 13 #include "chrome/browser/extensions/extension_tab_util.h" | 13 #include "chrome/browser/extensions/extension_tab_util.h" |
| 14 #include "chrome/browser/extensions/tab_helper.h" | 14 #include "chrome/browser/extensions/tab_helper.h" |
| 15 #include "chrome/browser/extensions/file_reader.h" | 15 #include "chrome/browser/extensions/file_reader.h" |
| 16 #include "chrome/browser/extensions/script_executor.h" | 16 #include "chrome/browser/extensions/script_executor.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 19 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 19 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 20 #include "chrome/common/extensions/api/tabs.h" |
| 20 #include "chrome/common/extensions/extension.h" | 21 #include "chrome/common/extensions/extension.h" |
| 21 #include "chrome/common/extensions/extension_constants.h" | 22 #include "chrome/common/extensions/extension_constants.h" |
| 22 #include "chrome/common/extensions/extension_error_utils.h" | 23 #include "chrome/common/extensions/extension_error_utils.h" |
| 23 #include "chrome/common/extensions/extension_file_util.h" | 24 #include "chrome/common/extensions/extension_file_util.h" |
| 24 #include "chrome/common/extensions/extension_l10n_util.h" | 25 #include "chrome/common/extensions/extension_l10n_util.h" |
| 25 #include "chrome/common/extensions/extension_manifest_constants.h" | 26 #include "chrome/common/extensions/extension_manifest_constants.h" |
| 26 #include "chrome/common/extensions/extension_messages.h" | 27 #include "chrome/common/extensions/extension_messages.h" |
| 27 #include "chrome/common/extensions/message_bundle.h" | 28 #include "chrome/common/extensions/message_bundle.h" |
| 28 #include "content/public/browser/render_view_host.h" | 29 #include "content/public/browser/render_view_host.h" |
| 29 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
| 30 | 31 |
| 31 using content::BrowserThread; | 32 using content::BrowserThread; |
| 33 using extensions::api::tabs::InjectDetails; |
| 32 using extensions::ScriptExecutor; | 34 using extensions::ScriptExecutor; |
| 35 using extensions::UserScript; |
| 33 | 36 |
| 34 namespace keys = extensions::tabs_constants; | 37 namespace keys = extensions::tabs_constants; |
| 35 | 38 |
| 36 ExecuteCodeInTabFunction::ExecuteCodeInTabFunction() | 39 ExecuteCodeInTabFunction::ExecuteCodeInTabFunction() |
| 37 : execute_tab_id_(-1), | 40 : execute_tab_id_(-1) { |
| 38 all_frames_(false), | |
| 39 run_at_(extensions::UserScript::DOCUMENT_IDLE) { | |
| 40 } | 41 } |
| 41 | 42 |
| 42 ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {} | 43 ExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() {} |
| 43 | 44 |
| 45 bool ExecuteCodeInTabFunction::HasPermission() { |
| 46 if (Init() && |
| 47 extension_->HasAPIPermissionForTab(execute_tab_id_, |
| 48 extensions::APIPermission::kTab)) { |
| 49 return true; |
| 50 } |
| 51 return ExtensionFunction::HasPermission(); |
| 52 } |
| 53 |
| 44 bool ExecuteCodeInTabFunction::RunImpl() { | 54 bool ExecuteCodeInTabFunction::RunImpl() { |
| 45 DictionaryValue* script_info; | 55 EXTENSION_FUNCTION_VALIDATE(Init()); |
| 46 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &script_info)); | 56 |
| 47 size_t number_of_value = script_info->size(); | 57 if (!details_->code.get() && !details_->file.get()) { |
| 48 if (number_of_value == 0) { | |
| 49 error_ = keys::kNoCodeOrFileToExecuteError; | 58 error_ = keys::kNoCodeOrFileToExecuteError; |
| 50 return false; | 59 return false; |
| 51 } else { | 60 } |
| 52 bool has_code = script_info->HasKey(keys::kCodeKey); | 61 if (details_->code.get() && details_->file.get()) { |
| 53 bool has_file = script_info->HasKey(keys::kFileKey); | 62 error_ = keys::kMoreThanOneValuesError; |
| 54 if (has_code && has_file) { | 63 return false; |
| 55 error_ = keys::kMoreThanOneValuesError; | |
| 56 return false; | |
| 57 } else if (!has_code && !has_file) { | |
| 58 error_ = keys::kNoCodeOrFileToExecuteError; | |
| 59 return false; | |
| 60 } | |
| 61 } | 64 } |
| 62 | 65 |
| 63 execute_tab_id_ = -1; | |
| 64 Browser* browser = NULL; | |
| 65 TabContents* contents = NULL; | 66 TabContents* contents = NULL; |
| 66 | 67 |
| 67 // If |tab_id| is specified, look for it. Otherwise default to selected tab | 68 // If |tab_id| is specified, look for the tab. Otherwise default to selected |
| 68 // in the current window. | 69 // tab in the current window. |
| 69 Value* tab_value = NULL; | 70 CHECK_GE(execute_tab_id_, 0); |
| 70 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); | 71 if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(), |
| 71 if (tab_value->IsType(Value::TYPE_NULL)) { | 72 include_incognito(), |
| 72 browser = GetCurrentBrowser(); | 73 NULL, NULL, &contents, NULL)) { |
| 73 if (!browser) { | 74 return false; |
| 74 error_ = keys::kNoCurrentWindowError; | |
| 75 return false; | |
| 76 } | |
| 77 if (!ExtensionTabUtil::GetDefaultTab(browser, &contents, &execute_tab_id_)) | |
| 78 return false; | |
| 79 } else { | |
| 80 EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&execute_tab_id_)); | |
| 81 if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(), | |
| 82 include_incognito(), | |
| 83 &browser, NULL, &contents, NULL)) { | |
| 84 return false; | |
| 85 } | |
| 86 } | 75 } |
| 87 | 76 |
| 88 // NOTE: This can give the wrong answer due to race conditions, but it is OK, | 77 // NOTE: This can give the wrong answer due to race conditions, but it is OK, |
| 89 // we check again in the renderer. | 78 // we check again in the renderer. |
| 90 CHECK(browser); | |
| 91 CHECK(contents); | 79 CHECK(contents); |
| 92 if (!GetExtension()->CanExecuteScriptOnPage( | 80 if (!GetExtension()->CanExecuteScriptOnPage( |
| 93 contents->web_contents()->GetURL(), execute_tab_id_, NULL, &error_)) { | 81 contents->web_contents()->GetURL(), execute_tab_id_, NULL, &error_)) { |
| 94 return false; | 82 return false; |
| 95 } | 83 } |
| 96 | 84 |
| 97 if (script_info->HasKey(keys::kAllFramesKey)) { | 85 if (details_->code.get()) |
| 98 if (!script_info->GetBoolean(keys::kAllFramesKey, &all_frames_)) | 86 return Execute(*details_->code); |
| 99 return false; | |
| 100 } | |
| 101 | 87 |
| 102 if (script_info->HasKey(keys::kRunAtKey)) { | 88 CHECK(details_->file.get()); |
| 103 std::string run_string; | 89 resource_ = GetExtension()->GetResource(*details_->file); |
| 104 EXTENSION_FUNCTION_VALIDATE(script_info->GetString( | |
| 105 keys::kRunAtKey, &run_string)); | |
| 106 | 90 |
| 107 if (run_string == extension_manifest_values::kRunAtDocumentStart) | |
| 108 run_at_ = extensions::UserScript::DOCUMENT_START; | |
| 109 else if (run_string == extension_manifest_values::kRunAtDocumentEnd) | |
| 110 run_at_ = extensions::UserScript::DOCUMENT_END; | |
| 111 else if (run_string == extension_manifest_values::kRunAtDocumentIdle) | |
| 112 run_at_ = extensions::UserScript::DOCUMENT_IDLE; | |
| 113 else | |
| 114 EXTENSION_FUNCTION_VALIDATE(false); | |
| 115 } | |
| 116 | |
| 117 std::string code_string; | |
| 118 if (script_info->HasKey(keys::kCodeKey)) { | |
| 119 if (!script_info->GetString(keys::kCodeKey, &code_string)) | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 if (!code_string.empty()) | |
| 124 return Execute(code_string); | |
| 125 | |
| 126 std::string relative_path; | |
| 127 if (script_info->HasKey(keys::kFileKey)) { | |
| 128 if (!script_info->GetString(keys::kFileKey, &relative_path)) | |
| 129 return false; | |
| 130 resource_ = GetExtension()->GetResource(relative_path); | |
| 131 } | |
| 132 if (resource_.extension_root().empty() || resource_.relative_path().empty()) { | 91 if (resource_.extension_root().empty() || resource_.relative_path().empty()) { |
| 133 error_ = keys::kNoCodeOrFileToExecuteError; | 92 error_ = keys::kNoCodeOrFileToExecuteError; |
| 134 return false; | 93 return false; |
| 135 } | 94 } |
| 136 | 95 |
| 137 scoped_refptr<FileReader> file_reader(new FileReader( | 96 scoped_refptr<FileReader> file_reader(new FileReader( |
| 138 resource_, base::Bind(&ExecuteCodeInTabFunction::DidLoadFile, this))); | 97 resource_, base::Bind(&ExecuteCodeInTabFunction::DidLoadFile, this))); |
| 139 file_reader->Start(); | 98 file_reader->Start(); |
| 140 | 99 |
| 141 return true; | 100 return true; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 156 void TabsExecuteScriptFunction::OnExecuteCodeFinished(bool success, | 115 void TabsExecuteScriptFunction::OnExecuteCodeFinished(bool success, |
| 157 int32 page_id, | 116 int32 page_id, |
| 158 const std::string& error, | 117 const std::string& error, |
| 159 const ListValue& result) { | 118 const ListValue& result) { |
| 160 if (error.empty()) | 119 if (error.empty()) |
| 161 SetResult(result.DeepCopy()); | 120 SetResult(result.DeepCopy()); |
| 162 ExecuteCodeInTabFunction::OnExecuteCodeFinished(success, page_id, error, | 121 ExecuteCodeInTabFunction::OnExecuteCodeFinished(success, page_id, error, |
| 163 result); | 122 result); |
| 164 } | 123 } |
| 165 | 124 |
| 125 bool ExecuteCodeInTabFunction::Init() { |
| 126 if (details_.get()) |
| 127 return true; |
| 128 |
| 129 // |tab_id| is optional so it's ok if it's not there. |
| 130 int tab_id = -1; |
| 131 args_->GetInteger(0, &tab_id); |
| 132 |
| 133 // |details| are not optional. |
| 134 DictionaryValue* details_value = NULL; |
| 135 if (!args_->GetDictionary(1, &details_value)) |
| 136 return false; |
| 137 scoped_ptr<InjectDetails> details(new InjectDetails()); |
| 138 if (!InjectDetails::Populate(*details_value, details.get())) |
| 139 return false; |
| 140 |
| 141 // If the tab ID is -1 then it needs to be converted to the currently active |
| 142 // tab's ID. |
| 143 if (tab_id == -1) { |
| 144 Browser* browser = GetCurrentBrowser(); |
| 145 if (!browser) |
| 146 return false; |
| 147 TabContents* tab_contents = NULL; |
| 148 if (!ExtensionTabUtil::GetDefaultTab(browser, &tab_contents, &tab_id)) |
| 149 return false; |
| 150 } |
| 151 |
| 152 execute_tab_id_ = tab_id; |
| 153 details_ = details.Pass(); |
| 154 return true; |
| 155 } |
| 156 |
| 166 void ExecuteCodeInTabFunction::DidLoadFile(bool success, | 157 void ExecuteCodeInTabFunction::DidLoadFile(bool success, |
| 167 const std::string& data) { | 158 const std::string& data) { |
| 168 std::string function_name = name(); | 159 std::string function_name = name(); |
| 169 const extensions::Extension* extension = GetExtension(); | 160 const extensions::Extension* extension = GetExtension(); |
| 170 | 161 |
| 171 // Check if the file is CSS and needs localization. | 162 // Check if the file is CSS and needs localization. |
| 172 if (success && | 163 if (success && |
| 173 function_name == TabsInsertCSSFunction::function_name() && | 164 function_name == TabsInsertCSSFunction::function_name() && |
| 174 extension != NULL && | 165 extension != NULL && |
| 175 data.find( | 166 data.find( |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 return false; | 236 return false; |
| 246 | 237 |
| 247 ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT; | 238 ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT; |
| 248 std::string function_name = name(); | 239 std::string function_name = name(); |
| 249 if (function_name == TabsInsertCSSFunction::function_name()) { | 240 if (function_name == TabsInsertCSSFunction::function_name()) { |
| 250 script_type = ScriptExecutor::CSS; | 241 script_type = ScriptExecutor::CSS; |
| 251 } else if (function_name != TabsExecuteScriptFunction::function_name()) { | 242 } else if (function_name != TabsExecuteScriptFunction::function_name()) { |
| 252 NOTREACHED(); | 243 NOTREACHED(); |
| 253 } | 244 } |
| 254 | 245 |
| 246 ScriptExecutor::FrameScope frame_scope = |
| 247 details_->all_frames.get() && *details_->all_frames ? |
| 248 ScriptExecutor::ALL_FRAMES : |
| 249 ScriptExecutor::TOP_FRAME; |
| 250 |
| 251 UserScript::RunLocation run_at = UserScript::UNDEFINED; |
| 252 switch (details_->run_at) { |
| 253 case InjectDetails::RUN_AT_NONE: |
| 254 case InjectDetails::RUN_AT_DOCUMENT_IDLE: |
| 255 run_at = UserScript::DOCUMENT_IDLE; |
| 256 break; |
| 257 case InjectDetails::RUN_AT_DOCUMENT_START: |
| 258 run_at = UserScript::DOCUMENT_START; |
| 259 break; |
| 260 case InjectDetails::RUN_AT_DOCUMENT_END: |
| 261 run_at = UserScript::DOCUMENT_END; |
| 262 break; |
| 263 } |
| 264 CHECK_NE(UserScript::UNDEFINED, run_at); |
| 265 |
| 255 contents->extension_tab_helper()->script_executor()->ExecuteScript( | 266 contents->extension_tab_helper()->script_executor()->ExecuteScript( |
| 256 extension->id(), | 267 extension->id(), |
| 257 script_type, | 268 script_type, |
| 258 code_string, | 269 code_string, |
| 259 all_frames_ ? ScriptExecutor::ALL_FRAMES : ScriptExecutor::TOP_FRAME, | 270 frame_scope, |
| 260 run_at_, | 271 run_at, |
| 261 ScriptExecutor::ISOLATED_WORLD, | 272 ScriptExecutor::ISOLATED_WORLD, |
| 262 base::Bind(&ExecuteCodeInTabFunction::OnExecuteCodeFinished, this)); | 273 base::Bind(&ExecuteCodeInTabFunction::OnExecuteCodeFinished, this)); |
| 263 return true; | 274 return true; |
| 264 } | 275 } |
| OLD | NEW |