/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2012 Intel 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 "core/timing/Performance.h"

#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8ObjectBuilder.h"
#include "core/dom/Document.h"
#include "core/dom/QualifiedName.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/loader/DocumentLoader.h"
#include "core/origin_trials/origin_trials.h"
#include "core/timing/PerformanceTiming.h"
#include "platform/loader/fetch/ResourceTimingInfo.h"
#include "platform/runtime_enabled_features.h"
#include "public/platform/TaskType.h"

static const double kLongTaskObserverThreshold = 0.05;

static const char kUnknownAttribution[] = "unknown";
static const char kAmbiguousAttribution[] = "multiple-contexts";
static const char kSameOriginAttribution[] = "same-origin";
static const char kSameOriginSelfAttribution[] = "self";
static const char kSameOriginAncestorAttribution[] = "same-origin-ancestor";
static const char kSameOriginDescendantAttribution[] = "same-origin-descendant";
static const char kCrossOriginAncestorAttribution[] = "cross-origin-ancestor";
static const char kCrossOriginDescendantAttribution[] =
    "cross-origin-descendant";
static const char kCrossOriginAttribution[] = "cross-origin-unreachable";

namespace blink {

namespace {

String GetFrameAttribute(HTMLFrameOwnerElement* frame_owner,
                         const QualifiedName& attr_name,
                         bool truncate) {
  String attr_value;
  if (frame_owner->hasAttribute(attr_name)) {
    attr_value = frame_owner->getAttribute(attr_name);
    if (truncate && attr_value.length() > 100)
      attr_value = attr_value.Substring(0, 100);  // Truncate to 100 chars
  }
  return attr_value;
}

const char* SameOriginAttribution(Frame* observer_frame, Frame* culprit_frame) {
  if (observer_frame == culprit_frame)
    return kSameOriginSelfAttribution;
  if (observer_frame->Tree().IsDescendantOf(culprit_frame))
    return kSameOriginAncestorAttribution;
  if (culprit_frame->Tree().IsDescendantOf(observer_frame))
    return kSameOriginDescendantAttribution;
  return kSameOriginAttribution;
}

bool IsSameOrigin(String key) {
  return key == kSameOriginAttribution ||
         key == kSameOriginDescendantAttribution ||
         key == kSameOriginAncestorAttribution ||
         key == kSameOriginSelfAttribution;
}

}  // namespace

static double ToTimeOrigin(LocalDOMWindow* window) {
  Document* document = window->document();
  if (!document)
    return 0.0;

  DocumentLoader* loader = document->Loader();
  if (!loader)
    return 0.0;

  return loader->GetTiming().ReferenceMonotonicTime();
}

Performance::Performance(LocalDOMWindow* window)
    : PerformanceBase(
          ToTimeOrigin(window),
          window->document()->GetTaskRunner(TaskType::kPerformanceTimeline)),
      DOMWindowClient(window) {}

Performance::~Performance() {
}

ExecutionContext* Performance::GetExecutionContext() const {
  if (!GetFrame())
    return nullptr;
  return GetFrame()->GetDocument();
}

MemoryInfo* Performance::memory() {
  return MemoryInfo::Create();
}

PerformanceNavigation* Performance::navigation() const {
  if (!navigation_)
    navigation_ = PerformanceNavigation::Create(GetFrame());

  return navigation_.Get();
}

PerformanceTiming* Performance::timing() const {
  if (!timing_)
    timing_ = PerformanceTiming::Create(GetFrame());

  return timing_.Get();
}

PerformanceNavigationTiming* Performance::CreateNavigationTimingInstance() {
  if (!RuntimeEnabledFeatures::PerformanceNavigationTiming2Enabled())
    return nullptr;
  if (!GetFrame())
    return nullptr;
  const DocumentLoader* document_loader =
      GetFrame()->Loader().GetDocumentLoader();
  DCHECK(document_loader);
  ResourceTimingInfo* info = document_loader->GetNavigationTimingInfo();
  if (!info)
    return nullptr;
  PerformanceServerTimingVector serverTiming =
      PerformanceServerTiming::ParseServerTiming(
          *info, PerformanceServerTiming::ShouldAllowTimingDetails::Yes);
  if (serverTiming.size()) {
    UseCounter::Count(GetFrame(), WebFeature::kPerformanceServerTiming);
  }
  return new PerformanceNavigationTiming(GetFrame(), info, GetTimeOrigin(),
                                         serverTiming);
}

void Performance::UpdateLongTaskInstrumentation() {
  DCHECK(GetFrame());
  if (!GetFrame()->GetDocument())
    return;

  if (HasObserverFor(PerformanceEntry::kLongTask)) {
    UseCounter::Count(&GetFrame()->LocalFrameRoot(),
                      WebFeature::kLongTaskObserver);
    GetFrame()->GetPerformanceMonitor()->Subscribe(
        PerformanceMonitor::kLongTask, kLongTaskObserverThreshold, this);
  } else {
    GetFrame()->GetPerformanceMonitor()->UnsubscribeAll(this);
  }
}

void Performance::BuildJSONValue(V8ObjectBuilder& builder) const {
  PerformanceBase::BuildJSONValue(builder);
  builder.Add("timing", timing()->toJSONForBinding(builder.GetScriptState()));
  builder.Add("navigation",
              navigation()->toJSONForBinding(builder.GetScriptState()));
}

void Performance::Trace(blink::Visitor* visitor) {
  visitor->Trace(navigation_);
  visitor->Trace(timing_);
  PerformanceBase::Trace(visitor);
  PerformanceMonitor::Client::Trace(visitor);
  DOMWindowClient::Trace(visitor);
}

static bool CanAccessOrigin(Frame* frame1, Frame* frame2) {
  const SecurityOrigin* security_origin1 =
      frame1->GetSecurityContext()->GetSecurityOrigin();
  const SecurityOrigin* security_origin2 =
      frame2->GetSecurityContext()->GetSecurityOrigin();
  return security_origin1->CanAccess(security_origin2);
}

/**
 * Report sanitized name based on cross-origin policy.
 * See detailed Security doc here: http://bit.ly/2duD3F7
 */
// static
std::pair<String, DOMWindow*> Performance::SanitizedAttribution(
    ExecutionContext* task_context,
    bool has_multiple_contexts,
    LocalFrame* observer_frame) {
  if (has_multiple_contexts) {
    // Unable to attribute, multiple script execution contents were involved.
    return std::make_pair(kAmbiguousAttribution, nullptr);
  }

  if (!task_context || !task_context->IsDocument() ||
      !ToDocument(task_context)->GetFrame()) {
    // Unable to attribute as no script was involved.
    return std::make_pair(kUnknownAttribution, nullptr);
  }

  // Exactly one culprit location, attribute based on origin boundary.
  Frame* culprit_frame = ToDocument(task_context)->GetFrame();
  DCHECK(culprit_frame);
  if (CanAccessOrigin(observer_frame, culprit_frame)) {
    // From accessible frames or same origin, return culprit location URL.
    return std::make_pair(SameOriginAttribution(observer_frame, culprit_frame),
                          culprit_frame->DomWindow());
  }
  // For cross-origin, if the culprit is the descendant or ancestor of
  // observer then indicate the *closest* cross-origin frame between
  // the observer and the culprit, in the corresponding direction.
  if (culprit_frame->Tree().IsDescendantOf(observer_frame)) {
    // If the culprit is a descendant of the observer, then walk up the tree
    // from culprit to observer, and report the *last* cross-origin (from
    // observer) frame.  If no intermediate cross-origin frame is found, then
    // report the culprit directly.
    Frame* last_cross_origin_frame = culprit_frame;
    for (Frame* frame = culprit_frame; frame != observer_frame;
         frame = frame->Tree().Parent()) {
      if (!CanAccessOrigin(observer_frame, frame)) {
        last_cross_origin_frame = frame;
      }
    }
    return std::make_pair(kCrossOriginDescendantAttribution,
                          last_cross_origin_frame->DomWindow());
  }
  if (observer_frame->Tree().IsDescendantOf(culprit_frame)) {
    return std::make_pair(kCrossOriginAncestorAttribution, nullptr);
  }
  return std::make_pair(kCrossOriginAttribution, nullptr);
}

void Performance::ReportLongTask(
    double start_time,
    double end_time,
    ExecutionContext* task_context,
    bool has_multiple_contexts,
    const SubTaskAttribution::EntriesVector& sub_task_attributions) {
  if (!GetFrame())
    return;
  std::pair<String, DOMWindow*> attribution = Performance::SanitizedAttribution(
      task_context, has_multiple_contexts, GetFrame());
  DOMWindow* culprit_dom_window = attribution.second;
  SubTaskAttribution::EntriesVector empty_vector;
  if (!culprit_dom_window || !culprit_dom_window->GetFrame() ||
      !culprit_dom_window->GetFrame()->DeprecatedLocalOwner()) {
    AddLongTaskTiming(
        start_time, end_time, attribution.first, g_empty_string, g_empty_string,
        g_empty_string,
        IsSameOrigin(attribution.first) ? sub_task_attributions : empty_vector);
  } else {
    HTMLFrameOwnerElement* frame_owner =
        culprit_dom_window->GetFrame()->DeprecatedLocalOwner();
    AddLongTaskTiming(
        start_time, end_time, attribution.first,
        GetFrameAttribute(frame_owner, HTMLNames::srcAttr, false),
        GetFrameAttribute(frame_owner, HTMLNames::idAttr, false),
        GetFrameAttribute(frame_owner, HTMLNames::nameAttr, true),
        IsSameOrigin(attribution.first) ? sub_task_attributions : empty_vector);
  }
}

}  // namespace blink
