• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/browser/automation/automation_util.h"
6 
7 #include <string>
8 
9 #include "base/memory/scoped_ptr.h"
10 #include "base/time.h"
11 #include "base/values.h"
12 #include "chrome/browser/automation/automation_provider.h"
13 #include "chrome/browser/automation/automation_provider_json.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "content/browser/browser_thread.h"
19 #include "content/browser/renderer_host/browser_render_process_host.h"
20 #include "content/browser/renderer_host/render_view_host.h"
21 #include "content/browser/tab_contents/tab_contents.h"
22 #include "net/base/cookie_monster.h"
23 #include "net/base/cookie_store.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_context_getter.h"
26 
27 namespace {
28 
GetCookiesOnIOThread(const GURL & url,const scoped_refptr<net::URLRequestContextGetter> & context_getter,base::WaitableEvent * event,std::string * cookies)29 void GetCookiesOnIOThread(
30     const GURL& url,
31     const scoped_refptr<net::URLRequestContextGetter>& context_getter,
32     base::WaitableEvent* event,
33     std::string* cookies) {
34   *cookies =
35       context_getter->GetURLRequestContext()->cookie_store()->GetCookies(url);
36   event->Signal();
37 }
38 
GetCanonicalCookiesOnIOThread(const GURL & url,const scoped_refptr<net::URLRequestContextGetter> & context_getter,base::WaitableEvent * event,net::CookieList * cookie_list)39 void GetCanonicalCookiesOnIOThread(
40     const GURL& url,
41     const scoped_refptr<net::URLRequestContextGetter>& context_getter,
42     base::WaitableEvent* event,
43     net::CookieList* cookie_list) {
44   *cookie_list =
45       context_getter->GetURLRequestContext()->cookie_store()->
46       GetCookieMonster()->GetAllCookiesForURL(url);
47   event->Signal();
48 }
49 
SetCookieOnIOThread(const GURL & url,const std::string & value,const scoped_refptr<net::URLRequestContextGetter> & context_getter,base::WaitableEvent * event,bool * success)50 void SetCookieOnIOThread(
51     const GURL& url,
52     const std::string& value,
53     const scoped_refptr<net::URLRequestContextGetter>& context_getter,
54     base::WaitableEvent* event,
55     bool* success) {
56   *success =
57       context_getter->GetURLRequestContext()->cookie_store()->
58       SetCookie(url, value);
59   event->Signal();
60 }
61 
SetCookieWithDetailsOnIOThread(const GURL & url,const net::CookieMonster::CanonicalCookie & cookie,const std::string & original_domain,const scoped_refptr<net::URLRequestContextGetter> & context_getter,base::WaitableEvent * event,bool * success)62 void SetCookieWithDetailsOnIOThread(
63     const GURL& url,
64     const net::CookieMonster::CanonicalCookie& cookie,
65     const std::string& original_domain,
66     const scoped_refptr<net::URLRequestContextGetter>& context_getter,
67     base::WaitableEvent* event,
68     bool* success) {
69   net::CookieMonster* cookie_monster =
70       context_getter->GetURLRequestContext()->cookie_store()->
71       GetCookieMonster();
72   *success = cookie_monster->SetCookieWithDetails(
73       url, cookie.Name(), cookie.Value(), original_domain,
74       cookie.Path(), cookie.ExpiryDate(), cookie.IsSecure(),
75       cookie.IsHttpOnly());
76   event->Signal();
77 }
78 
DeleteCookieOnIOThread(const GURL & url,const std::string & name,const scoped_refptr<net::URLRequestContextGetter> & context_getter,base::WaitableEvent * event)79 void DeleteCookieOnIOThread(
80     const GURL& url,
81     const std::string& name,
82     const scoped_refptr<net::URLRequestContextGetter>& context_getter,
83     base::WaitableEvent* event) {
84   context_getter->GetURLRequestContext()->cookie_store()->
85       DeleteCookie(url, name);
86   event->Signal();
87 }
88 
89 }  // namespace
90 
91 namespace automation_util {
92 
GetBrowserAt(int index)93 Browser* GetBrowserAt(int index) {
94   if (index < 0 || index >= static_cast<int>(BrowserList::size()))
95     return NULL;
96   return *(BrowserList::begin() + index);
97 }
98 
GetTabContentsAt(int browser_index,int tab_index)99 TabContents* GetTabContentsAt(int browser_index, int tab_index) {
100   if (tab_index < 0)
101     return NULL;
102   Browser* browser = GetBrowserAt(browser_index);
103   if (!browser || tab_index >= browser->tab_count())
104     return NULL;
105   return browser->GetTabContentsAt(tab_index);
106 }
107 
GetCookies(const GURL & url,TabContents * contents,int * value_size,std::string * value)108 void GetCookies(const GURL& url,
109                 TabContents* contents,
110                 int* value_size,
111                 std::string* value) {
112   *value_size = -1;
113   if (url.is_valid() && contents) {
114     // Since we may be on the UI thread don't call GetURLRequestContext().
115     // Get the request context specific to the current TabContents and app.
116     const Extension* installed_app = static_cast<BrowserRenderProcessHost*>(
117         contents->render_view_host()->process())->installed_app();
118     scoped_refptr<net::URLRequestContextGetter> context_getter =
119         contents->profile()->GetRequestContextForPossibleApp(installed_app);
120 
121     base::WaitableEvent event(true /* manual reset */,
122                               false /* not initially signaled */);
123     CHECK(BrowserThread::PostTask(
124               BrowserThread::IO, FROM_HERE,
125               NewRunnableFunction(&GetCookiesOnIOThread,
126                                   url, context_getter, &event, value)));
127     event.Wait();
128 
129     *value_size = static_cast<int>(value->size());
130   }
131 }
132 
SetCookie(const GURL & url,const std::string & value,TabContents * contents,int * response_value)133 void SetCookie(const GURL& url,
134                const std::string& value,
135                TabContents* contents,
136                int* response_value) {
137   *response_value = -1;
138 
139   if (url.is_valid() && contents) {
140     // Since we may be on the UI thread don't call GetURLRequestContext().
141     // Get the request context specific to the current TabContents and app.
142     const Extension* installed_app = static_cast<BrowserRenderProcessHost*>(
143         contents->render_view_host()->process())->installed_app();
144     scoped_refptr<net::URLRequestContextGetter> context_getter =
145         contents->profile()->GetRequestContextForPossibleApp(installed_app);
146 
147     base::WaitableEvent event(true /* manual reset */,
148                               false /* not initially signaled */);
149     bool success = false;
150     CHECK(BrowserThread::PostTask(
151               BrowserThread::IO, FROM_HERE,
152               NewRunnableFunction(&SetCookieOnIOThread,
153                                   url, value, context_getter, &event,
154                                   &success)));
155     event.Wait();
156     if (success)
157       *response_value = 1;
158   }
159 }
160 
DeleteCookie(const GURL & url,const std::string & cookie_name,TabContents * contents,bool * success)161 void DeleteCookie(const GURL& url,
162                   const std::string& cookie_name,
163                   TabContents* contents,
164                   bool* success) {
165   *success = false;
166   if (url.is_valid() && contents) {
167     // Since we may be on the UI thread don't call GetURLRequestContext().
168     // Get the request context specific to the current TabContents and app.
169     const Extension* installed_app = static_cast<BrowserRenderProcessHost*>(
170         contents->render_view_host()->process())->installed_app();
171     scoped_refptr<net::URLRequestContextGetter> context_getter =
172         contents->profile()->GetRequestContextForPossibleApp(installed_app);
173 
174     base::WaitableEvent event(true /* manual reset */,
175                               false /* not initially signaled */);
176     CHECK(BrowserThread::PostTask(
177               BrowserThread::IO, FROM_HERE,
178               NewRunnableFunction(&DeleteCookieOnIOThread,
179                                   url, cookie_name, context_getter, &event)));
180     event.Wait();
181     *success = true;
182   }
183 }
184 
GetCookiesJSON(AutomationProvider * provider,DictionaryValue * args,IPC::Message * reply_message)185 void GetCookiesJSON(AutomationProvider* provider,
186                     DictionaryValue* args,
187                     IPC::Message* reply_message) {
188   AutomationJSONReply reply(provider, reply_message);
189   std::string url;
190   if (!args->GetString("url", &url)) {
191     reply.SendError("'url' missing or invalid");
192     return;
193   }
194 
195   // Since we may be on the UI thread don't call GetURLRequestContext().
196   scoped_refptr<net::URLRequestContextGetter> context_getter =
197       provider->profile()->GetRequestContext();
198 
199   net::CookieList cookie_list;
200   base::WaitableEvent event(true /* manual reset */,
201                             false /* not initially signaled */);
202   Task* task = NewRunnableFunction(
203       &GetCanonicalCookiesOnIOThread,
204       GURL(url), context_getter, &event, &cookie_list);
205   if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task)) {
206     reply.SendError("Couldn't post task to get the cookies");
207     return;
208   }
209   event.Wait();
210 
211   ListValue* list = new ListValue();
212   for (size_t i = 0; i < cookie_list.size(); ++i) {
213     const net::CookieMonster::CanonicalCookie& cookie = cookie_list[i];
214     DictionaryValue* cookie_dict = new DictionaryValue();
215     cookie_dict->SetString("name", cookie.Name());
216     cookie_dict->SetString("value", cookie.Value());
217     cookie_dict->SetString("path", cookie.Path());
218     cookie_dict->SetString("domain", cookie.Domain());
219     cookie_dict->SetBoolean("secure", cookie.IsSecure());
220     cookie_dict->SetBoolean("http_only", cookie.IsHttpOnly());
221     if (cookie.DoesExpire())
222       cookie_dict->SetDouble("expiry", cookie.ExpiryDate().ToDoubleT());
223     list->Append(cookie_dict);
224   }
225   DictionaryValue dict;
226   dict.Set("cookies", list);
227   reply.SendSuccess(&dict);
228 }
229 
DeleteCookieJSON(AutomationProvider * provider,DictionaryValue * args,IPC::Message * reply_message)230 void DeleteCookieJSON(AutomationProvider* provider,
231                       DictionaryValue* args,
232                       IPC::Message* reply_message) {
233   AutomationJSONReply reply(provider, reply_message);
234   std::string url, name;
235   if (!args->GetString("url", &url)) {
236     reply.SendError("'url' missing or invalid");
237     return;
238   }
239   if (!args->GetString("name", &name)) {
240     reply.SendError("'name' missing or invalid");
241     return;
242   }
243 
244   // Since we may be on the UI thread don't call GetURLRequestContext().
245   scoped_refptr<net::URLRequestContextGetter> context_getter =
246       provider->profile()->GetRequestContext();
247 
248   base::WaitableEvent event(true /* manual reset */,
249                             false /* not initially signaled */);
250   Task* task = NewRunnableFunction(
251       &DeleteCookieOnIOThread,
252       GURL(url), name, context_getter, &event);
253   if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task)) {
254     reply.SendError("Couldn't post task to delete the cookie");
255     return;
256   }
257   event.Wait();
258   reply.SendSuccess(NULL);
259 }
260 
SetCookieJSON(AutomationProvider * provider,DictionaryValue * args,IPC::Message * reply_message)261 void SetCookieJSON(AutomationProvider* provider,
262                    DictionaryValue* args,
263                    IPC::Message* reply_message) {
264   AutomationJSONReply reply(provider, reply_message);
265   std::string url;
266   if (!args->GetString("url", &url)) {
267     reply.SendError("'url' missing or invalid");
268     return;
269   }
270   DictionaryValue* cookie_dict;
271   if (!args->GetDictionary("cookie", &cookie_dict)) {
272     reply.SendError("'cookie' missing or invalid");
273     return;
274   }
275   std::string name, value;
276   std::string domain;
277   std::string path = "/";
278   bool secure = false;
279   double expiry = 0;
280   bool http_only = false;
281   if (!cookie_dict->GetString("name", &name)) {
282     reply.SendError("'name' missing or invalid");
283     return;
284   }
285   if (!cookie_dict->GetString("value", &value)) {
286     reply.SendError("'value' missing or invalid");
287     return;
288   }
289   if (cookie_dict->HasKey("domain") &&
290       !cookie_dict->GetString("domain", &domain)) {
291     reply.SendError("optional 'domain' invalid");
292     return;
293   }
294   if (cookie_dict->HasKey("path") &&
295       !cookie_dict->GetString("path", &path)) {
296     reply.SendError("optional 'path' invalid");
297     return;
298   }
299   if (cookie_dict->HasKey("secure") &&
300       !cookie_dict->GetBoolean("secure", &secure)) {
301     reply.SendError("optional 'secure' invalid");
302     return;
303   }
304   if (cookie_dict->HasKey("expiry")) {
305     int expiry_int;
306     if (cookie_dict->GetInteger("expiry", &expiry_int)) {
307       expiry = expiry_int;
308     } else if (!cookie_dict->GetDouble("expiry", &expiry)) {
309       reply.SendError("optional 'expiry' invalid");
310       return;
311     }
312   }
313   if (cookie_dict->HasKey("http_only") &&
314       !cookie_dict->GetBoolean("http_only", &http_only)) {
315     reply.SendError("optional 'http_only' invalid");
316     return;
317   }
318 
319   scoped_ptr<net::CookieMonster::CanonicalCookie> cookie(
320       net::CookieMonster::CanonicalCookie::Create(
321           GURL(url), name, value, domain, path, base::Time(),
322           base::Time::FromDoubleT(expiry), secure, http_only));
323   if (!cookie.get()) {
324     reply.SendError("given 'cookie' parameters are invalid");
325     return;
326   }
327 
328   // Since we may be on the UI thread don't call GetURLRequestContext().
329   scoped_refptr<net::URLRequestContextGetter> context_getter =
330       provider->profile()->GetRequestContext();
331 
332   base::WaitableEvent event(true /* manual reset */,
333                             false /* not initially signaled */);
334   bool success = false;
335   Task* task = NewRunnableFunction(
336       &SetCookieWithDetailsOnIOThread,
337       GURL(url), *cookie.get(), domain, context_getter, &event, &success);
338   if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task)) {
339     reply.SendError("Couldn't post task to set the cookie");
340     return;
341   }
342   event.Wait();
343 
344   if (!success) {
345     reply.SendError("Could not set the cookie");
346     return;
347   }
348   reply.SendSuccess(NULL);
349 }
350 
351 }  // namespace automation_util
352