/*
 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "third_party/blink/renderer/core/page/create_window.h"

#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/frame/from_ad_state.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/current_input_event.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/ad_tracker.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"

namespace blink {

// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when
// parsing window features.
static bool IsWindowFeaturesSeparator(UChar c) {
  return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' ||
         c == ',' || c == '\f';
}

WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string) {
  WebWindowFeatures window_features;

  // This code follows the HTML spec, specifically
  // https://html.spec.whatwg.org/#concept-window-open-features-tokenize
  if (feature_string.IsEmpty())
    return window_features;

  window_features.menu_bar_visible = false;
  window_features.status_bar_visible = false;
  window_features.tool_bar_visible = false;
  window_features.scrollbars_visible = false;

  unsigned key_begin, key_end;
  unsigned value_begin, value_end;

  String buffer = feature_string.DeprecatedLower();
  unsigned length = buffer.length();
  for (unsigned i = 0; i < length;) {
    // skip to first non-separator (start of key name), but don't skip
    // past the end of the string
    while (i < length && IsWindowFeaturesSeparator(buffer[i]))
      i++;
    key_begin = i;

    // skip to first separator (end of key name), but don't skip past
    // the end of the string
    while (i < length && !IsWindowFeaturesSeparator(buffer[i]))
      i++;
    key_end = i;

    SECURITY_DCHECK(i <= length);

    // skip separators past the key name, except '=', and don't skip past
    // the end of the string
    while (i < length && buffer[i] != '=') {
      if (buffer[i] == ',' || !IsWindowFeaturesSeparator(buffer[i]))
        break;

      i++;
    }

    if (i < length && IsWindowFeaturesSeparator(buffer[i])) {
      // skip to first non-separator (start of value), but don't skip
      // past a ',' or the end of the string.
      while (i < length && IsWindowFeaturesSeparator(buffer[i])) {
        if (buffer[i] == ',')
          break;

        i++;
      }

      value_begin = i;

      SECURITY_DCHECK(i <= length);

      // skip to first separator (end of value)
      while (i < length && !IsWindowFeaturesSeparator(buffer[i]))
        i++;

      value_end = i;

      SECURITY_DCHECK(i <= length);
    } else {
      // No value given.
      value_begin = i;
      value_end = i;
    }

    String key_string(
        buffer.Substring(key_begin, key_end - key_begin).LowerASCII());
    String value_string(
        buffer.Substring(value_begin, value_end - value_begin).LowerASCII());

    // Listing a key with no value is shorthand for key=yes
    int value;
    if (value_string.IsEmpty() || value_string == "yes")
      value = 1;
    else
      value = value_string.ToInt();

    if (key_string.IsEmpty())
      continue;

    if (key_string == "left" || key_string == "screenx") {
      window_features.x_set = true;
      window_features.x = value;
    } else if (key_string == "top" || key_string == "screeny") {
      window_features.y_set = true;
      window_features.y = value;
    } else if (key_string == "width" || key_string == "innerwidth") {
      window_features.width_set = true;
      window_features.width = value;
    } else if (key_string == "height" || key_string == "innerheight") {
      window_features.height_set = true;
      window_features.height = value;
    } else if (key_string == "menubar") {
      window_features.menu_bar_visible = value;
    } else if (key_string == "toolbar" || key_string == "location") {
      window_features.tool_bar_visible |= static_cast<bool>(value);
    } else if (key_string == "status") {
      window_features.status_bar_visible = value;
    } else if (key_string == "scrollbars") {
      window_features.scrollbars_visible = value;
    } else if (key_string == "resizable") {
      window_features.resizable = value;
    } else if (key_string == "noopener") {
      window_features.noopener = true;
    } else if (key_string == "background") {
      window_features.background = true;
    } else if (key_string == "persistent") {
      window_features.persistent = true;
    }
  }

  return window_features;
}

static Frame* ReuseExistingWindow(LocalFrame& active_frame,
                                  LocalFrame& lookup_frame,
                                  const AtomicString& frame_name,
                                  const KURL& destination_url) {
  if (!frame_name.IsEmpty() && !EqualIgnoringASCIICase(frame_name, "_blank")) {
    if (Frame* frame = lookup_frame.FindFrameForNavigation(
            frame_name, active_frame, destination_url)) {
      if (!EqualIgnoringASCIICase(frame_name, "_self")) {
        if (Page* page = frame->GetPage()) {
          if (page == active_frame.GetPage())
            page->GetFocusController().SetFocusedFrame(frame);
          else
            page->GetChromeClient().Focus(&active_frame);
        }
      }
      return frame;
    }
  }
  return nullptr;
}

static void MaybeLogWindowOpen(LocalFrame& opener_frame) {
  AdTracker* ad_tracker = opener_frame.GetAdTracker();
  if (!ad_tracker)
    return;

  bool is_ad_subframe = opener_frame.IsAdSubframe();
  bool is_ad_script_in_stack = ad_tracker->IsAdScriptInStack();
  FromAdState state =
      blink::GetFromAdState(is_ad_subframe, is_ad_script_in_stack);

  // Log to UMA.
  UMA_HISTOGRAM_ENUMERATION("Blink.WindowOpen.FromAdState", state);

  // Log to UKM.
  ukm::UkmRecorder* ukm_recorder = opener_frame.GetDocument()->UkmRecorder();
  ukm::SourceId source_id = opener_frame.GetDocument()->UkmSourceID();
  if (source_id != ukm::kInvalidSourceId) {
    ukm::builders::AbusiveExperienceHeuristic_WindowOpen(source_id)
        .SetFromAdSubframe(is_ad_subframe)
        .SetFromAdScript(is_ad_script_in_stack)
        .Record(ukm_recorder);
  }
}

static Frame* CreateNewWindow(LocalFrame& opener_frame,
                              const FrameLoadRequest& request,
                              const WebWindowFeatures& features,
                              bool force_new_foreground_tab,
                              bool& created) {
  Page* old_page = opener_frame.GetPage();
  if (!old_page)
    return nullptr;

  NavigationPolicy policy = force_new_foreground_tab
                                ? kNavigationPolicyNewForegroundTab
                                : NavigationPolicyForCreateWindow(features);

  const SandboxFlags sandbox_flags =
      opener_frame.GetDocument()->IsSandboxed(
          kSandboxPropagatesToAuxiliaryBrowsingContexts)
          ? opener_frame.GetSecurityContext()->GetSandboxFlags()
          : kSandboxNone;

  SessionStorageNamespaceId new_namespace_id =
      AllocateSessionStorageNamespaceId();

  if (base::FeatureList::IsEnabled(features::kOnionSoupDOMStorage)) {
    // TODO(dmurph): Don't copy session storage when features.noopener is true:
    // https://html.spec.whatwg.org/multipage/browsers.html#copy-session-storage
    // https://crbug.com/771959
    CoreInitializer::GetInstance().CloneSessionStorage(old_page,
                                                       new_namespace_id);
  }

  Page* page = old_page->GetChromeClient().CreateWindow(
      &opener_frame, request, features, policy, sandbox_flags,
      new_namespace_id);
  if (!page)
    return nullptr;

  if (page == old_page) {
    Frame* frame = &opener_frame.Tree().Top();
    if (!opener_frame.CanNavigate(*frame))
      return nullptr;
    if (request.GetShouldSetOpener() == kMaybeSetOpener)
      frame->Client()->SetOpener(&opener_frame);
    return frame;
  }

  DCHECK(page->MainFrame());
  LocalFrame& frame = *ToLocalFrame(page->MainFrame());

  page->SetWindowFeatures(features);

  frame.View()->SetCanHaveScrollbars(features.scrollbars_visible);

  IntRect window_rect = page->GetChromeClient().RootWindowRect(frame);
  if (features.x_set)
    window_rect.SetX(features.x);
  if (features.y_set)
    window_rect.SetY(features.y);
  if (features.width_set)
    window_rect.SetWidth(features.width);
  if (features.height_set)
    window_rect.SetHeight(features.height);

  page->GetChromeClient().SetWindowRectWithAdjustment(window_rect, frame);
  page->GetChromeClient().Show(policy);

  MaybeLogWindowOpen(opener_frame);
  created = true;
  return &frame;
}

static Frame* CreateWindowHelper(LocalFrame& opener_frame,
                                 LocalFrame& active_frame,
                                 LocalFrame& lookup_frame,
                                 const FrameLoadRequest& request,
                                 const WebWindowFeatures& features,
                                 bool force_new_foreground_tab,
                                 bool& created) {
  DCHECK(request.GetResourceRequest().RequestorOrigin() ||
         opener_frame.GetDocument()->Url().IsEmpty());
  DCHECK_EQ(request.GetResourceRequest().GetFrameType(),
            network::mojom::RequestContextFrameType::kAuxiliary);
  probe::windowOpen(opener_frame.GetDocument(),
                    request.GetResourceRequest().Url(), request.FrameName(),
                    features,
                    LocalFrame::HasTransientUserActivation(&opener_frame));
  created = false;

  Frame* window =
      features.noopener || force_new_foreground_tab
          ? nullptr
          : ReuseExistingWindow(active_frame, lookup_frame, request.FrameName(),
                                request.GetResourceRequest().Url());

  if (!window) {
    // Sandboxed frames cannot open new auxiliary browsing contexts.
    if (opener_frame.GetDocument()->IsSandboxed(kSandboxPopups)) {
      // FIXME: This message should be moved off the console once a solution to
      // https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
      opener_frame.GetDocument()->AddConsoleMessage(ConsoleMessage::Create(
          kSecurityMessageSource, kErrorMessageLevel,
          "Blocked opening '" +
              request.GetResourceRequest().Url().ElidedString() +
              "' in a new window because the request was made in a sandboxed "
              "frame whose 'allow-popups' permission is not set."));
      return nullptr;
    }
  }

  if (window) {
    // JS can run inside ReuseExistingWindow (via onblur), which can detach
    // the target window.
    if (!window->Client())
      return nullptr;
    if (request.GetShouldSetOpener() == kMaybeSetOpener)
      window->Client()->SetOpener(&opener_frame);
    return window;
  }

  return CreateNewWindow(opener_frame, request, features,
                         force_new_foreground_tab, created);
}

DOMWindow* CreateWindow(const String& url_string,
                        const AtomicString& frame_name,
                        const String& window_features_string,
                        LocalDOMWindow& incumbent_window,
                        LocalFrame& entered_window_frame,
                        LocalFrame& opener_frame,
                        ExceptionState& exception_state) {
  LocalFrame* active_frame = incumbent_window.GetFrame();
  DCHECK(active_frame);

  KURL completed_url =
      url_string.IsEmpty()
          ? KURL(g_empty_string)
          : entered_window_frame.GetDocument()->CompleteURL(url_string);
  if (!completed_url.IsEmpty() && !completed_url.IsValid()) {
    UseCounter::Count(active_frame, WebFeature::kWindowOpenWithInvalidURL);
    exception_state.ThrowDOMException(
        DOMExceptionCode::kSyntaxError,
        "Unable to open a window with invalid URL '" +
            completed_url.GetString() + "'.\n");
    return nullptr;
  }

  if (completed_url.ProtocolIsJavaScript() &&
      opener_frame.GetDocument()->GetContentSecurityPolicy() &&
      !ContentSecurityPolicy::ShouldBypassMainWorld(
          opener_frame.GetDocument())) {
    String script_source = DecodeURLEscapeSequences(
        completed_url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);

    if (!opener_frame.GetDocument()
             ->GetContentSecurityPolicy()
             ->AllowJavaScriptURLs(nullptr, script_source,
                                   opener_frame.GetDocument()->Url(),
                                   OrdinalNumber())) {
      return nullptr;
    }
  }

  WebWindowFeatures window_features =
      GetWindowFeaturesFromString(window_features_string);

  FrameLoadRequest frame_request(incumbent_window.document(),
                                 ResourceRequest(completed_url), frame_name);
  frame_request.SetShouldSetOpener(window_features.noopener ? kNeverSetOpener
                                                            : kMaybeSetOpener);
  frame_request.GetResourceRequest().SetFrameType(
      network::mojom::RequestContextFrameType::kAuxiliary);

  // Normally, FrameLoader would take care of setting the referrer for a
  // navigation that is triggered from javascript. However, creating a window
  // goes through sufficient processing that it eventually enters FrameLoader as
  // an embedder-initiated navigation.  FrameLoader assumes no responsibility
  // for generating an embedder-initiated navigation's referrer, so we need to
  // ensure the proper referrer is set now.
  // TODO(domfarolino): Stop setting ResourceRequest's HTTP Referrer and store
  // this is a separate member. See https://crbug.com/850813.
  frame_request.GetResourceRequest().SetHTTPReferrer(
      SecurityPolicy::GenerateReferrer(
          active_frame->GetDocument()->GetReferrerPolicy(), completed_url,
          active_frame->GetDocument()->OutgoingReferrer()));

  // Records HasUserGesture before the value is invalidated inside
  // createWindow(LocalFrame& openerFrame, ...).
  // This value will be set in ResourceRequest loaded in a new LocalFrame.
  bool has_user_gesture = LocalFrame::HasTransientUserActivation(&opener_frame);

  // We pass the opener frame for the lookupFrame in case the active frame is
  // different from the opener frame, and the name references a frame relative
  // to the opener frame.
  bool created;
  Frame* new_frame = CreateWindowHelper(
      opener_frame, *active_frame, opener_frame, frame_request, window_features,
      false /* force_new_foreground_tab */, created);
  if (!new_frame)
    return nullptr;
  if (new_frame->DomWindow()->IsInsecureScriptAccess(incumbent_window,
                                                     completed_url))
    return window_features.noopener ? nullptr : new_frame->DomWindow();

  // TODO(dcheng): Special case for window.open("about:blank") to ensure it
  // loads synchronously into a new window. This is our historical behavior, and
  // it's consistent with the creation of a new iframe with src="about:blank".
  // Perhaps we could get rid of this if we started reporting the initial empty
  // document's url as about:blank? See crbug.com/471239.
  // TODO(japhet): This special case is also necessary for behavior asserted by
  // some extensions tests.  Using NavigationScheduler::scheduleNavigationChange
  // causes the navigation to be flagged as a client redirect, which is
  // observable via the webNavigation extension api.
  if (created) {
    FrameLoadRequest request(incumbent_window.document(),
                             ResourceRequest(completed_url));
    request.GetResourceRequest().SetHasUserGesture(has_user_gesture);
    if (const WebInputEvent* input_event = CurrentInputEvent::Get()) {
      request.SetInputStartTime(input_event->TimeStamp());
    }
    new_frame->Navigate(request, WebFrameLoadType::kStandard);
  } else if (!url_string.IsEmpty()) {
    new_frame->ScheduleNavigation(*incumbent_window.document(), completed_url,
                                  WebFrameLoadType::kStandard,
                                  has_user_gesture ? UserGestureStatus::kActive
                                                   : UserGestureStatus::kNone);
  }
  return window_features.noopener ? nullptr : new_frame->DomWindow();
}

