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 EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_TIME_TRACKER_H_
6#define EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_TIME_TRACKER_H_
7
8#include <map>
9#include <queue>
10#include <set>
11#include <string>
12
13#include "base/gtest_prod_util.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/time/time.h"
16#include "url/gurl.h"
17
18namespace base {
19class Time;
20}
21
22class ExtensionWebRequestTimeTrackerDelegate {
23 public:
24  virtual ~ExtensionWebRequestTimeTrackerDelegate() {}
25
26  // Notifies the delegate that |num_delayed_messages| of the last
27  // |total_num_messages| inspected messages were excessively/moderately
28  // delayed. Every excessively delayed message is also counted as a moderately
29  // delayed message.
30  virtual void NotifyExcessiveDelays(
31      void* profile,
32      size_t num_delayed_messages,
33      size_t total_num_messages,
34      const std::set<std::string>& extension_ids) = 0;
35  virtual void NotifyModerateDelays(
36      void* profile,
37      size_t num_delayed_messages,
38      size_t total_num_messages,
39      const std::set<std::string>& extension_ids) = 0;
40};
41
42// This class keeps monitors how much delay extensions add to network requests
43// by using the webRequest API. If the delay is sufficient, we will warn the
44// user that extensions are slowing down the browser.
45class ExtensionWebRequestTimeTracker {
46 public:
47  ExtensionWebRequestTimeTracker();
48  ~ExtensionWebRequestTimeTracker();
49
50  // Records the time that a request was created.
51  void LogRequestStartTime(int64 request_id, const base::Time& start_time,
52                           const GURL& url, void* profile);
53
54  // Records the time that a request either completed or encountered an error.
55  void LogRequestEndTime(int64 request_id, const base::Time& end_time);
56
57  // Records an additional delay for the given request caused by the given
58  // extension.
59  void IncrementExtensionBlockTime(
60      const std::string& extension_id,
61      int64 request_id,
62      const base::TimeDelta& block_time);
63
64  // Records an additional delay for the given request caused by all extensions
65  // combined.
66  void IncrementTotalBlockTime(
67      int64 request_id,
68      const base::TimeDelta& block_time);
69
70  // Called when an extension has canceled the given request.
71  void SetRequestCanceled(int64 request_id);
72
73  // Called when an extension has redirected the given request to another URL.
74  void SetRequestRedirected(int64 request_id);
75
76  // Takes ownership of |delegate|.
77  void SetDelegate(ExtensionWebRequestTimeTrackerDelegate* delegate);
78
79 private:
80  // Timing information for a single request.
81  struct RequestTimeLog {
82    GURL url;  // used for debug purposes only
83    void* profile;  // profile that created the request
84    bool completed;
85    base::Time request_start_time;
86    base::TimeDelta request_duration;
87    base::TimeDelta block_duration;
88    std::map<std::string, base::TimeDelta> extension_block_durations;
89    RequestTimeLog();
90    ~RequestTimeLog();
91  };
92
93  // Called after a request finishes, to analyze the delays and warn the user
94  // if necessary.
95  void Analyze(int64 request_id);
96
97  // Returns a list of all extension IDs that contributed to delay for |log|.
98  std::set<std::string> GetExtensionIds(const RequestTimeLog& log) const;
99
100  // A map of recent request IDs to timing info for each request.
101  std::map<int64, RequestTimeLog> request_time_logs_;
102
103  // A list of recent request IDs that we know about. Used to limit the size of
104  // the logs.
105  std::queue<int64> request_ids_;
106
107  // The set of recent requests that have been delayed either a large or
108  // moderate amount by extensions.
109  std::set<int64> excessive_delays_;
110  std::set<int64> moderate_delays_;
111
112  // Defaults to a delegate that sets warnings in the extension service.
113  scoped_ptr<ExtensionWebRequestTimeTrackerDelegate> delegate_;
114
115  FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTimeTrackerTest, Basic);
116  FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTimeTrackerTest,
117                           IgnoreFastRequests);
118  FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTimeTrackerTest,
119                           CancelOrRedirect);
120  FRIEND_TEST_ALL_PREFIXES(ExtensionWebRequestTimeTrackerTest, Delays);
121
122  DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestTimeTracker);
123};
124
125#endif  // EXTENSIONS_BROWSER_API_WEB_REQUEST_WEB_REQUEST_TIME_TRACKER_H_
126