Chrome源码分析----注册默认浏览器

研究了一下Chrome源码中注册默认浏览器的代码,把研究的笔记直接发出来吧.
 
  
 
  
 
//-------------------------ShellIntegration::SetAsDefaultBrowser Begin---------------------------
bool ShellIntegration::SetAsDefaultBrowser() {
FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
LOG(ERROR) << "Error getting app exe path";
return false;
}

// From UI currently we only allow setting default browser for current user.
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
if (!ShellUtil::MakeChromeDefault(dist, ShellUtil::CURRENT_USER,
chrome_exe.value(), true)) {
LOG(ERROR) << "Chrome could not be set as default browser.";
return false;
}

VLOG(1) << " Chrome registered as default browser.";
return true;
}
//-------------------------ShellIntegration::SetAsDefaultBrowser End---------------------------



//-------------------------ShellUtil::MakeChromeDefault Begin---------------------------
bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
int shell_change,
const std::wstring& chrome_exe,
bool elevate_if_not_admin) {
if (!dist->CanSetAsDefault())
return false;

//在注册表中写入默认浏览器所需要的项
//这里如果注册不成功也没做任何处理,返回值根本没用.
ShellUtil::RegisterChromeBrowser(dist, chrome_exe, L"", elevate_if_not_admin);

bool ret = true;
// First use the new "recommended" way on Vista to make Chrome default
// browser.
//vista下注册默认浏览器的方法
//详见http://msdn.microsoft.com/zh-cn/bb776332.aspx
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {

VLOG(1) << "Registering Chrome as default browser on Vista.";
IApplicationAssociationRegistration* pAAR;
HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration),
(void**)&pAAR);
if (SUCCEEDED(hr)) {
std::wstring app_name = dist->GetApplicationName();
std::wstring suffix;
if (ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
app_name += suffix;

hr = pAAR->SetAppAsDefaultAll(app_name.c_str());
pAAR->Release();
}
if (!SUCCEEDED(hr)) {
ret = false;
LOG(ERROR) << "Could not make Chrome default browser.";
}
}

// Now use the old way to associate Chrome with supported protocols and file
// associations. This should not be required on Vista but since some
// applications still read Software\Classes\http key directly, we have to do
// this on Vista also.
//在vista之前的系统中注册默认浏览器的方式,由于一些程序依然按照旧的方式读取注册表项来获取默认浏览器
//所以在vista系统中依然会将旧的项写上

std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
std::wstring suffix;
if (!GetUserSpecificDefaultBrowserSuffix(dist, &suffix))
suffix = L"";

//获取注册默认浏览器所需的注册表项
RegistryEntry::GetUserEntries(dist, chrome_exe, suffix, &entries);


// Change the default browser for current user.
//HKEY_CURRENT_USER,在CURRENT_USER用户级上注册
if ((shell_change & ShellUtil::CURRENT_USER) &&
!AddRegistryEntries(HKEY_CURRENT_USER, entries))
ret = false;

// Chrome as default browser at system level.
//注册HKEY_LOCAL_MACHINE,如果在chrome中注册默认浏览器仅注册HKEY_CURRENT_USER
//在ShellIntegration::SetAsDefaultBrowser代码中写死
if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
!AddRegistryEntries(HKEY_LOCAL_MACHINE, entries))
ret = false;

// Send Windows notification event so that it can update icons for
// file associations.
//通知windows为修改的文件关联刷新图标
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return ret;
}
//-------------------------ShellUtil::MakeChromeDefault End---------------------------


//-------------------------ShellUtil::RegisterChromeBrowser Begin---------------------------
bool ShellUtil::RegisterChromeBrowser(BrowserDistribution* dist,
const std::wstring& chrome_exe,
const std::wstring& unique_suffix,
bool elevate_if_not_admin) {
if (!dist->CanSetAsDefault())
return false;

// First figure out we need to append a suffix to the registry entries to
// make them unique.
//是否在注册的名字后加上当前用户名以保证其唯一
std::wstring suffix;
if (!unique_suffix.empty()) {
suffix = unique_suffix;
} else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) &&
!GetUserSpecificDefaultBrowserSuffix(dist, &suffix) &&
!AnotherUserHasDefaultBrowser(dist, chrome_exe)) {
suffix = L"";
}


// Check if Chrome is already registered with this suffix.
//判断当前浏览器是否已经注册,如果已经注册则不再重复注册
//这里只判断键值是否存在,没有比对值是否和当前要注册的相同,所以可能会有问题
if (IsChromeRegistered(dist, chrome_exe, suffix))
return true;

// If user is an admin try to register and return the status.
// 如果当前是管理员权限运行,在HKEY_LOCAL_MACHINE中直接注册数据
if (IsUserAnAdmin()) {
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries);
return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries);
}

