diff --git a/headers/os/storage/MimeType.h b/headers/os/storage/MimeType.h index 3124035144..f82548c394 100644 --- a/headers/os/storage/MimeType.h +++ b/headers/os/storage/MimeType.h @@ -158,7 +158,6 @@ class BMimeType { // for testing only friend class BAppFileInfo; - friend class BPrivate::Storage::Mime::CreateAppMetaMimeThread; virtual void _ReservedMimeType1(); virtual void _ReservedMimeType2(); diff --git a/headers/private/storage/mime/AppMetaMimeCreator.h b/headers/private/storage/mime/AppMetaMimeCreator.h new file mode 100644 index 0000000000..cc30c7640c --- /dev/null +++ b/headers/private/storage/mime/AppMetaMimeCreator.h @@ -0,0 +1,62 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + */ +#ifndef _MIME_APP_META_MIME_CREATOR_H +#define _MIME_APP_META_MIME_CREATOR_H + + +#include + +#include + + +struct entry_ref; + + +namespace BPrivate { +namespace Storage { +namespace Mime { + + +class Database; + + +class AppMetaMimeCreator { +public: + class DatabaseLocker; + +public: + AppMetaMimeCreator(Database* database, + DatabaseLocker* databaseLocker, + int32 force); + ~AppMetaMimeCreator(); + + status_t Do(const entry_ref& entry, bool* _entryIsDir); + +private: + Database* fDatabase; + DatabaseLocker* fDatabaseLocker; + int32 fForce; + +}; + + +class AppMetaMimeCreator::DatabaseLocker { +public: + virtual ~DatabaseLocker(); + + virtual bool Lock() = 0; + virtual void Unlock() = 0; +}; + + +} // namespace Mime +} // namespace Storage +} // namespace BPrivate + + +#endif // _MIME_APP_META_MIME_CREATOR_H diff --git a/src/kits/storage/mime/AppMetaMimeCreator.cpp b/src/kits/storage/mime/AppMetaMimeCreator.cpp new file mode 100644 index 0000000000..e6cafcf529 --- /dev/null +++ b/src/kits/storage/mime/AppMetaMimeCreator.cpp @@ -0,0 +1,214 @@ +/* + * Copyright 2002-2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Tyler Dauwalder + * Axel Dörfler, axeld@pinc-software.de + * Ingo Weinhold, ingo_weinhold@gmx.de + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace BPrivate { +namespace Storage { +namespace Mime { + + +// #pragma mark - AppMetaMimeCreator + + +AppMetaMimeCreator::AppMetaMimeCreator(Database* database, + DatabaseLocker* databaseLocker, int32 force) + : + fDatabase(database), + fDatabaseLocker(databaseLocker), + fForce(force) +{ +} + + +AppMetaMimeCreator::~AppMetaMimeCreator() +{ +} + + +status_t +AppMetaMimeCreator::Do(const entry_ref& entry, bool* _entryIsDir) +{ + BFile file; + status_t status = file.SetTo(&entry, B_READ_ONLY | O_NOTRAVERSE); + if (status < B_OK) + return status; + + bool isDir = file.IsDirectory(); + if (_entryIsDir != NULL) + *_entryIsDir = isDir; + + if (isDir || !file.IsFile()) + return B_OK; + + BAppFileInfo appInfo(&file); + status = appInfo.InitCheck(); + if (status < B_OK) + return status; + + // Read the app sig (which consequently keeps us from updating + // non-applications, since we get an error if the file has no + // app sig) + BString signature; + status = file.ReadAttrString("BEOS:APP_SIG", &signature); + if (status != B_OK) + return B_BAD_TYPE; + + if (!BMimeType::IsValid(signature)) + return B_BAD_TYPE; + + InstallNotificationDeferrer _(fDatabase, signature.String()); + + if (!fDatabase->Location()->IsInstalled(signature)) { + AutoLocker databaseLocker(fDatabaseLocker); + fDatabase->Install(signature); + } + + BNode typeNode; + status = fDatabase->Location()->OpenType(signature, typeNode); + if (status != B_OK) + return status; + + // Preferred App + attr_info info; + if (status == B_OK + && (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetPreferredApp(signature, signature); + } + + // Short Description (name of the application) + if (status == B_OK + && (fForce + || typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetShortDescription(signature, entry.name); + } + + // App Hint + if (status == B_OK + && (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetAppHint(signature, &entry); + } + + // Vector Icon + if (status == B_OK + && (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) { + uint8* data = NULL; + size_t size = 0; + if (appInfo.GetIcon(&data, &size) == B_OK) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetIcon(signature, data, size); + free(data); + } + } + // Mini Icon + BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8); + if (status == B_OK + && (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) { + if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetIcon(signature, &miniIcon, B_MINI_ICON); + } + } + // Large Icon + BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8); + if (status == B_OK + && (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) { + if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetIcon(signature, &largeIcon, B_LARGE_ICON); + } + } + + // Supported Types + bool setSupportedTypes = false; + BMessage supportedTypes; + if (status == B_OK + && (fForce + || typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) { + if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK) + setSupportedTypes = true; + } + + // defer notifications for supported types + const char* type; + for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) + fDatabase->DeferInstallNotification(type); + + // set supported types + if (setSupportedTypes) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetSupportedTypes(signature, &supportedTypes, true); + } + + // Icons for supported types + for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; + i++) { + // vector icon + uint8* data = NULL; + size_t size = 0; + if (status == B_OK + && appInfo.GetIconForType(type, &data, &size) == B_OK) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetIconForType(signature, type, data, size); + free(data); + } + // mini icon + if (status == B_OK + && appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetIconForType(signature, type, &miniIcon, + B_MINI_ICON); + } + // large icon + if (status == B_OK + && appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) { + AutoLocker databaseLocker(fDatabaseLocker); + status = fDatabase->SetIconForType(signature, type, &largeIcon, + B_LARGE_ICON); + } + } + + // undefer notifications for supported types + for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) + fDatabase->UndeferInstallNotification(type); + + return status; +} + + +// #pragma mark - DatabaseLocker + + +AppMetaMimeCreator::DatabaseLocker::~DatabaseLocker() +{ +} + + +} // namespace Mime +} // namespace Storage +} // namespace BPrivate diff --git a/src/kits/storage/mime/Jamfile b/src/kits/storage/mime/Jamfile index d736873f74..93fb64b926 100644 --- a/src/kits/storage/mime/Jamfile +++ b/src/kits/storage/mime/Jamfile @@ -10,6 +10,7 @@ UsePrivateHeaders app shared storage ; #UsePublicHeaders [ FDirName add-ons registrar ] ; StaticLibrary libstorage_kit_mime.a : + AppMetaMimeCreator.cpp AssociatedTypes.cpp Database.cpp DatabaseDirectory.cpp diff --git a/src/servers/registrar/MIMEManager.cpp b/src/servers/registrar/MIMEManager.cpp index ebde527dd7..4fab7405f6 100644 --- a/src/servers/registrar/MIMEManager.cpp +++ b/src/servers/registrar/MIMEManager.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include "CreateAppMetaMimeThread.h" @@ -53,6 +54,30 @@ init_mime_sniffer_add_on_manager() } +class MIMEManager::DatabaseLocker + : public BPrivate::Storage::Mime::AppMetaMimeCreator::DatabaseLocker { +public: + DatabaseLocker(MIMEManager* manager) + : + fManager(manager) + { + } + + virtual bool Lock() + { + return fManager->Lock(); + } + + virtual void Unlock() + { + fManager->Unlock(); + } + +private: + MIMEManager* fManager; +}; + + /*! \brief Creates and initializes a MIMEManager. */ MIMEManager::MIMEManager() @@ -60,6 +85,7 @@ MIMEManager::MIMEManager() BLooper("main_mime"), fDatabase(BPrivate::Storage::Mime::default_database_location(), init_mime_sniffer_add_on_manager(), this), + fDatabaseLocker(new(std::nothrow) DatabaseLocker(this)), fThreadManager() { AddHandler(&fThreadManager); @@ -245,7 +271,7 @@ MIMEManager::MessageReceived(BMessage *message) thread = new(nothrow) CreateAppMetaMimeThread( synchronous ? "create_app_meta_mime (s)" : "create_app_meta_mime (a)", - B_NORMAL_PRIORITY + 1, &fDatabase, + B_NORMAL_PRIORITY + 1, &fDatabase, fDatabaseLocker, BMessenger(&fThreadManager), &root, recursive, force, synchronous ? message : NULL); break; diff --git a/src/servers/registrar/MIMEManager.h b/src/servers/registrar/MIMEManager.h index f1cc8564ff..ceae1f66a1 100644 --- a/src/servers/registrar/MIMEManager.h +++ b/src/servers/registrar/MIMEManager.h @@ -22,11 +22,16 @@ private: // Database::NotificationListener virtual status_t Notify(BMessage* message, const BMessenger& target); +private: + class DatabaseLocker; + private: void HandleSetParam(BMessage *message); void HandleDeleteParam(BMessage *message); - + +private: BPrivate::Storage::Mime::Database fDatabase; + DatabaseLocker* fDatabaseLocker; RegistrarThreadManager fThreadManager; BMessenger fManagerMessenger; }; diff --git a/src/servers/registrar/mime/CreateAppMetaMimeThread.cpp b/src/servers/registrar/mime/CreateAppMetaMimeThread.cpp index 599c2a13cd..669380ab18 100644 --- a/src/servers/registrar/mime/CreateAppMetaMimeThread.cpp +++ b/src/servers/registrar/mime/CreateAppMetaMimeThread.cpp @@ -1,41 +1,31 @@ /* - * Copyright 2002-2006, Haiku. + * Copyright 2002-2013, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: * Tyler Dauwalder * Axel Dörfler, axeld@pinc-software.de + * Ingo Weinhold, ingo_weinhold@gmx.de */ #include "CreateAppMetaMimeThread.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - namespace BPrivate { namespace Storage { namespace Mime { -CreateAppMetaMimeThread::CreateAppMetaMimeThread(const char *name, - int32 priority, Database *database, BMessenger managerMessenger, - const entry_ref *root, bool recursive, int32 force, BMessage *replyee) - : MimeUpdateThread(name, priority, database, managerMessenger, root, - recursive, force, replyee) +CreateAppMetaMimeThread::CreateAppMetaMimeThread(const char* name, + int32 priority, Database* database, + AppMetaMimeCreator::DatabaseLocker* databaseLocker, + BMessenger managerMessenger, const entry_ref* root, bool recursive, + int32 force, BMessage* replyee) + : + MimeUpdateThread(name, priority, database, managerMessenger, root, + recursive, force, replyee), + fCreator(database, databaseLocker, force) { } @@ -46,124 +36,10 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir) if (ref == NULL) return B_BAD_VALUE; - BFile file; - status_t status = file.SetTo(ref, B_READ_ONLY | O_NOTRAVERSE); - if (status < B_OK) - return status; - - bool isDir = file.IsDirectory(); - if (_entryIsDir != NULL) - *_entryIsDir = isDir; - - if (isDir || !file.IsFile()) - return B_OK; - - BAppFileInfo appInfo(&file); - status = appInfo.InitCheck(); - if (status < B_OK) - return status; - - // Read the app sig (which consequently keeps us from updating - // non-applications, since we get an error if the file has no - // app sig) - BString signature; - status = file.ReadAttrString("BEOS:APP_SIG", &signature); - if (status < B_OK) - return B_BAD_TYPE; - - // Init our various objects - - BMimeType mime; - status = mime.SetTo(signature.String()); - if (status < B_OK) - return status; - - InstallNotificationDeferrer _(fDatabase, signature.String()); - - if (!mime.IsInstalled()) - mime.Install(); - - BNode typeNode; - status = fDatabase->Location()->OpenType(signature, typeNode); - if (status < B_OK) - return status; - - // Preferred App - attr_info info; - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) - status = mime.SetPreferredApp(signature.String()); - - // Short Description (name of the application) - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) - status = mime.SetShortDescription(ref->name); - - // App Hint - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) - status = mime.SetAppHint(ref); - - // Vector Icon - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) { - uint8* data = NULL; - size_t size = 0; - if (appInfo.GetIcon(&data, &size) == B_OK) { - status = mime.SetIcon(data, size); - free(data); - } - } - // Mini Icon - BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8); - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) { - if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) - status = mime.SetIcon(&miniIcon, B_MINI_ICON); - } - // Large Icon - BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8); - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) { - if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) - status = mime.SetIcon(&largeIcon, B_LARGE_ICON); - } - - // Supported Types - bool setSupportedTypes = false; - BMessage supportedTypes; - if (status == B_OK && (fForce || typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) { - if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK) - setSupportedTypes = true; - } - - // defer notifications for supported types - const char* type; - for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) - fDatabase->DeferInstallNotification(type); - - // set supported types - if (setSupportedTypes) - status = mime.SetSupportedTypes(&supportedTypes); - - // Icons for supported types - for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) { - // vector icon - uint8* data = NULL; - size_t size = 0; - if (status == B_OK && appInfo.GetIconForType(type, &data, &size) == B_OK) { - status = mime.SetIconForType(type, data, size); - free(data); - } - // mini icon - if (status == B_OK && appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) - status = mime.SetIconForType(type, &miniIcon, B_MINI_ICON); - // large icon - if (status == B_OK && appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) - status = mime.SetIconForType(type, &largeIcon, B_LARGE_ICON); - } - - // undefer notifications for supported types - for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) - fDatabase->UndeferInstallNotification(type); - - return status; + return fCreator.Do(*ref, _entryIsDir); } + } // namespace Mime } // namespace Storage } // namespace BPrivate diff --git a/src/servers/registrar/mime/CreateAppMetaMimeThread.h b/src/servers/registrar/mime/CreateAppMetaMimeThread.h index 9f44fc0254..b94866b836 100644 --- a/src/servers/registrar/mime/CreateAppMetaMimeThread.h +++ b/src/servers/registrar/mime/CreateAppMetaMimeThread.h @@ -10,20 +10,35 @@ #ifndef _CREATE_APP_META_MIME_THREAD_H #define _CREATE_APP_META_MIME_THREAD_H + +#include + #include "MimeUpdateThread.h" + namespace BPrivate { namespace Storage { namespace Mime { + class CreateAppMetaMimeThread : public MimeUpdateThread { public: - CreateAppMetaMimeThread(const char *name, int32 priority, - Database *database, BMessenger managerMessenger, const entry_ref *root, - bool recursive, int32 force, BMessage *replyee); - status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir); + CreateAppMetaMimeThread(const char* name, + int32 priority, Database* database, + AppMetaMimeCreator::DatabaseLocker* + databaseLocker, + BMessenger managerMessenger, + const entry_ref* root, bool recursive, + int32 force, BMessage* replyee); + + virtual status_t DoMimeUpdate(const entry_ref* entry, + bool* _entryIsDir); + +private: + AppMetaMimeCreator fCreator; }; - + + } // namespace Mime } // namespace Storage } // namespace BPrivate