forked from mirrors/gecko-dev
		
	Bug 1919755 - correctly calculate content analysis URL for local PDF file a=dmeehan
This was already working for remote PDF files but I went ahead and added tests for both. Original Revision: https://phabricator.services.mozilla.com/D223639 Differential Revision: https://phabricator.services.mozilla.com/D226391
This commit is contained in:
		
							parent
							
								
									ca35f40858
								
							
						
					
					
						commit
						e99d78b4cd
					
				
					 8 changed files with 340 additions and 6 deletions
				
			
		|  | @ -2300,6 +2300,7 @@ ContentAnalysis::GetDiagnosticInfo(JSContext* aCx, | |||
|   if (!windowGlobal) { | ||||
|     return nullptr; | ||||
|   } | ||||
|   dom::CanonicalBrowsingContext* oldBrowsingContext = aBrowsingContext; | ||||
|   nsIPrincipal* principal = windowGlobal->DocumentPrincipal(); | ||||
|   dom::CanonicalBrowsingContext* curBrowsingContext = | ||||
|       aBrowsingContext->GetParent(); | ||||
|  | @ -2314,8 +2315,19 @@ ContentAnalysis::GetDiagnosticInfo(JSContext* aCx, | |||
|       break; | ||||
|     } | ||||
|     principal = newPrincipal; | ||||
|     oldBrowsingContext = curBrowsingContext; | ||||
|     curBrowsingContext = curBrowsingContext->GetParent(); | ||||
|   } | ||||
|   if (nsContentUtils::IsPDFJS(principal)) { | ||||
|     // the principal's URI is the URI of the pdf.js reader
 | ||||
|     // so get the document's URI
 | ||||
|     dom::WindowContext* windowContext = | ||||
|         oldBrowsingContext->GetCurrentWindowContext(); | ||||
|     if (!windowContext) { | ||||
|       return nullptr; | ||||
|     } | ||||
|     return windowContext->Canonical()->GetDocumentURI(); | ||||
|   } | ||||
|   return principal->GetURI(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -58,3 +58,17 @@ support-files = [ | |||
|   "!/toolkit/components/printing/tests/simplifyArticleSample.html", | ||||
|   "clipboard_print_iframe.html", | ||||
| ] | ||||
| 
 | ||||
| ["browser_print_pdf_local_content_analysis.js"] | ||||
| support-files = [ | ||||
|   "!/toolkit/components/printing/tests/head.js", | ||||
|   "browser_print_pdf_content_analysis_impl.js", | ||||
|   "file_pdf.pdf", | ||||
| ] | ||||
| 
 | ||||
| ["browser_print_pdf_remote_content_analysis.js"] | ||||
| support-files = [ | ||||
|   "!/toolkit/components/printing/tests/head.js", | ||||
|   "browser_print_pdf_content_analysis_impl.js", | ||||
|   "file_pdf.pdf", | ||||
| ] | ||||
|  |  | |||
|  | @ -0,0 +1,273 @@ | |||
| /* Any copyright is dedicated to the Public Domain. | ||||
|    http://creativecommons.org/publicdomain/zero/1.0/ */
 | ||||
| 
 | ||||
| Services.scriptloader.loadSubScript( | ||||
|   "chrome://mochitests/content/browser/toolkit/components/printing/tests/head.js", | ||||
|   this | ||||
| ); | ||||
| 
 | ||||
| const PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].getService( | ||||
|   Ci.nsIPrintSettingsService | ||||
| ); | ||||
| 
 | ||||
| let mockCA = makeMockContentAnalysis(); | ||||
| 
 | ||||
| add_setup(async function test_setup() { | ||||
|   mockCA = mockContentAnalysisService(mockCA); | ||||
| }); | ||||
| 
 | ||||
| let testPDFUrl; | ||||
| // Callers should set testPDFUrl
 | ||||
| 
 | ||||
| function addUniqueSuffix(prefix) { | ||||
|   return `${prefix}-${Services.uuid | ||||
|     .generateUUID() | ||||
|     .toString() | ||||
|     .slice(1, -1)}.pdf`;
 | ||||
| } | ||||
| 
 | ||||
| async function printToDestination(aBrowser, aDestination) { | ||||
|   let tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile); | ||||
|   let fileName = addUniqueSuffix(`printDestinationTest-${aDestination}`); | ||||
|   let filePath = PathUtils.join(tmpDir.path, fileName); | ||||
| 
 | ||||
|   info(`Printing to ${filePath}`); | ||||
| 
 | ||||
