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

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/renderer/dispatcher.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 "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "v8/include/v8.h"

namespace {
// The length of time to wait after the DOM is complete to try and run user
// scripts.
const int kUserScriptIdleTimeoutMs = 200;
}

using blink::WebDocument;
using blink::WebFrame;
using blink::WebString;
using blink::WebVector;
using blink::WebView;

namespace extensions {

UserScriptScheduler::UserScriptScheduler(WebFrame* frame,
                                         Dispatcher* dispatcher)
    : weak_factory_(this),
      frame_(frame),
      current_location_(UserScript::UNDEFINED),
      has_run_idle_(false),
      dispatcher_(dispatcher) {
  for (int i = UserScript::UNDEFINED; i < UserScript::RUN_LOCATION_LAST; ++i) {
    pending_execution_map_[static_cast<UserScript::RunLocation>(i)] =
      std::queue<linked_ptr<ExtensionMsg_ExecuteCode_Params> >();
  }
}

UserScriptScheduler::~UserScriptScheduler() {
}

void UserScriptScheduler::ExecuteCode(
    const ExtensionMsg_ExecuteCode_Params& params) {
  UserScript::RunLocation run_at =
    static_cast<UserScript::RunLocation>(params.run_at);
  if (current_location_ < run_at) {
    pending_execution_map_[run_at].push(
        linked_ptr<ExtensionMsg_ExecuteCode_Params>(
            new ExtensionMsg_ExecuteCode_Params(params)));
    return;
  }

  ExecuteCodeImpl(params);
}

void UserScriptScheduler::DidCreateDocumentElement() {
  current_location_ = UserScript::DOCUMENT_START;
  MaybeRun();
}

void UserScriptScheduler::DidFinishDocumentLoad() {
  current_location_ = UserScript::DOCUMENT_END;
  MaybeRun();
  // Schedule a run for DOCUMENT_IDLE
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&UserScriptScheduler::IdleTimeout, weak_factory_.GetWeakPtr()),
      base::TimeDelta::FromMilliseconds(kUserScriptIdleTimeoutMs));
}

void UserScriptScheduler::DidFinishLoad() {
  current_location_ = UserScript::DOCUMENT_IDLE;
  // Ensure that running scripts does not keep any progress UI running.
  base::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&UserScriptScheduler::MaybeRun, weak_factory_.GetWeakPtr()));
}

void UserScriptScheduler::DidStartProvisionalLoad() {
  // The frame is navigating, so reset the state since we'll want to inject
  // scripts once the load finishes.
  current_location_ = UserScript::UNDEFINED;
  has_run_idle_ = false;
  weak_factory_.InvalidateWeakPtrs();
  std::map<UserScript::RunLocation, ExecutionQueue>::iterator itr =
    pending_execution_map_.begin();
  for (itr = pending_execution_map_.begin();
       itr != pending_execution_map_.end(); ++itr) {
    while (!itr->second.empty())
      itr->second.pop();
  }
}

void UserScriptScheduler::IdleTimeout() {
  current_location_ = UserScript::DOCUMENT_IDLE;
  MaybeRun();
}

void UserScriptScheduler::MaybeRun() {
  if (current_location_ == UserScript::UNDEFINED)
    return;

  if (!has_run_idle_ && current_location_ == UserScript::DOCUMENT_IDLE) {
    has_run_idle_ = true;
    dispatcher_->user_script_slave()->InjectScripts(
        frame_, UserScript::DOCUMENT_IDLE);
  }

  // Run all tasks from the current time and earlier.
  for (int i = UserScript::DOCUMENT_START;
       i <= current_location_; ++i) {
    UserScript::RunLocation run_time = static_cast<UserScript::RunLocation>(i);
    while (!pending_execution_map_[run_time].empty()) {
      linked_ptr<ExtensionMsg_ExecuteCode_Params>& params =
        pending_execution_map_[run_time].front();
      ExecuteCodeImpl(*params);
      pending_execution_map_[run_time].pop();
    }
  }
}

