summaryrefslogtreecommitdiffstats
path: root/ios/crnet
diff options
context:
space:
mode:
authorellyjones <ellyjones@chromium.org>2015-05-21 11:12:54 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-21 18:13:31 +0000
commita7ce8df915247cafcd8a0d27090c15c293b4fc51 (patch)
tree2401a19910068bc5c33c3738c611177f2a4c474d /ios/crnet
parent01edd9afad2afea360828875c2225d01b198bb88 (diff)
downloadchromium_src-a7ce8df915247cafcd8a0d27090c15c293b4fc51.zip
chromium_src-a7ce8df915247cafcd8a0d27090c15c293b4fc51.tar.gz
chromium_src-a7ce8df915247cafcd8a0d27090c15c293b4fc51.tar.bz2
ios: add CrNet
This code is copied directly from the downstream iOS repo, except for the changes to ios/ios.gyp. BUG=483209 Review URL: https://codereview.chromium.org/1125293004 Cr-Commit-Position: refs/heads/master@{#330952}
Diffstat (limited to 'ios/crnet')
-rw-r--r--ios/crnet/CrNet.h132
-rw-r--r--ios/crnet/CrNet.mm132
-rw-r--r--ios/crnet/DEPS8
-rw-r--r--ios/crnet/OWNERS3
-rw-r--r--ios/crnet/Resources/Localization/am.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ar.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/bg.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/bn.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ca.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/cs.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/da.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/de.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/el.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/en-GB.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/en.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/es-419.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/es.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/et.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/fa.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/fi.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/fil.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/fr.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/gu.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/he.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/hi.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/hr.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/hu.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/id.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/it.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ja.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/kn.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ko.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/lt.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/lv.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ml.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/mr.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ms.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/nb.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/nl.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/pl.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/pt-BR.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/pt-PT.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/pt.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ro.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ru.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/sk.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/sl.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/sr.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/sv.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/sw.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/ta.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/te.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/th.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/tr.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/uk.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/vi.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/zh-Hans.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/zh-Hant.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/Localization/zh.lproj/Localizable.strings2
-rw-r--r--ios/crnet/Resources/README9
-rwxr-xr-xios/crnet/build.py322
-rw-r--r--ios/crnet/crnet.gyp119
-rw-r--r--ios/crnet/crnet_consumer/crnet-consumer-Info.plist45
-rw-r--r--ios/crnet/crnet_consumer/crnet_consumer.gyp62
-rw-r--r--ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h20
-rw-r--r--ios/crnet/crnet_consumer/crnet_consumer_app_delegate.mm72
-rw-r--r--ios/crnet/crnet_consumer/crnet_consumer_view_controller.h14
-rw-r--r--ios/crnet/crnet_consumer/crnet_consumer_view_controller.m46
-rw-r--r--ios/crnet/crnet_consumer/main.m15
-rw-r--r--ios/crnet/crnet_empty_for_link.cc3
-rw-r--r--ios/crnet/crnet_environment.h153
-rw-r--r--ios/crnet/crnet_environment.mm464
-rw-r--r--ios/crnet/crnet_net_log.cc46
-rw-r--r--ios/crnet/crnet_net_log.h51
-rw-r--r--ios/crnet/crnet_pack.gyp65
75 files changed, 1891 insertions, 0 deletions
diff --git a/ios/crnet/CrNet.h b/ios/crnet/CrNet.h
new file mode 100644
index 0000000..d516ac0
--- /dev/null
+++ b/ios/crnet/CrNet.h
@@ -0,0 +1,132 @@
+// Copyright 2014 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 <Foundation/Foundation.h>
+
+// A block, that takes a request, and returns YES if the request should
+// be handled.
+typedef BOOL(^RequestFilterBlock)(NSURLRequest *request);
+
+
+// A callback, called when the clearCache message has completed. The |errorCode|
+// is a network stack error code indicating whether the clear request succeeded
+// or not. Even if the request failed, the cache may have been cleared anyway,
+// or it may not have; it is not useful to retry a failing cache-clear attempt.
+// The only real use of |errorCode| is for error reporting and statistics
+// gathering.
+typedef void(^ClearCacheCallback)(int errorCode);
+
+// Interface for installing CrNet.
+@interface CrNet : NSObject
+
+// Sets whether SPDY should be supported by CrNet. This method only has any
+// effect before |install| is called.
++ (void)setSpdyEnabled:(BOOL)spdyEnabled;
+
+// Sets whether QUIC should be supported by CrNet. This method only has any
+// effect before |install| is called.
++ (void)setQuicEnabled:(BOOL)quicEnabled;
+
+// Set the alternate protocol threshold. Servers announce alternate protocols
+// with a probability value; any alternate protocol whose probability value is
+// greater than this value will be used, so |alternateProtocolThreshold| == 0
+// implies any announced alternate protocol will be used, and
+// |alternateProtocolThreshold| == 1 implies no alternate protocol will ever be
+// used. Note that individual alternate protocols must also be individually
+// enabled to be considered; currently the only alternate protocol is QUIC (SPDY
+// is not controlled by this mechanism).
+//
+// For example, imagine your service has two frontends a.service.com and
+// b.service.com, and you would like to divide your users into three classes:
+// Users who use QUIC for both a and b
+// Users who use QUIC for a but not b
+// Users who use QUIC for neither a nor b
+// You can achieve that effect with:
+// a.service.com advertises QUIC with p=0.67
+// b.service.com advertises QUIC with p=0.33
+// alternateProtocolThreshold set to a uniform random number in [0,1]
+// Now equal proportions of users will fall into the three experimental groups.
+//
+// The default for this value is 1.0, i.e. all alternate protocols disabled.
++ (void)setAlternateProtocolThreshold:(double)alternateProtocolThreshold;
+
+// |userAgent| is expected to be of the form Product/Version.
+// Example: Foo/3.0.0.0
+//
+// This method only has any effect before |install| is called.
++ (void)setPartialUserAgent:(NSString *)userAgent;
+
+// Set the block used to determine whether or not CrNet should handle the
+// request. If this is not set, CrNet will handle all requests.
+// Must not be called while requests are in progress. This method can be called
+// either before or after |install|.
++ (void)setRequestFilterBlock:(RequestFilterBlock)block;
+
+// Installs CrNet. Once installed, CrNet intercepts and handles all
+// NSURLConnection and NSURLRequests issued by the app, including UIWebView page
+// loads.
++ (void)install;
+
+// Installs CrNet into an NSURLSession, passed in by the caller. Note that this
+// NSURLSession will share settings with the sharedSession, which the |install|
+// method installs CrNet into. This method must be called after |install|.
++ (void)installIntoSessionConfiguration:(NSURLSessionConfiguration*)config;
+
+// Installs CrNet. This function is a deprecated shortcut for:
+// [CrNet setPartialUserAgent:userAgent];
+// [CrNet install];
+// See the documentation for |setPartialUserAgent| for details about the
+// |userAgent| argument.
++ (void)installWithPartialUserAgent:(NSString *)userAgent
+ __attribute__((deprecated));
+
+// Installs CrNet. This function is a deprecated shortcut for:
+// [CrNet setPartialUserAgent:userAgent];
+// [CrNet install];
+// The |enableDataReductionProxy| argument is ignored since data reduction proxy
+// support is currently missing from CrNet. See |setPartialUserAgent| for
+// details about the |userAgent| argument.
++ (void)installWithPartialUserAgent:(NSString *)userAgent
+ enableDataReductionProxy:(BOOL)enableDataReductionProxy
+ __attribute__((deprecated));
+
+// Installs CrNet. This function is a deprecated shortcut for:
+// [CrNet setPartialUserAgent:userAgent];
+// [CrNet setRequestFilterBlock:block];
+// [CrNet install];
+// See |setPartialUserAgent| and |setRequestFilterBlock| for details about the
+// |userAgent| and |requestFilterBlock| arguments respectively.
++ (void)installWithPartialUserAgent:(NSString *)userAgent
+ withRequestFilterBlock:(RequestFilterBlock)requestFilterBlock
+ __attribute__((deprecated));
+
+// Starts net-internals logging to a file named |fileName| in the application
+// temporary directory. |fileName| must not be empty. Log level is determined
+// by |logBytes| - if YES then LOG_ALL otherwise LOG_ALL_BUT_BYTES. If the file
+// exists it is truncated before starting. If actively logging the call is
+// ignored.
++ (void)startNetLogToFile:(NSString *)fileName logBytes:(BOOL)logBytes;
+
+// Stop net-internals logging and flush file to disk. If a logging session is
+// not in progress this call is ignored.
++ (void)stopNetLog;
+
+// Closes all current SPDY sessions. Do not do this unless you know what
+// you're doing.
+// TODO(alokm): This is a hack. Remove it later.
++ (void)closeAllSpdySessions;
+
+// "Uninstalls" CrNet. This means that CrNet will stop intercepting requests.
+// However, it won't tear down all of the CrNet environment.
++ (void)uninstall;
+
+// Returns the full user-agent that the stack uses.
+// This is the exact string servers will see.
++ (NSString *)userAgent;
+
+// Clears CrNet's http cache. The supplied callback, if not nil, is run on an
+// unspecified thread.
++ (void)clearCacheWithCompletionCallback:(ClearCacheCallback)completionBlock;
+
+@end
diff --git a/ios/crnet/CrNet.mm b/ios/crnet/CrNet.mm
new file mode 100644
index 0000000..9ea2dd9
--- /dev/null
+++ b/ios/crnet/CrNet.mm
@@ -0,0 +1,132 @@
+// Copyright 2014 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/crnet/CrNet.h"
+
+#include "base/logging.h"
+#import "ios/net/crn_http_protocol_handler.h"
+#import "ios/crnet/crnet_environment.h"
+
+static CrNetEnvironment* g_chrome_net = NULL;
+
+static BOOL g_spdy_enabled = YES;
+static BOOL g_quic_enabled = NO;
+static NSString *g_user_agent = nil;
+static double g_alternate_protocol_threshold = 1.0;
+static RequestFilterBlock g_request_filter_block = nil;
+
+@implementation CrNet
+
++ (void)setSpdyEnabled:(BOOL)spdyEnabled {
+ g_spdy_enabled = spdyEnabled;
+}
+
++ (void)setQuicEnabled:(BOOL)quicEnabled {
+ g_quic_enabled = quicEnabled;
+}
+
++ (void)setPartialUserAgent:(NSString *)userAgent {
+ g_user_agent = userAgent;
+}
+
++ (void)setAlternateProtocolThreshold:(double)alternateProtocolThreshold {
+ g_alternate_protocol_threshold = alternateProtocolThreshold;
+}
+
++ (void)installInternal {
+ CrNetEnvironment::Initialize();
+ std::string partial_user_agent =
+ [g_user_agent cStringUsingEncoding:NSASCIIStringEncoding];
+ g_chrome_net = new CrNetEnvironment(partial_user_agent);
+
+ g_chrome_net->set_spdy_enabled(g_spdy_enabled);
+ g_chrome_net->set_quic_enabled(g_quic_enabled);
+ g_chrome_net->set_alternate_protocol_threshold(
+ g_alternate_protocol_threshold);
+
+ g_chrome_net->Install();
+ g_chrome_net->SetHTTPProtocolHandlerRegistered(true);
+ g_chrome_net->SetRequestFilterBlock(g_request_filter_block);
+}
+
++ (void)install {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ [self installInternal];
+ });
+}
+
++ (void)installIntoSessionConfiguration:(NSURLSessionConfiguration*)config {
+ g_chrome_net->InstallIntoSessionConfiguration(config);
+}
+
++ (void)installWithPartialUserAgent:(NSString *)partialUserAgent {
+ [self setPartialUserAgent:partialUserAgent];
+ [self install];
+}
+
++ (void)installWithPartialUserAgent:(NSString *)partialUserAgent
+ enableDataReductionProxy:(BOOL)enableDataReductionProxy {
+ LOG(ERROR) << "enableDataReductionProxy is no longer respected. The "
+ << "functionality has been removed from CrNet.";
+
+ [self setPartialUserAgent:partialUserAgent];
+ [self install];
+}
+
++ (void)installWithPartialUserAgent:(NSString *)partialUserAgent
+ withRequestFilterBlock:(RequestFilterBlock)requestFilterBlock {
+ [self setPartialUserAgent:partialUserAgent];
+ [self setRequestFilterBlock:requestFilterBlock];
+ [self install];
+}
+
++ (void)setRequestFilterBlock:(RequestFilterBlock)block {
+ if (g_chrome_net)
+ g_chrome_net->SetRequestFilterBlock(block);
+ else
+ g_request_filter_block = block;
+}
+
++ (void)uninstall {
+ if (g_chrome_net) {
+ g_chrome_net->SetHTTPProtocolHandlerRegistered(false);
+ }
+}
+
++ (void)startNetLogToFile:(NSString *)fileName logBytes:(BOOL)logBytes {
+ if (g_chrome_net && [fileName length]) {
+ g_chrome_net->StartNetLog([fileName UTF8String], logBytes);
+ }
+}
+
++ (void)stopNetLog {
+ if (g_chrome_net) {
+ return g_chrome_net->StopNetLog();
+ }
+}
+
++ (NSString *)userAgent {
+ if (!g_chrome_net) {
+ return nil;
+ }
+
+ std::string user_agent = g_chrome_net->user_agent();
+ return [NSString stringWithCString:user_agent.c_str()
+ encoding:[NSString defaultCStringEncoding]];
+}
+
++ (void)closeAllSpdySessions {
+ if (g_chrome_net) {
+ return g_chrome_net->CloseAllSpdySessions();
+ }
+}
+
++ (void)clearCacheWithCompletionCallback:(ClearCacheCallback)clearCacheCallback {
+ if (g_chrome_net) {
+ g_chrome_net->ClearCache(clearCacheCallback);
+ }
+}
+
+@end
diff --git a/ios/crnet/DEPS b/ios/crnet/DEPS
new file mode 100644
index 0000000..df845d4
--- /dev/null
+++ b/ios/crnet/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ "+components/webp_transcode",
+ "+crypto/nss_util.h",
+ "+ios/crnet",
+ "+ios/net",
+ "+ios/web/public/user_agent.h",
+ "+net"
+]
diff --git a/ios/crnet/OWNERS b/ios/crnet/OWNERS
new file mode 100644
index 0000000..0bf94e5
--- /dev/null
+++ b/ios/crnet/OWNERS
@@ -0,0 +1,3 @@
+droger@chromium.org
+ellyjones@chromium.org
+mef@chromium.org
diff --git a/ios/crnet/Resources/Localization/am.lproj/Localizable.strings b/ios/crnet/Resources/Localization/am.lproj/Localizable.strings
new file mode 100644
index 0000000..ba55b06
--- /dev/null
+++ b/ios/crnet/Resources/Localization/am.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "am,en-GB,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ar.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ar.lproj/Localizable.strings
new file mode 100644
index 0000000..dcd3304
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ar.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ar,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/bg.lproj/Localizable.strings b/ios/crnet/Resources/Localization/bg.lproj/Localizable.strings
new file mode 100644
index 0000000..407c27b
--- /dev/null
+++ b/ios/crnet/Resources/Localization/bg.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "bg-BG,bg"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/bn.lproj/Localizable.strings b/ios/crnet/Resources/Localization/bn.lproj/Localizable.strings
new file mode 100644
index 0000000..08a6464
--- /dev/null
+++ b/ios/crnet/Resources/Localization/bn.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "bn-IN,bn,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ca.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ca.lproj/Localizable.strings
new file mode 100644
index 0000000..bec5e21
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ca.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ca-ES,ca"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/cs.lproj/Localizable.strings b/ios/crnet/Resources/Localization/cs.lproj/Localizable.strings
new file mode 100644
index 0000000..665a4e3
--- /dev/null
+++ b/ios/crnet/Resources/Localization/cs.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "cs-CZ,cs"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/da.lproj/Localizable.strings b/ios/crnet/Resources/Localization/da.lproj/Localizable.strings
new file mode 100644
index 0000000..428e5f7
--- /dev/null
+++ b/ios/crnet/Resources/Localization/da.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "da-DK,da,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/de.lproj/Localizable.strings b/ios/crnet/Resources/Localization/de.lproj/Localizable.strings
new file mode 100644
index 0000000..ca69ecb
--- /dev/null
+++ b/ios/crnet/Resources/Localization/de.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "de-DE,de,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/el.lproj/Localizable.strings b/ios/crnet/Resources/Localization/el.lproj/Localizable.strings
new file mode 100644
index 0000000..450fd28
--- /dev/null
+++ b/ios/crnet/Resources/Localization/el.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "el-GR,el"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/en-GB.lproj/Localizable.strings b/ios/crnet/Resources/Localization/en-GB.lproj/Localizable.strings
new file mode 100644
index 0000000..790ff2c
--- /dev/null
+++ b/ios/crnet/Resources/Localization/en-GB.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "en-GB,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/en.lproj/Localizable.strings b/ios/crnet/Resources/Localization/en.lproj/Localizable.strings
new file mode 100644
index 0000000..b379815
--- /dev/null
+++ b/ios/crnet/Resources/Localization/en.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. DO NOT TRANSLATE. */
+"IDS_ACCEPT_LANGUAGES" = "en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/es-419.lproj/Localizable.strings b/ios/crnet/Resources/Localization/es-419.lproj/Localizable.strings
new file mode 100644
index 0000000..347bc57
--- /dev/null
+++ b/ios/crnet/Resources/Localization/es-419.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "es-419,es"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/es.lproj/Localizable.strings b/ios/crnet/Resources/Localization/es.lproj/Localizable.strings
new file mode 100644
index 0000000..1ed553b
--- /dev/null
+++ b/ios/crnet/Resources/Localization/es.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "es-ES,es"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/et.lproj/Localizable.strings b/ios/crnet/Resources/Localization/et.lproj/Localizable.strings
new file mode 100644
index 0000000..6260779
--- /dev/null
+++ b/ios/crnet/Resources/Localization/et.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "et-EE,et,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/fa.lproj/Localizable.strings b/ios/crnet/Resources/Localization/fa.lproj/Localizable.strings
new file mode 100644
index 0000000..69d343f
--- /dev/null
+++ b/ios/crnet/Resources/Localization/fa.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "fa,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/fi.lproj/Localizable.strings b/ios/crnet/Resources/Localization/fi.lproj/Localizable.strings
new file mode 100644
index 0000000..3c35a79
--- /dev/null
+++ b/ios/crnet/Resources/Localization/fi.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "fi-FI,fi,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/fil.lproj/Localizable.strings b/ios/crnet/Resources/Localization/fil.lproj/Localizable.strings
new file mode 100644
index 0000000..6a90add
--- /dev/null
+++ b/ios/crnet/Resources/Localization/fil.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "fil,fil-PH,tl,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/fr.lproj/Localizable.strings b/ios/crnet/Resources/Localization/fr.lproj/Localizable.strings
new file mode 100644
index 0000000..1cf4700
--- /dev/null
+++ b/ios/crnet/Resources/Localization/fr.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "fr-FR,fr,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/gu.lproj/Localizable.strings b/ios/crnet/Resources/Localization/gu.lproj/Localizable.strings
new file mode 100644
index 0000000..b8439e8
--- /dev/null
+++ b/ios/crnet/Resources/Localization/gu.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "gu-IN,gu,hi-IN,hi,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/he.lproj/Localizable.strings b/ios/crnet/Resources/Localization/he.lproj/Localizable.strings
new file mode 100644
index 0000000..23c6a0d
--- /dev/null
+++ b/ios/crnet/Resources/Localization/he.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "he-IL,he,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/hi.lproj/Localizable.strings b/ios/crnet/Resources/Localization/hi.lproj/Localizable.strings
new file mode 100644
index 0000000..28466ff
--- /dev/null
+++ b/ios/crnet/Resources/Localization/hi.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "hi-IN,hi,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/hr.lproj/Localizable.strings b/ios/crnet/Resources/Localization/hr.lproj/Localizable.strings
new file mode 100644
index 0000000..db8c1e6
--- /dev/null
+++ b/ios/crnet/Resources/Localization/hr.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "hr-HR,hr,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/hu.lproj/Localizable.strings b/ios/crnet/Resources/Localization/hu.lproj/Localizable.strings
new file mode 100644
index 0000000..3b86667
--- /dev/null
+++ b/ios/crnet/Resources/Localization/hu.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "hu-HU,hu,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/id.lproj/Localizable.strings b/ios/crnet/Resources/Localization/id.lproj/Localizable.strings
new file mode 100644
index 0000000..7af26ce
--- /dev/null
+++ b/ios/crnet/Resources/Localization/id.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "id-ID,id,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/it.lproj/Localizable.strings b/ios/crnet/Resources/Localization/it.lproj/Localizable.strings
new file mode 100644
index 0000000..fd855c0
--- /dev/null
+++ b/ios/crnet/Resources/Localization/it.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "it-IT,it,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ja.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ja.lproj/Localizable.strings
new file mode 100644
index 0000000..6a1779e
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ja.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ja,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/kn.lproj/Localizable.strings b/ios/crnet/Resources/Localization/kn.lproj/Localizable.strings
new file mode 100644
index 0000000..167d19c
--- /dev/null
+++ b/ios/crnet/Resources/Localization/kn.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "kn-IN,kn,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ko.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ko.lproj/Localizable.strings
new file mode 100644
index 0000000..c5e8d4f2
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ko.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ko-KR,ko,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/lt.lproj/Localizable.strings b/ios/crnet/Resources/Localization/lt.lproj/Localizable.strings
new file mode 100644
index 0000000..857146a
--- /dev/null
+++ b/ios/crnet/Resources/Localization/lt.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "lt,en-US,en,ru,pl"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/lv.lproj/Localizable.strings b/ios/crnet/Resources/Localization/lv.lproj/Localizable.strings
new file mode 100644
index 0000000..1efd5e8
--- /dev/null
+++ b/ios/crnet/Resources/Localization/lv.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "lv-LV,lv,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ml.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ml.lproj/Localizable.strings
new file mode 100644
index 0000000..4382668
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ml.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ml-IN,ml,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/mr.lproj/Localizable.strings b/ios/crnet/Resources/Localization/mr.lproj/Localizable.strings
new file mode 100644
index 0000000..fbf98d7
--- /dev/null
+++ b/ios/crnet/Resources/Localization/mr.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "mr-IN,mr,hi-IN,hi,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ms.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ms.lproj/Localizable.strings
new file mode 100644
index 0000000..a8b6d58
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ms.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. DO NOT TRANSLATE. */
+"IDS_ACCEPT_LANGUAGES" = "ms,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/nb.lproj/Localizable.strings b/ios/crnet/Resources/Localization/nb.lproj/Localizable.strings
new file mode 100644
index 0000000..4e3271b
--- /dev/null
+++ b/ios/crnet/Resources/Localization/nb.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "nb-NO,nb,no,nn,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/nl.lproj/Localizable.strings b/ios/crnet/Resources/Localization/nl.lproj/Localizable.strings
new file mode 100644
index 0000000..dca54fe
--- /dev/null
+++ b/ios/crnet/Resources/Localization/nl.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "nl-NL,nl,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/pl.lproj/Localizable.strings b/ios/crnet/Resources/Localization/pl.lproj/Localizable.strings
new file mode 100644
index 0000000..f9ea84e
--- /dev/null
+++ b/ios/crnet/Resources/Localization/pl.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "pl-PL,pl,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/pt-BR.lproj/Localizable.strings b/ios/crnet/Resources/Localization/pt-BR.lproj/Localizable.strings
new file mode 100644
index 0000000..8b04250
--- /dev/null
+++ b/ios/crnet/Resources/Localization/pt-BR.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "pt-BR,pt,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/pt-PT.lproj/Localizable.strings b/ios/crnet/Resources/Localization/pt-PT.lproj/Localizable.strings
new file mode 100644
index 0000000..2e0d86c
--- /dev/null
+++ b/ios/crnet/Resources/Localization/pt-PT.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "pt-PT,pt,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/pt.lproj/Localizable.strings b/ios/crnet/Resources/Localization/pt.lproj/Localizable.strings
new file mode 100644
index 0000000..fb3c1eb
--- /dev/null
+++ b/ios/crnet/Resources/Localization/pt.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. DO NOT TRANSLATE. */
+"IDS_ACCEPT_LANGUAGES" = "pt-PT,pt,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ro.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ro.lproj/Localizable.strings
new file mode 100644
index 0000000..7428ce5
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ro.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ro-RO,ro,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ru.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ru.lproj/Localizable.strings
new file mode 100644
index 0000000..2d56449
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ru.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ru-RU,ru,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/sk.lproj/Localizable.strings b/ios/crnet/Resources/Localization/sk.lproj/Localizable.strings
new file mode 100644
index 0000000..5dff353
--- /dev/null
+++ b/ios/crnet/Resources/Localization/sk.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "sk-SK,sk,cs,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/sl.lproj/Localizable.strings b/ios/crnet/Resources/Localization/sl.lproj/Localizable.strings
new file mode 100644
index 0000000..811ab06
--- /dev/null
+++ b/ios/crnet/Resources/Localization/sl.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "sl-SI,sl,en-GB,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/sr.lproj/Localizable.strings b/ios/crnet/Resources/Localization/sr.lproj/Localizable.strings
new file mode 100644
index 0000000..ff18f14
--- /dev/null
+++ b/ios/crnet/Resources/Localization/sr.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "sr-RS,sr,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/sv.lproj/Localizable.strings b/ios/crnet/Resources/Localization/sv.lproj/Localizable.strings
new file mode 100644
index 0000000..3daf55f
--- /dev/null
+++ b/ios/crnet/Resources/Localization/sv.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "sv-SE,sv,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/sw.lproj/Localizable.strings b/ios/crnet/Resources/Localization/sw.lproj/Localizable.strings
new file mode 100644
index 0000000..ef6b492
--- /dev/null
+++ b/ios/crnet/Resources/Localization/sw.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "sw,en-GB,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/ta.lproj/Localizable.strings b/ios/crnet/Resources/Localization/ta.lproj/Localizable.strings
new file mode 100644
index 0000000..2bde014
--- /dev/null
+++ b/ios/crnet/Resources/Localization/ta.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "ta-IN,ta,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/te.lproj/Localizable.strings b/ios/crnet/Resources/Localization/te.lproj/Localizable.strings
new file mode 100644
index 0000000..38fb4a4
--- /dev/null
+++ b/ios/crnet/Resources/Localization/te.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "te-IN,te,hi-IN,hi,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/th.lproj/Localizable.strings b/ios/crnet/Resources/Localization/th.lproj/Localizable.strings
new file mode 100644
index 0000000..464b637
--- /dev/null
+++ b/ios/crnet/Resources/Localization/th.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "th-TH,th"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/tr.lproj/Localizable.strings b/ios/crnet/Resources/Localization/tr.lproj/Localizable.strings
new file mode 100644
index 0000000..b5289e2
--- /dev/null
+++ b/ios/crnet/Resources/Localization/tr.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "tr-TR,tr,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/uk.lproj/Localizable.strings b/ios/crnet/Resources/Localization/uk.lproj/Localizable.strings
new file mode 100644
index 0000000..1fe6381
--- /dev/null
+++ b/ios/crnet/Resources/Localization/uk.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "uk-UA,uk,ru,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/vi.lproj/Localizable.strings b/ios/crnet/Resources/Localization/vi.lproj/Localizable.strings
new file mode 100644
index 0000000..082f76d
--- /dev/null
+++ b/ios/crnet/Resources/Localization/vi.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. */
+"IDS_ACCEPT_LANGUAGES" = "vi-VN,vi,fr-FR,fr,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/zh-Hans.lproj/Localizable.strings b/ios/crnet/Resources/Localization/zh-Hans.lproj/Localizable.strings
new file mode 100644
index 0000000..0a14ff7
--- /dev/null
+++ b/ios/crnet/Resources/Localization/zh-Hans.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. DO NOT TRANSLATE. */
+"IDS_ACCEPT_LANGUAGES" = "zh-CN,zh"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/zh-Hant.lproj/Localizable.strings b/ios/crnet/Resources/Localization/zh-Hant.lproj/Localizable.strings
new file mode 100644
index 0000000..fadad918
--- /dev/null
+++ b/ios/crnet/Resources/Localization/zh-Hant.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. DO NOT TRANSLATE. */
+"IDS_ACCEPT_LANGUAGES" = "zh-TW,zh,en-US,en"; \ No newline at end of file
diff --git a/ios/crnet/Resources/Localization/zh.lproj/Localizable.strings b/ios/crnet/Resources/Localization/zh.lproj/Localizable.strings
new file mode 100644
index 0000000..0a14ff7
--- /dev/null
+++ b/ios/crnet/Resources/Localization/zh.lproj/Localizable.strings
@@ -0,0 +1,2 @@
+/* These values are copied from Chrome's .xtb files, this is so the same values are used in the |Accept-Language| header. Key name matches Chrome's. DO NOT TRANSLATE. */
+"IDS_ACCEPT_LANGUAGES" = "zh-CN,zh"; \ No newline at end of file
diff --git a/ios/crnet/Resources/README b/ios/crnet/Resources/README
new file mode 100644
index 0000000..681b853
--- /dev/null
+++ b/ios/crnet/Resources/README
@@ -0,0 +1,9 @@
+This localization directory contains language strings taken from Chrome. These
+language strings are taken from Chrome's *.xtb files with the key
+IDS_ACCEPT_LANGUAGES.
+
+DO NOT translate strings with a IDS_ACCEPT_LANGUAGES key from these .strings
+files in the translation console.
+
+On top of Chrome's language list, the following languages were added:
+"pt" "ms" "zh"
diff --git a/ios/crnet/build.py b/ios/crnet/build.py
new file mode 100755
index 0000000..12874bf
--- /dev/null
+++ b/ios/crnet/build.py
@@ -0,0 +1,322 @@
+#!/usr/bin/env python
+# Copyright 2014 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 argparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+
+
+SUPPORTED_ARCHES = ['i386', 'x86_64', 'armv7', 'arm64']
+
+
+class SubprocessError(Exception):
+ pass
+
+
+class ConfigurationError(Exception):
+ pass
+
+
+def out_directories(root):
+ """Returns all output directories containing crnet objects under root.
+
+ Currently this list is just hardcoded.
+
+ Args:
+ root: prefix for output directories.
+ """
+ out_dirs = ['Release-iphoneos', 'Release-iphonesimulator']
+ return map(lambda x: os.path.join(root, 'out', x), out_dirs)
+
+
+def check_command(command):
+ """Runs a command, raising an exception if it fails.
+
+ If the command returns a nonzero exit code, prints any data the command
+ emitted on stdout and stderr.
+
+ Args:
+ command: command to execute, in argv format.
+
+ Raises:
+ SubprocessError: the specified command returned nonzero exit status.
+ """
+ p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode == 0:
+ return
+ message = 'Command failed: {0} (status {1})'.format(command, p.returncode)
+ print message
+ print 'stdout: {0}'.format(stdout)
+ print 'stderr: {0}'.format(stderr)
+ raise SubprocessError(message)
+
+
+def file_contains_string(path, string):
+ """Returns whether the file named by path contains string.
+
+ Args:
+ path: path of the file to search.
+ string: string to search the file for.
+
+ Returns:
+ True if file contains string, False otherwise.
+ """
+ with open(path, 'r') as f:
+ for line in f:
+ if string in line:
+ return True
+ return False
+
+
+def is_object_filename(filename):
+ """Returns whether the given filename names an object file.
+
+ Args:
+ filename: filename to inspect.
+
+ Returns:
+ True if filename names an object file, false otherwise.
+ """
+ (_, ext) = os.path.splitext(filename)
+ return ext in ('.a', '.o')
+
+
+class Step(object):
+ """Represents a single step of the crnet build process.
+
+ This parent class exists only to define the interface Steps present and keep
+ track of elapsed time for each step. Subclasses of Step should override the
+ run() method, which is called internally by start().
+
+ Attributes:
+ name: human-readable name of this step, used in debug output.
+ started_at: seconds since epoch that this step started running at.
+ """
+ def __init__(self, name):
+ self._name = name
+ self._started_at = None
+ self._ended_at = None
+
+ @property
+ def name(self):
+ return self._name
+
+ def start(self):
+ """Start running this step.
+
+ This method keeps track of how long the run() method takes to run and emits
+ the elapsed time after run() returns.
+ """
+ self._started_at = time.time()
+ print '{0}: '.format(self._name),
+ sys.stdout.flush()
+ self._run()
+ self._ended_at = time.time()
+ print '{0:.2f}s'.format(self._ended_at - self._started_at)
+
+ def _run(self):
+ """Actually run this step.
+
+ Subclasses should override this method to implement their own step logic.
+ """
+ raise NotImplementedError
+
+
+class CleanStep(Step):
+ """Clean the build output directories.
+
+ This step deletes intermediates generated by the build process. Some of these
+ intermediates (crnet_consumer.app and crnet_resources.bundle) are directories,
+ which contain files ninja doesn't know and hence won't remove, so the run()
+ method here explicitly deletes those directories before running 'ninja -t
+ clean'.
+
+ Attributes:
+ dirs: list of output directories to clean.
+ """
+ def __init__(self, root):
+ super(CleanStep, self).__init__('clean')
+ self._dirs = out_directories(root)
+
+ def _run(self):
+ """Runs the clean step.
+
+ Deletes crnet_consumer.app and crnet_resources.bundle in each output
+ directory and runs 'ninja -t clean' in each output directory.
+ """
+ for d in self._dirs:
+ if os.path.exists(os.path.join(d, 'crnet_consumer.app')):
+ shutil.rmtree(os.path.join(d, 'crnet_consumer.app'))
+ if os.path.exists(os.path.join(d, 'crnet_resources.bundle')):
+ shutil.rmtree(os.path.join(d, 'crnet_resources.bundle'))
+ check_command(['ninja', '-C', d, '-t', 'clean'])
+
+
+class HooksStep(Step):
+ """Validates the gyp config and reruns gclient hooks.
+
+ Attributes:
+ root: directory to find gyp config under.
+ """
+ def __init__(self, root):
+ super(HooksStep, self).__init__('hooks')
+ self._root = root
+
+ def _run(self):
+ """Runs the hooks step.
+
+ Checks that root/build/common.gypi contains target_subarch = both in a crude
+ way, then calls 'gclient runhooks'. TODO(ellyjones): parse common.gypi in a
+ more robust way.
+
+ Raises:
+ ConfigurationError: if target_subarch != both
+ """
+ common_gypi = os.path.join(self._root, 'build', 'common.gypi')
+ if not file_contains_string(common_gypi, "'target_subarch%': 'both'"):
+ raise ConfigurationError('target_subarch must be both in {0}'.format(
+ common_gypi))
+ check_command(['gclient', 'runhooks'])
+
+
+class BuildStep(Step):
+ """Builds all the intermediate crnet binaries.
+
+ All the hard work of this step is done by ninja; this step just shells out to
+ ninja to build the crnet_pack target.
+
+ Attributes:
+ dirs: output directories to run ninja in.
+ """
+ def __init__(self, root):
+ super(BuildStep, self).__init__('build')
+ self._dirs = out_directories(root)
+
+ def _run(self):
+ """Runs the build step.
+
+ For each output directory, run ninja to build the crnet_pack target in that
+ directory.
+ """
+ for d in self._dirs:
+ check_command(['ninja', '-C', d, 'crnet_pack'])
+
+
+class PackageStep(Step):
+ """Packages the built object files for release.
+
+ The release format is a tarball, containing one gzipped tarball per
+ architecture and a manifest file, which lists metadata about the build.
+
+ Attributes:
+ outdirs: directories containing built object files.
+ workdir: temporary working directory. Deleted at end of the step.
+ archdir: temporary directory under workdir. Used for collecting per-arch
+ binaries.
+ proddir: temporary directory under workdir. Used for intermediate per-arch
+ tarballs.
+ """
+ def __init__(self, root, outfile):
+ super(PackageStep, self).__init__('package')
+ self._outdirs = out_directories(root)
+ self._outfile = outfile
+
+ def _run(self):
+ """Runs the package step.
+
+ Packages each architecture from |root| into an individual .tar.gz file, then
+ packages all the .tar.gz files into one .tar file, which is written to
+ |outfile|.
+ """
+ (workdir, archdir, proddir) = self.create_work_dirs()
+ for arch in SUPPORTED_ARCHES:
+ self.package_arch(archdir, proddir, arch)
+ self.package(proddir)
+ shutil.rmtree(workdir)
+
+ def create_work_dirs(self):
+ """Creates working directories and returns their paths."""
+ workdir = tempfile.mkdtemp()
+ archdir = os.path.join(workdir, 'arch')
+ proddir = os.path.join(workdir, 'prod')
+ os.mkdir(archdir)
+ os.mkdir(proddir)
+ return (workdir, archdir, proddir)
+
+ def object_files_for_arch(self, arch):
+ """Returns a list of object files for the given architecture.
+
+ Under each outdir d, per-arch files are stored in d/arch, and object files
+ for a given arch contain the arch's name as a substring.
+
+ Args:
+ arch: architecture name. Must be in SUPPORTED_ARCHES.
+
+ Returns:
+ List of full pathnames to object files in outdirs for the named arch.
+ """
+ arch_files = []
+ for d in self._outdirs:
+ files = os.listdir(os.path.join(d, 'arch'))
+ for f in filter(is_object_filename, files):
+ if arch in f:
+ arch_files.append(os.path.join(d, 'arch', f))
+ return arch_files
+
+ def package_arch(self, archdir, proddir, arch):
+ """Packages an individual architecture.
+
+ Copies all the object files for the specified arch into a working directory
+ under self.archdir, then tars them up into a gzipped tarball under
+ self.proddir.
+
+ Args:
+ archdir: directory to stage architecture files in.
+ proddir: directory to stage result tarballs in.
+ arch: architecture name to package. Must be in SUPPORTED_ARCHES.
+ """
+ arch_files = self.object_files_for_arch(arch)
+ os.mkdir(os.path.join(archdir, arch))
+ for f in arch_files:
+ shutil.copy(f, os.path.join(archdir, arch))
+ out_filename = os.path.join(proddir, '{0}.tar.gz'.format(arch))
+ check_command(['tar', '-C', archdir, '-czf', out_filename, arch])
+
+ def package(self, proddir):
+ """Final packaging step. Packages all the arch tarballs into one tarball."""
+ arch_tarballs = []
+ for a in SUPPORTED_ARCHES:
+ arch_tarballs.append('{0}.tar.gz'.format(a))
+ check_command(['tar', '-C', proddir, '-cf', self._outfile] +
+ arch_tarballs)
+
+
+def main():
+ step_classes = {
+ 'clean': lambda: CleanStep(args.rootdir),
+ 'hooks': lambda: HooksStep(args.rootdir),
+ 'build': lambda: BuildStep(args.rootdir),
+ 'package': lambda: PackageStep(args.rootdir, args.outfile)
+ }
+ parser = argparse.ArgumentParser(description='Build and package crnet.')
+ parser.add_argument('--outfile', dest='outfile', default='crnet.tar',
+ help='Output file to generate (default: crnet.tar)')
+ parser.add_argument('--rootdir', dest='rootdir', default='../..',
+ help='Root directory to build from (default: ../..)')
+ parser.add_argument('steps', metavar='step', nargs='*')
+ args = parser.parse_args()
+ step_names = args.steps or ['clean', 'hooks', 'build', 'package']
+ steps = [step_classes[x]() for x in step_names]
+ for step in steps:
+ step.start()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/ios/crnet/crnet.gyp b/ios/crnet/crnet.gyp
new file mode 100644
index 0000000..53358c2
--- /dev/null
+++ b/ios/crnet/crnet.gyp
@@ -0,0 +1,119 @@
+# Copyright 2014 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'crnet',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../../components/components.gyp:webp_transcode',
+ '../../ios/net/ios_net.gyp:ios_net',
+ '../../ios/web/ios_web.gyp:user_agent',
+ '../../net/net.gyp:net',
+ 'crnet_resources',
+ ],
+ 'mac_framework_headers': [
+ 'CrNet.h',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [ '.' ],
+ },
+ 'sources': [
+ # TODO(ellyjones): http://crbug.com/485144
+ '../../net/url_request/sdch_dictionary_fetcher.cc',
+ '../../net/url_request/sdch_dictionary_fetcher.h',
+ 'CrNet.h',
+ 'CrNet.mm',
+ 'crnet_environment.h',
+ 'crnet_environment.mm',
+ 'crnet_net_log.h',
+ 'crnet_net_log.cc',
+ ],
+ 'defines': [
+ # TODO(stuartmorgan): Revisit the way this is set, and the above is
+ # built, once the web/ layer is complete. Note that this setting doesn't
+ # propagate to any included targets.
+ 'CRNET=1',
+ ],
+ 'xcode_settings': {
+ 'DEAD_CODE_STRIPPING': 'YES',
+ },
+ },
+ {
+ # This bundle contains "Accept-Languages" header values for known locales.
+ # TODO(huey): These strings should be auto-generated from chrome's .xtb
+ # files, not hardcoded.
+ 'target_name': 'crnet_resources',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ 'mac_bundle_resources': [
+ 'Resources/Localization/am.lproj/Localizable.strings',
+ 'Resources/Localization/ar.lproj/Localizable.strings',
+ 'Resources/Localization/bg.lproj/Localizable.strings',
+ 'Resources/Localization/bn.lproj/Localizable.strings',
+ 'Resources/Localization/ca.lproj/Localizable.strings',
+ 'Resources/Localization/cs.lproj/Localizable.strings',
+ 'Resources/Localization/da.lproj/Localizable.strings',
+ 'Resources/Localization/de.lproj/Localizable.strings',
+ 'Resources/Localization/el.lproj/Localizable.strings',
+ 'Resources/Localization/en-GB.lproj/Localizable.strings',
+ 'Resources/Localization/en.lproj/Localizable.strings',
+ 'Resources/Localization/es-419.lproj/Localizable.strings',
+ 'Resources/Localization/es.lproj/Localizable.strings',
+ 'Resources/Localization/fa.lproj/Localizable.strings',
+ 'Resources/Localization/fi.lproj/Localizable.strings',
+ 'Resources/Localization/fil.lproj/Localizable.strings',
+ 'Resources/Localization/fr.lproj/Localizable.strings',
+ 'Resources/Localization/gu.lproj/Localizable.strings',
+ 'Resources/Localization/he.lproj/Localizable.strings',
+ 'Resources/Localization/hi.lproj/Localizable.strings',
+ 'Resources/Localization/hr.lproj/Localizable.strings',
+ 'Resources/Localization/hu.lproj/Localizable.strings',
+ 'Resources/Localization/id.lproj/Localizable.strings',
+ 'Resources/Localization/it.lproj/Localizable.strings',
+ 'Resources/Localization/ja.lproj/Localizable.strings',
+ 'Resources/Localization/kn.lproj/Localizable.strings',
+ 'Resources/Localization/ko.lproj/Localizable.strings',
+ 'Resources/Localization/lt.lproj/Localizable.strings',
+ 'Resources/Localization/lv.lproj/Localizable.strings',
+ 'Resources/Localization/ml.lproj/Localizable.strings',
+ 'Resources/Localization/mr.lproj/Localizable.strings',
+ 'Resources/Localization/ms.lproj/Localizable.strings',
+ 'Resources/Localization/nb.lproj/Localizable.strings',
+ 'Resources/Localization/nl.lproj/Localizable.strings',
+ 'Resources/Localization/pl.lproj/Localizable.strings',
+ 'Resources/Localization/pt-BR.lproj/Localizable.strings',
+ 'Resources/Localization/pt-PT.lproj/Localizable.strings',
+ 'Resources/Localization/pt.lproj/Localizable.strings',
+ 'Resources/Localization/ro.lproj/Localizable.strings',
+ 'Resources/Localization/ru.lproj/Localizable.strings',
+ 'Resources/Localization/sk.lproj/Localizable.strings',
+ 'Resources/Localization/sl.lproj/Localizable.strings',
+ 'Resources/Localization/sr.lproj/Localizable.strings',
+ 'Resources/Localization/sv.lproj/Localizable.strings',
+ 'Resources/Localization/sw.lproj/Localizable.strings',
+ 'Resources/Localization/ta.lproj/Localizable.strings',
+ 'Resources/Localization/te.lproj/Localizable.strings',
+ 'Resources/Localization/th.lproj/Localizable.strings',
+ 'Resources/Localization/tr.lproj/Localizable.strings',
+ 'Resources/Localization/uk.lproj/Localizable.strings',
+ 'Resources/Localization/vi.lproj/Localizable.strings',
+ 'Resources/Localization/zh-Hans.lproj/Localizable.strings',
+ 'Resources/Localization/zh-Hant.lproj/Localizable.strings',
+ 'Resources/Localization/zh.lproj/Localizable.strings',
+ ],
+ 'all_dependent_settings': {
+ 'link_settings': {
+ 'mac_bundle_resources': [
+ '>(PRODUCT_DIR)/crnet_resources.bundle',
+ ],
+ },
+ },
+ },
+ ],
+}
diff --git a/ios/crnet/crnet_consumer/crnet-consumer-Info.plist b/ios/crnet/crnet_consumer/crnet-consumer-Info.plist
new file mode 100644
index 0000000..57ee6ae
--- /dev/null
+++ b/ios/crnet/crnet_consumer/crnet-consumer-Info.plist
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>chromium.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/ios/crnet/crnet_consumer/crnet_consumer.gyp b/ios/crnet/crnet_consumer/crnet_consumer.gyp
new file mode 100644
index 0000000..e94d65a
--- /dev/null
+++ b/ios/crnet/crnet_consumer/crnet_consumer.gyp
@@ -0,0 +1,62 @@
+# Copyright 2014 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [],
+ 'conditions': [
+ # Our shared library hack only works with ninja; xcode cannot generate
+ # iOS build targets for dynamic libraries.
+ ['"<(GENERATOR)"=="ninja"', {
+ 'targets': [
+ {
+ 'target_name': 'crnet_consumer',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'dependencies': [
+ '../../../ios/crnet/crnet_pack.gyp:crnet_pack',
+ ],
+ 'sources': [
+ 'crnet_consumer_app_delegate.h',
+ 'crnet_consumer_app_delegate.mm',
+ 'crnet_consumer_view_controller.h',
+ 'crnet_consumer_view_controller.m',
+ 'main.m',
+ ],
+ 'mac_bundle_resources': [
+ 'crnet-consumer-Info.plist',
+ '../../../third_party/icu/source/data/in/icudtl.dat',
+ ],
+ 'include_dirs': [
+ '../../..',
+ '..',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '<(PRODUCT_DIR)/libcrnet_standalone.a',
+ '$(SDKROOT)/System/Library/Frameworks/CFNetwork.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreGraphics.framework',
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ '$(SDKROOT)/System/Library/Frameworks/MobileCoreServices.framework',
+ '$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
+ '$(SDKROOT)/System/Library/Frameworks/Security.framework',
+ '$(SDKROOT)/System/Library/Frameworks/SystemConfiguration.framework',
+ '$(SDKROOT)/usr/lib/libresolv.dylib',
+ '$(SDKROOT)/usr/lib/libsqlite3.dylib',
+ '$(SDKROOT)/usr/lib/libxml2.dylib',
+ ],
+ },
+ 'xcode_settings': {
+ 'CLANG_ENABLE_OBJC_ARC': 'YES',
+ 'DEAD_CODE_STRIPPING': 'YES',
+ 'INFOPLIST_FILE': 'crnet-consumer-Info.plist',
+ },
+ },
+ ],
+ }],
+ ],
+}
diff --git a/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h b/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h
new file mode 100644
index 0000000..7f819d0
--- /dev/null
+++ b/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.h
@@ -0,0 +1,20 @@
+// Copyright 2014 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.
+
+#ifndef CRNET_CONSUMER_APP_DELEGATE_
+#define CRNET_CONSUMER_APP_DELEGATE_
+
+#import <UIKit/UIKit.h>
+
+@class CrNetConsumerViewController;
+
+// The main app controller and UIApplicationDelegate.
+@interface CrNetConsumerAppDelegate : UIResponder <UIApplicationDelegate>
+
+@property(strong, nonatomic) UIWindow* window;
+@property(strong, nonatomic) CrNetConsumerViewController* viewController;
+
+@end
+
+#endif // CRNET_CONSUMER_APP_DELEGATE_
diff --git a/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.mm b/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.mm
new file mode 100644
index 0000000..a4b3587
--- /dev/null
+++ b/ios/crnet/crnet_consumer/crnet_consumer_app_delegate.mm
@@ -0,0 +1,72 @@
+// Copyright 2014 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 "crnet_consumer_app_delegate.h"
+
+#import "CrNet.h"
+#include "base/format_macros.h"
+#import "crnet_consumer_view_controller.h"
+
+@implementation CrNetConsumerAppDelegate {
+ NSUInteger _counter;
+}
+
+@synthesize window;
+@synthesize viewController;
+
+// Returns a file name to save net internals logging. This method suffixes
+// the ivar |_counter| to the file name so a new name can be obtained by
+// modifying that.
+- (NSString *)currentNetLogFileName {
+ return [NSString
+ stringWithFormat:@"crnet-consumer-net-log%" PRIuNS ".json", _counter];
+}
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [CrNet setPartialUserAgent:@"Dummy/1.0"];
+ [CrNet setQuicEnabled:YES];
+ // Always use QUIC if able.
+ [CrNet setAlternateProtocolThreshold:0.0];
+ [CrNet install];
+ [CrNet startNetLogToFile:[self currentNetLogFileName] logBytes:NO];
+
+ NSURLSessionConfiguration* config =
+ [NSURLSessionConfiguration ephemeralSessionConfiguration];
+ [CrNet installIntoSessionConfiguration:config];
+
+ // Just for fun, don't route chromium.org requests through CrNet.
+ //
+ // |chromiumPrefix| is declared outside the scope of the request block so that
+ // the block references something outside of its own scope, and cannot be
+ // declared as a global block. This makes sure the block is
+ // an __NSStackBlock__, and verifies the fix for http://crbug.com/436175 .
+ NSString *chromiumPrefix = @"www.chromium.org";
+ [CrNet setRequestFilterBlock:^BOOL (NSURLRequest *request) {
+ BOOL isChromiumSite = [[[request URL] host] hasPrefix:chromiumPrefix];
+ return !isChromiumSite;
+ }];
+
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ self.viewController =
+ [[CrNetConsumerViewController alloc] initWithNibName:nil bundle:nil];
+ self.window.rootViewController = self.viewController;
+ [self.window makeKeyAndVisible];
+
+ return YES;
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ [CrNet stopNetLog];
+ [CrNet clearCacheWithCompletionCallback:^(int error) {
+ NSLog(@"Cache cleared: %d\n", error);
+ }];
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ _counter++;
+ [CrNet startNetLogToFile:[self currentNetLogFileName] logBytes:NO];
+}
+
+@end
diff --git a/ios/crnet/crnet_consumer/crnet_consumer_view_controller.h b/ios/crnet/crnet_consumer/crnet_consumer_view_controller.h
new file mode 100644
index 0000000..e8539e9
--- /dev/null
+++ b/ios/crnet/crnet_consumer/crnet_consumer_view_controller.h
@@ -0,0 +1,14 @@
+// Copyright 2014 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.
+
+#ifndef CRNET_CONSUMER_VIEW_CONTROLLER_
+#define CRNET_CONSUMER_VIEW_CONTROLLER_
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface CrNetConsumerViewController : UIViewController
+@end
+
+#endif // CRNET_CONSUMER_VIEW_CONTROLLER_
diff --git a/ios/crnet/crnet_consumer/crnet_consumer_view_controller.m b/ios/crnet/crnet_consumer/crnet_consumer_view_controller.m
new file mode 100644
index 0000000..bdcd4ef
--- /dev/null
+++ b/ios/crnet/crnet_consumer/crnet_consumer_view_controller.m
@@ -0,0 +1,46 @@
+// Copyright 2014 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 "crnet_consumer_view_controller.h"
+
+#import "CrNet.h"
+
+@implementation CrNetConsumerViewController {
+ UIWebView* _webView;
+}
+
+- (void)viewDidLoad {
+ self.view.backgroundColor = [UIColor whiteColor];
+
+ UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem];
+ [button setTitle:@"chromium.org" forState:UIControlStateNormal];
+ [button setFrame:CGRectMake(5, 0, 95, 50)];
+ [button addTarget:self
+ action:@selector(loadChromium)
+ forControlEvents:UIControlEventTouchUpInside];
+ [self.view addSubview:button];
+
+ _webView = [[UIWebView alloc]
+ initWithFrame:CGRectMake(0,
+ 52,
+ self.view.bounds.size.width,
+ self.view.bounds.size.height - 52)];
+ [self.view addSubview:_webView];
+ _webView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
+ UIViewAutoresizingFlexibleHeight;
+
+ [self loadChromium];
+}
+
+// Disable the status bar to sidestep all the iOS7 status bar issues.
+- (BOOL)prefersStatusBarHidden {
+ return YES;
+}
+
+- (void)loadChromium {
+ [_webView loadRequest:[NSURLRequest requestWithURL:
+ [NSURL URLWithString:@"https://www.chromium.org"]]];
+}
+
+@end
diff --git a/ios/crnet/crnet_consumer/main.m b/ios/crnet/crnet_consumer/main.m
new file mode 100644
index 0000000..0a3e5f4
--- /dev/null
+++ b/ios/crnet/crnet_consumer/main.m
@@ -0,0 +1,15 @@
+// Copyright 2014 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 <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+#import "crnet_consumer_app_delegate.h"
+
+int main(int argc, char *argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(
+ argc, argv, nil, NSStringFromClass([CrNetConsumerAppDelegate class]));
+ }
+}
diff --git a/ios/crnet/crnet_empty_for_link.cc b/ios/crnet/crnet_empty_for_link.cc
new file mode 100644
index 0000000..7487e66
--- /dev/null
+++ b/ios/crnet/crnet_empty_for_link.cc
@@ -0,0 +1,3 @@
+// Copyright 2014 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.
diff --git a/ios/crnet/crnet_environment.h b/ios/crnet/crnet_environment.h
new file mode 100644
index 0000000..e3a71c3
--- /dev/null
+++ b/ios/crnet/crnet_environment.h
@@ -0,0 +1,153 @@
+// Copyright 2014 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.
+
+#ifndef IOS_CRNET_CRNET_ENVIRONMENT_H_
+#define IOS_CRNET_CRNET_ENVIRONMENT_H_
+
+#include "base/files/file_path.h"
+#include "base/message_loop/message_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#import "ios/crnet/CrNet.h"
+#include "ios/crnet/crnet_net_log.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+
+namespace net {
+class HttpCache;
+class NetworkChangeNotifier;
+class ProxyConfigService;
+class SdchManager;
+class URLRequestContextGetter;
+}
+
+class CrNetHttpProtocolHandlerDelegate;
+
+// CrNetEnvironment contains all the network stack configuration
+// and initialization.
+class CrNetEnvironment {
+ public:
+ // Must be called on the main thread.
+ static void Initialize();
+
+ // |user_agent_product_name| will be used to generate the user-agent.
+ CrNetEnvironment(std::string user_agent_product_name);
+ ~CrNetEnvironment();
+
+ // Installs this CrNet environment so requests are intercepted.
+ // Can only be called once; to enable/disable CrNet at runtime, use
+ // SetHTTPProtocolHandlerRegistered.
+ void Install();
+
+ // Installs this CrNet environment into the supplied
+ // NSURLSessionConfiguration. Settings are inherited from the shared
+ // NSURLSessionConfiguration, which Install() affects.
+ void InstallIntoSessionConfiguration(NSURLSessionConfiguration* config);
+
+ // The full user-agent.
+ std::string user_agent();
+
+ // Returns the global request context getter for use in the network stack.
+ //
+ // The request context gathers all the settings needed to do an actual network
+ // request (cache type and path, cookies store, proxy setting ...).
+ // Chrome network stacks supports multiple active contexts, and this is used
+ // for example to separate Incognito data from the main profile data.
+ // CrNetEnvironment only implement one request context for now, but it can be
+ // extended in the future.
+ net::URLRequestContextGetter* GetMainContextGetter();
+
+ // Enables or disables the HTTP protocol handler.
+ //
+ // When the HTTP protocol handler is registered, it will be used for all the
+ // network requests the application does (including requests from UIWebView).
+ void SetHTTPProtocolHandlerRegistered(bool registered);
+
+ // Creates a new net log (overwrites existing file with this name). If
+ // actively logging, this call is ignored.
+ void StartNetLog(base::FilePath::StringType file_name, bool log_bytes);
+ // Stops logging and flushes file. If not currently logging this call is
+ // ignored.
+ void StopNetLog();
+ // Closes all existing SPDY sessions with ERR_ABORTED.
+ void CloseAllSpdySessions();
+
+ // Sets the block used to determine whether or not CrNet should handle the
+ // request. If this is not set, CrNet will handle all requests.
+ // Must not be called while requests are in progress.
+ void SetRequestFilterBlock(RequestFilterBlock block);
+
+ // Setters and getters for |spdy_enabled_|, |quic_enabled_|, and
+ // |forced_quic_origin_|. These only have any effect before Install() is
+ // called.
+ void set_spdy_enabled(bool enabled) { spdy_enabled_ = enabled; }
+ void set_quic_enabled(bool enabled) { quic_enabled_ = enabled; }
+ void set_alternate_protocol_threshold(double threshold) {
+ alternate_protocol_threshold_ = threshold;
+ }
+
+ bool spdy_enabled() const { return spdy_enabled_; }
+ bool quic_enabled() const { return quic_enabled_; }
+ double alternate_protocol_threshold() const {
+ return alternate_protocol_threshold_;
+ }
+
+ // Clears the network stack's disk cache.
+ void ClearCache(ClearCacheCallback callback);
+
+ private:
+ // Runs a closure on the network thread.
+ void PostToNetworkThread(const tracked_objects::Location& from_here,
+ const base::Closure& task);
+
+ // Performs initialization tasks that must happen on the network thread.
+ void InitializeOnNetworkThread();
+
+ // Runs a closure on the file user blocking thread.
+ void PostToFileUserBlockingThread(const tracked_objects::Location& from_here,
+ const base::Closure& task);
+
+ // Helper methods that start/stop net-internals logging on the file
+ // user blocking thread.
+ void StartNetLogInternal(base::FilePath::StringType file_name,
+ bool log_bytes);
+ void StopNetLogInternal();
+
+ // Returns the HttpNeteworkSession object from the passed in
+ // URLRequestContext or NULL if none exists.
+ net::HttpNetworkSession* GetHttpNetworkSession(
+ net::URLRequestContext* context);
+
+ // Helper method that closes all current SPDY sessions on the network IO
+ // thread.
+ void CloseAllSpdySessionsInternal();
+
+ bool spdy_enabled_;
+ bool quic_enabled_;
+ double alternate_protocol_threshold_;
+
+ // Helper method that clears the cache on the network thread.
+ void ClearCacheOnNetworkThread(ClearCacheCallback callback);
+
+ static CrNetEnvironment* chrome_net_;
+ scoped_ptr<base::Thread> network_io_thread_;
+ scoped_ptr<base::Thread> network_cache_thread_;
+ scoped_ptr<base::Thread> file_thread_;
+ scoped_ptr<base::Thread> file_user_blocking_thread_;
+ scoped_ptr<net::SdchManager> sdch_manager_;
+ scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
+ scoped_ptr<net::ProxyConfigService> proxy_config_service_;
+ scoped_ptr<net::HttpServerProperties> http_server_properties_;
+ scoped_refptr<net::URLRequestContextGetter> main_context_getter_;
+ scoped_ptr<net::URLRequestContext> main_context_;
+ scoped_ptr<CrNetHttpProtocolHandlerDelegate> http_protocol_handler_delegate_;
+ std::string user_agent_product_name_;
+ base::Lock net_log_lock_;
+ bool net_log_started_;
+ scoped_ptr<CrNetNetLog> net_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrNetEnvironment);
+};
+
+#endif // IOS_CRNET_CRNET_ENVIRONMENT_H_
diff --git a/ios/crnet/crnet_environment.mm b/ios/crnet/crnet_environment.mm
new file mode 100644
index 0000000..d216159
--- /dev/null
+++ b/ios/crnet/crnet_environment.mm
@@ -0,0 +1,464 @@
+// Copyright 2014 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.
+
+#include "ios/crnet/crnet_environment.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/i18n/icu_util.h"
+#include "base/json/json_writer.h"
+#include "base/mac/bind_objc_block.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_block.h"
+#include "base/path_service.h"
+#include "base/threading/worker_pool.h"
+#import "components/webp_transcode/webp_network_client_factory.h"
+#include "crypto/nss_util.h"
+#include "ios/net/cookies/cookie_store_ios.h"
+#include "ios/net/crn_http_protocol_handler.h"
+#include "ios/net/request_tracker.h"
+#include "ios/web/public/user_agent.h"
+#include "net/base/net_errors.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/sdch_manager.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cert_net/nss_ocsp.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_server_properties_impl.h"
+#include "net/http/http_stream_factory.h"
+#include "net/http/http_util.h"
+#include "net/proxy/proxy_service.h"
+#include "net/socket/next_proto.h"
+#include "net/ssl/channel_id_service.h"
+#include "net/ssl/default_channel_id_store.h"
+#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/url_request/data_protocol_handler.h"
+#include "net/url_request/file_protocol_handler.h"
+#include "net/url_request/sdch_dictionary_fetcher.h"
+#include "net/url_request/static_http_user_agent_settings.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_context_storage.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "url/url_util.h"
+
+namespace {
+
+base::AtExitManager* g_at_exit_ = nullptr;
+
+// Request context getter for CrNet.
+class CrNetURLRequestContextGetter : public net::URLRequestContextGetter {
+ public:
+ CrNetURLRequestContextGetter(
+ net::URLRequestContext* context,
+ const scoped_refptr<base::MessageLoopProxy>& loop)
+ : context_(context), loop_(loop) {}
+
+ net::URLRequestContext* GetURLRequestContext() override { return context_; }
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
+ const override {
+ return loop_;
+ }
+ private:
+ // Must be called on the IO thread.
+ ~CrNetURLRequestContextGetter() override {}
+
+ net::URLRequestContext* context_;
+ scoped_refptr<base::MessageLoopProxy> loop_;
+ DISALLOW_COPY_AND_ASSIGN(CrNetURLRequestContextGetter);
+};
+
+} // namespace
+
+// net::HTTPProtocolHandlerDelegate for CrNet.
+class CrNetHttpProtocolHandlerDelegate
+ : public net::HTTPProtocolHandlerDelegate {
+ public:
+ CrNetHttpProtocolHandlerDelegate(net::URLRequestContextGetter* getter,
+ RequestFilterBlock filter)
+ : getter_(getter), filter_(filter, base::scoped_policy::RETAIN) {}
+
+ private:
+ // net::HTTPProtocolHandlerDelegate implementation:
+ bool CanHandleRequest(NSURLRequest* request) override {
+ // Don't advertise support for file:// URLs for now.
+ // This broke some time ago but it's not clear how to fix it at the moment.
+ // http://crbug.com/480620
+ if ([[[request URL] scheme] caseInsensitiveCompare:@"file"] ==
+ NSOrderedSame) {
+ return false;
+ }
+ if (filter_) {
+ RequestFilterBlock block = filter_.get();
+ return block(request);
+ }
+ return true;
+ }
+
+ bool IsRequestSupported(NSURLRequest* request) override {
+ NSString* scheme = [[request URL] scheme];
+ if (!scheme)
+ return false;
+ return [scheme caseInsensitiveCompare:@"data"] == NSOrderedSame ||
+ [scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
+ [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame;
+ }
+
+ net::URLRequestContextGetter* GetDefaultURLRequestContext() override {
+ return getter_.get();
+ }
+
+ scoped_refptr<net::URLRequestContextGetter> getter_;
+ base::mac::ScopedBlock<RequestFilterBlock> filter_;
+};
+
+void CrNetEnvironment::PostToNetworkThread(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ network_io_thread_->message_loop()->PostTask(from_here, task);
+}
+
+void CrNetEnvironment::PostToFileUserBlockingThread(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ file_user_blocking_thread_->message_loop()->PostTask(from_here, task);
+}
+
+// static
+void CrNetEnvironment::Initialize() {
+ DCHECK_EQ([NSThread currentThread], [NSThread mainThread]);
+ if (!g_at_exit_)
+ g_at_exit_ = new base::AtExitManager;
+
+ CHECK(base::i18n::InitializeICU());
+ url::Initialize();
+ base::CommandLine::Init(0, nullptr);
+ // This needs to happen on the main thread. NSPR's initialization sets up its
+ // memory allocator; if this is not done before other threads are created,
+ // this initialization can race to cause accidental free/allocation
+ // mismatches.
+ crypto::EnsureNSPRInit();
+
+ // Create a message loop on the UI thread.
+ base::MessageLoop* main_message_loop =
+ new base::MessageLoop(base::MessageLoop::TYPE_UI);
+#pragma unused(main_message_loop)
+ base::MessageLoopForUI::current()->Attach();
+}
+
+void CrNetEnvironment::StartNetLog(base::FilePath::StringType file_name,
+ bool log_bytes) {
+ DCHECK(file_name.length());
+ base::AutoLock lock(net_log_lock_);
+ if (net_log_started_) {
+ return;
+ }
+ net_log_started_ = true;
+ PostToFileUserBlockingThread(FROM_HERE,
+ base::Bind(&CrNetEnvironment::StartNetLogInternal,
+ base::Unretained(this), file_name, log_bytes));
+}
+
+void CrNetEnvironment::StartNetLogInternal(
+ base::FilePath::StringType file_name, bool log_bytes) {
+ DCHECK(base::MessageLoop::current() ==
+ file_user_blocking_thread_->message_loop());
+ DCHECK(file_name.length());
+ if (!net_log_.get()) {
+ net_log_.reset(new CrNetNetLog());
+ main_context_.get()->set_net_log(net_log_.get());
+ }
+ CrNetNetLog::Mode mode = log_bytes ? CrNetNetLog::LOG_ALL_BYTES :
+ CrNetNetLog::LOG_STRIP_PRIVATE_DATA;
+ net_log_->Start(base::FilePath(file_name), mode);
+}
+
+void CrNetEnvironment::StopNetLog() {
+ base::AutoLock lock(net_log_lock_);
+ if (!net_log_started_) {
+ return;
+ }
+ net_log_started_ = false;
+ PostToFileUserBlockingThread(FROM_HERE,
+ base::Bind(&CrNetEnvironment::StopNetLogInternal,
+ base::Unretained(this)));
+}
+
+void CrNetEnvironment::StopNetLogInternal() {
+ DCHECK(base::MessageLoop::current() ==
+ file_user_blocking_thread_->message_loop());
+ if (net_log_.get()) {
+ net_log_->Stop();
+ }
+}
+
+void CrNetEnvironment::CloseAllSpdySessions() {
+ PostToNetworkThread(FROM_HERE,
+ base::Bind(&CrNetEnvironment::CloseAllSpdySessionsInternal,
+ base::Unretained(this)));
+}
+
+void CrNetEnvironment::SetRequestFilterBlock(RequestFilterBlock block) {
+ http_protocol_handler_delegate_.reset(
+ new CrNetHttpProtocolHandlerDelegate(main_context_getter_.get(), block));
+ net::HTTPProtocolHandlerDelegate::SetInstance(
+ http_protocol_handler_delegate_.get());
+}
+
+net::HttpNetworkSession* CrNetEnvironment::GetHttpNetworkSession(
+ net::URLRequestContext* context) {
+ DCHECK(context);
+ if (!context->http_transaction_factory())
+ return nullptr;
+
+ return context->http_transaction_factory()->GetSession();
+}
+
+void CrNetEnvironment::CloseAllSpdySessionsInternal() {
+ DCHECK(base::MessageLoop::current() ==
+ network_io_thread_->message_loop());
+
+ net::HttpNetworkSession* http_network_session =
+ GetHttpNetworkSession(GetMainContextGetter()->GetURLRequestContext());
+
+ if (http_network_session) {
+ net::SpdySessionPool *spdy_session_pool =
+ http_network_session->spdy_session_pool();
+ if (spdy_session_pool)
+ spdy_session_pool->CloseCurrentSessions(net::ERR_ABORTED);
+ }
+}
+
+CrNetEnvironment::CrNetEnvironment(std::string user_agent_product_name)
+ : main_context_(new net::URLRequestContext),
+ user_agent_product_name_(user_agent_product_name) {
+
+}
+
+void CrNetEnvironment::Install() {
+ // Threads setup.
+ network_cache_thread_.reset(new base::Thread("Chrome Network Cache Thread"));
+ network_cache_thread_->StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+ network_io_thread_.reset(new base::Thread("Chrome Network IO Thread"));
+ network_io_thread_->StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+ file_thread_.reset(new base::Thread("Chrome File Thread"));
+ file_thread_->StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+ file_user_blocking_thread_.reset(
+ new base::Thread("Chrome File User Blocking Thread"));
+ file_user_blocking_thread_->StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+
+ // The network change notifier must be initialized so that registered
+ // delegates will receive callbacks.
+ network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
+ proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService(
+ network_io_thread_->message_loop_proxy(), nullptr));
+
+ PostToNetworkThread(FROM_HERE,
+ base::Bind(&CrNetEnvironment::InitializeOnNetworkThread,
+ base::Unretained(this)));
+
+ net::SetURLRequestContextForNSSHttpIO(main_context_.get());
+ main_context_getter_ = new CrNetURLRequestContextGetter(
+ main_context_.get(), network_io_thread_->message_loop_proxy());
+ SetRequestFilterBlock(nil);
+ net_log_started_ = false;
+}
+
+void CrNetEnvironment::InstallIntoSessionConfiguration(
+ NSURLSessionConfiguration* config) {
+ config.protocolClasses = @[ [CRNHTTPProtocolHandler class] ];
+}
+
+CrNetEnvironment::~CrNetEnvironment() {
+ net::HTTPProtocolHandlerDelegate::SetInstance(nullptr);
+ net::SetURLRequestContextForNSSHttpIO(nullptr);
+}
+
+net::URLRequestContextGetter* CrNetEnvironment::GetMainContextGetter() {
+ return main_context_getter_.get();
+}
+
+void CrNetEnvironment::SetHTTPProtocolHandlerRegistered(bool registered) {
+ if (registered) {
+ // Disable the default cache.
+ [NSURLCache setSharedURLCache:nil];
+ // Register the chrome http protocol handler to replace the default one.
+ BOOL success = [NSURLProtocol registerClass:[CRNHTTPProtocolHandler class]];
+ DCHECK(success);
+ } else {
+ // Set up an empty default cache, with default size.
+ // TODO(droger): If the NSURLCache is to be used, its size should most
+ // likely be changed. On an iPod2 with iOS4, the default size is 512k.
+ [NSURLCache setSharedURLCache:[[[NSURLCache alloc] init] autorelease]];
+ [NSURLProtocol unregisterClass:[CRNHTTPProtocolHandler class]];
+ }
+}
+
+void CrNetEnvironment::InitializeOnNetworkThread() {
+ DCHECK(base::MessageLoop::current() == network_io_thread_->message_loop());
+
+ // Register network clients.
+ net::RequestTracker::AddGlobalNetworkClientFactory(
+ [[[WebPNetworkClientFactory alloc]
+ initWithTaskRunner:file_user_blocking_thread_
+ ->message_loop_proxy()] autorelease]);
+
+#if 0
+ // TODO(huey): Re-enable this once SDCH supports SSL and dictionaries from
+ // previous sessions can be used on the first request after a fresh launch.
+ sdch_manager_.reset(new net::SdchManager());
+ sdch_manager_->set_sdch_fetcher(
+ new SdchDictionaryFetcher(main_context_getter_));
+#else
+ // Otherwise, explicitly disable SDCH to avoid a crash.
+ net::SdchManager::EnableSdchSupport(false);
+#endif
+
+ NSString* bundlePath =
+ [[NSBundle mainBundle] pathForResource:@"crnet_resources"
+ ofType:@"bundle"];
+ NSBundle* bundle = [NSBundle bundleWithPath:bundlePath];
+ NSString* acceptableLanguages = NSLocalizedStringWithDefaultValue(
+ @"IDS_ACCEPT_LANGUAGES",
+ @"Localizable",
+ bundle,
+ @"en-US,en",
+ @"These values are copied from Chrome's .xtb files, so the same "
+ "values are used in the |Accept-Language| header. Key name matches "
+ "Chrome's.");
+ DCHECK(acceptableLanguages);
+ std::string acceptable_languages =
+ [acceptableLanguages cStringUsingEncoding:NSUTF8StringEncoding];
+ std::string user_agent =
+ web::BuildUserAgentFromProduct(user_agent_product_name_);
+ // Set the user agent through NSUserDefaults. This sets it for both
+ // UIWebViews and WKWebViews, and javascript calls to navigator.userAgent
+ // return this value.
+ [[NSUserDefaults standardUserDefaults] registerDefaults:@{
+ @"UserAgent" : [NSString stringWithUTF8String:user_agent.c_str()]
+ }];
+ main_context_->set_http_user_agent_settings(
+ new net::StaticHttpUserAgentSettings(acceptable_languages, user_agent));
+
+ main_context_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
+ main_context_->set_transport_security_state(
+ new net::TransportSecurityState());
+ http_server_properties_.reset(new net::HttpServerPropertiesImpl());
+ main_context_->set_http_server_properties(
+ http_server_properties_->GetWeakPtr());
+ main_context_->set_host_resolver(
+ net::HostResolver::CreateDefaultResolver(nullptr).release());
+ main_context_->set_cert_verifier(net::CertVerifier::CreateDefault());
+ main_context_->set_http_auth_handler_factory(
+ net::HttpAuthHandlerRegistryFactory::CreateDefault(
+ main_context_->host_resolver()));
+ main_context_->set_proxy_service(
+ net::ProxyService::CreateUsingSystemProxyResolver(
+ proxy_config_service_.get(), 0, nullptr));
+
+ // Cache
+ NSArray* dirs = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
+ NSUserDomainMask,
+ YES);
+ base::FilePath cache_path =
+ base::mac::NSStringToFilePath([dirs objectAtIndex:0]);
+ cache_path = cache_path.Append(FILE_PATH_LITERAL("crnet"));
+ net::HttpCache::DefaultBackend* main_backend =
+ new net::HttpCache::DefaultBackend(
+ net::DISK_CACHE,
+ net::CACHE_BACKEND_DEFAULT,
+ cache_path,
+ 0, // Default cache size.
+ network_cache_thread_->message_loop_proxy());
+
+ net::HttpNetworkSession::Params params;
+ params.host_resolver = main_context_->host_resolver();
+ params.cert_verifier = main_context_->cert_verifier();
+ params.channel_id_service = main_context_->channel_id_service();
+ params.transport_security_state = main_context_->transport_security_state();
+ params.proxy_service = main_context_->proxy_service();
+ params.ssl_session_cache_shard = "";
+ params.ssl_config_service = main_context_->ssl_config_service();
+ params.http_auth_handler_factory = main_context_->http_auth_handler_factory();
+ params.network_delegate = main_context_->network_delegate();
+ params.http_server_properties = main_context_->http_server_properties();
+ params.net_log = main_context_->net_log();
+ params.next_protos =
+ net::NextProtosWithSpdyAndQuic(spdy_enabled(), quic_enabled());
+ params.use_alternate_protocols = true;
+ params.enable_quic = quic_enabled();
+ params.alternative_service_probability_threshold =
+ alternate_protocol_threshold_;
+
+ if (!params.channel_id_service) {
+ // The main context may not have a ChannelIDService, since it is lazily
+ // constructed. If not, build an ephemeral ChannelIDService with no backing
+ // disk store.
+ // TODO(ellyjones): support persisting ChannelID.
+ params.channel_id_service = new net::ChannelIDService(
+ new net::DefaultChannelIDStore(NULL),
+ base::WorkerPool::GetTaskRunner(true));
+ }
+
+ net::HttpCache* main_cache = new net::HttpCache(params, main_backend);
+ main_context_->set_http_transaction_factory(main_cache);
+
+ // Cookies
+ scoped_refptr<net::CookieStore> cookie_store =
+ net::CookieStoreIOS::CreateCookieStoreFromNSHTTPCookieStorage();
+ main_context_->set_cookie_store(cookie_store.get());
+
+ net::URLRequestJobFactoryImpl* job_factory =
+ new net::URLRequestJobFactoryImpl;
+ job_factory->SetProtocolHandler("data", new net::DataProtocolHandler);
+ job_factory->SetProtocolHandler(
+ "file", new net::FileProtocolHandler(file_thread_->message_loop_proxy()));
+ main_context_->set_job_factory(job_factory);
+}
+
+std::string CrNetEnvironment::user_agent() {
+ const net::HttpUserAgentSettings* user_agent_settings =
+ main_context_->http_user_agent_settings();
+ if (!user_agent_settings) {
+ return nullptr;
+ }
+
+ return user_agent_settings->GetUserAgent();
+}
+
+void CrNetEnvironment::ClearCache(ClearCacheCallback callback) {
+ PostToNetworkThread(FROM_HERE,
+ base::Bind(&CrNetEnvironment::ClearCacheOnNetworkThread,
+ base::Unretained(this),
+ callback));
+}
+
+void CrNetEnvironment::ClearCacheOnNetworkThread(ClearCacheCallback callback) {
+ DCHECK(base::MessageLoop::current() == network_io_thread_->message_loop());
+ __block disk_cache::Backend* backend = nullptr;
+ net::HttpCache* cache = main_context_->http_transaction_factory()->GetCache();
+ net::CompletionCallback client_callback = base::BindBlock(^(int error) {
+ if (callback != nil) {
+ callback(error);
+ }
+ });
+ net::CompletionCallback doom_callback = base::BindBlock(^(int error) {
+ if (backend)
+ backend->DoomAllEntries(client_callback);
+ });
+ int rc = cache->GetBackend(&backend, doom_callback);
+ if (rc != net::ERR_IO_PENDING) {
+ // GetBackend doesn't call the callback if it completes synchronously, so
+ // call it directly here.
+ doom_callback.Run(rc);
+ }
+}
diff --git a/ios/crnet/crnet_net_log.cc b/ios/crnet/crnet_net_log.cc
new file mode 100644
index 0000000..4ad3d30
--- /dev/null
+++ b/ios/crnet/crnet_net_log.cc
@@ -0,0 +1,46 @@
+// Copyright 2015 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.
+
+#include "ios/crnet/crnet_net_log.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
+#include "base/values.h"
+#include "net/log/net_log.h"
+#include "net/log/net_log_util.h"
+#include "net/log/write_to_file_net_log_observer.h"
+
+CrNetNetLog::CrNetNetLog() { }
+CrNetNetLog::~CrNetNetLog() { }
+
+bool CrNetNetLog::Start(const base::FilePath& log_file,
+ CrNetNetLog::Mode mode) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ base::FilePath temp_dir;
+ if (!base::GetTempDir(&temp_dir))
+ return false;
+
+ base::FilePath full_path = temp_dir.Append(log_file);
+ base::ScopedFILE file(base::OpenFile(full_path, "w"));
+ if (!file)
+ return false;
+
+ scoped_ptr<base::Value> constants(net::GetNetConstants().Pass());
+
+ net::NetLogCaptureMode capture_mode = mode == LOG_ALL_BYTES ?
+ net::NetLogCaptureMode::IncludeSocketBytes() :
+ net::NetLogCaptureMode::Default();
+ write_to_file_observer_.reset(new net::WriteToFileNetLogObserver());
+ write_to_file_observer_->set_capture_mode(capture_mode);
+ write_to_file_observer_->StartObserving(this, file.Pass(), constants.get(),
+ nullptr);
+ return true;
+}
+
+void CrNetNetLog::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ write_to_file_observer_->StopObserving(nullptr);
+ write_to_file_observer_.reset();
+}
diff --git a/ios/crnet/crnet_net_log.h b/ios/crnet/crnet_net_log.h
new file mode 100644
index 0000000..6bdc076
--- /dev/null
+++ b/ios/crnet/crnet_net_log.h
@@ -0,0 +1,51 @@
+// Copyright 2015 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.
+
+#ifndef IOS_CRNET_CRNET_NET_LOG_H_
+#define IOS_CRNET_CRNET_NET_LOG_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "net/log/net_log.h"
+
+namespace base {
+class FilePath;
+class DictionaryValue;
+}
+
+namespace net {
+class WriteToFileNetLogObserver;
+}
+
+// CrNet-specific NetLog subclass.
+// This class can be used as a NetLog where needed; it logs all log entries to
+// the file specified in Start().
+class CrNetNetLog : public net::NetLog {
+ public:
+ enum Mode {
+ LOG_ALL_BYTES,
+ LOG_STRIP_PRIVATE_DATA,
+ };
+
+ CrNetNetLog();
+ ~CrNetNetLog() override;
+
+ // Starts logging to the file named |log_file|. If |mode| is LOG_ALL_BYTES,
+ // logs all network traffic, including raw bytes. If |mode| is
+ // LOG_STRIP_PRIVATE_DATA, strips cookies and other private data, and does
+ // not log raw bytes.
+ bool Start(const base::FilePath& log_file, Mode mode);
+
+ // Stops logging.
+ void Stop();
+
+ private:
+ // Underlying file writer. This observer observes NetLog events and writes
+ // them back to the file this class is logging to.
+ scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_;
+
+ base::ThreadChecker thread_checker_;
+};
+
+#endif // IOS_CRNET_CRNET_NET_LOG_H
diff --git a/ios/crnet/crnet_pack.gyp b/ios/crnet/crnet_pack.gyp
new file mode 100644
index 0000000..81b2e78b
--- /dev/null
+++ b/ios/crnet/crnet_pack.gyp
@@ -0,0 +1,65 @@
+# Copyright 2014 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [],
+ 'conditions': [
+ # Our shared library hack only works with ninja; xcode cannot generate
+ # iOS build targets for dynamic libraries. More details below.
+ ['"<(GENERATOR)"=="ninja"', {
+ 'targets': [
+ {
+ 'target_name': 'crnet_dummy',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'dependencies': [
+ '../../ios/crnet/crnet.gyp:crnet',
+ ],
+ 'sources': [
+ '../../ios/build/packaging/dummy_main.mm',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': '../../ios/build/packaging/dummy-Info.plist',
+ },
+ },
+ {
+ # Build this target to package a standalone CrNet in a single
+ # .a file.
+ 'target_name': 'crnet_pack',
+ 'type': 'none',
+ 'dependencies': [
+ # Depend on the dummy target so that all of CrNet's dependencies
+ # are built before packaging.
+ 'crnet_dummy',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'Package CrNet',
+ 'variables': {
+ 'tool_path':
+ '../../ios/build/packaging/link_dependencies.py',
+ },
+
+ # Actions need an inputs list, even if it's empty.
+ 'inputs': [],
+ # Only specify one output, since this will be libtool's output.
+ 'outputs': [ '<(PRODUCT_DIR)/libcrnet_standalone.a' ],
+ 'action': ['<(tool_path)',
+ '<(PRODUCT_DIR)',
+ 'crnet_dummy.app/crnet_dummy',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ ],
+ }],
+ ],
+}