diff options
author | Vincent Sanders <vince@netsurf-browser.org> | 2013-02-14 15:09:28 +0000 |
---|---|---|
committer | Vincent Sanders <vince@netsurf-browser.org> | 2013-02-18 11:23:27 +0000 |
commit | 3bfb5b96a7c7cb2718a60987e69cd659ed49b9d8 (patch) | |
tree | 40aa4e52aa50010c8f7c47dda79be2b77339e546 /desktop | |
parent | c545bb4b42dff8bfd4c288e330f52848ec2df6c4 (diff) | |
download | netsurf-3bfb5b96a7c7cb2718a60987e69cd659ed49b9d8.tar.gz netsurf-3bfb5b96a7c7cb2718a60987e69cd659ed49b9d8.tar.bz2 |
browser_window_navigate refactor
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/browser.c | 345 | ||||
-rw-r--r-- | desktop/browser.h | 71 | ||||
-rw-r--r-- | desktop/frames.c | 25 | ||||
-rw-r--r-- | desktop/history_core.c | 36 |
4 files changed, 249 insertions, 228 deletions
diff --git a/desktop/browser.c b/desktop/browser.c index f9353afef..c373e84e3 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -662,17 +662,20 @@ void browser_window_debug_dump(struct browser_window *bw, FILE *f) /** * Create and open a new root browser window with the given page. * - * \param url URL to start fetching in the new window (copied) + * \param url URL to start fetching in the new window + * \param referer The referring uri or NULL if none * \param clone The browser window to clone - * \param referer The referring uri (copied), or 0 if none * \param history_add add to history * \param new_tab create a new tab * \return new browser window or NULL on error */ -struct browser_window *browser_window_create(const char *url, - struct browser_window *clone, - const char *referer, bool history_add, bool new_tab) +struct browser_window * +browser_window_create(nsurl *url, + nsurl *referer, + struct browser_window *clone, + bool history_add, + bool new_tab) { struct browser_window *bw; struct browser_window *top; @@ -709,11 +712,15 @@ struct browser_window *browser_window_create(const char *url, return NULL; } - if (url) { - browser_window_go(bw, url, referer, history_add); + if (url != NULL) { + enum browser_window_nav_flags flags; + flags = BROWSER_WINDOW_GO_FLAG_VERIFIABLE; + if (history_add) { + flags |= BROWSER_WINDOW_GO_FLAG_HISTORY; + } + browser_window_navigate(bw, url, referer, flags, NULL, NULL, NULL); } - return bw; } @@ -755,92 +762,55 @@ void browser_window_initialise_common(struct browser_window *bw, bw->status_miss = 0; } - -/** - * Start fetching a page in a browser window. - * - * \param bw browser window - * \param url URL to start fetching (copied) - * \param referer the referring uri (copied), or 0 if none - * \param history_add Add to history - * - * Any existing fetches in the window are aborted. - */ - -void browser_window_go(struct browser_window *bw, const char *url, - const char *referer, bool history_add) -{ - /* All fetches passing through here are verifiable - * (i.e are the result of user action) */ - browser_window_go_post(bw, url, 0, 0, history_add, referer, - false, true, NULL); -} - - /** - * Start a download of the given URL from a browser window. - * - * \param bw browser window - * \param url URL to start downloading (copied) - * \param referer the referring uri (copied), or 0 if none + * implements the download operation of a window navigate */ - -void browser_window_download(struct browser_window *bw, const char *url, - const char *referer) +static nserror +browser_window_download(struct browser_window *bw, + nsurl *url, + nsurl *nsref, + uint32_t fetch_flags, + bool fetch_is_post, + llcache_post_data *post) { - browser_window_go_post(bw, url, 0, 0, false, referer, - true, true, NULL); -} + llcache_handle *l; + struct browser_window *root; + nserror error; + root = browser_window_get_root(bw); + assert(root != NULL); -/** - * Start fetching a page in a browser window. - * - * \param bw browser window - * \param url URL to start fetching (copied) - * \param referer the referring uri (copied), or 0 if none - * \param history_add add to history - * \param parent parent handle - * - * Any existing fetches in the window are aborted. - */ + fetch_flags |= LLCACHE_RETRIEVE_FORCE_FETCH; + fetch_flags |= LLCACHE_RETRIEVE_STREAM_DATA; + + error = llcache_handle_retrieve(url, fetch_flags, nsref, + fetch_is_post ? post : NULL, + NULL, NULL, &l); + if (error == NSERROR_NO_FETCH_HANDLER) { + /* no internal handler for this type, call out to frontend */ + gui_launch_url(nsurl_access(url)); + } else if (error != NSERROR_OK) { + LOG(("Failed to fetch download: %d", error)); + } else { + error = download_context_create(l, root->window); + if (error != NSERROR_OK) { + LOG(("Failed creating download context: %d", error)); + llcache_handle_abort(l); + llcache_handle_release(l); + } + } -void browser_window_go_unverifiable(struct browser_window *bw, - const char *url, const char *referer, bool history_add, - hlcache_handle *parent) -{ - /* All fetches passing through here are unverifiable - * (i.e are not the result of user action) */ - browser_window_go_post(bw, url, 0, 0, history_add, referer, - false, false, parent); + return error; } -/** - * Start fetching a page in a browser window, POSTing form data. - * - * \param bw browser window - * \param url URL to start fetching (copied) - * \param post_urlenc url encoded post data, or 0 if none - * \param post_multipart multipart post data, or 0 if none - * \param add_to_history add to window history - * \param referer the referring uri (copied), or 0 if none - * \param download download, rather than render the uri - * \param verifiable this transaction is verifiable - * \param parent Parent content, or NULL - * - * Any existing fetches in the window are aborted. - * - * If post_urlenc and post_multipart are 0 the url is fetched using GET. - * - * The page is not added to the window history if add_to_history is false. - * This should be used when returning to a page in the window history. - */ - -void browser_window_go_post(struct browser_window *bw, const char *url, - char *post_urlenc, - struct fetch_multipart_data *post_multipart, - bool add_to_history, const char *referer, bool download, - bool verifiable, hlcache_handle *parent) +/* exported interface documented in desktop/browser.h */ +nserror browser_window_navigate(struct browser_window *bw, + nsurl *url, + nsurl *referrer, + enum browser_window_nav_flags flags, + char *post_urlenc, + struct fetch_multipart_data *post_multipart, + hlcache_handle *parent) { hlcache_handle *c; int depth = 0; @@ -851,24 +821,23 @@ void browser_window_go_post(struct browser_window *bw, const char *url, hlcache_child_context child; nserror error; - nsurl *nsref = NULL; - nsurl *nsurl; - LOG(("bw %p, url %s", bw, url)); assert(bw); assert(url); /* don't allow massively nested framesets */ - for (cur = bw; cur->parent; cur = cur->parent) + for (cur = bw; cur->parent; cur = cur->parent) { depth++; + } if (depth > FRAME_DEPTH) { LOG(("frame depth too high.")); - return; + return NSERROR_FRAME_DEPTH; } /* Set up retrieval parameters */ - if (verifiable) + if ((flags & BROWSER_WINDOW_GO_FLAG_VERIFIABLE) != 0) { fetch_flags |= LLCACHE_RETRIEVE_VERIFIABLE; + } if (post_multipart != NULL) { post.type = LLCACHE_POST_MULTIPART; @@ -878,72 +847,46 @@ void browser_window_go_post(struct browser_window *bw, const char *url, post.data.urlenc = post_urlenc; } - if (parent != NULL && content_get_type(parent) == CONTENT_HTML) { + if ((parent != NULL) && (content_get_type(parent) == CONTENT_HTML)) { child.charset = html_get_encoding(parent); child.quirks = content_get_quirks(parent); } - error = nsurl_create(url, &nsurl); - if (error != NSERROR_OK) { - return; - } + url = nsurl_ref(url); - if (referer != NULL) { - error = nsurl_create(referer, &nsref); - if (error != NSERROR_OK) { - nsurl_unref(nsurl); - return; - } + if (referrer != NULL) { + referrer = nsurl_ref(referrer); } /* Get download out of the way */ - if (download) { - llcache_handle *l; - struct browser_window *root; - - root = browser_window_get_root(bw); - assert(root != NULL); - - fetch_flags |= LLCACHE_RETRIEVE_FORCE_FETCH; - fetch_flags |= LLCACHE_RETRIEVE_STREAM_DATA; - - error = llcache_handle_retrieve(nsurl, fetch_flags, nsref, - fetch_is_post ? &post : NULL, - NULL, NULL, &l); - if (error == NSERROR_NO_FETCH_HANDLER) { - gui_launch_url(nsurl_access(nsurl)); - } else if (error != NSERROR_OK) { - LOG(("Failed to fetch download: %d", error)); - } else { - error = download_context_create(l, root->window); - if (error != NSERROR_OK) { - LOG(("Failed creating download context: %d", - error)); - llcache_handle_abort(l); - llcache_handle_release(l); - } + if ((flags & BROWSER_WINDOW_GO_FLAG_DOWNLOAD) != 0) { + error = browser_window_download(bw, + url, + referrer, + fetch_flags, + fetch_is_post, + &post); + nsurl_unref(url); + if (referrer != NULL) { + nsurl_unref(referrer); } - - nsurl_unref(nsurl); - if (nsref != NULL) - nsurl_unref(nsref); - - return; + return error; } - if (bw->frag_id != NULL) + if (bw->frag_id != NULL) { lwc_string_unref(bw->frag_id); + } bw->frag_id = NULL; - if (nsurl_has_component(nsurl, NSURL_FRAGMENT)) { + if (nsurl_has_component(url, NSURL_FRAGMENT)) { bool same_url = false; - bw->frag_id = nsurl_get_component(nsurl, NSURL_FRAGMENT); + bw->frag_id = nsurl_get_component(url, NSURL_FRAGMENT); /* Compare new URL with existing one (ignoring fragments) */ - if (bw->current_content != NULL && - hlcache_handle_get_url(bw->current_content) != NULL) { - same_url = nsurl_compare(nsurl, + if ((bw->current_content != NULL) && + (hlcache_handle_get_url(bw->current_content) != NULL)) { + same_url = nsurl_compare(url, hlcache_handle_get_url(bw->current_content), NSURL_COMPLETE); } @@ -951,23 +894,30 @@ void browser_window_go_post(struct browser_window *bw, const char *url, /* if we're simply moving to another ID on the same page, * don't bother to fetch, just update the window. */ - if (same_url && fetch_is_post == false && - nsurl_has_component(nsurl, NSURL_QUERY) == - false) { - nsurl_unref(nsurl); - if (nsref != NULL) - nsurl_unref(nsref); - if (add_to_history) - history_add(bw->history, bw->current_content, - bw->frag_id == NULL ? NULL : - lwc_string_data(bw->frag_id)); + if ((same_url) && + (fetch_is_post == false) && + (nsurl_has_component(url, NSURL_QUERY) == false)) { + nsurl_unref(url); + + if (referrer != NULL) { + nsurl_unref(referrer); + } + + if ((flags & BROWSER_WINDOW_GO_FLAG_HISTORY) != 0) { + history_add(bw->history, + bw->current_content, + bw->frag_id == NULL ? NULL : + lwc_string_data(bw->frag_id)); + } + browser_window_update(bw, false); + if (bw->current_content != NULL) { browser_window_refresh_url_bar(bw, hlcache_handle_get_url(bw->current_content), bw->frag_id); } - return; + return NSERROR_OK; } } @@ -975,53 +925,55 @@ void browser_window_go_post(struct browser_window *bw, const char *url, browser_window_remove_caret(bw); browser_window_destroy_children(bw); - LOG(("Loading '%s'", nsurl_access(nsurl))); + LOG(("Loading '%s'", nsurl_access(url))); browser_window_set_status(bw, messages_get("Loading")); - bw->history_add = add_to_history; + if ((flags & BROWSER_WINDOW_GO_FLAG_HISTORY) != 0) { + bw->history_add = true; + } /* Verifiable fetches may trigger a download */ - if (verifiable) + if ((flags & BROWSER_WINDOW_GO_FLAG_VERIFIABLE) != 0) { fetch_flags |= HLCACHE_RETRIEVE_MAY_DOWNLOAD; + } - error = hlcache_handle_retrieve(nsurl, + error = hlcache_handle_retrieve(url, fetch_flags | HLCACHE_RETRIEVE_SNIFF_TYPE, - nsref, + referrer, fetch_is_post ? &post : NULL, browser_window_callback, bw, parent != NULL ? &child : NULL, CONTENT_ANY, &c); switch (error) { - case NSERROR_NO_FETCH_HANDLER: /* no handler for this type */ - gui_launch_url(nsurl_access(nsurl)); - nsurl_unref(nsurl); - if (nsref != NULL) - nsurl_unref(nsref); - break; - case NSERROR_OK: bw->loading_content = c; browser_window_start_throbber(bw); - browser_window_refresh_url_bar(bw, nsurl, NULL); + browser_window_refresh_url_bar(bw, url, NULL); + break; - nsurl_unref(nsurl); - if (nsref != NULL) - nsurl_unref(nsref); + case NSERROR_NO_FETCH_HANDLER: /* no handler for this type */ + /** @todo does this always try and download even unverifiable content? */ + gui_launch_url(nsurl_access(url)); break; - default: /* assume out of memory */ - /* TODO: fix all fetcher errors being reported as OOM? */ - nsurl_unref(nsurl); - if (nsref != NULL) - nsurl_unref(nsref); - browser_window_set_status(bw, messages_get("NoMemory")); - warn_user("NoMemory", 0); + default: /* report error to user */ + browser_window_set_status(bw, messages_get_errorcode(error)); + /** @todo should the caller report the error? */ + warn_user(messages_get_errorcode(error), 0); + break; } + nsurl_unref(url); + if (referrer != NULL) { + nsurl_unref(referrer); + } + /* Record time */ bw->last_action = wallclock(); + + return error; } @@ -1658,9 +1610,10 @@ void browser_window_convert_to_download(struct browser_window *bw, void browser_window_refresh(void *p) { struct browser_window *bw = p; - bool history_add = true; - const char *url; - const char *refresh; + nsurl *url; + nsurl *refresh; + hlcache_handle *parent = NULL; + enum browser_window_nav_flags flags = BROWSER_WINDOW_GO_FLAG_NONE; assert(bw->current_content != NULL && (content_get_status(bw->current_content) == @@ -1670,16 +1623,17 @@ void browser_window_refresh(void *p) /* Ignore if the refresh URL has gone * (may happen if a fetch error occurred) */ - refresh = nsurl_access(content_get_refresh_url(bw->current_content)); + refresh = content_get_refresh_url(bw->current_content); if (refresh == NULL) return; /* mark this content as invalid so it gets flushed from the cache */ content_invalidate_reuse_data(bw->current_content); - url = nsurl_access(hlcache_handle_get_url(bw->current_content)); - if (url != NULL && strcmp(url, refresh) == 0) - history_add = false; + url = hlcache_handle_get_url(bw->current_content); + if ((url == NULL) || (nsurl_compare(url, refresh, NSURL_COMPLETE))) { + flags |= BROWSER_WINDOW_GO_FLAG_HISTORY; + } /* Treat an (almost) immediate refresh in a top-level browser window as * if it were an HTTP redirect, and thus make the resulting fetch @@ -1689,11 +1643,19 @@ void browser_window_refresh(void *p) * all. */ if (bw->refresh_interval <= 100 && bw->parent == NULL) { - browser_window_go(bw, refresh, url, history_add); + flags |= BROWSER_WINDOW_GO_FLAG_VERIFIABLE; } else { - browser_window_go_unverifiable(bw, refresh, url, history_add, - bw->current_content); + parent = bw->current_content; } + + browser_window_navigate(bw, + refresh, + url, + flags, + NULL, + NULL, + parent); + } @@ -1962,8 +1924,13 @@ void browser_window_reload(struct browser_window *bw, bool all) content_invalidate_reuse_data(bw->current_content); - browser_window_go(bw, nsurl_access( - hlcache_handle_get_url(bw->current_content)), 0, false); + browser_window_navigate(bw, + hlcache_handle_get_url(bw->current_content), + NULL, + BROWSER_WINDOW_GO_FLAG_VERIFIABLE, + NULL, + NULL, + NULL); } @@ -2386,7 +2353,7 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, * OR * - button_2 opens in new tab and the link target is "_blank" */ - bw_target = browser_window_create(NULL, bw, NULL, false, true); + bw_target = browser_window_create(NULL, NULL, bw, false, true); if (!bw_target) return bw; return bw_target; @@ -2407,7 +2374,7 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, * - button_2 doesn't open in new tabs and the link target is * "_blank" */ - bw_target = browser_window_create(NULL, bw, NULL, false, false); + bw_target = browser_window_create(NULL, NULL, bw, false, false); if (!bw_target) return bw; return bw_target; @@ -2441,7 +2408,7 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, if (!nsoption_bool(target_blank)) return bw; - bw_target = browser_window_create(NULL, bw, NULL, false, false); + bw_target = browser_window_create(NULL, NULL, bw, false, false); if (!bw_target) return bw; diff --git a/desktop/browser.h b/desktop/browser.h index f3c68fa09..7e62eb613 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -60,30 +60,69 @@ typedef enum { DRAGGING_OTHER } browser_drag_type; - extern bool browser_reformat_pending; -struct browser_window * browser_window_create(const char *url, - struct browser_window *clone, const char *referrer, - bool history_add, bool new_tab); +/** flags to browser window go */ +enum browser_window_nav_flags { + BROWSER_WINDOW_GO_FLAG_NONE = 0, + /** The page is added to the window history, this should + * be used when returning to a page in the window history. + */ + BROWSER_WINDOW_GO_FLAG_HISTORY = 1, + /** download rather than render the uri */ + BROWSER_WINDOW_GO_FLAG_DOWNLOAD = 2, + /** this transaction is verifiable */ + BROWSER_WINDOW_GO_FLAG_VERIFIABLE = 4, +}; + void browser_window_initialise_common(struct browser_window *bw, struct browser_window *clone); -void browser_window_go(struct browser_window *bw, const char *url, - const char *referrer, bool history_add); -void browser_window_go_post(struct browser_window *bw, - const char *url, char *post_urlenc, - struct fetch_multipart_data *post_multipart, - bool add_to_history, const char *referer, bool download, - bool verifiable, struct hlcache_handle *parent); -void browser_window_go_unverifiable(struct browser_window *bw, - const char *url, const char *referrer, bool history_add, - struct hlcache_handle *parent); + +/** + * Create and open a new root browser window with the given page. + * + * \param url URL to start fetching in the new window + * \param referer The referring uri or NULL if none + * \param clone The browser window to clone + * \param history_add add to history + * \param new_tab create a new tab + * \return new browser window or NULL on error + */ +struct browser_window *browser_window_create(nsurl *url, + nsurl *referer, + struct browser_window *clone, + bool history_add, + bool new_tab); + +/** + * Start fetching a page in a browser window. + * + * \param bw browser window + * \param url URL to start fetching + * \param referrer The referring uri or NULL if none + * \param post_urlenc url encoded post data or NULL if none + * \param post_multipart multipart post data or NULL if none + * \param parent Parent content or NULL if none + * \param flags Flags to control operation + * + * Any existing fetches in the window are aborted. + * + * If post_urlenc and post_multipart are NULL the url is fetched using + * GET rather than POST. + * + */ +nserror browser_window_navigate(struct browser_window *bw, + nsurl *url, + nsurl *referrer, + enum browser_window_nav_flags flags, + char *post_urlenc, + struct fetch_multipart_data *post_multipart, + hlcache_handle *parent); + void browser_window_get_dimensions(struct browser_window *bw, int *width, int *height, bool scaled); void browser_window_set_dimensions(struct browser_window *bw, int width, int height); -void browser_window_download(struct browser_window *bw, - const char *url, const char *referrer); void browser_window_update(struct browser_window *bw, bool scroll_to_top); void browser_window_update_box(struct browser_window *bw, struct rect *rect); void browser_window_stop(struct browser_window *bw); diff --git a/desktop/frames.c b/desktop/frames.c index cc2cabfd2..235dc83ef 100644 --- a/desktop/frames.c +++ b/desktop/frames.c @@ -249,11 +249,13 @@ void browser_window_create_iframes(struct browser_window *bw, window = &(bw->iframes[index++]); if (cur->url) { /* fetch iframe's content */ - browser_window_go_unverifiable(window, - nsurl_access(cur->url), - nsurl_access(hlcache_handle_get_url( - bw->current_content)), - false, bw->current_content); + browser_window_navigate(window, + cur->url, + hlcache_handle_get_url(bw->current_content), + BROWSER_WINDOW_GO_FLAG_NONE, + NULL, + NULL, + bw->current_content); } } } @@ -384,12 +386,13 @@ void browser_window_create_frameset(struct browser_window *bw, window = &bw->children[index]; if (frame->url) { - browser_window_go_unverifiable(window, - nsurl_access(frame->url), - nsurl_access(hlcache_handle_get_url( - parent)), - true, - parent); + browser_window_navigate(window, + frame->url, + hlcache_handle_get_url(parent), + BROWSER_WINDOW_GO_FLAG_HISTORY, + NULL, + NULL, + parent); } } } diff --git a/desktop/history_core.c b/desktop/history_core.c index 2430e04e5..dda4bcaec 100644 --- a/desktop/history_core.c +++ b/desktop/history_core.c @@ -423,40 +423,52 @@ bool history_forward_available(struct history *history) /* Documented in history_core.h */ -void history_go(struct browser_window *bw, struct history *history, - struct history_entry *entry, bool new_window) +void history_go(struct browser_window *bw, + struct history *history, + struct history_entry *entry, + bool new_window) { - char *url; + char *full_url; + nsurl *url; struct history_entry *current; + nserror error; // LOG(("%p %p %p", bw, history, entry)); // LOG(("%s %s %s", // entry->page.url, entry->page.title, entry->page.frag_id)); if (entry->page.frag_id) { - url = malloc(strlen(entry->page.url) + + full_url = malloc(strlen(entry->page.url) + strlen(entry->page.frag_id) + 5); - if (!url) { + if (full_url == NULL) { warn_user("NoMemory", 0); return; } - sprintf(url, "%s#%s", entry->page.url, entry->page.frag_id); + sprintf(full_url, "%s#%s", entry->page.url, entry->page.frag_id); + + error = nsurl_create(full_url, &url); + free(full_url); + } else { + error = nsurl_create(entry->page.url, &url); + } + + + if (error != NSERROR_OK) { + warn_user("NoMemory", 0); + return; } - else - url = entry->page.url; if (new_window) { current = history->current; history->current = entry; - browser_window_create(url, bw, 0, false, false); + browser_window_create(url, NULL, bw, false, false); history->current = current; } else { history->current = entry; - browser_window_go(bw, url, 0, false); + browser_window_navigate(bw, url, NULL, BROWSER_WINDOW_GO_FLAG_VERIFIABLE, NULL, NULL, NULL); } - if (entry->page.frag_id) - free(url); + nsurl_unref(url); } |