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

#include <map>

#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
#include "base/pickle.h"
#include "base/timer/elapsed_timer.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_handlers/csp_info.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/renderer/extension_helper.h"
#include "extensions/renderer/extensions_renderer_client.h"
#include "extensions/renderer/script_context.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "url/gurl.h"

using blink::WebFrame;
using blink::WebSecurityOrigin;
using blink::WebSecurityPolicy;
using blink::WebString;
using content::RenderThread;

namespace extensions {

int UserScriptSlave::GetIsolatedWorldIdForExtension(const Extension* extension,
                                                    WebFrame* frame) {
  static int g_next_isolated_world_id =
      ExtensionsRendererClient::Get()->GetLowestIsolatedWorldId();

  int id = 0;
  IsolatedWorldMap::iterator iter = isolated_world_ids_.find(extension->id());
  if (iter != isolated_world_ids_.end()) {
    id = iter->second;
  } else {
    id = g_next_isolated_world_id++;
    // This map will tend to pile up over time, but realistically, you're never
    // going to have enough extensions for it to matter.
    isolated_world_ids_[extension->id()] = id;
  }

  // We need to set the isolated world origin and CSP even if it's not a new
  // world since these are stored per frame, and we might not have used this
  // isolated world in this frame before.
  frame->setIsolatedWorldSecurityOrigin(
      id, WebSecurityOrigin::create(extension->url()));
  frame->setIsolatedWorldContentSecurityPolicy(
      id, WebString::fromUTF8(CSPInfo::GetContentSecurityPolicy(extension)));

  return id;
}

std::string UserScriptSlave::GetExtensionIdForIsolatedWorld(
    int isolated_world_id) {
  for (IsolatedWorldMap::iterator iter = isolated_world_ids_.begin();
       iter != isolated_world_ids_.end();
       ++iter) {
    if (iter->second == isolated_world_id)
      return iter->first;
  }
  return std::string();
}

void UserScriptSlave::RemoveIsolatedWorld(const std::string& extension_id) {
  isolated_world_ids_.erase(extension_id);
}

UserScriptSlave::UserScriptSlave(const ExtensionSet* extensions)
    : extensions_(extensions) {
}

UserScriptSlave::~UserScriptSlave() {
}

void UserScriptSlave::GetActiveExtensions(
    std::set<std::string>* extension_ids) {
  DCHECK(extension_ids);
  for (ScopedVector<ScriptInjection>::const_iterator iter =
           script_injections_.begin();
       iter != script_injections_.end();
       ++iter) {
    DCHECK(!(*iter)->extension_id().empty());
    extension_ids->insert((*iter)->extension_id());
  }
}

const Extension* UserScriptSlave::GetExtension(
    const std::string& extension_id) {
  return extensions_->GetByID(extension_id);
}

bool UserScriptSlave::UpdateScripts(
    base::SharedMemoryHandle shared_memory,
    const std::set<std::string>& changed_extensions) {
  bool only_inject_incognito =
      ExtensionsRendererClient::Get()->IsIncognitoProcess();

  // Create the shared memory object (read only).
  shared_memory_.reset(new base::SharedMemory(shared_memory, true));
  if (!shared_memory_.get())
    return false;

  // First get the size of the memory block.
  if (!shared_memory_->Map(sizeof(Pickle::Header)))
    return false;
  Pickle::Header* pickle_header =
      reinterpret_cast<Pickle::Header*>(shared_memory_->memory());

  // Now map in the rest of the block.
  int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size;
  shared_memory_->Unmap();
  if (!shared_memory_->Map(pickle_size))
    return false;

  // Unpickle scripts.
  uint64 num_scripts = 0;
  Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size);
  PickleIterator iter(pickle);
  CHECK(pickle.ReadUInt64(&iter, &num_scripts));

  // If we pass no explicit extension ids, we should refresh all extensions.
  bool include_all_extensions = changed_extensions.empty();

  // If we include all extensions, then we clear the script injections and
  // start from scratch. If not, then clear only the scripts for extension ids
  // that we are updating. This is important to maintain pending script
  // injection state for each ScriptInjection.
  if (include_all_extensions) {
    script_injections_.clear();
  } else {
    for (ScopedVector<ScriptInjection>::iterator iter =
             script_injections_.begin();
         iter != script_injections_.end();) {
      if (changed_extensions.count((*iter)->extension_id()) > 0)
        iter = script_injections_.erase(iter);
      else
        ++iter;
    }
  }

