diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:33 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:33 +0000 |
commit | 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch) | |
tree | a4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /toolkit/components/contentanalysis/ContentAnalysis.cpp | |
parent | Adding debian version 124.0.1-1. (diff) | |
download | firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip |
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/contentanalysis/ContentAnalysis.cpp')
-rw-r--r-- | toolkit/components/contentanalysis/ContentAnalysis.cpp | 437 |
1 files changed, 350 insertions, 87 deletions
diff --git a/toolkit/components/contentanalysis/ContentAnalysis.cpp b/toolkit/components/contentanalysis/ContentAnalysis.cpp index e749fd0acd..1c71f5d986 100644 --- a/toolkit/components/contentanalysis/ContentAnalysis.cpp +++ b/toolkit/components/contentanalysis/ContentAnalysis.cpp @@ -12,9 +12,11 @@ #include "GMPUtils.h" // ToHexString #include "mozilla/Components.h" #include "mozilla/dom/Promise.h" +#include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/Logging.h" #include "mozilla/ScopeExit.h" #include "mozilla/Services.h" +#include "mozilla/StaticMutex.h" #include "mozilla/StaticPrefs_browser.h" #include "nsAppRunner.h" #include "nsComponentManagerUtils.h" @@ -27,11 +29,13 @@ #include <algorithm> #include <sstream> +#include <string> #ifdef XP_WIN # include <windows.h> # define SECURITY_WIN32 1 # include <security.h> +# include "mozilla/WinDllServices.h" #endif // XP_WIN namespace mozilla::contentanalysis { @@ -53,8 +57,9 @@ const char* kIsDLPEnabledPref = "browser.contentanalysis.enabled"; const char* kIsPerUserPref = "browser.contentanalysis.is_per_user"; const char* kPipePathNamePref = "browser.contentanalysis.pipe_path_name"; const char* kDefaultAllowPref = "browser.contentanalysis.default_allow"; - -static constexpr uint32_t kAnalysisTimeoutSecs = 30; // 30 sec +const char* kClientSignature = "browser.contentanalysis.client_signature"; +const char* kAllowUrlPref = "browser.contentanalysis.allow_url_regex_list"; +const char* kDenyUrlPref = "browser.contentanalysis.deny_url_regex_list"; nsresult MakePromise(JSContext* aCx, RefPtr<mozilla::dom::Promise>* aPromise) { nsIGlobalObject* go = xpc::CurrentNativeGlobal(aCx); @@ -181,8 +186,9 @@ ContentAnalysisRequest::GetWindowGlobalParent( return NS_OK; } -nsresult ContentAnalysis::CreateContentAnalysisClient(nsCString&& aPipePathName, - bool aIsPerUser) { +nsresult ContentAnalysis::CreateContentAnalysisClient( + nsCString&& aPipePathName, nsString&& aClientSignatureSetting, + bool aIsPerUser) { MOZ_ASSERT(!NS_IsMainThread()); // This method should only be called once MOZ_ASSERT(!mCaClientPromise->IsResolved()); @@ -191,6 +197,30 @@ nsresult ContentAnalysis::CreateContentAnalysisClient(nsCString&& aPipePathName, content_analysis::sdk::Client::Create({aPipePathName.Data(), aIsPerUser}) .release()); LOGD("Content analysis is %s", client ? "connected" : "not available"); +#ifdef XP_WIN + if (client && !aClientSignatureSetting.IsEmpty()) { + std::string agentPath = client->GetAgentInfo().binary_path; + nsString agentWidePath = NS_ConvertUTF8toUTF16(agentPath); + UniquePtr<wchar_t[]> orgName = + mozilla::DllServices::Get()->GetBinaryOrgName(agentWidePath.Data()); + bool signatureMatches = false; + if (orgName) { + auto dependentOrgName = nsDependentString(orgName.get()); + LOGD("Content analysis client signed with organization name \"%S\"", + static_cast<const wchar_t*>(dependentOrgName.get())); + signatureMatches = aClientSignatureSetting.Equals(dependentOrgName); + } else { + LOGD("Content analysis client has no signature"); + } + if (!signatureMatches) { + LOGE( + "Got mismatched content analysis client signature! All content " + "analysis operations will fail."); + mCaClientPromise->Reject(NS_ERROR_INVALID_SIGNATURE, __func__); + return NS_OK; + } + } +#endif // XP_WIN mCaClientPromise->Resolve(client, __func__); return NS_OK; @@ -258,6 +288,15 @@ nsresult ContentAnalysisRequest::GetFileDigest(const nsAString& aFilePath, return NS_OK; } +// Generate an ID that will be shared by all DLP requests. +// Used to cancel all requests on Firefox shutdown. +void ContentAnalysis::GenerateUserActionId() { + nsID id = nsID::GenerateUUID(); + mUserActionId = nsPrintfCString("Firefox %s", id.ToString().get()); +} + +nsCString ContentAnalysis::GetUserActionId() { return mUserActionId; } + static nsresult ConvertToProtobuf( nsIClientDownloadResource* aIn, content_analysis::sdk::ClientDownloadRequest_Resource* aOut) { @@ -277,9 +316,11 @@ static nsresult ConvertToProtobuf( } static nsresult ConvertToProtobuf( - nsIContentAnalysisRequest* aIn, + nsIContentAnalysisRequest* aIn, nsCString&& aUserActionId, + int64_t aRequestCount, content_analysis::sdk::ContentAnalysisRequest* aOut) { - aOut->set_expires_at(time(nullptr) + kAnalysisTimeoutSecs); // TODO: + uint32_t timeout = StaticPrefs::browser_contentanalysis_agent_timeout(); + aOut->set_expires_at(time(nullptr) + timeout); nsIContentAnalysisRequest::AnalysisType analysisType; nsresult rv = aIn->GetAnalysisType(&analysisType); @@ -293,6 +334,9 @@ static nsresult ConvertToProtobuf( NS_ENSURE_SUCCESS(rv, rv); aOut->set_request_token(requestToken.get(), requestToken.Length()); + aOut->set_user_action_id(aUserActionId.get()); + aOut->set_user_action_requests_count(aRequestCount); + const std::string tag = "dlp"; // TODO: *aOut->add_tags() = tag; @@ -440,8 +484,7 @@ static void LogRequest( } ContentAnalysisResponse::ContentAnalysisResponse( - content_analysis::sdk::ContentAnalysisResponse&& aResponse) - : mHasAcknowledged(false) { + content_analysis::sdk::ContentAnalysisResponse&& aResponse) { mAction = Action::eUnspecified; for (const auto& result : aResponse.results()) { if (!result.has_status() || @@ -469,7 +512,7 @@ ContentAnalysisResponse::ContentAnalysisResponse( ContentAnalysisResponse::ContentAnalysisResponse( Action aAction, const nsACString& aRequestToken) - : mAction(aAction), mRequestToken(aRequestToken), mHasAcknowledged(false) {} + : mAction(aAction), mRequestToken(aRequestToken) {} /* static */ already_AddRefed<ContentAnalysisResponse> ContentAnalysisResponse::FromProtobuf( @@ -658,6 +701,122 @@ NS_IMETHODIMP ContentAnalysisResult::GetShouldAllowContent( return NS_OK; } +void ContentAnalysis::EnsureParsedUrlFilters() { + MOZ_ASSERT(NS_IsMainThread()); + if (mParsedUrlLists) { + return; + } + + mParsedUrlLists = true; + nsAutoCString allowList; + MOZ_ALWAYS_SUCCEEDS(Preferences::GetCString(kAllowUrlPref, allowList)); + for (const nsACString& regexSubstr : allowList.Split(u' ')) { + if (!regexSubstr.IsEmpty()) { + auto flatStr = PromiseFlatCString(regexSubstr); + const char* regex = flatStr.get(); + LOGD("CA will allow URLs that match %s", regex); + mAllowUrlList.push_back(std::regex(regex)); + } + } + + nsAutoCString denyList; + MOZ_ALWAYS_SUCCEEDS(Preferences::GetCString(kDenyUrlPref, denyList)); + for (const nsACString& regexSubstr : denyList.Split(u' ')) { + if (!regexSubstr.IsEmpty()) { + auto flatStr = PromiseFlatCString(regexSubstr); + const char* regex = flatStr.get(); + LOGD("CA will block URLs that match %s", regex); + mDenyUrlList.push_back(std::regex(regex)); + } + } +} + +ContentAnalysis::UrlFilterResult ContentAnalysis::FilterByUrlLists( + nsIContentAnalysisRequest* aRequest) { + EnsureParsedUrlFilters(); + + nsIURI* nsiUrl = nullptr; + MOZ_ALWAYS_SUCCEEDS(aRequest->GetUrl(&nsiUrl)); + nsCString urlString; + nsresult rv = nsiUrl->GetSpec(urlString); + NS_ENSURE_SUCCESS(rv, UrlFilterResult::eDeny); + MOZ_ASSERT(!urlString.IsEmpty()); + std::string url = urlString.BeginReading(); + size_t count = 0; + for (const auto& denyFilter : mDenyUrlList) { + if (std::regex_search(url, denyFilter)) { + LOGD("Denying CA request : Deny filter %zu matched url %s", count, + url.c_str()); + return UrlFilterResult::eDeny; + } + ++count; + } + + count = 0; + UrlFilterResult result = UrlFilterResult::eCheck; + for (const auto& allowFilter : mAllowUrlList) { + if (std::regex_match(url, allowFilter)) { + LOGD("CA request : Allow filter %zu matched %s", count, url.c_str()); + result = UrlFilterResult::eAllow; + break; + } + ++count; + } + + // The rest only applies to download resources. + nsIContentAnalysisRequest::AnalysisType analysisType; + MOZ_ALWAYS_SUCCEEDS(aRequest->GetAnalysisType(&analysisType)); + if (analysisType != ContentAnalysisRequest::AnalysisType::eFileDownloaded) { + MOZ_ASSERT(result == UrlFilterResult::eCheck || + result == UrlFilterResult::eAllow); + LOGD("CA request filter result: %s", + result == UrlFilterResult::eCheck ? "check" : "allow"); + return result; + } + + nsTArray<RefPtr<nsIClientDownloadResource>> resources; + MOZ_ALWAYS_SUCCEEDS(aRequest->GetResources(resources)); + for (size_t resourceIdx = 0; resourceIdx < resources.Length(); + /* noop */) { + auto& resource = resources[resourceIdx]; + nsAutoString nsUrl; + MOZ_ALWAYS_SUCCEEDS(resource->GetUrl(nsUrl)); + std::string url = NS_ConvertUTF16toUTF8(nsUrl).get(); + count = 0; + for (auto& denyFilter : mDenyUrlList) { + if (std::regex_search(url, denyFilter)) { + LOGD( + "Denying CA request : Deny filter %zu matched download resource " + "at url %s", + count, url.c_str()); + return UrlFilterResult::eDeny; + } + ++count; + } + + count = 0; + bool removed = false; + for (auto& allowFilter : mAllowUrlList) { + if (std::regex_search(url, allowFilter)) { + LOGD( + "CA request : Allow filter %zu matched download resource " + "at url %s", + count, url.c_str()); + resources.RemoveElementAt(resourceIdx); + removed = true; + break; + } + ++count; + } + if (!removed) { + ++resourceIdx; + } + } + + // Check unless all were allowed. + return resources.Length() ? UrlFilterResult::eCheck : UrlFilterResult::eAllow; +} + NS_IMPL_CLASSINFO(ContentAnalysisRequest, nullptr, 0, {0}); NS_IMPL_ISUPPORTS_CI(ContentAnalysisRequest, nsIContentAnalysisRequest); NS_IMPL_CLASSINFO(ContentAnalysisResponse, nullptr, 0, {0}); @@ -672,8 +831,11 @@ ContentAnalysis::ContentAnalysis() : mCaClientPromise( new ClientPromise::Private("ContentAnalysis::ContentAnalysis")), mClientCreationAttempted(false), + mSetByEnterprise(false), mCallbackMap("ContentAnalysis::mCallbackMap"), - mWarnResponseDataMap("ContentAnalysis::mWarnResponseDataMap") {} + mWarnResponseDataMap("ContentAnalysis::mWarnResponseDataMap") { + GenerateUserActionId(); +} ContentAnalysis::~ContentAnalysis() { // Accessing mClientCreationAttempted so need to be on the main thread @@ -689,12 +851,20 @@ ContentAnalysis::GetIsActive(bool* aIsActive) { *aIsActive = false; // Need to be on the main thread to read prefs MOZ_ASSERT(NS_IsMainThread()); - // gAllowContentAnalysis is only set in the parent process + // gAllowContentAnalysisArgPresent is only set in the parent process MOZ_ASSERT(XRE_IsParentProcess()); - if (!gAllowContentAnalysis || !Preferences::GetBool(kIsDLPEnabledPref)) { + if (!Preferences::GetBool(kIsDLPEnabledPref)) { LOGD("Local DLP Content Analysis is not active"); return NS_OK; } + if (!gAllowContentAnalysisArgPresent && !mSetByEnterprise) { + LOGE( + "The content analysis pref is enabled but not by an enterprise " + "policy and -allow-content-analysis was not present on the " + "command-line. Content Analysis will not be active."); + return NS_OK; + } + *aIsActive = true; LOGD("Local DLP Content Analysis is active"); // mClientCreationAttempted is only accessed on the main thread, @@ -710,12 +880,15 @@ ContentAnalysis::GetIsActive(bool* aIsActive) { return rv; } bool isPerUser = Preferences::GetBool(kIsPerUserPref); + nsString clientSignature; + // It's OK if this fails, we will default to the empty string + Preferences::GetString(kClientSignature, clientSignature); rv = NS_DispatchBackgroundTask(NS_NewCancelableRunnableFunction( "ContentAnalysis::CreateContentAnalysisClient", [owner = RefPtr{this}, pipePathName = std::move(pipePathName), - isPerUser]() mutable { - owner->CreateContentAnalysisClient(std::move(pipePathName), - isPerUser); + clientSignature = std::move(clientSignature), isPerUser]() mutable { + owner->CreateContentAnalysisClient( + std::move(pipePathName), std::move(clientSignature), isPerUser); })); if (NS_WARN_IF(NS_FAILED(rv))) { mCaClientPromise->Reject(rv, __func__); @@ -736,10 +909,33 @@ ContentAnalysis::GetMightBeActive(bool* aMightBeActive) { return NS_OK; } +NS_IMETHODIMP +ContentAnalysis::GetIsSetByEnterprisePolicy(bool* aSetByEnterprise) { + *aSetByEnterprise = mSetByEnterprise; + return NS_OK; +} + +NS_IMETHODIMP +ContentAnalysis::SetIsSetByEnterprisePolicy(bool aSetByEnterprise) { + mSetByEnterprise = aSetByEnterprise; + return NS_OK; +} + +NS_IMETHODIMP +ContentAnalysis::TestOnlySetCACmdLineArg(bool aVal) { +#ifdef ENABLE_TESTS + gAllowContentAnalysisArgPresent = aVal; + return NS_OK; +#else + LOGE("ContentAnalysis::TestOnlySetCACmdLineArg is test-only"); + return NS_ERROR_UNEXPECTED; +#endif +} + nsresult ContentAnalysis::CancelWithError(nsCString aRequestToken, nsresult aResult) { return NS_DispatchToMainThread(NS_NewCancelableRunnableFunction( - "ContentAnalysis::RunAnalyzeRequestTask::HandleResponse", + "ContentAnalysis::CancelWithError", [aResult, aRequestToken = std::move(aRequestToken)] { RefPtr<ContentAnalysis> owner = GetContentAnalysisFromService(); if (!owner) { @@ -787,7 +983,10 @@ RefPtr<ContentAnalysis> ContentAnalysis::GetContentAnalysisFromService() { nsresult ContentAnalysis::RunAnalyzeRequestTask( const RefPtr<nsIContentAnalysisRequest>& aRequest, bool aAutoAcknowledge, + int64_t aRequestCount, const RefPtr<nsIContentAnalysisCallback>& aCallback) { + MOZ_ASSERT(NS_IsMainThread()); + nsresult rv = NS_ERROR_FAILURE; auto callbackCopy = aCallback; auto se = MakeScopeExit([&] { @@ -797,23 +996,52 @@ nsresult ContentAnalysis::RunAnalyzeRequestTask( } }); - content_analysis::sdk::ContentAnalysisRequest pbRequest; - rv = ConvertToProtobuf(aRequest, &pbRequest); + nsCString requestToken; + rv = aRequest->GetRequestToken(requestToken); NS_ENSURE_SUCCESS(rv, rv); - nsCString requestToken; nsMainThreadPtrHandle<nsIContentAnalysisCallback> callbackHolderCopy( new nsMainThreadPtrHolder<nsIContentAnalysisCallback>( "content analysis callback", aCallback)); CallbackData callbackData(std::move(callbackHolderCopy), aAutoAcknowledge); - rv = aRequest->GetRequestToken(requestToken); - NS_ENSURE_SUCCESS(rv, rv); { auto lock = mCallbackMap.Lock(); lock->InsertOrUpdate(requestToken, std::move(callbackData)); } + // Check URLs of requested info against + // browser.contentanalysis.allow_url_regex_list/deny_url_regex_list. + // Build the list once since creating regexs is slow. + // URLs that match the allow list are removed from the check. There is + // only one URL in all cases except downloads. If all contents are removed + // or the page URL is allowed (for downloads) then the operation is allowed. + // URLs that match the deny list block the entire operation. + // If the request is completely covered by this filter then flag it as + // not needing to send an Acknowledge. + auto filterResult = FilterByUrlLists(aRequest); + if (filterResult == ContentAnalysis::UrlFilterResult::eDeny) { + LOGD("Blocking request due to deny URL filter."); + auto response = ContentAnalysisResponse::FromAction( + nsIContentAnalysisResponse::Action::eBlock, requestToken); + response->DoNotAcknowledge(); + IssueResponse(response); + return NS_OK; + } + if (filterResult == ContentAnalysis::UrlFilterResult::eAllow) { + LOGD("Allowing request -- all operations match allow URL filter."); + auto response = ContentAnalysisResponse::FromAction( + nsIContentAnalysisResponse::Action::eAllow, requestToken); + response->DoNotAcknowledge(); + IssueResponse(response); + return NS_OK; + } + LOGD("Issuing ContentAnalysisRequest for token %s", requestToken.get()); + + content_analysis::sdk::ContentAnalysisRequest pbRequest; + rv = + ConvertToProtobuf(aRequest, GetUserActionId(), aRequestCount, &pbRequest); + NS_ENSURE_SUCCESS(rv, rv); LogRequest(&pbRequest); mCaClientPromise->Then( @@ -915,75 +1143,75 @@ void ContentAnalysis::DoAnalyzeRequest( LOGE("Content analysis got invalid response!"); return; } - nsCString responseRequestToken; - nsresult requestRv = response->GetRequestToken(responseRequestToken); - if (NS_FAILED(requestRv)) { - LOGE( - "Content analysis couldn't get request token " - "from response!"); - return; - } - Maybe<CallbackData> maybeCallbackData; - { - auto callbackMap = owner->mCallbackMap.Lock(); - maybeCallbackData = callbackMap->Extract(responseRequestToken); - } - if (maybeCallbackData.isNothing()) { - LOGD( - "Content analysis did not find callback for " - "token %s", - responseRequestToken.get()); - return; - } - response->SetOwner(owner); - if (maybeCallbackData->Canceled()) { - // request has already been cancelled, so there's - // nothing to do - LOGD( - "Content analysis got response but ignoring " - "because it was already cancelled for token %s", - responseRequestToken.get()); - // Note that we always acknowledge here, even if - // autoAcknowledge isn't set, since we raise an exception - // at the caller on cancellation. - auto acknowledgement = MakeRefPtr<ContentAnalysisAcknowledgement>( - nsIContentAnalysisAcknowledgement::Result::eTooLate, - nsIContentAnalysisAcknowledgement::FinalAction::eBlock); - response->Acknowledge(acknowledgement); - return; - } + owner->IssueResponse(response); + })); +} - LOGD( - "Content analysis resolving response promise for " - "token %s", - responseRequestToken.get()); - nsIContentAnalysisResponse::Action action = response->GetAction(); - nsCOMPtr<nsIObserverService> obsServ = - mozilla::services::GetObserverService(); - if (action == nsIContentAnalysisResponse::Action::eWarn) { - { - auto warnResponseDataMap = owner->mWarnResponseDataMap.Lock(); - warnResponseDataMap->InsertOrUpdate( - responseRequestToken, - WarnResponseData(std::move(*maybeCallbackData), response)); - } - obsServ->NotifyObservers(response, "dlp-response", nullptr); - return; - } +void ContentAnalysis::IssueResponse(RefPtr<ContentAnalysisResponse>& response) { + MOZ_ASSERT(NS_IsMainThread()); + nsCString responseRequestToken; + nsresult requestRv = response->GetRequestToken(responseRequestToken); + if (NS_FAILED(requestRv)) { + LOGE("Content analysis couldn't get request token from response!"); + return; + } - obsServ->NotifyObservers(response, "dlp-response", nullptr); - if (maybeCallbackData->AutoAcknowledge()) { - auto acknowledgement = MakeRefPtr<ContentAnalysisAcknowledgement>( - nsIContentAnalysisAcknowledgement::Result::eSuccess, - ConvertResult(action)); - response->Acknowledge(acknowledgement); - } + Maybe<CallbackData> maybeCallbackData; + { + auto callbackMap = mCallbackMap.Lock(); + maybeCallbackData = callbackMap->Extract(responseRequestToken); + } + if (maybeCallbackData.isNothing()) { + LOGD("Content analysis did not find callback for token %s", + responseRequestToken.get()); + return; + } + response->SetOwner(this); + if (maybeCallbackData->Canceled()) { + // request has already been cancelled, so there's + // nothing to do + LOGD( + "Content analysis got response but ignoring " + "because it was already cancelled for token %s", + responseRequestToken.get()); + // Note that we always acknowledge here, even if + // autoAcknowledge isn't set, since we raise an exception + // at the caller on cancellation. + auto acknowledgement = MakeRefPtr<ContentAnalysisAcknowledgement>( + nsIContentAnalysisAcknowledgement::Result::eTooLate, + nsIContentAnalysisAcknowledgement::FinalAction::eBlock); + response->Acknowledge(acknowledgement); + return; + } - nsMainThreadPtrHandle<nsIContentAnalysisCallback> callbackHolder = - maybeCallbackData->TakeCallbackHolder(); - callbackHolder->ContentResult(response); - })); + LOGD("Content analysis resolving response promise for token %s", + responseRequestToken.get()); + nsIContentAnalysisResponse::Action action = response->GetAction(); + nsCOMPtr<nsIObserverService> obsServ = + mozilla::services::GetObserverService(); + if (action == nsIContentAnalysisResponse::Action::eWarn) { + { + auto warnResponseDataMap = mWarnResponseDataMap.Lock(); + warnResponseDataMap->InsertOrUpdate( + responseRequestToken, + WarnResponseData(std::move(*maybeCallbackData), response)); + } + obsServ->NotifyObservers(response, "dlp-response", nullptr); + return; + } + + obsServ->NotifyObservers(response, "dlp-response", nullptr); + if (maybeCallbackData->AutoAcknowledge()) { + auto acknowledgement = MakeRefPtr<ContentAnalysisAcknowledgement>( + nsIContentAnalysisAcknowledgement::Result::eSuccess, + ConvertResult(action)); + response->Acknowledge(acknowledgement); + } + + nsMainThreadPtrHandle<nsIContentAnalysisCallback> callbackHolder = + maybeCallbackData->TakeCallbackHolder(); + callbackHolder->ContentResult(response); } NS_IMETHODIMP @@ -1018,7 +1246,11 @@ ContentAnalysis::AnalyzeContentRequestCallback( mozilla::services::GetObserverService(); obsServ->NotifyObservers(aRequest, "dlp-request-made", nullptr); - return RunAnalyzeRequestTask(aRequest, aAutoAcknowledge, aCallback); + MOZ_ASSERT(NS_IsMainThread()); + // since we're on the main thread, don't need to synchronize this + int64_t requestCount = ++mRequestCount; + return RunAnalyzeRequestTask(aRequest, aAutoAcknowledge, requestCount, + aCallback); } NS_IMETHODIMP @@ -1047,6 +1279,33 @@ ContentAnalysis::CancelContentAnalysisRequest(const nsACString& aRequestToken) { } NS_IMETHODIMP +ContentAnalysis::CancelAllRequests() { + mCaClientPromise->Then( + GetCurrentSerialEventTarget(), __func__, + [&](std::shared_ptr<content_analysis::sdk::Client> client) { + auto owner = GetContentAnalysisFromService(); + if (!owner) { + // May be shutting down + return; + } + if (!client) { + LOGE("CancelAllRequests got a null client"); + return; + } + content_analysis::sdk::ContentAnalysisCancelRequests requests; + requests.set_user_action_id(owner->GetUserActionId().get()); + int err = client->CancelRequests(requests); + if (err != 0) { + LOGE("CancelAllRequests got error %d", err); + } else { + LOGD("CancelAllRequests did cancelling of requests"); + } + }, + [&](nsresult rv) { LOGE("CancelAllRequests failed to get the client"); }); + return NS_OK; +} + +NS_IMETHODIMP ContentAnalysis::RespondToWarnDialog(const nsACString& aRequestToken, bool aAllowContent) { nsCString requestToken(aRequestToken); @@ -1108,6 +1367,10 @@ ContentAnalysisResponse::Acknowledge( return NS_ERROR_FAILURE; } mHasAcknowledged = true; + + if (mDoNotAcknowledge) { + return NS_OK; + } return mOwner->RunAcknowledgeTask(aAcknowledgement, mRequestToken); }; |