Bug 1916804: Make content analysis DND use getURIForDropEvent a=dmeehan

getURIForDropEvent delegates to getURIForBrowsingContext -- the ground truth for
CA URIs.

This also adds a check that getURIForDropEvent is correctly called in CA tests.
We do not yet test that it returns the right value -- that is future work.

Original Revision: https://phabricator.services.mozilla.com/D222192

Differential Revision: https://phabricator.services.mozilla.com/D227592
This commit is contained in:
David Parks 2024-11-05 15:35:37 +00:00
parent 3752ee37f2
commit c98cc41962
8 changed files with 77 additions and 29 deletions

View file

@ -11,8 +11,10 @@
#include "base/process_util.h" #include "base/process_util.h"
#include "GMPUtils.h" // ToHexString #include "GMPUtils.h" // ToHexString
#include "mozilla/Components.h" #include "mozilla/Components.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/CanonicalBrowsingContext.h" #include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/DataTransfer.h" #include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/DragEvent.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
@ -2339,6 +2341,22 @@ NS_IMETHODIMP ContentAnalysis::GetURIForBrowsingContext(
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
ContentAnalysis::GetURIForDropEvent(dom::DragEvent* aEvent, nsIURI** aURI) {
MOZ_ASSERT(XRE_IsParentProcess());
*aURI = nullptr;
auto* widgetEvent = aEvent->WidgetEventPtr();
MOZ_ASSERT(widgetEvent);
MOZ_ASSERT(widgetEvent->mClass == eDragEventClass &&
widgetEvent->mMessage == eDrop);
auto* bp =
dom::BrowserParent::GetBrowserParentFromLayersId(widgetEvent->mLayersId);
NS_ENSURE_TRUE(bp, NS_ERROR_FAILURE);
auto* bc = bp->GetBrowsingContext();
NS_ENSURE_TRUE(bc, NS_ERROR_FAILURE);
return GetURIForBrowsingContext(bc, aURI);
}
NS_IMETHODIMP ContentAnalysisCallback::ContentResult( NS_IMETHODIMP ContentAnalysisCallback::ContentResult(
nsIContentAnalysisResponse* aResponse) { nsIContentAnalysisResponse* aResponse) {
if (mPromise.isSome()) { if (mPromise.isSome()) {

View file

@ -7,6 +7,7 @@
interface nsIURI; interface nsIURI;
webidl BrowsingContext; webidl BrowsingContext;
webidl DragEvent;
webidl WindowGlobalParent; webidl WindowGlobalParent;
[scriptable, uuid(06e6a60f-3a2b-41fa-a63b-fea7a7f71649)] [scriptable, uuid(06e6a60f-3a2b-41fa-a63b-fea7a7f71649)]
@ -309,4 +310,10 @@ interface nsIContentAnalysis : nsISupports
* handles iframes. * handles iframes.
*/ */
nsIURI getURIForBrowsingContext(in BrowsingContext aBrowsingContext); nsIURI getURIForBrowsingContext(in BrowsingContext aBrowsingContext);
/**
* Gets the URI to use for the passed-in drop event. This correctly
* handles iframes.
*/
nsIURI getURIForDropEvent(in DragEvent aEvent);
}; };

View file

@ -24,6 +24,13 @@ let mockCA = {
mightBeActive: true, mightBeActive: true,
caShouldAllow: undefined, caShouldAllow: undefined,
numAnalyzeContentRequestCalls: undefined, numAnalyzeContentRequestCalls: undefined,
numGetURIForDropEvent: undefined,
getURIForDropEvent(event) {
info(`[${testName}]| Called getURIForDropEvent`);
this.numGetURIForDropEvent += 1;
return this.realCAService.getURIForDropEvent(event);
},
async analyzeContentRequest(_aRequest, _aAutoAcknowledge) { async analyzeContentRequest(_aRequest, _aAutoAcknowledge) {
info(`[${testName}]| Called analyzeContentRequest`); info(`[${testName}]| Called analyzeContentRequest`);
@ -76,6 +83,7 @@ runTest = async function (
info(testRootName); info(testRootName);
testName = testRootName; testName = testRootName;
mockCA.numAnalyzeContentRequestCalls = 0; mockCA.numAnalyzeContentRequestCalls = 0;
mockCA.numGetURIForDropEvent = 0;
await runDnd(testRootName, sourceBrowsingCxt, targetBrowsingCxt, { await runDnd(testRootName, sourceBrowsingCxt, targetBrowsingCxt, {
...dndOptions, ...dndOptions,
}); });
@ -84,6 +92,11 @@ runTest = async function (
0, 0,
`[${testName}]| AnalyzeContentRequest was not called` `[${testName}]| AnalyzeContentRequest was not called`
); );
is(
mockCA.numGetURIForDropEvent,
0,
`[${testName}]| GetURIForDropEvent was not called`
);
return; return;
} }
@ -93,6 +106,7 @@ runTest = async function (
testName = name; testName = name;
mockCA.caShouldAllow = caShouldAllow; mockCA.caShouldAllow = caShouldAllow;
mockCA.numAnalyzeContentRequestCalls = 0; mockCA.numAnalyzeContentRequestCalls = 0;
mockCA.numGetURIForDropEvent = 0;
let dropPromise = new Promise(res => { let dropPromise = new Promise(res => {
resolveDropPromise = res; resolveDropPromise = res;
}); });
@ -106,5 +120,10 @@ runTest = async function (
1, 1,
`[${testName}]| Called AnalyzeContentRequest once` `[${testName}]| Called AnalyzeContentRequest once`
); );
is(
mockCA.numGetURIForDropEvent,
1,
`[${testName}]| GetURIForDropEvent was called exactly once`
);
} }
}; };

