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