1 // Copyright (c) 2015 GitHub, Inc.
2 // Use of this source code is governed by the MIT license that can be
3 // found in the LICENSE file.
5 #include "atom/browser/api/atom_api_session.h"
11 #include "atom/browser/api/atom_api_cookies.h"
12 #include "atom/browser/api/atom_api_download_item.h"
13 #include "atom/browser/api/atom_api_protocol.h"
14 #include "atom/browser/api/atom_api_web_request.h"
15 #include "atom/browser/atom_browser_context.h"
16 #include "atom/browser/atom_browser_main_parts.h"
17 #include "atom/browser/atom_permission_manager.h"
18 #include "atom/browser/browser.h"
19 #include "atom/browser/net/atom_cert_verifier.h"
20 #include "atom/common/native_mate_converters/callback.h"
21 #include "atom/common/native_mate_converters/content_converter.h"
22 #include "atom/common/native_mate_converters/file_path_converter.h"
23 #include "atom/common/native_mate_converters/gurl_converter.h"
24 #include "atom/common/native_mate_converters/net_converter.h"
25 #include "atom/common/native_mate_converters/value_converter.h"
26 #include "atom/common/node_includes.h"
27 #include "base/files/file_path.h"
28 #include "base/guid.h"
29 #include "base/strings/string_number_conversions.h"
30 #include "base/strings/string_util.h"
31 #include "base/threading/thread_task_runner_handle.h"
32 #include "brightray/browser/media/media_device_id_salt.h"
33 #include "brightray/browser/net/devtools_network_conditions.h"
34 #include "brightray/browser/net/devtools_network_controller_handle.h"
35 #include "chrome/common/pref_names.h"
36 #include "components/prefs/pref_service.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/download_manager_delegate.h"
39 #include "content/public/browser/storage_partition.h"
40 #include "native_mate/dictionary.h"
41 #include "native_mate/object_template_builder.h"
42 #include "net/base/load_flags.h"
43 #include "net/disk_cache/disk_cache.h"
44 #include "net/dns/host_cache.h"
45 #include "net/http/http_auth_handler_factory.h"
46 #include "net/http/http_auth_preferences.h"
47 #include "net/proxy/proxy_config_service_fixed.h"
48 #include "net/proxy/proxy_service.h"
49 #include "net/url_request/static_http_user_agent_settings.h"
50 #include "net/url_request/url_request_context.h"
51 #include "net/url_request/url_request_context_getter.h"
52 #include "tizen/common/env_variables.h"
53 #include "ui/base/l10n/l10n_util.h"
55 using atom::api::Cookies;
56 using content::BrowserThread;
57 using content::StoragePartition;
61 struct ClearStorageDataOptions {
63 uint32_t storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
64 uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
67 struct ClearAuthCacheOptions {
71 base::string16 username;
72 base::string16 password;
73 net::HttpAuth::Scheme auth_scheme;
76 uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
77 uint32_t storage_mask = 0;
78 for (const auto& it : storage_types) {
79 auto type = base::ToLowerASCII(it);
80 if (type == "appcache")
81 storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
82 else if (type == "cookies")
83 storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
84 else if (type == "filesystem")
85 storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
86 else if (type == "indexdb")
87 storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
88 else if (type == "localstorage")
89 storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
90 else if (type == "shadercache")
91 storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
92 else if (type == "websql")
93 storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
94 else if (type == "serviceworkers")
95 storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
100 uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
101 uint32_t quota_mask = 0;
102 for (const auto& it : quota_types) {
103 auto type = base::ToLowerASCII(it);
104 if (type == "temporary")
105 quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
106 else if (type == "persistent")
107 quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
108 else if (type == "syncable")
109 quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
114 net::HttpAuth::Scheme GetAuthSchemeFromString(const std::string& scheme) {
115 if (scheme == "basic")
116 return net::HttpAuth::AUTH_SCHEME_BASIC;
117 if (scheme == "digest")
118 return net::HttpAuth::AUTH_SCHEME_DIGEST;
119 if (scheme == "ntlm")
120 return net::HttpAuth::AUTH_SCHEME_NTLM;
121 if (scheme == "negotiate")
122 return net::HttpAuth::AUTH_SCHEME_NEGOTIATE;
123 return net::HttpAuth::AUTH_SCHEME_MAX;
126 void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
127 const std::string& accept_lang,
128 const std::string& user_agent) {
129 getter->GetURLRequestContext()->set_http_user_agent_settings(
130 new net::StaticHttpUserAgentSettings(
131 net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
140 struct Converter<ClearStorageDataOptions> {
141 static bool FromV8(v8::Isolate* isolate,
142 v8::Local<v8::Value> val,
143 ClearStorageDataOptions* out) {
144 mate::Dictionary options;
145 if (!ConvertFromV8(isolate, val, &options))
147 options.Get("origin", &out->origin);
148 std::vector<std::string> types;
149 if (options.Get("storages", &types))
150 out->storage_types = GetStorageMask(types);
151 if (options.Get("quotas", &types))
152 out->quota_types = GetQuotaMask(types);
158 struct Converter<ClearAuthCacheOptions> {
159 static bool FromV8(v8::Isolate* isolate,
160 v8::Local<v8::Value> val,
161 ClearAuthCacheOptions* out) {
162 mate::Dictionary options;
163 if (!ConvertFromV8(isolate, val, &options))
165 options.Get("type", &out->type);
166 options.Get("origin", &out->origin);
167 options.Get("realm", &out->realm);
168 options.Get("username", &out->username);
169 options.Get("password", &out->password);
171 if (options.Get("scheme", &scheme))
172 out->auth_scheme = GetAuthSchemeFromString(scheme);
178 struct Converter<net::ProxyConfig> {
179 static bool FromV8(v8::Isolate* isolate,
180 v8::Local<v8::Value> val,
181 net::ProxyConfig* out) {
182 std::string proxy_rules, proxy_bypass_rules;
184 mate::Dictionary options;
185 // Fallback to previous API when passed String.
186 // https://git.io/vuhjj
187 if (ConvertFromV8(isolate, val, &proxy_rules)) {
188 pac_url = GURL(proxy_rules); // Assume it is PAC script if it is URL.
189 } else if (ConvertFromV8(isolate, val, &options)) {
190 options.Get("pacScript", &pac_url);
191 options.Get("proxyRules", &proxy_rules);
192 options.Get("proxyBypassRules", &proxy_bypass_rules);
197 // pacScript takes precedence over proxyRules.
198 if (!pac_url.is_empty() && pac_url.is_valid()) {
199 out->set_pac_url(pac_url);
201 out->proxy_rules().ParseFromString(proxy_rules);
202 out->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_rules);
209 struct Converter<atom::VerifyRequestParams> {
210 static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
211 atom::VerifyRequestParams val) {
212 mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
213 dict.Set("hostname", val.hostname);
214 dict.Set("certificate", val.certificate);
215 dict.Set("verificationResult", val.default_result);
216 return dict.GetHandle();
228 const char kPersistPrefix[] = "persist:";
230 // Referenced session objects.
231 std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
233 class ResolveProxyHelper {
235 ResolveProxyHelper(AtomBrowserContext* browser_context,
237 const Session::ResolveProxyCallback& callback)
238 : callback_(callback),
239 original_thread_(base::ThreadTaskRunnerHandle::Get()) {
240 scoped_refptr<net::URLRequestContextGetter> context_getter =
241 browser_context->url_request_context_getter();
242 context_getter->GetNetworkTaskRunner()->PostTask(
244 base::Bind(&ResolveProxyHelper::ResolveProxy,
245 base::Unretained(this), context_getter, url));
248 void OnResolveProxyCompleted(int result) {
250 if (result == net::OK)
251 proxy = proxy_info_.ToPacString();
252 original_thread_->PostTask(FROM_HERE,
253 base::Bind(callback_, proxy));
258 void ResolveProxy(scoped_refptr<net::URLRequestContextGetter> context_getter,
260 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
262 net::ProxyService* proxy_service =
263 context_getter->GetURLRequestContext()->proxy_service();
264 net::CompletionCallback completion_callback =
265 base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
266 base::Unretained(this));
268 // Start the request.
269 int result = proxy_service->ResolveProxy(
270 url, "GET", &proxy_info_, completion_callback, &pac_req_, nullptr,
271 net::NetLogWithSource());
273 // Completed synchronously.
274 if (result != net::ERR_IO_PENDING)
275 completion_callback.Run(result);
278 Session::ResolveProxyCallback callback_;
279 net::ProxyInfo proxy_info_;
280 net::ProxyService::PacRequest* pac_req_;
281 scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
283 DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
286 // Runs the callback in UI thread.
287 void RunCallbackInUI(const base::Callback<void()>& callback) {
288 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
290 template<typename ...T>
291 void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... result) {
292 BrowserThread::PostTask(
293 BrowserThread::UI, FROM_HERE, base::Bind(callback, result...));
296 // Callback of HttpCache::GetBackend.
297 void OnGetBackend(disk_cache::Backend** backend_ptr,
298 Session::CacheAction action,
299 const net::CompletionCallback& callback,
301 if (result != net::OK) {
302 RunCallbackInUI(callback, result);
303 } else if (backend_ptr && *backend_ptr) {
304 if (action == Session::CacheAction::CLEAR) {
305 (*backend_ptr)->DoomAllEntries(base::Bind(&RunCallbackInUI<int>,
307 } else if (action == Session::CacheAction::STATS) {
308 base::StringPairs stats;
309 (*backend_ptr)->GetStats(&stats);
310 for (const auto& stat : stats) {
311 if (stat.first == "Current size") {
313 base::StringToInt(stat.second, ¤t_size);
314 RunCallbackInUI(callback, current_size);
320 RunCallbackInUI<int>(callback, net::ERR_FAILED);
324 void DoCacheActionInIO(
325 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
326 Session::CacheAction action,
327 const net::CompletionCallback& callback) {
328 auto request_context = context_getter->GetURLRequestContext();
329 auto http_cache = request_context->http_transaction_factory()->GetCache();
331 RunCallbackInUI<int>(callback, net::ERR_FAILED);
333 // Call GetBackend and make the backend's ptr accessable in OnGetBackend.
334 using BackendPtr = disk_cache::Backend*;
335 auto* backend_ptr = new BackendPtr(nullptr);
336 net::CompletionCallback on_get_backend =
337 base::Bind(&OnGetBackend, base::Owned(backend_ptr), action, callback);
338 int rv = http_cache->GetBackend(backend_ptr, on_get_backend);
339 if (rv != net::ERR_IO_PENDING)
340 on_get_backend.Run(net::OK);
343 void SetProxyInIO(net::URLRequestContextGetter* getter,
344 const net::ProxyConfig& config,
345 const base::Closure& callback) {
346 auto proxy_service = getter->GetURLRequestContext()->proxy_service();
347 proxy_service->ResetConfigService(base::WrapUnique(
348 new net::ProxyConfigServiceFixed(config)));
349 // Refetches and applies the new pac script if provided.
350 proxy_service->ForceReloadProxyConfig();
351 RunCallbackInUI(callback);
354 void SetCertVerifyProcInIO(
355 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
356 const AtomCertVerifier::VerifyProc& proc) {
357 auto request_context = context_getter->GetURLRequestContext();
358 static_cast<AtomCertVerifier*>(request_context->cert_verifier())->
362 void ClearHostResolverCacheInIO(
363 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
364 const base::Closure& callback) {
365 auto request_context = context_getter->GetURLRequestContext();
366 auto cache = request_context->host_resolver()->GetHostCache();
369 DCHECK_EQ(0u, cache->size());
370 if (!callback.is_null())
371 RunCallbackInUI(callback);
375 void ClearAuthCacheInIO(
376 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
377 const ClearAuthCacheOptions& options,
378 const base::Closure& callback) {
379 auto request_context = context_getter->GetURLRequestContext();
380 auto network_session =
381 request_context->http_transaction_factory()->GetSession();
382 if (network_session) {
383 if (options.type == "password") {
384 auto auth_cache = network_session->http_auth_cache();
385 if (!options.origin.is_empty()) {
387 options.origin, options.realm, options.auth_scheme,
388 net::AuthCredentials(options.username, options.password));
390 auth_cache->ClearEntriesAddedWithin(base::TimeDelta::Max());
392 } else if (options.type == "clientCertificate") {
393 auto client_auth_cache = network_session->ssl_client_auth_cache();
394 client_auth_cache->Remove(net::HostPortPair::FromURL(options.origin));
396 network_session->CloseAllConnections();
398 if (!callback.is_null())
399 RunCallbackInUI(callback);
402 void AllowNTLMCredentialsForDomainsInIO(
403 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
404 const std::string& domains) {
405 auto request_context = context_getter->GetURLRequestContext();
406 auto auth_handler = request_context->http_auth_handler_factory();
408 auto auth_preferences = const_cast<net::HttpAuthPreferences*>(
409 auth_handler->http_auth_preferences());
410 if (auth_preferences)
411 auth_preferences->set_server_whitelist(domains);
415 void OnClearStorageDataDone(const base::Closure& callback) {
416 if (!callback.is_null())
420 void DownloadIdCallback(content::DownloadManager* download_manager,
421 const base::FilePath& path,
422 const std::vector<GURL>& url_chain,
423 const std::string& mime_type,
426 const std::string& last_modified,
427 const std::string& etag,
428 const base::Time& start_time,
430 download_manager->CreateDownloadItem(
431 base::GenerateGUID(), id, path, path, url_chain, GURL(), GURL(), GURL(),
432 GURL(), mime_type, mime_type, start_time, base::Time(), etag,
433 last_modified, offset, length, std::string(),
434 content::DownloadItem::INTERRUPTED,
435 content::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
436 content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false);
441 Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
442 : devtools_network_emulation_client_id_(base::GenerateGUID()),
443 browser_context_(browser_context) {
444 // Observe DownloadManager to get download notifications.
445 content::BrowserContext::GetDownloadManager(browser_context)->
449 AttachAsUserData(browser_context);
452 Session::~Session() {
453 content::BrowserContext::GetDownloadManager(browser_context())->
454 RemoveObserver(this);
455 g_sessions.erase(weak_map_id());
458 void Session::OnDownloadCreated(content::DownloadManager* manager,
459 content::DownloadItem* item) {
460 if (item->IsSavePackageDownload())
463 if (!::tizen::is_single_process)
464 v8::Locker locker(isolate());
465 v8::HandleScope handle_scope(isolate());
466 auto handle = DownloadItem::Create(isolate(), item);
467 if (item->GetState() == content::DownloadItem::INTERRUPTED)
468 handle->SetSavePath(item->GetTargetFilePath());
469 bool prevent_default = Emit("will-download", handle, item->GetWebContents());
470 if (prevent_default) {
476 void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
477 new ResolveProxyHelper(browser_context(), url, callback);
480 template<Session::CacheAction action>
481 void Session::DoCacheAction(const net::CompletionCallback& callback) {
482 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
483 base::Bind(&DoCacheActionInIO,
484 make_scoped_refptr(browser_context_->GetRequestContext()),
489 void Session::ClearStorageData(mate::Arguments* args) {
490 // clearStorageData([options, callback])
491 ClearStorageDataOptions options;
492 base::Closure callback;
493 args->GetNext(&options);
494 args->GetNext(&callback);
496 auto storage_partition =
497 content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
498 if (options.storage_types & StoragePartition::REMOVE_DATA_MASK_COOKIES) {
499 // Reset media device id salt when cookies are cleared.
500 // https://w3c.github.io/mediacapture-main/#dom-mediadeviceinfo-deviceid
501 brightray::MediaDeviceIDSalt::Reset(browser_context()->prefs());
503 storage_partition->ClearData(
504 options.storage_types, options.quota_types, options.origin,
505 content::StoragePartition::OriginMatcherFunction(),
506 base::Time(), base::Time::Max(),
507 base::Bind(&OnClearStorageDataDone, callback));
510 void Session::FlushStorageData() {
511 auto storage_partition =
512 content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
513 storage_partition->Flush();
516 void Session::SetProxy(const net::ProxyConfig& config,
517 const base::Closure& callback) {
518 auto getter = browser_context_->GetRequestContext();
519 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
520 base::Bind(&SetProxyInIO, base::Unretained(getter), config, callback));
523 void Session::SetDownloadPath(const base::FilePath& path) {
524 browser_context_->prefs()->SetFilePath(
525 prefs::kDownloadDefaultDirectory, path);
528 void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
529 std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
530 bool offline = false;
531 double latency = 0.0, download_throughput = 0.0, upload_throughput = 0.0;
532 if (options.Get("offline", &offline) && offline) {
533 conditions.reset(new brightray::DevToolsNetworkConditions(offline));
535 options.Get("latency", &latency);
536 options.Get("downloadThroughput", &download_throughput);
537 options.Get("uploadThroughput", &upload_throughput);
539 new brightray::DevToolsNetworkConditions(false,
545 browser_context_->network_controller_handle()->SetNetworkState(
546 devtools_network_emulation_client_id_, std::move(conditions));
547 browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId(
548 devtools_network_emulation_client_id_);
551 void Session::DisableNetworkEmulation() {
552 std::unique_ptr<brightray::DevToolsNetworkConditions> conditions;
553 browser_context_->network_controller_handle()->SetNetworkState(
554 devtools_network_emulation_client_id_, std::move(conditions));
555 browser_context_->network_delegate()->SetDevToolsNetworkEmulationClientId(
559 void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
560 mate::Arguments* args) {
561 AtomCertVerifier::VerifyProc proc;
562 if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) {
563 args->ThrowError("Must pass null or function");
567 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
568 base::Bind(&SetCertVerifyProcInIO,
569 make_scoped_refptr(browser_context_->GetRequestContext()),
573 void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
574 mate::Arguments* args) {
575 AtomPermissionManager::RequestHandler handler;
576 if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &handler))) {
577 args->ThrowError("Must pass null or function");
580 auto permission_manager = static_cast<AtomPermissionManager*>(
581 browser_context()->GetPermissionManager());
582 permission_manager->SetPermissionRequestHandler(handler);
585 void Session::ClearHostResolverCache(mate::Arguments* args) {
586 base::Closure callback;
587 args->GetNext(&callback);
589 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
590 base::Bind(&ClearHostResolverCacheInIO,
591 make_scoped_refptr(browser_context_->GetRequestContext()),
595 void Session::ClearAuthCache(mate::Arguments* args) {
596 ClearAuthCacheOptions options;
597 if (!args->GetNext(&options)) {
598 args->ThrowError("Must specify options object");
601 base::Closure callback;
602 args->GetNext(&callback);
604 BrowserThread::PostTask(
605 BrowserThread::IO, FROM_HERE,
606 base::Bind(&ClearAuthCacheInIO,
607 make_scoped_refptr(browser_context_->GetRequestContext()),
611 void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
612 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
613 base::Bind(&AllowNTLMCredentialsForDomainsInIO,
614 make_scoped_refptr(browser_context_->GetRequestContext()),
618 void Session::SetUserAgent(const std::string& user_agent,
619 mate::Arguments* args) {
620 browser_context_->SetUserAgent(user_agent);
622 std::string accept_lang = l10n_util::GetApplicationLocale("");
623 args->GetNext(&accept_lang);
625 auto getter = browser_context_->GetRequestContext();
626 getter->GetNetworkTaskRunner()->PostTask(
628 base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
631 std::string Session::GetUserAgent() {
632 return browser_context_->GetUserAgent();
635 void Session::GetBlobData(
636 const std::string& uuid,
637 const AtomBlobReader::CompletionCallback& callback) {
638 if (callback.is_null())
641 AtomBlobReader* blob_reader =
642 browser_context()->GetBlobReader();
643 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
644 base::Bind(&AtomBlobReader::StartReading,
645 base::Unretained(blob_reader),
650 void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
651 int64_t offset = 0, length = 0;
652 double start_time = 0.0;
653 std::string mime_type, last_modified, etag;
655 std::vector<GURL> url_chain;
656 options.Get("path", &path);
657 options.Get("urlChain", &url_chain);
658 options.Get("mimeType", &mime_type);
659 options.Get("offset", &offset);
660 options.Get("length", &length);
661 options.Get("lastModified", &last_modified);
662 options.Get("eTag", &etag);
663 options.Get("startTime", &start_time);
664 if (path.empty() || url_chain.empty() || length == 0) {
665 isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
666 isolate(), "Must pass non-empty path, urlChain and length.")));
669 if (offset >= length) {
670 isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
671 isolate(), "Must pass an offset value less than length.")));
674 auto download_manager =
675 content::BrowserContext::GetDownloadManager(browser_context());
676 download_manager->GetDelegate()->GetNextId(base::Bind(
677 &DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
678 length, last_modified, etag, base::Time::FromDoubleT(start_time)));
681 v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
682 if (cookies_.IsEmpty()) {
683 auto handle = Cookies::Create(isolate, browser_context());
684 cookies_.Reset(isolate, handle.ToV8());
686 return v8::Local<v8::Value>::New(isolate, cookies_);
689 v8::Local<v8::Value> Session::Protocol(v8::Isolate* isolate) {
690 if (protocol_.IsEmpty()) {
691 auto handle = atom::api::Protocol::Create(isolate, browser_context());
692 protocol_.Reset(isolate, handle.ToV8());
694 return v8::Local<v8::Value>::New(isolate, protocol_);
697 v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
698 if (web_request_.IsEmpty()) {
699 auto handle = atom::api::WebRequest::Create(isolate, browser_context());
700 web_request_.Reset(isolate, handle.ToV8());
702 return v8::Local<v8::Value>::New(isolate, web_request_);
706 mate::Handle<Session> Session::CreateFrom(
707 v8::Isolate* isolate, AtomBrowserContext* browser_context) {
708 auto existing = TrackableObject::FromWrappedClass(isolate, browser_context);
710 return mate::CreateHandle(isolate, static_cast<Session*>(existing));
712 auto handle = mate::CreateHandle(
713 isolate, new Session(isolate, browser_context));
715 // The Sessions should never be garbage collected, since the common pattern is
716 // to use partition strings, instead of using the Session object directly.
717 g_sessions[handle->weak_map_id()] =
718 v8::Global<v8::Object>(isolate, handle.ToV8());
724 mate::Handle<Session> Session::FromPartition(
725 v8::Isolate* isolate, const std::string& partition,
726 const base::DictionaryValue& options) {
727 scoped_refptr<AtomBrowserContext> browser_context;
728 if (partition.empty()) {
729 browser_context = AtomBrowserContext::From("", false, options);
730 } else if (base::StartsWith(partition, kPersistPrefix,
731 base::CompareCase::SENSITIVE)) {
732 std::string name = partition.substr(8);
733 browser_context = AtomBrowserContext::From(name, false, options);
735 browser_context = AtomBrowserContext::From(partition, true, options);
737 return CreateFrom(isolate, browser_context.get());
741 void Session::BuildPrototype(v8::Isolate* isolate,
742 v8::Local<v8::FunctionTemplate> prototype) {
743 prototype->SetClassName(mate::StringToV8(isolate, "Session"));
744 mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
746 .SetMethod("resolveProxy", &Session::ResolveProxy)
747 .SetMethod("getCacheSize", &Session::DoCacheAction<CacheAction::STATS>)
748 .SetMethod("clearCache", &Session::DoCacheAction<CacheAction::CLEAR>)
749 .SetMethod("clearStorageData", &Session::ClearStorageData)
750 .SetMethod("flushStorageData", &Session::FlushStorageData)
751 .SetMethod("setProxy", &Session::SetProxy)
752 .SetMethod("setDownloadPath", &Session::SetDownloadPath)
753 .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
754 .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
755 .SetMethod("_setCertificateVerifyProc", &Session::SetCertVerifyProc)
756 .SetMethod("setPermissionRequestHandler",
757 &Session::SetPermissionRequestHandler)
758 .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
759 .SetMethod("clearAuthCache", &Session::ClearAuthCache)
760 .SetMethod("allowNTLMCredentialsForDomains",
761 &Session::AllowNTLMCredentialsForDomains)
762 .SetMethod("setUserAgent", &Session::SetUserAgent)
763 .SetMethod("getUserAgent", &Session::GetUserAgent)
764 .SetMethod("getBlobData", &Session::GetBlobData)
765 .SetMethod("createInterruptedDownload",
766 &Session::CreateInterruptedDownload)
767 .SetProperty("cookies", &Session::Cookies)
768 .SetProperty("protocol", &Session::Protocol)
769 .SetProperty("webRequest", &Session::WebRequest);
778 using atom::api::Session;
780 v8::Local<v8::Value> FromPartition(
781 const std::string& partition, mate::Arguments* args) {
782 if (!atom::Browser::Get()->is_ready()) {
783 args->ThrowError("Session can only be received when app is ready");
784 return v8::Null(args->isolate());
786 base::DictionaryValue options;
787 args->GetNext(&options);
788 return Session::FromPartition(args->isolate(), partition, options).ToV8();
791 void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
792 v8::Local<v8::Context> context, void* priv) {
793 v8::Isolate* isolate = context->GetIsolate();
794 mate::Dictionary dict(isolate, exports);
795 dict.Set("Session", Session::GetConstructor(isolate)->GetFunction());
796 dict.Set("Cookies", Cookies::GetConstructor(isolate)->GetFunction());
797 dict.SetMethod("fromPartition", &FromPartition);
802 NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize)