summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/gtk/options/general_page_gtk.cc36
-rw-r--r--chrome/browser/gtk/options/general_page_gtk.h12
-rw-r--r--chrome/browser/shell_integration.cc192
-rw-r--r--chrome/browser/shell_integration.h65
-rw-r--r--chrome/browser/shell_integration_win.cc155
-rw-r--r--chrome/browser/views/options/general_page_view.cc129
-rw-r--r--chrome/browser/views/options/general_page_view.h17
7 files changed, 322 insertions, 284 deletions
diff --git a/chrome/browser/gtk/options/general_page_gtk.cc b/chrome/browser/gtk/options/general_page_gtk.cc
index 7f1520c..636d2e0 100644
--- a/chrome/browser/gtk/options/general_page_gtk.cc
+++ b/chrome/browser/gtk/options/general_page_gtk.cc
@@ -14,7 +14,6 @@
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/session_startup_pref.h"
-#include "chrome/browser/shell_integration.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_names.h"
@@ -58,7 +57,9 @@ GeneralPageGtk::GeneralPageGtk(Profile* profile)
: OptionsPageBase(profile),
template_url_model_(NULL),
default_search_initializing_(true),
- initializing_(true) {
+ initializing_(true),
+ default_browser_worker_(
+ new ShellIntegration::DefaultBrowserWorker(this)) {
OptionsLayoutBuilderGtk options_builder;
options_builder.AddOptionGroup(
l10n_util::GetStringUTF8(IDS_OPTIONS_STARTUP_GROUP_NAME),
@@ -93,6 +94,8 @@ GeneralPageGtk::~GeneralPageGtk() {
if (template_url_model_)
template_url_model_->RemoveObserver(this);
+
+ default_browser_worker_->ObserverDestroyed();
}
///////////////////////////////////////////////////////////////////////////////
@@ -339,6 +342,8 @@ GtkWidget* GeneralPageGtk::InitDefaultSearchGroup() {
GtkWidget* GeneralPageGtk::InitDefaultBrowserGroup() {
GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
+ // TODO(mattm): the label should be created with a text like "checking for
+ // default" to be displayed while we wait for the check to complete.
default_browser_status_label_ = gtk_label_new(NULL);
gtk_box_pack_start(GTK_BOX(vbox), default_browser_status_label_,
FALSE, FALSE, 0);
@@ -354,7 +359,7 @@ GtkWidget* GeneralPageGtk::InitDefaultBrowserGroup() {
GtkWidget* vbox_alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
gtk_container_add(GTK_CONTAINER(vbox_alignment), vbox);
- SetDefaultBrowserUIState(ShellIntegration::IsDefaultBrowser());
+ default_browser_worker_->StartCheckDefaultBrowser();
return vbox_alignment;
}
@@ -478,8 +483,7 @@ void GeneralPageGtk::OnDefaultSearchManageEnginesClicked(
void GeneralPageGtk::OnBrowserUseAsDefaultClicked(
GtkButton* button,
GeneralPageGtk* general_page) {
- general_page->SetDefaultBrowserUIState(
- ShellIntegration::SetAsDefaultBrowser());
+ general_page->default_browser_worker_->StartSetAsDefaultBrowser();
// If the user made Chrome the default browser, then he/she arguably wants
// to be notified when that changes.
general_page->profile()->GetPrefs()->SetBoolean(prefs::kCheckDefaultBrowser,
@@ -680,22 +684,26 @@ void GeneralPageGtk::EnableCustomHomepagesControls(bool enable) {
gtk_widget_set_sensitive(startup_custom_pages_tree_, enable);
}
-void GeneralPageGtk::SetDefaultBrowserUIState(bool is_default) {
- const char* color;
+void GeneralPageGtk::SetDefaultBrowserUIState(
+ ShellIntegration::DefaultBrowserUIState state) {
+ const char* color = NULL;
std::string text;
- if (is_default) {
+ if (state == ShellIntegration::STATE_DEFAULT) {
color = kDefaultBrowserLabelColor;
text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_DEFAULT,
l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
- } else {
+ } else if (state == ShellIntegration::STATE_NOT_DEFAULT) {
color = kNotDefaultBrowserLabelColor;
text = l10n_util::GetStringFUTF8(IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT,
l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
}
- char* markup = g_markup_printf_escaped(kDefaultBrowserLabelMarkup,
- color, text.c_str());
- gtk_label_set_markup(GTK_LABEL(default_browser_status_label_), markup);
- g_free(markup);
+ if (color) {
+ char* markup = g_markup_printf_escaped(kDefaultBrowserLabelMarkup,
+ color, text.c_str());
+ gtk_label_set_markup(GTK_LABEL(default_browser_status_label_), markup);
+ g_free(markup);
+ }
- gtk_widget_set_sensitive(default_browser_use_as_default_button_, !is_default);
+ gtk_widget_set_sensitive(default_browser_use_as_default_button_,
+ state == ShellIntegration::STATE_NOT_DEFAULT);
}
diff --git a/chrome/browser/gtk/options/general_page_gtk.h b/chrome/browser/gtk/options/general_page_gtk.h
index c1f6d81..efbf8d0 100644
--- a/chrome/browser/gtk/options/general_page_gtk.h
+++ b/chrome/browser/gtk/options/general_page_gtk.h
@@ -13,6 +13,7 @@
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/options_page_base.h"
#include "chrome/browser/search_engines/template_url_model.h"
+#include "chrome/browser/shell_integration.h"
#include "chrome/common/pref_member.h"
#include "googleurl/src/gurl.h"
@@ -20,7 +21,8 @@ class Profile;
class ListStoreFavIconLoader;
class GeneralPageGtk : public OptionsPageBase,
- public TemplateURLModelObserver {
+ public TemplateURLModelObserver,
+ public ShellIntegration::DefaultBrowserObserver {
public:
explicit GeneralPageGtk(Profile* profile);
~GeneralPageGtk();
@@ -126,8 +128,9 @@ class GeneralPageGtk : public OptionsPageBase,
// option if that preference is not selected.
void EnableCustomHomepagesControls(bool enable);
- // Sets the UI state to match
- void SetDefaultBrowserUIState(bool is_default);
+ // ShellIntegration::DefaultBrowserObserver implementation.
+ virtual void SetDefaultBrowserUIState(
+ ShellIntegration::DefaultBrowserUIState state);
// Widgets of the startup group
GtkWidget* startup_homepage_radio_;
@@ -175,6 +178,9 @@ class GeneralPageGtk : public OptionsPageBase,
// Helper to load the favicon pixbufs into the |startup_custom_pages_model_|.
scoped_ptr<ListStoreFavIconLoader> favicon_loader_;
+ // The helper object that performs default browser set/check tasks.
+ scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
+
DISALLOW_COPY_AND_ASSIGN(GeneralPageGtk);
};
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index 6f1957a..e982ab8 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -4,152 +4,74 @@
#include "chrome/browser/shell_integration.h"
-#include <windows.h>
-#include <shlobj.h>
-#include <shobjidl.h>
-
-#include "app/win_util.h"
-#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/registry.h"
-#include "base/string_util.h"
-#include "base/task.h"
-#include "base/win_util.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/create_reg_key_work_item.h"
-#include "chrome/installer/util/set_reg_value_work_item.h"
-#include "chrome/installer/util/shell_util.h"
-#include "chrome/installer/util/util_constants.h"
-#include "chrome/installer/util/work_item.h"
-#include "chrome/installer/util/work_item_list.h"
+#include "base/thread.h"
+#include "chrome/browser/browser_process.h"
-bool ShellIntegration::SetAsDefaultBrowser() {
- std::wstring chrome_exe;
- if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
- LOG(ERROR) << "Error getting app exe path";
- return false;
- }
+///////////////////////////////////////////////////////////////////////////////
+// ShellIntegration::DefaultBrowserWorker
+//
- // From UI currently we only allow setting default browser for current user.
- if (!ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER,
- chrome_exe, true)) {
- LOG(ERROR) << "Chrome could not be set as default browser.";
- return false;
- }
+ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
+ DefaultBrowserObserver* observer)
+ : observer_(observer),
+ ui_loop_(MessageLoop::current()),
+ file_loop_(g_browser_process->file_thread()->message_loop()) {
+}
- LOG(INFO) << "Chrome registered as default browser.";
- return true;
+void ShellIntegration::DefaultBrowserWorker::StartCheckDefaultBrowser() {
+ observer_->SetDefaultBrowserUIState(STATE_PROCESSING);
+ file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &DefaultBrowserWorker::ExecuteCheckDefaultBrowser));
}
-bool ShellIntegration::IsDefaultBrowser() {
- // First determine the app path. If we can't determine what that is, we have
- // bigger fish to fry...
- std::wstring app_path;
- if (!PathService::Get(base::FILE_EXE, &app_path)) {
- LOG(ERROR) << "Error getting app exe path";
- return false;
- }
- // When we check for default browser we don't necessarily want to count file
- // type handlers and icons as having changed the default browser status,
- // since the user may have changed their shell settings to cause HTML files
- // to open with a text editor for example. We also don't want to aggressively
- // claim FTP, since the user may have a separate FTP client. It is an open
- // question as to how to "heal" these settings. Perhaps the user should just
- // re-run the installer or run with the --set-default-browser command line
- // flag. There is doubtless some other key we can hook into to cause "Repair"
- // to show up in Add/Remove programs for us.
- const std::wstring kChromeProtocols[] = {L"http", L"https"};
+void ShellIntegration::DefaultBrowserWorker::StartSetAsDefaultBrowser() {
+ observer_->SetDefaultBrowserUIState(STATE_PROCESSING);
+ file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &DefaultBrowserWorker::ExecuteSetAsDefaultBrowser));
+}
- if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
- IApplicationAssociationRegistration* pAAR;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
- NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration),
- (void**)&pAAR);
- if (!SUCCEEDED(hr))
- return false;
+void ShellIntegration::DefaultBrowserWorker::ObserverDestroyed() {
+ // Our associated view has gone away, so we shouldn't call back to it if
+ // our worker thread returns after the view is dead.
+ observer_ = NULL;
+}
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- std::wstring app_name = dist->GetApplicationName();
- std::wstring app_name_with_suffix;
- ShellUtil::GetUserSpecificDefaultBrowserSuffix(&app_name_with_suffix);
- app_name_with_suffix = app_name + app_name_with_suffix;
- for (int i = 0; i < _countof(kChromeProtocols); i++) {
- BOOL result = TRUE;
- hr = pAAR->QueryAppIsDefault(kChromeProtocols[i].c_str(), AT_URLPROTOCOL,
- AL_EFFECTIVE, app_name_with_suffix.c_str(), &result);
- if (!SUCCEEDED(hr) || (result == FALSE)) {
- hr = pAAR->QueryAppIsDefault(kChromeProtocols[i].c_str(),
- AT_URLPROTOCOL, AL_EFFECTIVE, app_name.c_str(), &result);
- if (!SUCCEEDED(hr) || (result == FALSE)) {
- pAAR->Release();
- return false;
- }
- }
- }
- pAAR->Release();
- } else {
- std::wstring short_app_path;
- GetShortPathName(app_path.c_str(), WriteInto(&short_app_path, MAX_PATH),
- MAX_PATH);
+///////////////////////////////////////////////////////////////////////////////
+// DefaultBrowserWorker, private:
+
+void ShellIntegration::DefaultBrowserWorker::ExecuteCheckDefaultBrowser() {
+ DCHECK(MessageLoop::current() == file_loop_);
+ bool is_default = ShellIntegration::IsDefaultBrowser();
+ ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &DefaultBrowserWorker::CompleteCheckDefaultBrowser, is_default));
+}
+
+void ShellIntegration::DefaultBrowserWorker::CompleteCheckDefaultBrowser(
+ bool is_default) {
+ DCHECK(MessageLoop::current() == ui_loop_);
+ UpdateUI(is_default);
+}
+
+void ShellIntegration::DefaultBrowserWorker::ExecuteSetAsDefaultBrowser() {
+ DCHECK(MessageLoop::current() == file_loop_);
+ ShellIntegration::SetAsDefaultBrowser();
+ ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &DefaultBrowserWorker::CompleteSetAsDefaultBrowser));
+}
- // open command for protocol associations
- for (int i = 0; i < _countof(kChromeProtocols); i++) {
- // Check in HKEY_CLASSES_ROOT that is the result of merge between
- // HKLM and HKCU
- HKEY root_key = HKEY_CLASSES_ROOT;
- // Check <protocol>\shell\open\command
- std::wstring key_path(kChromeProtocols[i] + ShellUtil::kRegShellOpen);
- RegKey key(root_key, key_path.c_str(), KEY_READ);
- std::wstring value;
- if (!key.Valid() || !key.ReadValue(L"", &value))
- return false;
- // Need to normalize path in case it's been munged.
- CommandLine command_line(L"");
- command_line.ParseFromString(value);
- std::wstring short_path;
- GetShortPathName(command_line.program().c_str(),
- WriteInto(&short_path, MAX_PATH), MAX_PATH);
- if ((short_path.size() != short_app_path.size()) ||
- (!std::equal(short_path.begin(),
- short_path.end(),
- short_app_path.begin(),
- CaseInsensitiveCompare<wchar_t>())))
- return false;
- }
+void ShellIntegration::DefaultBrowserWorker::CompleteSetAsDefaultBrowser() {
+ DCHECK(MessageLoop::current() == ui_loop_);
+ if (observer_) {
+ // Set as default completed, check again to make sure it stuck...
+ StartCheckDefaultBrowser();
}
- return true;
}
-// There is no reliable way to say which browser is default on a machine (each
-// browser can have some of the protocols/shortcuts). So we look for only HTTP
-// protocol handler. Even this handler is located at different places in
-// registry on XP and Vista:
-// - HKCR\http\shell\open\command (XP)
-// - HKCU\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\
-// http\UserChoice (Vista)
-// This method checks if Firefox is defualt browser by checking these
-// locations and returns true if Firefox traces are found there. In case of
-// error (or if Firefox is not found)it returns the default value which
-// is false.
-bool ShellIntegration::IsFirefoxDefaultBrowser() {
- bool ff_default = false;
- if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
- std::wstring app_cmd;
- RegKey key(HKEY_CURRENT_USER, ShellUtil::kRegVistaUrlPrefs, KEY_READ);
- if (key.Valid() && key.ReadValue(L"Progid", &app_cmd) &&
- app_cmd == L"FirefoxURL")
- ff_default = true;
- } else {
- std::wstring key_path(L"http");
- key_path.append(ShellUtil::kRegShellOpen);
- RegKey key(HKEY_CLASSES_ROOT, key_path.c_str(), KEY_READ);
- std::wstring app_cmd;
- if (key.Valid() && key.ReadValue(L"", &app_cmd) &&
- std::wstring::npos != StringToLowerASCII(app_cmd).find(L"firefox"))
- ff_default = true;
+void ShellIntegration::DefaultBrowserWorker::UpdateUI(bool is_default) {
+ if (observer_) {
+ DefaultBrowserUIState state =
+ is_default ? STATE_DEFAULT : STATE_NOT_DEFAULT;
+ observer_->SetDefaultBrowserUIState(state);
}
- return ff_default;
}
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index 46219af..4059266 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -7,6 +7,10 @@
#include <string>
+#include "base/ref_counted.h"
+
+class MessageLoop;
+
class ShellIntegration {
public:
// Sets Chrome as default browser (only for current user). Returns false if
@@ -22,6 +26,67 @@ class ShellIntegration {
// Returns true if Firefox is likely to be the default browser for the current
// user. This method is very fast so it can be invoked in the UI thread.
static bool IsFirefoxDefaultBrowser();
+
+
+ // The current default browser UI state
+ enum DefaultBrowserUIState {
+ STATE_PROCESSING,
+ STATE_DEFAULT,
+ STATE_NOT_DEFAULT
+ };
+
+ class DefaultBrowserObserver {
+ public:
+ // Updates the UI state to reflect the current default browser state.
+ virtual void SetDefaultBrowserUIState(DefaultBrowserUIState state) = 0;
+ virtual ~DefaultBrowserObserver() {}
+ };
+ // A helper object that handles checking if Chrome is the default browser on
+ // Windows and also setting it as the default browser. These operations are
+ // performed asynchronously on the file thread since registry access is
+ // involved and this can be slow.
+ //
+ class DefaultBrowserWorker
+ : public base::RefCountedThreadSafe<DefaultBrowserWorker> {
+ public:
+ explicit DefaultBrowserWorker(DefaultBrowserObserver* observer);
+ virtual ~DefaultBrowserWorker() {}
+
+ // Checks if Chrome is the default browser.
+ void StartCheckDefaultBrowser();
+
+ // Sets Chrome as the default browser.
+ void StartSetAsDefaultBrowser();
+
+ // Called to notify the worker that the view is gone.
+ void ObserverDestroyed();
+
+ private:
+ // Functions that track the process of checking if Chrome is the default
+ // browser. |ExecuteCheckDefaultBrowser| checks the registry on the file
+ // thread. |CompleteCheckDefaultBrowser| notifies the view to update on the
+ // UI thread.
+ void ExecuteCheckDefaultBrowser();
+ void CompleteCheckDefaultBrowser(bool is_default);
+
+ // Functions that track the process of setting Chrome as the default
+ // browser. |ExecuteSetAsDefaultBrowser| updates the registry on the file
+ // thread. |CompleteSetAsDefaultBrowser| notifies the view to update on the
+ // UI thread.
+ void ExecuteSetAsDefaultBrowser();
+ void CompleteSetAsDefaultBrowser();
+
+ // Updates the UI in our associated view with the current default browser
+ // state.
+ void UpdateUI(bool is_default);
+
+ DefaultBrowserObserver* observer_;
+
+ MessageLoop* ui_loop_;
+ MessageLoop* file_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultBrowserWorker);
+ };
};
#endif // CHROME_BROWSER_SHELL_INTEGRATION_H__
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
new file mode 100644
index 0000000..6f1957a
--- /dev/null
+++ b/chrome/browser/shell_integration_win.cc
@@ -0,0 +1,155 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/shell_integration.h"
+
+#include <windows.h>
+#include <shlobj.h>
+#include <shobjidl.h>
+
+#include "app/win_util.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/registry.h"
+#include "base/string_util.h"
+#include "base/task.h"
+#include "base/win_util.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/create_reg_key_work_item.h"
+#include "chrome/installer/util/set_reg_value_work_item.h"
+#include "chrome/installer/util/shell_util.h"
+#include "chrome/installer/util/util_constants.h"
+#include "chrome/installer/util/work_item.h"
+#include "chrome/installer/util/work_item_list.h"
+
+bool ShellIntegration::SetAsDefaultBrowser() {
+ std::wstring 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.
+ if (!ShellUtil::MakeChromeDefault(ShellUtil::CURRENT_USER,
+ chrome_exe, true)) {
+ LOG(ERROR) << "Chrome could not be set as default browser.";
+ return false;
+ }
+
+ LOG(INFO) << "Chrome registered as default browser.";
+ return true;
+}
+
+bool ShellIntegration::IsDefaultBrowser() {
+ // First determine the app path. If we can't determine what that is, we have
+ // bigger fish to fry...
+ std::wstring app_path;
+ if (!PathService::Get(base::FILE_EXE, &app_path)) {
+ LOG(ERROR) << "Error getting app exe path";
+ return false;
+ }
+ // When we check for default browser we don't necessarily want to count file
+ // type handlers and icons as having changed the default browser status,
+ // since the user may have changed their shell settings to cause HTML files
+ // to open with a text editor for example. We also don't want to aggressively
+ // claim FTP, since the user may have a separate FTP client. It is an open
+ // question as to how to "heal" these settings. Perhaps the user should just
+ // re-run the installer or run with the --set-default-browser command line
+ // flag. There is doubtless some other key we can hook into to cause "Repair"
+ // to show up in Add/Remove programs for us.
+ const std::wstring kChromeProtocols[] = {L"http", L"https"};
+
+ if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
+ IApplicationAssociationRegistration* pAAR;
+ HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
+ NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration),
+ (void**)&pAAR);
+ if (!SUCCEEDED(hr))
+ return false;
+
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ std::wstring app_name = dist->GetApplicationName();
+ std::wstring app_name_with_suffix;
+ ShellUtil::GetUserSpecificDefaultBrowserSuffix(&app_name_with_suffix);
+ app_name_with_suffix = app_name + app_name_with_suffix;
+ for (int i = 0; i < _countof(kChromeProtocols); i++) {
+ BOOL result = TRUE;
+ hr = pAAR->QueryAppIsDefault(kChromeProtocols[i].c_str(), AT_URLPROTOCOL,
+ AL_EFFECTIVE, app_name_with_suffix.c_str(), &result);
+ if (!SUCCEEDED(hr) || (result == FALSE)) {
+ hr = pAAR->QueryAppIsDefault(kChromeProtocols[i].c_str(),
+ AT_URLPROTOCOL, AL_EFFECTIVE, app_name.c_str(), &result);
+ if (!SUCCEEDED(hr) || (result == FALSE)) {
+ pAAR->Release();
+ return false;
+ }
+ }
+ }
+ pAAR->Release();
+ } else {
+ std::wstring short_app_path;
+ GetShortPathName(app_path.c_str(), WriteInto(&short_app_path, MAX_PATH),
+ MAX_PATH);
+
+ // open command for protocol associations
+ for (int i = 0; i < _countof(kChromeProtocols); i++) {
+ // Check in HKEY_CLASSES_ROOT that is the result of merge between
+ // HKLM and HKCU
+ HKEY root_key = HKEY_CLASSES_ROOT;
+ // Check <protocol>\shell\open\command
+ std::wstring key_path(kChromeProtocols[i] + ShellUtil::kRegShellOpen);
+ RegKey key(root_key, key_path.c_str(), KEY_READ);
+ std::wstring value;
+ if (!key.Valid() || !key.ReadValue(L"", &value))
+ return false;
+ // Need to normalize path in case it's been munged.
+ CommandLine command_line(L"");
+ command_line.ParseFromString(value);
+ std::wstring short_path;
+ GetShortPathName(command_line.program().c_str(),
+ WriteInto(&short_path, MAX_PATH), MAX_PATH);
+ if ((short_path.size() != short_app_path.size()) ||
+ (!std::equal(short_path.begin(),
+ short_path.end(),
+ short_app_path.begin(),
+ CaseInsensitiveCompare<wchar_t>())))
+ return false;
+ }
+ }
+ return true;
+}
+
+// There is no reliable way to say which browser is default on a machine (each
+// browser can have some of the protocols/shortcuts). So we look for only HTTP
+// protocol handler. Even this handler is located at different places in
+// registry on XP and Vista:
+// - HKCR\http\shell\open\command (XP)
+// - HKCU\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\
+// http\UserChoice (Vista)
+// This method checks if Firefox is defualt browser by checking these
+// locations and returns true if Firefox traces are found there. In case of
+// error (or if Firefox is not found)it returns the default value which
+// is false.
+bool ShellIntegration::IsFirefoxDefaultBrowser() {
+ bool ff_default = false;
+ if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
+ std::wstring app_cmd;
+ RegKey key(HKEY_CURRENT_USER, ShellUtil::kRegVistaUrlPrefs, KEY_READ);
+ if (key.Valid() && key.ReadValue(L"Progid", &app_cmd) &&
+ app_cmd == L"FirefoxURL")
+ ff_default = true;
+ } else {
+ std::wstring key_path(L"http");
+ key_path.append(ShellUtil::kRegShellOpen);
+ RegKey key(HKEY_CLASSES_ROOT, key_path.c_str(), KEY_READ);
+ std::wstring app_cmd;
+ if (key.Valid() && key.ReadValue(L"", &app_cmd) &&
+ std::wstring::npos != StringToLowerASCII(app_cmd).find(L"firefox"))
+ ff_default = true;
+ }
+ return ff_default;
+}
diff --git a/chrome/browser/views/options/general_page_view.cc b/chrome/browser/views/options/general_page_view.cc
index dcf579f..e99444d 100644
--- a/chrome/browser/views/options/general_page_view.cc
+++ b/chrome/browser/views/options/general_page_view.cc
@@ -9,10 +9,8 @@
#include "base/gfx/png_decoder.h"
#include "base/message_loop.h"
#include "base/string_util.h"
-#include "base/thread.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
-#include "chrome/browser/browser_process.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/net/url_fixer_upper.h"
@@ -20,7 +18,6 @@
#include "chrome/browser/session_startup_pref.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
-#include "chrome/browser/shell_integration.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/keyword_editor_view.h"
#include "chrome/browser/views/options/options_group_view.h"
@@ -54,118 +51,6 @@ std::wstring GetNewTabUIURLString() {
}
///////////////////////////////////////////////////////////////////////////////
-// GeneralPageView::DefaultBrowserWorker
-//
-// A helper object that handles checking if Chrome is the default browser on
-// Windows and also setting it as the default browser. These operations are
-// performed asynchronously on the file thread since registry access is
-// involved and this can be slow.
-//
-class GeneralPageView::DefaultBrowserWorker
- : public base::RefCountedThreadSafe<GeneralPageView::DefaultBrowserWorker> {
- public:
- explicit DefaultBrowserWorker(GeneralPageView* general_page_view);
-
- // Checks if Chrome is the default browser.
- void StartCheckDefaultBrowser();
-
- // Sets Chrome as the default browser.
- void StartSetAsDefaultBrowser();
-
- // Called to notify the worker that the view is gone.
- void ViewDestroyed();
-
- private:
- // Functions that track the process of checking if Chrome is the default
- // browser.
- // |ExecuteCheckDefaultBrowser| checks the registry on the file thread.
- // |CompleteCheckDefaultBrowser| notifies the view to update on the UI thread.
- void ExecuteCheckDefaultBrowser();
- void CompleteCheckDefaultBrowser(bool is_default);
-
- // Functions that track the process of setting Chrome as the default browser.
- // |ExecuteSetAsDefaultBrowser| updates the registry on the file thread.
- // |CompleteSetAsDefaultBrowser| notifies the view to update on the UI thread.
- void ExecuteSetAsDefaultBrowser();
- void CompleteSetAsDefaultBrowser();
-
- // Updates the UI in our associated view with the current default browser
- // state.
- void UpdateUI(bool is_default);
-
- GeneralPageView* general_page_view_;
-
- MessageLoop* ui_loop_;
- MessageLoop* file_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(GeneralPageView::DefaultBrowserWorker);
-};
-
-GeneralPageView::DefaultBrowserWorker::DefaultBrowserWorker(
- GeneralPageView* general_page_view)
- : general_page_view_(general_page_view),
- ui_loop_(MessageLoop::current()),
- file_loop_(g_browser_process->file_thread()->message_loop()) {
-}
-
-void GeneralPageView::DefaultBrowserWorker::StartCheckDefaultBrowser() {
- general_page_view_->SetDefaultBrowserUIState(STATE_PROCESSING);
- file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &DefaultBrowserWorker::ExecuteCheckDefaultBrowser));
-}
-
-void GeneralPageView::DefaultBrowserWorker::StartSetAsDefaultBrowser() {
- general_page_view_->SetDefaultBrowserUIState(STATE_PROCESSING);
- file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &DefaultBrowserWorker::ExecuteSetAsDefaultBrowser));
-}
-
-void GeneralPageView::DefaultBrowserWorker::ViewDestroyed() {
- // Our associated view has gone away, so we shouldn't call back to it if
- // our worker thread returns after the view is dead.
- general_page_view_ = NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DefaultBrowserWorker, private:
-
-void GeneralPageView::DefaultBrowserWorker::ExecuteCheckDefaultBrowser() {
- DCHECK(MessageLoop::current() == file_loop_);
- bool is_default = ShellIntegration::IsDefaultBrowser();
- ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &DefaultBrowserWorker::CompleteCheckDefaultBrowser, is_default));
-}
-
-void GeneralPageView::DefaultBrowserWorker::CompleteCheckDefaultBrowser(
- bool is_default) {
- DCHECK(MessageLoop::current() == ui_loop_);
- UpdateUI(is_default);
-}
-
-void GeneralPageView::DefaultBrowserWorker::ExecuteSetAsDefaultBrowser() {
- DCHECK(MessageLoop::current() == file_loop_);
- bool result = ShellIntegration::SetAsDefaultBrowser();
- ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &DefaultBrowserWorker::CompleteSetAsDefaultBrowser));
-}
-
-void GeneralPageView::DefaultBrowserWorker::CompleteSetAsDefaultBrowser() {
- DCHECK(MessageLoop::current() == ui_loop_);
- if (general_page_view_) {
- // Set as default completed, check again to make sure it stuck...
- StartCheckDefaultBrowser();
- }
-}
-
-void GeneralPageView::DefaultBrowserWorker::UpdateUI(bool is_default) {
- if (general_page_view_) {
- DefaultBrowserUIState state =
- is_default ? STATE_DEFAULT : STATE_NOT_DEFAULT;
- general_page_view_->SetDefaultBrowserUIState(state);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
// CustomHomePagesTableModel
// CustomHomePagesTableModel is the model for the TableView showing the list
@@ -525,7 +410,8 @@ GeneralPageView::GeneralPageView(Profile* profile)
default_browser_status_label_(NULL),
default_browser_use_as_default_button_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(
- default_browser_worker_(new DefaultBrowserWorker(this))),
+ default_browser_worker_(
+ new ShellIntegration::DefaultBrowserWorker(this))),
OptionsPageView(profile) {
}
@@ -535,7 +421,7 @@ GeneralPageView::~GeneralPageView() {
prefs::kURLsToRestoreOnStartup, this);
if (startup_custom_pages_table_)
startup_custom_pages_table_->SetModel(NULL);
- default_browser_worker_->ViewDestroyed();
+ default_browser_worker_->ObserverDestroyed();
}
///////////////////////////////////////////////////////////////////////////////
@@ -755,16 +641,17 @@ void GeneralPageView::Layout() {
///////////////////////////////////////////////////////////////////////////////
// GeneralPageView, private:
-void GeneralPageView::SetDefaultBrowserUIState(DefaultBrowserUIState state) {
- bool button_enabled = state == STATE_NOT_DEFAULT;
+void GeneralPageView::SetDefaultBrowserUIState(
+ ShellIntegration::DefaultBrowserUIState state) {
+ bool button_enabled = state == ShellIntegration::STATE_NOT_DEFAULT;
default_browser_use_as_default_button_->SetEnabled(button_enabled);
- if (state == STATE_DEFAULT) {
+ if (state == ShellIntegration::STATE_DEFAULT) {
default_browser_status_label_->SetText(
l10n_util::GetStringF(IDS_OPTIONS_DEFAULTBROWSER_DEFAULT,
l10n_util::GetString(IDS_PRODUCT_NAME)));
default_browser_status_label_->SetColor(kDefaultBrowserLabelColor);
Layout();
- } else if (state == STATE_NOT_DEFAULT) {
+ } else if (state == ShellIntegration::STATE_NOT_DEFAULT) {
default_browser_status_label_->SetText(
l10n_util::GetStringF(IDS_OPTIONS_DEFAULTBROWSER_NOTDEFAULT,
l10n_util::GetString(IDS_PRODUCT_NAME)));
diff --git a/chrome/browser/views/options/general_page_view.h b/chrome/browser/views/options/general_page_view.h
index 3faa421..27827be 100644
--- a/chrome/browser/views/options/general_page_view.h
+++ b/chrome/browser/views/options/general_page_view.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_VIEWS_OPTIONS_GENERAL_PAGE_VIEW_H_
#define CHROME_BROWSER_VIEWS_OPTIONS_GENERAL_PAGE_VIEW_H_
+#include "chrome/browser/shell_integration.h"
#include "chrome/browser/views/options/options_page_view.h"
#include "chrome/browser/views/shelf_item_dialog.h"
#include "chrome/common/pref_member.h"
@@ -35,7 +36,8 @@ class GeneralPageView : public OptionsPageView,
public views::ButtonListener,
public views::Textfield::Controller,
public ShelfItemDialogDelegate,
- public views::TableViewObserver {
+ public views::TableViewObserver,
+ public ShellIntegration::DefaultBrowserObserver {
public:
explicit GeneralPageView(Profile* profile);
virtual ~GeneralPageView();
@@ -64,14 +66,9 @@ class GeneralPageView : public OptionsPageView,
virtual void Layout();
private:
- // The current default browser UI state
- enum DefaultBrowserUIState {
- STATE_PROCESSING,
- STATE_DEFAULT,
- STATE_NOT_DEFAULT
- };
+ // ShellIntegration::DefaultBrowserObserver implementation:
// Updates the UI state to reflect the current default browser state.
- void SetDefaultBrowserUIState(DefaultBrowserUIState state);
+ virtual void SetDefaultBrowserUIState(ShellIntegration::DefaultBrowserUIState state);
// Init all the dialog controls
void InitStartupGroup();
@@ -151,9 +148,7 @@ class GeneralPageView : public OptionsPageView,
views::NativeButton* default_browser_use_as_default_button_;
// The helper object that performs default browser set/check tasks.
- class DefaultBrowserWorker;
- friend DefaultBrowserWorker;
- scoped_refptr<DefaultBrowserWorker> default_browser_worker_;
+ scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
DISALLOW_COPY_AND_ASSIGN(GeneralPageView);
};