// 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/programmatic_script_injector.h" #include #include "base/values.h" #include "content/public/renderer/render_view.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" #include "extensions/common/extension_messages.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/renderer/script_context.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebScriptSource.h" namespace extensions { ProgrammaticScriptInjector::ProgrammaticScriptInjector( const ExtensionMsg_ExecuteCode_Params& params, blink::WebFrame* web_frame) : params_(new ExtensionMsg_ExecuteCode_Params(params)), url_(ScriptContext::GetDataSourceURLForFrame(web_frame)), render_view_(content::RenderView::FromWebView(web_frame->view())), results_(new base::ListValue()), finished_(false) { } ProgrammaticScriptInjector::~ProgrammaticScriptInjector() { } UserScript::InjectionType ProgrammaticScriptInjector::script_type() const { return UserScript::PROGRAMMATIC_SCRIPT; } bool ProgrammaticScriptInjector::ShouldExecuteInChildFrames() const { return params_->all_frames; } bool ProgrammaticScriptInjector::ShouldExecuteInMainWorld() const { return params_->in_main_world; } bool ProgrammaticScriptInjector::IsUserGesture() const { return params_->user_gesture; } bool ProgrammaticScriptInjector::ExpectsResults() const { return params_->wants_result; } bool ProgrammaticScriptInjector::ShouldInjectJs( UserScript::RunLocation run_location) const { return GetRunLocation() == run_location && params_->is_javascript; } bool ProgrammaticScriptInjector::ShouldInjectCss( UserScript::RunLocation run_location) const { return GetRunLocation() == run_location && !params_->is_javascript; } PermissionsData::AccessType ProgrammaticScriptInjector::CanExecuteOnFrame( const Extension* extension, blink::WebFrame* frame, int tab_id, const GURL& top_url) const { GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( frame, frame->document().url(), params_->match_about_blank); if (params_->is_web_view) { if (frame->parent()) { // This is a subframe inside , so allow it. return PermissionsData::ACCESS_ALLOWED; } return effective_document_url == params_->webview_src ? PermissionsData::ACCESS_ALLOWED : PermissionsData::ACCESS_DENIED; } return extension->permissions_data()->GetPageAccess(extension, effective_document_url, top_url, tab_id, -1, // no process ID. NULL /* ignore error */); } std::vector ProgrammaticScriptInjector::GetJsSources( UserScript::RunLocation run_location) const { DCHECK_EQ(GetRunLocation(), run_location); DCHECK(params_->is_javascript); return std::vector( 1, blink::WebScriptSource( blink::WebString::fromUTF8(params_->code), params_->file_url)); } std::vector ProgrammaticScriptInjector::GetCssSources( UserScript::RunLocation run_location) const { DCHECK_EQ(GetRunLocation(), run_location); DCHECK(!params_->is_javascript); return std::vector(1, params_->code); } void ProgrammaticScriptInjector::OnInjectionComplete( scoped_ptr execution_results, ScriptsRunInfo* scripts_run_info, UserScript::RunLocation run_location) { results_ = execution_results.Pass(); Finish(std::string()); } void ProgrammaticScriptInjector::OnWillNotInject(InjectFailureReason reason) { std::string error; switch (reason) { case NOT_ALLOWED: error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage, url_.spec()); break; case EXTENSION_REMOVED: // no special error here. case WONT_INJECT: break; } Finish(error); } UserScript::RunLocation ProgrammaticScriptInjector::GetRunLocation() const { return static_cast(params_->run_at); } void ProgrammaticScriptInjector::Finish(const std::string& error) { DCHECK(!finished_); finished_ = true; render_view_->Send(new ExtensionHostMsg_ExecuteCodeFinished( render_view_->GetRoutingID(), params_->request_id, error, url_, *results_)); } } // namespace extensions