0

I'm trying to figure out if it's possible to track when Safari is done loading a page request. I call Safari to open using this code:

// Open Safari
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.example.com/" description]]];

But, since my app goes to the background, it may be suspended (and not able to execute code). Is this even possible to do within Xcode 4?

EDIT

The reason why I am doing this is because the UIWebView and Safari are not running at the same level and I want to do some performance related testing on some websites.

Community
  • 1
  • 1
justderb
  • 2,835
  • 1
  • 25
  • 38

3 Answers3

2

So, if you'd like to see how I did it for jailbroken iOS (instead of the quite boring "Not possible"): I basically hooked safari to get access to the particular method that is called when the page has finished loaing. Using MobileSubstrate (filter for com.apple.mobilesafari when injecting your dynamic library):

#import <substrate.h>
#import <UIKit/UIKit.h>

/* Some globals */
static IMP _orig_1, _orig_2;
static id tabController;

id _mod_1(id __self, SEL __cmd, CGRect frame, id tabDocument);
void _mod_2(id __self, SEL __cmd, id doc, BOOL error);


/* The library constructor */
__attribute__((constructor))
static void init()
{
    Class tabClass;

    tabClass = objc_getClass("TabController");

    MSHookMessageEx(tabClass, @selector(initWithFrame:tabDocument:),    
        (IMP)_mod_1, &_orig_1);
    MSHookMessageEx(tabClass, @selector(tabDocument:didFinishLoadingWithError:),
        (IMP)_mod_2, &_orig_2);
}


/* This hook merely captures the TabController of Safari. */
id _mod_1(id __self, SEL __cmd, CGRect frame, id tabDocument)
{
    __self = _orig_1(__self, __cmd, frame, tabDocument);
    tabController = __self;
    return __self;
}

/* This is called when the page loading is done */
void _mod_2(id __self, SEL __cmd, id doc, BOOL error)
{
    /* Make sure you always call the original method */
    _orig_2(__self, __cmd, doc, error);

    /* then do what you want */
}
1

This is not possible in general.

One thing you could do is from the page to be loaded, do a redirect to your application's URL scheme, which will launch your app. For more information on this matter, look at the -[UIApplicationDelegate application:openURL:sourceApplication:annotation:] method.

I don't think your application can reject the activation through such an URL scheme, so this means that your application will become active. Maybe the return value of the above method (which is a boolean) can be used, you'll have to test that.

This method also assumes that you have access to the page you're opening, so that you can add the redirect.

Joost
  • 10,333
  • 4
  • 55
  • 61
  • I'm testing pages that are not exactly mine... is there anyway to insert Javascript into the Safari webpage to do a re-direct back to my app when it is done loading? – justderb May 25 '12 at 19:24
  • I guess there isn't, because then you are essentially doing an XSS attack. – Joost May 25 '12 at 19:30
  • This makes sense from a security stand-point.... I'm probably thinking there isn't a way either because of this. – justderb May 25 '12 at 19:32
  • So sadly, you'll then have to wait for Apple to update `UIWebView` to the fast Javascript engine used in Mobile Safari. Maybe iOS6? Just two weeks until WWDC! – Joost May 25 '12 at 19:45
0

No, this is not possible. You can do this if you open the link in a UIWebView within your own application, however.

Senior
  • 2,259
  • 1
  • 20
  • 31