# Copyright (c) 2012 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 dbus, gobject, os, sys

import common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import session_manager
from autotest_lib.client.cros import ownership

"""Utility class for tests that generate, push and fetch policies.

As the python bindings for the protobufs used in policies are built as a part
of tests that use them, callers must pass in their location at call time."""


def install_protobufs(autodir, job):
    """Installs policy protobuf dependencies and set import path.

    After calling this, you can simply import any policy pb2.py file directly,
    e.g. import chrome_device_policy_pb2.

    @param autodir: Autotest directory (usually the caller's self.autodir).
    @param job: Job instance (usually the caller's self.job).
    """
    # TODO(crbug.com/807950): Change the installation process so that policy
    #                         proto imports can be moved to the top.
    dep = 'policy_protos'
    dep_dir = os.path.join(autodir, 'deps', dep)
    job.install_pkg(dep, 'dep', dep_dir)
    sys.path.append(dep_dir)


def compare_policy_response(policy_response, owner=None, guests=None,
                            new_users=None, roaming=None, whitelist=None):
    """Check the contents of |policy_response| against given args.

    Deserializes |policy_response| into a PolicyFetchResponse protobuf,
    with an embedded (serialized) PolicyData protobuf that embeds a
    (serialized) ChromeDeviceSettingsProto, and checks to see if this
    protobuf turducken contains the information passed in.

    @param policy_response: string serialization of a PolicyData protobuf.
    @param owner: string representing the owner's name/account.
    @param guests: boolean indicating whether guests should be allowed.
    @param new_users: boolean indicating if user pods are on login screen.
    @param roaming: boolean indicating whether data roaming is enabled.
    @param whitelist: list of accounts that are allowed to log in.

    @return True if |policy_response| has all the provided data, else False.
    """
    import chrome_device_policy_pb2
    import device_management_backend_pb2

    response_proto = device_management_backend_pb2.PolicyFetchResponse()
    response_proto.ParseFromString(policy_response)
    ownership.assert_has_policy_data(response_proto)

    data_proto = device_management_backend_pb2.PolicyData()
    data_proto.ParseFromString(response_proto.policy_data)
    ownership.assert_has_device_settings(data_proto)
    if owner: ownership.assert_username(data_proto, owner)

    settings = chrome_device_policy_pb2.ChromeDeviceSettingsProto()
    settings.ParseFromString(data_proto.policy_value)
    if guests: ownership.assert_guest_setting(settings, guests)
    if new_users: ownership.assert_show_users(settings, new_users)
    if roaming: ownership.assert_roaming(settings, roaming)
    if whitelist:
        ownership.assert_new_users(settings, False)
        ownership.assert_users_on_whitelist(settings, whitelist)


def build_policy_data(owner=None, guests=None, new_users=None, roaming=None,
                      whitelist=None):
    """Generate and serialize a populated device policy protobuffer.

    Creates a PolicyData protobuf, with an embedded
    ChromeDeviceSettingsProto, containing the information passed in.

    @param owner: string representing the owner's name/account.
    @param guests: boolean indicating whether guests should be allowed.
    @param new_users: boolean indicating if user pods are on login screen.
    @param roaming: boolean indicating whether data roaming is enabled.
    @param whitelist: list of accounts that are allowed to log in.

    @return serialization of the PolicyData proto that we build.
    """
    import chrome_device_policy_pb2
    import device_management_backend_pb2

    data_proto = device_management_backend_pb2.PolicyData()
    data_proto.policy_type = ownership.POLICY_TYPE
    if owner: data_proto.username = owner

    settings = chrome_device_policy_pb2.ChromeDeviceSettingsProto()
    if guests:
        settings.guest_mode_enabled.guest_mode_enabled = guests
    if new_users:
        settings.show_user_names.show_user_names = new_users
    if roaming:
        settings.data_roaming_enabled.data_roaming_enabled = roaming
    if whitelist:
        settings.allow_new_users.allow_new_users = False
        for user in whitelist:
            settings.user_whitelist.user_whitelist.append(user)

    data_proto.policy_value = settings.SerializeToString()
    return data_proto.SerializeToString()


def generate_policy(key, pubkey, policy, old_key=None):
    """Generate and serialize a populated, signed device policy protobuffer.

    Creates a protobuf containing the device policy |policy|, signed with
    |key|.  Also includes the public key |pubkey|, signed with |old_key|
    if provided.  If not, |pubkey| is signed with |key|.  The protobuf
    is serialized to a string and returned.

    @param key: new policy signing key.
    @param pubkey: new public key to be signed and embedded in generated
                   PolicyFetchResponse.
    @param policy: policy data to be embedded in generated PolicyFetchResponse.
    @param old_key: if provided, this implies the generated PolicyFetchRespone
                    is intended to represent a key rotation.  pubkey will be
                    signed with this key before embedding.

    @return serialization of the PolicyFetchResponse proto that we build.
    """
    import device_management_backend_pb2

    if old_key == None:
        old_key = key
    policy_proto = device_management_backend_pb2.PolicyFetchResponse()
    policy_proto.policy_data = policy
    policy_proto.policy_data_signature = ownership.sign(key, policy)
    policy_proto.new_public_key = pubkey
    policy_proto.new_public_key_signature = ownership.sign(old_key, pubkey)
    return policy_proto.SerializeToString()


def push_policy_and_verify(policy_string, sm):
    """Push a device policy to the session manager over DBus.

    The serialized device policy |policy_string| is sent to the session
    manager with the StorePolicy DBus call.  Success of the store is
    validated by fetching the policy again and comparing.

    @param policy_string: serialized policy to push to the session manager.
    @param sm: a connected SessionManagerInterface.

    @raises error.TestFail if policy push failed.
    """
    listener = session_manager.OwnershipSignalListener(gobject.MainLoop())
    listener.listen_for_new_policy()
    sm.StorePolicy(dbus.ByteArray(policy_string), byte_arrays=True)
    listener.wait_for_signals(desc='Policy push.')

    retrieved_policy = sm.RetrievePolicy(byte_arrays=True)
    if retrieved_policy != policy_string:
        raise error.TestFail('Policy should not be %s' % retrieved_policy)


def get_policy(sm):
    """Get a device policy from the session manager over DBus.

    Provided mainly for symmetry with push_policy_and_verify().

    @param sm: a connected SessionManagerInterface.

    @return Serialized PolicyFetchResponse.
    """
    return sm.RetrievePolicy(byte_arrays=True)