// If user is not an admin and OS is Vista, try to elevate and register.
//如果是windows vista又没有管理员权限,是没有权限写入HKEY_LOCAL_MACHINE的
//windows的提升权限只能在进程边界上进行,所以打开另一个程序弹出UAC注册数据
if (elevate_if_not_admin &&
base::win::GetVersion() >= base::win::VERSION_VISTA &&
ElevateAndRegisterChrome(dist, chrome_exe, suffix))
return true;

// If we got to this point then all we can do is create ProgIds under HKCU
// on XP as well as Vista.
//如果执行到这里,说明确实得不到权限写入HKEY_LOCAL_MACHINE了,只能把数据注册在HKEY_CURRENT_USER下了
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, L"", &entries);
return AddRegistryEntries(HKEY_CURRENT_USER, entries);
}
//-------------------------ShellUtil::RegisterChromeBrowser End---------------------------


//-------------------------IsChromeRegistered Begin---------------------------
// This method checks if Chrome is already registered on the local machine.
// It gets all the required registry entries for Chrome and then checks if
// they exist in HKLM. Returns true if all the entries exist, otherwise false.
bool IsChromeRegistered(BrowserDistribution* dist,
const std::wstring& chrome_exe,
const std::wstring& suffix) {
bool registered = true;
std::list<RegistryEntry*> entries;
STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
RegistryEntry::GetProgIdEntries(dist, chrome_exe, suffix, &entries);
RegistryEntry::GetSystemEntries(dist, chrome_exe, suffix, &entries);
//仅仅判断是否存在,有一项不存在就跳出循环
for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
itr != entries.end() && registered; ++itr) {
// We do not need registered = registered && ... since the loop condition
// is set to exit early.
registered = (*itr)->ExistsInHKLM();
}
return registered;
}
//-------------------------IsChromeRegistered End---------------------------

//-------------------------GetProgIdEntries Begin---------------------------
// This method returns a list of all the registry entries that
// are needed to register Chrome ProgIds.
static bool GetProgIdEntries(BrowserDistribution* dist,
const std::wstring& chrome_exe,
const std::wstring& suffix,
std::list<RegistryEntry*>* entries) {
std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe);
std::wstring open_cmd = ShellUtil::GetChromeShellOpenCmd(chrome_exe);

// File association ProgId
// Software\Classes\ChromeHTML\
std::wstring chrome_html_prog_id(ShellUtil::kRegClasses);
file_util::AppendToPath(&chrome_html_prog_id, ShellUtil::kChromeHTMLProgId);
chrome_html_prog_id.append(suffix);

//写在Software\Classes\ChromeHTML\下 ProgId的类型描述
//const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML Document"
entries->push_front(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc));

//写在Software\Classes\ChromeHTML\下 declares a custom protocol handler
//Under this new key, the URL Protocol string value indicates that this key declares a custom protocol handler.
// Without this key, the handler application will not launch. The value should be an empty string.
//见http://msdn.microsoft.com/en-us/library/ie/aa767914(v=vs.85).aspx
//Registry value name that is needed for ChromeHTML ProgId
//static const wchar_t* kRegUrlProtocol = "URL Protocol";
entries->push_front(new RegistryEntry(
chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L""));

//写Software\Classes\ChromeHTML\DefaultIcon value:chrome.exe所在路径
//关联文件的默认图标路径,chrome直接使用程序图标,所以value是chrome.exe所在路径
entries->push_front(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path));

//写Software\Classes\ChromeHTML\shell\open\command value:chrome.exe所在路径
//打开ChromeHTML时使用的程序所在位置
entries->push_front(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));

return true;
}
//-------------------------GetProgIdEntries End---------------------------


//-------------------------GetSystemEntries Begin---------------------------
// This method returns a list of all the system level registry entries that
// are needed to register Chrome on the machine.
static bool GetSystemEntries(BrowserDistribution* dist,
const std::wstring& chrome_exe,
const std::wstring& suffix,
std::list<RegistryEntry*>* entries) {
std::wstring icon_path = ShellUtil::GetChromeIcon(dist, chrome_exe);
std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\"";

std::wstring app_name = dist->GetApplicationName() + suffix;
std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
start_menu_entry.append(L"\\" + app_name);
//开始菜单处的浏览器显示
//Software\Clients\StartMenuInternet\Chrome value是Chrome
entries->push_front(new RegistryEntry(start_menu_entry, app_name));
//开始菜单浏览器的打开命令
//Software\Clients\StartMenuInternet\Chrome\shell\open\command value是exe所在路径,这里还加了一个引号
entries->push_front(new RegistryEntry(
start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path));

//开始菜单显示的浏览器图标
//Software\Clients\StartMenuInternet\Chrome\DefaultIcon value是exe所在路径
entries->push_front(new RegistryEntry(
start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));

//Software\Clients\StartMenuInternet\Chrome\InstallInfo
//详见http://msdn.microsoft.com/en-us/library/cc144109(VS.85).aspx
std::wstring install_info(start_menu_entry + L"\\InstallInfo");
// TODO: use CommandLine API instead of constructing command lines.
entries->push_front(new RegistryEntry(install_info, L"ReinstallCommand",
quoted_exe_path + L" --" + ASCIIToWide(switches::kMakeDefaultBrowser)));
entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand",
quoted_exe_path + L" --" + ASCIIToWide(switches::kHideIcons)));
entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand",
quoted_exe_path + L" --" + ASCIIToWide(switches::kShowIcons)));
entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1));



