/*
 * Copyright (C) 2009 Google Inc. 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/V8DOMWrapper.h"

#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8Location.h"
#include "bindings/core/v8/V8ObjectConstructor.h"
#include "bindings/core/v8/V8PerContextData.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "bindings/core/v8/V8ScriptRunner.h"
#include "bindings/core/v8/V8Window.h"
#include "core/dom/Document.h"
#include "core/frame/LocalDOMWindow.h"

namespace blink {

v8::Local<v8::Object> V8DOMWrapper::createWrapper(
    v8::Isolate* isolate,
    v8::Local<v8::Object> creationContext,
    const WrapperTypeInfo* type) {
  ASSERT(!type->equals(&V8Window::wrapperTypeInfo));
  // According to
  // https://html.spec.whatwg.org/multipage/browsers.html#security-location,
  // cross-origin script access to a few properties of Location is allowed.
  // Location already implements the necessary security checks.
  bool withSecurityCheck = !type->equals(&V8Location::wrapperTypeInfo);
  V8WrapperInstantiationScope scope(creationContext, isolate,
                                    withSecurityCheck);

  V8PerContextData* perContextData = V8PerContextData::from(scope.context());
  v8::Local<v8::Object> wrapper;
  if (perContextData) {
    wrapper = perContextData->createWrapperFromCache(type);
  } else {
    // The context is detached, but still accessible.
    // TODO(yukishiino): This code does not create a wrapper with
    // the correct settings.  Should follow the same way as
    // V8PerContextData::createWrapperFromCache, though there is no need to
    // cache resulting objects or their constructors.
    const DOMWrapperWorld& world = DOMWrapperWorld::world(scope.context());
    wrapper = type->domTemplate(isolate, world)
                  ->InstanceTemplate()
                  ->NewInstance(scope.context())
                  .ToLocalChecked();
  }
  return wrapper;
}

bool V8DOMWrapper::isWrapper(v8::Isolate* isolate, v8::Local<v8::Value> value) {
  if (value.IsEmpty() || !value->IsObject())
    return false;
  v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);

  if (object->InternalFieldCount() < v8DefaultWrapperInternalFieldCount)
    return false;

  const WrapperTypeInfo* untrustedWrapperTypeInfo = toWrapperTypeInfo(object);
  V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate);
  if (!(untrustedWrapperTypeInfo && perIsolateData))
    return false;
  return perIsolateData->hasInstance(untrustedWrapperTypeInfo, object);
}

bool V8DOMWrapper::hasInternalFieldsSet(v8::Local<v8::Value> value) {
  if (value.IsEmpty() || !value->IsObject())
    return false;
  v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);

  if (object->InternalFieldCount() < v8DefaultWrapperInternalFieldCount)
    return false;

  const ScriptWrappable* untrustedScriptWrappable = toScriptWrappable(object);
  const WrapperTypeInfo* untrustedWrapperTypeInfo = toWrapperTypeInfo(object);
  return untrustedScriptWrappable && untrustedWrapperTypeInfo &&
         untrustedWrapperTypeInfo->ginEmbedder == gin::kEmbedderBlink;
}

void V8WrapperInstantiationScope::securityCheck(
    v8::Isolate* isolate,
    v8::Local<v8::Context> contextForWrapper) {
  if (m_context.IsEmpty())
    return;
  // If the context is different, we need to make sure that the current
  // context has access to the creation context.
  Frame* frame = toFrameIfNotDetached(contextForWrapper);
  if (!frame) {
    // Sandbox detached frames - they can't create cross origin objects.
    LocalDOMWindow* callingWindow = currentDOMWindow(isolate);
    DOMWindow* targetWindow = toDOMWindow(contextForWrapper);
    // TODO(jochen): Currently, Location is the only object for which we can
    // reach this code path. Should be generalized.
    ExceptionState exceptionState(isolate, ExceptionState::ConstructionContext,
                                  "Location");
    if (BindingSecurity::shouldAllowAccessToDetachedWindow(
            callingWindow, targetWindow, exceptionState))
      return;

    CHECK_EQ(SecurityError, exceptionState.code());
    return;
  }
  const DOMWrapperWorld& currentWorld = DOMWrapperWorld::world(m_context);
  RELEASE_ASSERT(currentWorld.worldId() ==
                 DOMWrapperWorld::world(contextForWrapper).worldId());
  // TODO(jochen): Add the interface name here once this is generalized.
  ExceptionState exceptionState(isolate, ExceptionState::ConstructionContext,
                                nullptr);
  if (currentWorld.isMainWorld() &&
      !BindingSecurity::shouldAllowAccessToFrame(currentDOMWindow(isolate),
                                                 frame, exceptionState)) {
    CHECK_EQ(SecurityError, exceptionState.code());
    return;
  }
}

void V8WrapperInstantiationScope::convertException() {
  v8::Isolate* isolate = m_context->GetIsolate();
  // TODO(jochen): Currently, Location is the only object for which we can reach
  // this code path. Should be generalized.
  ExceptionState exceptionState(isolate, ExceptionState::ConstructionContext,
                                "Location");
  LocalDOMWindow* callingWindow = currentDOMWindow(isolate);
  DOMWindow* targetWindow = toDOMWindow(m_context);
  exceptionState.throwSecurityError(
      targetWindow->sanitizedCrossDomainAccessErrorMessage(callingWindow),
      targetWindow->crossDomainAccessErrorMessage(callingWindow));
}

}  // namespace blink
