BBGMultiAccountManager
|
00001 /* Copyright (c) 2011 Google Inc. 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 // GTMOAuth2WindowController 00017 // 00018 // This window controller for Mac handles sign-in via OAuth2 to Google or 00019 // other services. 00020 // 00021 // This controller is not reusable; create a new instance of this controller 00022 // every time the user will sign in. 00023 // 00024 // Sample usage for signing in to a Google service: 00025 // 00026 // static NSString *const kKeychainItemName = @”My App: Google Plus”; 00027 // NSString *scope = @"https://www.googleapis.com/auth/plus.me"; 00028 // 00029 // 00030 // GTMOAuth2WindowController *windowController; 00031 // windowController = [[[GTMOAuth2WindowController alloc] initWithScope:scope 00032 // clientID:clientID 00033 // clientSecret:clientSecret 00034 // keychainItemName:kKeychainItemName 00035 // resourceBundle:nil] autorelease]; 00036 // 00037 // [windowController signInSheetModalForWindow:mMainWindow 00038 // delegate:self 00039 // finishedSelector:@selector(windowController:finishedWithAuth:error:)]; 00040 // 00041 // The finished selector should have a signature matching this: 00042 // 00043 // - (void)windowController:(GTMOAuth2WindowController *)windowController 00044 // finishedWithAuth:(GTMOAuth2Authentication *)auth 00045 // error:(NSError *)error { 00046 // if (error != nil) { 00047 // // sign in failed 00048 // } else { 00049 // // sign in succeeded 00050 // // 00051 // // with the GTL library, pass the authentication to the service object, 00052 // // like 00053 // // [[self contactService] setAuthorizer:auth]; 00054 // // 00055 // // or use it to sign a request directly, like 00056 // // BOOL isAuthorizing = [self authorizeRequest:request 00057 // // delegate:self 00058 // // didFinishSelector:@selector(auth:finishedWithError:)]; 00059 // } 00060 // } 00061 // 00062 // To sign in to services other than Google, use the longer init method, 00063 // as shown in the sample application 00064 // 00065 // If the network connection is lost for more than 30 seconds while the sign-in 00066 // html is displayed, the notification kGTLOAuthNetworkLost will be sent. 00067 00068 #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES 00069 00070 #include <Foundation/Foundation.h> 00071 00072 #if !TARGET_OS_IPHONE 00073 00074 #import <Cocoa/Cocoa.h> 00075 #import <WebKit/WebKit.h> 00076 00077 // GTMHTTPFetcher.h brings in GTLDefines/GDataDefines 00078 #import "GTMHTTPFetcher.h" 00079 00080 #import "GTMOAuth2SignIn.h" 00081 #import "GTMOAuth2Authentication.h" 00082 #import "GTMHTTPFetchHistory.h" // for GTMCookieStorage 00083 00084 @class GTMOAuth2SignIn; 00085 00086 @interface GTMOAuth2WindowController : NSWindowController { 00087 @private 00088 // IBOutlets 00089 NSButton *keychainCheckbox_; 00090 WebView *webView_; 00091 NSButton *webCloseButton_; 00092 NSButton *webBackButton_; 00093 00094 // the object responsible for the sign-in networking sequence; it holds 00095 // onto the authentication object as well 00096 GTMOAuth2SignIn *signIn_; 00097 00098 // the page request to load when awakeFromNib occurs 00099 NSURLRequest *initialRequest_; 00100 00101 // local storage for WebKit cookies so they're not shared with Safari 00102 GTMCookieStorage *cookieStorage_; 00103 00104 // the user we're calling back 00105 // 00106 // the delegate is retained only until the callback is invoked 00107 // or the sign-in is canceled 00108 id delegate_; 00109 SEL finishedSelector_; 00110 00111 #if NS_BLOCKS_AVAILABLE 00112 void (^completionBlock_)(GTMOAuth2Authentication *, NSError *); 00113 #elif !__LP64__ 00114 // placeholders: for 32-bit builds, keep the size of the object's ivar section 00115 // the same with and without blocks 00116 #ifndef __clang_analyzer__ 00117 id completionPlaceholder_; 00118 #endif 00119 #endif 00120 00121 // flag allowing application to quit during display of sign-in sheet on 10.6 00122 // and later 00123 BOOL shouldAllowApplicationTermination_; 00124 00125 // delegate method for handling URLs to be opened in external windows 00126 SEL externalRequestSelector_; 00127 00128 BOOL isWindowShown_; 00129 00130 // paranoid flag to ensure we only close once during the sign-in sequence 00131 BOOL hasDoneFinalRedirect_; 00132 00133 // paranoid flag to ensure we only call the user back once 00134 BOOL hasCalledFinished_; 00135 00136 // if non-nil, we display as a sheet on the specified window 00137 NSWindow *sheetModalForWindow_; 00138 00139 // if non-empty, the name of the application and service used for the 00140 // keychain item 00141 NSString *keychainItemName_; 00142 00143 // if non-nil, the html string to be displayed immediately upon opening 00144 // of the web view 00145 NSString *initialHTMLString_; 00146 00147 // if true, we allow default WebView handling of cookies, so the 00148 // same user remains signed in each time the dialog is displayed 00149 BOOL shouldPersistUser_; 00150 00151 // user-defined data 00152 id userData_; 00153 NSMutableDictionary *properties_; 00154 } 00155 00156 // User interface elements 00157 @property (nonatomic, assign) IBOutlet NSButton *keychainCheckbox; 00158 @property (nonatomic, assign) IBOutlet WebView *webView; 00159 @property (nonatomic, assign) IBOutlet NSButton *webCloseButton; 00160 @property (nonatomic, assign) IBOutlet NSButton *webBackButton; 00161 00162 // The application and service name to use for saving the auth tokens 00163 // to the keychain 00164 @property (nonatomic, copy) NSString *keychainItemName; 00165 00166 // If true, the sign-in will remember which user was last signed in 00167 // 00168 // Defaults to false, so showing the sign-in window will always ask for 00169 // the username and password, rather than skip to the grant authorization 00170 // page. During development, it may be convenient to set this to true 00171 // to speed up signing in. 00172 @property (nonatomic, assign) BOOL shouldPersistUser; 00173 00174 // Optional html string displayed immediately upon opening the web view 00175 // 00176 // This string is visible just until the sign-in web page loads, and 00177 // may be used for a "Loading..." type of message 00178 @property (nonatomic, copy) NSString *initialHTMLString; 00179 00180 // The default timeout for an unreachable network during display of the 00181 // sign-in page is 30 seconds, after which the notification 00182 // kGTLOAuthNetworkLost is sent; set this to 0 to have no timeout 00183 @property (nonatomic, assign) NSTimeInterval networkLossTimeoutInterval; 00184 00185 // On 10.6 and later, the sheet can allow application termination by calling 00186 // NSWindow's setPreventsApplicationTerminationWhenModal: 00187 @property (nonatomic, assign) BOOL shouldAllowApplicationTermination; 00188 00189 // Selector for a delegate method to handle requests sent to an external 00190 // browser. 00191 // 00192 // Selector should have a signature matching 00193 // - (void)windowController:(GTMOAuth2WindowController *)controller 00194 // opensRequest:(NSURLRequest *)request; 00195 // 00196 // The controller's default behavior is to use NSWorkspace's openURL: 00197 @property (nonatomic, assign) SEL externalRequestSelector; 00198 00199 // The underlying object to hold authentication tokens and authorize http 00200 // requests 00201 @property (nonatomic, retain, readonly) GTMOAuth2Authentication *authentication; 00202 00203 // The underlying object which performs the sign-in networking sequence 00204 @property (nonatomic, retain, readonly) GTMOAuth2SignIn *signIn; 00205 00206 // Any arbitrary data object the user would like the controller to retain 00207 @property (nonatomic, retain) id userData; 00208 00209 // Stored property values are retained for the convenience of the caller 00210 - (void)setProperty:(id)obj forKey:(NSString *)key; 00211 - (id)propertyForKey:(NSString *)key; 00212 00213 @property (nonatomic, retain) NSDictionary *properties; 00214 00215 - (IBAction)closeWindow:(id)sender; 00216 00217 // Create a controller for authenticating to Google services 00218 // 00219 // scope is the requested scope of authorization 00220 // (like "http://www.google.com/m8/feeds") 00221 // 00222 // keychainItemName is used for storing the token on the keychain, 00223 // and is required for the "remember for later" checkbox to be shown; 00224 // keychainItemName should be like "My Application: Google Contacts" 00225 // (or set to nil if no persistent keychain storage is desired) 00226 // 00227 // resourceBundle may be nil if the window is in the main bundle's nib 00228 #if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT 00229 + (id)controllerWithScope:(NSString *)scope 00230 clientID:(NSString *)clientID 00231 clientSecret:(NSString *)clientSecret 00232 keychainItemName:(NSString *)keychainItemName // may be nil 00233 resourceBundle:(NSBundle *)bundle; // may be nil 00234 00235 - (id)initWithScope:(NSString *)scope 00236 clientID:(NSString *)clientID 00237 clientSecret:(NSString *)clientSecret 00238 keychainItemName:(NSString *)keychainItemName 00239 resourceBundle:(NSBundle *)bundle; 00240 #endif 00241 00242 // Create a controller for authenticating to non-Google services, taking 00243 // explicit endpoint URLs and an authentication object 00244 + (id)controllerWithAuthentication:(GTMOAuth2Authentication *)auth 00245 authorizationURL:(NSURL *)authorizationURL 00246 keychainItemName:(NSString *)keychainItemName // may be nil 00247 resourceBundle:(NSBundle *)bundle; // may be nil 00248 00249 // This is the designated initializer 00250 - (id)initWithAuthentication:(GTMOAuth2Authentication *)auth 00251 authorizationURL:(NSURL *)authorizationURL 00252 keychainItemName:(NSString *)keychainItemName 00253 resourceBundle:(NSBundle *)bundle; 00254 00255 // Entry point to begin displaying the sign-in window 00256 // 00257 // the finished selector should have a signature matching 00258 // - (void)windowController:(GTMOAuth2WindowController *)windowController 00259 // finishedWithAuth:(GTMOAuth2Authentication *)auth 00260 // error:(NSError *)error { 00261 // 00262 // Once the finished method has been invoked with no error, the auth object 00263 // may be used to authorize requests (refreshing the access token, if necessary, 00264 // and adding the auth header) like: 00265 // 00266 // [authorizer authorizeRequest:myNSMutableURLRequest] 00267 // delegate:self 00268 // didFinishSelector:@selector(auth:finishedWithError:)]; 00269 // 00270 // or can be stored in a GTL service object like 00271 // GTLServiceGoogleContact *service = [self contactService]; 00272 // [service setAuthorizer:auth]; 00273 // 00274 // The delegate is retained only until the finished selector is invoked or 00275 // the sign-in is canceled 00276 - (void)signInSheetModalForWindow:(NSWindow *)parentWindowOrNil 00277 delegate:(id)delegate 00278 finishedSelector:(SEL)finishedSelector; 00279 00280 #if NS_BLOCKS_AVAILABLE 00281 - (void)signInSheetModalForWindow:(NSWindow *)parentWindowOrNil 00282 completionHandler:(void (^)(GTMOAuth2Authentication *auth, NSError *error))handler; 00283 #endif 00284 00285 - (void)cancelSigningIn; 00286 00287 // Subclasses may override authNibName to specify a custom name 00288 + (NSString *)authNibName; 00289 00290 // apps may replace the sign-in class with their own subclass of it 00291 + (Class)signInClass; 00292 + (void)setSignInClass:(Class)theClass; 00293 00294 // Revocation of an authorized token from Google 00295 #if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT 00296 + (void)revokeTokenForGoogleAuthentication:(GTMOAuth2Authentication *)auth; 00297 #endif 00298 00299 // Keychain 00300 // 00301 // The keychain checkbox is shown if the keychain application service 00302 // name (typically set in the initWithScope: method) is non-empty 00303 // 00304 00305 // Create an authentication object for Google services from the access 00306 // token and secret stored in the keychain; if no token is available, return 00307 // an unauthorized auth object 00308 #if !GTM_OAUTH2_SKIP_GOOGLE_SUPPORT 00309 + (GTMOAuth2Authentication *)authForGoogleFromKeychainForName:(NSString *)keychainItemName 00310 clientID:(NSString *)clientID 00311 clientSecret:(NSString *)clientSecret; 00312 #endif 00313 00314 // Add tokens from the keychain, if available, to the authentication object 00315 // 00316 // returns YES if the authentication object was authorized from the keychain 00317 + (BOOL)authorizeFromKeychainForName:(NSString *)keychainItemName 00318 authentication:(GTMOAuth2Authentication *)auth; 00319 00320 // Method for deleting the stored access token and secret, useful for "signing 00321 // out" 00322 + (BOOL)removeAuthFromKeychainForName:(NSString *)keychainItemName; 00323 00324 // Method for saving the stored access token and secret; typically, this method 00325 // is used only by the window controller 00326 + (BOOL)saveAuthToKeychainForName:(NSString *)keychainItemName 00327 authentication:(GTMOAuth2Authentication *)auth; 00328 @end 00329 00330 #endif // #if !TARGET_OS_IPHONE 00331 00332 #endif // #if GTM_INCLUDE_OAUTH2 || !GDATA_REQUIRE_SERVICE_INCLUDES