зеркало из https://github.com/mozilla/gecko-dev.git
282196 - need to access arbitrary metdata on default application handler (windows) - make nsMIMEInfoWin implement nsIPropertyBag with property keys to access moz-icon URIs for default and preferred application handlers. r=biesi sr=bz
252189 - retrieve proper application handler names from windows registry/binary VERSIONINFO metadata r=biesi sr=bz
This commit is contained in:
Родитель
85f22a376c
Коммит
100019a66e
|
@ -370,4 +370,3 @@ nsMIMEInfoImpl::LaunchDefaultWithFile(nsIFile* aFile)
|
|||
return LaunchWithIProcess(mDefaultApplication, aFile);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,17 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
/**
|
||||
* UTF8 moz-icon URI string for the default handler application's icon, if
|
||||
* available.
|
||||
*/
|
||||
#define PROPERTY_DEFAULT_APP_ICON_URL "defaultApplicationIconURL"
|
||||
/**
|
||||
* UTF8 moz-icon URI string for the user's preferred handler application's
|
||||
* icon, if available.
|
||||
*/
|
||||
#define PROPERTY_CUSTOM_APP_ICON_URL "customApplicationIconURL"
|
||||
|
||||
/**
|
||||
* Basic implementation of nsIMIMEInfo. Incomplete - it is meant to be
|
||||
* subclassed, and GetHasDefaultHandler as well as LaunchDefaultWithFile need to
|
||||
|
|
|
@ -38,8 +38,14 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsMIMEInfoWin.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsMIMEInfoWin, nsMIMEInfoBase, nsIPropertyBag)
|
||||
|
||||
nsMIMEInfoWin::~nsMIMEInfoWin()
|
||||
{
|
||||
|
@ -70,3 +76,46 @@ nsMIMEInfoWin::GetHasDefaultHandler(PRBool * _retval)
|
|||
*_retval = !mDefaultAppDescription.IsEmpty();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInfoWin::GetEnumerator(nsISimpleEnumerator* *_retval)
|
||||
{
|
||||
nsCOMArray<nsIVariant> properties;
|
||||
|
||||
nsCOMPtr<nsIVariant> variant;
|
||||
GetProperty(NS_LITERAL_STRING("defaultApplicationIconURL"), getter_AddRefs(variant));
|
||||
if (variant)
|
||||
properties.AppendObject(variant);
|
||||
|
||||
GetProperty(NS_LITERAL_STRING("customApplicationIconURL"), getter_AddRefs(variant));
|
||||
if (variant)
|
||||
properties.AppendObject(variant);
|
||||
|
||||
return NS_NewArrayEnumerator(_retval, properties);
|
||||
}
|
||||
|
||||
static nsresult GetIconURLVariant(nsIFile* aApplication, nsIVariant* *_retval)
|
||||
{
|
||||
nsresult rv = CallCreateInstance("@mozilla.org/variant;1", _retval);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
nsCAutoString fileURLSpec;
|
||||
NS_GetURLSpecFromFile(aApplication, fileURLSpec);
|
||||
nsCAutoString iconURLSpec; iconURLSpec.AssignLiteral("moz-icon://");
|
||||
iconURLSpec += fileURLSpec;
|
||||
nsCOMPtr<nsIWritableVariant> writable(do_QueryInterface(*_retval));
|
||||
writable->SetAsAUTF8String(iconURLSpec);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInfoWin::GetProperty(const nsAString& aName, nsIVariant* *_retval)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (mDefaultApplication && aName.EqualsLiteral(PROPERTY_DEFAULT_APP_ICON_URL))
|
||||
rv = GetIconURLVariant(mDefaultApplication, _retval);
|
||||
else if (mPreferredApplication && aName.EqualsLiteral(PROPERTY_CUSTOM_APP_ICON_URL))
|
||||
rv = GetIconURLVariant(mPreferredApplication, _retval);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,16 +38,28 @@
|
|||
#define nsMIMEInfoWin_h_
|
||||
|
||||
#include "nsMIMEInfoImpl.h"
|
||||
#include "nsIPropertyBag.h"
|
||||
|
||||
class nsMIMEInfoWin : public nsMIMEInfoBase {
|
||||
class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag {
|
||||
public:
|
||||
nsMIMEInfoWin(const char* aType = "") : nsMIMEInfoBase(aType) {}
|
||||
nsMIMEInfoWin(const nsACString& aMIMEType) : nsMIMEInfoBase(aMIMEType) {}
|
||||
virtual ~nsMIMEInfoWin();
|
||||
|
||||
NS_IMETHOD GetHasDefaultHandler(PRBool * _retval);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIPROPERTYBAG
|
||||
|
||||
void SetDefaultApplicationHandler(nsIFile* aDefaultApplication)
|
||||
{
|
||||
mDefaultApplication = aDefaultApplication;
|
||||
}
|
||||
protected:
|
||||
virtual nsresult LaunchDefaultWithFile(nsIFile* aFile);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIFile> mDefaultApplication;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "nsIMIMEInfo.h"
|
||||
#include "nsMIMEInfoWin.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsILocalFileWin.h"
|
||||
#include "nsIProcess.h"
|
||||
#include "plstr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -245,7 +245,6 @@ nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL)
|
|||
#ifdef WINCE // WinCE doesn't support helper applications yet.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#else
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// 1. Find the default app for this protocol
|
||||
|
@ -347,7 +346,7 @@ nsresult nsOSHelperAppService::GetMIMEInfoFromRegistry( const nsAFlatString& fil
|
|||
nsOSHelperAppService::typeFromExtEquals(const PRUnichar* aExt, const char *aType)
|
||||
{
|
||||
#ifdef WINCE // WinCE doesn't support helper applications yet.
|
||||
return FALSE;
|
||||
return PR_FALSE;
|
||||
#else
|
||||
if (!aType)
|
||||
return PR_FALSE;
|
||||
|
@ -385,12 +384,151 @@ nsOSHelperAppService::typeFromExtEquals(const PRUnichar* aExt, const char *aType
|
|||
#endif
|
||||
}
|
||||
|
||||
static void RemoveParameters(nsString& aPath)
|
||||
{
|
||||
// Command Strings stored in the Windows registry with parameters look like
|
||||
// this:
|
||||
//
|
||||
// 1) "C:\Program Files\Company Name\product.exe" -foo -bar (long version)
|
||||
// -- OR --
|
||||
// 2) C:\PROGRA~1\COMPAN~2\product.exe -foo -bar (short version)
|
||||
//
|
||||
// For 1), the path is the first "" quoted string. (quotes are used to
|
||||
// prevent parameter parsers from choking)
|
||||
// For 2), the path is the string up until the first space (spaces are
|
||||
// illegal in short DOS-style paths)
|
||||
//
|
||||
if (aPath.First() == PRUnichar('"')) {
|
||||
aPath = Substring(aPath, 1, aPath.Length() - 1);
|
||||
PRInt32 nextQuote = aPath.FindChar(PRUnichar('"'));
|
||||
if (nextQuote != kNotFound)
|
||||
aPath.Truncate(nextQuote);
|
||||
}
|
||||
else {
|
||||
PRInt32 firstSpace = aPath.FindChar(PRUnichar(' '));
|
||||
if (firstSpace != kNotFound)
|
||||
aPath.Truncate(firstSpace);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The "real" name of a given helper app (as specified by the path to the
|
||||
// executable file held in various registry keys) is stored n the VERSIONINFO
|
||||
// block in the file's resources. We need to find the path to the executable
|
||||
// and then retrieve the "FileDescription" field value from the file.
|
||||
//
|
||||
// For a given extension, we find the file handler like so:
|
||||
//
|
||||
// HKCR
|
||||
// \.ext\ <type key> <-- default value
|
||||
// \<type key>\
|
||||
// \shell\open\command\ <path+params> <-- default value
|
||||
//
|
||||
// We need to do some parsing on the <path+params> to strip off params and
|
||||
// deal with some Windows quirks (like the fact that many Shell "applications"
|
||||
// are actually DLLs invoked via rundll32.exe)
|
||||
//
|
||||
nsresult
|
||||
nsOSHelperAppService::GetDefaultAppInfo(nsAString& aTypeName, nsAString& aDefaultDescription,
|
||||
nsIFile** aDefaultApplication)
|
||||
{
|
||||
// If all else fails, use the file type key name, which will be something like "pngfile" for
|
||||
// .pngs, "WMVFile" for .wmvs, etc.
|
||||
aDefaultDescription = aTypeName;
|
||||
*aDefaultApplication = nsnull;
|
||||
|
||||
nsCAutoString handlerKeyName;
|
||||
NS_CopyUnicodeToNative(aTypeName, handlerKeyName);
|
||||
handlerKeyName += "\\shell\\open\\command";
|
||||
HKEY handlerKey;
|
||||
LONG err = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, handlerKeyName.get(), 0, KEY_QUERY_VALUE, &handlerKey);
|
||||
if (err == ERROR_SUCCESS) {
|
||||
nsAutoString handlerCommand;
|
||||
PRBool found = GetValueString(handlerKey, NULL, handlerCommand);
|
||||
if (found) {
|
||||
nsAutoString handlerFilePath;
|
||||
// First look to see if we're invoking a Windows shell service, such as
|
||||
// the Picture & Fax Viewer, which are invoked through rundll32.exe, and
|
||||
// so we need to extract the DLL path because that's where the version
|
||||
// info is held - not in rundll32.exe
|
||||
//
|
||||
// The format of rundll32.exe calls is:
|
||||
//
|
||||
// rundll32.exe c:\path\to.dll,Function %args
|
||||
//
|
||||
// What we want is the DLL - since that's where the real application name
|
||||
// is stored, e.g. zipfldr.dll, shimgvw.dll, etc.
|
||||
//
|
||||
// Working from the end of the registry value, the path begins at the last
|
||||
// comma in the string (stripping off Function and args) to the position
|
||||
// just after the first space (the space after rundll32.exe).
|
||||
//
|
||||
NS_NAMED_LITERAL_STRING(rundllSegment, "rundll32.exe ");
|
||||
if (StringBeginsWith(handlerCommand, rundllSegment)) {
|
||||
PRInt32 lastCommaPos = handlerCommand.RFindChar(',');
|
||||
PRUint32 rundllSegmentLength = rundllSegment.Length();
|
||||
if (lastCommaPos != kNotFound)
|
||||
handlerFilePath = Substring(handlerCommand, rundllSegmentLength,
|
||||
lastCommaPos - rundllSegmentLength);
|
||||
else
|
||||
handlerFilePath = Substring(handlerCommand, rundllSegmentLength,
|
||||
handlerCommand.Length() - rundllSegmentLength);
|
||||
}
|
||||
else
|
||||
handlerFilePath = handlerCommand;
|
||||
|
||||
// Trim any command parameters so that we have a native path we can
|
||||
// initialize a local file with...
|
||||
RemoveParameters(handlerFilePath);
|
||||
|
||||
// Similarly replace embedded environment variables... (this must be done
|
||||
// AFTER |RemoveParameters| since it may introduce spaces into the path string)
|
||||
TCHAR* destination = nsnull;
|
||||
nsCAutoString nativeHandlerFilePath;
|
||||
NS_CopyUnicodeToNative(handlerFilePath, nativeHandlerFilePath);
|
||||
DWORD required = ::ExpandEnvironmentStrings(nativeHandlerFilePath.get(), destination, 0);
|
||||
destination = new TCHAR[required];
|
||||
if (!destination) {
|
||||
::RegCloseKey(handlerKey);
|
||||
delete[] destination;
|
||||
destination = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
::ExpandEnvironmentStrings(nativeHandlerFilePath.get(), destination, required);
|
||||
NS_CopyNativeToUnicode(nsDependentCString(destination), handlerFilePath);
|
||||
delete[] destination;
|
||||
destination = nsnull;
|
||||
|
||||
nsCOMPtr<nsILocalFile> lf;
|
||||
NS_NewLocalFile(handlerFilePath, PR_TRUE, getter_AddRefs(lf));
|
||||
if (!lf) {
|
||||
::RegCloseKey(handlerKey);
|
||||
delete[] destination;
|
||||
destination = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsILocalFileWin* lfw = nsnull;
|
||||
nsresult rv = CallQueryInterface(lf, &lfw);
|
||||
if (NS_SUCCEEDED(rv) && lfw) {
|
||||
// The "FileDescription" field contains the actual name of the application.
|
||||
lfw->GetVersionInfoField("FileDescription", aDefaultDescription);
|
||||
// QI addref'ed for us.
|
||||
*aDefaultApplication = lfw;
|
||||
}
|
||||
|
||||
}
|
||||
::RegCloseKey(handlerKey);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(const nsAFlatString& aFileExt, const char *aTypeHint)
|
||||
{
|
||||
#ifdef WINCE // WinCE doesn't support helper applications yet.
|
||||
#ifdef WINCE // WinCE doesn't support helper applications yet
|
||||
return nsnull;
|
||||
#else
|
||||
|
||||
if (aFileExt.IsEmpty())
|
||||
return nsnull;
|
||||
|
||||
|
@ -441,14 +579,12 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(const nsAFl
|
|||
|
||||
mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
|
||||
|
||||
nsAutoString visibleDesc(description);
|
||||
PRInt32 pos = visibleDesc.FindChar('.');
|
||||
if (pos > 0)
|
||||
visibleDesc.Truncate(pos);
|
||||
// the format of the description usually looks like appname.version.something.
|
||||
// for now, let's try to make it pretty and just show you the appname.
|
||||
|
||||
mimeInfo->SetDefaultDescription(visibleDesc);
|
||||
nsAutoString defaultDescription;
|
||||
nsCOMPtr<nsIFile> defaultApplication;
|
||||
GetDefaultAppInfo(description, defaultDescription, getter_AddRefs(defaultApplication));
|
||||
|
||||
mimeInfo->SetDefaultDescription(defaultDescription);
|
||||
mimeInfo->SetDefaultApplicationHandler(defaultApplication);
|
||||
|
||||
// Get other nsIMIMEInfo fields from registry, if possible.
|
||||
if ( found )
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
static PRBool GetValueString(HKEY hKey, const PRUnichar* pValueName, nsAString& result);
|
||||
|
||||
protected:
|
||||
nsresult GetDefaultAppInfo(nsAString& aTypeName, nsAString& aDefaultDescription, nsIFile** aDefaultApplication);
|
||||
// Lookup a mime info by extension, using an optional type hint
|
||||
already_AddRefed<nsMIMEInfoWin> GetByExtension(const nsAFlatString& aFileExt, const char *aTypeHint = nsnull);
|
||||
nsresult FindOSMimeInfoForType(const char * aMimeContentType, nsIURI * aURI, char ** aFileExtension, nsIMIMEInfo ** aMIMEInfo);
|
||||
|
|
Загрузка…
Ссылка в новой задаче