Set up a network service bootstrap.

This adds a script to download network service binaries identified by
a versioned stamp kept in services/network/VERSION and adds a DEPS hook
to run it at gclient --sync.

BUG=450356
R=jamesr@chromium.org

Review URL: https://codereview.chromium.org/869193005
diff --git a/.gitignore b/.gitignore
index 41c17be..9a867a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@
 /out/
 /out_*/
 /sdch/open-vcdiff/
+/services/network/prebuilt/
 /testing/gmock/
 /testing/gtest/
 /third_party/android_tools/
diff --git a/DEPS b/DEPS
index 0dd8e35..fc8b36f 100644
--- a/DEPS
+++ b/DEPS
@@ -317,6 +317,13 @@
                 '-s', 'src/build/linux/bin/eu-strip.sha1',
     ],
   },
+  # Pull the prebuilt network service binaries according to
+  # services/network/VERSION.
+  {
+    'name': 'download_network_service',
+    'pattern': '',
+    'action': [ 'python', 'src/services/network/download_network_service.py' ],
+  },
   {
     # Ensure that we don't accidentally reference any .pyc files whose
     # corresponding .py files have already been deleted.
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
new file mode 100644
index 0000000..df5578b
--- /dev/null
+++ b/services/network/BUILD.gn
@@ -0,0 +1,20 @@
+# 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.
+
+copy("copy_prebuilt_network_service") {
+  filename = "network_service.mojo"
+  if (is_android) {
+    sources = [
+      "prebuilt/android-arm/$filename",
+    ]
+  } else {
+    assert(is_linux)
+    sources = [
+      "prebuilt/linux-x64/$filename",
+    ]
+  }
+  outputs = [
+    "$root_out_dir/$filename",
+  ]
+}
diff --git a/services/network/VERSION b/services/network/VERSION
new file mode 100644
index 0000000..2f3fb49
--- /dev/null
+++ b/services/network/VERSION
@@ -0,0 +1 @@
+749f2049192aedba7a1cb165ad80ab8afdb047e0
diff --git a/services/network/download_network_service.py b/services/network/download_network_service.py
new file mode 100755
index 0000000..1859b90
--- /dev/null
+++ b/services/network/download_network_service.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# 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.
+
+import argparse
+import os
+import sys
+import tempfile
+import zipfile
+
+_PLATFORMS = ["linux-x64", "android-arm"]
+
+if not sys.platform.startswith("linux"):
+  print "Not supported for your platform"
+  sys.exit(0)
+
+# Add //tools to the system path so that we can import the gs helper.
+script_dir = os.path.dirname(os.path.realpath(__file__))
+tools_path = os.path.join(script_dir, os.pardir, os.pardir, "tools")
+sys.path.insert(0, tools_path)
+# pylint: disable=F0401
+import gs
+
+
+def download_binary(version, platform, prebuilt_directory):
+  gs_path = "gs://mojo/network/%s/%s.zip" % (version, platform)
+  output_directory = os.path.join(prebuilt_directory, platform)
+  binary_name = "network_service.mojo"
+
+  with tempfile.NamedTemporaryFile() as temp_zip_file:
+    gs.download_from_public_bucket(gs_path, temp_zip_file.name)
+    with zipfile.ZipFile(temp_zip_file.name) as z:
+      zi = z.getinfo(binary_name)
+      mode = zi.external_attr >> 16
+      z.extract(zi, output_directory)
+      os.chmod(os.path.join(output_directory, binary_name), mode)
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description="Download prebuilt network service binaries from google " +
+                  "storage")
+  parser.parse_args()
+
+  prebuilt_directory_path = os.path.join(script_dir, "prebuilt")
+  stamp_path = os.path.join(prebuilt_directory_path, "STAMP")
+  version_path = os.path.join(script_dir, "VERSION")
+  with open(version_path) as version_file:
+    version = version_file.read().strip()
+
+  try:
+    with open(stamp_path) as stamp_file:
+      current_version = stamp_file.read().strip()
+      if current_version == version:
+        return 0  # Already have the right version.
+  except IOError:
+    pass  # If the stamp file does not exist we need to download a new binary.
+
+  for platform in _PLATFORMS:
+    download_binary(version, platform, prebuilt_directory_path)
+
+  with open(stamp_path, 'w') as stamp_file:
+    stamp_file.write(version)
+  return 0
+
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/tools/gs.py b/tools/gs.py
new file mode 100755
index 0000000..65e6e43
--- /dev/null
+++ b/tools/gs.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# 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.
+
+import os
+import subprocess
+import find_depot_tools
+
+def download_from_public_bucket(gs_path, output_path):
+  depot_tools_path = find_depot_tools.add_depot_tools_to_path()
+  gsutil_exe = os.path.join(depot_tools_path, "third_party", "gsutil", "gsutil")
+
+  # We're downloading from a public bucket which does not need authentication,
+  # but the user might have busted credential files somewhere such as ~/.boto
+  # that the gsutil script will try (and fail) to use. Setting these
+  # environment variables convinces gsutil not to attempt to use these, but
+  # also generates a useless warning about failing to load the file. We want
+  # to discard this warning but still preserve all output in the case of an
+  # actual failure. So, we run the script and capture all output and then
+  # throw the output away if the script succeeds (return code 0).
+  env = os.environ.copy()
+  env["AWS_CREDENTIAL_FILE"] = ""
+  env["BOTO_CONFIG"] = ""
+  try:
+    subprocess.check_output(
+        [gsutil_exe,
+         "--bypass_prodaccess",
+         "cp",
+         gs_path,
+         output_path],
+        stderr=subprocess.STDOUT,
+        env=env)
+  except subprocess.CalledProcessError as e:
+    print e.output
+    sys.exit(1)