xref: /haiku/src/kits/storage/mime/AppMetaMimeCreator.cpp (revision 9f81ca838ce7b92b5689e57d3f86765db4705a7b)
1 /*
2  * Copyright 2002-2013, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Tyler Dauwalder
7  *		Axel Dörfler, axeld@pinc-software.de
8  *		Ingo Weinhold, ingo_weinhold@gmx.de
9  */
10 
11 
12 #include <mime/AppMetaMimeCreator.h>
13 
14 #include <stdlib.h>
15 
16 #include <AppFileInfo.h>
17 #include <Bitmap.h>
18 #include <File.h>
19 #include <fs_attr.h>
20 #include <Message.h>
21 #include <MimeType.h>
22 #include <String.h>
23 
24 #include <AutoLocker.h>
25 #include <mime/Database.h>
26 #include <mime/database_support.h>
27 #include <mime/DatabaseLocation.h>
28 
29 
30 namespace BPrivate {
31 namespace Storage {
32 namespace Mime {
33 
34 
AppMetaMimeCreator(Database * database,DatabaseLocker * databaseLocker,int32 force)35 AppMetaMimeCreator::AppMetaMimeCreator(Database* database,
36 	DatabaseLocker* databaseLocker, int32 force)
37 	:
38 	MimeEntryProcessor(database, databaseLocker, force)
39 {
40 }
41 
42 
~AppMetaMimeCreator()43 AppMetaMimeCreator::~AppMetaMimeCreator()
44 {
45 }
46 
47 
48 status_t
Do(const entry_ref & entry,bool * _entryIsDir)49 AppMetaMimeCreator::Do(const entry_ref& entry, bool* _entryIsDir)
50 {
51 	BFile file;
52 	status_t status = file.SetTo(&entry, B_READ_ONLY | O_NOTRAVERSE);
53 	if (status < B_OK)
54 		return status;
55 
56 	bool isDir = file.IsDirectory();
57 	if (_entryIsDir != NULL)
58 		*_entryIsDir = isDir;
59 
60 	if (isDir || !file.IsFile())
61 		return B_OK;
62 
63 	BAppFileInfo appInfo(&file);
64 	status = appInfo.InitCheck();
65 	if (status < B_OK)
66 		return status;
67 
68 	// Read the app sig (which consequently keeps us from updating
69 	// non-applications, since we get an error if the file has no
70 	// app sig)
71 	BString signature;
72 	status = file.ReadAttrString("BEOS:APP_SIG", &signature);
73 	if (status != B_OK)
74 		return B_BAD_TYPE;
75 
76 	if (!BMimeType::IsValid(signature))
77 		return B_BAD_TYPE;
78 
79 	InstallNotificationDeferrer _(fDatabase, signature.String());
80 
81 	if (!fDatabase->Location()->IsInstalled(signature)) {
82 		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
83 		fDatabase->Install(signature);
84 	}
85 
86 	BNode typeNode;
87 	status = fDatabase->Location()->OpenType(signature, typeNode);
88 	if (status != B_OK)
89 		return status;
90 
91 	// Preferred App
92 	attr_info info;
93 	if (status == B_OK
94 		&& (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) {
95 		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
96 		status = fDatabase->SetPreferredApp(signature, signature);
97 	}
98 
99 	// Short Description (name of the application)
100 	if (status == B_OK
101 		&& (fForce
102 			|| typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) {
103 		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
104 		status = fDatabase->SetShortDescription(signature, entry.name);
105 	}
106 
107 	// App Hint
108 	if (status == B_OK
109 		&& (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) {
110 		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
111 		status = fDatabase->SetAppHint(signature, &entry);
112 	}
113 
114 	// Vector Icon
115 	if (status == B_OK
116 		&& (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) {
117 		uint8* data = NULL;
118 		size_t size = 0;
119 		if (appInfo.GetIcon(&data, &size) == B_OK) {
120 			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
121 			status = fDatabase->SetIcon(signature, data, size);
122 			free(data);
123 		}
124 	}
125 	// Mini Icon
126 	BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
127 	if (status == B_OK
128 		&& (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) {
129 		if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) {
130 			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
131 			status = fDatabase->SetIcon(signature, &miniIcon, B_MINI_ICON);
132 		}
133 	}
134 	// Large Icon
135 	BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
136 	if (status == B_OK
137 		&& (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) {
138 		if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) {
139 			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
140 			status = fDatabase->SetIcon(signature, &largeIcon, B_LARGE_ICON);
141 		}
142 	}
143 
144 	// Supported Types
145 	bool setSupportedTypes = false;
146 	BMessage supportedTypes;
147 	if (status == B_OK
148 		&& (fForce
149 			|| typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) {
150 		if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK)
151 			setSupportedTypes = true;
152 	}
153 
154 	// defer notifications for supported types
155 	const char* type;
156 	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
157 		fDatabase->DeferInstallNotification(type);
158 
159 	// set supported types
160 	if (setSupportedTypes) {
161 		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
162 		status = fDatabase->SetSupportedTypes(signature, &supportedTypes, true);
163 	}
164 
165 	// Icons for supported types
166 	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK;
167 		 i++) {
168 		// vector icon
169 		uint8* data = NULL;
170 		size_t size = 0;
171 		if (status == B_OK
172 			&& appInfo.GetIconForType(type, &data, &size) == B_OK) {
173 			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
174 			status = fDatabase->SetIconForType(signature, type, data, size);
175 			free(data);
176 		}
177 		// mini icon
178 		if (status == B_OK
179 			&& appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) {
180 			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
181 			status = fDatabase->SetIconForType(signature, type, &miniIcon,
182 				B_MINI_ICON);
183 		}
184 		// large icon
185 		if (status == B_OK
186 			&& appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) {
187 			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
188 			status = fDatabase->SetIconForType(signature, type, &largeIcon,
189 				B_LARGE_ICON);
190 		}
191 	}
192 
193 	// undefer notifications for supported types
194 	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
195 		fDatabase->UndeferInstallNotification(type);
196 
197 	return status;
198 }
199 
200 
201 } // namespace Mime
202 } // namespace Storage
203 } // namespace BPrivate
204