1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/async_policy_provider.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/location.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/sequenced_task_runner.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/async_policy_loader.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_bundle.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/schema_registry.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AsyncPolicyProvider::AsyncPolicyProvider( 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SchemaRegistry* registry, 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<AsyncPolicyLoader> loader) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : loader_(loader.release()), 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make an immediate synchronous load on startup. 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OnLoaderReloaded(loader_->InitialLoad(registry->schema_map())); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AsyncPolicyProvider::~AsyncPolicyProvider() { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown() must have been called before. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!loader_); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AsyncPolicyProvider::Init(SchemaRegistry* registry) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConfigurationPolicyProvider::Init(registry); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!loader_) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsyncPolicyLoader::UpdateCallback callback = 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AsyncPolicyProvider::LoaderUpdateCallback, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MessageLoopProxy::current(), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.GetWeakPtr()); 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool post = loader_->task_runner()->PostTask( 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FROM_HERE, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AsyncPolicyLoader::Init, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(loader_), 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback)); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(post) << "AsyncPolicyProvider::Init() called with threads not running"; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsyncPolicyProvider::Shutdown() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note on the lifetime of |loader_|: 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The |loader_| lives on the background thread, and is deleted from here. 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // This means that posting tasks on the |loader_| to the background thread 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // from the AsyncPolicyProvider is always safe, since a potential DeleteSoon() 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // is only posted from here. The |loader_| posts back to the 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // AsyncPolicyProvider through the |update_callback_|, which has a WeakPtr to 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // |this|. 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!loader_->task_runner()->DeleteSoon(FROM_HERE, loader_)) { 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The background thread doesn't exist; this only happens on unit tests. 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete loader_; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loader_ = NULL; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConfigurationPolicyProvider::Shutdown(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsyncPolicyProvider::RefreshPolicies() { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subtle: RefreshPolicies() has a contract that requires the next policy 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update notification (triggered from UpdatePolicy()) to reflect any changes 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // made before this call. So if a caller has modified the policy settings and 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invoked RefreshPolicies(), then by the next notification these policies 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should already be provided. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, it's also possible that an asynchronous Reload() is in progress 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and just posted OnLoaderReloaded(). Therefore a task is posted to the 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // background thread before posting the next Reload, to prevent a potential 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // concurrent Reload() from triggering a notification too early. If another 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // refresh task has been posted, it is invalidated now. 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!loader_) 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_callback_.Reset( 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AsyncPolicyProvider::ReloadAfterRefreshSync, 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) weak_factory_.GetWeakPtr())); 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) loader_->task_runner()->PostTaskAndReply( 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FROM_HERE, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(base::DoNothing), 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_callback_.callback()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsyncPolicyProvider::ReloadAfterRefreshSync() { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This task can only enter if it was posted from RefreshPolicies(), and it 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hasn't been cancelled meanwhile by another call to RefreshPolicies(). 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!refresh_callback_.IsCancelled()); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There can't be another refresh callback pending now, since its creation 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in RefreshPolicies() would have cancelled the current execution. So it's 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // safe to cancel the |refresh_callback_| now, so that OnLoaderReloaded() 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sees that there is no refresh pending. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) refresh_callback_.Cancel(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!loader_) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) loader_->task_runner()->PostTask( 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&AsyncPolicyLoader::RefreshPolicies, 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Unretained(loader_), 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) schema_map())); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsyncPolicyProvider::OnLoaderReloaded(scoped_ptr<PolicyBundle> bundle) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only propagate policy updates if there are no pending refreshes, and if 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown() hasn't been called yet. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (refresh_callback_.IsCancelled() && loader_) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdatePolicy(bundle.Pass()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AsyncPolicyProvider::LoaderUpdateCallback( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::MessageLoopProxy> loop, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtr<AsyncPolicyProvider> weak_this, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<PolicyBundle> bundle) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loop->PostTask(FROM_HERE, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AsyncPolicyProvider::OnLoaderReloaded, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_this, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Passed(&bundle))); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 135