void CreateWindowForRequest(const FrameLoadRequest& request,
                            LocalFrame& opener_frame) {
  DCHECK(request.GetResourceRequest().RequestorOrigin() ||
         (opener_frame.GetDocument() &&
          opener_frame.GetDocument()->Url().IsEmpty()));

  if (opener_frame.GetDocument()->PageDismissalEventBeingDispatched() !=
      Document::kNoDismissal)
    return;

  if (opener_frame.GetDocument() &&
      opener_frame.GetDocument()->IsSandboxed(kSandboxPopups))
    return;

  WebWindowFeatures features;
  features.noopener = request.GetShouldSetOpener() == kNeverSetOpener;
  bool created;
  Frame* new_frame = CreateWindowHelper(
      opener_frame, opener_frame, opener_frame, request, features,
      true /* force_new_foreground_tab */, created);
  if (!new_frame)
    return;
  if (request.GetShouldSendReferrer() == kMaybeSendReferrer) {
    // TODO(japhet): Does network::mojom::ReferrerPolicy need to be proagated
    // for RemoteFrames?
    if (new_frame->IsLocalFrame())
      ToLocalFrame(new_frame)->GetDocument()->SetReferrerPolicy(
          opener_frame.GetDocument()->GetReferrerPolicy());
  }

  // TODO(japhet): Form submissions on RemoteFrames don't work yet.
  FrameLoadRequest new_request(nullptr, request.GetResourceRequest());
  new_request.SetForm(request.Form());
  if (const WebInputEvent* input_event = CurrentInputEvent::Get()) {
    new_request.SetInputStartTime(input_event->TimeStamp());
  }
  auto blob_url_token = request.GetBlobURLToken();
  if (blob_url_token)
    new_request.SetBlobURLToken(std::move(blob_url_token));
  if (new_frame->IsLocalFrame())
    ToLocalFrame(new_frame)->Loader().StartNavigation(new_request);
}

}  // namespace blink
