Index: ios/chrome/browser/ui/chrome_web_view_factory.mm |
diff --git a/ios/chrome/browser/ui/chrome_web_view_factory.mm b/ios/chrome/browser/ui/chrome_web_view_factory.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b1674ff8636cfd00611034ad29cc162400476dcd |
--- /dev/null |
+++ b/ios/chrome/browser/ui/chrome_web_view_factory.mm |
@@ -0,0 +1,163 @@ |
+// Copyright 2012 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. |
+ |
+#import "ios/chrome/browser/ui/chrome_web_view_factory.h" |
+ |
+#include "base/base64.h" |
+#include "base/logging.h" |
+#include "base/mac/scoped_nsobject.h" |
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
+#include "ios/web/net/request_group_util.h" |
+#include "ios/web/net/request_tracker_impl.h" |
+#include "ios/web/public/web_thread.h" |
+#include "net/cookies/cookie_store.h" |
+#include "net/url_request/url_request_context.h" |
+#include "net/url_request/url_request_context_getter.h" |
+ |
+NSString* const kExternalUserAgent = @"UIWebViewForExternalContent"; |
+ |
+namespace ChromeWebView { |
+// Shared desktop user agent used to mimic Safari on a mac. |
+NSString* const kDesktopUserAgent = |
+ @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) " |
+ @"AppleWebKit/600.7.12 (KHTML, like Gecko) " |
+ @"Version/8.0.7 " |
+ @"Safari/600.7.12"; |
+ |
+NSString* const kExternalRequestGroupID = @"kExternalRequestGroupID"; |
+ |
+// Returns an absolute path where sharing service data is stored (such as |
+// cookies and server-bound certificates). |
+const base::FilePath GetExternalServicePath( |
+ ios::ChromeBrowserState* browser_state, |
+ IOSWebViewFactoryExternalService service) { |
+ const base::FilePath path = |
+ browser_state->GetOriginalChromeBrowserState()->GetStatePath(); |
+ switch (service) { |
+ case SSO_AUTHENTICATION: |
+ return path.Append("SSOAuthentication"); |
+ case NUM_SHARING_SERVICES: |
+ NOTREACHED(); |
+ return path.Append("ExternalUnknownService"); |
+ } |
+} |
+} // namespace ChromeWebView |
+ |
+namespace { |
+ios::ChromeBrowserState* g_external_browser_state = nullptr; |
+scoped_refptr<web::RequestTrackerImpl> g_request_tracker; |
+ |
+// Empty callback used by ClearCookiesOnIOThread below. |
+void DoNothing(int n) {} |
+ |
+// Clears the cookies. |
+void ClearCookiesOnIOThread(net::URLRequestContextGetter* context_getter, |
+ base::Time delete_begin, |
+ base::Time delete_end) { |
+ DCHECK(context_getter); |
+ DCHECK_CURRENTLY_ON(web::WebThread::IO); |
+ net::CookieStore* cookie_store = |
+ context_getter->GetURLRequestContext()->cookie_store(); |
+ cookie_store->DeleteAllCreatedBetweenAsync(delete_begin, delete_end, |
+ base::Bind(&DoNothing)); |
+} |
+ |
+// Registers |user_agent| as the user agent string to be used by the UIWebView |
+// instances that are created from now on. |
+void RegisterUserAgentForUIWebView(NSString* user_agent) { |
+ [[NSUserDefaults standardUserDefaults] registerDefaults:@{ |
+ @"UserAgent" : user_agent, |
+ }]; |
+} |
+ |
+} // namespace |
+ |
+@implementation ChromeWebViewFactory |
+ |
++ (void)setBrowserStateToUseForExternal:(ios::ChromeBrowserState*)browserState { |
+ g_external_browser_state = browserState; |
+} |
+ |
++ (void)externalSessionFinished { |
+ g_external_browser_state = nullptr; |
+ if (g_request_tracker.get()) |
+ g_request_tracker->Close(); |
+ g_request_tracker = nullptr; |
+} |
+ |
++ (net::URLRequestContextGetter*)requestContextForExternalService: |
+ (IOSWebViewFactoryExternalService)externalService { |
+ DCHECK(g_external_browser_state); |
+ const base::FilePath servicePath = |
+ [ChromeWebViewFactory partitionPathForExternalService:externalService]; |
+ return g_external_browser_state->CreateIsolatedRequestContext(servicePath); |
+} |
+ |
++ (base::FilePath)partitionPathForExternalService: |
+ (IOSWebViewFactoryExternalService)externalService { |
+ return ChromeWebView::GetExternalServicePath(g_external_browser_state, |
+ externalService); |
+} |
+ |
++ (ChromeBrowserStateIOData*)ioDataForExternalWebViews { |
+ DCHECK(g_external_browser_state); |
+ return g_external_browser_state->GetIOData(); |
+} |
+ |
++ (void)clearExternalCookies:(IOSWebViewFactoryExternalService)externalService |
+ browserState:(ios::ChromeBrowserState*)browserState |
+ fromTime:(base::Time)deleteBegin |
+ toTime:(base::Time)deleteEnd { |
+ const base::FilePath servicePath = |
+ ChromeWebView::GetExternalServicePath(browserState, externalService); |
+ scoped_refptr<net::URLRequestContextGetter> contextGetter = |
+ browserState->CreateIsolatedRequestContext(servicePath); |
+ [self clearCookiesForContextGetter:contextGetter |
+ fromTime:deleteBegin |
+ toTime:deleteEnd]; |
+} |
+ |
++ (void)clearCookiesForContextGetter: |
+ (scoped_refptr<net::URLRequestContextGetter>)contextGetter |
+ fromTime:(base::Time)deleteBegin |
+ toTime:(base::Time)deleteEnd { |
+ DCHECK(contextGetter.get()); |
+ web::WebThread::PostTask( |
+ web::WebThread::IO, FROM_HERE, |
+ base::Bind(&ClearCookiesOnIOThread, base::RetainedRef(contextGetter), |
+ deleteBegin, deleteEnd)); |
+} |
+ |
++ (void)clearExternalCookies:(ios::ChromeBrowserState*)browserState |
+ fromTime:(base::Time)deleteBegin |
+ toTime:(base::Time)deleteEnd { |
+ for (unsigned int i = 0; i < NUM_SHARING_SERVICES; ++i) { |
+ [ChromeWebViewFactory |
+ clearExternalCookies:static_cast<IOSWebViewFactoryExternalService>(i) |
+ browserState:browserState |
+ fromTime:deleteBegin |
+ toTime:deleteEnd]; |
+ } |
+} |
+ |
+#pragma mark - |
+#pragma mark ChromeWebViewFactory |
++ (UIWebView*)newExternalWebView: |
+ (IOSWebViewFactoryExternalService)externalService { |
+ // All UIWebView's created for sharing share the same user agent, as there is |
+ // no need for them to be differentiated and this choice ensures that only |
+ // one request tracker is created on a per-sharing-session basis. |
+ NSString* userAgent = web::AddRequestGroupIDToUserAgent( |
+ kExternalUserAgent, ChromeWebView::kExternalRequestGroupID); |
+ RegisterUserAgentForUIWebView(userAgent); |
+ if (!g_request_tracker.get()) { |
+ DCHECK(g_external_browser_state); |
+ g_request_tracker = web::RequestTrackerImpl::CreateTrackerForRequestGroupID( |
+ ChromeWebView::kExternalRequestGroupID, g_external_browser_state, |
+ [self requestContextForExternalService:externalService], nil); |
+ } |
+ return [[UIWebView alloc] initWithFrame:CGRectZero]; |
+} |
+ |
+@end |