|   let settings = PSSVC.createNewPrintSettings(); | ||||
|   settings.outputFormat = Ci.nsIPrintSettings.kOutputFormatPDF; | ||||
|   settings.outputDestination = aDestination; | ||||
| 
 | ||||
|   settings.headerStrCenter = ""; | ||||
|   settings.headerStrLeft = ""; | ||||
|   settings.headerStrRight = ""; | ||||
|   settings.footerStrCenter = ""; | ||||
|   settings.footerStrLeft = ""; | ||||
|   settings.footerStrRight = ""; | ||||
| 
 | ||||
|   settings.unwriteableMarginTop = 1; /* Just to ensure settings are respected on both */ | ||||
|   let outStream = null; | ||||
|   if (aDestination == Ci.nsIPrintSettings.kOutputDestinationFile) { | ||||
|     settings.toFileName = PathUtils.join(tmpDir.path, fileName); | ||||
|   } else { | ||||
|     is(aDestination, Ci.nsIPrintSettings.kOutputDestinationStream); | ||||
|     outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance( | ||||
|       Ci.nsIFileOutputStream | ||||
|     ); | ||||
|     let tmpFile = tmpDir.clone(); | ||||
|     tmpFile.append(fileName); | ||||
|     outStream.init(tmpFile, -1, 0o666, 0); | ||||
|     settings.outputStream = outStream; | ||||
|   } | ||||
| 
 | ||||
|   await aBrowser.browsingContext.print(settings); | ||||
| 
 | ||||
|   return filePath; | ||||
| } | ||||
| 
 | ||||
| function assertContentAnalysisRequest(request, expectedUrl) { | ||||
|   is(request.url.spec, expectedUrl ?? testPDFUrl, "request has correct URL"); | ||||
|   is( | ||||
|     request.analysisType, | ||||
|     Ci.nsIContentAnalysisRequest.ePrint, | ||||
|     "request has print analysisType" | ||||
|   ); | ||||
|   is( | ||||
|     request.operationTypeForDisplay, | ||||
|     Ci.nsIContentAnalysisRequest.eOperationPrint, | ||||
|     "request has print operationTypeForDisplay" | ||||
|   ); | ||||
|   is(request.textContent, "", "request textContent should be empty"); | ||||
|   is(request.filePath, "", "request filePath should be empty"); | ||||
|   isnot(request.printDataHandle, 0, "request printDataHandle should not be 0"); | ||||
|   isnot(request.printDataSize, 0, "request printDataSize should not be 0"); | ||||
|   ok(!!request.requestToken.length, "request requestToken should not be empty"); | ||||
| } | ||||
| 
 | ||||
| // Printing to a stream is different than going through the print preview dialog because it
 | ||||
| // doesn't make a static clone of the document before the print, which causes the
 | ||||
| // Content Analysis code to go through a different code path. This is similar to what
 | ||||
| // happens when various preferences are set to skip the print preview dialog, for example
 | ||||
| // print.prefer_system_dialog.
 | ||||
| add_task( | ||||
|   async function testPrintToStreamWithContentAnalysisActiveAndAllowing() { | ||||
|     await PrintHelper.withTestPage( | ||||
|       async helper => { | ||||
|         mockCA.setupForTest(true); | ||||
| 
 | ||||
|         let filePath = await printToDestination( | ||||
|           helper.sourceBrowser, | ||||
|           Ci.nsIPrintSettings.kOutputDestinationFile | ||||
|         ); | ||||
|         is( | ||||
|           mockCA.calls.length, | ||||
|           1, | ||||
|           "Correct number of calls to Content Analysis" | ||||
|         ); | ||||
|         assertContentAnalysisRequest(mockCA.calls[0]); | ||||
| 
 | ||||
|         await waitForFileToAlmostMatchSize( | ||||
|           filePath, | ||||
|           mockCA.calls[0].printDataSize | ||||
|         ); | ||||
| 
 | ||||
|         await IOUtils.remove(filePath); | ||||
|       }, | ||||
|       testPDFUrl, | ||||
|       true | ||||
|     ); | ||||
|   } | ||||
| ); | ||||
| 
 | ||||
| add_task( | ||||
|   async function testPrintToStreamWithContentAnalysisActiveAndBlocking() { | ||||
|     await PrintHelper.withTestPage( | ||||
|       async helper => { | ||||
|         mockCA.setupForTest(false); | ||||
| 
 | ||||
|         try { | ||||
|           await printToDestination( | ||||
|             helper.sourceBrowser, | ||||
|             Ci.nsIPrintSettings.kOutputDestinationFile | ||||
|           ); | ||||
|           ok(false, "Content analysis should make this fail to print"); | ||||
|         } catch (e) { | ||||
|           ok( | ||||
|             /NS_ERROR_CONTENT_BLOCKED/.test(e.toString()), | ||||
|             "Got content blocked error" | ||||
|           ); | ||||
|         } | ||||
|         is( | ||||
|           mockCA.calls.length, | ||||
|           1, | ||||
|           "Correct number of calls to Content Analysis" | ||||
|         ); | ||||
|         assertContentAnalysisRequest(mockCA.calls[0]); | ||||
|       }, | ||||
|       testPDFUrl, | ||||
|       true | ||||
|     ); | ||||
|   } | ||||
| ); | ||||
| 
 | ||||
