// Copyright 2020 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 "third_party/blink/renderer/controller/performance_manager/renderer_resource_coordinator_impl.h"

#include <utility>

#include "base/bind.h"
#include "base/check.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"

using performance_manager::mojom::blink::IframeAttributionData;
using performance_manager::mojom::blink::IframeAttributionDataPtr;
using performance_manager::mojom::blink::ProcessCoordinationUnit;
using performance_manager::mojom::blink::V8ContextDescription;
using performance_manager::mojom::blink::V8ContextDescriptionPtr;
using performance_manager::mojom::blink::V8ContextWorldType;

namespace WTF {

// Copies the data by move.
template <>
struct CrossThreadCopier<V8ContextDescriptionPtr>
    : public WTF::CrossThreadCopierByValuePassThrough<V8ContextDescriptionPtr> {
};

// Copies the data by move.
template <>
struct CrossThreadCopier<IframeAttributionDataPtr>
    : public WTF::CrossThreadCopierByValuePassThrough<
          IframeAttributionDataPtr> {};

// Copies the data using the copy constructor.
template <>
struct CrossThreadCopier<blink::V8ContextToken>
    : public WTF::CrossThreadCopierPassThrough<blink::V8ContextToken> {};

}  // namespace WTF

namespace blink {

using mojom::blink::FrameOwnerElementType;

namespace {

// Determines if the given stable world ID is an extension world ID.
// Extensions IDs are 32-character strings containing characters in the range of
// 'a' to 'p', inclusive.
// TODO(chrisha): Lift this somewhere public and common in components/extensions
// and reuse it from there.
bool IsExtensionStableWorldId(const String& stable_world_id) {
  if (stable_world_id.IsNull() || stable_world_id.IsEmpty())
    return false;
  if (stable_world_id.length() != 32)
    return false;
  for (size_t i = 0; i < stable_world_id.length(); ++i) {
    if (stable_world_id[i] < 'a' || stable_world_id[i] > 'p')
      return false;
  }
  return true;
}

// Returns true if |owner| is an iframe, false otherwise.
// This will also return true for custom elements built on iframe, like
// <webview> and <guestview>. Since the renderer has no knowledge of these they
// must be filtered out on the browser side.
bool ShouldSendIframeNotificationsFor(const HTMLFrameOwnerElement& owner) {
  return owner.OwnerType() == FrameOwnerElementType::kIframe;
}

// If |frame| is a RemoteFrame with a local parent, returns the parent.
// Otherwise returns nullptr.
LocalFrame* GetLocalParentOfRemoteFrame(const Frame& frame) {
  if (IsA<RemoteFrame>(frame)) {
    if (Frame* parent = frame.Tree().Parent()) {
      return DynamicTo<LocalFrame>(parent);
    }
  }
  return nullptr;
}

IframeAttributionDataPtr AttributionDataForOwner(
    const HTMLFrameOwnerElement& owner) {
  auto attribution_data = IframeAttributionData::New();
  attribution_data->id = owner.FastGetAttribute(html_names::kIdAttr);
  attribution_data->src = owner.FastGetAttribute(html_names::kSrcAttr);
  return attribution_data;
}

}  // namespace

RendererResourceCoordinatorImpl::~RendererResourceCoordinatorImpl() = default;

// static
void RendererResourceCoordinatorImpl::MaybeInitialize() {
  if (!RuntimeEnabledFeatures::PerformanceManagerInstrumentationEnabled())
    return;

  blink::Platform* platform = Platform::Current();
  DCHECK(IsMainThread());
  DCHECK(platform);

  mojo::PendingRemote<ProcessCoordinationUnit> remote;
  platform->GetBrowserInterfaceBroker()->GetInterface(
      remote.InitWithNewPipeAndPassReceiver());
  RendererResourceCoordinator::Set(
      new RendererResourceCoordinatorImpl(std::move(remote)));
}

void RendererResourceCoordinatorImpl::SetMainThreadTaskLoadIsLow(
    bool main_thread_task_load_is_low) {
  DCHECK(service_);
  service_->SetMainThreadTaskLoadIsLow(main_thread_task_load_is_low);
}

void RendererResourceCoordinatorImpl::OnScriptStateCreated(
    ScriptState* script_state,
    ExecutionContext* execution_context) {
  DCHECK(script_state);
  DCHECK(service_);

  auto v8_desc = V8ContextDescription::New();
  v8_desc->token = script_state->GetToken();

  IframeAttributionDataPtr iframe_attribution_data;

  // Default the world name to being empty.

  auto& dom_wrapper = script_state->World();
  switch (dom_wrapper.GetWorldType()) {
    case DOMWrapperWorld::WorldType::kMain: {
      v8_desc->world_type = V8ContextWorldType::kMain;
    } break;
    case DOMWrapperWorld::WorldType::kIsolated: {
      auto stable_world_id = dom_wrapper.NonMainWorldStableId();
      if (IsExtensionStableWorldId(stable_world_id)) {
        v8_desc->world_type = V8ContextWorldType::kExtension;
        v8_desc->world_name = stable_world_id;
      } else {
        v8_desc->world_type = V8ContextWorldType::kIsolated;
        v8_desc->world_name = dom_wrapper.NonMainWorldHumanReadableName();
      }
    } break;
    case DOMWrapperWorld::WorldType::kInspectorIsolated: {
      v8_desc->world_type = V8ContextWorldType::kInspector;
    } break;
    case DOMWrapperWorld::WorldType::kRegExp: {
      v8_desc->world_type = V8ContextWorldType::kRegExp;
    } break;
    case DOMWrapperWorld::WorldType::kForV8ContextSnapshotNonMain: {
      // This should not happen in the production browser.
      NOTREACHED();
    } break;
    case DOMWrapperWorld::WorldType::kWorker: {
      v8_desc->world_type = V8ContextWorldType::kWorkerOrWorklet;
    } break;
  }

  if (execution_context) {
    // This should never happen for a regexp world.
    DCHECK_NE(DOMWrapperWorld::WorldType::kRegExp, dom_wrapper.GetWorldType());

    v8_desc->execution_context_token =
        execution_context->GetExecutionContextToken();

    // Only report the iframe data alongside the main world.
    // If this is the main world (so also a LocalDOMWindow) ...
    if (v8_desc->world_type == V8ContextWorldType::kMain) {
      auto* local_dom_window = To<LocalDOMWindow>(execution_context);
      // ... with a parent ...
      auto* local_frame = local_dom_window->GetFrame();
      DCHECK(local_frame);
      if (auto* parent_frame = local_frame->Parent()) {
        // ... that is also local ...
        if (IsA<LocalFrame>(parent_frame)) {
          // ... then we want to grab the iframe data associated with this
          // frame.
          auto* owner = To<HTMLFrameOwnerElement>(local_frame->Owner());
          DCHECK(owner);
          iframe_attribution_data = AttributionDataForOwner(*owner);
        }
      }
    }
  }

  DispatchOnV8ContextCreated(std::move(v8_desc),
                             std::move(iframe_attribution_data));
}

void RendererResourceCoordinatorImpl::OnScriptStateDetached(
    ScriptState* script_state) {
  DCHECK(script_state);
  DispatchOnV8ContextDetached(script_state->GetToken());
}

void RendererResourceCoordinatorImpl::OnScriptStateDestroyed(
    ScriptState* script_state) {
  DCHECK(script_state);
  DispatchOnV8ContextDestroyed(script_state->GetToken());
}

void RendererResourceCoordinatorImpl::OnBeforeContentFrameAttached(
    const Frame& frame,
    const HTMLFrameOwnerElement& owner) {
  DCHECK(service_);
  if (!ShouldSendIframeNotificationsFor(owner))
    return;
  LocalFrame* parent = GetLocalParentOfRemoteFrame(frame);
  if (!parent)
    return;
  service_->OnRemoteIframeAttached(
      parent->GetLocalFrameToken(),
      frame.GetFrameToken().GetAs<RemoteFrameToken>(),
      AttributionDataForOwner(owner));
}

void RendererResourceCoordinatorImpl::OnBeforeContentFrameDetached(
    const Frame& frame,
    const HTMLFrameOwnerElement& owner) {
  DCHECK(service_);
  if (!ShouldSendIframeNotificationsFor(owner))
    return;
  LocalFrame* parent = GetLocalParentOfRemoteFrame(frame);
  if (!parent)
    return;
  service_->OnRemoteIframeDetached(
      parent->GetLocalFrameToken(),
      frame.GetFrameToken().GetAs<RemoteFrameToken>());
}

RendererResourceCoordinatorImpl::RendererResourceCoordinatorImpl(
    mojo::PendingRemote<ProcessCoordinationUnit> remote) {
  service_.Bind(std::move(remote));
}

void RendererResourceCoordinatorImpl::DispatchOnV8ContextCreated(
    V8ContextDescriptionPtr v8_desc,
    IframeAttributionDataPtr iframe_attribution_data) {
  DCHECK(service_);
  // Calls to this can arrive on any thread (due to workers, etc), but the
  // interface itself is bound to the main thread. In this case, once we've
  // collated the necessary data we bounce over to the main thread. Note that
  // posting "this" unretained is safe because the renderer resource coordinator
  // is a singleton that leaks at process shutdown.
  if (!IsMainThread()) {
    blink::PostCrossThreadTask(
        *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
        WTF::CrossThreadBindOnce(
            &RendererResourceCoordinatorImpl::DispatchOnV8ContextCreated,
            WTF::CrossThreadUnretained(this), std::move(v8_desc),
            std::move(iframe_attribution_data)));
  } else {
    service_->OnV8ContextCreated(std::move(v8_desc),
                                 std::move(iframe_attribution_data));
  }
}

void RendererResourceCoordinatorImpl::DispatchOnV8ContextDetached(
    const blink::V8ContextToken& token) {
  DCHECK(service_);
  // See DispatchOnV8ContextCreated for why this is both needed and safe.
  if (!IsMainThread()) {
    blink::PostCrossThreadTask(
        *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
        WTF::CrossThreadBindOnce(
            &RendererResourceCoordinatorImpl::DispatchOnV8ContextDetached,
            WTF::CrossThreadUnretained(this), token));
  } else {
    service_->OnV8ContextDetached(token);
  }
}
void RendererResourceCoordinatorImpl::DispatchOnV8ContextDestroyed(
    const blink::V8ContextToken& token) {
  DCHECK(service_);
  // See DispatchOnV8ContextCreated for why this is both needed and safe.
  if (!IsMainThread()) {
    blink::PostCrossThreadTask(
        *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
        WTF::CrossThreadBindOnce(
            &RendererResourceCoordinatorImpl::DispatchOnV8ContextDestroyed,
            WTF::CrossThreadUnretained(this), token));
  } else {
    service_->OnV8ContextDestroyed(token);
  }
}

}  // namespace blink
