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 "KeyRequestWindow.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 <Key.h> 17 #include <MenuField.h> 18 #include <MenuItem.h> 19 #include <NetworkDevice.h> 20 #include <PopUpMenu.h> 21 #include <SpaceLayoutItem.h> 22 #include <StringView.h> 23 #include <TextControl.h> 24 #include <TextView.h> 25 #include <View.h> 26 27 #include <new> 28 29 30 #undef B_TRANSLATION_CONTEXT 31 #define B_TRANSLATION_CONTEXT "KeyRequestWindow" 32 33 34 static const uint32 kMessageCancel = 'btcl'; 35 static const uint32 kMessageUnlock = 'btul'; 36 37 38 class KeyRequestView : public BView { 39 public: 40 KeyRequestView() 41 : 42 BView("KeyRequestView", B_WILL_DRAW), 43 fPassword(NULL) 44 { 45 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 46 47 BGroupLayout* rootLayout = new(std::nothrow) BGroupLayout(B_VERTICAL); 48 if (rootLayout == NULL) 49 return; 50 51 SetLayout(rootLayout); 52 53 BGridView* controls = new(std::nothrow) BGridView(); 54 if (controls == NULL) 55 return; 56 57 BGridLayout* layout = controls->GridLayout(); 58 59 float inset = ceilf(be_plain_font->Size() * 0.7); 60 rootLayout->SetInsets(inset, inset, inset, inset); 61 rootLayout->SetSpacing(inset); 62 layout->SetSpacing(inset, inset); 63 64 BStringView* label = new(std::nothrow) BStringView("keyringLabel", 65 B_TRANSLATE("Keyring:")); 66 if (label == NULL) 67 return; 68 69 int32 row = 0; 70 layout->AddView(label, 0, row); 71 72 fKeyringName = new(std::nothrow) BStringView("keyringName", ""); 73 if (fKeyringName == NULL) 74 return; 75 76 layout->AddView(fKeyringName, 1, row++); 77 78 fPassword = new(std::nothrow) BTextControl(B_TRANSLATE("Password:"), "", NULL); 79 if (fPassword == NULL) 80 return; 81 82 BLayoutItem* layoutItem = fPassword->CreateTextViewLayoutItem(); 83 layoutItem->SetExplicitMinSize(BSize(fPassword->StringWidth( 84 "0123456789012345678901234567890123456789") + inset, 85 B_SIZE_UNSET)); 86 87 layout->AddItem(fPassword->CreateLabelLayoutItem(), 0, row); 88 layout->AddItem(layoutItem, 1, row++); 89 90 BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL); 91 if (buttons == NULL) 92 return; 93 94 fCancelButton = new(std::nothrow) BButton(B_TRANSLATE("Cancel"), 95 new BMessage(kMessageCancel)); 96 buttons->GroupLayout()->AddView(fCancelButton); 97 98 buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); 99 100 fUnlockButton = new(std::nothrow) BButton(B_TRANSLATE("Unlock"), 101 new BMessage(kMessageUnlock)); 102 buttons->GroupLayout()->AddView(fUnlockButton); 103 104 BTextView* message = new(std::nothrow) BTextView("message"); 105 message->SetText(B_TRANSLATE("An application wants to access the " 106 "keyring below, but it is locked with a passphrase. Please enter " 107 "the passphrase to unlock the keyring.\n" 108 "If you unlock the keyring, it stays unlocked until the system is " 109 "shut down or the keyring is manually locked again.\n" 110 "If you cancel this dialog the keyring will remain locked.")); 111 message->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 112 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); 113 message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor); 114 message->MakeEditable(false); 115 message->MakeSelectable(false); 116 message->SetWordWrap(true); 117 118 rootLayout->AddView(message); 119 rootLayout->AddView(controls); 120 rootLayout->AddView(buttons); 121 } 122 123 virtual void 124 AttachedToWindow() 125 { 126 fCancelButton->SetTarget(Window()); 127 fUnlockButton->SetTarget(Window()); 128 fUnlockButton->MakeDefault(true); 129 fPassword->MakeFocus(); 130 } 131 132 void 133 SetUp(const BString& keyringName) 134 { 135 fKeyringName->SetText(keyringName); 136 } 137 138 status_t 139 Complete(BMessage& keyMessage) 140 { 141 BPasswordKey password(fPassword->Text(), B_KEY_PURPOSE_KEYRING, ""); 142 return password.Flatten(keyMessage); 143 } 144 145 private: 146 BStringView* fKeyringName; 147 BTextControl* fPassword; 148 BButton* fCancelButton; 149 BButton* fUnlockButton; 150 }; 151 152 153 KeyRequestWindow::KeyRequestWindow() 154 : 155 BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Unlock keyring"), 156 B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS 157 | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS 158 | B_CLOSE_ON_ESCAPE), 159 fRequestView(NULL), 160 fDoneSem(-1), 161 fResult(B_ERROR) 162 { 163 fDoneSem = create_sem(0, "keyring unlock dialog"); 164 if (fDoneSem < 0) 165 return; 166 167 BLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL); 168 if (layout == NULL) 169 return; 170 171 SetLayout(layout); 172 173 fRequestView = new(std::nothrow) KeyRequestView(); 174 if (fRequestView == NULL) 175 return; 176 177 layout->AddView(fRequestView); 178 } 179 180 181 KeyRequestWindow::~KeyRequestWindow() 182 { 183 if (fDoneSem >= 0) 184 delete_sem(fDoneSem); 185 } 186 187 188 bool 189 KeyRequestWindow::QuitRequested() 190 { 191 fResult = B_CANCELED; 192 release_sem(fDoneSem); 193 return false; 194 } 195 196 197 void 198 KeyRequestWindow::MessageReceived(BMessage* message) 199 { 200 switch (message->what) { 201 case kMessageCancel: 202 case kMessageUnlock: 203 fResult = message->what == kMessageUnlock ? B_OK : B_CANCELED; 204 release_sem(fDoneSem); 205 return; 206 } 207 208 BWindow::MessageReceived(message); 209 } 210 211 212 status_t 213 KeyRequestWindow::RequestKey(const BString& keyringName, BMessage& keyMessage) 214 { 215 fRequestView->SetUp(keyringName); 216 217 ResizeToPreferred(); 218 CenterOnScreen(); 219 Show(); 220 221 while (acquire_sem(fDoneSem) == B_INTERRUPTED) 222 ; 223 224 status_t result = fResult; 225 if (result == B_OK) 226 result = fRequestView->Complete(keyMessage); 227 228 LockLooper(); 229 Quit(); 230 return result; 231 } 232