| add_task(async function testPrintToStreamWithContentAnalysisReturningError() { | ||||
|   await PrintHelper.withTestPage( | ||||
|     async helper => { | ||||
|       expectUncaughtException(); | ||||
|       mockCA.setupForTestWithError(Cr.NS_ERROR_NOT_AVAILABLE); | ||||
| 
 | ||||
|       try { | ||||
|         await printToDestination( | ||||
|           helper.sourceBrowser, | ||||
|           Ci.nsIPrintSettings.kOutputDestinationFile | ||||
|         ); | ||||
|         ok(false, "Content analysis should make this fail to print"); | ||||
|       } catch (e) { | ||||
|         ok( | ||||
|           /NS_ERROR_NOT_AVAILABLE/.test(e.toString()), | ||||
|           "Error in mock CA was propagated out" | ||||
|         ); | ||||
|       } | ||||
|       is(mockCA.calls.length, 1, "Correct number of calls to Content Analysis"); | ||||
|       assertContentAnalysisRequest(mockCA.calls[0]); | ||||
|     }, | ||||
|     testPDFUrl, | ||||
|     true | ||||
|   ); | ||||
| }); | ||||
| 
 | ||||
| add_task(async function testPrintThroughDialogWithContentAnalysisActive() { | ||||
|   await PrintHelper.withTestPage( | ||||
|     async helper => { | ||||
|       mockCA.setupForTest(true); | ||||
| 
 | ||||
|       await helper.startPrint(); | ||||
|       let fileName = addUniqueSuffix(`printDialogTest`); | ||||
|       let file = helper.mockFilePicker(fileName); | ||||
|       info(`Printing to ${file.path}`); | ||||
|       await helper.assertPrintToFile(file, () => { | ||||
|         EventUtils.sendKey("return", helper.win); | ||||
|       }); | ||||
| 
 | ||||
|       is(mockCA.calls.length, 1, "Correct number of calls to Content Analysis"); | ||||
|       assertContentAnalysisRequest(mockCA.calls[0]); | ||||
| 
 | ||||
|       await waitForFileToAlmostMatchSize( | ||||
|         file.path, | ||||
|         mockCA.calls[0].printDataSize | ||||
|       ); | ||||
|     }, | ||||
|     testPDFUrl, | ||||
|     true | ||||
|   ); | ||||
| }); | ||||
| 
 | ||||
| add_task( | ||||
|   async function testPrintThroughDialogWithContentAnalysisActiveAndBlocking() { | ||||
|     await PrintHelper.withTestPage( | ||||
|       async helper => { | ||||
|         mockCA.setupForTest(false); | ||||
| 
 | ||||
|         await helper.startPrint(); | ||||
|         let fileName = addUniqueSuffix(`printDialogTest`); | ||||
|         let file = helper.mockFilePicker(fileName); | ||||
|         info(`Printing to ${file.path}`); | ||||
|         try { | ||||
|           await helper.assertPrintToFile(file, () => { | ||||
|             EventUtils.sendKey("return", helper.win); | ||||
|           }); | ||||
|         } catch (e) { | ||||
|           ok( | ||||
|             /Wait for target file to get created/.test(e.toString()), | ||||
|             "Target file should not get created" | ||||
|           ); | ||||
|         } | ||||
|         ok(!file.exists(), "File should not exist"); | ||||
| 
 | ||||
|         is( | ||||
|           mockCA.calls.length, | ||||
|           1, | ||||
|           "Correct number of calls to Content Analysis" | ||||
|         ); | ||||
|         assertContentAnalysisRequest(mockCA.calls[0]); | ||||
|       }, | ||||
|       testPDFUrl, | ||||
|       true | ||||
|     ); | ||||
|   } | ||||
| ); | ||||
| 
 | ||||
