/*
 *  Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 *  Copyright (C) 2008 Apple Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA 02110-1301 USA
 */

#include "modules/plugins/DOMPluginArray.h"

#include "core/dom/Document.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Navigator.h"
#include "core/page/Page.h"
#include "modules/plugins/DOMMimeTypeArray.h"
#include "modules/plugins/NavigatorPlugins.h"
#include "platform/plugins/PluginData.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/text/AtomicString.h"

namespace blink {

DOMPluginArray::DOMPluginArray(LocalFrame* frame)
    : ContextLifecycleObserver(frame ? frame->GetDocument() : nullptr),
      PluginsChangedObserver(frame ? frame->GetPage() : nullptr) {
  UpdatePluginData();
}

void DOMPluginArray::Trace(blink::Visitor* visitor) {
  visitor->Trace(dom_plugins_);
  ScriptWrappable::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
  PluginsChangedObserver::Trace(visitor);
}

unsigned DOMPluginArray::length() const {
  return dom_plugins_.size();
}

DOMPlugin* DOMPluginArray::item(unsigned index) {
  if (index >= dom_plugins_.size())
    return nullptr;

  if (!dom_plugins_[index]) {
    dom_plugins_[index] =
        DOMPlugin::Create(GetFrame(), *GetPluginData()->Plugins()[index]);
  }

  return dom_plugins_[index];
}

DOMPlugin* DOMPluginArray::namedItem(const AtomicString& property_name) {
  PluginData* data = GetPluginData();
  if (!data)
    return nullptr;

  for (const Member<PluginInfo>& plugin_info : data->Plugins()) {
    if (plugin_info->Name() == property_name) {
      size_t index = &plugin_info - &data->Plugins()[0];
      return item(index);
    }
  }
  return nullptr;
}

void DOMPluginArray::NamedPropertyEnumerator(Vector<String>& property_names,
                                             ExceptionState&) const {
  PluginData* data = GetPluginData();
  if (!data)
    return;
  property_names.ReserveInitialCapacity(data->Plugins().size());
  for (const PluginInfo* plugin_info : data->Plugins()) {
    property_names.UncheckedAppend(plugin_info->Name());
  }
}

bool DOMPluginArray::NamedPropertyQuery(const AtomicString& property_name,
                                        ExceptionState& exception_state) const {
  Vector<String> properties;
  NamedPropertyEnumerator(properties, exception_state);
  return properties.Contains(property_name);
}

void DOMPluginArray::refresh(bool reload) {
  if (!GetFrame())
    return;

  Page::RefreshPlugins();
  if (PluginData* data = GetPluginData())
    data->ResetPluginData();

  for (Frame* frame = GetFrame()->GetPage()->MainFrame(); frame;
       frame = frame->Tree().TraverseNext()) {
    if (!frame->IsLocalFrame())
      continue;
    Navigator& navigator = *ToLocalFrame(frame)->DomWindow()->navigator();
    NavigatorPlugins::plugins(navigator)->UpdatePluginData();
    NavigatorPlugins::mimeTypes(navigator)->UpdatePluginData();
  }

  if (reload) {
    GetFrame()->Reload(kFrameLoadTypeReload,
                       ClientRedirectPolicy::kClientRedirect);
  }
}

PluginData* DOMPluginArray::GetPluginData() const {
  if (!GetFrame())
    return nullptr;
  return GetFrame()->GetPluginData();
}

void DOMPluginArray::UpdatePluginData() {
  PluginData* data = GetPluginData();
  if (!data) {
    dom_plugins_.clear();
    return;
  }

  HeapVector<Member<DOMPlugin>> old_dom_plugins(std::move(dom_plugins_));
  dom_plugins_.clear();
  dom_plugins_.resize(data->Plugins().size());

  for (Member<DOMPlugin>& plugin : old_dom_plugins) {
    if (plugin) {
      for (const Member<PluginInfo>& plugin_info : data->Plugins()) {
        if (plugin->name() == plugin_info->Name()) {
          size_t index = &plugin_info - &data->Plugins()[0];
          dom_plugins_[index] = plugin;
        }
      }
    }
  }
}

void DOMPluginArray::ContextDestroyed(ExecutionContext*) {
  dom_plugins_.clear();
}

void DOMPluginArray::PluginsChanged() {
  UpdatePluginData();
}

}  // namespace blink
