Update code documentation for enum in EWK headers
[platform/framework/web/chromium-efl.git] / chrome / notification_helper / com_server_module.cc
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This macro is used in <wrl/module.h>. Since only the COM functionality is
6 // used here (while WinRT isn't being used), define this macro to optimize
7 // compilation of <wrl/module.h> for COM-only.
8 #ifndef __WRL_CLASSIC_COM_STRICT__
9 #define __WRL_CLASSIC_COM_STRICT__
10 #endif  // __WRL_CLASSIC_COM_STRICT__
11
12 #include "chrome/notification_helper/com_server_module.h"
13
14 #include <wrl/module.h>
15
16 #include <type_traits>
17
18 #include "base/metrics/histogram_macros.h"
19 #include "chrome/install_static/install_util.h"
20 #include "chrome/notification_helper/notification_activator.h"
21 #include "chrome/notification_helper/trace_util.h"
22
23 namespace mswr = Microsoft::WRL;
24
25 namespace {
26
27 // These values are persisted to logs. Entries should not be renumbered and
28 // numeric values should never be reused.
29 enum class ComServerModuleStatus {
30   SUCCESS = 0,
31   FACTORY_CREATION_FAILED = 1,
32   ICLASSFACTORY_OBJECT_CREATION_FAILED = 2,
33   REGISTRATION_FAILED = 3,
34   UNREGISTRATION_FAILED = 4,
35   COUNT  // Must be the final value.
36 };
37
38 void LogComServerModuleHistogram(ComServerModuleStatus status) {
39   UMA_HISTOGRAM_ENUMERATION(
40       "Notifications.NotificationHelper.ComServerModuleStatus", status,
41       ComServerModuleStatus::COUNT);
42 }
43
44 }  // namespace
45
46 namespace notification_helper {
47
48 // The reset policy of the event MUST BE set to MANUAL to avoid signaling the
49 // event in IsSignaled() itself, which is called by IsEventSignaled().
50 ComServerModule::ComServerModule()
51     : object_zero_count_(base::WaitableEvent::ResetPolicy::MANUAL,
52                          base::WaitableEvent::InitialState::NOT_SIGNALED) {}
53
54 ComServerModule::~ComServerModule() = default;
55
56 HRESULT ComServerModule::Run() {
57   HRESULT hr = RegisterClassObjects();
58   if (SUCCEEDED(hr)) {
59     WaitForZeroObjectCount();
60     hr = UnregisterClassObjects();
61   }
62   if (SUCCEEDED(hr))
63     LogComServerModuleHistogram(ComServerModuleStatus::SUCCESS);
64
65   return hr;
66 }
67
68 HRESULT ComServerModule::RegisterClassObjects() {
69   // Create an out-of-proc COM module with caching disabled. The supplied
70   // method is invoked when the last instance object of the module is released.
71   auto& module = mswr::Module<mswr::OutOfProcDisableCaching>::Create(
72       this, &ComServerModule::SignalObjectCountZero);
73
74   // Usually COM module classes statically define their CLSID at compile time
75   // through the use of various macros, and WRL::Module internals takes care of
76   // creating the class objects and registering them. However, we need to
77   // register the same object with different CLSIDs depending on a runtime
78   // setting, so we handle that logic here.
79
80   mswr::ComPtr<IUnknown> factory;
81   unsigned int flags = mswr::ModuleType::OutOfProcDisableCaching;
82
83   HRESULT hr = mswr::Details::CreateClassFactory<
84       mswr::SimpleClassFactory<NotificationActivator>>(
85       &flags, nullptr, __uuidof(IClassFactory), &factory);
86   if (FAILED(hr)) {
87     LogComServerModuleHistogram(ComServerModuleStatus::FACTORY_CREATION_FAILED);
88     Trace(L"%hs(Factory creation failed; hr: 0x%08X)\n", __func__, hr);
89     return hr;
90   }
91
92   mswr::ComPtr<IClassFactory> class_factory;
93   hr = factory.As(&class_factory);
94   if (FAILED(hr)) {
95     LogComServerModuleHistogram(
96         ComServerModuleStatus::ICLASSFACTORY_OBJECT_CREATION_FAILED);
97     Trace(L"%hs(IClassFactory object creation failed; hr: 0x%08X)\n", __func__,
98           hr);
99     return hr;
100   }
101
102   // All pointers in this array are unowned. Do not release them.
103   IClassFactory* class_factories[] = {class_factory.Get()};
104   static_assert(std::extent<decltype(cookies_)>() == std::size(class_factories),
105                 "Arrays cookies_ and class_factories must be the same size.");
106
107   IID class_ids[] = {install_static::GetToastActivatorClsid()};
108   static_assert(std::extent<decltype(cookies_)>() == std::size(class_ids),
109                 "Arrays cookies_ and class_ids must be the same size.");
110
111   hr = module.RegisterCOMObject(nullptr, class_ids, class_factories, cookies_,
112                                 std::extent<decltype(cookies_)>());
113   if (FAILED(hr)) {
114     LogComServerModuleHistogram(ComServerModuleStatus::REGISTRATION_FAILED);
115     Trace(L"%hs(NotificationActivator registration failed; hr: 0x%08X)\n",
116           __func__, hr);
117   }
118
119   return hr;
120 }
121
122 HRESULT ComServerModule::UnregisterClassObjects() {
123   auto& module = mswr::Module<mswr::OutOfProcDisableCaching>::GetModule();
124   HRESULT hr = module.UnregisterCOMObject(nullptr, cookies_,
125                                           std::extent<decltype(cookies_)>());
126   if (FAILED(hr)) {
127     LogComServerModuleHistogram(ComServerModuleStatus::UNREGISTRATION_FAILED);
128     Trace(L"%hs(NotificationActivator unregistration failed; hr: 0x%08X)\n",
129           __func__, hr);
130   }
131   return hr;
132 }
133
134 bool ComServerModule::IsEventSignaled() {
135   return object_zero_count_.IsSignaled();
136 }
137
138 void ComServerModule::WaitForZeroObjectCount() {
139   object_zero_count_.Wait();
140 }
141
142 void ComServerModule::SignalObjectCountZero() {
143   object_zero_count_.Signal();
144 }
145
146 }  // namespace notification_helper