void UserScriptScheduler::ExecuteCodeImpl(
    const ExtensionMsg_ExecuteCode_Params& params) {
  const Extension* extension = dispatcher_->extensions()->GetByID(
      params.extension_id);
  content::RenderView* render_view =
      content::RenderView::FromWebView(frame_->view());
  ExtensionHelper* extension_helper = ExtensionHelper::Get(render_view);
  base::ListValue execution_results;

  // Since extension info is sent separately from user script info, they can
  // be out of sync. We just ignore this situation.
  if (!extension) {
    render_view->Send(
        new ExtensionHostMsg_ExecuteCodeFinished(render_view->GetRoutingID(),
                                                 params.request_id,
                                                 std::string(),  // no error
                                                 -1,
                                                 GURL(std::string()),
                                                 execution_results));
    return;
  }

  std::vector<WebFrame*> frame_vector;
  frame_vector.push_back(frame_);
  if (params.all_frames)
    GetAllChildFrames(frame_, &frame_vector);

  std::string error;

  scoped_ptr<blink::WebScopedUserGesture> gesture;
  if (params.user_gesture)
    gesture.reset(new blink::WebScopedUserGesture);

  GURL top_url = frame_->document().url();

  for (std::vector<WebFrame*>::iterator frame_it = frame_vector.begin();
       frame_it != frame_vector.end(); ++frame_it) {
    WebFrame* child_frame = *frame_it;
    CHECK(child_frame) << top_url;

    // We recheck access here in the renderer for extra safety against races
    // with navigation.
    //
    // But different frames can have different URLs, and the extension might
    // only have access to a subset of them. For the top frame, we can
    // immediately send an error and stop because the browser process
    // considers that an error too.
    //
    // For child frames, we just skip ones the extension doesn't have access
    // to and carry on.

    GURL document_url = ScriptContext::GetEffectiveDocumentURL(
        child_frame, child_frame->document().url(), params.match_about_blank);
    bool can_execute_script =
        extension->permissions_data()->CanAccessPage(extension,
                                                     document_url,
                                                     top_url,
                                                     extension_helper->tab_id(),
                                                     -1,     // no process ID.
                                                     NULL);  // ignore error.
    if ((!params.is_web_view && !can_execute_script) ||
        (params.is_web_view && document_url != params.webview_src)) {
      if (child_frame->parent()) {
        continue;
      } else {
        error = ErrorUtils::FormatErrorMessage(
            manifest_errors::kCannotAccessPage, document_url.spec());
        break;
      }
    }

    if (params.is_javascript) {
      blink::WebScriptSource source(
          WebString::fromUTF8(params.code), params.file_url);
      v8::HandleScope scope(v8::Isolate::GetCurrent());

      scoped_ptr<content::V8ValueConverter> v8_converter(
          content::V8ValueConverter::create());
      v8::Local<v8::Value> script_value;

      if (params.in_main_world) {
        DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId,
                                         extension->id());
        script_value = child_frame->executeScriptAndReturnValue(source);
      } else {
        blink::WebVector<v8::Local<v8::Value> > results;
        std::vector<blink::WebScriptSource> sources;
        sources.push_back(source);
        int isolated_world_id =
            dispatcher_->user_script_slave()->GetIsolatedWorldIdForExtension(
                extension, child_frame);
        DOMActivityLogger::AttachToWorld(isolated_world_id, extension->id());
        child_frame->executeScriptInIsolatedWorld(
            isolated_world_id, &sources.front(),
            sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS, &results);
        // We only expect one value back since we only pushed one source
        if (results.size() == 1 && !results[0].IsEmpty())
          script_value = results[0];
      }

      if (params.wants_result && !script_value.IsEmpty()) {
        // It's safe to always use the main world context when converting here.
        // V8ValueConverterImpl shouldn't actually care about the context scope,
        // and it switches to v8::Object's creation context when encountered.
        v8::Local<v8::Context> context = child_frame->mainWorldScriptContext();
        base::Value* result = v8_converter->FromV8Value(script_value, context);
        // Always append an execution result (i.e. no result == null result) so
        // that |execution_results| lines up with the frames.
        execution_results.Append(
            result ? result : base::Value::CreateNullValue());
      }
    } else {
      child_frame->document().insertStyleSheet(
          WebString::fromUTF8(params.code));
    }
  }

  render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
      render_view->GetRoutingID(),
      params.request_id,
      error,
      render_view->GetPageId(),
      ScriptContext::GetDataSourceURLForFrame(frame_),
      execution_results));
}

bool UserScriptScheduler::GetAllChildFrames(
    WebFrame* parent_frame,
    std::vector<WebFrame*>* frames_vector) const {
  if (!parent_frame)
    return false;

  for (WebFrame* child_frame = parent_frame->firstChild(); child_frame;
       child_frame = child_frame->nextSibling()) {
    frames_vector->push_back(child_frame);
    GetAllChildFrames(child_frame, frames_vector);
  }
  return true;
}

}  // namespace extensions
