xref: /haiku/src/servers/keystore/AppAccessRequestWindow.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
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 <Button.h>
10 #include <CheckBox.h>
11 #include <GridLayout.h>
12 #include <GridView.h>
13 #include <GroupLayout.h>
14 #include <GroupView.h>
15 #include <MenuField.h>
16 #include <MenuItem.h>
17 #include <NetworkDevice.h>
18 #include <PopUpMenu.h>
19 #include <SpaceLayoutItem.h>
20 #include <TextView.h>
21 #include <View.h>
22 
23 #include <new>
24 
25 
26 static const uint32 kMessageDisallow = 'btda';
27 static const uint32 kMessageOnce = 'btao';
28 static const uint32 kMessageAlways = 'btaa';
29 
30 
31 class AppAccessRequestView : public BView {
32 public:
33 	AppAccessRequestView(const char* keyringName, const char* signature,
34 		const char* path, const char* accessString, bool appIsNew,
35 		bool appWasUpdated)
36 		:
37 		BView("AppAccessRequestView", B_WILL_DRAW)
38 	{
39 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
40 
41 		BGroupLayout* rootLayout = new(std::nothrow) BGroupLayout(B_VERTICAL);
42 		if (rootLayout == NULL)
43 			return;
44 
45 		SetLayout(rootLayout);
46 
47 		float inset = ceilf(be_plain_font->Size() * 0.7);
48 		rootLayout->SetInsets(inset, inset, inset, inset);
49 		rootLayout->SetSpacing(inset);
50 
51 		BTextView* message = new(std::nothrow) BTextView("Message");
52 		if (message == NULL)
53 			return;
54 
55 		BString details;
56 		details << "The application:\n"
57 			<< signature << " (" << path << ")\n\n";
58 
59 		if (keyringName != NULL) {
60 			details << "requests access to keyring:\n"
61 				<< keyringName << "\n\n";
62 		}
63 
64 		if (accessString != NULL) {
65 			details << "to perform the following action:\n"
66 				<< accessString << "\n\n";
67 		}
68 
69 		if (appIsNew)
70 			details << "This application hasn't been granted access before.";
71 		else if (appWasUpdated) {
72 			details << "This application has been updated since it was last"
73 				<< " granted access.";
74 		} else {
75 			details << "This application doesn't yet have the required"
76 				" privileges.";
77 		}
78 
79 		message->SetText(details);
80 		message->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
81 		rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
82 		message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
83 		message->MakeEditable(false);
84 		message->MakeSelectable(false);
85 		message->SetWordWrap(true);
86 
87 		message->SetExplicitMinSize(BSize(message->StringWidth(
88 				"01234567890123456789012345678901234567890123456789") + inset,
89 			B_SIZE_UNSET));
90 
91 		BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL);
92 		if (buttons == NULL)
93 			return;
94 
95 		fDisallowButton = new(std::nothrow) BButton("Disallow",
96 			new BMessage(kMessageDisallow));
97 		buttons->GroupLayout()->AddView(fDisallowButton);
98 
99 		buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
100 
101 		fOnceButton = new(std::nothrow) BButton("Allow Once",
102 			new BMessage(kMessageOnce));
103 		buttons->GroupLayout()->AddView(fOnceButton);
104 
105 		fAlwaysButton = new(std::nothrow) BButton("Allow Always",
106 			new BMessage(kMessageAlways));
107 		buttons->GroupLayout()->AddView(fAlwaysButton);
108 
109 		rootLayout->AddView(message);
110 		rootLayout->AddView(buttons);
111 	}
112 
113 	virtual void
114 	AttachedToWindow()
115 	{
116 		fDisallowButton->SetTarget(Window());
117 		fOnceButton->SetTarget(Window());
118 		fAlwaysButton->SetTarget(Window());
119 
120 		// TODO: Decide for a sane default button (or none at all).
121 		//fButton->MakeDefault(true);
122 	}
123 
124 private:
125 	BButton* fDisallowButton;
126 	BButton* fOnceButton;
127 	BButton* fAlwaysButton;
128 };
129 
130 
131 AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName,
132 	const char* signature, const char* path, const char* accessString,
133 	bool appIsNew, bool appWasUpdated)
134 	:
135 	BWindow(BRect(50, 50, 269, 302), "Application Keyring Access",
136 		B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS
137 			| B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
138 	fRequestView(NULL),
139 	fDoneSem(-1),
140 	fResult(kMessageDisallow)
141 {
142 	fDoneSem = create_sem(0, "application keyring access dialog");
143 	if (fDoneSem < 0)
144 		return;
145 
146 	BLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL);
147 	if (layout == NULL)
148 		return;
149 
150 	SetLayout(layout);
151 
152 	fRequestView = new(std::nothrow) AppAccessRequestView(keyringName,
153 		signature, path, accessString, appIsNew, appWasUpdated);
154 	if (fRequestView == NULL)
155 		return;
156 
157 	layout->AddView(fRequestView);
158 }
159 
160 
161 AppAccessRequestWindow::~AppAccessRequestWindow()
162 {
163 	if (fDoneSem >= 0)
164 		delete_sem(fDoneSem);
165 }
166 
167 
168 void
169 AppAccessRequestWindow::DispatchMessage(BMessage* message, BHandler* handler)
170 {
171 	int8 key;
172 	if (message->what == B_KEY_DOWN
173 		&& message->FindInt8("byte", 0, &key) == B_OK
174 		&& key == B_ESCAPE) {
175 		PostMessage(kMessageDisallow);
176 	}
177 
178 	BWindow::DispatchMessage(message, handler);
179 }
180 
181 
182 void
183 AppAccessRequestWindow::MessageReceived(BMessage* message)
184 {
185 	switch (message->what) {
186 		case kMessageDisallow:
187 		case kMessageOnce:
188 		case kMessageAlways:
189 			fResult = message->what;
190 			release_sem(fDoneSem);
191 			return;
192 	}
193 
194 	BWindow::MessageReceived(message);
195 }
196 
197 
198 status_t
199 AppAccessRequestWindow::RequestAppAccess(bool& allowAlways)
200 {
201 	CenterOnScreen();
202 	Show();
203 
204 	while (acquire_sem(fDoneSem) == B_INTERRUPTED)
205 		;
206 
207 	status_t result;
208 	switch (fResult) {
209 		default:
210 		case kMessageDisallow:
211 			result = B_NOT_ALLOWED;
212 			allowAlways = false;
213 			break;
214 		case kMessageOnce:
215 			result = B_OK;
216 			allowAlways = false;
217 			break;
218 		case kMessageAlways:
219 			result = B_OK;
220 			allowAlways = true;
221 			break;
222 	}
223 
224 	LockLooper();
225 	Quit();
226 	return result;
227 }
228