|
21 | 21 | #include "content/nw/src/api/window/window.h"
|
22 | 22 |
|
23 | 23 | #include "base/values.h"
|
| 24 | +#include "base/strings/utf_string_conversions.h" |
24 | 25 | #include "content/nw/src/api/dispatcher_host.h"
|
25 | 26 | #include "content/nw/src/api/menu/menu.h"
|
26 | 27 | #include "content/nw/src/browser/native_window.h"
|
27 | 28 | #include "content/nw/src/nw_shell.h"
|
| 29 | +#include "content/nw/src/shell_browser_context.h" |
| 30 | +#include "content/public/browser/browser_thread.h" |
| 31 | +#include "content/public/browser/render_view_host.h" |
| 32 | +#include "net/cookies/canonical_cookie.h" |
| 33 | +#include "net/cookies/cookie_constants.h" |
| 34 | +#include "net/cookies/cookie_monster.h" |
| 35 | +#include "net/cookies/cookie_util.h" |
| 36 | +#include "net/url_request/url_request_context.h" |
| 37 | +#include "url/gurl.h" |
| 38 | + |
| 39 | +using content::BrowserThread; |
| 40 | + |
| 41 | +namespace { |
| 42 | + |
| 43 | +void GetCookieListFromStore( |
| 44 | + net::CookieStore* cookie_store, const GURL& url, |
| 45 | + const net::CookieMonster::GetCookieListCallback& callback) { |
| 46 | + DCHECK(cookie_store); |
| 47 | + net::CookieMonster* monster = cookie_store->GetCookieMonster(); |
| 48 | + if (!url.is_empty()) { |
| 49 | + DCHECK(url.is_valid()); |
| 50 | + monster->GetAllCookiesForURLAsync(url, callback); |
| 51 | + } else { |
| 52 | + monster->GetAllCookiesAsync(callback); |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +} // namespace |
28 | 57 |
|
29 | 58 | namespace api {
|
30 | 59 |
|
@@ -130,6 +159,8 @@ void Window::Call(const std::string& method,
|
130 | 159 | std::string image_format_str;
|
131 | 160 | if (arguments.GetString(0, &image_format_str))
|
132 | 161 | shell_->window()->CapturePage(image_format_str);
|
| 162 | + } else if (method == "CookieGet") { |
| 163 | + CookieGet(arguments); |
133 | 164 | } else {
|
134 | 165 | NOTREACHED() << "Invalid call to Window method:" << method
|
135 | 166 | << " arguments:" << arguments;
|
@@ -159,4 +190,87 @@ void Window::CallSync(const std::string& method,
|
159 | 190 | }
|
160 | 191 | }
|
161 | 192 |
|
| 193 | + |
| 194 | +void Window::CookieGet(const base::ListValue& arguments) { |
| 195 | + content::RenderProcessHost* render_process_host = |
| 196 | + dispatcher_host()->render_view_host()->GetProcess(); |
| 197 | + net::URLRequestContextGetter* context_getter = |
| 198 | + render_process_host->GetBrowserContext()-> |
| 199 | + GetRequestContextForRenderProcess(render_process_host->GetID()); |
| 200 | + |
| 201 | + const base::DictionaryValue* details = NULL; |
| 202 | + std::string url; |
| 203 | + |
| 204 | + store_context_ = context_getter; |
| 205 | + if (details) { |
| 206 | + details_.reset(details->DeepCopyWithoutEmptyChildren()); |
| 207 | + details->GetString("url", &url); |
| 208 | + } |
| 209 | + url_ = GURL(url); |
| 210 | + |
| 211 | + bool rv = BrowserThread::PostTask( |
| 212 | + BrowserThread::IO, FROM_HERE, |
| 213 | + base::Bind(&Window::GetCookieOnIOThread, base::Unretained(this))); |
| 214 | + DCHECK(rv); |
| 215 | +} |
| 216 | + |
| 217 | +void Window::GetCookieOnIOThread() { |
| 218 | + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 219 | + net::CookieStore* cookie_store = |
| 220 | + store_context_->GetURLRequestContext()->cookie_store(); |
| 221 | + GetCookieListFromStore( |
| 222 | + cookie_store, url_, |
| 223 | + base::Bind(&Window::GetCookieCallback, base::Unretained(this))); |
| 224 | +} |
| 225 | + |
| 226 | +void Window::GetCookieCallback(const net::CookieList& cookie_list) { |
| 227 | + net::CookieList::const_iterator it; |
| 228 | + std::string name; |
| 229 | + details_->GetString("name", &name); |
| 230 | + |
| 231 | + if (!result_) |
| 232 | + result_.reset(new base::DictionaryValue); |
| 233 | + result_->Clear(); |
| 234 | + |
| 235 | + for (it = cookie_list.begin(); it != cookie_list.end(); ++it) { |
| 236 | + // Return the first matching cookie. Relies on the fact that the |
| 237 | + // CookieMonster returns them in canonical order (longest path, then |
| 238 | + // earliest creation time). |
| 239 | + |
| 240 | + if (it->Name() == name) { |
| 241 | + const net::CanonicalCookie& canonical_cookie = *it; |
| 242 | + // A cookie is a raw byte sequence. By explicitly parsing it as UTF-8, we |
| 243 | + // apply error correction, so the string can be safely passed to the renderer. |
| 244 | + result_->SetString("name", UTF16ToUTF8(UTF8ToUTF16(canonical_cookie.Name()))); |
| 245 | + result_->SetString("value", UTF16ToUTF8(UTF8ToUTF16(canonical_cookie.Value()))); |
| 246 | + result_->SetString("domain", canonical_cookie.Domain()); |
| 247 | + result_->SetBoolean("host_only", net::cookie_util::DomainIsHostOnly( |
| 248 | + canonical_cookie.Domain())); |
| 249 | + // A non-UTF8 path is invalid, so we just replace it with an empty string. |
| 250 | + result_->SetString("path", IsStringUTF8(canonical_cookie.Path()) ? canonical_cookie.Path() |
| 251 | + : std::string()); |
| 252 | + result_->SetBoolean("secure", canonical_cookie.IsSecure()); |
| 253 | + result_->SetBoolean("http_only", canonical_cookie.IsHttpOnly()); |
| 254 | + result_->SetBoolean("session", !canonical_cookie.IsPersistent()); |
| 255 | + if (canonical_cookie.IsPersistent()) { |
| 256 | + result_->SetDouble("expiration_date", |
| 257 | + canonical_cookie.ExpiryDate().ToDoubleT()); |
| 258 | + } |
| 259 | + break; |
| 260 | + } |
| 261 | + } |
| 262 | + |
| 263 | + bool rv = BrowserThread::PostTask( |
| 264 | + BrowserThread::UI, FROM_HERE, |
| 265 | + base::Bind(&Window::RespondOnUIThread, base::Unretained(this))); |
| 266 | + DCHECK(rv); |
| 267 | +} |
| 268 | + |
| 269 | +void Window::RespondOnUIThread() { |
| 270 | + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 271 | + base::ListValue args; |
| 272 | + args.Append(result_.release()); |
| 273 | + dispatcher_host()->SendEvent(this, "__nw_gotcookie", args); |
| 274 | +} |
| 275 | + |
162 | 276 | } // namespace api
|
0 commit comments