summaryrefslogtreecommitdiffstats
path: root/toolkit/components/contentanalysis/ContentAnalysis.h
blob: 4579a7113d3023f69dcb967fa5ad95aaea69be9a (plain)
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
/* -*- 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/dom/WindowGlobalParent.h"
#include "nsIContentAnalysis.h"
#include "nsProxyRelease.h"
#include "nsString.h"
#include "nsTHashMap.h"

#include <atomic>
#include <string>

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;
};

#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();

 private:
  ~ContentAnalysis();
  // Remove unneeded copy constructor/assignment
  ContentAnalysis(const ContentAnalysis&) = delete;
  ContentAnalysis& operator=(ContentAnalysis&) = delete;
  nsresult CreateContentAnalysisClient(nsCString&& aPipePathName,
                                       bool aIsPerUser);
  nsresult RunAnalyzeRequestTask(
      const RefPtr<nsIContentAnalysisRequest>& aRequest, bool aAutoAcknowledge,
      const RefPtr<nsIContentAnalysisCallback>& aCallback);
  nsresult RunAcknowledgeTask(
      nsIContentAnalysisAcknowledgement* aAcknowledgement,
      const nsACString& aRequestToken);
  nsresult CancelWithError(nsCString aRequestToken, nsresult aResult);
  static RefPtr<ContentAnalysis> GetContentAnalysisFromService();
  static void DoAnalyzeRequest(
      nsCString aRequestToken,
      content_analysis::sdk::ContentAnalysisRequest&& aRequest,
      const std::shared_ptr<content_analysis::sdk::Client>& aClient);

  using ClientPromise =
      MozPromise<std::shared_ptr<content_analysis::sdk::Client>, nsresult,
                 false>;
  RefPtr<ClientPromise::Private> mCaClientPromise;
  // Only accessed from the main thread
  bool mClientCreationAttempted;

  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;

  friend class ContentAnalysisResponse;
};

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);

 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;

  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