Bug 1807260 - ensure nsMimeInfoWin's default app information is always-up-to-date, r=mhowell,necko-reviewers,kershaw

Differential Revision: https://phabricator.services.mozilla.com/D169712
This commit is contained in:
Gijs Kruitbosch 2023-02-20 16:44:18 +00:00
parent 97f7ae55a3
commit 3dca426d77
8 changed files with 79 additions and 20 deletions

View File

@ -110,6 +110,14 @@ interface nsIMIMEService : nsISupports {
in ACString aFileExtension,
out boolean aFound);
/**
* Update the mime info's default app information based on OS
* lookups.
* Note: normally called automatically by nsIMIMEInfo. If you find
* yourself needing to call this from elsewhere, file a bug instead.
*/
void updateDefaultAppInfo(in nsIMIMEInfo aMIMEInfo);
/**
* Default filename validation for getValidFileName and
* validateFileNameForSaving where other flags are not true.

View File

@ -3200,6 +3200,11 @@ nsresult nsExternalHelperAppService::GetMIMEInfoFromOS(
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsExternalHelperAppService::UpdateDefaultAppInfo(
nsIMIMEInfo* aMIMEInfo) {
return NS_ERROR_NOT_IMPLEMENTED;
}
bool nsExternalHelperAppService::GetFileNameFromChannel(nsIChannel* aChannel,
nsAString& aFileName,
nsIURI** aURI) {

View File

@ -140,10 +140,14 @@ nsMIMEInfoBase::SetPrimaryExtension(const nsACString& aExtension) {
mExtensions.RemoveElementAt(i);
}
mExtensions.InsertElementAt(0, aExtension);
mIsDefaultAppInfoFresh = false;
return NS_OK;
}
void nsMIMEInfoBase::AddUniqueExtension(const nsACString& aExtension) {
if (mExtensions.IsEmpty()) {
mIsDefaultAppInfoFresh = false;
}
if (!aExtension.IsEmpty() &&
!mExtensions.Contains(aExtension,
nsCaseInsensitiveCStringArrayComparator())) {

View File

@ -163,6 +163,7 @@ class nsMIMEInfoBase : public nsIMIMEInfo {
nsString mPreferredAppDescription;
nsString mDefaultAppDescription;
bool mAlwaysAskBeforeHandling;
bool mIsDefaultAppInfoFresh = false;
};
/**
@ -194,7 +195,8 @@ class nsMIMEInfoImpl : public nsMIMEInfoBase {
* App Services.
*/
void SetDefaultApplication(nsIFile* aApp) {
if (!mDefaultApplication) mDefaultApplication = aApp;
mDefaultApplication = aApp;
mIsDefaultAppInfoFresh = true;
}
protected:

View File

