You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cordova.apache.org by GitBox <gi...@apache.org> on 2021/07/01 16:10:20 UTC

[GitHub] [cordova-plugin-inappbrowser] emily-curry edited a comment on issue #753: Issue with Cookie

emily-curry edited a comment on issue #753:
URL: https://github.com/apache/cordova-plugin-inappbrowser/issues/753#issuecomment-872372518


   I have successfully worked around this issue by doing some method-swizzling with some of this plugin's internals. What is happening here is that on browser open, we sync the app's persistent NSHTTPCookieStorage with the new webview's WKHTTPCookieStore. On browser close, we do the reverse; read from the WKHTTPCookieStore and write to the persistent NSHTTPCookieStorage (modifying any properties that would cause the cookies to _not_ persist between app loads, because that is important to my use case).
   
   ```objc
   
   #import <Foundation/Foundation.h>
   #import <objc/runtime.h>
   #import "CDVWKInAppBrowser.h"
   
   /**
    * A category of CDVWKInAppBrowser that handles persisting cookies from the WKWebView on close, and reapplying them on load.
    */
   @interface CDVWKInAppBrowser (Cookies)
   - (void) cookies_open:(NSURL*)url withOptions:(NSString*)options;
   - (void) cookies_close;
   @end
   
   @implementation CDVWKInAppBrowser (Cookies)
   /**
    * Swizzles the implementations of openInInAppBrowser:withOptions: and browserExit with versions that syncronize WKWebView cookies with the app's NSHTTPCookieStorage.
    */
   + (void) load
   {
       static dispatch_once_t once_token;
       dispatch_once(&once_token,  ^{
           // ignore undeclared selector warnings, which are caused by overriding private methods of CDVWKInAppBrowser
   #pragma clang diagnostic push
   #pragma clang diagnostic ignored "-Wundeclared-selector"
           SEL openSelector = @selector(openInInAppBrowser:withOptions:);
           SEL cookiesOpenSelector = @selector(cookies_open:withOptions:);
           Method originalOpenMethod = class_getInstanceMethod(self, openSelector);
           Method extendedOpenMethod = class_getInstanceMethod(self, cookiesOpenSelector);
           method_exchangeImplementations(originalOpenMethod, extendedOpenMethod);
           
           SEL closeSelector = @selector(browserExit);
           SEL cookiesCloseSelector = @selector(cookies_close);
           Method originalCloseMethod = class_getInstanceMethod(self, closeSelector);
           Method extendedCloseMethod = class_getInstanceMethod(self, cookiesCloseSelector);
           method_exchangeImplementations(originalCloseMethod, extendedCloseMethod);
   #pragma clang diagnostic pop
       });
   }
   
   /**
    * Loads all cookies from the app's NSHTTPCookieStorage instance, and applies them to the WKHTTPCookieStore.
    * The overridden method is called after this happens, so if the webview was opened with the "clearsession" option, cookies will still be cleared.
    */
   - (void) cookies_open:(NSURL*)url withOptions:(NSString*)options
   {
       WKWebsiteDataStore* dataStore = [WKWebsiteDataStore defaultDataStore];
       WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore;
       NSHTTPCookieStorage* storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
       NSHTTPCookie* cookie;
       for (cookie in storage.cookies) {
           [cookieStore setCookie:cookie completionHandler:nil];
       }
       [self cookies_open:url withOptions:options];
   }
   
   /**
    * Loads all cookies from the WKHTTPCookieStore, sets the "Discard" flag to false, and persists them to the app's NSHTTPCookieStorage instance.
    */
   - (void) cookies_close
   {
       WKWebsiteDataStore* dataStore = [WKWebsiteDataStore defaultDataStore];
       WKHTTPCookieStore* cookieStore = dataStore.httpCookieStore;
       int secondsToKeep = 60*60*24*90;
       [cookieStore getAllCookies:^(NSArray* cookies) {
           NSHTTPCookie* cookie;
           for(cookie in cookies) {
               NSMutableDictionary* cookieDict = [cookie.properties mutableCopy];
               [cookieDict removeObjectForKey:NSHTTPCookieDiscard]; // Remove the discard flag. If it is set (even to false), the expires date will NOT be kept.
               if (![cookieDict objectForKey:NSHTTPCookieExpires]) { // If the cookie doesn't have an expiration date, set it to the maximum value. Otherwise, keep the existing value.
                   [cookieDict setObject:[NSDate dateWithTimeIntervalSinceNow:secondsToKeep] forKey:NSHTTPCookieExpires]; // Expires in 90 days. Only applies to version 0 cookies (rare).
               }
               if (![cookieDict objectForKey:NSHTTPCookieMaximumAge]) { // If the cookie doesn't have a max age, set it to the maximum value. Otherwise, keep the existing value.
                   [cookieDict setObject:[NSString stringWithFormat:@"%d",secondsToKeep] forKey:NSHTTPCookieMaximumAge]; // Expires in 90 days. Only applies to version 1 cookies.
               }
               NSHTTPCookie* newCookie = [NSHTTPCookie cookieWithProperties:cookieDict];
               [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:newCookie];
               
           }
       }];
       [self cookies_close];
   }
   
   @end
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@cordova.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@cordova.apache.org
For additional commands, e-mail: issues-help@cordova.apache.org