上一次说到需要调用这个
OpenURLFromTab
函数,那么这个函数是做什么的呢?从名称上可能猜到它是打开网页,但是是从目前
TAB
页里打开呢?还是新建一个?或者使用每个
TAB
页一个进程呢?这些疑惑,只能通过代码的分析来理解它的实现,代码如下:
这个函数的参数意思:
source
是
TAB
内容。
url
是网络连接地址。
disposition
是窗口打开的位置。
transition
是连接传送的类型。
override_encoding
是编码类型。
#001
void Browser::OpenURLFromTab(TabContents* source,
#002
const GURL& url,
#003
WindowOpenDisposition disposition,
#004
PageTransition::Type transition,
#005
const std::string& override_encoding) {
调试时检查代码。
#006
// No code for these yet
#007
DCHECK((disposition != NEW_POPUP) && (disposition != SAVE_TO_DISK));
#008
获取当前的
TAB
页。
#009
TabContents* current_tab = source ? source : GetSelectedTabContents();
判断是否当前
TAB
页选中。
#010
bool source_tab_was_frontmost = (current_tab == GetSelectedTabContents());
#011
TabContents* new_contents = NULL;
#012
#013
// If the URL is part of the same web site, then load it in the same
#014
// SiteInstance (and thus the same process).
This is an optimization to
#015
// reduce process overhead; it is not necessary for compatibility.
(That is,
#016
// the new tab will not have script connections to the previous tab, so it
#017
// does not need to be part of the same SiteInstance or BrowsingInstance.)
#018
// Default to loading in a new SiteInstance and BrowsingInstance.
#019
// TODO(creis): should this apply to applications?
保存打开连接的实例指针。
#020
SiteInstance* instance = NULL;
如果不使用每个
TAB
页一个进程的方式,就不需要进行下面的处理。因为同一个连接在一个进程里打开是比较快,这里主要做优化。
#021
// Don't use this logic when "--process-per-tab" is specified.
判断是否有每一个
TAB
一个进程的方式。
#022
if (!CommandLine().HasSwitch(switches::kProcessPerTab)) {
有当前进程页。
#023
if (current_tab) {
#024
const WebContents* const web_contents = current_tab->AsWebContents();
判断是否相同的网络连接地址。
#025
if (web_contents) {
#026
const GURL& current_url = web_contents->GetURL();
如果相同的网络地址,并且有实例打开,就返回这个实例在
instance
。
#027
if (SiteInstance::IsSameWebSite(current_url, url))
#028
instance = web_contents->site_instance();
#029
}
#030
}
#031
}
#032
#033
// If this is an application we can only have one tab so a new tab always
#034
// goes into a tabbed browser window.
下面进行不打开新窗口的处理。
#035
if (disposition != NEW_WINDOW && type_ == BrowserType::APPLICATION) {
#036
// If the disposition is OFF_THE_RECORD we don't want to create a new
#037
// browser that will itself create another OTR browser. This will result in
#038
// a browser leak (and crash below because no tab is created or selected).
#039
if (disposition == OFF_THE_RECORD) {
#040
OpenURLOffTheRecord(profile_, url);
#041
return;
#042
}
#043
#044
Browser* b = GetOrCreateTabbedBrowser();
#045
DCHECK(b);
#046
#047
// If we have just created a new browser window, make sure we select the
#048
// tab.
#049
if (b->tab_count() == 0 && disposition == NEW_BACKGROUND_TAB)
#050
disposition = NEW_FOREGROUND_TAB;
#051
#052
b->OpenURL(url, disposition, transition);
#053
b->Show();
#054
b->MoveToFront(true);
#055
return;
#056
}
#057
#058
if (profile_->IsOffTheRecord() && disposition == OFF_THE_RECORD)
#059
disposition = NEW_FOREGROUND_TAB;
#060
这里开始处理打开一个新窗口显示网络连接。
#061
if (disposition == NEW_WINDOW) {
创建一个新的
Browser
浏览器对象。
#062
Browser* new_browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_,
#063
BrowserType::TABBED_BROWSER, L"");
创建一个
TAB
内容。
#064
new_contents = new_browser->AddTabWithURL(url, transition, true, instance);
这里开始显示这个网络连接的内容。
#065
new_browser->Show();
#066
} else if ((disposition == CURRENT_TAB) && current_tab) {
下面开始在当前
TAB
页里打开连接,同时判断处理的类型。
#067
if (transition == PageTransition::TYPED ||
#068
transition == PageTransition::AUTO_BOOKMARK ||
#069
transition == PageTransition::GENERATED ||
#070
transition == PageTransition::START_PAGE) {
#071
// Don't forget the openers if this tab is a New Tab page opened at the
#072
// end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one
#073
// navigation of one of these transition types before resetting the
#074
// opener relationships (this allows for the use case of opening a new
#075
// tab to do a quick look-up of something while viewing a tab earlier in
#076
// the strip). We can make this heuristic more permissive if need be.
#077
// TODO(beng): (http://b/1306495) write unit tests for this once this
#078
//
object is unit-testable.
#079
int current_tab_index =
#080
tabstrip_model_.GetIndexOfTabContents(current_tab);
#081
bool forget_openers =
#082
!(current_tab->type() == TAB_CONTENTS_NEW_TAB_UI &&
#083
current_tab_index == (tab_count() - 1) &&
#084
current_tab->controller()->GetEntryCount() == 1);
#085
if (forget_openers) {
#086
// If the user navigates the current tab to another page in any way
#087
// other than by clicking a link, we want to pro-actively forget all
#088
// TabStrip opener relationships since we assume they're beginning a
#089
// different task by reusing the current tab.
#090
tabstrip_model_.ForgetAllOpeners();
#091
// In this specific case we also want to reset the group relationship,
#092
// since it is now technically invalid.
#093
tabstrip_model_.ForgetGroup(current_tab);
#094
}
#095
}
这里开始在当前
TAB
页里加载网络地址连接。
#096
current_tab->controller()->LoadURL(url, transition);
#097
// The TabContents might have changed as part of the navigation (ex: new tab
#098
// page can become WebContents).
获取当前显示的内容。
#099
new_contents = current_tab->controller()->active_contents();
隐藏最下面状态提示窗口。
#100
GetStatusBubble()->Hide();
#101
#102
// Synchronously update the location bar. This allows us to immediately
#103
// have the URL bar update when the user types something, rather than
#104
// going through the normal system of ScheduleUIUpdate which has a delay.
更新本地的工具条。
#105
UpdateToolBar(false);
后面的内容先不分析,主要分析目前打开当前连接的内容。
#106
} else if (disposition == OFF_THE_RECORD) {
#107
OpenURLOffTheRecord(profile_, url);
#108
return;
#109
} else if (disposition != SUPPRESS_OPEN) {
#110
new_contents =
#111
AddTabWithURL(url, transition, disposition != NEW_BACKGROUND_TAB,
#112
instance);
#113
}
#114
#115
if (disposition != NEW_BACKGROUND_TAB && source_tab_was_frontmost) {
#116
// Give the focus to the newly navigated tab, if the source tab was
#117
// front-most.
#118
new_contents->Focus();
#119
}
#120
#121
if (!override_encoding.empty()) {
#122
// The new tab needs a special encoding, such as a view source page
#123
// which should use the same encoding as the original page.
#124
WebContents* web_contents = new_contents->AsWebContents();
#125
if (web_contents)
#126
web_contents->set_override_encoding(override_encoding);
#127
}
#128
}
#129
上面函数的过程是这样的:主要根据打开网页的方式来选择窗口,比如是创建新窗口,还是只是打开一个
TAB
页,然后在
TAB
页显示。在这里还做了同一个网页地址的优化,不让它打开两个相同的进程来处理。
Browser
对象是创建一个浏览器对象,接着调用
LoadURL
函数来加载输入的网页连接,隐藏当前窗口最下面的加载状态条,更新当前窗口的状态条,就完成了这个函数对当前
TAB
页加载网页的功能。下一次再来分析
LoadURL
函数是怎么样打开网页连接了。