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
TBarView::RemoveItem(int32 id)
{
+1
View File
@@ -125,6 +125,7 @@ class TBarView : public BView {
int32 CountItems(DeskbarShelf shelf);
status_t AddItem(BMessage* archive, DeskbarShelf shelf, int32* id);
status_t AddItem(BEntry* entry, DeskbarShelf shelf, int32* id);
void RemoveItem(int32 id);
void RemoveItem(const char* name, DeskbarShelf shelf);
+6 -13
View File
@@ -518,7 +518,7 @@ TBarWindow::CountItems(BMessage* message)
void
TBarWindow::AddItem(BMessage* message)
{
DeskbarShelf shelf;
DeskbarShelf shelf = B_DESKBAR_TRAY;
entry_ref ref;
int32 id = 999;
BMessage reply;
@@ -527,24 +527,17 @@ TBarWindow::AddItem(BMessage* message)
BMessage archivedView;
if (message->FindMessage("view", &archivedView) == B_OK) {
#if SHELF_AWARE
if (message->FindInt32("shelf", (int32*)&shelf) != B_OK)
message->FindInt32("shelf", &shelf);
#endif
shelf = B_DESKBAR_TRAY;
BMessage* archive = new BMessage(archivedView);
err = fBarView->AddItem(archive, shelf, &id);
if (err < B_OK)
delete archive;
} 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);
err = tray->LoadAddOn(&entry, &id, true);
}
BEntry entry(&ref);
err = entry.InitCheck();
if (err == B_OK)
err = fBarView->AddItem(&entry, shelf, &id);
}
if (err == B_OK)
+38 -182
View File
@@ -83,11 +83,8 @@ using std::max;
const char* const kInstantiateItemCFunctionName = "instantiate_deskbar_item";
const char* const kInstantiateEntryCFunctionName = "instantiate_deskbar_entry";
const char* const kDeskbarSecurityCodeFile = "Deskbar_security_code";
const char* const kDeskbarSecurityCodeAttr = "be:deskbar_security_code";
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";
const char* const kReplicantSettingsFile = "Deskbar_replicants";
const char* const kReplicantRefField = "replicant";
float sMinimumWindowWidth = kGutter + kMinimumTrayWidth + kDragRegionWidth;
@@ -331,7 +328,6 @@ TReplicantTray::MessageReceived(BMessage* message)
#ifdef DB_ADDONS
case B_NODE_MONITOR:
case B_QUERY_UPDATE:
HandleEntryUpdate(message);
break;
#endif
@@ -410,53 +406,48 @@ TReplicantTray::InitAddOnSupport()
{
// list to maintain refs to each rep added/deleted
fItemList = new BList();
bool haveKey = false;
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
path.Append(kDeskbarSecurityCodeFile);
path.Append(kReplicantSettingsFile);
BFile file(path.Path(), B_READ_ONLY);
if (file.InitCheck() == B_OK
&& file.Read(&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode))
== sizeof(fDeskbarSecurityCode))
haveKey = true;
}
if (!haveKey) {
// create the security code
bigtime_t real = real_time_clock_usecs();
bigtime_t boot = system_time();
// two computers would have to have exactly matching clocks, and launch
// Deskbar at the exact same time into the bootsequence in order for
// their security-ID to be identical
fDeskbarSecurityCode = ((real & 0xffffffffULL) << 32)
| (boot & 0xffffffffULL);
if (find_directory (B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
path.Append(kDeskbarSecurityCodeFile);
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE
| B_ERASE_FILE);
if (file.InitCheck() == B_OK)
file.Write(&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode));
if (file.InitCheck() == B_OK) {
entry_ref ref;
status_t result;
BEntry entry;
int32 id;
if (fAddOnSettings.Unflatten(&file) == B_OK) {
for (int32 i = 0; fAddOnSettings.FindRef(kReplicantRefField,
i, &ref) == B_OK; i++) {
if (entry.SetTo(&ref) == B_OK && entry.Exists()) {
result = LoadAddOn(&entry, &id, false);
} else
result = B_ENTRY_NOT_FOUND;
if (result != B_OK) {
fAddOnSettings.RemoveData(kReplicantRefField, i);
--i;
}
}
}
}
}
// 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
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 ;) {
DeskbarItemInfo* item = (DeskbarItemInfo*)fItemList->RemoveItem(i);
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*
TReplicantTray::DeskbarItemFor(node_ref& nodeRef)
{
@@ -565,61 +515,6 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
BPath path;
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:
{
entry_ref ref;
@@ -663,32 +558,6 @@ TReplicantTray::HandleEntryUpdate(BMessage* message)
}
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
*/
status_t
TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool addToSettings)
{
if (!entry)
return B_ERROR;
@@ -710,21 +579,6 @@ TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
return B_ERROR;
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;
status_t status = entry->GetPath(&path);
if (status < B_OK)
@@ -770,9 +624,12 @@ TReplicantTray::LoadAddOn(BEntry* entry, int32* id, bool force)
AddIcon(data, id, &ref);
// add the rep; adds info to list
node.WriteAttr(kDeskbarSecurityCodeAttr, B_UINT64_TYPE, 0,
&fDeskbarSecurityCode, sizeof(fDeskbarSecurityCode));
if (addToSettings) {
entry_ref ref;
if (entry->GetRef(&ref) == B_OK)
fAddOnSettings.AddRef(kReplicantRefField, &ref);
}
return B_OK;
}
@@ -841,7 +698,6 @@ TReplicantTray::RemoveItem(int32 id)
// attribute was added via Deskbar API (AddItem(entry_ref*, int32*)
if (item->isAddOn) {
BNode node(&item->entryRef);
node.RemoveAttr(kStatusPredicate);
watch_node(&item->nodeRef, B_STOP_WATCHING, this, Window());
}
+2 -4
View File
@@ -117,7 +117,7 @@ public:
void DealWithClock(bool);
#ifdef DB_ADDONS
status_t LoadAddOn(BEntry* entry, int32* id, bool force = false);
status_t LoadAddOn(BEntry* entry, int32* id, bool addToSettings = true);
#endif
private:
@@ -129,9 +129,7 @@ private:
#ifdef DB_ADDONS
void InitAddOnSupport();
void DeleteAddOnSupport();
void RunAddOnQuery(BVolume* volume, const char* predicated);
bool IsAddOn(entry_ref &ref);
DeskbarItemInfo* DeskbarItemFor(node_ref &nodeRef);
DeskbarItemInfo* DeskbarItemFor(int32 id);
bool NodeExists(node_ref &nodeRef);
@@ -162,7 +160,7 @@ private:
bool fAlignmentSupport;
#ifdef DB_ADDONS
BList* fItemList;
uint64 fDeskbarSecurityCode;
BMessage fAddOnSettings;
#endif
};