diff --git a/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm b/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm index 55d5ccc36d..3a43ddd494 100644 --- a/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm +++ b/application/basilisk/extensions/pdfjs/content/PdfStreamConverter.jsm @@ -871,6 +871,11 @@ PdfStreamConverter.prototype = { aRequest.setResponseHeader("Refresh", "", false); } + // The document will be loaded via the stream converter as html, but we + // may have come here via a download/attachment path. Force inline so we + // don't get redirected back to the external helper service. + aRequest.contentDisposition = Ci.nsIChannel.DISPOSITION_FORCE_INLINE; + // Creating storage for PDF data var contentLength = aRequest.contentLength; this.dataListener = new PdfDataListener(contentLength); diff --git a/netwerk/base/nsIChannel.idl b/netwerk/base/nsIChannel.idl index 743e942920..4ffd1aaf99 100644 --- a/netwerk/base/nsIChannel.idl +++ b/netwerk/base/nsIChannel.idl @@ -293,10 +293,14 @@ interface nsIChannel : nsIRequest * if available and if applicable. This allows determining inline versus * attachment. * - * Setting contentDisposition provides a hint to the channel about the - * disposition. If a normal Content-Disposition header is present its - * value will always be used. If it is missing the hinted value will - * be used if set. + * Setting contentDisposition provides a hint to the channel about the + * disposition. If the hint is DISPOSITION_ATTACHMENT and a normal + * Content-Disposition header is present, the hinted value will always be + * used. If the hint is DISPOSITION_FORCE_INLINE then the disposition is + * inline and the header is not used. The value from Content-Disposition + * header is only used when the hinted value is not DISPOSITION_INLINE or + * DISPOSITION_FORCE_INLINE. + * If the header is missing the hinted value will be used if set. * * Implementations should throw NS_ERROR_NOT_AVAILABLE if the header either * doesn't exist for this type of channel or is empty, and return @@ -305,6 +309,7 @@ interface nsIChannel : nsIRequest attribute unsigned long contentDisposition; const unsigned long DISPOSITION_INLINE = 0; const unsigned long DISPOSITION_ATTACHMENT = 1; + const unsigned long DISPOSITION_FORCE_INLINE = 2; /** * Access to the filename portion of the Content-Disposition header if diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 3c5fa6763a..aee8f29e9f 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -511,6 +511,14 @@ HttpBaseChannel::SetContentCharset(const nsACString& aContentCharset) NS_IMETHODIMP HttpBaseChannel::GetContentDisposition(uint32_t *aContentDisposition) { + // DISPOSITION_FORCE_INLINE is used to explicitly set inline, used by + // the pdf reader when loading an attachment pdf without downloading it. + if (mContentDispositionHint == nsIChannel::DISPOSITION_ATTACHMENT || + mContentDispositionHint == nsIChannel::DISPOSITION_FORCE_INLINE) { + *aContentDisposition = mContentDispositionHint; + return NS_OK; + } + nsresult rv; nsCString header; diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp index 224f2219ed..d3f70ce191 100644 --- a/uriloader/base/nsURILoader.cpp +++ b/uriloader/base/nsURILoader.cpp @@ -41,6 +41,10 @@ #include "nsCExternalHandlerService.h" // contains contractids for the helper app service #include "nsIMIMEHeaderParam.h" +#include "nsIMIMEInfo.h" +#include "nsIMIMEService.h" +#include "nsILoadInfo.h" +#include "nsIContentPolicy.h" #include "nsNetCID.h" #include "nsMimeTypes.h" @@ -389,6 +393,36 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports * forceExternalHandling = true; } + // For a PDF, check if it will be handled internally. If so, don't force + // external handling for top-level document loads. + if (forceExternalHandling && + mContentType.LowerCaseEqualsASCII(APPLICATION_PDF)) { + nsCOMPtr loadInfo; + aChannel->GetLoadInfo(getter_AddRefs(loadInfo)); + if (loadInfo && + loadInfo->GetExternalContentPolicyType() == + nsIContentPolicy::TYPE_DOCUMENT) { + nsCOMPtr mimeInfo; + nsCOMPtr mimeSvc( + do_GetService(NS_MIMESERVICE_CONTRACTID)); + if (mimeSvc) { + mimeSvc->GetFromTypeAndExtension(nsLiteralCString(APPLICATION_PDF), + EmptyCString(), + getter_AddRefs(mimeInfo)); + } + + if (mimeInfo) { + int32_t action = nsIHandlerInfo::saveToDisk; + mimeInfo->GetPreferredAction(&action); + + bool alwaysAsk = true; + mimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk); + forceExternalHandling = + alwaysAsk || action != nsIHandlerInfo::handleInternally; + } + } + } + LOG((" forceExternalHandling: %s", forceExternalHandling ? "yes" : "no")); // The type or data the contentListener wants. diff --git a/uriloader/exthandler/ContentHandlerService.cpp b/uriloader/exthandler/ContentHandlerService.cpp index 75575a7304..ec2da390b4 100644 --- a/uriloader/exthandler/ContentHandlerService.cpp +++ b/uriloader/exthandler/ContentHandlerService.cpp @@ -104,7 +104,9 @@ NS_IMETHODIMP RemoteHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequesto NS_IMPL_ISUPPORTS(RemoteHandlerApp, nsIHandlerApp) -static inline void CopyHanderInfoTonsIHandlerInfo(HandlerInfo info, nsIHandlerInfo* aHandlerInfo) +static inline void +CopyHandlerInfoTonsIHandlerInfo(const HandlerInfo& info, + nsIHandlerInfo* aHandlerInfo) { HandlerApp preferredApplicationHandler = info.preferredApplicationHandler(); nsCOMPtr preferredApp(new RemoteHandlerApp(preferredApplicationHandler)); @@ -112,6 +114,8 @@ static inline void CopyHanderInfoTonsIHandlerInfo(HandlerInfo info, nsIHandlerIn nsCOMPtr possibleHandlers; aHandlerInfo->GetPossibleApplicationHandlers(getter_AddRefs(possibleHandlers)); possibleHandlers->AppendElement(preferredApp, false); + aHandlerInfo->SetPreferredAction(info.preferredAction()); + aHandlerInfo->SetAlwaysAskBeforeHandling(info.alwaysAskBeforeHandling()); } ContentHandlerService::~ContentHandlerService() { @@ -127,7 +131,7 @@ NS_IMETHODIMP ContentHandlerService::FillHandlerInfo(nsIHandlerInfo *aHandlerInf HandlerInfo info; nsIHandlerInfoToHandlerInfo(aHandlerInfo, &info); mHandlerServiceChild->SendFillHandlerInfo(info, nsCString(aOverrideType), &info); - CopyHanderInfoTonsIHandlerInfo(info, aHandlerInfo); + CopyHandlerInfoTonsIHandlerInfo(info, aHandlerInfo); return NS_OK; } diff --git a/uriloader/exthandler/PHandlerService.ipdl b/uriloader/exthandler/PHandlerService.ipdl index bcaab60ac3..9171ef2982 100644 --- a/uriloader/exthandler/PHandlerService.ipdl +++ b/uriloader/exthandler/PHandlerService.ipdl @@ -19,7 +19,7 @@ struct HandlerInfo { bool alwaysAskBeforeHandling; HandlerApp preferredApplicationHandler; HandlerApp[] possibleApplicationHandlers; - long preferredAction; + int32_t preferredAction; }; sync protocol PHandlerService