1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/policy/policy_notifier.h"
6
7namespace policy {
8
9void PolicyNotifier::AddObserver(CloudPolicySubsystem::Observer* observer) {
10  observer_list_.AddObserver(observer);
11}
12
13void PolicyNotifier::RemoveObserver(CloudPolicySubsystem::Observer* observer) {
14  observer_list_.RemoveObserver(observer);
15}
16
17PolicyNotifier::PolicyNotifier()
18    : state_(CloudPolicySubsystem::UNENROLLED),
19      error_details_(CloudPolicySubsystem::NO_DETAILS) {
20  for (int i = 0; i < NUM_SOURCES; ++i) {
21    component_states_[i] = CloudPolicySubsystem::UNENROLLED;
22    component_error_details_[i] = CloudPolicySubsystem::NO_DETAILS;
23  }
24}
25
26PolicyNotifier::~PolicyNotifier() {
27}
28
29void PolicyNotifier::Inform(PolicySubsystemState state,
30                            ErrorDetails error_details,
31                            StatusSource source) {
32  component_states_[source] = state;
33  component_error_details_[source] = error_details;
34  RecomputeState();
35}
36
37void PolicyNotifier::RecomputeState() {
38  // Define shortcuts.
39  PolicySubsystemState* s = component_states_;
40  ErrorDetails* e = component_error_details_;
41
42  // Compute overall state. General idea: If any component knows we're
43  // unmanaged, set that as global state. Otherwise, ask components in the
44  // order they normally do work in. If anyone reports 'SUCCESS' or 'UNENROLLED'
45  // (which can also be read as 'undefined/unknown', ask the next component.
46  if (s[TOKEN_FETCHER] == CloudPolicySubsystem::UNMANAGED ||
47      s[POLICY_CONTROLLER] == CloudPolicySubsystem::UNMANAGED ||
48      s[POLICY_CACHE] == CloudPolicySubsystem::UNMANAGED) {
49    state_ = CloudPolicySubsystem::UNMANAGED;
50    error_details_ = CloudPolicySubsystem::NO_DETAILS;
51  } else if (s[TOKEN_FETCHER] == CloudPolicySubsystem::NETWORK_ERROR) {
52    state_ = s[TOKEN_FETCHER];
53    error_details_ = e[TOKEN_FETCHER];
54  } else if (s[TOKEN_FETCHER] ==  CloudPolicySubsystem::BAD_GAIA_TOKEN) {
55    state_ = s[TOKEN_FETCHER];
56    error_details_ = e[TOKEN_FETCHER];
57  } else if (s[POLICY_CONTROLLER] == CloudPolicySubsystem::NETWORK_ERROR) {
58    state_ = s[POLICY_CONTROLLER];
59    error_details_ = e[POLICY_CONTROLLER];
60  } else if (s[TOKEN_FETCHER] == CloudPolicySubsystem::SUCCESS &&
61             s[POLICY_CONTROLLER] != CloudPolicySubsystem::SUCCESS) {
62    // We need to be able to differentiate between token fetch success or
63    // policy fetch success.
64    state_ = CloudPolicySubsystem::TOKEN_FETCHED;
65    error_details_ = CloudPolicySubsystem::NO_DETAILS;
66  } else {
67    state_ = s[POLICY_CACHE];
68    error_details_ = e[POLICY_CACHE];
69  }
70
71  FOR_EACH_OBSERVER(CloudPolicySubsystem::Observer, observer_list_,
72                    OnPolicyStateChanged(state_, error_details_));
73}
74
75}  // namespace policy
76