1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "FOGIPC.h"
7
8 #include "mozilla/glean/fog_ffi_generated.h"
9 #include "mozilla/glean/GleanMetrics.h"
10 #include "mozilla/dom/ContentChild.h"
11 #include "mozilla/dom/ContentParent.h"
12 #include "mozilla/MozPromise.h"
13 #include "nsTArray.h"
14 #include "nsThreadUtils.h"
15
16 using mozilla::dom::ContentParent;
17 using mozilla::ipc::ByteBuf;
18 using FlushFOGDataPromise = mozilla::dom::ContentParent::FlushFOGDataPromise;
19
20 namespace mozilla {
21 namespace glean {
22
23 /**
24 * The parent process is asking you to flush your data ASAP.
25 *
26 * @param aResolver - The function you need to call with the bincoded,
27 * serialized payload that the Rust impl hands you.
28 */
FlushFOGData(std::function<void (ipc::ByteBuf &&)> && aResolver)29 void FlushFOGData(std::function<void(ipc::ByteBuf&&)>&& aResolver) {
30 #ifndef MOZ_GLEAN_ANDROID
31 ByteBuf buf;
32 uint32_t ipcBufferSize = impl::fog_serialize_ipc_buf();
33 bool ok = buf.Allocate(ipcBufferSize);
34 if (!ok) {
35 return;
36 }
37 uint32_t writtenLen = impl::fog_give_ipc_buf(buf.mData, buf.mLen);
38 if (writtenLen != ipcBufferSize) {
39 return;
40 }
41 aResolver(std::move(buf));
42 #endif
43 }
44
45 /**
46 * Called by FOG on the parent process when it wants to flush all its
47 * children's data.
48 * @param aResolver - The function that'll be called with the results.
49 */
FlushAllChildData(std::function<void (nsTArray<ipc::ByteBuf> &&)> && aResolver)50 void FlushAllChildData(
51 std::function<void(nsTArray<ipc::ByteBuf>&&)>&& aResolver) {
52 #ifndef MOZ_GLEAN_ANDROID
53 nsTArray<ContentParent*> parents;
54 ContentParent::GetAll(parents);
55 if (parents.Length() == 0) {
56 nsTArray<ipc::ByteBuf> results;
57 aResolver(std::move(results));
58 return;
59 }
60
61 auto timerId = fog_ipc::flush_durations.Start();
62 nsTArray<RefPtr<FlushFOGDataPromise>> promises;
63 for (auto* parent : parents) {
64 promises.EmplaceBack(parent->SendFlushFOGData());
65 }
66 // TODO: Don't throw away resolved data if some of the promises reject.
67 // (not sure how, but it'll mean not using ::All... maybe a custom copy of
68 // AllPromiseHolder? Might be impossible outside MozPromise.h)
69 FlushFOGDataPromise::All(GetCurrentSerialEventTarget(), promises)
70 ->Then(GetCurrentSerialEventTarget(), __func__,
71 [aResolver = std::move(aResolver), timerId](
72 FlushFOGDataPromise::AllPromiseType::ResolveOrRejectValue&&
73 aValue) {
74 fog_ipc::flush_durations.StopAndAccumulate(std::move(timerId));
75 if (aValue.IsResolve()) {
76 aResolver(std::move(aValue.ResolveValue()));
77 } else {
78 nsTArray<ipc::ByteBuf> results;
79 aResolver(std::move(results));
80 }
81 });
82 #endif
83 }
84
85 /**
86 * A child process has sent you this buf as a treat.
87 * @param buf - a bincoded serialized payload that the Rust impl understands.
88 */
FOGData(ipc::ByteBuf && buf)89 void FOGData(ipc::ByteBuf&& buf) {
90 #ifndef MOZ_GLEAN_ANDROID
91 fog_ipc::buffer_sizes.Accumulate(buf.mLen);
92 impl::fog_use_ipc_buf(buf.mData, buf.mLen);
93 #endif
94 }
95
96 /**
97 * Called by FOG on a child process when it wants to send a buf to the parent.
98 * @param buf - a bincoded serialized payload that the Rust impl understands.
99 */
SendFOGData(ipc::ByteBuf && buf)100 void SendFOGData(ipc::ByteBuf&& buf) {
101 #ifndef MOZ_GLEAN_ANDROID
102 switch (XRE_GetProcessType()) {
103 case GeckoProcessType_Content:
104 mozilla::dom::ContentChild::GetSingleton()->SendFOGData(std::move(buf));
105 break;
106 default:
107 MOZ_ASSERT_UNREACHABLE("Unsuppored process type");
108 }
109 #endif
110 }
111
112 /**
113 * Called on the parent process to ask all child processes for data,
114 * sending it all down into Rust to be used.
115 */
FlushAndUseFOGData()116 RefPtr<GenericPromise> FlushAndUseFOGData() {
117 RefPtr<GenericPromise::Private> ret = new GenericPromise::Private(__func__);
118 std::function<void(nsTArray<ByteBuf> &&)> resolver =
119 [ret](nsTArray<ByteBuf>&& bufs) {
120 for (ByteBuf& buf : bufs) {
121 FOGData(std::move(buf));
122 }
123 ret->Resolve(true, __func__);
124 };
125 FlushAllChildData(std::move(resolver));
126 return ret;
127 }
128
129 } // namespace glean
130 } // namespace mozilla
131