# Copyright 2019 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 logging
import re
import utils

from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.enterprise import enterprise_policy_base


class policy_PlatformKeys(enterprise_policy_base.EnterprisePolicyTest):
    version = 1


    def initialize(self, **kwargs):
        """Set some global variables."""
        super(policy_PlatformKeys, self).initialize(**kwargs)
        # PlatformKeys extension ID.
        self.EXTENSION_ID = 'hoppbgdeajkagempifacalpdapphfoai'
        self.EXTENSION_PAGE = ('chrome-extension://%s/main.html'
                               % self.EXTENSION_ID)
        self.tab = None


    def click_button(self, id):
        """Click an element given its ID."""
        self.tab.ExecuteJavaScript(
                "document.querySelector('#%s').click()" % id)


    def field_value(self, id):
        """Return the value of a text field."""
        return self.tab.EvaluateJavaScript(
            "document.querySelector('#%s').value" % id)


    def call_api(self, button_id, field_id=None):
        """
        Call the API by clicking a button and checking its output fields.

        @param button_id: ID of the button element.
        @param field_id: Text field output is printed to (if any).

        @returns: Output of the call, if any.
        @raises error.TestFail: If the API call fails.

        """
        error_id = button_id + '-error'
        self.click_button(button_id)

        # Wait for the API to return 'OK' and raise an error if it doesn't.
        utils.poll_for_condition(
                lambda: 'OK' in self.field_value(error_id),
                timeout=15,
                exception=error.TestFail(
                    'API error: %s' % self.field_value(error_id)))

        if field_id:
            field = self.field_value(field_id)
            return field


    def create_certificate(self):
        """Return a certificate using the generated public key."""
        cert = self.call_api('create-cert', 'certificate')
        return cert.rstrip()


    def list_certificates(self):
        """Fetch all certificates and parse them into a list."""
        raw_certs = self.call_api('list-certs', 'certificates')

        if raw_certs:
            pattern = re.compile('-----BEGIN CERTIFICATE-----.*?'
                                 '-----END CERTIFICATE-----', flags=re.DOTALL)
            certs = re.findall(pattern, raw_certs)
        else:
            certs = []

        return certs


    def wait_for_extension(self):
        """Wait for the extension to install so we can open it."""
        def load_page():
            self.tab = self.navigate_to_url(self.EXTENSION_PAGE, self.tab)
            return self.tab.EvaluateJavaScript(
                      "document.querySelector('#cert-enrollment') !== null")

        utils.poll_for_condition(
            load_page,
            timeout=15,
            sleep_interval=1,
            desc='Timed out waiting for extension to install.')


    def test_platform_keys(self):
        """
        Test the chrome.enterprise.platformKeys API.

        The following API methods are tested:
            - getToken
            - getCertificates
            - importCertificate
            - removeCertificate

        """
        self.wait_for_extension()

        if self.list_certificates():
            raise error.TestFail('Certificates list should be empty at start.')

        public_key = self.call_api('generate', 'public-key')

        certificate = self.create_certificate()
        self.call_api('import-cert')

        installed_certs = self.list_certificates()
        if len(installed_certs) != 1:
            raise error.TestFail('There should be 1 certificate instead of %s.'
                                 % len(installed_certs))

        if installed_certs[0] != certificate:
            raise error.TestFail('Installed certificate does not match '
                                 'expected certificate. %s != %s' %
                                 (installed_certs[0], certificate))

        self.call_api('remove-cert')

        if self.list_certificates():
            raise error.TestFail('All certificates should have been removed '
                                 'at the end of the test.')


    def run_once(self):
        """Setup and run the test configured for the specified test case."""
        self.setup_case(user_policies={
            'ExtensionInstallForcelist': [self.EXTENSION_ID],
            'DeveloperToolsAvailability': 1
        })

        self.test_platform_keys()
