// Copyright (c) 2012 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 CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_
#define CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_

#include <list>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "chrome/browser/prerender/prerender_handle.h"
#include "components/keyed_service/core/keyed_service.h"
#include "url/gurl.h"

class Profile;

namespace content {
struct Referrer;
}

namespace gfx {
class Size;
}

FORWARD_DECLARE_TEST(WebViewTest, NoPrerenderer);

namespace prerender {

class PrerenderContents;
class PrerenderManager;

// PrerenderLinkManager implements the API on Link elements for all documents
// being rendered in this chrome instance.  It receives messages from the
// renderer indicating addition, cancelation and abandonment of link elements,
// and controls the PrerenderManager accordingly.
class PrerenderLinkManager : public KeyedService,
                             public PrerenderHandle::Observer {
 public:
  explicit PrerenderLinkManager(PrerenderManager* manager);
  virtual ~PrerenderLinkManager();

  // A <link rel=prerender ...> element has been inserted into the document.
  // The |prerender_id| must be unique per |child_id|, and is assigned by the
  // WebPrerendererClient.
  void OnAddPrerender(int child_id,
                      int prerender_id,
                      const GURL& url,
                      uint32 rel_types,
                      const content::Referrer& referrer,
                      const gfx::Size& size,
                      int render_view_route_id);

  // A <link rel=prerender ...> element has been explicitly removed from a
  // document.
  void OnCancelPrerender(int child_id, int prerender_id);

  // A renderer launching <link rel=prerender ...> has navigated away from the
  // launching page, the launching renderer process has crashed, or perhaps the
  // renderer process was fast-closed when the last render view in it was
  // closed.
  void OnAbandonPrerender(int child_id, int prerender_id);

  // If a renderer channel closes (crash, fast exit, etc...), that's effectively
  // an abandon of any prerenders launched by that child.
  void OnChannelClosing(int child_id);

 private:
  friend class PrerenderBrowserTest;
  friend class PrerenderTest;
  // WebViewTest.NoPrerenderer needs to access the private IsEmpty() method.
  FRIEND_TEST_ALL_PREFIXES(::WebViewTest, NoPrerenderer);

  struct LinkPrerender {
    LinkPrerender(int launcher_child_id,
                  int prerender_id,
                  const GURL& url,
                  uint32 rel_types,
                  const content::Referrer& referrer,
                  const gfx::Size& size,
                  int render_view_route_id,
                  base::TimeTicks creation_time,
                  PrerenderContents* deferred_launcher);
    ~LinkPrerender();

    // Parameters from PrerenderLinkManager::OnAddPrerender():
    int launcher_child_id;
    int prerender_id;
    GURL url;
    uint32 rel_types;
    content::Referrer referrer;
    gfx::Size size;
    int render_view_route_id;

    // The time at which this Prerender was added to PrerenderLinkManager.
    base::TimeTicks creation_time;

    // If non-NULL, this link prerender was launched by an unswapped prerender,
    // |deferred_launcher|. When |deferred_launcher| is swapped in, the field is
    // set to NULL.
    PrerenderContents* deferred_launcher;

    // Initially NULL, |handle| is set once we start this prerender. It is owned
    // by this struct, and must be deleted before destructing this struct.
    PrerenderHandle* handle;

    // True if this prerender has become a MatchComplete replacement. This state
    // is maintained so the renderer is not notified of a stop twice.
    bool is_match_complete_replacement;

    // True if this prerender has been abandoned by its launcher.
    bool has_been_abandoned;
  };

  class PendingPrerenderManager;

  bool IsEmpty() const;

  // Returns a count of currently running prerenders.
  size_t CountRunningPrerenders() const;

  // Start any prerenders that can be started, respecting concurrency limits for
  // the system and per launcher.
  void StartPrerenders();

  LinkPrerender* FindByLauncherChildIdAndPrerenderId(int child_id,
                                                     int prerender_id);

  LinkPrerender* FindByPrerenderHandle(PrerenderHandle* prerender_handle);

  // Removes |prerender| from the the prerender link manager. Deletes the
  // PrerenderHandle as needed.
  void RemovePrerender(LinkPrerender* prerender);

  // Cancels |prerender| and removes |prerender| from the prerender link
  // manager.
  void CancelPrerender(LinkPrerender* prerender);

  // Called when |launcher| is swapped in.
  void StartPendingPrerendersForLauncher(PrerenderContents* launcher);

  // Called when |launcher| is aborted.
  void CancelPendingPrerendersForLauncher(PrerenderContents* launcher);

  // From KeyedService:
  virtual void Shutdown() OVERRIDE;

  // From PrerenderHandle::Observer:
  virtual void OnPrerenderStart(PrerenderHandle* prerender_handle) OVERRIDE;
  virtual void OnPrerenderStopLoading(PrerenderHandle* prerender_handle)
      OVERRIDE;
  virtual void OnPrerenderDomContentLoaded(PrerenderHandle* prerender_handle)
      OVERRIDE;
  virtual void OnPrerenderStop(PrerenderHandle* prerender_handle) OVERRIDE;
  virtual void OnPrerenderCreatedMatchCompleteReplacement(
      PrerenderHandle* handle) OVERRIDE;

  bool has_shutdown_;

  PrerenderManager* manager_;

  // All prerenders known to this PrerenderLinkManager. Insertions are always
  // made at the back, so the oldest prerender is at the front, and the youngest
  // at the back.
  std::list<LinkPrerender> prerenders_;

  // Helper object to manage prerenders which are launched by other prerenders
  // and must be deferred until the launcher is swapped in.
  scoped_ptr<PendingPrerenderManager> pending_prerender_manager_;

  DISALLOW_COPY_AND_ASSIGN(PrerenderLinkManager);
};

}  // namespace prerender

#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_LINK_MANAGER_H_
