* For operations that implicitly install a MIME type, we no longer send
two notifications (install + update), but only the install notification. * When create_app_meta_mime() installs a new MIME type (app signature or supported type), it only sends the install notification, instead of install + one or more updates. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25730 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
9a18e1d269
commit
8d1699709a
|
@ -22,16 +22,19 @@
|
|||
|
||||
#include <mime/database_support.h>
|
||||
|
||||
#include "Database.h"
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
|
||||
CreateAppMetaMimeThread::CreateAppMetaMimeThread(const char *name,
|
||||
int32 priority, BMessenger managerMessenger, const entry_ref *root,
|
||||
bool recursive, int32 force, BMessage *replyee)
|
||||
: MimeUpdateThread(name, priority, managerMessenger, root, recursive, force,
|
||||
replyee)
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -76,6 +79,8 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir)
|
|||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
InstallNotificationDeferrer _(fDatabase, signature.String());
|
||||
|
||||
if (!mime.IsInstalled())
|
||||
mime.Install();
|
||||
|
||||
|
@ -126,14 +131,23 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir)
|
|||
}
|
||||
|
||||
// Supported Types
|
||||
bool setSupportedTypes = false;
|
||||
BMessage supportedTypes;
|
||||
if (status == B_OK && (fForce || typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) {
|
||||
if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK)
|
||||
status = mime.SetSupportedTypes(&supportedTypes);
|
||||
setSupportedTypes = true;
|
||||
}
|
||||
|
||||
// Icons for supported types
|
||||
// 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;
|
||||
|
@ -150,6 +164,10 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ namespace Mime {
|
|||
class CreateAppMetaMimeThread : public MimeUpdateThread {
|
||||
public:
|
||||
CreateAppMetaMimeThread(const char *name, int32 priority,
|
||||
BMessenger managerMessenger, const entry_ref *root, bool recursive,
|
||||
int32 force, BMessage *replyee);
|
||||
Database *database, BMessenger managerMessenger, const entry_ref *root,
|
||||
bool recursive, int32 force, BMessage *replyee);
|
||||
status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir);
|
||||
};
|
||||
|
||||
|
|
|
@ -10,16 +10,18 @@
|
|||
|
||||
#include "Database.h"
|
||||
|
||||
#include <mime/database_access.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <storage_support.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <DataIO.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Locker.h>
|
||||
#include <fs_attr.h>
|
||||
#include <Message.h>
|
||||
#include <MimeType.h>
|
||||
#include <Node.h>
|
||||
|
@ -27,12 +29,10 @@
|
|||
#include <String.h>
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include <fs_attr.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <AutoLocker.h>
|
||||
#include <mime/database_access.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <storage_support.h>
|
||||
|
||||
#include "MessageDeliverer.h"
|
||||
|
||||
|
@ -60,7 +60,10 @@ namespace Mime {
|
|||
/*! \brief Creates and initializes a Mime::Database object.
|
||||
*/
|
||||
Database::Database()
|
||||
: fStatus(B_NO_INIT)
|
||||
:
|
||||
fStatus(B_NO_INIT),
|
||||
fDeferredInstallNotificationsLocker("deferred install notifications"),
|
||||
fDeferredInstallNotifications()
|
||||
{
|
||||
// Do some really minor error checking
|
||||
BEntry entry(kDatabaseDir.c_str());
|
||||
|
@ -200,8 +203,8 @@ Database::_SetStringValue(const char *type, int32 what, const char* attribute,
|
|||
if (status == B_OK) {
|
||||
if (didCreate)
|
||||
_SendInstallNotification(type);
|
||||
|
||||
_SendMonitorUpdate(what, type, B_META_MIME_MODIFIED);
|
||||
else
|
||||
_SendMonitorUpdate(what, type, B_META_MIME_MODIFIED);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -259,7 +262,8 @@ Database::SetAttrInfo(const char *type, const BMessage *info)
|
|||
if (status == B_OK) {
|
||||
if (didCreate)
|
||||
_SendInstallNotification(type);
|
||||
_SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_MODIFIED);
|
||||
else
|
||||
_SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_MODIFIED);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -325,9 +329,12 @@ Database::SetFileExtensions(const char *type, const BMessage *extensions)
|
|||
extensions, &didCreate);
|
||||
|
||||
if (status == B_OK) {
|
||||
if (didCreate)
|
||||
if (didCreate) {
|
||||
_SendInstallNotification(type);
|
||||
_SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_MODIFIED);
|
||||
} else {
|
||||
_SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type,
|
||||
B_META_MIME_MODIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -424,20 +431,22 @@ Database::SetIconForType(const char *type, const char *fileType,
|
|||
bool didCreate = false;
|
||||
|
||||
status_t err = open_or_create_type(type, &node, &didCreate);
|
||||
if (!err && didCreate)
|
||||
_SendInstallNotification(type);
|
||||
if (err != B_OK)
|
||||
return err;
|
||||
|
||||
if (!err)
|
||||
err = node.WriteAttr(attr.c_str(), attrType, 0, data, attrSize);
|
||||
if (err >= 0)
|
||||
err = err == (ssize_t)attrSize ? (status_t)B_OK : (status_t)B_FILE_ERROR;
|
||||
if (!err) {
|
||||
if (didCreate) {
|
||||
_SendInstallNotification(type);
|
||||
} else if (!err) {
|
||||
if (fileType) {
|
||||
_SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
|
||||
(which == B_LARGE_ICON), B_META_MIME_MODIFIED);
|
||||
} else {
|
||||
_SendMonitorUpdate(B_ICON_CHANGED, type, (which == B_LARGE_ICON),
|
||||
B_META_MIME_MODIFIED);
|
||||
_SendMonitorUpdate(B_ICON_CHANGED, type,
|
||||
(which == B_LARGE_ICON), B_META_MIME_MODIFIED);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
|
@ -483,14 +492,16 @@ Database::SetIconForType(const char *type, const char *fileType,
|
|||
bool didCreate = false;
|
||||
|
||||
status_t err = open_or_create_type(type, &node, &didCreate);
|
||||
if (!err && didCreate)
|
||||
_SendInstallNotification(type);
|
||||
if (err != B_OK)
|
||||
return err;
|
||||
|
||||
if (!err)
|
||||
err = node.WriteAttr(attr.c_str(), attrType, 0, data, dataSize);
|
||||
if (err >= 0)
|
||||
err = err == (ssize_t)dataSize ? (status_t)B_OK : (status_t)B_FILE_ERROR;
|
||||
if (!err) {
|
||||
if (didCreate) {
|
||||
_SendInstallNotification(type);
|
||||
} else if (!err) {
|
||||
// TODO: extra notification for vector icons (currently
|
||||
// passing "true" for B_LARGE_ICON)?
|
||||
if (fileType) {
|
||||
|
@ -542,10 +553,11 @@ Database::SetSnifferRule(const char *type, const char *rule)
|
|||
if (status == B_OK)
|
||||
status = fSnifferRules.SetSnifferRule(type, rule);
|
||||
|
||||
if (status == B_OK) {
|
||||
if (didCreate)
|
||||
_SendInstallNotification(type);
|
||||
_SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type, B_META_MIME_MODIFIED);
|
||||
if (didCreate) {
|
||||
_SendInstallNotification(type);
|
||||
} else if (status == B_OK) {
|
||||
_SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type,
|
||||
B_META_MIME_MODIFIED);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -593,16 +605,20 @@ Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSy
|
|||
&didCreate);
|
||||
|
||||
// Notify the monitor if we created the type when we opened it
|
||||
if (status == B_OK && didCreate)
|
||||
_SendInstallNotification(type);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// Update the supporting apps map
|
||||
if (status == B_OK)
|
||||
status = fSupportingApps.SetSupportedTypes(type, types, fullSync);
|
||||
|
||||
// Notify the monitor
|
||||
if (status == B_OK)
|
||||
_SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type, B_META_MIME_MODIFIED);
|
||||
if (didCreate) {
|
||||
_SendInstallNotification(type);
|
||||
} else if (status == B_OK) {
|
||||
_SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type,
|
||||
B_META_MIME_MODIFIED);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1274,6 +1290,51 @@ Database::DeleteSupportedTypes(const char *type, bool fullSync)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
Database::DeferInstallNotification(const char* type)
|
||||
{
|
||||
AutoLocker<BLocker> _(fDeferredInstallNotificationsLocker);
|
||||
|
||||
// check, if already deferred
|
||||
if (_FindDeferredInstallNotification(type))
|
||||
return;
|
||||
|
||||
// add new
|
||||
DeferredInstallNotification* notification
|
||||
= new(std::nothrow) DeferredInstallNotification;
|
||||
if (notification == NULL)
|
||||
return;
|
||||
|
||||
strlcpy(notification->type, type, sizeof(notification->type));
|
||||
notification->notify = false;
|
||||
|
||||
if (!fDeferredInstallNotifications.AddItem(notification))
|
||||
delete notification;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Database::UndeferInstallNotification(const char* type)
|
||||
{
|
||||
AutoLocker<BLocker> locker(fDeferredInstallNotificationsLocker);
|
||||
|
||||
// check, if deferred at all
|
||||
DeferredInstallNotification* notification
|
||||
= _FindDeferredInstallNotification(type, true);
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
if (notification == NULL)
|
||||
return;
|
||||
|
||||
// notify, if requested
|
||||
if (notification->notify)
|
||||
_SendInstallNotification(notification->type);
|
||||
|
||||
delete notification;
|
||||
}
|
||||
|
||||
|
||||
//! \brief Sends a \c B_MIME_TYPE_CREATED notification to the mime monitor service
|
||||
status_t
|
||||
Database::_SendInstallNotification(const char *type)
|
||||
|
@ -1305,7 +1366,10 @@ Database::_SendMonitorUpdate(int32 which, const char *type, const char *extraTyp
|
|||
{
|
||||
BMessage msg(B_META_MIME_CHANGED);
|
||||
status_t err;
|
||||
|
||||
|
||||
if (_CheckDeferredInstallNotification(which, type))
|
||||
return B_OK;
|
||||
|
||||
err = msg.AddInt32("be:which", which);
|
||||
if (!err)
|
||||
err = msg.AddString("be:type", type);
|
||||
|
@ -1331,6 +1395,9 @@ status_t
|
|||
Database::_SendMonitorUpdate(int32 which, const char *type, const char *extraType,
|
||||
int32 action)
|
||||
{
|
||||
if (_CheckDeferredInstallNotification(which, type))
|
||||
return B_OK;
|
||||
|
||||
BMessage msg(B_META_MIME_CHANGED);
|
||||
|
||||
status_t err = msg.AddInt32("be:which", which);
|
||||
|
@ -1356,6 +1423,9 @@ Database::_SendMonitorUpdate(int32 which, const char *type, const char *extraTyp
|
|||
status_t
|
||||
Database::_SendMonitorUpdate(int32 which, const char *type, bool largeIcon, int32 action)
|
||||
{
|
||||
if (_CheckDeferredInstallNotification(which, type))
|
||||
return B_OK;
|
||||
|
||||
BMessage msg(B_META_MIME_CHANGED);
|
||||
|
||||
status_t err = msg.AddInt32("be:which", which);
|
||||
|
@ -1379,6 +1449,9 @@ Database::_SendMonitorUpdate(int32 which, const char *type, bool largeIcon, int3
|
|||
status_t
|
||||
Database::_SendMonitorUpdate(int32 which, const char *type, int32 action)
|
||||
{
|
||||
if (_CheckDeferredInstallNotification(which, type))
|
||||
return B_OK;
|
||||
|
||||
BMessage msg(B_META_MIME_CHANGED);
|
||||
|
||||
status_t err = msg.AddInt32("be:which", which);
|
||||
|
@ -1413,7 +1486,58 @@ Database::_SendMonitorUpdate(BMessage &msg)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
Database::DeferredInstallNotification*
|
||||
Database::_FindDeferredInstallNotification(const char* type, bool remove)
|
||||
{
|
||||
for (int32 i = 0;
|
||||
DeferredInstallNotification* notification
|
||||
= (DeferredInstallNotification*)fDeferredInstallNotifications
|
||||
.ItemAt(i); i++) {
|
||||
if (strcmp(type, notification->type) == 0) {
|
||||
if (remove)
|
||||
fDeferredInstallNotifications.RemoveItem(i);
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Database::_CheckDeferredInstallNotification(int32 which, const char* type)
|
||||
{
|
||||
AutoLocker<BLocker> locker(fDeferredInstallNotificationsLocker);
|
||||
|
||||
// check, if deferred at all
|
||||
DeferredInstallNotification* notification
|
||||
= _FindDeferredInstallNotification(type);
|
||||
if (notification == NULL)
|
||||
return false;
|
||||
|
||||
if (which == B_MIME_TYPE_DELETED) {
|
||||
// MIME type deleted -- if the install notification had been
|
||||
// deferred, we don't send anything
|
||||
if (notification->notify) {
|
||||
fDeferredInstallNotifications.RemoveItem(notification);
|
||||
delete notification;
|
||||
return true;
|
||||
}
|
||||
} else if (which == B_MIME_TYPE_CREATED) {
|
||||
// MIME type created -- defer notification
|
||||
notification->notify = true;
|
||||
return true;
|
||||
} else {
|
||||
// MIME type update -- don't send update, if deferred
|
||||
if (notification->notify)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Mime
|
||||
} // namespace Storage
|
||||
} // namespace BPrivate
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
#include <Mime.h>
|
||||
#include <Messenger.h>
|
||||
#include <StorageDefs.h>
|
||||
|
@ -102,7 +104,16 @@ class Database {
|
|||
status_t DeleteSnifferRule(const char *type);
|
||||
status_t DeleteSupportedTypes(const char *type, bool fullSync);
|
||||
|
||||
// deferred notifications
|
||||
void DeferInstallNotification(const char* type);
|
||||
void UndeferInstallNotification(const char* type);
|
||||
|
||||
private:
|
||||
struct DeferredInstallNotification {
|
||||
char type[B_MIME_TYPE_LENGTH];
|
||||
bool notify;
|
||||
};
|
||||
|
||||
status_t _SetStringValue(const char *type, int32 what,
|
||||
const char* attribute, type_code attributeType,
|
||||
size_t maxLength, const char *value);
|
||||
|
@ -120,6 +131,10 @@ class Database {
|
|||
int32 action);
|
||||
status_t _SendMonitorUpdate(BMessage &msg);
|
||||
|
||||
DeferredInstallNotification* _FindDeferredInstallNotification(
|
||||
const char* type, bool remove = false);
|
||||
bool _CheckDeferredInstallNotification(int32 which, const char* type);
|
||||
|
||||
private:
|
||||
status_t fStatus;
|
||||
std::set<BMessenger> fMonitorMessengers;
|
||||
|
@ -127,6 +142,31 @@ class Database {
|
|||
InstalledTypes fInstalledTypes;
|
||||
SnifferRules fSnifferRules;
|
||||
SupportingApps fSupportingApps;
|
||||
|
||||
BLocker fDeferredInstallNotificationsLocker;
|
||||
BList fDeferredInstallNotifications;
|
||||
};
|
||||
|
||||
class InstallNotificationDeferrer {
|
||||
public:
|
||||
InstallNotificationDeferrer(Database* database, const char* type)
|
||||
:
|
||||
fDatabase(database),
|
||||
fType(type)
|
||||
{
|
||||
if (fDatabase != NULL && fType != NULL)
|
||||
fDatabase->DeferInstallNotification(fType);
|
||||
}
|
||||
|
||||
~InstallNotificationDeferrer()
|
||||
{
|
||||
if (fDatabase != NULL && fType != NULL)
|
||||
fDatabase->UndeferInstallNotification(fType);
|
||||
}
|
||||
|
||||
private:
|
||||
Database* fDatabase;
|
||||
const char* fType;
|
||||
};
|
||||
|
||||
} // namespace Mime
|
||||
|
|
|
@ -49,9 +49,11 @@ namespace Mime {
|
|||
The message will be replied to at the end of the thread's execution.
|
||||
*/
|
||||
MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority,
|
||||
BMessenger managerMessenger, const entry_ref *root, bool recursive,
|
||||
int32 force, BMessage *replyee)
|
||||
: RegistrarThread(name, priority, managerMessenger),
|
||||
Database *database, BMessenger managerMessenger, const entry_ref *root,
|
||||
bool recursive, int32 force, BMessage *replyee)
|
||||
:
|
||||
RegistrarThread(name, priority, managerMessenger),
|
||||
fDatabase(database),
|
||||
fRoot(root ? *root : entry_ref()),
|
||||
fRecursive(recursive),
|
||||
fForce(force),
|
||||
|
|
|
@ -25,9 +25,11 @@ namespace BPrivate {
|
|||
namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
class Database;
|
||||
|
||||
class MimeUpdateThread : public RegistrarThread {
|
||||
public:
|
||||
MimeUpdateThread(const char *name, int32 priority,
|
||||
MimeUpdateThread(const char *name, int32 priority, Database *database,
|
||||
BMessenger managerMessenger, const entry_ref *root, bool recursive,
|
||||
int32 force, BMessage *replyee);
|
||||
virtual ~MimeUpdateThread();
|
||||
|
@ -37,7 +39,8 @@ public:
|
|||
protected:
|
||||
virtual status_t ThreadFunction();
|
||||
virtual status_t DoMimeUpdate(const entry_ref *entry, bool *entryIsDir) = 0;
|
||||
|
||||
|
||||
Database* fDatabase;
|
||||
const entry_ref fRoot;
|
||||
const bool fRecursive;
|
||||
const int32 fForce;
|
||||
|
|
|
@ -66,10 +66,10 @@ is_shared_object_mime_type(BMimeType &type)
|
|||
// constructor
|
||||
//! Creates a new UpdateMimeInfoThread object
|
||||
UpdateMimeInfoThread::UpdateMimeInfoThread(const char *name, int32 priority,
|
||||
BMessenger managerMessenger, const entry_ref *root, bool recursive,
|
||||
int32 force, BMessage *replyee)
|
||||
: MimeUpdateThread(name, priority, managerMessenger, root, recursive, force,
|
||||
replyee)
|
||||
Database *database, BMessenger managerMessenger, const entry_ref *root,
|
||||
bool recursive, int32 force, BMessage *replyee)
|
||||
: MimeUpdateThread(name, priority, database, managerMessenger, root,
|
||||
recursive, force, replyee)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Mime {
|
|||
|
||||
class UpdateMimeInfoThread : public MimeUpdateThread {
|
||||
public:
|
||||
UpdateMimeInfoThread(const char *name, int32 priority,
|
||||
UpdateMimeInfoThread(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);
|
||||
|
|
Loading…
Reference in New Issue