blob: d698d92259c7dc71777738fc59e09f4227fa939b [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2013 The Chromium OS 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 httplib2
import json
import os
import re
import shutil
import urllib2
import common
from autotest_lib.client.common_lib import utils
version = 1
TEST_EXTENSION_ID = 'hfaagokkkhdbgiakmmlclaapfelnkoah'
UPDATE_CHECK_URL = ('https://clients2.google.com/service/update2/')
UPDATE_CHECK_PARAMETER = ('crx?x=id%%3D%s%%26v%%3D0%%26uc')
MANIFEST_KEY = ('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+hlN5FB+tjCsBszmBIvI'
'cD/djLLQm2zZfFygP4U4/o++ZM91EWtgII10LisoS47qT2TIOg4Un4+G57e'
'lZ9PjEIhcJfANqkYrD3t9dpEzMNr936TLB2u683B5qmbB68Nq1Eel7KVc+F'
'0BqhBondDqhvDvGPEV0vBsbErJFlNH7SQIDAQAB')
def get_download_url_from_omaha(extension_id):
"""Retrieves an update url from omaha for the specified extension id.
@param extension_id: The extension id of the chromecast extension.
@return: A url to download the extension from.
@raises IOError: If the response returned by the omaha server is invalid.
"""
update_check_link = '%s%s' % (UPDATE_CHECK_URL,
UPDATE_CHECK_PARAMETER % extension_id)
response_xml = httplib2.Http().request(update_check_link, 'GET')[1]
codebase_match = re.compile(r'codebase="(.*crx)"').search(response_xml)
if codebase_match is not None:
return codebase_match.groups()[0]
raise IOError('Omaha response is invalid %s.' % response_xml)
def download_extension(dest_file):
"""Retrieve the extension into a destination crx file.
@param dest_file: Path to a destination file for the extension.
"""
download_url = get_download_url_from_omaha(TEST_EXTENSION_ID)
response = urllib2.urlopen(download_url)
with open(dest_file, 'w') as f:
f.write(response.read())
def fix_public_key(extracted_extension_folder):
"""Modifies the manifest.json to include a public key.
This function will erase the content in the original manifest
and replace it with a new manifest that contains the key.
@param extracted_extension_folder: The folder containing
the extracted extension.
"""
manifest_json_file = os.path.join(extracted_extension_folder,
'manifest.json')
with open(manifest_json_file, 'r') as f:
manifest_json = json.loads(f.read())
manifest_json['key'] = MANIFEST_KEY
with open(manifest_json_file, 'w') as f:
f.write(json.dumps(manifest_json))
def setup(output_crx, unzipped_crx_dir):
"""Setup for tests that need a chromecast extension.
Download the extension from an omaha server, unzip it and modify its
manifest.json to include a public key.
@param output_crx: The name of the crx file into which we will download
the extension. If this file already exists it will get
re-written.
@param unzipped_crx_dir: A directory for the unzipped extension.
@raises CmdTimeoutError: If we timeout unzipping the extension.
"""
download_extension(output_crx)
unzip_cmd = 'unzip -o "%s" -d "%s"' % (output_crx, unzipped_crx_dir)
# The unzip command will return a non-zero exit status if there are
# extra bytes at the start/end of the zipfile. This is not a critical
# failure and the extension will still work.
cmd_output = utils.run(unzip_cmd, ignore_status=True, timeout=1)
if not os.path.exists(unzipped_crx_dir):
raise IOError('Unzip failed, command %s, stderr %s', unzip_cmd,
cmd_output.stderr)
# TODO(beeps): crbug.com/325869, investigate the limits of component
# extensions. For now this is ok because even sonic testing inlines a
# public key for their test extension.
fix_public_key(unzipped_crx_dir)
srcdir = os.path.join(os.getcwd(), 'src')
output_crx = os.path.join(srcdir, 'sonic_extension.crx')
unzipped_crx_dir = os.path.join(os.path.dirname(output_crx),
re.split('[.]', os.path.basename(output_crx))[0])
try:
setup(output_crx, unzipped_crx_dir)
except:
if os.path.exists(unzipped_crx_dir):
shutil.rmtree(unzipped_crx_dir, ignore_errors=True)
raise
finally:
if os.path.exists(output_crx):
os.remove(output_crx)