1

I'm implementing a minimal browser in PyObjC for my study. First, I googled about the way to use webkit from pyobjc and wrote code like below:

#coding: utf-8

import Foundation
import WebKit
import AppKit
import objc

def main():
    app = AppKit.NSApplication.sharedApplication()
    rect = Foundation.NSMakeRect(100,350,600,800)
    win = AppKit.NSWindow.alloc()
    win.initWithContentRect_styleMask_backing_defer_(
        rect,
        AppKit.NSTitledWindowMask |
            AppKit.NSClosableWindowMask |
            AppKit.NSResizableWindowMask |
            AppKit.NSMiniaturizableWindowMask,
        AppKit.NSBackingStoreBuffered,
        False)
    win.display()
    win.orderFrontRegardless()

    webview = WebKit.WebView.alloc()
    webview.initWithFrame_(rect)

    pageurl = Foundation.NSURL.URLWithString_("http://twitter.com")
    req = Foundation.NSURLRequest.requestWithURL_(pageurl)
    webview.mainFrame().loadRequest_(req)

    win.setContentView_(webview)
    app.run()

if __name__ == '__main__':
    main()

It worked fine. But I noticed that this browser is sharing cookies with safari. I want it to be independent from my Safari.app. So I googled again and I learned that I can override cookie-handling-methods by using NSMutableURLRequest. Below is the second code I tested:

#coding: utf-8

import Foundation
import WebKit
import AppKit
import objc

def main():
    app = AppKit.NSApplication.sharedApplication()
    rect = Foundation.NSMakeRect(100,350,600,800)
    win = AppKit.NSWindow.alloc()
    win.initWithContentRect_styleMask_backing_defer_(
        rect,
        AppKit.NSTitledWindowMask |
            AppKit.NSClosableWindowMask |
            AppKit.NSResizableWindowMask |
            AppKit.NSMiniaturizableWindowMask,
        AppKit.NSBackingStoreBuffered,
        False)
    win.display()
    win.orderFrontRegardless()

    webview = WebKit.WebView.alloc()
    webview.initWithFrame_(rect)

    pageurl = Foundation.NSURL.URLWithString_("http://twitter.com")
    req = Foundation.NSMutableURLRequest.requestWithURL_(pageurl)
    Foundation.NSMutableURLRequest.setHTTPShouldHandleCookies_(req, False)
    webview.mainFrame().loadRequest_(req)

    win.setContentView_(webview)
    app.run()

if __name__ == '__main__':
    main()

This code show me a login screen of twitter :-) But I couldn't login to twitter by this browser. I input account name, password and pushed enter key. Then the browser displays the timeline of the account which I always use in Safari.app.

Yes, I know that it's proper result. I didn't write anything about handling cookies. And my question is on this point. I want to know that:

  1. How can I implement and use something like NSHTTPCookieStorage?
  2. Can I write it in python?

Thank you.

user2100702
  • 267
  • 2
  • 8

1 Answers1

0

To start with the easy part: if it is possible to do this in Objective-C it should also be possible with PyObjC.

That said, it is unclear to me if this is possible at all. How can I have multiple instances of webkit without sharing cookies? seems to indicate that it isn't although you might be able to do something through the webkit delegate.

An other alternative is to use NSURLProtocol, register a custom NSURLProtocol class for handling http/https requests and implement that using Python's urllib or urllib2. The PyDocURL example shows how to do this (that example registers a subclass for pydoc:// URLs).

More information on NSURLConnection is on Apple's website.

Updated with an implemention hint:

An alternate method might be to disable cookie storaga by NSHTTPCookieStorage (NSHTTPCookieStorage.sharedHTTPCookieStorage.setCookieAcceptPolicy_(NSHTTPCookieAcceptPolicyNever)). Then use the webkit resource loading delegate to handle cookies yourself:

  • Maintain your own cookie store (possibly using a class in urllib2)

  • In webView:resource:willSendRequest:redirectResponse:fromDataSource: add cookie headers based on information in that store

  • In webView:resource:didReceiveResponse:fromDataSource: check for "set-cookie" headers and update your own cookie store.

It shouldn't be too hard to do this, and I'd love to have this functionality as an example on the PyObjC website (or even as a utility class in the WebKit bindings for PyObjC).

Community
  • 1
  • 1
Ronald Oussoren
  • 2,715
  • 20
  • 29
  • First, thank you for your answer. I know that there are some browsers implemented in Obj-C/Cocoa and they have own cookies. And yesterday, I found a blog article in which he explained how-to implement cookie management which departed from Safari.app. But I con't find how to do it in pyobjc. I must study more about basis of Cocoa and PyObjC. – user2100702 Feb 25 '13 at 08:59
  • Could you post a reference to that blog article, I might be able to help (I'm the author of PyObjC btw.) – Ronald Oussoren Feb 25 '13 at 14:19
  • [This article](http://d.hatena.ne.jp/RNatori/20081203) is explaining about handling cookie. It says that `- (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource ;` and `- (void)webView:(WebView *)sender resource:(id)identifier didReceiveResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource ;` is the key. – user2100702 Feb 25 '13 at 18:19
  • I cannot read that article, but it is likely a red herring. It likely says the same as the StackOverlow question I linked to earlier: you might be able to do this through the methods you mention but that will be a lot of work. – Ronald Oussoren Feb 26 '13 at 08:08
  • I agree with you. It may too hard for my skill. I'll make it as a long term homework. Thanks a lot! – user2100702 Feb 26 '13 at 19:02