{WebFrame是一個接口類,但它先繼承引用計數類RefCounted,這樣對于這個對象多次訪問,就可以使用引用計數來判斷對象的生命周期了。對于base::RefCounted的語法,其實它是一種模板實現的多態特性,這種方案是最高" />

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

谷歌瀏覽器的源碼分析(23)

系統 1721 0
?

繼續上一次來分析 LoadRequest 的代碼,在分析這個函數代碼之前,先看看 WebFrame 類的繼承層次關系,如下:

class WebFrame : public base::RefCounted<WebFrame> {

WebFrame 是一個接口類,但它先繼承引用計數類 RefCounted ,這樣對于這個對象多次訪問,就可以使用引用計數來判斷對象的生命周期了。對于 base::RefCounted<WebFrame> 的語法,其實它是一種模板實現的多態特性,這種方案是最高效的實現方式,比使用虛函數更少占內存,并且運行的速度也更快。它就是解決如下的問題:

? void Release() {

??? if (subtle::RefCountedBase::Release()) {

????? delete static_cast<T*>(this);

??? }

? }

上面的函數里 static_cast<T*>(this) ,它就是一種多態的實現方法,由于 base::RefCounted 類并沒有聲明為虛析構函數,如下:

template <class T>

class RefCounted : public subtle::RefCountedBase {

? public:

? RefCounted() { }

? ~RefCounted() { }

?

既然沒有把類 RefCounted 聲明為虛析構函數,又想在基類里調用派生類的析構函數,只好使用 static_cast 和類型轉換了,這是一種比較好的模板使用方法,在 WTL 里就大量使用這種技術。

接著可以看到:

class WebFrameImpl : public WebFrame {

? public:

? WebFrameImpl();

? ~WebFrameImpl();

WebFrameImpl 是繼承接口類 WebFrame ,這里是使用接口與實現分析的設計模式,這樣更方便代碼靈活地復用。可見設計 Chrome 的設計師和寫代碼的程序員,都是頂尖的模板高手,大部的思想與 WTL 庫的設計是一脈相承。也難怪 Chrome 的瀏覽器使用 WTL 庫來設計界面。

?

#001 ? void WebFrameImpl::LoadRequest(WebRequest* request) {

#002 ??? SubstituteData data;

#003 ??? InternalLoadRequest(request, data, false);

#004 ? }

WebFrame 里調用函數 LoadRequest ,實際上是調用實現類 WebFrameImpl 函數 LoadRequest ,而在這個函數又是調用 InternalLoadRequest 來實現的,它的代碼如下:

#001 ? void WebFrameImpl::InternalLoadRequest(const WebRequest* request,

#002 ???????????????????????????????????????? const SubstituteData& data,

#003 ???????????????????????????????????????? bool replace) {

?

// 轉換請求參數。

#004 ??? const WebRequestImpl* request_impl =

#005 ??????? static_cast<const WebRequestImpl*>(request);

#006 ?

?

獲取請求的資源。

#007 ??? const ResourceRequest& resource_request =

#008 ??????? request_impl->frame_load_request().resourceRequest();

#009 ?

#010 ??? // Special-case javascript URLs. ? Do not interrupt the existing load when

#011 ??? // asked to load a javascript URL unless the script generates a result.

#012 ??? // We can't just use FrameLoader::executeIfJavaScriptURL because it doesn't

#013 ??? // handle redirects properly.

?

獲取需要下載網頁的地址。

#014 ??? const KURL& kurl = resource_request.url();

?

處理加載 javascript 的連接情況。

#015 ??? if (!data.isValid() && kurl.protocol() == "javascript") {

#016 ????? // Don't attempt to reload javascript URLs.

#017 ????? if (resource_request.cachePolicy() == ReloadIgnoringCacheData)

#018 ??????? return;

#019 ?

#020 ????? // We can't load a javascript: URL if there is no Document!

#021 ????? if (!frame_->document())

#022 ??????? return;

#023 ?

#024 ????? // TODO(darin): Is this the best API to use here? ? It works and seems good,

#025 ????? // but will it change out from under us?

#026 ????? DeprecatedString script =

#027 ????????? KURL::decode_string(kurl.deprecatedString().mid(sizeof("javascript:")-1));

#028 ????? bool succ = false;

?

加載執行腳本。

#029 ????? WebCore::String value =

#030 ????????? frame_->loader()->executeScript(script, &succ, true);

#031 ????? if (succ && !frame_->loader()->isScheduledLocationChangePending()) {

#032 ??????? // TODO(darin): We need to figure out how to represent this in session

#033 ??????? // history. ? Hint: don't re-eval script when the user or script navigates

#034 ??????? // back-n-forth (instead store the script result somewhere).

#035 ??????? LoadDocumentData(kurl, value, String("text/html"), String());

#036 ????? }

#037 ????? return;

#038 ??? }

#039 ?

?

停止上一次沒有完成的加載情況。

#040 ??? StopLoading(); ? // make sure existing activity stops

#041 ?

#042 ??? // Keep track of the request temporarily. ? This is effectively a way of

#043 ??? // passing the request to callbacks that may need it. ? See

#044 ??? // WebFrameLoaderClient::createDocumentLoader.

?

保存當前的請求連接。

#045 ??? currently_loading_request_ = request;

#046 ?

#047 ??? // If we have a current datasource, save the request info on it immediately.

#048 ??? // This is because WebCore may not actually initiate a load on the toplevel

#049 ??? // frame for some subframe navigations, so we want to update its request.

?

獲取當前數據源,如果已經存在就可以保存它。

#050 ??? WebDataSourceImpl* datasource = GetDataSourceImpl();

#051 ??? if (datasource)

#052 ????? CacheCurrentRequestInfo(datasource);

#053 ?

?

如果數據有效就可以直接替換就行了。

#054 ??? if (data.isValid()) {

#055 ????? frame_->loader()->load(resource_request, data);

#056 ????? if (replace) {

#057 ??????? // Do this to force WebKit to treat the load as replacing the currently

#058 ??????? // loaded page.

#059 ??????? frame_->loader()->setReplacing();

#060 ????? }

?

如果是歷史網頁選擇,就判斷是否出錯的加載處理。

#061 ??? } else if (request_impl->history_item()) {

#062 ????? // Use the history item if we have one, otherwise fall back to standard

#063 ????? // load.

#064 ????? RefPtr<HistoryItem> current_item = frame_->loader()->currentHistoryItem();

#065 ?

#066 ????? // If there is no current_item, which happens when we are navigating in

#067 ????? // session history after a crash, we need to manufacture one otherwise

#068 ????? // WebKit hoarks. This is probably the wrong thing to do, but it seems to

#069 ??? ?? // work.

#070 ????? if (!current_item) {

#071 ??????? current_item = new HistoryItem(KURL("about:blank"), "");

#072 ??????? frame_->loader()->setCurrentHistoryItem(current_item);

#073 ??????? frame_->page()->backForwardList()->setCurrentItem(current_item.get());

#074 ?

#075 ??????? // Mark the item as fake, so that we don't attempt to save its state and

#076 ??????? // end up with about:blank in the navigation history.

#077 ??????? frame_->page()->backForwardList()->setCurrentItemFake(true);

#078 ????? }

#079 ?

#080 ????? frame_->loader()->goToItem(request_impl->history_item().get(),

#081 ???????????????????????????????? WebCore::FrameLoadTypeIndexedBackForward);

?

重新加載網頁。

#082 ??? } else if (resource_request.cachePolicy() == ReloadIgnoringCacheData) {

#083 ????? frame_->loader()->reload();

?

?

下面開始調用 load 來加載新下載的網頁資源。

#084 ??? } else {

#085 ????? frame_->loader()->load(resource_request);

#086 ??? }

#087 ?

#088 ??? currently_loading_request_ = NULL;

#089 ? }

?

上面通過幾種情況來分別實現了加載 javascript 網頁的處理,還有歷史選項處理,還有重新加載網頁和加載新網頁的處理。下一次再來分析加載新網頁的函數 frame_->loader()->load 的實現。

谷歌瀏覽器的源碼分析(23)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 在线看的成人性视频 | 尤物国产在线精品福利一区 | 精品成人在线观看 | 97成人资源 | 精品四虎免费观看国产高清午夜 | 日本中文字幕在线看 | 亚洲狠狠操 | 欧美精品一区二区三区在线 | 亚洲综合精品一二三区在线 | 在线 亚洲 欧美 | 97视频在线观看免费 | 成人精品第一区二区三区 | 四虎最新紧急更新地址 | 日日噜噜噜夜夜爽爽狠狠图片 | 亚洲欧洲国产精品 | 九九精品热线免费观看6 | 美女视频黄的全i免费 | 久久久久久人精品免费费看 | 欧美日韩不卡在线 | 精品一区二区三区四区乱码90 | 国产精品久久久久久久久ktv | 欧美日韩网站 | 国产啪爱视频精品免视 | 97欧美精品一区二区三区 | 日韩中文字幕精品免费一区 | 99久久免费看国产精品 | 国产欧美久久精品 | 91精品国产91久久久久久 | avav在线精品 | 手机看片福利视频 | 亚洲国产精品日韩在线观看 | 中文字幕在线一区二区三区 | 99精品国产第一福利网站 | 久久频| 天天摸夜夜摸夜夜狠狠摸 | 欧美色网在线 | 亚洲精品在线视频观看 | 一区二区三区四区免费视频 | 国产成人精品久久二区二区 | 婷婷亚洲国产成人精品性色 | 日日摸日日添夜夜爽97 |