Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: chrome/browser/policy/async_policy_provider.cc

Issue 10448118: Add the AsyncPolicyProvider and AsyncPolicyLoader (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Store the MessageLoopProxy in the callback Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/async_policy_provider.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop.h"
10 #include "base/message_loop_proxy.h"
11 #include "chrome/browser/policy/async_policy_loader.h"
12 #include "chrome/browser/policy/policy_bundle.h"
13 #include "content/public/browser/browser_thread.h"
14
15 using content::BrowserThread;
16
17 namespace policy {
18
19 namespace {
20
21 // Helper for a PostTaskAndReply used as a synchronization point between the
22 // main thread and FILE thread. See AsyncPolicyProvider::RefreshPolicies.
23 void Nop() {}
24
25 } // namespace
26
27 AsyncPolicyProvider::AsyncPolicyProvider(
28 const PolicyDefinitionList* policy_list,
29 scoped_ptr<AsyncPolicyLoader> loader)
30 : ConfigurationPolicyProvider(policy_list),
31 loader_(loader.release()),
32 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
33 // The FILE thread isn't ready early during startup. Post a task to the
34 // current loop to resume initialization on FILE once the loops are spinning.
35 MessageLoop::current()->PostTask(
36 FROM_HERE,
37 base::Bind(&AsyncPolicyProvider::InitWithLoopsReady,
38 weak_factory_.GetWeakPtr()));
39 // Make an immediate synchronous load on startup.
40 OnLoaderReloaded(loader_->InitialLoad());
41 }
42
43 AsyncPolicyProvider::~AsyncPolicyProvider() {
44 DCHECK(CalledOnValidThread());
45
46 // Note on the lifetime of |loader_|:
47 // The |loader_| lives on the FILE thread, and is deleted from here. This
48 // means that posting tasks on the |loader_| to FILE from the
49 // AsyncPolicyProvider is always safe, since a potential DeleteSoon() is only
50 // posted from here. The |loader_| posts back to the AsyncPolicyProvider
51 // through the |update_callback_|, which has a WeakPtr to |this|.
52 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, loader_);
53 }
54
55 void AsyncPolicyProvider::RefreshPolicies() {
56 DCHECK(CalledOnValidThread());
57
58 // Subtle: RefreshPolicies() has a contract that requires the next policy
59 // update notification (triggered from UpdatePolicy()) to reflect any changes
60 // made before this call. So if a caller has modified the policy settings and
61 // invoked RefreshPolicies(), then by the next notification these policies
62 // should already be provided.
63 // However, it's also possible that an asynchronous Reload() is in progress
64 // and just posted OnLoaderReloaded(). Therefore a task is posted to the
65 // FILE thread before posting the next Reload, to prevent a potential
66 // concurrent Reload() from triggering a notification too early. If another
67 // refresh task has been posted, it is invalidated now.
68 refresh_callback_.Reset(
69 base::Bind(&AsyncPolicyProvider::ReloadAfterRefreshSync,
70 base::Unretained(this)));
71 BrowserThread::PostTaskAndReply(
72 BrowserThread::FILE, FROM_HERE,
73 base::Bind(Nop),
74 refresh_callback_.callback());
75 }
76
77 void AsyncPolicyProvider::InitWithLoopsReady() {
78 DCHECK(CalledOnValidThread());
79 AsyncPolicyLoader::UpdateCallback callback =
80 base::Bind(&AsyncPolicyProvider::LoaderUpdateCallback,
81 base::MessageLoopProxy::current(),
82 weak_factory_.GetWeakPtr());
83 BrowserThread::PostTask(
84 BrowserThread::FILE, FROM_HERE,
85 base::Bind(&AsyncPolicyLoader::Init,
86 base::Unretained(loader_),
87 callback));
88 }
89
90 void AsyncPolicyProvider::ReloadAfterRefreshSync() {
91 DCHECK(CalledOnValidThread());
92 // This task can only enter if it was posted from RefreshPolicies(), and it
93 // hasn't been cancelled meanwhile by another call to RefreshPolicies().
94 DCHECK(!refresh_callback_.IsCancelled());
95 // There can't be another refresh callback pending now, since its creation
96 // in RefreshPolicies() would have cancelled the current execution. So it's
97 // safe to cancel the |refresh_callback_| now, so that OnLoaderReloaded()
98 // sees that there is no refresh pending.
99 refresh_callback_.Cancel();
100
101 BrowserThread::PostTask(
102 BrowserThread::FILE, FROM_HERE,
103 base::Bind(&AsyncPolicyLoader::Reload,
104 base::Unretained(loader_),
105 true /* force */));
106 }
107
108 void AsyncPolicyProvider::OnLoaderReloaded(scoped_ptr<PolicyBundle> bundle) {
109 DCHECK(CalledOnValidThread());
110 if (refresh_callback_.IsCancelled())
111 UpdatePolicy(bundle.Pass());
112 }
113
114 // static
115 void AsyncPolicyProvider::LoaderUpdateCallback(
116 scoped_refptr<base::MessageLoopProxy> loop,
117 base::WeakPtr<AsyncPolicyProvider> weak_this,
118 scoped_ptr<PolicyBundle> bundle) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
120 loop->PostTask(FROM_HERE,
121 base::Bind(&AsyncPolicyProvider::OnLoaderReloaded,
122 weak_this,
123 base::Passed(&bundle)));
124 }
125
Mattias Nissler (ping if slow) 2012/06/04 18:09:03 remove extra blank line
Joao da Silva 2012/06/05 08:19:21 Done.
126
127 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698