// 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/script_injection.h"

#include <vector>

#include "base/lazy_instance.h"
#include "base/metrics/histogram.h"
#include "content/public/common/url_constants.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/renderer/dom_activity_logger.h"
#include "extensions/renderer/extension_groups.h"
#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/user_script_slave.h"
#include "grit/extensions_renderer_resources.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"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/resource/resource_bundle.h"
#include "url/gurl.h"

namespace extensions {

namespace {

// The id of the next pending injection.
int64 g_next_pending_id = 0;

// The number of an invalid request, which is used if the feature to delay
// script injection is not enabled.
const int64 kInvalidRequestId = -1;

// These two strings are injected before and after the Greasemonkey API and
// user script to wrap it in an anonymous scope.
const char kUserScriptHead[] = "(function (unsafeWindow) {\n";
const char kUserScriptTail[] = "\n})(window);";

// Greasemonkey API source that is injected with the scripts.
struct GreasemonkeyApiJsString {
  GreasemonkeyApiJsString();
  blink::WebScriptSource source;
};

// The below constructor, monstrous as it is, just makes a WebScriptSource from
// the GreasemonkeyApiJs resource.
GreasemonkeyApiJsString::GreasemonkeyApiJsString()
    : source(blink::WebScriptSource(blink::WebString::fromUTF8(
          ResourceBundle::GetSharedInstance().GetRawDataResource(
              IDR_GREASEMONKEY_API_JS).as_string()))) {
}

base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace

ScriptInjection::ScriptsRunInfo::ScriptsRunInfo() : num_css(0u), num_js(0u) {
}

ScriptInjection::ScriptsRunInfo::~ScriptsRunInfo() {
}

struct ScriptInjection::PendingInjection {
  PendingInjection(blink::WebFrame* web_frame,
                   UserScript::RunLocation run_location,
                   int page_id);
  ~PendingInjection();

  // The globally-unique id of this request.
  int64 id;

  // The pointer to the web frame into which the script should be injected.
  // This is weak, but safe because we remove pending requests when a frame is
  // terminated.
  blink::WebFrame* web_frame;

  // The run location to inject at.
  // Note: This could be a lie - we might inject well after this run location
  // has come and gone. But we need to know it to know which scripts to inject.
  UserScript::RunLocation run_location;

  // The corresponding page id, to protect against races.
  int page_id;
};

ScriptInjection::PendingInjection::PendingInjection(
    blink::WebFrame* web_frame,
    UserScript::RunLocation run_location,
    int page_id)
    : id(g_next_pending_id++),
      web_frame(web_frame),
      run_location(run_location),
      page_id(page_id) {
}

ScriptInjection::PendingInjection::~PendingInjection() {
}

// static
GURL ScriptInjection::GetDocumentUrlForFrame(blink::WebFrame* frame) {
  GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
  if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
    data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
                           data_source_url.spec());
  }

  return data_source_url;
}

ScriptInjection::ScriptInjection(
    scoped_ptr<UserScript> script,
    UserScriptSlave* user_script_slave)
    : script_(script.Pass()),
      extension_id_(script_->extension_id()),
      user_script_slave_(user_script_slave),
      is_standalone_or_emulate_greasemonkey_(
          script_->is_standalone() || script_->emulate_greasemonkey()) {
}

ScriptInjection::~ScriptInjection() {
}

void ScriptInjection::InjectIfAllowed(blink::WebFrame* frame,
                                      UserScript::RunLocation run_location,
                                      const GURL& document_url,
                                      ScriptsRunInfo* scripts_run_info) {
  if (!WantsToRun(frame, run_location, document_url))
    return;

  const Extension* extension = user_script_slave_->GetExtension(extension_id_);
  DCHECK(extension);  // WantsToRun() should be false if there's no extension.

  // We use the top render view here (instead of the render view for the
  // frame), because script injection on any frame requires permission for
  // the top frame. Additionally, if we have to show any UI for permissions,
  // it should only be done on the top frame.
  content::RenderView* top_render_view =
      content::RenderView::FromWebView(frame->top()->view());

  int tab_id = ExtensionHelper::Get(top_render_view)->tab_id();

  // By default, we allow injection.
  bool should_inject = true;

  // Check if the extension requires user consent for injection *and* we have a
  // valid tab id (if we don't have a tab id, we have no UI surface to ask for
  // user consent).
  if (tab_id != -1 &&
      extension->permissions_data()->RequiresActionForScriptExecution(
          extension, tab_id, frame->top()->document().url())) {
    int64 request_id = kInvalidRequestId;
    int page_id = top_render_view->GetPageId();

    // We only delay the injection if the feature is enabled.
    // Otherwise, we simply treat this as a notification by passing an invalid
    // id.
    if (FeatureSwitch::scripts_require_action()->IsEnabled()) {
      should_inject = false;
      ScopedVector<PendingInjection>::iterator pending_injection =
          pending_injections_.insert(
              pending_injections_.end(),
              new PendingInjection(frame, run_location, page_id));
      request_id = (*pending_injection)->id;
    }

    top_render_view->Send(
        new ExtensionHostMsg_RequestContentScriptPermission(
            top_render_view->GetRoutingID(),
            extension->id(),
            page_id,
            request_id));
  }

  if (should_inject)
    Inject(frame, run_location, scripts_run_info);
}