//Software\Clients\StartMenuInternet\Chrome\Capabilities
//http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx
std::wstring capabilities(start_menu_entry + L"\\Capabilities");
entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
app_name, capabilities));
entries->push_front(new RegistryEntry(
capabilities, L"ApplicationDescription",
dist->GetLongAppDescription()));
entries->push_front(new RegistryEntry(
capabilities, L"ApplicationIcon", icon_path));
entries->push_front(new RegistryEntry(
capabilities, L"ApplicationName", app_name));

entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu",
L"StartMenuInternet", app_name));

//接下来是把文件扩展名和协议与html_prog_id关联上,就是在GetProgIdEntries写入的那个
//比如Software\Clients\StartMenuInternet\Chrome\Capabilities\FileAssociations
//name 是.htm value是ChromeHTMl
std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
html_prog_id.append(suffix);
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
entries->push_front(new RegistryEntry(
capabilities + L"\\FileAssociations",
ShellUtil::kFileAssociations[i], html_prog_id));
}
//Software\Clients\StartMenuInternet\Chrome\Capabilities\URLAssociations
//其它是一样的
for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
entries->push_front(new RegistryEntry(
capabilities + L"\\URLAssociations",
ShellUtil::kProtocolAssociations[i], html_prog_id));
}

//Software\Microsoft\Windows\CurrentVersion\App Paths\Chrome.exe
//注册exe所在目录和路径
FilePath chrome_path(chrome_exe);
std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey);
file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value());
entries->push_front(new RegistryEntry(app_path_key, chrome_exe));
entries->push_front(new RegistryEntry(app_path_key,
ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value()));

// TODO: add chrome to open with list (Bug 16726).
return true;
}

//-------------------------GetSystemEntries End---------------------------

//-------------------------GetUserEntries Begin---------------------------
//XP下使用的项
//这个博文写的很清楚了
//http://www.cnblogs.com/greenerycn/archive/2010/08/13/how_to_set_default_browser.html
// This method returns a list of all the user level registry entries that
// are needed to make Chrome default browser.
static bool GetUserEntries(BrowserDistribution* dist,
const std::wstring& chrome_exe,
const std::wstring& suffix,
std::list<RegistryEntry*>* entries) {
// File extension associations.
std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
html_prog_id.append(suffix);
for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
std::wstring ext_key(ShellUtil::kRegClasses);
file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]);
entries->push_front(new RegistryEntry(ext_key, html_prog_id));
}

// Protocols associations.
std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
std::wstring chrome_icon = ShellUtil::GetChromeIcon(dist, chrome_exe);
for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
std::wstring url_key(ShellUtil::kRegClasses);
file_util::AppendToPath(&url_key, ShellUtil::kProtocolAssociations[i]);

// <root hkey>\Software\Classes\<protocol>\DefaultIcon
std::wstring icon_key = url_key + ShellUtil::kRegDefaultIcon;
entries->push_front(new RegistryEntry(icon_key, chrome_icon));

// <root hkey>\Software\Classes\<protocol>\shell\open\command
std::wstring shell_key = url_key + ShellUtil::kRegShellOpen;
entries->push_front(new RegistryEntry(shell_key, chrome_open));

// <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
std::wstring dde_key = url_key + L"\\shell\\open\\ddeexec";
entries->push_front(new RegistryEntry(dde_key, L""));

// <root hkey>\Software\Classes\<protocol>\shell\@
std::wstring protocol_shell_key = url_key + ShellUtil::kRegShellPath;
entries->push_front(new RegistryEntry(protocol_shell_key, L"open"));
}

// start->Internet shortcut.
std::wstring start_menu(ShellUtil::kRegStartMenuInternet);
std::wstring app_name = dist->GetApplicationName() + suffix;
entries->push_front(new RegistryEntry(start_menu, app_name));
return true;
}
//-------------------------GetUserEntries End---------------------------

转载于:https://www.cnblogs.com/Entreri/archive/2012/02/05/2339145.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值