  script_injections_.reserve(num_scripts);
  for (uint64 i = 0; i < num_scripts; ++i) {
    scoped_ptr<UserScript> script(new UserScript());
    script->Unpickle(pickle, &iter);

    // Note that this is a pointer into shared memory. We don't own it. It gets
    // cleared up when the last renderer or browser process drops their
    // reference to the shared memory.
    for (size_t j = 0; j < script->js_scripts().size(); ++j) {
      const char* body = NULL;
      int body_length = 0;
      CHECK(pickle.ReadData(&iter, &body, &body_length));
      script->js_scripts()[j].set_external_content(
          base::StringPiece(body, body_length));
    }
    for (size_t j = 0; j < script->css_scripts().size(); ++j) {
      const char* body = NULL;
      int body_length = 0;
      CHECK(pickle.ReadData(&iter, &body, &body_length));
      script->css_scripts()[j].set_external_content(
          base::StringPiece(body, body_length));
    }

    if (only_inject_incognito && !script->is_incognito_enabled())
      continue; // This script shouldn't run in an incognito tab.

    // If we include all extensions or the given extension changed, we add a
    // new script injection.
    if (include_all_extensions ||
        changed_extensions.count(script->extension_id()) > 0) {
      script_injections_.push_back(new ScriptInjection(script.Pass(), this));
    } else {
      // Otherwise, we need to update the existing script injection with the
      // new user script (since the old content was invalidated).
      //
      // Note: Yes, this is O(n^2). But vectors are faster than maps for
      // relatively few elements, and less than 1% of our users actually have
      // enough content scripts for it to matter. If this changes, or if
      // std::maps get a much faster implementation, we should look into
      // making a map for script injections.
      for (ScopedVector<ScriptInjection>::iterator iter =
               script_injections_.begin();
           iter != script_injections_.end();
           ++iter) {
        if ((*iter)->script()->id() == script->id()) {
          (*iter)->SetScript(script.Pass());
          break;
        }
      }
    }
  }
  return true;
}

void UserScriptSlave::InjectScripts(WebFrame* frame,
                                    UserScript::RunLocation location) {
  GURL document_url = ScriptInjection::GetDocumentUrlForFrame(frame);
  if (document_url.is_empty())
    return;

  ScriptInjection::ScriptsRunInfo scripts_run_info;
  for (ScopedVector<ScriptInjection>::const_iterator iter =
           script_injections_.begin();
       iter != script_injections_.end();
       ++iter) {
    (*iter)->InjectIfAllowed(frame, location, document_url, &scripts_run_info);
  }

  LogScriptsRun(frame, location, scripts_run_info);
}

void UserScriptSlave::OnContentScriptGrantedPermission(
    content::RenderView* render_view, int request_id) {
  ScriptInjection::ScriptsRunInfo run_info;
  blink::WebFrame* frame = NULL;
  // Notify the injections that a request to inject has been granted.
  for (ScopedVector<ScriptInjection>::iterator iter =
           script_injections_.begin();
       iter != script_injections_.end();
       ++iter) {
    if ((*iter)->NotifyScriptPermitted(request_id,
                                       render_view,
                                       &run_info,
                                       &frame)) {
      DCHECK(frame);
      LogScriptsRun(frame, UserScript::RUN_DEFERRED, run_info);
      break;
    }
  }
}

void UserScriptSlave::FrameDetached(blink::WebFrame* frame) {
  for (ScopedVector<ScriptInjection>::iterator iter =
           script_injections_.begin();
       iter != script_injections_.end();
       ++iter) {
    (*iter)->FrameDetached(frame);
  }
}

void UserScriptSlave::LogScriptsRun(
    blink::WebFrame* frame,
    UserScript::RunLocation location,
    const ScriptInjection::ScriptsRunInfo& info) {
  // Notify the browser if any extensions are now executing scripts.
  if (!info.executing_scripts.empty()) {
    content::RenderView* render_view =
        content::RenderView::FromWebView(frame->view());
    render_view->Send(new ExtensionHostMsg_ContentScriptsExecuting(
        render_view->GetRoutingID(),
        info.executing_scripts,
        render_view->GetPageId(),
        ScriptContext::GetDataSourceURLForFrame(frame)));
  }

  switch (location) {
    case UserScript::DOCUMENT_START:
      UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_CssCount",
                               info.num_css);
      UMA_HISTOGRAM_COUNTS_100("Extensions.InjectStart_ScriptCount",
                               info.num_js);
      if (info.num_css || info.num_js)
        UMA_HISTOGRAM_TIMES("Extensions.InjectStart_Time",
                            info.timer.Elapsed());
      break;
    case UserScript::DOCUMENT_END:
      UMA_HISTOGRAM_COUNTS_100("Extensions.InjectEnd_ScriptCount", info.num_js);
      if (info.num_js)
        UMA_HISTOGRAM_TIMES("Extensions.InjectEnd_Time", info.timer.Elapsed());
      break;
    case UserScript::DOCUMENT_IDLE:
      UMA_HISTOGRAM_COUNTS_100("Extensions.InjectIdle_ScriptCount",
                               info.num_js);
      if (info.num_js)
        UMA_HISTOGRAM_TIMES("Extensions.InjectIdle_Time", info.timer.Elapsed());
      break;
    case UserScript::RUN_DEFERRED:
      // TODO(rdevlin.cronin): Add histograms.
      break;
    case UserScript::UNDEFINED:
    case UserScript::RUN_LOCATION_LAST:
      NOTREACHED();
  }
}

}  // namespace extensions
