/*
 * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2014 Opera Software ASA. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "bindings/core/v8/ScriptController.h"

#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "bindings/core/v8/WindowProxy.h"
#include "core/dom/Document.h"
#include "core/dom/ScriptableDocumentParser.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameClient.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLPlugInElement.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/inspector/MainThreadDebugger.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/NavigationScheduler.h"
#include "core/loader/ProgressTracker.h"
#include "core/plugins/PluginView.h"
#include "core/probe/CoreProbes.h"
#include "platform/FrameViewBase.h"
#include "platform/Histogram.h"
#include "platform/UserGestureIndicator.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/wtf/CurrentTime.h"
#include "platform/wtf/StdLibExtras.h"
#include "platform/wtf/StringExtras.h"
#include "platform/wtf/text/CString.h"
#include "platform/wtf/text/StringBuilder.h"

namespace blink {

DEFINE_TRACE(ScriptController) {
  visitor->Trace(frame_);
  visitor->Trace(window_proxy_manager_);
}

void ScriptController::ClearForClose() {
  window_proxy_manager_->ClearForClose();
  MainThreadDebugger::Instance()->DidClearContextsForFrame(GetFrame());
}

void ScriptController::UpdateSecurityOrigin(SecurityOrigin* security_origin) {
  window_proxy_manager_->UpdateSecurityOrigin(security_origin);
}

namespace {

V8CacheOptions CacheOptions(const ScriptResource* resource,
                            const Settings* settings) {
  V8CacheOptions v8_cache_options(kV8CacheOptionsDefault);
  if (settings)
    v8_cache_options = settings->GetV8CacheOptions();
  if (resource && !resource->GetResponse().CacheStorageCacheName().IsNull()) {
    switch (settings->GetV8CacheStrategiesForCacheStorage()) {
      case V8CacheStrategiesForCacheStorage::kNone:
        v8_cache_options = kV8CacheOptionsNone;
        break;
      case V8CacheStrategiesForCacheStorage::kNormal:
        v8_cache_options = kV8CacheOptionsCode;
        break;
      case V8CacheStrategiesForCacheStorage::kDefault:
      case V8CacheStrategiesForCacheStorage::kAggressive:
        v8_cache_options = kV8CacheOptionsAlways;
        break;
    }
  }
  return v8_cache_options;
}

}  // namespace

v8::Local<v8::Value> ScriptController::ExecuteScriptAndReturnValue(
    v8::Local<v8::Context> context,
    const ScriptSourceCode& source,
    AccessControlStatus access_control_status) {
  TRACE_EVENT1(
      "devtools.timeline", "EvaluateScript", "data",
      InspectorEvaluateScriptEvent::Data(GetFrame(), source.Url().GetString(),
                                         source.StartPosition()));
  v8::Local<v8::Value> result;
  {
    V8CacheOptions v8_cache_options =
        CacheOptions(source.GetResource(), GetFrame()->GetSettings());

    // Isolate exceptions that occur when compiling and executing
    // the code. These exceptions should not interfere with
    // javascript code we might evaluate from C++ when returning
    // from here.
    v8::TryCatch try_catch(GetIsolate());
    try_catch.SetVerbose(true);

    v8::Local<v8::Script> script;
    if (!V8ScriptRunner::CompileScript(source, GetIsolate(),
                                       access_control_status, v8_cache_options)
             .ToLocal(&script))
      return result;

    if (!V8ScriptRunner::RunCompiledScript(GetIsolate(), script,
                                           GetFrame()->GetDocument())
             .ToLocal(&result))
      return result;
  }

  return result;
}

bool ScriptController::ShouldBypassMainWorldCSP() {
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> context = GetIsolate()->GetCurrentContext();
  if (context.IsEmpty() || !ToLocalDOMWindow(context))
    return false;
  DOMWrapperWorld& world = DOMWrapperWorld::Current(GetIsolate());
  return world.IsIsolatedWorld() ? world.IsolatedWorldHasContentSecurityPolicy()
                                 : false;
}

TextPosition ScriptController::EventHandlerPosition() const {
  ScriptableDocumentParser* parser =
      GetFrame()->GetDocument()->GetScriptableDocumentParser();
  if (parser)
    return parser->GetTextPosition();
  return TextPosition::MinimumPosition();
}

void ScriptController::EnableEval() {
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> v8_context =
      window_proxy_manager_->MainWorldProxyMaybeUninitialized()
          ->ContextIfInitialized();
  if (v8_context.IsEmpty())
    return;
  v8_context->AllowCodeGenerationFromStrings(true);
}

void ScriptController::DisableEval(const String& error_message) {
  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Context> v8_context =
      window_proxy_manager_->MainWorldProxyMaybeUninitialized()
          ->ContextIfInitialized();
  if (v8_context.IsEmpty())
    return;
  v8_context->AllowCodeGenerationFromStrings(false);
  v8_context->SetErrorMessageForCodeGenerationFromStrings(
      V8String(GetIsolate(), error_message));
}

V8Extensions& ScriptController::RegisteredExtensions() {
  DEFINE_STATIC_LOCAL(V8Extensions, extensions, ());
  return extensions;
}

void ScriptController::RegisterExtensionIfNeeded(v8::Extension* extension) {
  const V8Extensions& extensions = RegisteredExtensions();
  for (size_t i = 0; i < extensions.size(); ++i) {
    if (extensions[i] == extension)
      return;
  }
  v8::RegisterExtension(extension);
  RegisteredExtensions().push_back(extension);
}

void ScriptController::ClearWindowProxy() {
  // V8 binding expects ScriptController::clearWindowProxy only be called when a
  // frame is loading a new page. This creates a new context for the new page.
  window_proxy_manager_->ClearForNavigation();
  MainThreadDebugger::Instance()->DidClearContextsForFrame(GetFrame());
}

void ScriptController::UpdateDocument() {
  window_proxy_manager_->MainWorldProxyMaybeUninitialized()->UpdateDocument();
}

bool ScriptController::ExecuteScriptIfJavaScriptURL(const KURL& url,
                                                    Element* element) {
  if (!url.ProtocolIsJavaScript())
    return false;

  const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
  String script_source = DecodeURLEscapeSequences(url.GetString())
                             .Substring(kJavascriptSchemeLength);

  bool should_bypass_main_world_content_security_policy =
      ContentSecurityPolicy::ShouldBypassMainWorld(GetFrame()->GetDocument());
  if (!GetFrame()->GetPage() ||
      (!should_bypass_main_world_content_security_policy &&
       !GetFrame()
            ->GetDocument()
            ->GetContentSecurityPolicy()
            ->AllowJavaScriptURLs(element, script_source,
                                  GetFrame()->GetDocument()->Url(),
                                  EventHandlerPosition().line_))) {
    return true;
  }

  bool progress_notifications_needed =
      GetFrame()->Loader().StateMachine()->IsDisplayingInitialEmptyDocument() &&
      !GetFrame()->IsLoading();
  if (progress_notifications_needed)
    GetFrame()->Loader().Progress().ProgressStarted(kFrameLoadTypeStandard);

  Document* owner_document = GetFrame()->GetDocument();

  bool location_change_before =
      GetFrame()->GetNavigationScheduler().LocationChangePending();

  v8::HandleScope handle_scope(GetIsolate());
  v8::Local<v8::Value> result = EvaluateScriptInMainWorld(
      ScriptSourceCode(script_source), kNotSharableCrossOrigin,
      kDoNotExecuteScriptWhenScriptsDisabled);

  // If executing script caused this frame to be removed from the page, we
  // don't want to try to replace its document!
  if (!GetFrame()->GetPage())
    return true;

  if (result.IsEmpty() || !result->IsString()) {
    if (progress_notifications_needed)
      GetFrame()->Loader().Progress().ProgressCompleted();
    return true;
  }
  String script_result = ToCoreString(v8::Local<v8::String>::Cast(result));

  // We're still in a frame, so there should be a DocumentLoader.
  DCHECK(GetFrame()->GetDocument()->Loader());
  if (!location_change_before &&
      GetFrame()->GetNavigationScheduler().LocationChangePending())
    return true;

  GetFrame()->Loader().ReplaceDocumentWhileExecutingJavaScriptURL(
      script_result, owner_document);
  return true;
}

void ScriptController::ExecuteScriptInMainWorld(const String& script,
                                                ExecuteScriptPolicy policy) {
  v8::HandleScope handle_scope(GetIsolate());
  EvaluateScriptInMainWorld(ScriptSourceCode(script), kNotSharableCrossOrigin,
                            policy);
}

void ScriptController::ExecuteScriptInMainWorld(
    const ScriptSourceCode& source_code,
    AccessControlStatus access_control_status) {
  v8::HandleScope handle_scope(GetIsolate());
  EvaluateScriptInMainWorld(source_code, access_control_status,
                            kDoNotExecuteScriptWhenScriptsDisabled);
}

v8::Local<v8::Value> ScriptController::ExecuteScriptInMainWorldAndReturnValue(
    const ScriptSourceCode& source_code,
    ExecuteScriptPolicy policy) {
  return EvaluateScriptInMainWorld(source_code, kNotSharableCrossOrigin,
                                   policy);
}

v8::Local<v8::Value> ScriptController::EvaluateScriptInMainWorld(
    const ScriptSourceCode& source_code,
    AccessControlStatus access_control_status,
    ExecuteScriptPolicy policy) {
  if (policy == kDoNotExecuteScriptWhenScriptsDisabled &&
      !GetFrame()->GetDocument()->CanExecuteScripts(kAboutToExecuteScript))
    return v8::Local<v8::Value>();

  // TODO(dcheng): Clean this up to not use ScriptState, to match
  // executeScriptInIsolatedWorld.
  ScriptState* script_state = ToScriptStateForMainWorld(GetFrame());
  if (!script_state)
    return v8::Local<v8::Value>();
  v8::EscapableHandleScope handle_scope(GetIsolate());
  ScriptState::Scope scope(script_state);

  if (GetFrame()->Loader().StateMachine()->IsDisplayingInitialEmptyDocument())
    GetFrame()->Loader().DidAccessInitialDocument();

  v8::Local<v8::Value> object = ExecuteScriptAndReturnValue(
      script_state->GetContext(), source_code, access_control_status);

  if (object.IsEmpty())
    return v8::Local<v8::Value>();

  return handle_scope.Escape(object);
}

void ScriptController::ExecuteScriptInIsolatedWorld(
    int world_id,
    const HeapVector<ScriptSourceCode>& sources,
    Vector<v8::Local<v8::Value>>* results) {
  DCHECK_GT(world_id, 0);

  RefPtr<DOMWrapperWorld> world =
      DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), world_id);
  LocalWindowProxy* isolated_world_window_proxy = WindowProxy(*world);
  // TODO(dcheng): Context must always be initialized here, due to the call to
  // windowProxy() on the previous line. Add a helper which makes that obvious?
  v8::Local<v8::Context> context =
      isolated_world_window_proxy->ContextIfInitialized();
  v8::Context::Scope scope(context);
  v8::Local<v8::Array> result_array =
      v8::Array::New(GetIsolate(), sources.size());

  for (size_t i = 0; i < sources.size(); ++i) {
    v8::Local<v8::Value> evaluation_result =
        ExecuteScriptAndReturnValue(context, sources[i]);
    if (evaluation_result.IsEmpty())
      evaluation_result =
          v8::Local<v8::Value>::New(GetIsolate(), v8::Undefined(GetIsolate()));
    bool did_create;
    if (!result_array->CreateDataProperty(context, i, evaluation_result)
             .To(&did_create) ||
        !did_create)
      return;
  }

  if (results) {
    for (size_t i = 0; i < result_array->Length(); ++i) {
      v8::Local<v8::Value> value;
      if (!result_array->Get(context, i).ToLocal(&value))
        return;
      results->push_back(value);
    }
  }
}

int ScriptController::CreateNewDInspectorIsolatedWorld(
    const String& world_name) {
  RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::Create(
      GetIsolate(), DOMWrapperWorld::WorldType::kInspectorIsolated);
  // Bail out if we could not create an isolated world.
  if (!world)
    return DOMWrapperWorld::kInvalidWorldId;
  if (!world_name.IsEmpty()) {
    DOMWrapperWorld::SetIsolatedWorldHumanReadableName(world->GetWorldId(),
                                                       world_name);
  }
  // Make sure the execution context exists.
  WindowProxy(*world);
  return world->GetWorldId();
}

}  // namespace blink
