Chromium Code Reviews| Index: components/arc/arc_service_manager.h |
| diff --git a/components/arc/arc_service_manager.h b/components/arc/arc_service_manager.h |
| index 81a4ea9e98b2e715e289b112d3cae2660d72cbd6..129e17b857f393c8275862c95b46bebebf2cd4e0 100644 |
| --- a/components/arc/arc_service_manager.h |
| +++ b/components/arc/arc_service_manager.h |
| @@ -6,6 +6,10 @@ |
| #define COMPONENTS_ARC_ARC_SERVICE_MANAGER_H_ |
| #include <memory> |
| +#include <string> |
| +#include <type_traits> |
| +#include <unordered_map> |
| +#include <utility> |
| #include <vector> |
| #include "base/macros.h" |
| @@ -22,6 +26,38 @@ class ArcBridgeService; |
| class ArcIntentHelperObserver; |
| class ArcService; |
| +namespace internal { |
| + |
| +// If an ArcService is declared with a Name, e.g.: |
| +// |
| +// class MyArcService : public ArcService { |
| +// public: |
| +// static const char Name[]; |
|
Yusuke Sato
2017/01/10 07:11:11
The variable name 'Name' doesn't seem to follow th
Luis Héctor Chávez
2017/01/10 18:41:55
Done.
|
| +// ... |
| +// }; |
| +// |
| +// it can then be retrieved from ArcServiceManager in a type-safe way using |
| +// Get<T>(). This struct allows the use of std::enable_if<...> to choose the |
| +// correct implementation of the AddService() functions to enable this |
| +// functionality. |
| +template <typename T> |
|
hidehiko
2017/01/10 08:03:12
Optional: How about minimizing template magic? E.g
Luis Héctor Chávez
2017/01/10 18:41:56
Simplified the first function a bit, but done.
|
| +struct NamedServiceTraits { |
| + private: |
| + typedef char No[1]; |
|
Yusuke Sato
2017/01/10 07:11:11
nit: do we have a reason to skip 0? No can be [0]
hidehiko
2017/01/10 08:03:12
FYI: 0 length is illegal, IIUC.
http://stackoverfl
Luis Héctor Chávez
2017/01/10 18:41:56
This is a commonly-used Method Detector idiom: htt
hidehiko
2017/01/11 05:17:45
Yes, I know, but it was developed in C++03 era, an
|
| + typedef char Yes[2]; |
| + |
| + template <typename U> |
| + static Yes& test(decltype(U::Name) *); |
|
Yusuke Sato
2017/01/10 07:11:11
nit: no space before *, maybe?
hidehiko
2017/01/10 08:03:12
Optional: Even in this way, trailing return type c
Luis Héctor Chávez
2017/01/10 18:41:56
Acknowledged.
|
| + |
| + template <typename U> |
| + static No& test(...); |
| + |
| + public: |
| + enum : bool { HasName = sizeof(test<T>(nullptr)) == sizeof(Yes) }; |
|
hidehiko
2017/01/10 08:03:12
With std::{true,false}_type,
constexpr bool kValu
Luis Héctor Chávez
2017/01/10 18:41:56
Acknowledged.
|
| +}; |
| + |
| +} // namespace internal |
| + |
| // Manages creation and destruction of services that communicate with the ARC |
| // instance via the ArcBridgeService. |
| class ArcServiceManager { |
| @@ -49,7 +85,26 @@ class ArcServiceManager { |
| ArcBridgeService* arc_bridge_service(); |
| // Adds a service to the managed services list. |
| - void AddService(std::unique_ptr<ArcService> service); |
| + template <typename T, |
| + typename std::enable_if<!internal::NamedServiceTraits<T>::HasName, |
| + int>::type = 0> |
| + void AddService(std::unique_ptr<T> service) { |
| + AddServiceInternal(std::move(service)); |
| + } |
| + |
| + // Adds a named service to the managed services list. |
| + template <typename T, |
| + typename std::enable_if<internal::NamedServiceTraits<T>::HasName, |
| + int>::type = 0> |
| + void AddService(std::unique_ptr<T> service) { |
| + AddNamedServiceInternal(std::string(T::Name), std::move(service)); |
|
Yusuke Sato
2017/01/10 07:11:11
nit: the cast (to string) seems unnecessary
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
| + } |
| + |
| + // Gets the named service from the managed services list. |
|
Yusuke Sato
2017/01/10 07:11:11
For developers who don't want to read the template
hidehiko
2017/01/10 08:03:12
Also, could you explicitly comment that, this will
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
| + template <typename T> |
| + T* GetService() { |
|
Yusuke Sato
2017/01/10 07:11:11
I think GetService<T>() is easy to test. How about
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
| + return static_cast<T*>(GetNamedServiceInternal(T::Name)); |
| + } |
| // Gets the global instance of the ARC Service Manager. This can only be |
| // called on the thread that this class was created on. |
| @@ -81,6 +136,12 @@ class ArcServiceManager { |
| private: |
| class IntentHelperObserverImpl; // implemented in arc_service_manager.cc. |
| + // Helper methods for AddService and GetService. |
| + void AddServiceInternal(std::unique_ptr<ArcService> service); |
| + void AddNamedServiceInternal(const std::string& name, |
| + std::unique_ptr<ArcService> service); |
| + ArcService* GetNamedServiceInternal(const std::string& name); |
| + |
| base::ThreadChecker thread_checker_; |
| scoped_refptr<base::TaskRunner> blocking_task_runner_; |
| @@ -89,6 +150,7 @@ class ArcServiceManager { |
| std::unique_ptr<ArcBridgeService> arc_bridge_service_; |
| std::vector<std::unique_ptr<ArcService>> services_; |
| + std::unordered_map<std::string, std::unique_ptr<ArcService>> named_services_; |
|
hidehiko
2017/01/10 08:03:12
Optional: how about mergine services_ and named_se
Luis Héctor Chávez
2017/01/10 18:41:56
Done.
|
| scoped_refptr<ActivityIconLoader> icon_loader_; |
| scoped_refptr<LocalActivityResolver> activity_resolver_; |