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