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 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 121 AppAccessRequestWindow::~AppAccessRequestWindow() 122 { 123 if (fDoneSem >= 0) 124 delete_sem(fDoneSem); 125 } 126 127 128 bool 129 AppAccessRequestWindow::QuitRequested() 130 { 131 fResult = kMessageDisallow; 132 release_sem(fDoneSem); 133 return false; 134 } 135 136 137 void 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 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 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