Rework Deskbar's tray replicant support a bit. Instead of relying on a live query

for be:deskbar_item_status in order to determine which replicants are supposed to
be living in the tray, a list of entry refs is now stored. While the former approach
was cool, it doesn't really work in either a multiuser or a package-aware world, where
executables are generally read-only. Note this means you'll lose your existing replicants
the first time you run this new revision, and need to re-add them.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43004 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent
2011-10-30 16:52:03 +00:00
parent 9f37e36f78
commit 3e6ff860b4
5 changed files with 54 additions and 199 deletions
+7
View File
@@ -1028,6 +1028,13 @@ TBarView::AddItem(BMessage* item, DeskbarShelf, int32* id)
} }
status_t
TBarView::AddItem(BEntry* entry, DeskbarShelf, int32* id)
{
return fReplicantTray->LoadAddOn(entry, id);
}
void void
TBarView::RemoveItem(int32 id) TBarView::RemoveItem(int32 id)
{ {
+1
View File
@@ -125,6 +125,7 @@ class TBarView : public BView {
int32 CountItems(DeskbarShelf shelf); int32 CountItems(DeskbarShelf shelf);
status_t AddItem(BMessage* archive, DeskbarShelf shelf, int32* id); status_t AddItem(BMessage* archive, DeskbarShelf shelf, int32* id);
status_t AddItem(BEntry* entry, DeskbarShelf shelf, int32* id);
void RemoveItem(int32 id); void RemoveItem(int32 id);
void RemoveItem(const char* name, DeskbarShelf shelf); void RemoveItem(const char* name, DeskbarShelf shelf);
+5 -12
View File
@@ -518,7 +518,7 @@ TBarWindow::CountItems(BMessage* message)
void void
TBarWindow::AddItem(BMessage* message) TBarWindow::AddItem(BMessage* message)
{ {
DeskbarShelf shelf; DeskbarShelf shelf = B_DESKBAR_TRAY;
entry_ref ref; entry_ref ref;
int32 id = 999; int32 id = 999;
BMessage reply; BMessage reply;
@@ -527,24 +527,17 @@ TBarWindow::AddItem(BMessage* message)
BMessage archivedView; BMessage archivedView;
if (message->FindMessage("view", &archivedView) == B_OK) { if (message->FindMessage("view", &archivedView) == B_OK) {
#if SHELF_AWARE #if SHELF_AWARE
if (message->FindInt32("shelf", (int32*)&shelf) != B_OK) message->FindInt32("shelf", &shelf);
#endif #endif
shelf = B_DESKBAR_TRAY;
BMessage* archive = new BMessage(archivedView); BMessage* archive = new BMessage(archivedView);
err = fBarView->AddItem(archive, shelf, &id); err = fBarView->AddItem(archive, shelf, &id);
if (err < B_OK) if (err < B_OK)
delete archive; delete archive;
} else if (message->FindRef("addon", &ref) == B_OK) { } else if (message->FindRef("addon", &ref) == B_OK) {
// exposing the name of the view here is not so great
TReplicantTray* tray
= dynamic_cast<TReplicantTray*>(FindView("Status"));
if (tray) {
// Force this into the deskbar even if the security code is wrong
// This is OK because the user specifically asked for this replicant
BEntry entry(&ref); BEntry entry(&ref);
err = tray->LoadAddOn(&entry, &id, true); err = entry.InitCheck();
} if (err == B_OK)
err = fBarView->AddItem(&entry, shelf, &id);
} }
if (err == B_OK) if (err == B_OK)
+35 -179
View File
@@ -83,11 +83,8 @@ using std::max;
const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item"; const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item";
const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry"; const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry";
const char* const kDeskbarSecurityCodeFile = "Deskbar_security_code"; const char* const kReplicantSettingsFile = "Deskbar_replicants";
const char* const kDeskbarSecurityCodeAttr = "be:deskbar_security_code"; const char* const kReplicantRefField = "replicant";
const char* const kStatusPredicate = "be:deskbar_item_status";
const char* const kEnabledPredicate = "be:deskbar_item_status = enabled";
const char* const kDisabledPredicate = "be:deskbar_item_status = disabled";
float sMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth; float sMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth;
@@ -331,7 +328,6 @@ TReplicantTray::MessageReceived(BMessage* message)
#ifdef DB_ADDONS #ifdef DB_ADDONS
case B_NODE_MONITOR: case B_NODE_MONITOR:
case B_QUERY_UPDATE:
HandleEntryUpdate(message); HandleEntryUpdate(message);
break; break;
#endif #endif
@@ -410,53 +406,48 @@ TReplicantTray::InitAddOnSupport()
{ {
// list to maintain refs to each rep added/deleted // list to maintain refs to each rep added/deleted
fItemList = new BList(); fItemList = new BList();
bool haveKey = false;
BPath path; BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) { if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
path.Append(kDeskbarSecurityCodeFile); path.Append(kReplicantSettingsFile);
BFile file(path.Path(), B_READ_ONLY); BFile file(path.Path(), B_READ_ONLY);
if (file.InitCheck() == B_OK if (file.InitCheck() == B_OK) {
&& file.Read(&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode)) entry_ref ref;
== sizeof(fDeskbarSecurityCode)) status_t result;
haveKey = true; BEntry entry;
} int32 id;
if (!haveKey) { if (fAddOnSettings.Unflatten(&file) == B_OK) {
// create the security code for (int32 i = 0; fAddOnSettings.FindRef(kReplicantRefField,
bigtime_t real = real_time_clock_usecs(); i, &ref) == B_OK; i++) {
bigtime_t boot = system_time(); if (entry.SetTo(&ref) == B_OK && entry.Exists()) {
// two computers would have to have exactly matching clocks, and launch result = LoadAddOn(&entry, &id, false);
// Deskbar at the exact same time into the bootsequence in order for } else
// their security-ID to be identical result = B_ENTRY_NOT_FOUND;
fDeskbarSecurityCode = ((real & 0xffffffffULL) << 32)
| (boot & 0xffffffffULL);
if (find_directory (B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) { if (result != B_OK) {
path.Append(kDeskbarSecurityCodeFile); fAddOnSettings.RemoveData(kReplicantRefField, i);
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE --i;
| B_ERASE_FILE); }
if (file.InitCheck() == B_OK) }
file.Write(&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode));
} }
} }
// for each volume currently mounted index the volume with our indices
BVolumeRoster roster;
BVolume volume;
while (roster.GetNextVolume(&volume) == B_OK) {
fs_create_index(volume.Device(), kStatusPredicate, B_STRING_TYPE, 0);
RunAddOnQuery(&volume, kEnabledPredicate);
} }
// we also watch for volumes mounted and unmounted
watch_node(NULL, B_WATCH_MOUNT | B_WATCH_ATTR, this, Window());
} }
void void
TReplicantTray::DeleteAddOnSupport() TReplicantTray::DeleteAddOnSupport()
{ {
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
path.Append(kReplicantSettingsFile);
BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
if (file.InitCheck() == B_OK)
fAddOnSettings.Flatten(&file);
}
for (int32 i = fItemList->CountItems(); i-- > 0 ;) { for (int32 i = fItemList->CountItems(); i-- > 0 ;) {
DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i); DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
if (item) { if (item) {
@@ -473,47 +464,6 @@ TReplicantTray::DeleteAddOnSupport()
} }
void
TReplicantTray::RunAddOnQuery(BVolume* volume, const char* predicate)
{
// Since the new BFS supports querying for attributes without
// an index, we only run the query if the index exists (for
// newly mounted devices only - the Deskbar will automatically
// create an index for every device mounted at startup).
index_info info;
if (!volume->KnowsQuery()
|| fs_stat_index(volume->Device(), kStatusPredicate, &info) != 0)
return;
// run a new query on a specific volume and make it live
BQuery query;
query.SetVolume(volume);
query.SetPredicate(predicate);
query.Fetch();
int32 id;
BEntry entry;
while (query.GetNextEntry(&entry) == B_OK) {
// scan any entries returned
// attempt to load them as add-ons
// collisions are handled in LoadAddOn
LoadAddOn(&entry, &id);
}
}
bool
TReplicantTray::IsAddOn(entry_ref& ref)
{
BFile file(&ref, B_READ_ONLY);
char status[64];
ssize_t size = file.ReadAttr(kStatusPredicate, B_STRING_TYPE, 0, &status,
sizeof(status));
return size > 0;
}
DeskbarItemInfo* DeskbarItemInfo*
TReplicantTray::DeskbarItemFor(node_ref& nodeRef) TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
{ {
@@ -565,61 +515,6 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
BPath path; BPath path;
switch (opcode) { switch (opcode) {
case B_ENTRY_CREATED:
{
// entry was just listed, matches live query
const char* name;
ino_t directory;
dev_t device;
// received when an app adds a ref to the
// Deskbar add-ons folder
if (message->FindString("name", &name) == B_OK
&& message->FindInt64("directory", &directory) == B_OK
&& message->FindInt32("device", &device) == B_OK) {
entry_ref ref(device, directory, name);
// see if this item has the attribute
// that we expect
if (IsAddOn(ref)) {
int32 id;
BEntry entry(&ref);
LoadAddOn(&entry, &id);
}
}
break;
}
case B_ATTR_CHANGED:
{
// from node watch on individual items
// (node_watch added in LoadAddOn)
node_ref nodeRef;
if (message->FindInt32("device", &(nodeRef.device)) == B_OK
&& message->FindInt64("node", &(nodeRef.node)) == B_OK) {
// get the add-on this is for
DeskbarItemInfo* item = DeskbarItemFor(nodeRef);
if (item == NULL)
break;
BFile file(&item->entryRef, B_READ_ONLY);
char status[255];
ssize_t size = file.ReadAttr(kStatusPredicate,
B_STRING_TYPE, 0, status, sizeof(status) - 1);
status[sizeof(status) - 1] = '\0';
// attribute was removed
if (size == B_ENTRY_NOT_FOUND) {
// cleans up and removes node_watch
UnloadAddOn(&nodeRef, NULL, true, false);
} else if (!strcmp(status, "enable")) {
int32 id;
BEntry entry(&item->entryRef, true);
LoadAddOn(&entry, &id);
}
}
break;
}
case B_ENTRY_MOVED: case B_ENTRY_MOVED:
{ {
entry_ref ref; entry_ref ref;
@@ -663,32 +558,6 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
} }
break; break;
} }
case B_DEVICE_MOUNTED:
{
// run a new query on the new device
dev_t device;
if (message->FindInt32("new device", &device) != B_OK)
break;
BVolume volume(device);
RunAddOnQuery(&volume, kEnabledPredicate);
break;
}
case B_DEVICE_UNMOUNTED:
{
// remove all items associated with the device
// unmounted
// contrary to what the BeBook says, the item is called "device",
// not "new device" like it is for B_DEVICE_MOUNTED
dev_t device;
if (message->FindInt32("device", &device) != B_OK)
break;
UnloadAddOn(NULL, &device, false, true);
break;
}
} }
} }
@@ -698,7 +567,7 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
primary function is the Instantiate function primary function is the Instantiate function
*/ */
status_t status_t
TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force) TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
{ {
if (!entry) if (!entry)
return B_ERROR; return B_ERROR;
@@ -710,21 +579,6 @@ TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
return B_ERROR; return B_ERROR;
BNode node(entry); BNode node(entry);
if (!force) {
status_t error = node.InitCheck();
if (error != B_OK)
return error;
uint64 deskbarID;
ssize_t size = node.ReadAttr(kDeskbarSecurityCodeAttr, B_UINT64_TYPE,
0, &deskbarID, sizeof(fDeskbarSecurityCode));
if (size != sizeof(fDeskbarSecurityCode)
|| deskbarID != fDeskbarSecurityCode) {
// no code or code doesn't match
return B_ERROR;
}
}
BPath path; BPath path;
status_t status = entry->GetPath(&path); status_t status = entry->GetPath(&path);
if (status < B_OK) if (status < B_OK)
@@ -770,8 +624,11 @@ TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
AddIcon(data, id, &ref); AddIcon(data, id, &ref);
// add the rep; adds info to list // add the rep; adds info to list
node.WriteAttr(kDeskbarSecurityCodeAttr, B_UINT64_TYPE, 0, if (addToSettings) {
&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode)); entry_ref ref;
if (entry->GetRef(&ref) == B_OK)
fAddOnSettings.AddRef(kReplicantRefField, &ref);
}
return B_OK; return B_OK;
} }
@@ -841,7 +698,6 @@ TReplicantTray::RemoveItem(int32 id)
// attribute was added via Deskbar API (AddItem(entry_ref*, int32*) // attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
if (item->isAddOn) { if (item->isAddOn) {
BNode node(&item->entryRef); BNode node(&item->entryRef);
node.RemoveAttr(kStatusPredicate);
watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window()); watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
} }
+2 -4
View File
@@ -117,7 +117,7 @@ public:
void DealWithClock(bool); void DealWithClock(bool);
#ifdef DB_ADDONS #ifdef DB_ADDONS
status_t LoadAddOn(BEntry* entry, int32* id, bool force = false); status_t LoadAddOn(BEntry* entry, int32* id, bool addToSettings = true);
#endif #endif
private: private:
@@ -129,9 +129,7 @@ private:
#ifdef DB_ADDONS #ifdef DB_ADDONS
void InitAddOnSupport(); void InitAddOnSupport();
void DeleteAddOnSupport(); void DeleteAddOnSupport();
void RunAddOnQuery(BVolume* volume, const char* predicated);
bool IsAddOn(entry_ref &ref);
DeskbarItemInfo* DeskbarItemFor(node_ref &nodeRef); DeskbarItemInfo* DeskbarItemFor(node_ref &nodeRef);
DeskbarItemInfo* DeskbarItemFor(int32 id); DeskbarItemInfo* DeskbarItemFor(int32 id);
bool NodeExists(node_ref &nodeRef); bool NodeExists(node_ref &nodeRef);
@@ -162,7 +160,7 @@ private:
bool fAlignmentSupport; bool fAlignmentSupport;
#ifdef DB_ADDONS #ifdef DB_ADDONS
BList* fItemList; BList* fItemList;
uint64 fDeskbarSecurityCode; BMessage fAddOnSettings;
#endif #endif
}; };