| 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 11 matching lines...) Expand all Loading... |
| 22 // The SystemInfoProvider is designed to query system information on the worker | 22 // The SystemInfoProvider is designed to query system information on the worker |
| 23 // pool. It also maintains a queue of callbacks on the UI thread which are | 23 // pool. It also maintains a queue of callbacks on the UI thread which are |
| 24 // waiting for the completion of querying operation. Once the query operation | 24 // waiting for the completion of querying operation. Once the query operation |
| 25 // is completed, all pending callbacks in the queue get called on the UI | 25 // is completed, all pending callbacks in the queue get called on the UI |
| 26 // thread. In this way, it avoids frequent querying operation in case of lots | 26 // thread. In this way, it avoids frequent querying operation in case of lots |
| 27 // of query requests, e.g. calling systemInfo.cpu.get repeatedly in an | 27 // of query requests, e.g. calling systemInfo.cpu.get repeatedly in an |
| 28 // extension process. | 28 // extension process. |
| 29 // | 29 // |
| 30 // Template parameter T is the system information type. It could be the | 30 // Template parameter T is the system information type. It could be the |
| 31 // structure type generated by IDL parser. | 31 // structure type generated by IDL parser. |
| 32 // |
| 33 // The class member |info_| is accessed on multiple threads, but that the whole |
| 34 // class is being guarded by SystemInfoProvider. |
| 35 // |
| 36 // |info_| is accessed on the UI thread while |is_waiting_for_completion_| is |
| 37 // false and on the BlockingPool under |worker_pool_token_| while |
| 38 // |is_waiting_for_completion_| is true. |
| 32 template<class T> | 39 template<class T> |
| 33 class SystemInfoProvider | 40 class SystemInfoProvider |
| 34 : public base::RefCountedThreadSafe<SystemInfoProvider<T> > { | 41 : public base::RefCountedThreadSafe<SystemInfoProvider<T> > { |
| 35 public: | 42 public: |
| 36 // Callback type for completing to get information. The callback accepts | 43 // Callback type for completing to get information. The callback accepts |
| 37 // two arguments. The first one is the information got already, the second | 44 // two arguments. The first one is the information got already, the second |
| 38 // one indicates whether its contents are valid, for example, no error | 45 // one indicates whether its contents are valid, for example, no error |
| 39 // occurs in querying the information. | 46 // occurs in querying the information. |
| 40 typedef base::Callback<void(const T&, bool)> QueryInfoCompletionCallback; | 47 typedef base::Callback<void(const T&, bool)> QueryInfoCompletionCallback; |
| 41 typedef std::queue<QueryInfoCompletionCallback> CallbackQueue; | 48 typedef std::queue<QueryInfoCompletionCallback> CallbackQueue; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 61 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 68 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 62 DCHECK(!callback.is_null()); | 69 DCHECK(!callback.is_null()); |
| 63 | 70 |
| 64 callbacks_.push(callback); | 71 callbacks_.push(callback); |
| 65 | 72 |
| 66 if (is_waiting_for_completion_) | 73 if (is_waiting_for_completion_) |
| 67 return; | 74 return; |
| 68 | 75 |
| 69 is_waiting_for_completion_ = true; | 76 is_waiting_for_completion_ = true; |
| 70 | 77 |
| 78 StartQueryInfoImpl(); |
| 79 } |
| 80 |
| 81 protected: |
| 82 // Default implementation of querying system information. |
| 83 // |
| 84 // While overriding, there are two things need to do: |
| 85 // 1). Bind custom callback function for query system information. |
| 86 // 2). Post the custom task to blocking pool. |
| 87 virtual void StartQueryInfoImpl() { |
| 88 base::Closure callback = |
| 89 base::Bind(&SystemInfoProvider<T>::QueryOnWorkerPool, this); |
| 90 PostQueryTaskToBlockingPool(FROM_HERE, callback); |
| 91 } |
| 92 |
| 93 // Post a task to blocking pool for information querying. |
| 94 // |
| 95 // The parameter query_callback should invoke QueryInfo directly or indirectly |
| 96 // to query the system information and return to UI thread when the query is |
| 97 // completed. |
| 98 void PostQueryTaskToBlockingPool(const tracked_objects::Location& from_here, |
| 99 const base::Closure& query_callback) { |
| 100 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 71 base::SequencedWorkerPool* worker_pool = | 101 base::SequencedWorkerPool* worker_pool = |
| 72 content::BrowserThread::GetBlockingPool(); | 102 content::BrowserThread::GetBlockingPool(); |
| 73 // The query task posted to the worker pool won't block shutdown, and any | 103 // The query task posted to the worker pool won't block shutdown, and any |
| 74 // running query task at shutdown time will be ignored. | 104 // running query task at shutdown time will be ignored. |
| 75 worker_pool->PostSequencedWorkerTaskWithShutdownBehavior( | 105 worker_pool->PostSequencedWorkerTaskWithShutdownBehavior( |
| 76 worker_pool_token_, | 106 worker_pool_token_, from_here, query_callback, |
| 77 FROM_HERE, | |
| 78 base::Bind(&SystemInfoProvider<T>::QueryOnWorkerPool, this), | |
| 79 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | 107 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 80 } | 108 } |
| 81 | 109 |
| 82 protected: | |
| 83 // Query the system information synchronously and output the result to the | 110 // Query the system information synchronously and output the result to the |
| 84 // |info| parameter. The |info| contents MUST be reset firstly in its | 111 // |info| parameter. The |info| contents MUST be reset firstly in its |
| 85 // platform specific implementation. Return true if it succeeds, otherwise | 112 // platform specific implementation. Return true if it succeeds, otherwise |
| 86 // false is returned. | 113 // false is returned. |
| 114 // TODO(Haojian): Remove the parameter T-typed pointer, replacing with void |
| 115 // QueryInfo(). |
| 87 virtual bool QueryInfo(T* info) = 0; | 116 virtual bool QueryInfo(T* info) = 0; |
| 88 | 117 |
| 89 virtual void QueryOnWorkerPool() { | |
| 90 bool success = QueryInfo(&info_); | |
| 91 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 92 base::Bind(&SystemInfoProvider<T>::OnQueryCompleted, this, success)); | |
| 93 } | |
| 94 | |
| 95 // Called on UI thread. The |success| parameter means whether it succeeds | 118 // Called on UI thread. The |success| parameter means whether it succeeds |
| 96 // to get the information. | 119 // to get the information. |
| 97 virtual void OnQueryCompleted(bool success) { | 120 void OnQueryCompleted(bool success) { |
| 98 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 121 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 99 | 122 |
| 100 while (!callbacks_.empty()) { | 123 while (!callbacks_.empty()) { |
| 101 QueryInfoCompletionCallback callback = callbacks_.front(); | 124 QueryInfoCompletionCallback callback = callbacks_.front(); |
| 102 callback.Run(info_, success); | 125 callback.Run(info_, success); |
| 103 callbacks_.pop(); | 126 callbacks_.pop(); |
| 104 } | 127 } |
| 105 | 128 |
| 106 is_waiting_for_completion_ = false; | 129 is_waiting_for_completion_ = false; |
| 107 } | 130 } |
| 108 | 131 |
| 109 // Template function for creating the single shared provider instance. | 132 // Template function for creating the single shared provider instance. |
| 110 // Template paramter I is the type of SystemInfoProvider implementation. | 133 // Template paramter I is the type of SystemInfoProvider implementation. |
| 111 template<class I> | 134 template<class I> |
| 112 static I* GetInstance() { | 135 static I* GetInstance() { |
| 113 if (!single_shared_provider_.Get().get()) | 136 if (!single_shared_provider_.Get().get()) |
| 114 single_shared_provider_.Get() = new I(); | 137 single_shared_provider_.Get() = new I(); |
| 115 return static_cast<I*>(single_shared_provider_.Get().get()); | 138 return static_cast<I*>(single_shared_provider_.Get().get()); |
| 116 } | 139 } |
| 117 | 140 |
| 118 // The latest information filled up by QueryInfo implementation. Here we | 141 // The latest information filled up by QueryInfo implementation. Here we |
| 119 // assume the T is disallowed to copy constructor, aligns with the structure | 142 // assume the T is disallowed to copy constructor, aligns with the structure |
| 120 // type generated by IDL parser. | 143 // type generated by IDL parser. |
| 121 T info_; | 144 T info_; |
| 122 | 145 |
| 123 private: | 146 private: |
| 147 // TODO(Haojian): Use PostBlockingPoolTaskAndReply to avoid unnecessary |
| 148 // trampolines trip. |
| 149 void QueryOnWorkerPool() { |
| 150 bool success = QueryInfo(&info_); |
| 151 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 152 base::Bind(&SystemInfoProvider<T>::OnQueryCompleted, this, success)); |
| 153 } |
| 154 |
| 124 // The single shared provider instance. We create it only when needed. | 155 // The single shared provider instance. We create it only when needed. |
| 125 static typename base::LazyInstance< | 156 static typename base::LazyInstance< |
| 126 scoped_refptr<SystemInfoProvider<T> > > single_shared_provider_; | 157 scoped_refptr<SystemInfoProvider<T> > > single_shared_provider_; |
| 127 | 158 |
| 128 // The queue of callbacks waiting for the info querying completion. It is | 159 // The queue of callbacks waiting for the info querying completion. It is |
| 129 // maintained on the UI thread. | 160 // maintained on the UI thread. |
| 130 CallbackQueue callbacks_; | 161 CallbackQueue callbacks_; |
| 131 | 162 |
| 132 // Indicates if it is waiting for the querying completion. | 163 // Indicates if it is waiting for the querying completion. |
| 133 bool is_waiting_for_completion_; | 164 bool is_waiting_for_completion_; |
| 134 | 165 |
| 135 // Unqiue sequence token so that the operation of querying inforation can | 166 // Unqiue sequence token so that the operation of querying inforation can |
| 136 // be executed in order. | 167 // be executed in order. |
| 137 base::SequencedWorkerPool::SequenceToken worker_pool_token_; | 168 base::SequencedWorkerPool::SequenceToken worker_pool_token_; |
| 138 | 169 |
| 139 DISALLOW_COPY_AND_ASSIGN(SystemInfoProvider<T>); | 170 DISALLOW_COPY_AND_ASSIGN(SystemInfoProvider<T>); |
| 140 }; | 171 }; |
| 141 | 172 |
| 142 // Static member intialization. | 173 // Static member intialization. |
| 143 template<class T> | 174 template<class T> |
| 144 typename base::LazyInstance<scoped_refptr<SystemInfoProvider<T> > > | 175 typename base::LazyInstance<scoped_refptr<SystemInfoProvider<T> > > |
| 145 SystemInfoProvider<T>::single_shared_provider_ = LAZY_INSTANCE_INITIALIZER; | 176 SystemInfoProvider<T>::single_shared_provider_ = LAZY_INSTANCE_INITIALIZER; |
| 146 | 177 |
| 147 } // namespace extensions | 178 } // namespace extensions |
| 148 | 179 |
| 149 #endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ | 180 #endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_INFO_SYSTEM_INFO_PROVIDER_H_ |
| OLD | NEW |