View file

@ -24,6 +24,13 @@ let mockCA = {
mightBeActive: true, mightBeActive: true,
caShouldAllow: undefined, caShouldAllow: undefined,
numAnalyzeContentRequestCalls: undefined, numAnalyzeContentRequestCalls: undefined,
numGetURIForDropEvent: undefined,
getURIForDropEvent(event) {
info(`[${testName}]| Called getURIForDropEvent`);
this.numGetURIForDropEvent += 1;
return this.realCAService.getURIForDropEvent(event);
},
async analyzeContentRequest(_aRequest, _aAutoAcknowledge) { async analyzeContentRequest(_aRequest, _aAutoAcknowledge) {
info(`[${testName}]| Called analyzeContentRequest`); info(`[${testName}]| Called analyzeContentRequest`);
@ -76,6 +83,7 @@ runTest = async function (
info(testRootName); info(testRootName);
testName = testRootName; testName = testRootName;
mockCA.numAnalyzeContentRequestCalls = 0; mockCA.numAnalyzeContentRequestCalls = 0;
mockCA.numGetURIForDropEvent = 0;
await runDnd(testRootName, sourceBrowsingCxt, targetBrowsingCxt, { await runDnd(testRootName, sourceBrowsingCxt, targetBrowsingCxt, {
...dndOptions, ...dndOptions,
}); });
@ -84,6 +92,11 @@ runTest = async function (
0, 0,
`[${testName}]| AnalyzeContentRequest was not called` `[${testName}]| AnalyzeContentRequest was not called`
); );
is(
mockCA.numGetURIForDropEvent,
0,
`[${testName}]| GetURIForDropEvent was not called`
);
return; return;
} }
@ -93,6 +106,7 @@ runTest = async function (
testName = name; testName = name;
mockCA.caShouldAllow = caShouldAllow; mockCA.caShouldAllow = caShouldAllow;
mockCA.numAnalyzeContentRequestCalls = 0; mockCA.numAnalyzeContentRequestCalls = 0;
mockCA.numGetURIForDropEvent = 0;
let dropPromise = new Promise(res => { let dropPromise = new Promise(res => {
resolveDropPromise = res; resolveDropPromise = res;
}); });
@ -106,5 +120,10 @@ runTest = async function (
1, 1,
`[${testName}]| Called AnalyzeContentRequest once` `[${testName}]| Called AnalyzeContentRequest once`
); );
is(
mockCA.numGetURIForDropEvent,
1,
`[${testName}]| GetURIForDropEvent was called exactly once`
);
} }
}; };