| add_task( | ||||
|   async function testPrintThroughDialogWithContentAnalysisReturningError() { | ||||
|     await PrintHelper.withTestPage( | ||||
|       async helper => { | ||||
|         expectUncaughtException(); | ||||
|         mockCA.setupForTestWithError(Cr.NS_ERROR_NOT_AVAILABLE); | ||||
| 
 | ||||
|         await helper.startPrint(); | ||||
|         let fileName = addUniqueSuffix(`printDialogTest`); | ||||
|         let file = helper.mockFilePicker(fileName); | ||||
|         info(`Printing to ${file.path}`); | ||||
|         try { | ||||
|           await helper.assertPrintToFile(file, () => { | ||||
|             EventUtils.sendKey("return", helper.win); | ||||
|           }); | ||||
|         } catch (e) { | ||||
|           ok( | ||||
|             /Wait for target file to get created/.test(e.toString()), | ||||
|             "Target file should not get created" | ||||
|           ); | ||||
|         } | ||||
|         ok(!file.exists(), "File should not exist"); | ||||
| 
 | ||||
|         is( | ||||
|           mockCA.calls.length, | ||||
|           1, | ||||
|           "Correct number of calls to Content Analysis" | ||||
|         ); | ||||
|         assertContentAnalysisRequest(mockCA.calls[0]); | ||||
|       }, | ||||
|       testPDFUrl, | ||||
|       true | ||||
|     ); | ||||
|   } | ||||
| ); | ||||
|  | @ -0,0 +1,14 @@ | |||
| /* Any copyright is dedicated to the Public Domain. | ||||
|    http://creativecommons.org/publicdomain/zero/1.0/ */
 | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| Services.scriptloader.loadSubScript( | ||||
|   "chrome://mochitests/content/browser/toolkit/components/contentanalysis/tests/browser/browser_print_pdf_content_analysis_impl.js", | ||||
|   this | ||||
| ); | ||||
| 
 | ||||
| let dir = getChromeDir(getResolvedURI(gTestPath)); | ||||
| dir.append("file_pdf.pdf"); | ||||
| dir.normalize(); | ||||
| testPDFUrl = Services.io.newFileURI(dir).spec; | ||||
|  | @ -0,0 +1,12 @@ | |||
| /* Any copyright is dedicated to the Public Domain. | ||||
|    http://creativecommons.org/publicdomain/zero/1.0/ */
 | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| Services.scriptloader.loadSubScript( | ||||
|   "chrome://mochitests/content/browser/toolkit/components/contentanalysis/tests/browser/browser_print_pdf_content_analysis_impl.js", | ||||
|   this | ||||
| ); | ||||
| 
 | ||||
| testPDFUrl = | ||||
|   "https://example.com/browser/toolkit/components/contentanalysis/tests/browser/file_pdf.pdf"; | ||||
|  | @ -0,0 +1,12 @@ | |||
| %PDF-1.0 | ||||
| 1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj 2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj 3 0 obj<</Type/Page/MediaBox[0 0 3 3]>>endobj | ||||
| xref | ||||
| 0 4 | ||||
| 0000000000 65535 f | ||||
| 0000000010 00000 n | ||||
| 0000000053 00000 n | ||||
| 0000000102 00000 n | ||||
| trailer<</Size 4/Root 1 0 R>> | ||||
| startxref | ||||
| 149 | ||||
| %EOF | ||||
|  | @ -190,11 +190,8 @@ function makeMockContentAnalysis() { | |||
|     }, | ||||
| 
 | ||||
|     getURIForBrowsingContext(aBrowsingContext) { | ||||
|       // The real implementation walks up the parent chain as long
 | ||||
|       // as the parent principal subsumes the child one. For testing
 | ||||
|       // purposes, just return the browsing context's URI.
 | ||||
|       this.browsingContextsForURIs.push(aBrowsingContext); | ||||
|       return aBrowsingContext.currentURI; | ||||
|       return this.realCAService.getURIForBrowsingContext(aBrowsingContext); | ||||
|     }, | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ class PrintHelper { | |||
|   } | ||||
| 
 | ||||
|   static getTestPageUrl(pathName) { | ||||
|     if (pathName.startsWith("http://")) { | ||||
|     if (pathName.startsWith("http://") || pathName.startsWith("file://")) { | ||||
|       return pathName; | ||||
|     } | ||||
|     const testPath = getRootDirectory(gTestPath).replace( | ||||
|  | @ -71,7 +71,7 @@ class PrintHelper { | |||
|   } | ||||
| 
 | ||||
|   static getTestPageUrlHTTPS(pathName) { | ||||
|     if (pathName.startsWith("https://")) { | ||||
|     if (pathName.startsWith("https://") || pathName.startsWith("file://")) { | ||||
|       return pathName; | ||||
|     } | ||||
|     const testPath = getRootDirectory(gTestPath).replace( | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Greg Stoll
						Greg Stoll