execute_code_in_tab_function.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/execute_code_in_tab_function.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_tabs_module.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_tabs_module_constants.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/file_reader.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h" 164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_constants.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_error_utils.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_service.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace keys = extension_tabs_module_constants; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickExecuteCodeInTabFunction::ExecuteCodeInTabFunction() 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : execute_tab_id_(-1), 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick all_frames_(false) { 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickExecuteCodeInTabFunction::~ExecuteCodeInTabFunction() { 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExecuteCodeInTabFunction::RunImpl() { 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* script_info; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &script_info)); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t number_of_value = script_info->size(); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (number_of_value == 0) { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCodeOrFileToExecuteError; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_code = script_info->HasKey(keys::kCodeKey); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_file = script_info->HasKey(keys::kFileKey); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (has_code && has_file) { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kMoreThanOneValuesError; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (!has_code && !has_file) { 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCodeOrFileToExecuteError; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch execute_tab_id_ = -1; 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = NULL; 54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If |tab_id| is specified, look for it. Otherwise default to selected tab 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in the current window. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Value* tab_value = NULL; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &tab_value)); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_value->IsType(Value::TYPE_NULL)) { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser = GetCurrentBrowser(); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser) { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCurrentWindowError; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ExtensionTabUtil::GetDefaultTab(browser, &contents, &execute_tab_id_)) 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXTENSION_FUNCTION_VALIDATE(tab_value->GetAsInteger(&execute_tab_id_)); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ExtensionTabUtil::GetTabById(execute_tab_id_, profile(), 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch include_incognito(), 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &browser, NULL, &contents, NULL)) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(browser); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(contents); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: This can give the wrong answer due to race conditions, but it is OK, 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we check again in the renderer. 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = GetExtension(); 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::vector<URLPattern> host_permissions = 84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick extension->host_permissions(); 85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!Extension::CanExecuteScriptOnPage( 86201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch contents->tab_contents()->GetURL(), 87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick extension->CanExecuteScriptEverywhere(), 88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &host_permissions, 89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NULL, 90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &error_)) { 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (script_info->HasKey(keys::kAllFramesKey)) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!script_info->GetBoolean(keys::kAllFramesKey, &all_frames_)) 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string code_string; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (script_info->HasKey(keys::kCodeKey)) { 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!script_info->GetString(keys::kCodeKey, &code_string)) 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!code_string.empty()) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!Execute(code_string)) 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string relative_path; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (script_info->HasKey(keys::kFileKey)) { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!script_info->GetString(keys::kFileKey, &relative_path)) 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource_ = GetExtension()->GetResource(relative_path); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (resource_.extension_root().empty() || resource_.relative_path().empty()) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = keys::kNoCodeOrFileToExecuteError; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<FileReader> file_reader(new FileReader( 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource_, NewCallback(this, &ExecuteCodeInTabFunction::DidLoadFile))); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_reader->Start(); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // Keep us alive until DidLoadFile is called. 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExecuteCodeInTabFunction::DidLoadFile(bool success, 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data) { 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success) { 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Execute(data); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX) 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(viettrungluu): bug: there's no particular reason the path should be 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // UTF-8, in which case this may fail. 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kLoadFileError, 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource_.relative_path().value()); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_WIN) 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kLoadFileError, 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WideToUTF8(resource_.relative_path().value())); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // OS_WIN 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // Balance the AddRef taken in RunImpl 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ExecuteCodeInTabFunction::Execute(const std::string& code_string) { 150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch TabContentsWrapper* contents = NULL; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = NULL; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = ExtensionTabUtil::GetTabById( 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch execute_tab_id_, profile(), include_incognito(), &browser, NULL, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &contents, NULL) && contents && browser; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!success) { 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = GetExtension(); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!extension) { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_js_code = true; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string function_name = name(); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (function_name == TabsInsertCSSFunction::function_name()) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_js_code = false; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (function_name != TabsExecuteScriptFunction::function_name()) { 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!contents->tab_contents()->ExecuteCode(request_id(), extension->id(), 176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch is_js_code, code_string, all_frames_)) { 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(false); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::TAB_CODE_EXECUTED, 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // balanced in Observe() 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExecuteCodeInTabFunction::Observe(NotificationType type, 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<int, bool>* result_details = 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<std::pair<int, bool> >(details).ptr(); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result_details->first == request_id()) { 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendResponse(result_details->second); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); // balanced in Execute() 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 196