OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/policy/core/common/async_policy_provider.h" | 5 #include "components/policy/core/common/async_policy_provider.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/sequenced_task_runner.h" | 12 #include "base/sequenced_task_runner.h" |
13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
15 #include "components/policy/core/common/async_policy_loader.h" | 15 #include "components/policy/core/common/async_policy_loader.h" |
16 #include "components/policy/core/common/policy_bundle.h" | 16 #include "components/policy/core/common/policy_bundle.h" |
17 #include "components/policy/core/common/schema_registry.h" | 17 #include "components/policy/core/common/schema_registry.h" |
18 | 18 |
19 namespace policy { | 19 namespace policy { |
20 | 20 |
21 AsyncPolicyProvider::AsyncPolicyProvider( | 21 AsyncPolicyProvider::AsyncPolicyProvider( |
22 SchemaRegistry* registry, | 22 SchemaRegistry* registry, |
23 std::unique_ptr<AsyncPolicyLoader> loader) | 23 std::unique_ptr<AsyncPolicyLoader> loader) |
24 : loader_(std::move(loader)), weak_factory_(this) { | 24 : loader_(std::move(loader)), weak_factory_(this) { |
25 // Make an immediate synchronous load on startup. | 25 // Make an immediate synchronous load on startup. |
26 OnLoaderReloaded(loader_->InitialLoad(registry->schema_map())); | 26 OnLoaderReloaded(loader_->InitialLoad(registry->schema_map())); |
27 } | 27 } |
28 | 28 |
29 AsyncPolicyProvider::~AsyncPolicyProvider() { | 29 AsyncPolicyProvider::~AsyncPolicyProvider() { |
30 DCHECK(CalledOnValidThread()); | 30 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
31 } | 31 } |
32 | 32 |
33 void AsyncPolicyProvider::Init(SchemaRegistry* registry) { | 33 void AsyncPolicyProvider::Init(SchemaRegistry* registry) { |
34 DCHECK(CalledOnValidThread()); | 34 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
35 ConfigurationPolicyProvider::Init(registry); | 35 ConfigurationPolicyProvider::Init(registry); |
36 | 36 |
37 if (!loader_) | 37 if (!loader_) |
38 return; | 38 return; |
39 | 39 |
40 AsyncPolicyLoader::UpdateCallback callback = | 40 AsyncPolicyLoader::UpdateCallback callback = |
41 base::Bind(&AsyncPolicyProvider::LoaderUpdateCallback, | 41 base::Bind(&AsyncPolicyProvider::LoaderUpdateCallback, |
42 base::ThreadTaskRunnerHandle::Get(), | 42 base::ThreadTaskRunnerHandle::Get(), |
43 weak_factory_.GetWeakPtr()); | 43 weak_factory_.GetWeakPtr()); |
44 bool post = loader_->task_runner()->PostTask( | 44 bool post = loader_->task_runner()->PostTask( |
45 FROM_HERE, | 45 FROM_HERE, |
46 base::Bind(&AsyncPolicyLoader::Init, | 46 base::Bind(&AsyncPolicyLoader::Init, |
47 base::Unretained(loader_.get()), | 47 base::Unretained(loader_.get()), |
48 callback)); | 48 callback)); |
49 DCHECK(post) << "AsyncPolicyProvider::Init() called with threads not running"; | 49 DCHECK(post) << "AsyncPolicyProvider::Init() called with threads not running"; |
50 } | 50 } |
51 | 51 |
52 void AsyncPolicyProvider::Shutdown() { | 52 void AsyncPolicyProvider::Shutdown() { |
53 DCHECK(CalledOnValidThread()); | 53 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
54 // Note on the lifetime of |loader_|: | 54 // Note on the lifetime of |loader_|: |
55 // The |loader_| lives on the background thread, and is deleted from here. | 55 // The |loader_| lives on the background thread, and is deleted from here. |
56 // This means that posting tasks on the |loader_| to the background thread | 56 // This means that posting tasks on the |loader_| to the background thread |
57 // from the AsyncPolicyProvider is always safe, since a potential DeleteSoon() | 57 // from the AsyncPolicyProvider is always safe, since a potential DeleteSoon() |
58 // is only posted from here. The |loader_| posts back to the | 58 // is only posted from here. The |loader_| posts back to the |
59 // AsyncPolicyProvider through the |update_callback_|, which has a WeakPtr to | 59 // AsyncPolicyProvider through the |update_callback_|, which has a WeakPtr to |
60 // |this|. | 60 // |this|. |
61 // If threads are spinning, delete the loader on the thread it lives on. If | 61 // If threads are spinning, delete the loader on the thread it lives on. If |
62 // there are no threads, kill it immediately. | 62 // there are no threads, kill it immediately. |
63 AsyncPolicyLoader* loader_to_delete = loader_.release(); | 63 AsyncPolicyLoader* loader_to_delete = loader_.release(); |
64 if (!loader_to_delete->task_runner()->DeleteSoon(FROM_HERE, loader_to_delete)) | 64 if (!loader_to_delete->task_runner()->DeleteSoon(FROM_HERE, loader_to_delete)) |
65 delete loader_to_delete; | 65 delete loader_to_delete; |
66 ConfigurationPolicyProvider::Shutdown(); | 66 ConfigurationPolicyProvider::Shutdown(); |
67 } | 67 } |
68 | 68 |
69 void AsyncPolicyProvider::RefreshPolicies() { | 69 void AsyncPolicyProvider::RefreshPolicies() { |
70 DCHECK(CalledOnValidThread()); | 70 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
71 | 71 |
72 // Subtle: RefreshPolicies() has a contract that requires the next policy | 72 // Subtle: RefreshPolicies() has a contract that requires the next policy |
73 // update notification (triggered from UpdatePolicy()) to reflect any changes | 73 // update notification (triggered from UpdatePolicy()) to reflect any changes |
74 // made before this call. So if a caller has modified the policy settings and | 74 // made before this call. So if a caller has modified the policy settings and |
75 // invoked RefreshPolicies(), then by the next notification these policies | 75 // invoked RefreshPolicies(), then by the next notification these policies |
76 // should already be provided. | 76 // should already be provided. |
77 // However, it's also possible that an asynchronous Reload() is in progress | 77 // However, it's also possible that an asynchronous Reload() is in progress |
78 // and just posted OnLoaderReloaded(). Therefore a task is posted to the | 78 // and just posted OnLoaderReloaded(). Therefore a task is posted to the |
79 // background thread before posting the next Reload, to prevent a potential | 79 // background thread before posting the next Reload, to prevent a potential |
80 // concurrent Reload() from triggering a notification too early. If another | 80 // concurrent Reload() from triggering a notification too early. If another |
81 // refresh task has been posted, it is invalidated now. | 81 // refresh task has been posted, it is invalidated now. |
82 if (!loader_) | 82 if (!loader_) |
83 return; | 83 return; |
84 refresh_callback_.Reset( | 84 refresh_callback_.Reset( |
85 base::Bind(&AsyncPolicyProvider::ReloadAfterRefreshSync, | 85 base::Bind(&AsyncPolicyProvider::ReloadAfterRefreshSync, |
86 weak_factory_.GetWeakPtr())); | 86 weak_factory_.GetWeakPtr())); |
87 loader_->task_runner()->PostTaskAndReply( | 87 loader_->task_runner()->PostTaskAndReply( |
88 FROM_HERE, | 88 FROM_HERE, |
89 base::Bind(base::DoNothing), | 89 base::Bind(base::DoNothing), |
90 refresh_callback_.callback()); | 90 refresh_callback_.callback()); |
91 } | 91 } |
92 | 92 |
93 void AsyncPolicyProvider::ReloadAfterRefreshSync() { | 93 void AsyncPolicyProvider::ReloadAfterRefreshSync() { |
94 DCHECK(CalledOnValidThread()); | 94 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
95 // This task can only enter if it was posted from RefreshPolicies(), and it | 95 // This task can only enter if it was posted from RefreshPolicies(), and it |
96 // hasn't been cancelled meanwhile by another call to RefreshPolicies(). | 96 // hasn't been cancelled meanwhile by another call to RefreshPolicies(). |
97 DCHECK(!refresh_callback_.IsCancelled()); | 97 DCHECK(!refresh_callback_.IsCancelled()); |
98 // There can't be another refresh callback pending now, since its creation | 98 // There can't be another refresh callback pending now, since its creation |
99 // in RefreshPolicies() would have cancelled the current execution. So it's | 99 // in RefreshPolicies() would have cancelled the current execution. So it's |
100 // safe to cancel the |refresh_callback_| now, so that OnLoaderReloaded() | 100 // safe to cancel the |refresh_callback_| now, so that OnLoaderReloaded() |
101 // sees that there is no refresh pending. | 101 // sees that there is no refresh pending. |
102 refresh_callback_.Cancel(); | 102 refresh_callback_.Cancel(); |
103 | 103 |
104 if (!loader_) | 104 if (!loader_) |
105 return; | 105 return; |
106 | 106 |
107 loader_->task_runner()->PostTask( | 107 loader_->task_runner()->PostTask( |
108 FROM_HERE, | 108 FROM_HERE, |
109 base::Bind(&AsyncPolicyLoader::RefreshPolicies, | 109 base::Bind(&AsyncPolicyLoader::RefreshPolicies, |
110 base::Unretained(loader_.get()), | 110 base::Unretained(loader_.get()), |
111 schema_map())); | 111 schema_map())); |
112 } | 112 } |
113 | 113 |
114 void AsyncPolicyProvider::OnLoaderReloaded( | 114 void AsyncPolicyProvider::OnLoaderReloaded( |
115 std::unique_ptr<PolicyBundle> bundle) { | 115 std::unique_ptr<PolicyBundle> bundle) { |
116 DCHECK(CalledOnValidThread()); | 116 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
117 // Only propagate policy updates if there are no pending refreshes, and if | 117 // Only propagate policy updates if there are no pending refreshes, and if |
118 // Shutdown() hasn't been called yet. | 118 // Shutdown() hasn't been called yet. |
119 if (refresh_callback_.IsCancelled() && loader_) | 119 if (refresh_callback_.IsCancelled() && loader_) |
120 UpdatePolicy(std::move(bundle)); | 120 UpdatePolicy(std::move(bundle)); |
121 } | 121 } |
122 | 122 |
123 // static | 123 // static |
124 void AsyncPolicyProvider::LoaderUpdateCallback( | 124 void AsyncPolicyProvider::LoaderUpdateCallback( |
125 scoped_refptr<base::SingleThreadTaskRunner> runner, | 125 scoped_refptr<base::SingleThreadTaskRunner> runner, |
126 base::WeakPtr<AsyncPolicyProvider> weak_this, | 126 base::WeakPtr<AsyncPolicyProvider> weak_this, |
127 std::unique_ptr<PolicyBundle> bundle) { | 127 std::unique_ptr<PolicyBundle> bundle) { |
128 runner->PostTask(FROM_HERE, | 128 runner->PostTask(FROM_HERE, |
129 base::Bind(&AsyncPolicyProvider::OnLoaderReloaded, | 129 base::Bind(&AsyncPolicyProvider::OnLoaderReloaded, |
130 weak_this, | 130 weak_this, |
131 base::Passed(&bundle))); | 131 base::Passed(&bundle))); |
132 } | 132 } |
133 | 133 |
134 } // namespace policy | 134 } // namespace policy |
OLD | NEW |