root/content/test/plugin/plugin_npobject_lifetime_test.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. timer_id_
  2. SetWindow
  3. TimerProc
  4. URLNotify
  5. SetWindow
  6. timer_id_
  7. SetWindow
  8. TimerProc

// 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).
  bool b1 = 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;
  bool result = 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

/* [<][>][^][v][top][bottom][index][help] */