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