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