@ -343,6 +343,16 @@ nsresult nsMIMEInfoWin::LoadUriInternal(nsIURI* aURL) {
return rv;
}
void nsMIMEInfoWin::UpdateDefaultInfoIfStale() {
if (!mIsDefaultAppInfoFresh) {
nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1");
if (mime) {
mime->UpdateDefaultAppInfo(static_cast<nsIMIMEInfo*>(this));
}
mIsDefaultAppInfoFresh = true;
}
}
// Given a path to a local file, return its nsILocalHandlerApp instance.
bool nsMIMEInfoWin::GetLocalHandlerApp(const nsAString& aCommandHandler,
nsCOMPtr<nsILocalHandlerApp>& aApp) {

View File

@ -25,6 +25,8 @@ class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag {
NS_IMETHOD GetPossibleLocalHandlers(nsIArray** _retval) override;
NS_IMETHOD IsCurrentAppOSDefault(bool* _retval) override;
void UpdateDefaultInfoIfStale();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPROPERTYBAG
@ -33,7 +35,10 @@ class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag {
}
protected:
nsIFile* GetDefaultApplication() { return mDefaultApplication; }
nsIFile* GetDefaultApplication() {
UpdateDefaultInfoIfStale();
return mDefaultApplication;
}
virtual nsresult LoadUriInternal(nsIURI* aURI);
virtual nsresult LaunchDefaultWithFile(nsIFile* aFile);

View File

@ -366,28 +366,46 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(
RefPtr<nsMIMEInfoWin> mimeInfo = new nsMIMEInfoWin(typeToUse);
// windows registry assumes your file extension is going to include the '.',
// but our APIs expect it to not be there, so make sure we normalize that bit.
nsAutoString fileExtToUse;
if (aFileExt.First() != char16_t('.')) fileExtToUse = char16_t('.');
fileExtToUse.Append(aFileExt);
// don't append the '.' for our APIs.
// Our extension APIs expect extensions without the '.', so normalize:
uint32_t dotlessIndex = aFileExt.First() != char16_t('.') ? 0 : 1;
nsAutoCString lowerFileExt =
NS_ConvertUTF16toUTF8(Substring(fileExtToUse, 1));
NS_ConvertUTF16toUTF8(Substring(aFileExt, dotlessIndex));
ToLowerCase(lowerFileExt);
mimeInfo->AppendExtension(lowerFileExt);
mozilla::StaticPrefs::browser_download_improvements_to_download_panel()
? mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk)
: mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
if (NS_FAILED(InternalSetDefaultsOnMIME(mimeInfo))) {
return nullptr;
}
return mimeInfo.forget();
}
nsresult nsOSHelperAppService::InternalSetDefaultsOnMIME(
nsMIMEInfoWin* aMIMEInfo) {
NS_ENSURE_ARG(aMIMEInfo);
nsAutoCString primaryExt;
aMIMEInfo->GetPrimaryExtension(primaryExt);
if (primaryExt.IsEmpty()) {
return NS_ERROR_FAILURE;
}
// windows registry assumes your file extension is going to include the '.',
// but our APIs don't have it, so add it:
nsAutoString assocType = NS_ConvertUTF8toUTF16(primaryExt);
if (assocType.First() != char16_t('.')) {
assocType.Insert(char16_t('.'), 0);
}
nsAutoString appInfo;
bool found;
// Retrieve the default application for this extension
NS_ENSURE_TRUE(mAppAssoc, nullptr);
nsString assocType(fileExtToUse);
NS_ENSURE_TRUE(mAppAssoc, NS_ERROR_NOT_AVAILABLE);
wchar_t* pResult = nullptr;
HRESULT hr = mAppAssoc->QueryCurrentDefault(assocType.get(), AT_FILEEXTENSION,
AL_EFFECTIVE, &pResult);
@ -403,7 +421,7 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(
if (appInfo.EqualsLiteral("XPSViewer.Document")) found = false;
if (!found) {
return nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
// Get other nsIMIMEInfo fields from registry, if possible.
@ -412,16 +430,15 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(
if (NS_FAILED(GetDefaultAppInfo(appInfo, defaultDescription,
getter_AddRefs(defaultApplication)))) {
return nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
mimeInfo->SetDefaultDescription(defaultDescription);
mimeInfo->SetDefaultApplicationHandler(defaultApplication);
aMIMEInfo->SetDefaultDescription(defaultDescription);
aMIMEInfo->SetDefaultApplicationHandler(defaultApplication);
// Grab the general description
GetMIMEInfoFromRegistry(appInfo, mimeInfo);
return mimeInfo.forget();
GetMIMEInfoFromRegistry(appInfo, aMIMEInfo);
return NS_OK;
}
NS_IMETHODIMP
@ -532,6 +549,12 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
return NS_OK;
}
NS_IMETHODIMP
nsOSHelperAppService::UpdateDefaultAppInfo(nsIMIMEInfo* aMIMEInfo) {
InternalSetDefaultsOnMIME(static_cast<nsMIMEInfoWin*>(aMIMEInfo));
return NS_OK;
}
NS_IMETHODIMP
nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const nsACString& aScheme,
bool* found,

View File

@ -44,6 +44,7 @@ class nsOSHelperAppService : public nsExternalHelperAppService {
NS_IMETHOD GetMIMEInfoFromOS(const nsACString& aMIMEType,
const nsACString& aFileExt, bool* aFound,
nsIMIMEInfo** aMIMEInfo) override;
NS_IMETHOD UpdateDefaultAppInfo(nsIMIMEInfo* aMIMEInfo) override;
NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme,
bool* found,
nsIHandlerInfo** _retval);
@ -63,6 +64,7 @@ class nsOSHelperAppService : public nsExternalHelperAppService {
// Lookup a mime info by extension, using an optional type hint
already_AddRefed<nsMIMEInfoWin> GetByExtension(
const nsString& aFileExt, const char* aTypeHint = nullptr);
nsresult InternalSetDefaultsOnMIME(nsMIMEInfoWin* aMIMEInfo);
nsresult FindOSMimeInfoForType(const char* aMimeContentType, nsIURI* aURI,
char** aFileExtension,
nsIMIMEInfo** aMIMEInfo);