/*
 * Copyright (C) 2008, 2010 Apple 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:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "third_party/blink/renderer/core/frame/location.h"

#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/dom_window.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/url/dom_url_utils_read_only.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"

namespace blink {

Location::Location(DOMWindow* dom_window) : dom_window_(dom_window) {}

void Location::Trace(Visitor* visitor) const {
  visitor->Trace(dom_window_);
  ScriptWrappable::Trace(visitor);
}

inline const KURL& Location::Url() const {
  const KURL& web_bundle_claimed_url = GetDocument()->WebBundleClaimedUrl();
  if (web_bundle_claimed_url.IsValid()) {
    return web_bundle_claimed_url;
  }
  const KURL& url = GetDocument()->Url();
  if (!url.IsValid()) {
    // Use "about:blank" while the page is still loading (before we have a
    // frame).
    return BlankURL();
  }

  return url;
}

String Location::href() const {
  return Url().StrippedForUseAsHref();
}

String Location::protocol() const {
  return DOMURLUtilsReadOnly::protocol(Url());
}

String Location::host() const {
  return DOMURLUtilsReadOnly::host(Url());
}

String Location::hostname() const {
  return DOMURLUtilsReadOnly::hostname(Url());
}

String Location::port() const {
  return DOMURLUtilsReadOnly::port(Url());
}

String Location::pathname() const {
  return DOMURLUtilsReadOnly::pathname(Url());
}

String Location::search() const {
  return DOMURLUtilsReadOnly::search(Url());
}

String Location::origin() const {
  return DOMURLUtilsReadOnly::origin(Url());
}

DOMStringList* Location::ancestorOrigins() const {
  auto* origins = MakeGarbageCollected<DOMStringList>();
  if (!IsAttached())
    return origins;
  for (Frame* frame = dom_window_->GetFrame()->Tree().Parent(); frame;
       frame = frame->Tree().Parent()) {
    origins->Append(
        frame->GetSecurityContext()->GetSecurityOrigin()->ToString());
  }
  return origins;
}

String Location::toString() const {
  return href();
}

String Location::hash() const {
  return DOMURLUtilsReadOnly::hash(Url());
}

void Location::setHref(v8::Isolate* isolate,
                       const String& url_string,
                       ExceptionState& exception_state) {
  LocalDOMWindow* incumbent_window = IncumbentDOMWindow(isolate);
  LocalDOMWindow* entered_window = EnteredDOMWindow(isolate);
  SetLocation(url_string, incumbent_window, entered_window, &exception_state);
}

void Location::setProtocol(v8::Isolate* isolate,
                           const String& protocol,
                           ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  if (!url.SetProtocol(protocol)) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kSyntaxError,
        "'" + protocol + "' is an invalid protocol.");
    return;
  }

  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::setHost(v8::Isolate* isolate,
                       const String& host,
                       ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  url.SetHostAndPort(host);
  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::setHostname(v8::Isolate* isolate,
                           const String& hostname,
                           ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  url.SetHost(hostname);
  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::setPort(v8::Isolate* isolate,
                       const String& port,
                       ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  url.SetPort(port);
  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::setPathname(v8::Isolate* isolate,
                           const String& pathname,
                           ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  url.SetPath(pathname);
  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::setSearch(v8::Isolate* isolate,
                         const String& search,
                         ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  url.SetQuery(search);
  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::setHash(v8::Isolate* isolate,
                       const String& hash,
                       ExceptionState& exception_state) {
  KURL url = GetDocument()->Url();
  String old_fragment_identifier = url.FragmentIdentifier();
  String new_fragment_identifier = hash;
  if (hash[0] == '#')
    new_fragment_identifier = hash.Substring(1);
  url.SetFragmentIdentifier(new_fragment_identifier);
  // Note that by parsing the URL and *then* comparing fragments, we are
  // comparing fragments post-canonicalization, and so this handles the
  // cases where fragment identifiers are ignored or invalid.
  if (EqualIgnoringNullity(old_fragment_identifier, url.FragmentIdentifier()))
    return;
  SetLocation(url.GetString(), IncumbentDOMWindow(isolate),
              EnteredDOMWindow(isolate), &exception_state);
}

void Location::assign(v8::Isolate* isolate,
                      const String& url_string,
                      ExceptionState& exception_state) {
  LocalDOMWindow* incumbent_window = IncumbentDOMWindow(isolate);
  LocalDOMWindow* entered_window = EnteredDOMWindow(isolate);
  SetLocation(url_string, incumbent_window, entered_window, &exception_state);
}

void Location::replace(v8::Isolate* isolate,
                       const String& url_string,
                       ExceptionState& exception_state) {
  LocalDOMWindow* incumbent_window = IncumbentDOMWindow(isolate);
  LocalDOMWindow* entered_window = EnteredDOMWindow(isolate);
  SetLocation(url_string, incumbent_window, entered_window, &exception_state,
              SetLocationPolicy::kReplaceThisFrame);
}

void Location::reload() {
  if (!IsAttached())
    return;
  if (GetDocument()->Url().ProtocolIsJavaScript())
    return;
  // reload() is not cross-origin accessible, so |dom_window_| will always be
  // local.
  To<LocalDOMWindow>(dom_window_.Get())
      ->GetFrame()
      ->Reload(WebFrameLoadType::kReload);
}

void Location::SetLocation(const String& url,
                           LocalDOMWindow* incumbent_window,
                           LocalDOMWindow* entered_window,
                           ExceptionState* exception_state,
                           SetLocationPolicy set_location_policy) {
  if (!IsAttached())
    return;

  if (!incumbent_window->GetFrame())
    return;

  Document* entered_document = entered_window->document();
  if (!entered_document)
    return;

  KURL completed_url = entered_document->CompleteURL(url);
  if (completed_url.IsNull())
    return;

  if (!incumbent_window->GetFrame()->CanNavigate(*dom_window_->GetFrame(),
                                                 completed_url)) {
    if (exception_state) {
      exception_state->ThrowSecurityError(
          "The current window does not have permission to navigate the target "
          "frame to '" +
          url + "'.");
    }
    return;
  }
  if (exception_state && !completed_url.IsValid()) {
    exception_state->ThrowDOMException(DOMExceptionCode::kSyntaxError,
                                       "'" + url + "' is not a valid URL.");
    return;
  }

  // Check the source browsing context's CSP to fulfill the CSP check
  // requirement of https://html.spec.whatwg.org/C/#navigate for javascript
  // URLs. Although the spec states we should perform this check on task
  // execution, there are concerns about the correctness of that statement,
  // see http://github.com/whatwg/html/issues/2591.
  if (completed_url.ProtocolIsJavaScript()) {
    String script_source = DecodeURLEscapeSequences(
        completed_url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
    if (!incumbent_window->GetContentSecurityPolicyForCurrentWorld()
             ->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
                           nullptr /* element */, script_source,
                           String() /* nonce */, incumbent_window->Url(),
                           OrdinalNumber())) {
      return;
    }
  }

  V8DOMActivityLogger* activity_logger =
      V8DOMActivityLogger::CurrentActivityLoggerIfIsolatedWorld();
  if (activity_logger) {
    Vector<String> argv;
    argv.push_back("LocalDOMWindow");
    argv.push_back("url");
    argv.push_back(entered_document->Url());
    argv.push_back(completed_url);
    activity_logger->LogEvent("blinkSetAttribute", argv.size(), argv.data());
  }

  FrameLoadRequest request(incumbent_window, ResourceRequest(completed_url));
  request.SetClientRedirectReason(ClientNavigationReason::kFrameNavigation);
  WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard;
  if (set_location_policy == SetLocationPolicy::kReplaceThisFrame)
    frame_load_type = WebFrameLoadType::kReplaceCurrentItem;

  incumbent_window->GetFrame()->MaybeLogAdClickNavigation();
  dom_window_->GetFrame()->Navigate(request, frame_load_type);
}

Document* Location::GetDocument() const {
  return To<LocalDOMWindow>(dom_window_.Get())->document();
}

bool Location::IsAttached() const {
  return dom_window_->GetFrame();
}

}  // namespace blink
