// Copyright (c) 2010 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 "content/test/plugin/plugin_npobject_lifetime_test.h"

namespace NPAPIClient {

const int kNPObjectLifetimeTimer = 100;
const int kNPObjectLifetimeTimerElapse = 2000;

NPObject* NPObjectLifetimeTestInstance2::plugin_instance_object_ = NULL;

NPObjectDeletePluginInNPN_Evaluate*
    NPObjectDeletePluginInNPN_Evaluate::g_npn_evaluate_test_instance_ = NULL;

NPObjectLifetimeTest::NPObjectLifetimeTest(NPP id,
                                           NPNetscapeFuncs *host_functions)
    : PluginTest(id, host_functions),
      other_plugin_instance_object_(NULL),
      timer_id_(0) {
}

NPError NPObjectLifetimeTest::SetWindow(NPWindow* pNPWindow) {
  if (pNPWindow->window == NULL)
    return NPERR_NO_ERROR;

  HWND window_handle = reinterpret_cast<HWND>(pNPWindow->window);
  if (!::GetProp(window_handle, L"Plugin_Instance")) {
    // TODO: this propery leaks.
    ::SetProp(window_handle, L"Plugin_Instance", this);
    // We attempt to retreive the NPObject for the plugin instance identified
    // by the NPObjectLifetimeTestInstance2 class as it may not have been
    // instantiated yet.
    timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer,
                         kNPObjectLifetimeTimerElapse, TimerProc);
  }
  return NPERR_NO_ERROR;
}

void CALLBACK NPObjectLifetimeTest::TimerProc(
    HWND window, UINT message, UINT_PTR timer_id,
    DWORD elapsed_milli_seconds) {

  NPObjectLifetimeTest* this_instance =
      reinterpret_cast<NPObjectLifetimeTest*>
          (::GetProp(window, L"Plugin_Instance"));
  KillTimer(window, this_instance->timer_id_);
  ::RemoveProp(window,  L"Plugin_Instance");

  this_instance->timer_id_ = 0;

  this_instance->other_plugin_instance_object_ =
      NPObjectLifetimeTestInstance2::plugin_instance_object_;
  this_instance->HostFunctions()->retainobject(
      this_instance->other_plugin_instance_object_);

  NPString script;
  script.UTF8Characters = "javascript:DeleteSecondPluginInstance()";
  script.UTF8Length = static_cast<uint32_t>(strlen(script.UTF8Characters));

  this_instance->HostFunctions()->geturlnotify(
      this_instance->id(), "javascript:DeleteSecondPluginInstance()", NULL,
      reinterpret_cast<void*>(1));
}

void NPObjectLifetimeTest::URLNotify(const char* url, NPReason reason,
                                     void* data) {
  // Create a "location" identifier.
  NPIdentifier identifier = HostFunctions()->getstringidentifier("location");
  // Declare a local variant value.
  NPVariant variantValue;
  // Get the location property from the window object (which is another object).
  HostFunctions()->getproperty(id(), other_plugin_instance_object_, identifier,
                               &variantValue );
  HostFunctions()->releaseobject(other_plugin_instance_object_);
  other_plugin_instance_object_ = NULL;
  // If this test failed, then we'd have crashed by now.
  SignalTestCompleted();
}

NPObjectLifetimeTestInstance2::NPObjectLifetimeTestInstance2(
    NPP id, NPNetscapeFuncs *host_functions)
    : PluginTest(id, host_functions) {
}

NPObjectLifetimeTestInstance2::~NPObjectLifetimeTestInstance2() {
  if (plugin_instance_object_) {
    HostFunctions()->releaseobject(plugin_instance_object_);
    plugin_instance_object_ = NULL;
  }
}

NPError NPObjectLifetimeTestInstance2::SetWindow(NPWindow* pNPWindow) {
  if (pNPWindow->window == NULL)
    return NPERR_NO_ERROR;

  if (!plugin_instance_object_) {
    if (!HostFunctions()->getvalue(id(), NPNVWindowNPObject,
                                   &plugin_instance_object_)) {
      SetError("Failed to get NPObject for plugin instance2");
      SignalTestCompleted();
      return NPERR_GENERIC_ERROR;
    }
  }

  return NPERR_NO_ERROR;
}


NPObjectDeletePluginInNPN_Evaluate::NPObjectDeletePluginInNPN_Evaluate(
    NPP id, NPNetscapeFuncs *host_functions)
    : PluginTest(id, host_functions),
      plugin_instance_object_(NULL),
      timer_id_(0) {
  g_npn_evaluate_test_instance_ = this;
}

NPObjectDeletePluginInNPN_Evaluate::~NPObjectDeletePluginInNPN_Evaluate() {
  if (plugin_instance_object_) {
    HostFunctions()->releaseobject(plugin_instance_object_);
    plugin_instance_object_ = NULL;
  }
}

NPError NPObjectDeletePluginInNPN_Evaluate::SetWindow(NPWindow* np_window) {
  if (np_window->window == NULL)
    return NPERR_NO_ERROR;

  HWND window_handle = reinterpret_cast<HWND>(np_window->window);
  // We setup a timerproc to invoke NPN_Evaluate to destroy this plugin
  // instance. This is to ensure that we don't destroy the plugin instance
  // while it is being used in webkit as this leads to crashes and is a
  // more accurate representation of the renderer crash as described in
  // http://b/issue?id=1134683.
  if (!timer_id_) {
    timer_id_ = SetTimer(window_handle, kNPObjectLifetimeTimer,
                         kNPObjectLifetimeTimerElapse, TimerProc);
  }
  return NPERR_NO_ERROR;
}

void CALLBACK NPObjectDeletePluginInNPN_Evaluate::TimerProc(
    HWND window, UINT message, UINT_PTR timer_id,
    DWORD elapsed_milli_seconds) {

  KillTimer(window, g_npn_evaluate_test_instance_->timer_id_);
  g_npn_evaluate_test_instance_->timer_id_ = 0;
  NPObject *window_obj = NULL;
  g_npn_evaluate_test_instance_->HostFunctions()->getvalue(
      g_npn_evaluate_test_instance_->id(), NPNVWindowNPObject,
      &window_obj);

  if (!window_obj) {
    g_npn_evaluate_test_instance_->SetError(
        "Failed to get NPObject for plugin instance2");
    g_npn_evaluate_test_instance_->SignalTestCompleted();
    return;
  }

  std::string script = "javascript:DeletePluginWithinScript()";
  NPString script_string;
  script_string.UTF8Characters = script.c_str();
  script_string.UTF8Length =
      static_cast<unsigned int>(script.length());

  NPVariant result_var;
  g_npn_evaluate_test_instance_->HostFunctions()->evaluate(
      g_npn_evaluate_test_instance_->id(), window_obj,
      &script_string, &result_var);
  // If this test failed we would have crashed by now.
}

} // namespace NPAPIClient
