diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index 102bb5f2c1..bcbf5e04fe 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -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; }