bool ScriptInjection::NotifyScriptPermitted(
    int64 request_id,
    content::RenderView* render_view,
    ScriptsRunInfo* scripts_run_info,
    blink::WebFrame** frame_out) {
  ScopedVector<PendingInjection>::iterator iter = pending_injections_.begin();
  while (iter != pending_injections_.end() && (*iter)->id != request_id)
    ++iter;

  // No matching request.
  if (iter == pending_injections_.end())
    return false;

  // We found the request, so pull it out of the pending list.
  scoped_ptr<PendingInjection> pending_injection(*iter);
  pending_injections_.weak_erase(iter);

  // Ensure the Page ID and Extension are still valid. Otherwise, don't inject.
  if (render_view->GetPageId() != pending_injection->page_id)
    return false;

  const Extension* extension = user_script_slave_->GetExtension(extension_id_);
  if (!extension)
    return false;

  // Everything matches! Inject the script.
  if (frame_out)
    *frame_out = pending_injection->web_frame;
  Inject(pending_injection->web_frame,
         pending_injection->run_location,
         scripts_run_info);
  return true;
}

void ScriptInjection::FrameDetached(blink::WebFrame* frame) {
  // Any pending injections associated with the given frame will never run.
  // Remove them.
  for (ScopedVector<PendingInjection>::iterator iter =
           pending_injections_.begin();
       iter != pending_injections_.end();) {
    if ((*iter)->web_frame == frame)
      iter = pending_injections_.erase(iter);
    else
      ++iter;
  }
}

void ScriptInjection::SetScript(scoped_ptr<UserScript> script) {
  script_.reset(script.release());
}

bool ScriptInjection::WantsToRun(blink::WebFrame* frame,
                                 UserScript::RunLocation run_location,
                                 const GURL& document_url) const {
  if (frame->parent() && !script_->match_all_frames())
    return false;  // Only match subframes if the script declared it wanted to.

  const Extension* extension = user_script_slave_->GetExtension(extension_id_);
  // Since extension info is sent separately from user script info, they can
  // be out of sync. We just ignore this situation.
  if (!extension)
    return false;

  // Content scripts are not tab-specific.
  static const int kNoTabId = -1;
  // We don't have a process id in this context.
  static const int kNoProcessId = -1;

  GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
      frame, document_url, script_->match_about_blank());

  if (!script_->MatchesURL(effective_document_url))
    return false;

  if (!extension->permissions_data()->CanRunContentScriptOnPage(
          extension,
          effective_document_url,
          frame->top()->document().url(),
          kNoTabId,
          kNoProcessId,
          NULL /* ignore error */)) {
    return false;
  }

  return ShouldInjectCSS(run_location) || ShouldInjectJS(run_location);
}

void ScriptInjection::Inject(blink::WebFrame* frame,
                             UserScript::RunLocation run_location,
                             ScriptsRunInfo* scripts_run_info) const {
  DCHECK(frame);
  DCHECK(scripts_run_info);
  DCHECK(WantsToRun(frame, run_location, GetDocumentUrlForFrame(frame)));
  DCHECK(user_script_slave_->GetExtension(extension_id_));

  if (ShouldInjectCSS(run_location))
    InjectCSS(frame, scripts_run_info);
  if (ShouldInjectJS(run_location))
    InjectJS(frame, scripts_run_info);
}

bool ScriptInjection::ShouldInjectJS(UserScript::RunLocation run_location)
    const {
  return !script_->js_scripts().empty() &&
         script_->run_location() == run_location;
}

bool ScriptInjection::ShouldInjectCSS(UserScript::RunLocation run_location)
    const {
  return !script_->css_scripts().empty() &&
         run_location == UserScript::DOCUMENT_START;
}

void ScriptInjection::InjectJS(blink::WebFrame* frame,
                               ScriptsRunInfo* scripts_run_info) const {
  const UserScript::FileList& js_scripts = script_->js_scripts();
  std::vector<blink::WebScriptSource> sources;
  scripts_run_info->num_js += js_scripts.size();
  for (UserScript::FileList::const_iterator iter = js_scripts.begin();
       iter != js_scripts.end();
       ++iter) {
    std::string content = iter->GetContent().as_string();

    // We add this dumb function wrapper for standalone user script to
    // emulate what Greasemonkey does.
    // TODO(aa): I think that maybe "is_standalone" scripts don't exist
    // anymore. Investigate.
    if (is_standalone_or_emulate_greasemonkey_) {
      content.insert(0, kUserScriptHead);
      content += kUserScriptTail;
    }
    sources.push_back(blink::WebScriptSource(
        blink::WebString::fromUTF8(content), iter->url()));
  }

  // Emulate Greasemonkey API for scripts that were converted to extensions
  // and "standalone" user scripts.
  if (is_standalone_or_emulate_greasemonkey_)
    sources.insert(sources.begin(), g_greasemonkey_api.Get().source);

  int isolated_world_id =
      user_script_slave_->GetIsolatedWorldIdForExtension(
          user_script_slave_->GetExtension(extension_id_), frame);
  base::ElapsedTimer exec_timer;
  DOMActivityLogger::AttachToWorld(isolated_world_id, extension_id_);
  frame->executeScriptInIsolatedWorld(isolated_world_id,
                                      &sources.front(),
                                      sources.size(),
                                      EXTENSION_GROUP_CONTENT_SCRIPTS);
  UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());

  for (std::vector<blink::WebScriptSource>::const_iterator iter =
           sources.begin();
       iter != sources.end();
       ++iter) {
    scripts_run_info->executing_scripts[extension_id_].insert(
        GURL(iter->url).path());
  }
}

void ScriptInjection::InjectCSS(blink::WebFrame* frame,
                                ScriptsRunInfo* scripts_run_info) const {
  const UserScript::FileList& css_scripts = script_->css_scripts();
  scripts_run_info->num_css += css_scripts.size();
  for (UserScript::FileList::const_iterator iter = css_scripts.begin();
       iter != css_scripts.end();
       ++iter) {
    frame->document().insertStyleSheet(
        blink::WebString::fromUTF8(iter->GetContent().as_string()));
  }
}

}  // namespace extensions
