Chromium Code Reviews| 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 #ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ | 4 #ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ |
| 5 #define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ | 5 #define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 // The class member info_ is accessed on multiple threads, but that the whole | 33 // The class member info_ is accessed on multiple threads, but that the whole |
| 34 // class is being guarded by SystemInfoProvider. | 34 // class is being guarded by SystemInfoProvider. |
| 35 template<class T> | 35 template<class T> |
| 36 class SystemInfoProvider | 36 class SystemInfoProvider |
| 37 : public base::RefCountedThreadSafe<SystemInfoProvider<T> > { | 37 : public base::RefCountedThreadSafe<SystemInfoProvider<T> > { |
| 38 public: | 38 public: |
| 39 // Callback type for completing to get information. The callback accepts | 39 // Callback type for completing to get information. The callback accepts |
| 40 // two arguments. The first one is the information got already, the second | 40 // two arguments. The first one is the information got already, the second |
| 41 // one indicates whether its contents are valid, for example, no error | 41 // one indicates whether its contents are valid, for example, no error |
| 42 // occurs in querying the information. | 42 // occurs in querying the information. |
| 43 typedef base::Callback<void(const T&, bool)> QueryInfoCompletionCallback; | 43 typedef base::Callback<void(bool)> QueryInfoCompletionCallback; |
| 44 typedef std::queue<QueryInfoCompletionCallback> CallbackQueue; | 44 typedef std::queue<QueryInfoCompletionCallback> CallbackQueue; |
| 45 | 45 |
| 46 SystemInfoProvider() | 46 SystemInfoProvider() |
| 47 : is_waiting_for_completion_(false) { | 47 : is_waiting_for_completion_(false), |
| 48 worker_pool_token_ = | 48 success_(false) {} |
| 49 content::BrowserThread::GetBlockingPool()->GetSequenceToken(); | |
| 50 } | |
| 51 | 49 |
| 52 virtual ~SystemInfoProvider() {} | 50 virtual ~SystemInfoProvider() {} |
| 53 | 51 |
| 54 // For testing | 52 // For testing |
| 55 static void InitializeForTesting( | 53 static void InitializeForTesting( |
| 56 scoped_refptr<SystemInfoProvider<T> > provider) { | 54 scoped_refptr<SystemInfoProvider<T> > provider) { |
| 57 DCHECK(provider.get() != NULL); | 55 DCHECK(provider.get() != NULL); |
| 58 single_shared_provider_.Get() = provider; | 56 single_shared_provider_.Get() = provider; |
| 59 } | 57 } |
| 60 | 58 |
| 61 // Start to query the system information. Should be called on UI thread. | 59 // Start to query the system information. Should be called on UI thread. |
| 62 // The |callback| will get called once the query is completed. | 60 // The |callback| will get called once the query is completed. |
| 63 void StartQueryInfo(const QueryInfoCompletionCallback& callback) { | 61 void StartQueryInfo(const QueryInfoCompletionCallback& callback) { |
| 64 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 62 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 65 DCHECK(!callback.is_null()); | 63 DCHECK(!callback.is_null()); |
| 66 | 64 |
| 67 callbacks_.push(callback); | 65 callbacks_.push(callback); |
| 68 | 66 |
| 69 if (is_waiting_for_completion_) | 67 if (is_waiting_for_completion_) |
| 70 return; | 68 return; |
| 71 | 69 |
| 72 is_waiting_for_completion_ = true; | 70 is_waiting_for_completion_ = true; |
| 73 | 71 |
| 74 StartQueryInfoImpl(); | 72 StartQueryInfoImpl(); |
| 75 } | 73 } |
| 76 | 74 |
| 77 protected: | 75 protected: |
| 78 // Default implementation of querying system information. | 76 // Default implementation of querying system information. |
| 79 virtual void StartQueryInfoImpl() { | 77 virtual void StartQueryInfoImpl() { |
| 80 base::Closure callback = | 78 // Post a task to blocking pool for information querying and reply with |
| 81 base::Bind(&SystemInfoProvider<T>::QueryOnWorkerPool, this); | 79 // OnQueryCompleted. |
| 82 PostQueryTaskToBlockingPool(FROM_HERE, callback); | 80 content::BrowserThread::PostBlockingPoolTaskAndReply(FROM_HERE, |
| 81 base::Bind(&SystemInfoProvider<T>::QueryInfo, this), | |
| 82 base::Bind(&SystemInfoProvider<T>::OnQueryCompleted, this)); | |
| 83 } | 83 } |
| 84 | 84 |
| 85 // Post a task to blocking pool for information querying. | 85 // Query the system information synchronously and the result is info_. |
| 86 void PostQueryTaskToBlockingPool(const tracked_objects::Location& from_here, | 86 virtual void QueryInfo() = 0; |
| 87 const base::Closure& query_callback) { | |
| 88 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 89 base::SequencedWorkerPool* worker_pool = | |
| 90 content::BrowserThread::GetBlockingPool(); | |
| 91 // The query task posted to the worker pool won't block shutdown, and any | |
| 92 // running query task at shutdown time will be ignored. | |
| 93 worker_pool->PostSequencedWorkerTaskWithShutdownBehavior( | |
| 94 worker_pool_token_, from_here, query_callback, | |
| 95 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | |
| 96 } | |
| 97 | |
| 98 // Query the system information synchronously and output the result to the | |
| 99 // |info| parameter. The |info| contents MUST be reset firstly in its | |
| 100 // platform specific implementation. Return true if it succeeds, otherwise | |
| 101 // false is returned. | |
| 102 // TODO(Haojian): Remove the parameter T-typed pointer. | |
| 103 virtual bool QueryInfo(T* info) = 0; | |
| 104 | |
| 105 // TODO(Haojian): Use PostBlockingPoolTaskAndReply to avoid unnecessary | |
| 106 // trampolines trip. | |
| 107 virtual void QueryOnWorkerPool() { | |
| 108 bool success = QueryInfo(&info_); | |
| 109 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 110 base::Bind(&SystemInfoProvider<T>::OnQueryCompleted, this, success)); | |
| 111 } | |
| 112 | 87 |
| 113 // Called on UI thread. The |success| parameter means whether it succeeds | 88 // Called on UI thread. The |success| parameter means whether it succeeds |
| 114 // to get the information. | 89 // to get the information. |
| 115 virtual void OnQueryCompleted(bool success) { | 90 virtual void OnQueryCompleted() { |
| 116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 91 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 117 | 92 |
| 118 while (!callbacks_.empty()) { | 93 while (!callbacks_.empty()) { |
| 119 QueryInfoCompletionCallback callback = callbacks_.front(); | 94 QueryInfoCompletionCallback callback = callbacks_.front(); |
| 120 callback.Run(info_, success); | 95 callback.Run(success_); |
| 121 callbacks_.pop(); | 96 callbacks_.pop(); |
| 122 } | 97 } |
| 123 | 98 |
| 99 // Reset success_ flag. | |
| 100 success_ = false; | |
|
Hongbo Min
2013/07/01 10:23:41
why to keep a member for success flag instead of t
Haojian Wu
2013/07/01 15:16:42
Since we are using PostBlockingPoolTaskAndReply fu
Hongbo Min
2013/07/02 00:57:58
If that is the only reason to let QueryInfo return
Haojian Wu
2013/07/05 03:01:34
Done.
| |
| 101 | |
| 124 is_waiting_for_completion_ = false; | 102 is_waiting_for_completion_ = false; |
| 125 } | 103 } |
| 126 | 104 |
| 127 // Template function for creating the single shared provider instance. | 105 // Template function for creating the single shared provider instance. |
| 128 // Template paramter I is the type of SystemInfoProvider implementation. | 106 // Template paramter I is the type of SystemInfoProvider implementation. |
| 129 template<class I> | 107 template<class I> |
| 130 static I* GetInstance() { | 108 static I* GetInstance() { |
| 131 if (!single_shared_provider_.Get().get()) | 109 if (!single_shared_provider_.Get().get()) |
| 132 single_shared_provider_.Get() = new I(); | 110 single_shared_provider_.Get() = new I(); |
| 133 return static_cast<I*>(single_shared_provider_.Get().get()); | 111 return static_cast<I*>(single_shared_provider_.Get().get()); |
| 134 } | 112 } |
| 135 | 113 |
| 136 // The latest information filled up by QueryInfo implementation. Here we | 114 // The latest information filled up by QueryInfo implementation. Here we |
| 137 // assume the T is disallowed to copy constructor, aligns with the structure | 115 // assume the T is disallowed to copy constructor, aligns with the structure |
| 138 // type generated by IDL parser. | 116 // type generated by IDL parser. |
| 139 T info_; | 117 T info_; |
| 140 | 118 |
| 119 // Record the last QueryInfo function call whether processed successfully. | |
| 120 bool success_; | |
| 121 | |
| 141 private: | 122 private: |
| 142 // The single shared provider instance. We create it only when needed. | 123 // The single shared provider instance. We create it only when needed. |
| 143 static typename base::LazyInstance< | 124 static typename base::LazyInstance< |
| 144 scoped_refptr<SystemInfoProvider<T> > > single_shared_provider_; | 125 scoped_refptr<SystemInfoProvider<T> > > single_shared_provider_; |
| 145 | 126 |
| 146 // The queue of callbacks waiting for the info querying completion. It is | 127 // The queue of callbacks waiting for the info querying completion. It is |
| 147 // maintained on the UI thread. | 128 // maintained on the UI thread. |
| 148 CallbackQueue callbacks_; | 129 CallbackQueue callbacks_; |
| 149 | 130 |
| 150 // Indicates if it is waiting for the querying completion. | 131 // Indicates if it is waiting for the querying completion. |
| 151 bool is_waiting_for_completion_; | 132 bool is_waiting_for_completion_; |
| 152 | 133 |
| 153 // Unqiue sequence token so that the operation of querying inforation can | |
| 154 // be executed in order. | |
| 155 base::SequencedWorkerPool::SequenceToken worker_pool_token_; | |
| 156 | |
| 157 DISALLOW_COPY_AND_ASSIGN(SystemInfoProvider<T>); | 134 DISALLOW_COPY_AND_ASSIGN(SystemInfoProvider<T>); |
| 158 }; | 135 }; |
| 159 | 136 |
| 160 // Static member intialization. | 137 // Static member intialization. |
| 161 template<class T> | 138 template<class T> |
| 162 typename base::LazyInstance<scoped_refptr<SystemInfoProvider<T> > > | 139 typename base::LazyInstance<scoped_refptr<SystemInfoProvider<T> > > |
| 163 SystemInfoProvider<T>::single_shared_provider_ = LAZY_INSTANCE_INITIALIZER; | 140 SystemInfoProvider<T>::single_shared_provider_ = LAZY_INSTANCE_INITIALIZER; |
| 164 | 141 |
| 165 } // namespace extensions | 142 } // namespace extensions |
| 166 | 143 |
| 167 #endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ | 144 #endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ |
| OLD | NEW |