summaryrefslogtreecommitdiffstats
path: root/chrome/browser/automation/automation_resource_message_filter.h
blob: d1a192dcf3d61e3566392492bb27d087b4f61fd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// Copyright (c) 2006-2009 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_AUTOMATION_AUTOMATION_RESOURCE_MESSAGE_FILTER_H_
#define CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MESSAGE_FILTER_H_
#pragma once

#include <map>

#include "base/atomicops.h"
#include "base/lazy_instance.h"
#include "ipc/ipc_channel_proxy.h"
#include "net/base/completion_callback.h"
#include "net/base/cookie_store.h"

class URLRequestAutomationJob;
class GURL;

namespace net {
class CookieStore;
}  // namespace net

// This class filters out incoming automation IPC messages for network
// requests and processes them on the IPC thread.  As a result, network
// requests are not delayed by costly UI processing that may be occurring
// on the main thread of the browser.  It also means that any hangs in
// starting a network request will not interfere with browser UI.
class AutomationResourceMessageFilter
    : public IPC::ChannelProxy::MessageFilter,
      public IPC::Message::Sender {
 public:
  // Information needed to send IPCs through automation.
  struct AutomationDetails {
    AutomationDetails();
    AutomationDetails(int tab, AutomationResourceMessageFilter* flt,
                      bool pending_view);
    ~AutomationDetails();

    void set_cookie_store(net::CookieStore* cookie_store) {
      cookie_store_ = cookie_store;
    }

    net::CookieStore* cookie_store() {
      return cookie_store_.get();
    }

    int tab_handle;
    int ref_count;
    scoped_refptr<AutomationResourceMessageFilter> filter;
    // Indicates whether network requests issued by this render view need to
    // be executed later.
    bool is_pending_render_view;

    // The cookie store associated with this render view.
    scoped_refptr<net::CookieStore> cookie_store_;
  };

  // Create the filter.
  AutomationResourceMessageFilter();
  virtual ~AutomationResourceMessageFilter();

  // Returns a new automation request id. This is unique across all instances
  // of AutomationResourceMessageFilter.
  int NewAutomationRequestId() {
    return base::subtle::Barrier_AtomicIncrement(&unique_request_id_, 1);
  }

  // IPC::ChannelProxy::MessageFilter methods:
  virtual void OnFilterAdded(IPC::Channel* channel);
  virtual void OnFilterRemoved();

  virtual void OnChannelConnected(int32 peer_pid);
  virtual void OnChannelClosing();
  virtual bool OnMessageReceived(const IPC::Message& message);

  // ResourceDispatcherHost::Receiver methods:
  virtual bool Send(IPC::Message* message);

  // Add request to the list of outstanding requests.
  virtual bool RegisterRequest(URLRequestAutomationJob* job);

  // Remove request from the list of outstanding requests.
  virtual void UnRegisterRequest(URLRequestAutomationJob* job);

  // Can be called from the UI thread.
  // The pending_view parameter should be true if network requests initiated by
  // this render view need to be paused waiting for an acknowledgement from
  // the external host.
  static bool RegisterRenderView(int renderer_pid, int renderer_id,
      int tab_handle, AutomationResourceMessageFilter* filter,
      bool pending_view);
  static void UnRegisterRenderView(int renderer_pid, int renderer_id);

  // Can be called from the UI thread.
  // Resumes pending render views, i.e. network requests issued by this view
  // can now be serviced.
  static bool ResumePendingRenderView(int renderer_pid, int renderer_id,
      int tab_handle, AutomationResourceMessageFilter* filter);

  // Called only on the IO thread.
  static bool LookupRegisteredRenderView(
      int renderer_pid, int renderer_id, AutomationDetails* details);

  // Sends the download request to the automation host.
  bool SendDownloadRequestToHost(int routing_id, int tab_handle,
                                 int request_id);

  // Retrieves cookies for the url passed in from the external host. The
  // callback passed in is notified on success or failure asynchronously.
  // Returns true on success.
  static bool GetCookiesForUrl(const GURL& url,
                               net::CompletionCallback* callback);

  // Sets cookies on the URL in the external host. Returns true on success.
  static bool SetCookiesForUrl(const GURL& url, const std::string& cookie_line,
                               net::CompletionCallback* callback);

  // This function gets invoked when we receive a response from the external
  // host for the cookie request sent in GetCookiesForUrl above. It sets the
  // cookie temporarily on the cookie store and executes the completion
  // callback which reads the cookie from the store. The cookie value is reset
  // after the callback finishes executing.
  void OnGetCookiesHostResponse(int tab_handle, bool success, const GURL& url,
                                const std::string& cookies, int cookie_id);

 protected:
  // Retrieves the automation request id for the passed in chrome request
  // id and returns it in the automation_request_id parameter.
  // Returns true on success.
  bool GetAutomationRequestId(int request_id, int* automation_request_id);

  static void RegisterRenderViewInIOThread(int renderer_pid, int renderer_id,
      int tab_handle, AutomationResourceMessageFilter* filter,
      bool pending_view);
  static void UnRegisterRenderViewInIOThread(int renderer_pid, int renderer_id);

  static bool ResumePendingRenderViewInIOThread(
      int renderer_pid, int renderer_id, int tab_handle,
      AutomationResourceMessageFilter* filter);

  // Helper function to execute the GetCookies completion callback with the
  // response for the GetCookies request from the renderer.
  static void OnGetCookiesHostResponseInternal(
      int tab_handle, bool success, const GURL& url,
      const std::string& cookies, net::CompletionCallback* callback,
      net::CookieStore* cookie_store);

 private:
  void OnSetFilteredInet(bool enable);
  void OnGetFilteredInetHitCount(int* hit_count);
  void OnRecordHistograms(const std::vector<std::string>& histogram_list);

  // Resumes pending jobs from the old AutomationResourceMessageFilter instance
  // passed in.
  static void ResumeJobsForPendingView(
      int tab_handle,
      AutomationResourceMessageFilter* old_filter,
      AutomationResourceMessageFilter* new_filter);

  static int GetNextCompletionCallbackId() {
    return ++next_completion_callback_id_;
  }

  // A unique renderer id is a combination of renderer process id and
  // it's routing id.
  struct RendererId {
    int pid_;
    int id_;

    RendererId() : pid_(0), id_(0) {}
    RendererId(int pid, int id) : pid_(pid), id_(id) {}

    bool operator < (const RendererId& rhs) const {
      return ((pid_ == rhs.pid_) ? (id_ < rhs.id_) : (pid_ < rhs.pid_));
    }
  };

  typedef std::map<RendererId, AutomationDetails> RenderViewMap;
  typedef std::map<int, scoped_refptr<URLRequestAutomationJob> > RequestMap;

  // The channel associated with the automation connection. This pointer is not
  // owned by this class.
  IPC::Channel* channel_;

  // A unique request id per process.
  static int unique_request_id_;

  // Map of outstanding requests.
  RequestMap request_map_;

  // Map of pending requests, i.e. requests which were waiting for the external
  // host to connect back.
  RequestMap pending_request_map_;

  // Map of render views interested in diverting url requests over automation.
  static base::LazyInstance<RenderViewMap> filtered_render_views_;

  // Contains information used for completing the request to read cookies from
  // the host coming in from the renderer.
  struct CookieCompletionInfo;

  // Map of completion callback id to CookieCompletionInfo, which contains the
  // actual callback which is invoked on successful retrieval of cookies from
  // host. The mapping is setup when GetCookiesForUrl is invoked to retrieve
  // cookies from the host and is removed when we receive a response from the
  // host. Please see the OnGetCookiesHostResponse function.
  typedef std::map<int, CookieCompletionInfo> CompletionCallbackMap;
  static base::LazyInstance<CompletionCallbackMap> completion_callback_map_;

  // Contains the id of the next completion callback. This is passed to the the
  // external host as a cookie referring to the completion callback.
  static int next_completion_callback_id_;

  DISALLOW_COPY_AND_ASSIGN(AutomationResourceMessageFilter);
};

#endif  // CHROME_BROWSER_AUTOMATION_AUTOMATION_RESOURCE_MESSAGE_FILTER_H_