1a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// found in the LICENSE file. 4a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 5a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/browser/extensions/api/execute_code_function.h" 6a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 7a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/browser/extensions/api/tabs/tabs_constants.h" 8a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/browser/extensions/script_executor.h" 9a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/common/extensions/api/i18n/default_locale_handler.h" 10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/common/extensions/extension_file_util.h" 11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/common/extensions/extension_messages.h" 12a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/common/extensions/message_bundle.h" 13a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "extensions/browser/file_reader.h" 14a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "extensions/common/error_utils.h" 15a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 16a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)namespace extensions { 17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 18a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)namespace keys = tabs_constants; 19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)using api::tabs::InjectDetails; 20a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)ExecuteCodeFunction::ExecuteCodeFunction() { 22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 23a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)ExecuteCodeFunction::~ExecuteCodeFunction() { 25a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 26a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ExecuteCodeFunction::DidLoadFile(bool success, 28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& data) { 29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const Extension* extension = GetExtension(); 30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Check if the file is CSS and needs localization. 32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (success && 33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ShouldInsertCSS() && 34a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) extension != NULL && 35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) data.find(MessageBundle::kMessageBegin) != std::string::npos) { 36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) content::BrowserThread::PostTask( 37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) content::BrowserThread::FILE, FROM_HERE, 38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::Bind(&ExecuteCodeFunction::LocalizeCSS, this, 39a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) data, 40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) extension->id(), 41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) extension->path(), 42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LocaleInfo::GetDefaultLocale(extension))); 43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DidLoadAndLocalizeFile(success, data); 45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ExecuteCodeFunction::LocalizeCSS( 49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& data, 50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& extension_id, 51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const base::FilePath& extension_path, 52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& extension_default_locale) { 53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) scoped_ptr<SubstitutionMap> localization_messages( 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) extension_file_util::LoadMessageBundleSubstitutionMap( 55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) extension_path, extension_id, extension_default_locale)); 56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // We need to do message replacement on the data, so it has to be mutable. 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::string css_data = data; 59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::string error; 60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) MessageBundle::ReplaceMessagesWithExternalDictionary(*localization_messages, 61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) &css_data, 62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) &error); 63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Call back DidLoadAndLocalizeFile on the UI thread. The success parameter 65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // is always true, because if loading had failed, we wouldn't have had 66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // anything to localize. 67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) content::BrowserThread::PostTask( 68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) content::BrowserThread::UI, FROM_HERE, 69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::Bind(&ExecuteCodeFunction::DidLoadAndLocalizeFile, this, 70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) true, css_data)); 71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ExecuteCodeFunction::DidLoadAndLocalizeFile(bool success, 74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& data) { 75a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (success) { 76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!Execute(data)) 77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SendResponse(false); 78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // TODO(viettrungluu): bug: there's no particular reason the path should be 80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // UTF-8, in which case this may fail. 81a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) error_ = ErrorUtils::FormatErrorMessage(keys::kLoadFileError, 82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) resource_.relative_path().AsUTF8Unsafe()); 83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SendResponse(false); 84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 86a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool ExecuteCodeFunction::Execute(const std::string& code_string) { 88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ScriptExecutor* executor = GetScriptExecutor(); 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!executor) 90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const Extension* extension = GetExtension(); 93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!extension) 94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ScriptExecutor::ScriptType script_type = ScriptExecutor::JAVASCRIPT; 97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (ShouldInsertCSS()) 98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) script_type = ScriptExecutor::CSS; 99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ScriptExecutor::FrameScope frame_scope = 101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) details_->all_frames.get() && *details_->all_frames ? 102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ScriptExecutor::ALL_FRAMES : 103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ScriptExecutor::TOP_FRAME; 104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) UserScript::RunLocation run_at = 106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) UserScript::UNDEFINED; 107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) switch (details_->run_at) { 108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case InjectDetails::RUN_AT_NONE: 109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case InjectDetails::RUN_AT_DOCUMENT_IDLE: 110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) run_at = UserScript::DOCUMENT_IDLE; 111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case InjectDetails::RUN_AT_DOCUMENT_START: 113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) run_at = UserScript::DOCUMENT_START; 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) case InjectDetails::RUN_AT_DOCUMENT_END: 116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) run_at = UserScript::DOCUMENT_END; 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CHECK_NE(UserScript::UNDEFINED, run_at); 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) executor->ExecuteScript( 122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) extension->id(), 123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) script_type, 124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) code_string, 125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) frame_scope, 126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) run_at, 127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ScriptExecutor::ISOLATED_WORLD, 128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) IsWebView(), 129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::Bind(&ExecuteCodeFunction::OnExecuteCodeFinished, this)); 130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return true; 131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool ExecuteCodeFunction::HasPermission() { 134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return true; 135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool ExecuteCodeFunction::RunImpl() { 138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(Init()); 139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!details_->code.get() && !details_->file.get()) { 141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) error_ = keys::kNoCodeOrFileToExecuteError; 142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (details_->code.get() && details_->file.get()) { 145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) error_ = keys::kMoreThanOneValuesError; 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!CanExecuteScriptOnPage()) 150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (details_->code.get()) 153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return Execute(*details_->code); 154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!details_->file.get()) 156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) resource_ = GetExtension()->GetResource(*details_->file); 158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (resource_.extension_root().empty() || resource_.relative_path().empty()) { 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) error_ = keys::kNoCodeOrFileToExecuteError; 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) scoped_refptr<FileReader> file_reader(new FileReader( 165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) resource_, base::Bind(&ExecuteCodeFunction::DidLoadFile, this))); 166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) file_reader->Start(); 167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return true; 169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ExecuteCodeFunction::OnExecuteCodeFinished( 172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& error, 173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int32 on_page_id, 174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const GURL& on_url, 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::ListValue& result) { 176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!error.empty()) 177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SetError(error); 178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SendResponse(error.empty()); 180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} // namespace extensions 183