| 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 |