1// Copyright 2013 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/web_resource/resource_request_allowed_notifier.h"
6
7#include "base/command_line.h"
8#include "chrome/common/chrome_switches.h"
9
10ResourceRequestAllowedNotifier::ResourceRequestAllowedNotifier()
11    : observer_requested_permission_(false),
12      waiting_for_network_(false),
13      waiting_for_user_to_accept_eula_(false),
14      observer_(NULL) {
15}
16
17ResourceRequestAllowedNotifier::~ResourceRequestAllowedNotifier() {
18  if (observer_)
19    net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
20}
21
22void ResourceRequestAllowedNotifier::Init(Observer* observer) {
23  DCHECK(!observer_ && observer);
24  observer_ = observer;
25
26  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
27
28  // Check this state during initialization. It is not expected to change until
29  // the corresponding notification is received.
30  waiting_for_network_ = net::NetworkChangeNotifier::IsOffline();
31
32  eula_notifier_.reset(CreateEulaNotifier());
33  if (eula_notifier_) {
34    eula_notifier_->Init(this);
35    waiting_for_user_to_accept_eula_ = !eula_notifier_->IsEulaAccepted();
36  }
37}
38
39ResourceRequestAllowedNotifier::State
40    ResourceRequestAllowedNotifier::GetResourceRequestsAllowedState() {
41  if (CommandLine::ForCurrentProcess()->HasSwitch(
42      switches::kDisableBackgroundNetworking)) {
43    return DISALLOWED_COMMAND_LINE_DISABLED;
44  }
45
46  // The observer requested permission. Return the current criteria state and
47  // set a flag to remind this class to notify the observer once the criteria
48  // is met.
49  observer_requested_permission_ = waiting_for_user_to_accept_eula_ ||
50                                   waiting_for_network_;
51  if (!observer_requested_permission_)
52    return ALLOWED;
53  return waiting_for_user_to_accept_eula_ ? DISALLOWED_EULA_NOT_ACCEPTED :
54                                            DISALLOWED_NETWORK_DOWN;
55}
56
57bool ResourceRequestAllowedNotifier::ResourceRequestsAllowed() {
58  return GetResourceRequestsAllowedState() == ALLOWED;
59}
60
61void ResourceRequestAllowedNotifier::SetWaitingForNetworkForTesting(
62    bool waiting) {
63  waiting_for_network_ = waiting;
64}
65
66void ResourceRequestAllowedNotifier::SetWaitingForEulaForTesting(
67    bool waiting) {
68  waiting_for_user_to_accept_eula_ = waiting;
69}
70
71void ResourceRequestAllowedNotifier::SetObserverRequestedForTesting(
72    bool requested) {
73  observer_requested_permission_ = requested;
74}
75
76void ResourceRequestAllowedNotifier::MaybeNotifyObserver() {
77  // Need to ensure that all criteria are met before notifying observers.
78  if (observer_requested_permission_ && ResourceRequestsAllowed()) {
79    DVLOG(1) << "Notifying observer of state change.";
80    observer_->OnResourceRequestsAllowed();
81    // Reset this so the observer is not informed again unless they check
82    // ResourceRequestsAllowed again.
83    observer_requested_permission_ = false;
84  }
85}
86
87EulaAcceptedNotifier* ResourceRequestAllowedNotifier::CreateEulaNotifier() {
88  return EulaAcceptedNotifier::Create();
89}
90
91void ResourceRequestAllowedNotifier::OnEulaAccepted() {
92  // This flag should have been set if this was waiting on the EULA
93  // notification.
94  DCHECK(waiting_for_user_to_accept_eula_);
95  DVLOG(1) << "EULA was accepted.";
96  waiting_for_user_to_accept_eula_ = false;
97  MaybeNotifyObserver();
98}
99
100void ResourceRequestAllowedNotifier::OnConnectionTypeChanged(
101    net::NetworkChangeNotifier::ConnectionType type) {
102  // Only attempt to notify observers if this was previously waiting for the
103  // network to reconnect, and new network state is actually available. This
104  // prevents the notifier from notifying the observer if the notifier was never
105  // waiting on the network, or if the network changes from one online state
106  // to another (for example, Wifi to 3G, or Wifi to Wifi, if the network were
107  // flaky).
108  if (waiting_for_network_ &&
109      type != net::NetworkChangeNotifier::CONNECTION_NONE) {
110    waiting_for_network_ = false;
111    DVLOG(1) << "Network came back online.";
112    MaybeNotifyObserver();
113  } else if (!waiting_for_network_ &&
114             type == net::NetworkChangeNotifier::CONNECTION_NONE) {
115    waiting_for_network_ = true;
116    DVLOG(1) << "Network went offline.";
117  }
118}
119