blob: 24478024fa75511a0e7c592e9a4ac7ee157405c2 [file] [log] [blame]
beepsbff9f9d2013-12-06 11:14:08 -08001#!/usr/bin/python
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import httplib2
7import json
8import os
9import re
10import shutil
11import urllib2
12
13import common
14
beepsf860bd12014-01-23 18:06:06 -080015from autotest_lib.client.common_lib import autotemp
beepsbff9f9d2013-12-06 11:14:08 -080016from autotest_lib.client.common_lib import utils
17
beepsbff9f9d2013-12-06 11:14:08 -080018
19TEST_EXTENSION_ID = 'hfaagokkkhdbgiakmmlclaapfelnkoah'
20UPDATE_CHECK_URL = ('https://clients2.google.com/service/update2/')
21UPDATE_CHECK_PARAMETER = ('crx?x=id%%3D%s%%26v%%3D0%%26uc')
22MANIFEST_KEY = ('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+hlN5FB+tjCsBszmBIvI'
23 'cD/djLLQm2zZfFygP4U4/o++ZM91EWtgII10LisoS47qT2TIOg4Un4+G57e'
24 'lZ9PjEIhcJfANqkYrD3t9dpEzMNr936TLB2u683B5qmbB68Nq1Eel7KVc+F'
25 '0BqhBondDqhvDvGPEV0vBsbErJFlNH7SQIDAQAB')
26
27
beepsf860bd12014-01-23 18:06:06 -080028class SonicDownloaderException(Exception):
29 """Generic sonic dowloader exception."""
30 pass
31
32
beepsbff9f9d2013-12-06 11:14:08 -080033def get_download_url_from_omaha(extension_id):
34 """Retrieves an update url from omaha for the specified extension id.
35
36 @param extension_id: The extension id of the chromecast extension.
37
38 @return: A url to download the extension from.
39
40 @raises IOError: If the response returned by the omaha server is invalid.
41 """
42 update_check_link = '%s%s' % (UPDATE_CHECK_URL,
43 UPDATE_CHECK_PARAMETER % extension_id)
44 response_xml = httplib2.Http().request(update_check_link, 'GET')[1]
45 codebase_match = re.compile(r'codebase="(.*crx)"').search(response_xml)
46 if codebase_match is not None:
47 return codebase_match.groups()[0]
48 raise IOError('Omaha response is invalid %s.' % response_xml)
49
50
51def download_extension(dest_file):
52 """Retrieve the extension into a destination crx file.
53
54 @param dest_file: Path to a destination file for the extension.
55 """
56 download_url = get_download_url_from_omaha(TEST_EXTENSION_ID)
57 response = urllib2.urlopen(download_url)
58 with open(dest_file, 'w') as f:
59 f.write(response.read())
60
61
62def fix_public_key(extracted_extension_folder):
63 """Modifies the manifest.json to include a public key.
64
65 This function will erase the content in the original manifest
66 and replace it with a new manifest that contains the key.
67
68 @param extracted_extension_folder: The folder containing
69 the extracted extension.
70 """
71 manifest_json_file = os.path.join(extracted_extension_folder,
72 'manifest.json')
73 with open(manifest_json_file, 'r') as f:
74 manifest_json = json.loads(f.read())
75
76 manifest_json['key'] = MANIFEST_KEY
77
78 with open(manifest_json_file, 'w') as f:
79 f.write(json.dumps(manifest_json))
80
81
beepsf860bd12014-01-23 18:06:06 -080082def setup_extension(unzipped_crx_dir):
beepsbff9f9d2013-12-06 11:14:08 -080083 """Setup for tests that need a chromecast extension.
84
85 Download the extension from an omaha server, unzip it and modify its
86 manifest.json to include a public key.
87
beepsf860bd12014-01-23 18:06:06 -080088 @param unzipped_crx_dir: Destination directory for the unzipped extension.
beepsbff9f9d2013-12-06 11:14:08 -080089
90 @raises CmdTimeoutError: If we timeout unzipping the extension.
91 """
beepsf860bd12014-01-23 18:06:06 -080092 output_crx_dir = autotemp.tempdir()
93 output_crx = os.path.join(output_crx_dir.name, 'sonic_extension.crx')
94 try:
95 download_extension(output_crx)
96 unzip_cmd = 'unzip -o "%s" -d "%s"' % (output_crx, unzipped_crx_dir)
beepsbff9f9d2013-12-06 11:14:08 -080097
beepsf860bd12014-01-23 18:06:06 -080098 # The unzip command will return a non-zero exit status if there are
99 # extra bytes at the start/end of the zipfile. This is not a critical
100 # failure and the extension will still work.
101 cmd_output = utils.run(unzip_cmd, ignore_status=True, timeout=1)
102 except Exception as e:
103 if os.path.exists(unzipped_crx_dir):
104 shutil.rmtree()
105 raise SonicDownloaderException(e)
106 finally:
107 if os.path.exists(output_crx):
108 os.remove(output_crx)
109 output_crx_dir.clean()
110
beepsbff9f9d2013-12-06 11:14:08 -0800111 if not os.path.exists(unzipped_crx_dir):
beepsf860bd12014-01-23 18:06:06 -0800112 raise SonicDownloaderException('Unable to download sonic extension.')
beepsbff9f9d2013-12-06 11:14:08 -0800113
114 # TODO(beeps): crbug.com/325869, investigate the limits of component
115 # extensions. For now this is ok because even sonic testing inlines a
116 # public key for their test extension.
beepsf860bd12014-01-23 18:06:06 -0800117 try:
118 fix_public_key(unzipped_crx_dir)
119 except Exception as e:
120 shutil.rmtree(unzipped_crx_dir)
121 raise SonicDownloaderException(e)