1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_contentanalysis_h
#define mozilla_contentanalysis_h
#include "mozilla/DataMutex.h"
#include "mozilla/MozPromise.h"
#include "mozilla/dom/Promise.h"
#include "nsIContentAnalysis.h"
#include "nsProxyRelease.h"
#include "nsString.h"
#include "nsTHashMap.h"
#include <atomic>
#include <regex>
#include <string>
class nsIPrincipal;
class ContentAnalysisTest;
namespace mozilla::dom {
class DataTransfer;
class WindowGlobalParent;
} // namespace mozilla::dom
namespace content_analysis::sdk {
class Client;
class ContentAnalysisRequest;
class ContentAnalysisResponse;
} // namespace content_analysis::sdk
namespace mozilla::contentanalysis {
class ContentAnalysisRequest final : public nsIContentAnalysisRequest {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTANALYSISREQUEST
ContentAnalysisRequest(AnalysisType aAnalysisType, nsString aString,
bool aStringIsFilePath, nsCString aSha256Digest,
nsCOMPtr<nsIURI> aUrl, OperationType aOperationType,
dom::WindowGlobalParent* aWindowGlobalParent);
static nsresult GetFileDigest(const nsAString& aFilePath,
nsCString& aDigestString);
private:
~ContentAnalysisRequest() = default;
// Remove unneeded copy constructor/assignment
ContentAnalysisRequest(const ContentAnalysisRequest&) = delete;
ContentAnalysisRequest& operator=(ContentAnalysisRequest&) = delete;
// See nsIContentAnalysisRequest for values
AnalysisType mAnalysisType;
// Text content to analyze. Only one of textContent or filePath is defined.
nsString mTextContent;
// Name of file to analyze. Only one of textContent or filePath is defined.
nsString mFilePath;
// The URL containing the file download/upload or to which web content is
// being uploaded.
nsCOMPtr<nsIURI> mUrl;
// Sha256 digest of file.
nsCString mSha256Digest;
// URLs involved in the download.
nsTArray<RefPtr<nsIClientDownloadResource>> mResources;
// Email address of user.
nsString mEmail;
// Unique identifier for this request
nsCString mRequestToken;
// Type of text to display, see nsIContentAnalysisRequest for values
OperationType mOperationTypeForDisplay;
// String to display if mOperationTypeForDisplay is
// OPERATION_CUSTOMDISPLAYSTRING
nsString mOperationDisplayString;
RefPtr<dom::WindowGlobalParent> mWindowGlobalParent;
friend class ::ContentAnalysisTest;
};
#define CONTENTANALYSIS_IID \
{ \
0xa37bed74, 0x4b50, 0x443a, { \
0xbf, 0x58, 0xf4, 0xeb, 0xbd, 0x30, 0x67, 0xb4 \
} \
}
class ContentAnalysisResponse;
class ContentAnalysis final : public nsIContentAnalysis {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(CONTENTANALYSIS_IID)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICONTENTANALYSIS
ContentAnalysis();
nsCString GetUserActionId();
private:
~ContentAnalysis();
// Remove unneeded copy constructor/assignment
ContentAnalysis(const ContentAnalysis&) = delete;
ContentAnalysis& operator=(ContentAnalysis&) = delete;
nsresult CreateContentAnalysisClient(nsCString&& aPipePathName,
nsString&& aClientSignatureSetting,
bool aIsPerUser);
nsresult RunAnalyzeRequestTask(
const RefPtr<nsIContentAnalysisRequest>& aRequest, bool aAutoAcknowledge,
int64_t aRequestCount,
const RefPtr<nsIContentAnalysisCallback>& aCallback);
nsresult RunAcknowledgeTask(
nsIContentAnalysisAcknowledgement* aAcknowledgement,
const nsACString& aRequestToken);
nsresult CancelWithError(nsCString aRequestToken, nsresult aResult);
void GenerateUserActionId();
static RefPtr<ContentAnalysis> GetContentAnalysisFromService();
static void DoAnalyzeRequest(
nsCString aRequestToken,
content_analysis::sdk::ContentAnalysisRequest&& aRequest,
const std::shared_ptr<content_analysis::sdk::Client>& aClient);
void IssueResponse(RefPtr<ContentAnalysisResponse>& response);
// Did the URL filter completely handle the request or do we need to check
// with the agent.
enum UrlFilterResult { eCheck, eDeny, eAllow };
UrlFilterResult FilterByUrlLists(nsIContentAnalysisRequest* aRequest);
void EnsureParsedUrlFilters();
using ClientPromise =
MozPromise<std::shared_ptr<content_analysis::sdk::Client>, nsresult,
false>;
nsCString mUserActionId;
int64_t mRequestCount = 0;
RefPtr<ClientPromise::Private> mCaClientPromise;
// Only accessed from the main thread
bool mClientCreationAttempted;
bool mSetByEnterprise;
class CallbackData final {
public:
CallbackData(
nsMainThreadPtrHandle<nsIContentAnalysisCallback>&& aCallbackHolder,
bool aAutoAcknowledge)
: mCallbackHolder(aCallbackHolder),
mAutoAcknowledge(aAutoAcknowledge) {}
nsMainThreadPtrHandle<nsIContentAnalysisCallback> TakeCallbackHolder() {
return std::move(mCallbackHolder);
}
bool AutoAcknowledge() const { return mAutoAcknowledge; }
void SetCanceled() { mCallbackHolder = nullptr; }
bool Canceled() const { return !mCallbackHolder; }
private:
nsMainThreadPtrHandle<nsIContentAnalysisCallback> mCallbackHolder;
bool mAutoAcknowledge;
};
DataMutex<nsTHashMap<nsCString, CallbackData>> mCallbackMap;
struct WarnResponseData {
WarnResponseData(CallbackData&& aCallbackData,
RefPtr<ContentAnalysisResponse> aResponse)
: mCallbackData(std::move(aCallbackData)), mResponse(aResponse) {}
ContentAnalysis::CallbackData mCallbackData;
RefPtr<ContentAnalysisResponse> mResponse;
};
DataMutex<nsTHashMap<nsCString, WarnResponseData>> mWarnResponseDataMap;
std::vector<std::regex> mAllowUrlList;
std::vector<std::regex> mDenyUrlList;
bool mParsedUrlLists;
friend class ContentAnalysisResponse;
friend class ::ContentAnalysisTest;
};
NS_DEFINE_STATIC_IID_ACCESSOR(ContentAnalysis, CONTENTANALYSIS_IID)
class ContentAnalysisResponse final : public nsIContentAnalysisResponse {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICONTENTANALYSISRESPONSE
static RefPtr<ContentAnalysisResponse> FromAction(
Action aAction, const nsACString& aRequestToken);
void SetOwner(RefPtr<ContentAnalysis> aOwner);
void DoNotAcknowledge() { mDoNotAcknowledge = true; }
private:
~ContentAnalysisResponse() = default;
// Remove unneeded copy constructor/assignment
ContentAnalysisResponse(const ContentAnalysisResponse&) = delete;
ContentAnalysisResponse& operator=(ContentAnalysisResponse&) = delete;
explicit ContentAnalysisResponse(
content_analysis::sdk::ContentAnalysisResponse&& aResponse);
ContentAnalysisResponse(Action aAction, const nsACString& aRequestToken);
static already_AddRefed<ContentAnalysisResponse> FromProtobuf(
content_analysis::sdk::ContentAnalysisResponse&& aResponse);
void ResolveWarnAction(bool aAllowContent);
// Action requested by the agent
Action mAction;
// Identifier for the corresponding nsIContentAnalysisRequest
nsCString mRequestToken;
// ContentAnalysis (or, more precisely, it's Client object) must outlive
// the transaction.
RefPtr<ContentAnalysis> mOwner;
// Whether the response has been acknowledged
bool mHasAcknowledged = false;
// If true, the request was completely handled by URL filter lists, so it
// was not sent to the agent and should not send an Acknowledge.
bool mDoNotAcknowledge = false;
friend class ContentAnalysis;
};
class ContentAnalysisAcknowledgement final
: public nsIContentAnalysisAcknowledgement {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICONTENTANALYSISACKNOWLEDGEMENT
ContentAnalysisAcknowledgement(Result aResult, FinalAction aFinalAction);
private:
~ContentAnalysisAcknowledgement() = default;
Result mResult;
FinalAction mFinalAction;
};
class ContentAnalysisCallback final : public nsIContentAnalysisCallback {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICONTENTANALYSISCALLBACK
ContentAnalysisCallback(std::function<void(nsIContentAnalysisResponse*)>&&
aContentResponseCallback,
std::function<void(nsresult)>&& aErrorCallback)
: mContentResponseCallback(std::move(aContentResponseCallback)),
mErrorCallback(std::move(aErrorCallback)) {}
private:
~ContentAnalysisCallback() = default;
explicit ContentAnalysisCallback(RefPtr<dom::Promise> aPromise);
std::function<void(nsIContentAnalysisResponse*)> mContentResponseCallback;
std::function<void(nsresult)> mErrorCallback;
Maybe<nsMainThreadPtrHandle<dom::Promise>> mPromise;
friend class ContentAnalysis;
};
} // namespace mozilla::contentanalysis
#endif // mozilla_contentanalysis_h
|