11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#ifndef EXTENSIONS_BROWSER_LAZY_BACKGROUND_TASK_QUEUE_H_
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#define EXTENSIONS_BROWSER_LAZY_BACKGROUND_TASK_QUEUE_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_forward.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/compiler_specific.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/gtest_prod_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/scoped_observer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_registry_observer.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace content {
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class BrowserContext;
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Extension;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionHost;
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass ExtensionRegistry;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class maintains a queue of tasks that should execute when an
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extension's lazy background page is loaded. It is also in charge of loading
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the page when the first task is queued.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is the consumer's responsibility to use this class when appropriate, i.e.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only with extensions that have not-yet-loaded lazy background pages.
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass LazyBackgroundTaskQueue : public content::NotificationObserver,
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                public ExtensionRegistryObserver {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::Callback<void(ExtensionHost*)> PendingTask;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  explicit LazyBackgroundTaskQueue(content::BrowserContext* browser_context);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~LazyBackgroundTaskQueue();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Returns the number of extensions having pending tasks.
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  size_t extensions_with_pending_tasks() { return pending_tasks_.size(); }
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the task should be added to the queue (that is, if the
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension has a lazy background page that isn't ready yet). If the
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension has a lazy background page that is being suspended this method
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cancels that suspension.
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool ShouldEnqueueTask(content::BrowserContext* context,
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         const Extension* extension);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds a task to the queue for a given extension. If this is the first
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task added for the extension, its lazy background page will be loaded.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The task will be called either when the page is loaded, or when the
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // page fails to load for some reason (e.g. a crash or browser
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // shutdown). In the latter case, the ExtensionHost parameter is NULL.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddPendingTask(
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      content::BrowserContext* context,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& extension_id,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const PendingTask& task);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(LazyBackgroundTaskQueueTest, ProcessPendingTasks);
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // A map between a BrowserContext/extension_id pair and the queue of tasks
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // pending the load of its background page.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::string ExtensionID;
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  typedef std::pair<content::BrowserContext*, ExtensionID> PendingTasksKey;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<PendingTask> PendingTasksList;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<PendingTasksKey,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   linked_ptr<PendingTasksList> > PendingTasksMap;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content::NotificationObserver interface.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // ExtensionRegistryObserver interface.
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void OnExtensionUnloaded(
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      content::BrowserContext* browser_context,
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const Extension* extension,
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UnloadedExtensionInfo::Reason reason) OVERRIDE;
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a lazy background page has finished loading, or has failed to
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // load (host is NULL in that case). All enqueued tasks are run in order.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ProcessPendingTasks(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionHost* host,
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      content::BrowserContext* context,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  content::BrowserContext* browser_context_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingTasksMap pending_tasks_;
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_registry_observer_;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#endif  // EXTENSIONS_BROWSER_LAZY_BACKGROUND_TASK_QUEUE_H_
103