0

Assume I have a Mac OS X application which links to WebKit and uses a WebView to display web content.

If the JavaScript in this webview calls the window.history.pushState() method, how do I detect this in Objective-C?

Ideally, I'm looking for something like an ObjC delegate callback which informs my application: "pushState() was called with these parameters: XXX".


Note: I am really looking for a solution in ObjC. Assume it is not acceptable for me to muck around with the JS on the page and replace/swizzle the pushState() method in JS.

Todd Ditchendorf
  • 11,217
  • 14
  • 69
  • 123
  • 1
    Just so I understand, is it acceptable to muck around with the pushState method from *ObjC*? You can use the WebView API to provide your own custom pushState from ObjC in that case. – Francisco Ryan Tolmasky I Jul 23 '12 at 19:45
  • I'll say that's not acceptable. Since this is a method of `window.history`, that would mean I would have to significantly alter WebKit internals. My app only links to WebKit. Bundling a custom version of WebKit for this feature alone is not acceptable in this case. – Todd Ditchendorf Jul 23 '12 at 19:48
  • Alternatively, I suppose I could provide a replacement implementation of `window.history` without bundling a custom WebKit in my app. But again, let's assume that's unacceptable, as that strikes me as a bad idea/not worth the effort for this feature. – Todd Ditchendorf Jul 23 '12 at 19:49
  • 1
    I think you can grab the history webScriptObject in ObjC and just change pushState alone using something like [historyObject setValue:customCallable forKey:@"pushState"]. – Francisco Ryan Tolmasky I Jul 23 '12 at 19:58
  • 1
    However I agree there's probably a way to do it without all that at all -- I would just look at the pushState implementation and see what that is calling internally. I would suspect it does a URL request or something. Specifically webView:decidePolicyForNavigationAction:request:frame:decisionListener: may be called – Francisco Ryan Tolmasky I Jul 23 '12 at 19:59
  • I see. Good point. I was hoping there was some API for this that I just couldn't find, but I see your idea may be the best way. – Todd Ditchendorf Jul 23 '12 at 20:01
  • and Calling Objective-C Methods From JavaScript ? here :https://developer.apple.com/library/mac/#documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html – divol Jul 23 '12 at 20:05
  • @divol As stated, any solution involving mucking with the JavaScript directly is not acceptable. – Todd Ditchendorf Jul 23 '12 at 20:08
  • so it's Schrödinger's cat !!! :D – divol Jul 23 '12 at 20:13
  • what about SafariBeforeNavigateEvent SafariNavigateEvent ? okay it's for extensions .... – divol Jul 23 '12 at 20:28
  • window.onpopstate is interesting, but not for objective-c ... MortBleue ! http://stackoverflow.com/questions/5129386/how-to-dected-when-history-pushstate-and-history-replacestate-are-used and http://code.google.com/p/html5-history/ – divol Jul 23 '12 at 20:47

1 Answers1

2

I found these private APIs in the WebKit source tree. This is exactly what I'm looking for, except that they are private, which may present problems for my particular use case.

@interface NSObject (WebFrameLoadDelegatePrivate)
...
- (void)webView:(WebView *)wv didPushStateWithinPageForFrame:(WebFrame *)frame ;
- (void)webView:(WebView *)wv didReplaceStateWithinPageForFrame:(WebFrame *)frame;
- (void)webView:(WebView *)wv didPopStateWithinPageForFrame:(WebFrame *)frame;
@end
Todd Ditchendorf
  • 11,217
  • 14
  • 69
  • 123
  • 1
    Generally, Apple seems to ignore the use of private APIs in WebKit, at least in my experience. Perhaps because the source is open? – Rob Keniger Jul 23 '12 at 22:09