Changed the behavior for BRoster::FindApp(), Launch() and related functionality:

Instead of only checking the preferred applications of a given MIME type and its
super type (i.e. "text/html" and "text"), build a list of all supporting apps,
where the preferred types of the sub and super type lead the respective
sections of the list. Then try to find the first valid application in the list.

This makes it possible to double click "Welcome" on the Desktop, even though
the text/html MIME type still has BeZillaBrowser set as preferred application.
Previously it would launch StyledEdit, even though WebPositive was readily
available.

The previous behavior was probably implementing exactly the BeOS behavior, but
I can't see a good reason why we should be compatible here. Until now, my
testing has also not revealed any regression.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36471 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2010-04-25 16:40:29 +00:00
parent 5af798836a
commit da24e53cf8

View File

@ -2563,11 +2563,11 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta,
|| appFile == NULL || strlen(mimeType) >= B_MIME_TYPE_LENGTH)
return B_BAD_VALUE;
// create a BMimeType and check, if the type is installed
// Create a BMimeType and check, if the type is installed.
BMimeType type;
status_t error = type.SetTo(mimeType);
// get the preferred app
// Get the preferred apps from the sub and super type.
char primarySignature[B_MIME_TYPE_LENGTH];
char secondarySignature[B_MIME_TYPE_LENGTH];
primarySignature[0] = '\0';
@ -2579,12 +2579,9 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta,
if (type.GetSupertype(&superType) == B_OK)
superType.GetPreferredApp(secondarySignature);
if (type.GetPreferredApp(primarySignature) != B_OK
&& !secondarySignature[0]) {
if (type.GetPreferredApp(primarySignature) != B_OK) {
// The type is installed, but has no preferred app.
// In fact it might be an app signature and even having a
// valid app hint. Nevertheless we fail.
error = B_LAUNCH_FAILED_NO_PREFERRED_APP;
primarySignature[0] = '\0';
} else if (!strcmp(primarySignature, secondarySignature)) {
// Both types have the same preferred app, there is
// no point in testing it twice.
@ -2596,37 +2593,80 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta,
}
}
// We will use this BMessage "signatures" to hold all supporting apps
// so we can iterator over them in the preferred order. We include
// the supporting apps in such a way that the configured preferred
// applications for the MIME type are in front of other supporting
// applications for the sub and the super type respectively.
const char* kSigField = "applications";
BMessage signatures;
if (error == B_OK && primarySignature[0] != '\0')
error = signatures.AddString(kSigField, primarySignature);
BMessage supportingSignatures;
if (error == B_OK
&& type.GetSupportingApps(&supportingSignatures) == B_OK) {
int32 subCount;
if (supportingSignatures.FindInt32("be:sub", &subCount) != B_OK)
subCount = 0;
// Add all signatures with direct support for the sub-type
const char* supportingType;
for (int32 i = 0; error == B_OK && i < subCount
&& supportingSignatures.FindString(kSigField, i,
&supportingType) == B_OK; i++) {
// don't add the signature if it's the preferred app already.
if (strcmp(primarySignature, supportingType) != 0)
error = signatures.AddString(kSigField, supportingType);
}
// Add the preferred type of the super type here before adding
// the other types supporting the super type.
if (error == B_OK && secondarySignature[0] != '\0')
error = signatures.AddString(kSigField, secondarySignature);
// Add all signatures with support for the super-type
for (int32 i = subCount; error == B_OK
&& supportingSignatures.FindString(kSigField, i,
&supportingType) == B_OK; i++) {
// don't add the signature if it's the preferred app already.
if (strcmp(secondarySignature, supportingType) != 0)
error = signatures.AddString(kSigField, supportingType);
}
} else {
// Failed to get supporting apps, just add the preferred apps.
if (error == B_OK)
error = signatures.AddString(kSigField, secondarySignature);
}
if (error != B_OK)
return error;
// see if we can find the application and if it's valid, try
// both preferred app signatures, if available (from type and
// super type)
// Set an error in case we can't resolve a single supporting app.
error = B_LAUNCH_FAILED_NO_PREFERRED_APP;
status_t primaryError = B_OK;
for (int32 tries = 0; tries < 2; tries++) {
const char* signature = tries == 0
? primarySignature : secondarySignature;
// See if we can find a good application that is valid from the messege.
const char* signature;
for (int32 i = 0;
signatures.FindString(kSigField, i, &signature) == B_OK; i++) {
if (signature[0] == '\0')
continue;
error = appMeta->SetTo(signature);
// check, whether the signature is installed and has an app hint
// Check, whether the signature is installed and has an app hint
bool appFound = false;
if (error == B_OK && appMeta->GetAppHint(appRef) == B_OK) {
// resolve symbolic links, if necessary
// Resolve symbolic links, if necessary
BEntry entry;
if (entry.SetTo(appRef, true) == B_OK && entry.IsFile()
&& entry.GetRef(appRef) == B_OK) {
appFound = true;
} else
appMeta->SetAppHint(NULL); // bad app hint -- remove it
} else {
// Bad app hint -- remove it
appMeta->SetAppHint(NULL);
}
}
// In case there is no app hint or it is invalid, we need to query for
// the app
// the app.
if (error == B_OK && !appFound)
error = query_for_app(appMeta->Type(), appRef);
if (error == B_OK)
@ -2635,12 +2675,7 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta,
if (error == B_OK)
error = can_app_be_used(appRef);
if (error != B_OK) {
if (tries == 0)
primaryError = error;
else if (primarySignature[0])
error = primaryError;
} else
if (error == B_OK)
break;
}