Chromium Code Reviews| Index: chrome/browser/extensions/system_info_provider.h |
| diff --git a/chrome/browser/extensions/system_info_provider.h b/chrome/browser/extensions/system_info_provider.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d28cec6c361223b0161ca8f2dd1e12e3dd63dbda |
| --- /dev/null |
| +++ b/chrome/browser/extensions/system_info_provider.h |
| @@ -0,0 +1,160 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| +#ifndef CHROME_BROWSER_EXTENSIONS_SYSTEM_INFO_PROVIDER_H_ |
| +#define CHROME_BROWSER_EXTENSIONS_SYSTEM_INFO_PROVIDER_H_ |
| + |
| +#include <queue> |
| + |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/memory/weak_ptr.h" |
| +#include "base/threading/sequenced_worker_pool.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +namespace extensions { |
| + |
| +// A generic template for all kinds of system information provider. Each kind |
| +// of SystemInfoProvider is a single shared instance. It is created if needed, |
| +// and destroyed at exit time. This is done via LazyInstance and scoped_ptr. |
| +// |
| +// The SystemInfoProvider is designed to query system information on the worker |
| +// pool. It also maintains a queue of callbacks on the UI thread which are |
| +// waiting for the completion of querying operation. Once the query operation |
| +// is completed, all pending callbacks in the queue get called on the UI |
| +// thread. In this way, it avoids frequent querying operation in case of lots |
| +// of query requests are arrived, e.g. calling systemInfo.cpu.get repeatedly |
| +// in renderer. |
| +// |
| +// Template parameter T is the system information type. It could be the |
| +// structure type generated by IDL parser. |
| +template<class T> |
| +class SystemInfoProvider { |
| + public: |
| + // Callback type for completing to get information. The callback accepts |
| + // two arguments. The first one is the information got already, the second |
| + // one indicates whether its contents are valid, for example, no error |
| + // occurs in querying the information. |
| + typedef base::Callback<void(const T&, bool)> GetInfoCompletionCallback; |
| + typedef std::queue<GetInfoCompletionCallback> CallbackQueue; |
| + |
| + SystemInfoProvider() |
| + : is_waiting_for_completion_(false) { |
| + worker_pool_token_ = |
| + content::BrowserThread::GetBlockingPool()->GetSequenceToken(); |
| + } |
| + |
| + // Static method to get the single shared instance. Should be implemented |
| + // in the impl file for each kind of provider. |
| + static SystemInfoProvider<T>* Get(); |
| + |
| + // For testing |
| + static void InitializeForTesting(SystemInfoProvider<T>* provider) { |
| + DCHECK(provider != NULL); |
| + single_shared_provider_.Get().reset(provider); |
| + } |
| + |
| + // Start to query the system information. Should be called on UI thread. |
| + // The |callback| will get called once the query is completed. |
| + virtual void StartGetInfo(const GetInfoCompletionCallback& callback) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + DCHECK(!callback.is_null()); |
| + |
| + callbacks_.push(callback); |
| + |
| + if (is_waiting_for_completion_) |
| + return; |
| + |
| + is_waiting_for_completion_ = true; |
| + |
| + base::SequencedWorkerPool* worker_pool = |
| + content::BrowserThread::GetBlockingPool(); |
| + // Post the query task to the worker pool with CONTINUE_ON_SHUTDOWN |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
This comment just says what the code says. Either
Hongbo Min
2012/08/21 03:07:11
Done.
|
| + // shutdown behavior. |
| + worker_pool->PostSequencedWorkerTaskWithShutdownBehavior( |
| + worker_pool_token_, |
| + FROM_HERE, |
| + base::Bind(&SystemInfoProvider<T>::QueryOnWorkerPool, |
| + base::Unretained(this)), |
| + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| + } |
| + |
| + virtual ~SystemInfoProvider() {} |
| + |
| + protected: |
| + // Query the information on worker pool. |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
Another redundant comment.
Hongbo Min
2012/08/21 03:07:11
Done.
|
| + virtual void QueryOnWorkerPool() { |
| + bool success = QueryInfo(); |
| + // Notify UI thread once it is completed. |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
Ditto.
Hongbo Min
2012/08/21 03:07:11
Done.
|
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&SystemInfoProvider<T>::OnQueryCompleted, |
| + base::Unretained(this), success)); |
| + } |
| + |
| + // Platform specific implementation for how to query the information and |
| + // save it into |info_|. The |info_| contents must be reset firstly in the |
| + // concrete implementation. Return true if it succeeds, otherwise false is |
| + // returned. |
| + virtual bool QueryInfo() = 0; |
| + |
| + // Called on UI thread. The |success| parameter means whether it succeeds |
| + // to get the information. |
| + virtual void OnQueryCompleted(bool success) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + |
| + // Traverse the queue to invoke the pending callbacks. |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
Ditto.
Hongbo Min
2012/08/21 03:07:11
Done.
|
| + while (!callbacks_.empty()) { |
| + GetInfoCompletionCallback callback = callbacks_.front(); |
| + callback.Run(info_, success); |
| + callbacks_.pop(); |
| + } |
| + |
| + // Reset waiting status. |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
Ditto.
|
| + is_waiting_for_completion_ = false; |
| + } |
| + |
| + // Template function for creating the single shared provider instance. |
| + // Template paramter I is the type of SystemInfoProvider implementation. |
| + template<class I> |
| + static SystemInfoProvider<T>* GetInstance() { |
| + if (!single_shared_provider_.Get().get()) { |
| + I* impl = new I(); |
| + single_shared_provider_.Get().reset(impl); |
| + } |
| + return single_shared_provider_.Get().get(); |
| + } |
| + |
| + // The latest information filled up by QueryInfo implementation. Here we |
| + // assume the T is disallowed to copy constructor, aligns with the structure |
| + // type generated by IDL parser. It leads to the |info_| can not be used as |
| + // an argument for base::Bind. |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
How is the base::Bind discussion relevant?
Hongbo Min
2012/08/21 03:07:11
Removed it now.
The origin implementation is to a
Hongbo Min
2012/08/21 05:16:39
Correct: It can not be used as a callback paramete
|
| + T info_; |
| + |
| + private: |
| + // The single shared provider instance. We create it only when needed. |
| + static typename base::LazyInstance< |
| + scoped_ptr<SystemInfoProvider<T> > > single_shared_provider_; |
| + |
| + // The queue of callbacks waiting for the info querying completion. It is |
| + // maintained on the UI thread. |
| + CallbackQueue callbacks_; |
| + |
| + // Indicates if it is waiting for the querying completion. |
| + bool is_waiting_for_completion_; |
| + |
| + // Unqiue sequence token so that the operation of querying inforation can |
| + // be executed in order. |
| + base::SequencedWorkerPool::SequenceToken worker_pool_token_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SystemInfoProvider<T>); |
| +}; |
| + |
| +// Static member intialization. |
| +template<class T> |
| +typename base::LazyInstance<scoped_ptr<SystemInfoProvider<T> > > |
|
Mihai Parparita -not on Chrome
2012/08/21 01:14:52
Do you actually need to use scoped_ptr here? From
Hongbo
2012/08/21 01:29:37
The reason I use scoped_ptr is, the SystemInfoProv
|
| + SystemInfoProvider<T>::single_shared_provider_ = LAZY_INSTANCE_INITIALIZER; |
| + |
| +} // namespace extensions |
| + |
| +#endif // CHROME_BROWSER_EXTENSIONS_SYSTEM_INFO_PROVIDER_H_ |