View file

@ -54,17 +54,24 @@ function mockService(serviceNames, contractId, interfaceObj, mockService) {
/** /**
* Mock the nsIContentAnalysis service with the object mockCAService. * Mock the nsIContentAnalysis service with the object mockCAService.
* *
* @param {object} mockCAService * @param {object} mockCAServiceTemplate
* the service to mock for nsIContentAnalysis * the mock nsIContentAnalysis template object
* @returns {object} The newly-mocked service * @returns {object} The newly-mocked service that integrates the template
*/ */
function mockContentAnalysisService(mockCAService) { function mockContentAnalysisService(mockCAServiceTemplate) {
return mockService( let realCAService = SpecialPowers.Cc[
"@mozilla.org/contentanalysis;1"
].getService(SpecialPowers.Ci.nsIContentAnalysis);
let mockCAService = mockService(
["nsIContentAnalysis"], ["nsIContentAnalysis"],
"@mozilla.org/contentanalysis;1", "@mozilla.org/contentanalysis;1",
Ci.nsIContentAnalysis, Ci.nsIContentAnalysis,
mockCAService mockCAServiceTemplate
); );
if (mockCAService) {
mockCAService.realCAService = realCAService;
}
return mockCAService;
} }
/** /**

View file

@ -239,7 +239,7 @@
{ {
requestToken: Services.uuid.generateUUID().toString(), requestToken: Services.uuid.generateUUID().toString(),
resources: [], resources: [],
url: dragSession.uriForEvent(event), url: lazy.contentAnalysis.getURIForDropEvent(event),
windowGlobalParent: windowGlobalParent:
this.browsingContext.currentWindowContext, this.browsingContext.currentWindowContext,
...requestFields, ...requestFields,

View file

@ -1275,22 +1275,6 @@ nsIWidget* nsBaseDragService::GetWidgetFromWidgetProvider(
return vm->GetRootWidget(); return vm->GetRootWidget();
} }
NS_IMETHODIMP
nsBaseDragSession::UriForEvent(DragEvent* aEvent, nsIURI** aUri) {
MOZ_ASSERT(XRE_IsParentProcess());
*aUri = nullptr;
auto* widgetEvent = aEvent->WidgetEventPtr();
MOZ_ASSERT(widgetEvent);
auto* bp =
dom::BrowserParent::GetBrowserParentFromLayersId(widgetEvent->mLayersId);
NS_ENSURE_TRUE(bp, NS_ERROR_FAILURE);
auto* bc = bp->GetBrowsingContext();
NS_ENSURE_TRUE(bc, NS_ERROR_FAILURE);
RefPtr<nsIURI> ret = bc->GetCurrentURI();
ret.forget(aUri);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsBaseDragSession::SendStoreDropTargetAndDelayEndDragSession( nsBaseDragSession::SendStoreDropTargetAndDelayEndDragSession(
DragEvent* aEvent) { DragEvent* aEvent) {

View file

@ -215,12 +215,6 @@ interface nsIDragSession : nsISupports
void endDragSession(in boolean aDoneDrag, void endDragSession(in boolean aDoneDrag,
[optional] in unsigned long aKeyModifiers); [optional] in unsigned long aKeyModifiers);
/**
* Returns the URI that should be used in a content analysis request for
* the given drag event.
*/
nsIURI uriForEvent(in DragEvent event);
/** /**
* Tell the drag session for the given browser that it * Tell the drag session for the given browser that it
* should store the would-be target of the aEvent (a drop event) and delay * should store the would-be target of the aEvent (a drop event) and delay