xref: /haiku/src/servers/keystore/AppAccessRequestWindow.cpp (revision 66cb2efaa8ea36030bb48a16ae664d975bb06e27)
1 /*
2  * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "AppAccessRequestWindow.h"
8 
9 #include <Catalog.h>
10 #include <LayoutBuilder.h>
11 #include <LayoutUtils.h>
12 #include <NodeInfo.h>
13 #include <Roster.h>
14 #include <SpaceLayoutItem.h>
15 #include <TextView.h>
16 
17 #include <new>
18 
19 #undef B_TRANSLATION_CONTEXT
20 #define B_TRANSLATION_CONTEXT "AppAccessRequestWindow"
21 
22 
23 static const uint32 kMessageDisallow = 'btda';
24 static const uint32 kMessageOnce = 'btao';
25 static const uint32 kMessageAlways = 'btaa';
26 
27 
AppAccessRequestWindow(const char * keyringName,const char * signature,const char * path,const char * accessString,bool appIsNew,bool appWasUpdated)28 AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName,
29 	const char* signature, const char* path, const char* accessString,
30 	bool appIsNew, bool appWasUpdated)
31 	:
32 	BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Application keyring access"),
33 		B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS
34 			| B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS
35 			| B_CLOSE_ON_ESCAPE),
36 	fDoneSem(-1),
37 	fResult(kMessageDisallow)
38 {
39 	fDoneSem = create_sem(0, "application keyring access dialog");
40 	if (fDoneSem < 0)
41 		return;
42 
43 
44 	BBitmap icon = GetIcon(32 * icon_layout_scale());
45 	fStripeView = new BStripeView(icon);
46 
47 	float inset = ceilf(be_plain_font->Size() * 0.7);
48 
49 	BTextView* message = new(std::nothrow) BTextView("Message");
50 	if (message == NULL)
51 		return;
52 
53 	BString details;
54 	details <<  B_TRANSLATE("The application:\n"
55 		"%signature% (%path%)\n\n");
56 	details.ReplaceFirst("%signature%", signature);
57 	details.ReplaceFirst("%path%", path);
58 
59 	if (keyringName != NULL) {
60 		details <<  B_TRANSLATE("requests access to keyring:\n"
61 			"%keyringName%\n\n");
62 		details.ReplaceFirst("%keyringName%", keyringName);
63 	}
64 
65 	if (accessString != NULL) {
66 		details <<  B_TRANSLATE("to perform the following action:\n"
67 			"%accessString%\n\n");
68 		details.ReplaceFirst("%accessString%", accessString);
69 	}
70 
71 	if (appIsNew)
72 		details <<  B_TRANSLATE("This application hasn't been granted "
73 		"access before.");
74 	else if (appWasUpdated) {
75 		details <<  B_TRANSLATE("This application has been updated since "
76 		"it was last granted access.");
77 	} else {
78 		details <<  B_TRANSLATE("This application doesn't yet have the "
79 		"required privileges.");
80 	}
81 
82 	message->SetText(details);
83 	message->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
84 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
85 	message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
86 	message->MakeEditable(false);
87 	message->MakeSelectable(false);
88 	message->SetWordWrap(true);
89 
90 	message->SetExplicitMinSize(BSize(message->StringWidth(
91 		"01234567890123456789012345678901234567890123456789") + inset,
92 		B_SIZE_UNSET));
93 
94 	fDisallowButton = new(std::nothrow) BButton(B_TRANSLATE("Disallow"),
95 		new BMessage(kMessageDisallow));
96 	fOnceButton = new(std::nothrow) BButton(B_TRANSLATE("Allow once"),
97 		new BMessage(kMessageOnce));
98 	fAlwaysButton = new(std::nothrow) BButton(B_TRANSLATE("Allow always"),
99 		new BMessage(kMessageAlways));
100 
101 	BLayoutBuilder::Group<>(this, B_HORIZONTAL, B_USE_ITEM_SPACING)
102 		.Add(fStripeView)
103 		.AddGroup(B_VERTICAL, 0)
104 			.SetInsets(0, B_USE_WINDOW_SPACING,
105 				B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING)
106 			.AddGroup(new BGroupView(B_VERTICAL, B_USE_ITEM_SPACING))
107 				.Add(message)
108 			.End()
109 			.AddStrut(B_USE_SMALL_SPACING)
110 			.AddGroup(new BGroupView(B_HORIZONTAL))
111 				.Add(fDisallowButton)
112 				.AddGlue()
113 				.Add(fOnceButton)
114 				.Add(fAlwaysButton)
115 			.End()
116 		.End()
117 	.End();
118 }
119 
120 
~AppAccessRequestWindow()121 AppAccessRequestWindow::~AppAccessRequestWindow()
122 {
123 	if (fDoneSem >= 0)
124 		delete_sem(fDoneSem);
125 }
126 
127 
128 bool
QuitRequested()129 AppAccessRequestWindow::QuitRequested()
130 {
131 	fResult = kMessageDisallow;
132 	release_sem(fDoneSem);
133 	return false;
134 }
135 
136 
137 void
MessageReceived(BMessage * message)138 AppAccessRequestWindow::MessageReceived(BMessage* message)
139 {
140 	switch (message->what) {
141 		case kMessageDisallow:
142 		case kMessageOnce:
143 		case kMessageAlways:
144 			fResult = message->what;
145 			release_sem(fDoneSem);
146 			return;
147 	}
148 
149 	BWindow::MessageReceived(message);
150 }
151 
152 
153 status_t
RequestAppAccess(bool & allowAlways)154 AppAccessRequestWindow::RequestAppAccess(bool& allowAlways)
155 {
156 	ResizeToPreferred();
157 	CenterOnScreen();
158 	Show();
159 
160 	while (acquire_sem(fDoneSem) == B_INTERRUPTED)
161 		;
162 
163 	status_t result;
164 	switch (fResult) {
165 		default:
166 		case kMessageDisallow:
167 			result = B_NOT_ALLOWED;
168 			allowAlways = false;
169 			break;
170 		case kMessageOnce:
171 			result = B_OK;
172 			allowAlways = false;
173 			break;
174 		case kMessageAlways:
175 			result = B_OK;
176 			allowAlways = true;
177 			break;
178 	}
179 
180 	LockLooper();
181 	Quit();
182 	return result;
183 }
184 
185 
186 BBitmap
GetIcon(int32 iconSize)187 AppAccessRequestWindow::GetIcon(int32 iconSize)
188 {
189 	BBitmap icon(BRect(0, 0, iconSize - 1, iconSize - 1), 0, B_RGBA32);
190 	team_info teamInfo;
191 	get_team_info(B_CURRENT_TEAM, &teamInfo);
192 	app_info appInfo;
193 	be_roster->GetRunningAppInfo(teamInfo.team, &appInfo);
194 	BNodeInfo::GetTrackerIcon(&appInfo.ref, &icon, icon_size(iconSize));
195 	return icon;
196 }
197