// Copyright 2014 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.

#ifndef CONTENT_RENDERER_PEPPER_PLUGIN_INSTANCE_THROTTLER_IMPL_H_
#define CONTENT_RENDERER_PEPPER_PLUGIN_INSTANCE_THROTTLER_IMPL_H_

#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/public/renderer/plugin_instance_throttler.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"

namespace blink {
class WebInputEvent;
struct WebRect;
}

namespace content {

class PepperWebPluginImpl;
class RenderFrameImpl;

class CONTENT_EXPORT PluginInstanceThrottlerImpl
    : public PluginInstanceThrottler {
 public:
  PluginInstanceThrottlerImpl();

  ~PluginInstanceThrottlerImpl() override;

  // PluginInstanceThrottler implementation:
  void AddObserver(Observer* observer) override;
  void RemoveObserver(Observer* observer) override;
  bool IsThrottled() const override;
  bool IsHiddenForPlaceholder() const override;
  void MarkPluginEssential(PowerSaverUnthrottleMethod method) override;
  void SetHiddenForPlaceholder(bool hidden) override;
  PepperWebPluginImpl* GetWebPlugin() const override;
  const gfx::Size& GetSize() const override;
  void NotifyAudioThrottled() override;

  void SetWebPlugin(PepperWebPluginImpl* web_plugin);

  bool needs_representative_keyframe() const {
    return state_ == THROTTLER_STATE_AWAITING_KEYFRAME;
  }

  bool power_saver_enabled() const {
    return state_ != THROTTLER_STATE_MARKED_ESSENTIAL;
  }

  void Initialize(RenderFrameImpl* frame,
                  const GURL& content_origin,
                  const std::string& plugin_module_name,
                  const gfx::Size& unobscured_size);

  // Called when the plugin flushes it's graphics context. Supplies the
  // throttler with a candidate to use as the representative keyframe.
  void OnImageFlush(const SkBitmap* bitmap);

  // Returns true if |event| was handled and shouldn't be further processed.
  bool ConsumeInputEvent(const blink::WebInputEvent& event);

 private:
  friend class PluginInstanceThrottlerImplTest;

  enum ThrottlerState {
    // Plugin has been found to be peripheral, Plugin Power Saver is enabled,
    // and throttler is awaiting a representative keyframe.
    THROTTLER_STATE_AWAITING_KEYFRAME,
    // A representative keyframe has been chosen and the plugin is throttled.
    THROTTLER_STATE_PLUGIN_THROTTLED,
    // Plugin instance has been marked essential.
    THROTTLER_STATE_MARKED_ESSENTIAL,
  };

  // Maximum number of frames to examine for a suitable keyframe. After that, we
  // simply suspend the plugin where it's at. Chosen arbitrarily.
  static const int kMaximumFramesToExamine;

  void AudioThrottledFrameTimeout();
  void EngageThrottle();

  ThrottlerState state_;

  bool is_hidden_for_placeholder_;

  PepperWebPluginImpl* web_plugin_;

  // Holds a reference to the last received frame. This doesn't actually copy
  // the pixel data, but rather increments the reference count to the pixels.
  SkBitmap last_received_frame_;

  // Number of frames we've examined to find a keyframe.
  int frames_examined_;

  // Plugin's unobscured dimensions as of initialization.
  gfx::Size unobscured_size_;

  // Video plugins with throttled audio often stop generating frames.
  // This timer is so we don't wait forever for candidate poster frames.
  bool audio_throttled_;
  base::DelayTimer<PluginInstanceThrottlerImpl> audio_throttled_frame_timeout_;

  base::ObserverList<Observer> observer_list_;

  base::WeakPtrFactory<PluginInstanceThrottlerImpl> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(PluginInstanceThrottlerImpl);
};
}

#endif  // CONTENT_RENDERER_PEPPER_PLUGIN_INSTANCE_THROTTLER_IMPL_H_
