1// Copyright (c) 2006-2009 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_AUTOMATION_AUTOMATION_RESOURCE_MESSAGE_FILTER_H_
6#define CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MESSAGE_FILTER_H_
7#pragma once
8
9#include <map>
10
11#include "base/atomicops.h"
12#include "base/lazy_instance.h"
13#include "ipc/ipc_channel_proxy.h"
14#include "net/base/completion_callback.h"
15#include "net/base/cookie_store.h"
16
17class URLRequestAutomationJob;
18class GURL;
19
20namespace net {
21class CookieStore;
22}  // namespace net
23
24// This class filters out incoming automation IPC messages for network
25// requests and processes them on the IPC thread.  As a result, network
26// requests are not delayed by costly UI processing that may be occurring
27// on the main thread of the browser.  It also means that any hangs in
28// starting a network request will not interfere with browser UI.
29class AutomationResourceMessageFilter
30    : public IPC::ChannelProxy::MessageFilter,
31      public IPC::Message::Sender {
32 public:
33  // Information needed to send IPCs through automation.
34  struct AutomationDetails {
35    AutomationDetails();
36    AutomationDetails(int tab, AutomationResourceMessageFilter* flt,
37                      bool pending_view);
38    ~AutomationDetails();
39
40    void set_cookie_store(net::CookieStore* cookie_store) {
41      cookie_store_ = cookie_store;
42    }
43
44    net::CookieStore* cookie_store() {
45      return cookie_store_.get();
46    }
47
48    int tab_handle;
49    int ref_count;
50    scoped_refptr<AutomationResourceMessageFilter> filter;
51    // Indicates whether network requests issued by this render view need to
52    // be executed later.
53    bool is_pending_render_view;
54
55    // The cookie store associated with this render view.
56    scoped_refptr<net::CookieStore> cookie_store_;
57  };
58
59  // Create the filter.
60  AutomationResourceMessageFilter();
61  virtual ~AutomationResourceMessageFilter();
62
63  // Returns a new automation request id. This is unique across all instances
64  // of AutomationResourceMessageFilter.
65  int NewAutomationRequestId() {
66    return base::subtle::Barrier_AtomicIncrement(&unique_request_id_, 1);
67  }
68
69  // IPC::ChannelProxy::MessageFilter methods:
70  virtual void OnFilterAdded(IPC::Channel* channel);
71  virtual void OnFilterRemoved();
72
73  virtual void OnChannelConnected(int32 peer_pid);
74  virtual void OnChannelClosing();
75  virtual bool OnMessageReceived(const IPC::Message& message);
76
77  // ResourceDispatcherHost::Receiver methods:
78  virtual bool Send(IPC::Message* message);
79
80  // Add request to the list of outstanding requests.
81  virtual bool RegisterRequest(URLRequestAutomationJob* job);
82
83  // Remove request from the list of outstanding requests.
84  virtual void UnRegisterRequest(URLRequestAutomationJob* job);
85
86  // Can be called from the UI thread.
87  // The pending_view parameter should be true if network requests initiated by
88  // this render view need to be paused waiting for an acknowledgement from
89  // the external host.
90  static bool RegisterRenderView(int renderer_pid, int renderer_id,
91      int tab_handle, AutomationResourceMessageFilter* filter,
92      bool pending_view);
93  static void UnRegisterRenderView(int renderer_pid, int renderer_id);
94
95  // Can be called from the UI thread.
96  // Resumes pending render views, i.e. network requests issued by this view
97  // can now be serviced.
98  static bool ResumePendingRenderView(int renderer_pid, int renderer_id,
99      int tab_handle, AutomationResourceMessageFilter* filter);
100
101  // Called only on the IO thread.
102  static bool LookupRegisteredRenderView(
103      int renderer_pid, int renderer_id, AutomationDetails* details);
104
105  // Sends the download request to the automation host.
106  bool SendDownloadRequestToHost(int routing_id, int tab_handle,
107                                 int request_id);
108
109  // Retrieves cookies for the url passed in from the external host. The
110  // callback passed in is notified on success or failure asynchronously.
111  // Returns true on success.
112  static bool GetCookiesForUrl(const GURL& url,
113                               net::CompletionCallback* callback);
114
115  // Sets cookies on the URL in the external host. Returns true on success.
116  static bool SetCookiesForUrl(const GURL& url, const std::string& cookie_line,
117                               net::CompletionCallback* callback);
118
119  // This function gets invoked when we receive a response from the external
120  // host for the cookie request sent in GetCookiesForUrl above. It sets the
121  // cookie temporarily on the cookie store and executes the completion
122  // callback which reads the cookie from the store. The cookie value is reset
123  // after the callback finishes executing.
124  void OnGetCookiesHostResponse(int tab_handle, bool success, const GURL& url,
125                                const std::string& cookies, int cookie_id);
126
127 protected:
128  // Retrieves the automation request id for the passed in chrome request
129  // id and returns it in the automation_request_id parameter.
130  // Returns true on success.
131  bool GetAutomationRequestId(int request_id, int* automation_request_id);
132
133  static void RegisterRenderViewInIOThread(int renderer_pid, int renderer_id,
134      int tab_handle, AutomationResourceMessageFilter* filter,
135      bool pending_view);
136  static void UnRegisterRenderViewInIOThread(int renderer_pid, int renderer_id);
137
138  static bool ResumePendingRenderViewInIOThread(
139      int renderer_pid, int renderer_id, int tab_handle,
140      AutomationResourceMessageFilter* filter);
141
142  // Helper function to execute the GetCookies completion callback with the
143  // response for the GetCookies request from the renderer.
144  static void OnGetCookiesHostResponseInternal(
145      int tab_handle, bool success, const GURL& url,
146      const std::string& cookies, net::CompletionCallback* callback,
147      net::CookieStore* cookie_store);
148
149 private:
150  void OnSetFilteredInet(bool enable);
151  void OnGetFilteredInetHitCount(int* hit_count);
152  void OnRecordHistograms(const std::vector<std::string>& histogram_list);
153
154  // Resumes pending jobs from the old AutomationResourceMessageFilter instance
155  // passed in.
156  static void ResumeJobsForPendingView(
157      int tab_handle,
158      AutomationResourceMessageFilter* old_filter,
159      AutomationResourceMessageFilter* new_filter);
160
161  static int GetNextCompletionCallbackId() {
162    return ++next_completion_callback_id_;
163  }
164
165  // A unique renderer id is a combination of renderer process id and
166  // it's routing id.
167  struct RendererId {
168    int pid_;
169    int id_;
170
171    RendererId() : pid_(0), id_(0) {}
172    RendererId(int pid, int id) : pid_(pid), id_(id) {}
173
174    bool operator < (const RendererId& rhs) const {
175      return ((pid_ == rhs.pid_) ? (id_ < rhs.id_) : (pid_ < rhs.pid_));
176    }
177  };
178
179  typedef std::map<RendererId, AutomationDetails> RenderViewMap;
180  typedef std::map<int, scoped_refptr<URLRequestAutomationJob> > RequestMap;
181
182  // The channel associated with the automation connection. This pointer is not
183  // owned by this class.
184  IPC::Channel* channel_;
185
186  // A unique request id per process.
187  static int unique_request_id_;
188
189  // Map of outstanding requests.
190  RequestMap request_map_;
191
192  // Map of pending requests, i.e. requests which were waiting for the external
193  // host to connect back.
194  RequestMap pending_request_map_;
195
196  // Map of render views interested in diverting url requests over automation.
197  static base::LazyInstance<RenderViewMap> filtered_render_views_;
198
199  // Contains information used for completing the request to read cookies from
200  // the host coming in from the renderer.
201  struct CookieCompletionInfo;
202
203  // Map of completion callback id to CookieCompletionInfo, which contains the
204  // actual callback which is invoked on successful retrieval of cookies from
205  // host. The mapping is setup when GetCookiesForUrl is invoked to retrieve
206  // cookies from the host and is removed when we receive a response from the
207  // host. Please see the OnGetCookiesHostResponse function.
208  typedef std::map<int, CookieCompletionInfo> CompletionCallbackMap;
209  static base::LazyInstance<CompletionCallbackMap> completion_callback_map_;
210
211  // Contains the id of the next completion callback. This is passed to the the
212  // external host as a cookie referring to the completion callback.
213  static int next_completion_callback_id_;
214
215  DISALLOW_COPY_AND_ASSIGN(AutomationResourceMessageFilter);
216};
217
218#endif  // CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MESSAGE_FILTER_H_
219
220