1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_LISTENER_H_
6#define CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_LISTENER_H_
7
8#include <deque>
9#include <list>
10#include <map>
11
12#include "base/compiler_specific.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/weak_ptr.h"
15#include "content/public/browser/browser_thread.h"
16#include "content/public/browser/notification_observer.h"
17#include "content/public/browser/notification_registrar.h"
18#include "content/public/common/resource_type.h"
19
20class GURL;
21class URLPattern;
22
23namespace content {
24class ResourceThrottle;
25}
26
27namespace extensions {
28class Extension;
29
30// This class handles delaying of resource loads that depend on unloaded user
31// scripts. For each request that comes in, we check if it depends on a user
32// script, and if so, whether that user script is ready; if not, we delay the
33// request.
34//
35// This class lives mostly on the IO thread. It listens on the UI thread for
36// updates to loaded extensions.
37class UserScriptListener
38    : public base::RefCountedThreadSafe<
39          UserScriptListener,
40          content::BrowserThread::DeleteOnUIThread>,
41      public content::NotificationObserver {
42 public:
43  UserScriptListener();
44
45  // Constructs a ResourceThrottle if the UserScriptListener needs to delay the
46  // given URL.  Otherwise, this method returns NULL.
47  content::ResourceThrottle* CreateResourceThrottle(
48      const GURL& url,
49      content::ResourceType resource_type);
50
51 private:
52  friend struct content::BrowserThread::DeleteOnThread<
53      content::BrowserThread::UI>;
54  friend class base::DeleteHelper<UserScriptListener>;
55
56  typedef std::list<URLPattern> URLPatterns;
57
58  virtual ~UserScriptListener();
59
60  bool ShouldDelayRequest(const GURL& url,
61                          content::ResourceType resource_type);
62  void StartDelayedRequests();
63
64  // Update user_scripts_ready_ based on the status of all profiles. On a
65  // transition from false to true, we resume all delayed requests.
66  void CheckIfAllUserScriptsReady();
67
68  // Resume any requests that we delayed in order to wait for user scripts.
69  void UserScriptsReady(void* profile_id);
70
71  // Clean up per-profile information related to the given profile.
72  void ProfileDestroyed(void* profile_id);
73
74  // Appends new url patterns to our list, also setting user_scripts_ready_
75  // to false.
76  void AppendNewURLPatterns(void* profile_id, const URLPatterns& new_patterns);
77
78  // Replaces our url pattern list. This is only used when patterns have been
79  // deleted, so user_scripts_ready_ remains unchanged.
80  void ReplaceURLPatterns(void* profile_id, const URLPatterns& patterns);
81
82  // True if all user scripts from all profiles are ready.
83  bool user_scripts_ready_;
84
85  // Stores a throttle per URL request that we have delayed.
86  class Throttle;
87  typedef base::WeakPtr<Throttle> WeakThrottle;
88  typedef std::deque<WeakThrottle> WeakThrottleList;
89  WeakThrottleList throttles_;
90
91  // Per-profile bookkeeping so we know when all user scripts are ready.
92  struct ProfileData;
93  typedef std::map<void*, ProfileData> ProfileDataMap;
94  ProfileDataMap profile_data_;
95
96  // --- UI thread:
97
98  // Helper to collect the extension's user script URL patterns in a list and
99  // return it.
100  void CollectURLPatterns(const Extension* extension,
101                          URLPatterns* patterns);
102
103  // content::NotificationObserver
104  virtual void Observe(int type,
105                       const content::NotificationSource& source,
106                       const content::NotificationDetails& details) OVERRIDE;
107
108  content::NotificationRegistrar registrar_;
109
110  DISALLOW_COPY_AND_ASSIGN(UserScriptListener);
111};
112
113}  // namespace extensions
114
115#endif  // CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_LISTENER_H_
116