summaryrefslogtreecommitdiffstats
path: root/chrome/browser/browser.cc
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-12 01:19:57 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-12 01:19:57 +0000
commit36b6dcb9c49dba6a984c514d2b569355899b1ebb (patch)
tree926dce2a1250d90b08f517ef14db51979a96e026 /chrome/browser/browser.cc
parent7a9c86180d397bab57899cde12c598760cb34b47 (diff)
downloadchromium_src-36b6dcb9c49dba6a984c514d2b569355899b1ebb.zip
chromium_src-36b6dcb9c49dba6a984c514d2b569355899b1ebb.tar.gz
chromium_src-36b6dcb9c49dba6a984c514d2b569355899b1ebb.tar.bz2
Reorder browser.cc to match style guide, and remove browser_commands.cc
Review URL: http://codereview.chromium.org/10623 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5246 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/browser.cc')
-rw-r--r--chrome/browser/browser.cc2445
1 files changed, 1692 insertions, 753 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 911805d..8252350 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -8,35 +8,51 @@
#include <shellapi.h>
#include "base/command_line.h"
+#include "base/file_version_info.h"
#include "base/idle_timer.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/app/locales/locale_settings.h"
+#include "chrome/browser/automation/ui_controls.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/browser_url_handler.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/cert_store.h"
+#include "chrome/browser/character_encoding.h"
#include "chrome/browser/debugger/debugger_window.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/download/save_package.h"
#include "chrome/browser/frame_util.h"
+#include "chrome/browser/history_tab_ui.h"
+#include "chrome/browser/interstitial_page.h"
#include "chrome/browser/navigation_controller.h"
#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/options_window.h"
#include "chrome/browser/plugin_process_host.h"
#include "chrome/browser/plugin_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/ssl_error_info.h"
#include "chrome/browser/site_instance.h"
+#include "chrome/browser/task_manager.h"
#include "chrome/browser/url_fixer_upper.h"
#include "chrome/browser/user_metrics.h"
#include "chrome/browser/view_ids.h"
+#include "chrome/browser/views/about_chrome_view.h"
+#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/views/bookmark_manager_view.h"
+#include "chrome/browser/views/bug_report_view.h"
+#include "chrome/browser/views/clear_browsing_data.h"
#include "chrome/browser/views/download_shelf_view.h"
+#include "chrome/browser/views/download_tab_view.h"
#include "chrome/browser/views/go_button.h"
-#include "chrome/browser/views/bookmark_bar_view.h"
#include "chrome/browser/views/html_dialog_view.h"
+#include "chrome/browser/views/importer_view.h"
+#include "chrome/browser/views/keyword_editor_view.h"
#include "chrome/browser/views/location_bar_view.h"
+#include "chrome/browser/views/password_manager_view.h"
#include "chrome/browser/views/status_bubble.h"
#include "chrome/browser/views/tabs/tab_strip.h"
#include "chrome/browser/views/toolbar_star_toggle.h"
@@ -70,7 +86,7 @@ static const int kBrowserReleaseMemoryInterval = 30; // In seconds.
// windows.
static const int kWindowTilePixels = 20;
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
// A task to reduce the working set of the plugins.
class ReducePluginsWorkingSetTask : public Task {
@@ -110,14 +126,15 @@ class BrowserIdleTimer : public base::IdleTimer {
process.ReduceWorkingSet();
}
- // Handle the Plugin(s). We need to iterate through the plugin processes on
- // the IO thread because that thread manages the plugin process collection.
+ // Handle the Plugin(s). We need to iterate through the plugin processes
+ // on the IO thread because that thread manages the plugin process
+ // collection.
g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
new ReducePluginsWorkingSetTask());
}
};
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
struct Browser::UIUpdate {
UIUpdate(const TabContents* src, unsigned flags)
@@ -132,57 +149,8 @@ struct Browser::UIUpdate {
unsigned changed_flags;
};
-////////////////////////////////////////////////////////////////////////////////
-
-// static
-Browser* Browser::GetBrowserForController(
- const NavigationController* controller, int* index_result) {
- BrowserList::const_iterator it;
- for (it = BrowserList::begin(); it != BrowserList::end(); ++it) {
- int index = (*it)->tabstrip_model_.GetIndexOfController(controller);
- if (index != TabStripModel::kNoTab) {
- if (index_result)
- *index_result = index;
- return *it;
- }
- }
-
- return NULL;
-}
-
-// static
-void Browser::OpenNewBrowserWindow(Profile* profile, int show_command) {
- Browser* browser = new Browser(gfx::Rect(), show_command, profile,
- BrowserType::TABBED_BROWSER, L"");
- browser->AddBlankTab(true);
- browser->Show();
-}
-
-// static
-void Browser::RegisterPrefs(PrefService* prefs) {
- prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
- prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
-}
-
-// static
-void Browser::RegisterUserPrefs(PrefService* prefs) {
- prefs->RegisterStringPref(prefs::kHomePage, L"chrome-internal:");
- prefs->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
- prefs->RegisterIntegerPref(prefs::kCookieBehavior,
- net::CookiePolicy::ALLOW_ALL_COOKIES);
- prefs->RegisterBooleanPref(prefs::kShowHomeButton, false);
- prefs->RegisterStringPref(prefs::kRecentlySelectedEncoding, L"");
- // TODO(peterson): bug #3870 move this to the AutofillManager once it is
- // checked-in.
- prefs->RegisterBooleanPref(prefs::kFormAutofillEnabled, true);
- prefs->RegisterBooleanPref(prefs::kDeleteBrowsingHistory, true);
- prefs->RegisterBooleanPref(prefs::kDeleteDownloadHistory, true);
- prefs->RegisterBooleanPref(prefs::kDeleteCache, true);
- prefs->RegisterBooleanPref(prefs::kDeleteCookies, true);
- prefs->RegisterBooleanPref(prefs::kDeletePasswords, false);
- prefs->RegisterBooleanPref(prefs::kDeleteFormData, true);
- prefs->RegisterIntegerPref(prefs::kDeleteTimePeriod, 0);
-}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Constructors, Creation, Showing:
Browser::Browser(const gfx::Rect& initial_bounds,
int show_command,
@@ -311,146 +279,1312 @@ void Browser::Show() {
selected_tab_contents->RestoreFocus();
}
-void Browser::CloseFrame() {
- window_->Close();
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Creation Helpers:
+
+// static
+void Browser::OpenNewBrowserWindow(Profile* profile, int show_command) {
+ Browser* browser = new Browser(gfx::Rect(), show_command, profile,
+ BrowserType::TABBED_BROWSER, L"");
+ browser->AddBlankTab(true);
+ browser->Show();
}
-GURL Browser::GetHomePage() {
- if (profile_->GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage)) {
- return NewTabUIURL();
- } else {
- GURL home_page = GURL(URLFixerUpper::FixupURL(
- profile_->GetPrefs()->GetString(prefs::kHomePage),
- std::wstring()));
- if (!home_page.is_valid())
- return NewTabUIURL();
+// static
+void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) {
+ Profile* off_the_record_profile = profile->GetOffTheRecordProfile();
+ Browser* browser = BrowserList::FindBrowserWithType(
+ off_the_record_profile, BrowserType::TABBED_BROWSER);
+ if (browser == NULL) {
+ browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, off_the_record_profile,
+ BrowserType::TABBED_BROWSER, L"");
+ }
+ // TODO(eroman): should we have referrer here?
+ browser->AddTabWithURL(url, GURL(), PageTransition::LINK, true, NULL);
+ browser->Show();
+ browser->window()->Activate();
+}
- return home_page;
+// static
+void Browser::OpenWebApplication(Profile* profile,
+ WebApp* app,
+ int show_command) {
+ const std::wstring& app_name =
+ app->name().empty() ? ComputeApplicationNameFromURL(app->url()) :
+ app->name();
+
+ RegisterAppPrefs(app_name);
+ Browser* browser = new Browser(gfx::Rect(), show_command, profile,
+ BrowserType::APPLICATION, app_name);
+ browser->AddWebApplicationTab(profile, app, false);
+ browser->Show();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Command API:
+
+bool Browser::SupportsCommand(int id) const {
+ return controller_.SupportsCommand(id);
+}
+
+bool Browser::IsCommandEnabled(int id) const {
+ switch (id) {
+ case IDC_BACK: {
+ NavigationController* nc = GetSelectedNavigationController();
+ return nc ? nc->CanGoBack() : false;
+ }
+ case IDC_FORWARD: {
+ NavigationController* nc = GetSelectedNavigationController();
+ return nc ? nc->CanGoForward() : false;
+ }
+ case IDC_STOP: {
+ TabContents* current_tab = GetSelectedTabContents();
+ return (current_tab && current_tab->is_loading());
+ }
+ default:
+ return controller_.IsCommandEnabled(id);
}
}
-////////////////////////////////////////////////////////////////////////////////
-// Toolbar creation, management
+///////////////////////////////////////////////////////////////////////////////
+// Browser, DEPRECATED DEPRECATED DEPRECATED:
-LocationBarView* Browser::GetLocationBarView() const {
- return window_->GetLocationBarView();
+HWND Browser::GetTopLevelHWND() const {
+ return window_ ? reinterpret_cast<HWND>(window_->GetNativeHandle()) : NULL;
}
-////////////////////////////////////////////////////////////////////////////////
-// Chrome update coalescing
+///////////////////////////////////////////////////////////////////////////////
+// Browser, State Storage and Retrieval for UI:
-void Browser::UpdateToolBar(bool should_restore_state) {
- window_->UpdateToolbar(GetSelectedTabContents(), should_restore_state);
+void Browser::SaveWindowPosition(const gfx::Rect& bounds, bool maximized) {
+ // We don't save window position for popups.
+ if (type() == BrowserType::BROWSER)
+ return;
+
+ // First save to local state, this is for remembering on subsequent starts.
+ PrefService* prefs = g_browser_process->local_state();
+ DCHECK(prefs);
+ std::wstring name(prefs::kBrowserWindowPlacement);
+ if (!app_name_.empty()) {
+ name.append(L"_");
+ name.append(app_name_);
+ }
+
+ DictionaryValue* win_pref = prefs->GetMutableDictionary(name.c_str());
+ DCHECK(win_pref);
+ win_pref->SetInteger(L"top", bounds.y());
+ win_pref->SetInteger(L"left", bounds.x());
+ win_pref->SetInteger(L"bottom", bounds.bottom());
+ win_pref->SetInteger(L"right", bounds.right());
+ win_pref->SetBoolean(L"maximized", maximized);
+
+ // Then save to the session storage service, used when reloading a past
+ // session. Note that we don't want to be the ones who cause lazy
+ // initialization of the session service. This function gets called during
+ // initial window showing, and we don't want to bring in the session service
+ // this early.
+ if (profile()->HasSessionService()) {
+ SessionService* session_service = profile()->GetSessionService();
+ if (session_service)
+ session_service->SetWindowBounds(session_id_, bounds, maximized);
+ }
}
-void Browser::ScheduleUIUpdate(const TabContents* source,
- unsigned changed_flags) {
- // Synchronously update the URL.
- if (changed_flags & TabContents::INVALIDATE_URL &&
- source == GetSelectedTabContents()) {
- // Only update the URL for the current tab. Note that we do not update
- // the navigation commands since those would have already been updated
- // synchronously by NavigationStateChanged.
- UpdateToolBar(false);
+void Browser::RestoreWindowPosition(gfx::Rect* bounds, bool* maximized) {
+ DCHECK(bounds && maximized);
+ WindowSizer::GetBrowserWindowBounds(app_name_, *bounds, bounds, maximized);
+}
- if (changed_flags == TabContents::INVALIDATE_URL)
- return; // Just had an update URL and nothing else.
+SkBitmap Browser::GetCurrentPageIcon() const {
+ TabContents* contents = tabstrip_model_.GetSelectedTabContents();
+ return contents ? contents->GetFavIcon() : SkBitmap();
+}
+
+std::wstring Browser::GetCurrentPageTitle() const {
+ TabContents* contents = tabstrip_model_.GetSelectedTabContents();
+ std::wstring title;
+ if (contents) {
+ title = contents->GetTitle();
+ FormatTitleForDisplay(&title);
}
+ if (title.empty())
+ title = l10n_util::GetString(IDS_TAB_UNTITLED_TITLE);
- // Save the dirty bits.
- scheduled_updates_.push_back(UIUpdate(source, changed_flags));
+ return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, title);
+}
- if (chrome_updater_factory_.empty()) {
- // No task currently scheduled, start another.
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- chrome_updater_factory_.NewRunnableMethod(
- &Browser::ProcessPendingUIUpdates),
- kUIUpdateCoalescingTimeMS);
+// static
+void Browser::FormatTitleForDisplay(std::wstring* title) {
+ size_t current_index = 0;
+ size_t match_index;
+ while ((match_index = title->find(L'\n', current_index)) !=
+ std::wstring::npos) {
+ title->replace(match_index, 1, L"");
+ current_index = match_index;
}
}
-void Browser::ProcessPendingUIUpdates() {
-#ifndef NDEBUG
- // Validate that all tabs we have pending updates for exist. This is scary
- // because the pending list must be kept in sync with any detached or
- // deleted tabs. This code does not dereference any TabContents pointers.
- for (size_t i = 0; i < scheduled_updates_.size(); i++) {
- bool found = false;
- for (int tab = 0; tab < tab_count(); tab++) {
- if (GetTabContentsAt(tab)->controller() ==
- scheduled_updates_[i].source->controller()) {
- found = true;
- break;
+///////////////////////////////////////////////////////////////////////////////
+// Browser, OnBeforeUnload handling:
+
+bool Browser::ShouldCloseWindow() {
+ if (HasCompletedUnloadProcessing()) {
+ return true;
+ }
+ is_attempting_to_close_browser_ = true;
+
+ for (int i = 0; i < tab_count(); ++i) {
+ if (tabstrip_model_.TabHasUnloadListener(i)) {
+ TabContents* tab = GetTabContentsAt(i);
+ tabs_needing_before_unload_fired_.push_back(tab);
+ }
+ }
+
+ if (tabs_needing_before_unload_fired_.empty())
+ return true;
+
+ ProcessPendingTabs();
+ return false;
+}
+
+void Browser::OnWindowClosing() {
+ if (!ShouldCloseWindow())
+ return;
+
+ if (BrowserList::size() == 1)
+ browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE);
+
+ // Don't use HasSessionService here, we want to force creation of the
+ // session service so that user can restore what was open.
+ SessionService* session_service = profile()->GetSessionService();
+ if (session_service)
+ session_service->WindowClosing(session_id());
+
+ CloseAllTabs();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Browser, TabStripModel pass-thrus:
+
+NavigationController* Browser::GetSelectedNavigationController() const {
+ TabContents* tc = GetSelectedTabContents();
+ if (tc)
+ return tc->controller();
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Tab adding/showing functions:
+
+TabContents* Browser::AddTabWithURL(
+ const GURL& url, const GURL& referrer, PageTransition::Type transition,
+ bool foreground, SiteInstance* instance) {
+ if (type_ == BrowserType::APPLICATION && tabstrip_model_.count() == 1) {
+ NOTREACHED() << "Cannot add a tab in a mono tab application.";
+ return NULL;
+ }
+
+ GURL url_to_load = url;
+ if (url_to_load.is_empty())
+ url_to_load = GetHomePage();
+ TabContents* contents =
+ CreateTabContentsForURL(url_to_load, referrer, profile_, transition,
+ false, instance);
+ tabstrip_model_.AddTabContents(contents, -1, transition, foreground);
+ // By default, content believes it is not hidden. When adding contents
+ // in the background, tell it that it's hidden.
+ if (!foreground)
+ contents->WasHidden();
+ return contents;
+}
+
+TabContents* Browser::AddWebApplicationTab(Profile* profile,
+ WebApp* web_app,
+ bool lazy) {
+ DCHECK(web_app);
+
+ // TODO(acw): Do we need an "application launched" transition type?
+ // TODO(creis): Should we reuse the current instance (ie. process) here?
+ TabContents* contents =
+ CreateTabContentsForURL(web_app->url(), GURL(), profile,
+ PageTransition::LINK, lazy, NULL);
+ if (contents->AsWebContents())
+ contents->AsWebContents()->SetWebApp(web_app);
+
+ if (lazy) {
+ contents->controller()->LoadURLLazily(
+ web_app->url(), GURL(), PageTransition::LINK, web_app->name(), NULL);
+ }
+ tabstrip_model_.AddTabContents(contents, -1, PageTransition::LINK, !lazy);
+ return contents;
+}
+
+TabContents* Browser::AddTabWithNavigationController(
+ NavigationController* ctrl, PageTransition::Type type) {
+ TabContents* tc = ctrl->active_contents();
+ tabstrip_model_.AddTabContents(tc, -1, type, true);
+ return tc;
+}
+
+NavigationController* Browser::AddRestoredTab(
+ const std::vector<TabNavigation>& navigations,
+ int tab_index,
+ int selected_navigation,
+ bool select) {
+ NavigationController* restored_controller =
+ BuildRestoredNavigationController(navigations, selected_navigation);
+
+ tabstrip_model_.InsertTabContentsAt(
+ tab_index,
+ restored_controller->active_contents(),
+ select, false);
+ if (profile_->HasSessionService()) {
+ SessionService* session_service = profile_->GetSessionService();
+ if (session_service)
+ session_service->TabRestored(restored_controller);
+ }
+ return restored_controller;
+}
+
+void Browser::ReplaceRestoredTab(
+ const std::vector<TabNavigation>& navigations,
+ int selected_navigation) {
+ NavigationController* restored_controller =
+ BuildRestoredNavigationController(navigations, selected_navigation);
+
+ tabstrip_model_.ReplaceNavigationControllerAt(
+ tabstrip_model_.selected_index(),
+ restored_controller);
+}
+
+void Browser::ShowNativeUITab(const GURL& url) {
+ int i, c;
+ TabContents* tc;
+ for (i = 0, c = tabstrip_model_.count(); i < c; ++i) {
+ tc = tabstrip_model_.GetTabContentsAt(i);
+ if (tc->type() == TAB_CONTENTS_NATIVE_UI &&
+ tc->GetURL() == url) {
+ tabstrip_model_.SelectTabContentsAt(i, false);
+ return;
+ }
+ }
+
+ TabContents* contents = CreateTabContentsForURL(url, GURL(), profile_,
+ PageTransition::LINK, false,
+ NULL);
+ AddNewContents(NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Assorted browser commands:
+
+void Browser::GoBack() {
+ // If we are showing an interstitial, just hide it.
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab) {
+ WebContents* web_contents = current_tab->AsWebContents();
+ if (web_contents && web_contents->showing_interstitial_page()) {
+ // Pressing back on an interstitial page means "don't proceed".
+ web_contents->interstitial_page()->DontProceed();
+ return;
+ }
+ }
+ NavigationController* nc = GetSelectedNavigationController();
+ if (nc && nc->CanGoBack())
+ nc->GoBack();
+}
+
+void Browser::GoForward() {
+ NavigationController* nc = GetSelectedNavigationController();
+ if (nc && nc->CanGoForward())
+ nc->GoForward();
+}
+
+void Browser::Reload() {
+ // If we are showing an interstitial, treat this as an OpenURL.
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab) {
+ WebContents* web_contents = current_tab->AsWebContents();
+ if (web_contents && web_contents->showing_interstitial_page()) {
+ NavigationEntry* entry = current_tab->controller()->GetActiveEntry();
+ DCHECK(entry); // Should exist if interstitial is showing.
+ OpenURL(entry->url(), GURL(), CURRENT_TAB, PageTransition::RELOAD);
+ return;
+ }
+ }
+
+ if (current_tab) {
+ // As this is caused by a user action, give the focus to the page.
+ current_tab->Focus();
+ current_tab->controller()->Reload(true);
+ }
+}
+
+void Browser::Stop() {
+ // TODO(mpcomplete): make this more abstracted.
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab && current_tab->AsWebContents())
+ current_tab->AsWebContents()->Stop();
+}
+
+void Browser::Home() {
+ GURL homepage_url = GetHomePage();
+ GetSelectedTabContents()->controller()->LoadURL(
+ homepage_url, GURL(), PageTransition::AUTO_BOOKMARK);
+}
+
+void Browser::FocusLocationBar() {
+ LocationBarView* location_bar = GetLocationBarView();
+ if (location_bar)
+ location_bar->location_entry()->SetFocus();
+}
+
+void Browser::BookmarkCurrentPage() {
+ TabContents* tab = GetSelectedTabContents();
+ if (!tab || !tab->AsWebContents())
+ return;
+
+ WebContents* rvh = tab->AsWebContents();
+ BookmarkModel* model = tab->profile()->GetBookmarkModel();
+ if (!model || !model->IsLoaded())
+ return; // Ignore requests until bookmarks are loaded.
+
+ NavigationEntry* entry = rvh->controller()->GetActiveEntry();
+ if (!entry)
+ return; // Can't star if there is no URL.
+ const GURL& url = entry->display_url();
+ if (url.is_empty() || !url.is_valid())
+ return;
+
+ if (window_->GetStarButton()) {
+ if (!window_->GetStarButton()->is_bubble_showing()) {
+ const bool newly_bookmarked = !model->IsBookmarked(url);
+ if (newly_bookmarked) {
+ model->SetURLStarred(url, entry->title(), true);
+ if (!model->IsBookmarked(url)) {
+ // Starring failed. This shouldn't happen.
+ NOTREACHED();
+ return;
+ }
}
+ window_->GetStarButton()->ShowStarBubble(url, newly_bookmarked);
}
- DCHECK(found);
+ } else if (model->IsBookmarked(url)) {
+ // If we can't find the star button and the user wanted to unstar it,
+ // go ahead and unstar it without showing the bubble.
+ model->SetURLStarred(url, std::wstring(), false);
+ }
+}
+
+void Browser::OpenDebuggerWindow() {
+#ifndef CHROME_DEBUGGER_DISABLED
+ TabContents* current_tab = GetSelectedTabContents();
+ if (!current_tab)
+ return;
+
+ if (current_tab->AsWebContents()) {
+ // Only one debugger instance can exist at a time right now.
+ // TODO(erikkay): need an alert, dialog, something
+ // or better yet, fix the one instance limitation
+ if (!DebuggerWindow::DoesDebuggerExist()) {
+ debugger_window_ = new DebuggerWindow();
+ }
+ debugger_window_->Show(current_tab);
}
#endif
+}
- chrome_updater_factory_.RevokeAll();
+void Browser::OpenFindInPageWindow() {
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab && current_tab->AsWebContents())
+ current_tab->AsWebContents()->view()->FindInPage(*this, false, false);
+}
- // We could have many updates for the same thing in the queue. This map tracks
- // the bits of the stuff we've already updated for each TabContents so we
- // don't update again.
- typedef std::map<const TabContents*, unsigned> UpdateTracker;
- UpdateTracker updated_stuff;
+void Browser::AdvanceFindSelection(bool forward_direction) {
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab && current_tab->AsWebContents()) {
+ current_tab->AsWebContents()->view()->FindInPage(*this, true,
+ forward_direction);
+ }
+}
- for (size_t i = 0; i < scheduled_updates_.size(); i++) {
- // Do not dereference |contents|, it may be out-of-date!
- const TabContents* contents = scheduled_updates_[i].source;
- unsigned flags = scheduled_updates_[i].changed_flags;
+void Browser::ConvertToTabbedBrowser() {
+ if (type() != BrowserType::BROWSER) {
+ NOTREACHED();
+ return;
+ }
- // Remove any bits we have already updated, and save the new bits.
- UpdateTracker::iterator updated = updated_stuff.find(contents);
- if (updated != updated_stuff.end()) {
- // Turn off bits already set.
- flags &= ~updated->second;
- if (!flags)
- continue;
+ int tab_strip_index = tabstrip_model_.selected_index();
+ TabContents* contents = tabstrip_model_.DetachTabContentsAt(tab_strip_index);
+ Browser* browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_,
+ BrowserType::TABBED_BROWSER, L"");
+ browser->AddNewContents(
+ NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true);
+ browser->Show();
+}
- updated->second |= flags;
- } else {
- updated_stuff[contents] = flags;
+void Browser::OpenKeywordEditor() {
+ KeywordEditorView::Show(profile());
+}
+
+void Browser::OpenClearBrowsingDataDialog() {
+ views::Window::CreateChromeWindow(
+ GetTopLevelHWND(),
+ gfx::Rect(),
+ new ClearBrowsingDataView(profile_))->Show();
+}
+
+void Browser::OpenImportSettingsDialog() {
+ views::Window::CreateChromeWindow(GetTopLevelHWND(), gfx::Rect(),
+ new ImporterView(profile_))->Show();
+}
+
+void Browser::OpenBugReportDialog() {
+ // Retrieve the URL for the current tab (if any) and tell the BugReportView
+ TabContents* current_tab = GetSelectedTabContents();
+ if (!current_tab)
+ return;
+
+ BugReportView* bug_report_view = new BugReportView(profile_, current_tab);
+
+ if (current_tab->controller()->GetLastCommittedEntry()) {
+ if (current_tab->type() == TAB_CONTENTS_WEB) {
+ // URL for the current page
+ bug_report_view->SetUrl(
+ current_tab->controller()->GetActiveEntry()->url());
}
+ }
- // Updates to the title or favicon require a tab repaint. However, the
- // inverse is not true since updates to the title also update the window
- // title.
- bool invalidate_tab = false;
- if (flags & TabContents::INVALIDATE_TITLE ||
- flags & TabContents::INVALIDATE_FAVICON) {
- invalidate_tab = true;
+ // retrieve the application version info
+ std::wstring version;
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+ if (version_info.get()) {
+ version = version_info->product_name() + L" - " +
+ version_info->file_version() +
+ L" (" + version_info->last_change() + L")";
+ }
+ bug_report_view->set_version(version);
- // Anything that repaints the tab means the favicon is updated.
- updated_stuff[contents] |= TabContents::INVALIDATE_FAVICON;
+ // Grab an exact snapshot of the window that the user is seeing (i.e. as
+ // rendered--do not re-render, and include windowed plugins)
+ std::vector<unsigned char> *screenshot_png = new std::vector<unsigned char>;
+ win_util::GrabWindowSnapshot(GetTopLevelHWND(), screenshot_png);
+ // the BugReportView takes ownership of the png data, and will dispose of
+ // it in its destructor.
+ bug_report_view->set_png_data(screenshot_png);
+
+ // Create and show the dialog
+ views::Window::CreateChromeWindow(GetTopLevelHWND(), gfx::Rect(),
+ bug_report_view)->Show();
+}
+
+void Browser::CopyCurrentURLToClipBoard() {
+ TabContents* tc = GetSelectedTabContents();
+ DCHECK(tc);
+
+ std::string url = tc->GetURL().spec();
+
+ if (!::OpenClipboard(NULL)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (::EmptyClipboard()) {
+ HGLOBAL text = ::GlobalAlloc(GMEM_MOVEABLE, url.size() + 1);
+ LPSTR ptr = static_cast<LPSTR>(::GlobalLock(text));
+ memcpy(ptr, url.c_str(), url.size());
+ ptr[url.size()] = '\0';
+ ::GlobalUnlock(text);
+
+ ::SetClipboardData(CF_TEXT, text);
+ }
+
+ if (!::CloseClipboard()) {
+ NOTREACHED();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// static
+void Browser::RegisterPrefs(PrefService* prefs) {
+ prefs->RegisterDictionaryPref(prefs::kBrowserWindowPlacement);
+ prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
+}
+
+// static
+void Browser::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterStringPref(prefs::kHomePage, L"chrome-internal:");
+ prefs->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
+ prefs->RegisterIntegerPref(prefs::kCookieBehavior,
+ net::CookiePolicy::ALLOW_ALL_COOKIES);
+ prefs->RegisterBooleanPref(prefs::kShowHomeButton, false);
+ prefs->RegisterStringPref(prefs::kRecentlySelectedEncoding, L"");
+ // TODO(peterson): bug #3870 move this to the AutofillManager once it is
+ // checked-in.
+ prefs->RegisterBooleanPref(prefs::kFormAutofillEnabled, true);
+ prefs->RegisterBooleanPref(prefs::kDeleteBrowsingHistory, true);
+ prefs->RegisterBooleanPref(prefs::kDeleteDownloadHistory, true);
+ prefs->RegisterBooleanPref(prefs::kDeleteCache, true);
+ prefs->RegisterBooleanPref(prefs::kDeleteCookies, true);
+ prefs->RegisterBooleanPref(prefs::kDeletePasswords, false);
+ prefs->RegisterBooleanPref(prefs::kDeleteFormData, true);
+ prefs->RegisterIntegerPref(prefs::kDeleteTimePeriod, 0);
+}
+
+// static
+Browser* Browser::GetBrowserForController(
+ const NavigationController* controller, int* index_result) {
+ BrowserList::const_iterator it;
+ for (it = BrowserList::begin(); it != BrowserList::end(); ++it) {
+ int index = (*it)->tabstrip_model_.GetIndexOfController(controller);
+ if (index != TabStripModel::kNoTab) {
+ if (index_result)
+ *index_result = index;
+ return *it;
}
+ }
- // Updating the URL happens synchronously in ScheduleUIUpdate.
+ return NULL;
+}
- if (flags & TabContents::INVALIDATE_LOAD)
- GetStatusBubble()->SetStatus(GetSelectedTabContents()->GetStatusText());
+///////////////////////////////////////////////////////////////////////////////
+// Browser, CommandHandler implementation:
- if (invalidate_tab) { // INVALIDATE_TITLE or INVALIDATE_FAVICON.
- tabstrip_model_.UpdateTabContentsStateAt(
- tabstrip_model_.GetIndexOfController(contents->controller()));
- window_->UpdateTitleBar();
+void Browser::ExecuteCommand(int id) {
+ if (!IsCommandEnabled(id)) {
+ NOTREACHED() << id;
+ return;
+ }
+ // This might happen during QMU testing.
+ if (!GetSelectedTabContents())
+ return;
- if (contents == GetSelectedTabContents()) {
- TabContents* current_tab = GetSelectedTabContents();
- controller_.UpdateCommandEnabled(IDC_CREATE_SHORTCUT,
- current_tab->type() == TAB_CONTENTS_WEB &&
- !current_tab->GetFavIcon().isNull());
+ switch (id) {
+ case IDC_BACK:
+ UserMetrics::RecordAction(L"Back", profile_);
+ GoBack();
+ break;
+
+ case IDC_FORWARD:
+ UserMetrics::RecordAction(L"Forward", profile_);
+ GoForward();
+ break;
+
+ case IDC_RELOAD:
+ UserMetrics::RecordAction(L"Reload", profile_);
+ Reload();
+ break;
+
+ case IDC_HOME:
+ UserMetrics::RecordAction(L"Home", profile_);
+ Home();
+ break;
+
+ case IDC_STOP:
+ UserMetrics::RecordAction(L"Stop", profile_);
+ Stop();
+ break;
+
+ case IDC_GO:
+ UserMetrics::RecordAction(L"Go", profile_);
+ {
+ LocationBarView* lbv = GetLocationBarView();
+ if (lbv)
+ lbv->location_entry()->model()->AcceptInput(CURRENT_TAB, false);
+ }
+ break;
+
+ case IDC_NEWTAB:
+ UserMetrics::RecordAction(L"NewTab", profile_);
+ if (type() == BrowserType::TABBED_BROWSER) {
+ AddBlankTab(true);
+ } else {
+ Browser* b = GetOrCreateTabbedBrowser();
+ DCHECK(b);
+ b->Show();
+ b->window()->Activate();
+ b->AddBlankTab(true);
+ }
+ break;
+
+ case IDC_CLOSE_WEB_APP:
+ UserMetrics::RecordAction(L"CloseWebApp", profile_);
+ tabstrip_model_.CloseTabContentsAt(tabstrip_model_.selected_index());
+ break;
+
+ case IDC_CLOSETAB:
+ UserMetrics::RecordAction(L"CloseTab_Accelerator", profile_);
+ tabstrip_model_.CloseTabContentsAt(tabstrip_model_.selected_index());
+ break;
+
+ case IDC_NEWWINDOW:
+ UserMetrics::RecordAction(L"NewWindow", profile_);
+ Browser::OpenNewBrowserWindow(profile_->GetOriginalProfile(),
+ SW_SHOWNORMAL);
+ break;
+
+ case IDC_CLOSEWINDOW:
+ UserMetrics::RecordAction(L"CloseWindow", profile_);
+ window_->Close();
+ break;
+
+ case IDC_FOCUS_LOCATION:
+ UserMetrics::RecordAction(L"FocusLocation", profile_);
+ {
+ LocationBarView* lbv = GetLocationBarView();
+ if (lbv) {
+ AutocompleteEditView* aev = lbv->location_entry();
+ aev->SetFocus();
+ aev->SelectAll(true);
+ }
+ }
+ break;
+
+ case IDC_FOCUS_SEARCH:
+ UserMetrics::RecordAction(L"FocusSearch", profile_);
+ {
+ LocationBarView* lbv = GetLocationBarView();
+ if (lbv) {
+ AutocompleteEditView* aev = lbv->location_entry();
+ aev->SetUserText(L"?");
+ aev->SetFocus();
+ }
+ }
+ break;
+
+ case IDC_FOCUS_TOOLBAR:
+ UserMetrics::RecordAction(L"FocusToolbar", profile_);
+ {
+ window_->FocusToolbar();
+ }
+ break;
+
+ case IDC_STAR:
+ UserMetrics::RecordAction(L"Star", profile_);
+ BookmarkCurrentPage();
+ break;
+
+ case IDC_OPENURL:
+ UserMetrics::RecordAction(L"LoadURL", profile_);
+ {
+ LocationBarView* lbv = GetLocationBarView();
+ if (lbv) {
+ OpenURL(GURL(lbv->location_input()), GURL(), lbv->disposition(),
+ lbv->transition());
+ } else {
+ OpenURL(GURL(), GURL(), CURRENT_TAB, PageTransition::TYPED);
+ }
+ }
+ break;
+
+ // TODO(devint): http://b/issue?id=1117225 Cut, Copy, and Paste are always
+ // enabled in the page menu regardless of whether the command will do
+ // anything. When someone selects the menu item, we just act as if they hit
+ // the keyboard shortcut for the command by sending the associated key press
+ // to windows. The real fix to this bug is to disable the commands when they
+ // won't do anything. We'll need something like an overall clipboard command
+ // manager to do that.
+ case IDC_CUT:
+ UserMetrics::RecordAction(L"Cut", profile_);
+ ui_controls::SendKeyPress(L'X', true, false, false);
+ break;
+
+ case IDC_COPY:
+ UserMetrics::RecordAction(L"Copy", profile_);
+ ui_controls::SendKeyPress(L'C', true, false, false);
+ break;
+
+ case IDC_PASTE:
+ UserMetrics::RecordAction(L"Paste", profile_);
+ ui_controls::SendKeyPress(L'V', true, false, false);
+ break;
+
+ case IDC_FIND:
+ UserMetrics::RecordAction(L"Find", profile_);
+ OpenFindInPageWindow();
+ break;
+
+ case IDC_FIND_NEXT:
+ UserMetrics::RecordAction(L"FindNext", profile_);
+ AdvanceFindSelection(true);
+ break;
+
+ case IDC_FIND_PREVIOUS:
+ UserMetrics::RecordAction(L"FindPrevious", profile_);
+ AdvanceFindSelection(false);
+ break;
+
+ case IDS_COMMANDS_REPORTBUG:
+ UserMetrics::RecordAction(L"ReportBug", profile_);
+ OpenBugReportDialog();
+ break;
+
+ case IDC_SELECT_NEXT_TAB:
+ UserMetrics::RecordAction(L"SelectNextTab", profile_);
+ tabstrip_model_.SelectNextTab();
+ break;
+
+ case IDC_SELECT_PREV_TAB:
+ UserMetrics::RecordAction(L"SelectPrevTab", profile_);
+ tabstrip_model_.SelectPreviousTab();
+ break;
+
+ case IDC_SELECT_TAB_0:
+ case IDC_SELECT_TAB_1:
+ case IDC_SELECT_TAB_2:
+ case IDC_SELECT_TAB_3:
+ case IDC_SELECT_TAB_4:
+ case IDC_SELECT_TAB_5:
+ case IDC_SELECT_TAB_6:
+ case IDC_SELECT_TAB_7: {
+ int new_index = id - IDC_SELECT_TAB_0;
+ if (new_index < tab_count()) {
+ tabstrip_model_.SelectTabContentsAt(new_index, true);
+ UserMetrics::RecordAction(L"SelectNumberedTab", profile_);
}
+ break;
}
- // We don't need to process INVALIDATE_STATE, since that's not visible.
+ case IDC_SELECT_LAST_TAB:
+ UserMetrics::RecordAction(L"SelectLastTab", profile_);
+ tabstrip_model_.SelectLastTab();
+ break;
+
+ case IDC_VIEWSOURCE: {
+ UserMetrics::RecordAction(L"ViewSource", profile_);
+
+ TabContents* current_tab = GetSelectedTabContents();
+ NavigationEntry* entry =
+ current_tab->controller()->GetLastCommittedEntry();
+ if (entry) {
+ GURL url("view-source:" + entry->url().spec());
+ AddTabWithURL(url, GURL(), PageTransition::LINK, true, NULL);
+ }
+ break;
+ }
+
+ case IDC_SHOW_JS_CONSOLE: {
+ UserMetrics::RecordAction(L"ShowJSConsole", profile_);
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab && current_tab->AsWebContents()) {
+ WebContents* wc = current_tab->AsWebContents();
+ wc->render_view_host()->ShowJavaScriptConsole();
+ }
+ break;
+ }
+
+ case IDC_CREATE_SHORTCUT: {
+ UserMetrics::RecordAction(L"CreateShortcut", profile_);
+ WebContents* contents = this->GetSelectedTabContents()->AsWebContents();
+ if (contents)
+ contents->CreateShortcut();
+ break;
+ }
+
+ case IDC_GOOFFTHERECORD: {
+ Browser::OpenNewBrowserWindow(profile_->GetOffTheRecordProfile(),
+ SW_SHOWNORMAL);
+ break;
+ }
+
+ case IDC_VIEW_PASSWORDS: {
+ PasswordManagerView::Show(profile_);
+ break;
+ }
+
+ case IDC_IMPORT_SETTINGS: {
+ UserMetrics::RecordAction(L"Import_ShowDlg", profile_);
+ OpenImportSettingsDialog();
+ break;
+ }
+
+ case IDC_CLEAR_BROWSING_DATA: {
+ UserMetrics::RecordAction(L"ClearBrowsingData_ShowDlg", profile_);
+ OpenClearBrowsingDataDialog();
+ break;
+ }
+
+ case IDC_ABOUT: {
+ UserMetrics::RecordAction(L"AboutChrome", profile_);
+ views::Window::CreateChromeWindow(
+ GetTopLevelHWND(),
+ gfx::Rect(),
+ new AboutChromeView(profile_))->Show();
+ break;
+ }
+
+ case IDC_EDIT_SEARCH_ENGINES: {
+ UserMetrics::RecordAction(L"EditSearchEngines", profile_);
+ OpenKeywordEditor();
+ break;
+ }
+
+ case IDC_ZOOM_PLUS: {
+ UserMetrics::RecordAction(L"ZoomPlus", profile_);
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab->AsWebContents()) {
+ current_tab->AsWebContents()->render_view_host()->Zoom(
+ PageZoom::LARGER);
+ }
+ break;
+ }
+
+ case IDC_ZOOM_MINUS: {
+ UserMetrics::RecordAction(L"ZoomMinus", profile_);
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab->AsWebContents()) {
+ current_tab->AsWebContents()->render_view_host()->Zoom(
+ PageZoom::SMALLER);
+ }
+ break;
+ }
+
+ case IDC_ZOOM_NORMAL: {
+ UserMetrics::RecordAction(L"ZoomNormal", profile_);
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab->AsWebContents()) {
+ current_tab->AsWebContents()->render_view_host()->Zoom(
+ PageZoom::STANDARD);
+ }
+ break;
+ }
+
+ case IDC_OPENFILE: {
+ UserMetrics::RecordAction(L"OpenFile", profile_);
+ if (!select_file_dialog_.get())
+ select_file_dialog_ = SelectFileDialog::Create(this);
+ select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
+ L"", L"", GetTopLevelHWND(), NULL);
+ break;
+ }
+
+ case IDC_TASKMANAGER:
+ UserMetrics::RecordAction(L"TaskManager", profile_);
+ TaskManager::Open();
+ break;
+
+ case IDC_CLOSEPOPUPS:
+ UserMetrics::RecordAction(L"CloseAllSuppressedPopups", profile_);
+ GetSelectedTabContents()->CloseAllSuppressedPopups();
+ break;
+
+ case IDC_PRINT: {
+ UserMetrics::RecordAction(L"PrintPreview", profile_);
+ WebContents* const web_contents =
+ GetSelectedTabContents()->AsWebContents();
+ DCHECK(web_contents);
+ web_contents->PrintPreview();
+ break;
+ }
+
+ case IDC_COPY_URL:
+ UserMetrics::RecordAction(L"CopyURLToClipBoard", profile_);
+ CopyCurrentURLToClipBoard();
+ break;
+
+ case IDC_SAVEPAGE: {
+ UserMetrics::RecordAction(L"SavePage", profile_);
+ TabContents* current_tab = GetSelectedTabContents();
+ if (current_tab) {
+ WebContents* web_tab = current_tab->AsWebContents();
+ DCHECK(web_tab);
+ web_tab->OnSavePage();
+ }
+ break;
+ }
+
+ case IDC_ENCODING_AUTO_DETECT: {
+ UserMetrics::RecordAction(L"AutoDetectChange", profile_);
+ encoding_auto_detect_.SetValue(!encoding_auto_detect_.GetValue());
+ // Reload the page so we can try to auto-detect the charset.
+ Reload();
+ break;
+ }
+
+ case IDC_ENCODING_UTF8:
+ case IDC_ENCODING_UTF16LE:
+ case IDC_ENCODING_ISO88591:
+ case IDC_ENCODING_WINDOWS1252:
+ case IDC_ENCODING_GB2312:
+ case IDC_ENCODING_GB18030:
+ case IDC_ENCODING_BIG5HKSCS:
+ case IDC_ENCODING_BIG5:
+ case IDC_ENCODING_KOREAN:
+ case IDC_ENCODING_SHIFTJIS:
+ case IDC_ENCODING_ISO2022JP:
+ case IDC_ENCODING_EUCJP:
+ case IDC_ENCODING_THAI:
+ case IDC_ENCODING_ISO885915:
+ case IDC_ENCODING_MACINTOSH:
+ case IDC_ENCODING_ISO88592:
+ case IDC_ENCODING_WINDOWS1250:
+ case IDC_ENCODING_ISO88595:
+ case IDC_ENCODING_WINDOWS1251:
+ case IDC_ENCODING_KOI8R:
+ case IDC_ENCODING_KOI8U:
+ case IDC_ENCODING_ISO88597:
+ case IDC_ENCODING_WINDOWS1253:
+ case IDC_ENCODING_ISO88594:
+ case IDC_ENCODING_ISO885913:
+ case IDC_ENCODING_WINDOWS1257:
+ case IDC_ENCODING_ISO88593:
+ case IDC_ENCODING_ISO885910:
+ case IDC_ENCODING_ISO885914:
+ case IDC_ENCODING_ISO885916:
+ case IDC_ENCODING_ISO88599:
+ case IDC_ENCODING_WINDOWS1254:
+ case IDC_ENCODING_ISO88596:
+ case IDC_ENCODING_WINDOWS1256:
+ case IDC_ENCODING_ISO88598:
+ case IDC_ENCODING_WINDOWS1255:
+ case IDC_ENCODING_WINDOWS1258: {
+ UserMetrics::RecordAction(L"OverrideEncoding", profile_);
+ const std::wstring selected_encoding =
+ CharacterEncoding::GetCanonicalEncodingNameByCommandId(id);
+ TabContents* current_tab = GetSelectedTabContents();
+ if (!selected_encoding.empty() && current_tab &&
+ current_tab->AsWebContents())
+ current_tab->AsWebContents()->override_encoding(selected_encoding);
+ // Update the list of recently selected encodings.
+ std::wstring new_selected_encoding_list;
+ if (CharacterEncoding::UpdateRecentlySelectdEncoding(
+ profile_->GetPrefs()->GetString(prefs::kRecentlySelectedEncoding),
+ id,
+ &new_selected_encoding_list))
+ profile_->GetPrefs()->SetString(prefs::kRecentlySelectedEncoding,
+ new_selected_encoding_list);
+ break;
+ }
+
+ case IDC_DUPLICATE:
+ UserMetrics::RecordAction(L"Duplicate", profile_);
+ DuplicateContentsAt(selected_index());
+ break;
+
+ case IDC_SHOW_BOOKMARKS_BAR:
+ UserMetrics::RecordAction(L"ShowBookmarksBar", profile_);
+ BookmarkBarView::ToggleWhenVisible(profile_);
+ break;
+
+ case IDC_SHOW_BOOKMARK_MANAGER:
+ UserMetrics::RecordAction(L"ShowBookmarkManager", profile_);
+ BookmarkManagerView::Show(profile_);
+ break;
+
+ case IDC_SHOW_HISTORY:
+ UserMetrics::RecordAction(L"ShowHistory", profile_);
+ ShowNativeUITab(HistoryTabUI::GetURL());
+ break;
+
+ case IDC_SHOW_DOWNLOADS:
+ UserMetrics::RecordAction(L"ShowDownloads", profile_);
+ ShowNativeUITab(DownloadTabUI::GetURL());
+ break;
+
+ case IDC_OPTIONS:
+ UserMetrics::RecordAction(L"ShowOptions", profile_);
+ ShowOptionsWindow(OPTIONS_PAGE_DEFAULT, OPTIONS_GROUP_NONE, profile_);
+ break;
+
+ case IDC_DEBUGGER:
+ UserMetrics::RecordAction(L"Debugger", profile_);
+ OpenDebuggerWindow();
+ break;
+
+ case IDC_SHOW_AS_TAB:
+ UserMetrics::RecordAction(L"ShowAsTab", profile_);
+ ConvertToTabbedBrowser();
+ break;
+
+ case IDC_RESTORE_TAB: {
+ UserMetrics::RecordAction(L"RestoreTab", profile_);
+ TabRestoreService* service = profile_->GetTabRestoreService();
+ if (!service)
+ break;
+
+ const TabRestoreService::Tabs& tabs = service->tabs();
+ if (tabs.empty() || tabs.front().from_last_session)
+ break;
+
+ const TabRestoreService::HistoricalTab& tab = tabs.front();
+ AddRestoredTab(tab.navigations, tab_count(), tab.current_navigation_index,
+ true);
+ service->RemoveHistoricalTabById(tab.id);
+ break;
+ }
+
+ case IDC_EXIT:
+ BrowserList::CloseAllBrowsers(true);
+ break;
+
+ case IDC_HELPMENU: {
+ GURL help_url(l10n_util::GetString(IDS_HELP_CONTENT_URL));
+ AddTabWithURL(help_url, GURL(), PageTransition::AUTO_BOOKMARK, true,
+ NULL);
+ break;
+ }
+
+ default:
+ LOG(WARNING) << "Received Unimplemented Command: " << id <<
+ " from window " << GetTopLevelHWND();
}
+}
- scheduled_updates_.clear();
+///////////////////////////////////////////////////////////////////////////////
+// Browser, TabStripModelDelegate implementation:
+
+void Browser::CreateNewStripWithContents(TabContents* detached_contents,
+ const gfx::Point& drop_point) {
+ DCHECK(type_ == BrowserType::TABBED_BROWSER);
+
+ // Create an empty new browser window the same size as the old one.
+ // TODO(beng): move elsewhere
+ CRect browser_rect;
+ GetWindowRect(reinterpret_cast<HWND>(window_->GetNativeHandle()),
+ &browser_rect);
+ gfx::Rect rect(0, 0);
+ if (drop_point.x() != 0 || drop_point.y() != 0) {
+ rect.SetRect(drop_point.x(), drop_point.y(), browser_rect.Width(),
+ browser_rect.Height());
+ }
+ Browser* new_window =
+ new Browser(rect, SW_SHOWNORMAL, profile_, BrowserType::TABBED_BROWSER,
+ std::wstring());
+ // Append the TabContents before showing it so the window doesn't flash
+ // black.
+ new_window->tabstrip_model()->AppendTabContents(detached_contents, true);
+ new_window->Show();
+
+ // When we detach a tab we need to make sure any associated Find window moves
+ // along with it to its new home (basically we just make new_window the parent
+ // of the Find window).
+ // TODO(brettw) this could probably be improved, see
+ // WebContentsView::ReparentFindWindow for more.
+ if (detached_contents->AsWebContents())
+ detached_contents->AsWebContents()->view()->ReparentFindWindow(new_window);
+}
+
+int Browser::GetDragActions() const {
+ int result = 0;
+ if (BrowserList::GetBrowserCountForType(profile_,
+ BrowserType::TABBED_BROWSER) > 1 ||
+ tab_count() > 1)
+ result |= TAB_TEAROFF_ACTION;
+ if (tab_count() > 1)
+ result |= TAB_MOVE_ACTION;
+ return result;
+}
+
+TabContents* Browser::CreateTabContentsForURL(
+ const GURL& url, const GURL& referrer, Profile* profile,
+ PageTransition::Type transition, bool defer_load,
+ SiteInstance* instance) const {
+ // Create an appropriate tab contents.
+ GURL real_url = url;
+ TabContentsType type = TabContents::TypeForURL(&real_url);
+ DCHECK(type != TAB_CONTENTS_UNKNOWN_TYPE);
+
+ TabContents* contents =
+ TabContents::CreateWithType(type, GetTopLevelHWND(), profile, instance);
+ contents->SetupController(profile);
+
+ if (!defer_load) {
+ // Load the initial URL before adding the new tab contents to the tab strip
+ // so that the tab contents has navigation state.
+ contents->controller()->LoadURL(url, referrer, transition);
+ }
+
+ return contents;
+}
+
+bool Browser::CanDuplicateContentsAt(int index) {
+ TabContents* contents = GetTabContentsAt(index);
+ DCHECK(contents);
+
+ NavigationController* nc = contents->controller();
+ return nc ? (nc->active_contents() && nc->GetLastCommittedEntry()) : false;
+}
+
+void Browser::DuplicateContentsAt(int index) {
+ TabContents* contents = GetTabContentsAt(index);
+ TabContents* new_contents = NULL;
+ DCHECK(contents);
+
+ if (type_ == BrowserType::TABBED_BROWSER) {
+ // If this is a tabbed browser, just create a duplicate tab inside the same
+ // window next to the tab being duplicated.
+ new_contents = contents->controller()->Clone(
+ GetTopLevelHWND())->active_contents();
+ // If you duplicate a tab that is not selected, we need to make sure to
+ // select the tab being duplicated so that DetermineInsertionIndex returns
+ // the right index (if tab 5 is selected and we right-click tab 1 we want
+ // the new tab to appear in index position 2, not 6).
+ if (tabstrip_model_.selected_index() != index)
+ tabstrip_model_.SelectTabContentsAt(index, true);
+ tabstrip_model_.AddTabContents(new_contents, index + 1,
+ PageTransition::LINK, true);
+ } else {
+ Browser* new_browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile(),
+ BrowserType::APPLICATION, app_name_);
+
+ // We need to show the browser now. Otherwise ContainerWin assumes the
+ // TabContents is invisible and won't size it.
+ new_browser->Show();
+
+ // The page transition below is only for the purpose of inserting the tab.
+ new_contents = new_browser->AddTabWithNavigationController(
+ contents->controller()->Clone(new_browser->GetTopLevelHWND()),
+ PageTransition::LINK);
+
+ new_browser->window()->Activate();
+ }
+
+ if (profile_->HasSessionService()) {
+ SessionService* session_service = profile_->GetSessionService();
+ if (session_service)
+ session_service->TabRestored(new_contents->controller());
+ }
+}
+
+void Browser::ValidateLoadingAnimations() {
+ // TODO(beng): Remove this, per http://crbug.com/3297
+ if (window_)
+ window_->ValidateThrobber();
+}
+
+void Browser::CloseFrameAfterDragSession() {
+ // This is scheduled to run after we return to the message loop because
+ // otherwise the frame will think the drag session is still active and ignore
+ // the request.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(&Browser::CloseFrame));
}
////////////////////////////////////////////////////////////////////////////////
-// TabContentsDelegate
+// Browser, TabStripModelObserver implementation:
+
+void Browser::TabInsertedAt(TabContents* contents,
+ int index,
+ bool foreground) {
+ contents->set_delegate(this);
+ contents->controller()->SetWindowID(session_id());
+
+ SyncHistoryWithTabs(tabstrip_model_.GetIndexOfTabContents(contents));
+
+ // When a tab is dropped into a tab strip we need to make sure that the
+ // associated Find window is moved along with it. We therefore change the
+ // parent of the Find window (if the parent is already correctly set this
+ // does nothing).
+ // TODO(brettw) this could probably be improved, see
+ // WebContentsView::ReparentFindWindow for more.
+ if (contents->AsWebContents())
+ contents->AsWebContents()->view()->ReparentFindWindow(this);
+
+ // If the tab crashes in the beforeunload or unload handler, it won't be
+ // able to ack. But we know we can close it.
+ NotificationService::current()->
+ AddObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED,
+ Source<TabContents>(contents));
+}
+
+void Browser::TabClosingAt(TabContents* contents, int index) {
+ NavigationController* controller = contents->controller();
+ DCHECK(controller);
+ NotificationService::current()->
+ Notify(NOTIFY_TAB_CLOSING,
+ Source<NavigationController>(controller),
+ NotificationService::NoDetails());
+
+ // Sever the TabContents' connection back to us.
+ contents->set_delegate(NULL);
+}
+
+void Browser::TabDetachedAt(TabContents* contents, int index) {
+ contents->set_delegate(NULL);
+ if (!tabstrip_model_.closing_all())
+ SyncHistoryWithTabs(0);
+
+ RemoveScheduledUpdatesFor(contents);
+
+ NotificationService::current()->
+ RemoveObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED,
+ Source<TabContents>(contents));
+}
+
+void Browser::TabSelectedAt(TabContents* old_contents,
+ TabContents* new_contents,
+ int index,
+ bool user_gesture) {
+ DCHECK(old_contents != new_contents);
+
+ // If we have any update pending, do it now.
+ if (!chrome_updater_factory_.empty() && old_contents)
+ ProcessPendingUIUpdates();
+
+ LocationBarView* location_bar = GetLocationBarView();
+ if (old_contents) {
+ // Save what the user's currently typing, so it can be restored when we
+ // switch back to this tab.
+ if (location_bar)
+ location_bar->location_entry()->SaveStateToTab(old_contents);
+ }
+
+ // Propagate the profile to the location bar.
+ UpdateToolbar(true);
+
+ // Force the go/stop button to change.
+ if (new_contents->AsWebContents()) {
+ GetGoButton()->ChangeMode(
+ new_contents->is_loading() ? GoButton::MODE_STOP : GoButton::MODE_GO);
+ } else {
+ GetGoButton()->ChangeMode(GoButton::MODE_GO);
+ }
+
+ // Update other parts of the toolbar.
+ UpdateNavigationCommands();
+
+ // Reset the status bubble.
+ GetStatusBubble()->Hide();
+
+ // Show the loading state (if any).
+ GetStatusBubble()->SetStatus(GetSelectedTabContents()->GetStatusText());
+
+ // Update sessions. Don't force creation of sessions. If sessions doesn't
+ // exist, the change will be picked up by sessions when created.
+ if (profile_->HasSessionService()) {
+ SessionService* session_service = profile_->GetSessionService();
+ if (session_service && !tabstrip_model_.closing_all()) {
+ session_service->SetSelectedTabInWindow(session_id(),
+ tabstrip_model_.selected_index());
+ }
+ }
+}
+
+void Browser::TabMoved(TabContents* contents,
+ int from_index,
+ int to_index) {
+ DCHECK(from_index >= 0 && to_index >= 0);
+ // Notify the history service.
+ SyncHistoryWithTabs(std::min(from_index, to_index));
+}
+
+void Browser::TabStripEmpty() {
+ // Close the frame after we return to the message loop (not immediately,
+ // otherwise it will destroy this object before the stack has a chance to
+ // cleanly unwind.)
+ // Note: This will be called several times if TabStripEmpty is called several
+ // times. This is because it does not close the window if tabs are
+ // still present.
+ // NOTE: If you change to be immediate (no invokeLater) then you'll need to
+ // update BrowserList::CloseAllBrowsers.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(&Browser::CloseFrame));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Browser, TabContentsDelegate implementation:
void Browser::OpenURLFromTab(TabContents* source,
const GURL& url, const GURL& referrer,
@@ -556,7 +1690,7 @@ void Browser::OpenURLFromTab(TabContents* source,
// Synchronously update the location bar. This allows us to immediately
// have the URL bar update when the user types something, rather than
// going through the normal system of ScheduleUIUpdate which has a delay.
- UpdateToolBar(false);
+ UpdateToolbar(false);
} else if (disposition == OFF_THE_RECORD) {
OpenURLOffTheRecord(profile_, url);
return;
@@ -669,10 +1803,6 @@ void Browser::ActivateContents(TabContents* contents) {
window_->Activate();
}
-HWND Browser::GetTopLevelHWND() const {
- return window_ ? reinterpret_cast<HWND>(window_->GetNativeHandle()) : NULL;
-}
-
void Browser::LoadingStateChanged(TabContents* source) {
tabstrip_model_.UpdateTabContentsLoadingAnimations();
@@ -721,6 +1851,105 @@ bool Browser::IsPopup(TabContents* source) {
return (type() == BrowserType::BROWSER);
}
+void Browser::ToolbarSizeChanged(TabContents* source, bool is_animating) {
+ if (source == GetSelectedTabContents() || source == NULL) {
+ // This will refresh the shelf if needed.
+ window_->SelectedTabToolbarSizeChanged(is_animating);
+ }
+}
+
+void Browser::URLStarredChanged(TabContents* source, bool starred) {
+ if (source == GetSelectedTabContents())
+ SetStarredButtonToggled(starred);
+}
+
+void Browser::ContentsMouseEvent(TabContents* source, UINT message) {
+ if (source == GetSelectedTabContents()) {
+ if (message == WM_MOUSEMOVE) {
+ GetStatusBubble()->MouseMoved();
+ } else if (message == WM_MOUSELEAVE) {
+ GetStatusBubble()->SetURL(GURL(), std::wstring());
+ }
+ }
+}
+
+void Browser::UpdateTargetURL(TabContents* source, const GURL& url) {
+ if (source == GetSelectedTabContents()) {
+ PrefService* prefs = profile_->GetPrefs();
+ GetStatusBubble()->SetURL(url, prefs->GetString(prefs::kAcceptLanguages));
+ }
+}
+
+void Browser::ContentsZoomChange(bool zoom_in) {
+ controller_.ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
+}
+
+bool Browser::IsApplication() const {
+ return type_ == BrowserType::APPLICATION;
+}
+
+void Browser::ConvertContentsToApplication(TabContents* contents) {
+ if (!contents->AsWebContents() || !contents->AsWebContents()->web_app()) {
+ NOTREACHED();
+ return;
+ }
+
+ int index = tabstrip_model_.GetIndexOfTabContents(contents);
+ if (index < 0)
+ return;
+
+ WebApp* app = contents->AsWebContents()->web_app();
+ const std::wstring& app_name =
+ app->name().empty() ? ComputeApplicationNameFromURL(app->url()) :
+ app->name();
+ RegisterAppPrefs(app_name);
+
+ tabstrip_model_.DetachTabContentsAt(index);
+ Browser* browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_,
+ BrowserType::APPLICATION, app_name);
+ browser->AddNewContents(
+ NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true);
+ browser->Show();
+}
+
+void Browser::ContentsStateChanged(TabContents* source) {
+ int index = tabstrip_model_.GetIndexOfTabContents(source);
+ if (index != TabStripModel::kNoTab)
+ tabstrip_model_.UpdateTabContentsStateAt(index);
+}
+
+bool Browser::ShouldDisplayURLField() {
+ return !IsApplication();
+}
+
+void Browser::BeforeUnloadFired(TabContents* tab,
+ bool proceed,
+ bool* proceed_to_fire_unload) {
+ if (!is_attempting_to_close_browser_) {
+ *proceed_to_fire_unload = proceed;
+ return;
+ }
+
+ if (!proceed) {
+ CancelWindowClose();
+ *proceed_to_fire_unload = false;
+ return;
+ }
+
+ if (RemoveFromVector(&tabs_needing_before_unload_fired_, tab)) {
+ // Now that beforeunload has fired, put the tab on the queue to fire unload.
+ tabs_needing_unload_fired_.push_back(tab);
+ ProcessPendingTabs();
+ // We want to handle firing the unload event ourselves since we want to
+ // fire all the beforeunload events before attempting to fire the unload
+ // events should the user cancel closing the browser.
+ *proceed_to_fire_unload = false;
+ return;
+ }
+
+ *proceed_to_fire_unload = true;
+}
+
void Browser::ShowHtmlDialog(HtmlDialogContentsDelegate* delegate,
HWND parent_hwnd) {
parent_hwnd = parent_hwnd ? parent_hwnd : GetTopLevelHWND();
@@ -730,6 +1959,18 @@ void Browser::ShowHtmlDialog(HtmlDialogContentsDelegate* delegate,
html_view->window()->Show();
}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, SelectFileDialog::Listener implementation:
+
+void Browser::FileSelected(const std::wstring& path, void* params) {
+ GURL file_url = net::FilePathToFileURL(path);
+ if (!file_url.is_empty())
+ OpenURL(file_url, GURL(), CURRENT_TAB, PageTransition::TYPED);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Browser, NotificationObserver implementation:
+
void Browser::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -754,7 +1995,7 @@ void Browser::Observe(NotificationType type,
if (GetSelectedTabContents() &&
GetSelectedTabContents()->controller() ==
Source<NavigationController>(source).ptr())
- UpdateToolBar(false);
+ UpdateToolbar(false);
break;
default:
@@ -762,6 +2003,126 @@ void Browser::Observe(NotificationType type,
}
}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Command and state updating (private):
+
+void Browser::InitCommandState() {
+ // All browser commands whose state isn't set automagically some other way
+ // (like Back & Forward with initial page load) must have their state
+ // initialized here, otherwise they will be forever disabled.
+
+ controller_.UpdateCommandEnabled(IDC_STOP, true);
+ controller_.UpdateCommandEnabled(IDC_RELOAD, true);
+ controller_.UpdateCommandEnabled(IDC_HOME,
+ type() == BrowserType::TABBED_BROWSER);
+ controller_.UpdateCommandEnabled(IDC_GO, true);
+ controller_.UpdateCommandEnabled(IDC_NEWTAB, true);
+ controller_.UpdateCommandEnabled(IDC_CLOSETAB, true);
+ controller_.UpdateCommandEnabled(IDC_NEWWINDOW, true);
+ controller_.UpdateCommandEnabled(IDC_CLOSEWINDOW, true);
+ controller_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, true);
+ controller_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, true);
+ controller_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, true);
+ controller_.UpdateCommandEnabled(IDC_STAR, true);
+ controller_.UpdateCommandEnabled(IDC_OPENURL, true);
+ controller_.UpdateCommandEnabled(IDC_SHOWALLTABS_NEXT, true);
+ controller_.UpdateCommandEnabled(IDC_SHOWALLTABS_PREV, true);
+ controller_.UpdateCommandEnabled(IDC_SHOWALLTABS, true);
+ controller_.UpdateCommandEnabled(IDC_CUT, true);
+ controller_.UpdateCommandEnabled(IDC_COPY, true);
+ controller_.UpdateCommandEnabled(IDC_PASTE, true);
+ controller_.UpdateCommandEnabled(IDC_FIND, true);
+ controller_.UpdateCommandEnabled(IDC_FIND_NEXT, true);
+ controller_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, true);
+ controller_.UpdateCommandEnabled(IDS_COMMANDS_REPORTBUG, true);
+ controller_.UpdateCommandEnabled(IDC_SHOW_JS_CONSOLE, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_PREV_TAB, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_0, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_1, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_2, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_3, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_4, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_5, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_6, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_TAB_7, true);
+ controller_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, true);
+ controller_.UpdateCommandEnabled(IDC_VIEWSOURCE, true);
+ controller_.UpdateCommandEnabled(IDC_CREATE_SHORTCUT, false);
+ controller_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, true);
+ controller_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
+ controller_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
+ controller_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
+ controller_.UpdateCommandEnabled(IDC_OPENFILE, true);
+ controller_.UpdateCommandEnabled(IDC_TASKMANAGER, true);
+ controller_.UpdateCommandEnabled(IDC_CLOSEPOPUPS, true);
+ controller_.UpdateCommandEnabled(IDC_PRINT, true);
+ controller_.UpdateCommandEnabled(IDC_COPY_URL, true);
+ controller_.UpdateCommandEnabled(IDC_DUPLICATE, true);
+ controller_.UpdateCommandEnabled(IDC_GOOFFTHERECORD, true);
+ controller_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, true);
+ controller_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, true);
+ controller_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, true);
+ controller_.UpdateCommandEnabled(IDC_ABOUT, true);
+ controller_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true);
+ controller_.UpdateCommandEnabled(IDC_SHOW_BOOKMARKS_BAR, true);
+ controller_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER, true);
+ controller_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88591, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_GB2312, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_BIG5HKSCS, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88599, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
+ controller_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
+ controller_.UpdateCommandEnabled(IDC_OPTIONS, true);
+ controller_.UpdateCommandEnabled(IDC_CLOSE_WEB_APP,
+ type() != BrowserType::TABBED_BROWSER);
+ controller_.UpdateCommandEnabled(IDC_SHOW_AS_TAB,
+ type() == BrowserType::BROWSER);
+ controller_.UpdateCommandEnabled(
+ IDC_RESTORE_TAB, (!profile_->IsOffTheRecord() &&
+ type() == BrowserType::TABBED_BROWSER));
+ controller_.UpdateCommandEnabled(IDC_EXIT, true);
+ // the debugger doesn't work in single process mode
+ controller_.UpdateCommandEnabled(IDC_DEBUGGER,
+ !RenderProcessHost::run_renderer_in_process());
+ controller_.UpdateCommandEnabled(IDC_DEVELOPER, true);
+ controller_.UpdateCommandEnabled(IDC_HELPMENU, true);
+}
+
void Browser::UpdateNavigationCommands() {
const TabContents* const current_tab = GetSelectedTabContents();
NavigationController* nc = current_tab->controller();
@@ -810,65 +2171,156 @@ void Browser::UpdateNavigationCommands() {
CanDuplicateContentsAt(selected_index()));
}
-// Notification that the starredness of a tab changed.
-void Browser::URLStarredChanged(TabContents* source, bool starred) {
- if (source == GetSelectedTabContents())
- SetStarredButtonToggled(starred);
+void Browser::SetStarredButtonToggled(bool starred) {
+ window_->GetStarButton()->SetToggled(starred);
}
-StatusBubble* Browser::GetStatusBubble() {
- return window_->GetStatusBubble();
+///////////////////////////////////////////////////////////////////////////////
+// Browser, UI update coalescing and handling (private):
+
+void Browser::UpdateToolbar(bool should_restore_state) {
+ window_->UpdateToolbar(GetSelectedTabContents(), should_restore_state);
}
-void Browser::ContentsMouseEvent(TabContents* source, UINT message) {
- if (source == GetSelectedTabContents()) {
- if (message == WM_MOUSEMOVE) {
- GetStatusBubble()->MouseMoved();
- } else if (message == WM_MOUSELEAVE) {
- GetStatusBubble()->SetURL(GURL(), std::wstring());
- }
+void Browser::ScheduleUIUpdate(const TabContents* source,
+ unsigned changed_flags) {
+ // Synchronously update the URL.
+ if (changed_flags & TabContents::INVALIDATE_URL &&
+ source == GetSelectedTabContents()) {
+ // Only update the URL for the current tab. Note that we do not update
+ // the navigation commands since those would have already been updated
+ // synchronously by NavigationStateChanged.
+ UpdateToolbar(false);
+
+ if (changed_flags == TabContents::INVALIDATE_URL)
+ return; // Just had an update URL and nothing else.
}
-}
-void Browser::UpdateTargetURL(TabContents* source, const GURL& url) {
- if (source == GetSelectedTabContents()) {
- PrefService* prefs = profile_->GetPrefs();
- GetStatusBubble()->SetURL(url, prefs->GetString(prefs::kAcceptLanguages));
+ // Save the dirty bits.
+ scheduled_updates_.push_back(UIUpdate(source, changed_flags));
+
+ if (chrome_updater_factory_.empty()) {
+ // No task currently scheduled, start another.
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ chrome_updater_factory_.NewRunnableMethod(
+ &Browser::ProcessPendingUIUpdates),
+ kUIUpdateCoalescingTimeMS);
}
}
-void Browser::SetStarredButtonToggled(bool starred) {
- window_->GetStarButton()->SetToggled(starred);
-}
+void Browser::ProcessPendingUIUpdates() {
+#ifndef NDEBUG
+ // Validate that all tabs we have pending updates for exist. This is scary
+ // because the pending list must be kept in sync with any detached or
+ // deleted tabs. This code does not dereference any TabContents pointers.
+ for (size_t i = 0; i < scheduled_updates_.size(); i++) {
+ bool found = false;
+ for (int tab = 0; tab < tab_count(); tab++) {
+ if (GetTabContentsAt(tab)->controller() ==
+ scheduled_updates_[i].source->controller()) {
+ found = true;
+ break;
+ }
+ }
+ DCHECK(found);
+ }
+#endif
-GoButton* Browser::GetGoButton() {
- return window_->GetGoButton();
-}
+ chrome_updater_factory_.RevokeAll();
-void Browser::ContentsZoomChange(bool zoom_in) {
- controller_.ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
+ // We could have many updates for the same thing in the queue. This map tracks
+ // the bits of the stuff we've already updated for each TabContents so we
+ // don't update again.
+ typedef std::map<const TabContents*, unsigned> UpdateTracker;
+ UpdateTracker updated_stuff;
+
+ for (size_t i = 0; i < scheduled_updates_.size(); i++) {
+ // Do not dereference |contents|, it may be out-of-date!
+ const TabContents* contents = scheduled_updates_[i].source;
+ unsigned flags = scheduled_updates_[i].changed_flags;
+
+ // Remove any bits we have already updated, and save the new bits.
+ UpdateTracker::iterator updated = updated_stuff.find(contents);
+ if (updated != updated_stuff.end()) {
+ // Turn off bits already set.
+ flags &= ~updated->second;
+ if (!flags)
+ continue;
+
+ updated->second |= flags;
+ } else {
+ updated_stuff[contents] = flags;
+ }
+
+ // Updates to the title or favicon require a tab repaint. However, the
+ // inverse is not true since updates to the title also update the window
+ // title.
+ bool invalidate_tab = false;
+ if (flags & TabContents::INVALIDATE_TITLE ||
+ flags & TabContents::INVALIDATE_FAVICON) {
+ invalidate_tab = true;
+
+ // Anything that repaints the tab means the favicon is updated.
+ updated_stuff[contents] |= TabContents::INVALIDATE_FAVICON;
+ }
+
+ // Updating the URL happens synchronously in ScheduleUIUpdate.
+
+ if (flags & TabContents::INVALIDATE_LOAD)
+ GetStatusBubble()->SetStatus(GetSelectedTabContents()->GetStatusText());
+
+ if (invalidate_tab) { // INVALIDATE_TITLE or INVALIDATE_FAVICON.
+ tabstrip_model_.UpdateTabContentsStateAt(
+ tabstrip_model_.GetIndexOfController(contents->controller()));
+ window_->UpdateTitleBar();
+
+ if (contents == GetSelectedTabContents()) {
+ TabContents* current_tab = GetSelectedTabContents();
+ controller_.UpdateCommandEnabled(IDC_CREATE_SHORTCUT,
+ current_tab->type() == TAB_CONTENTS_WEB &&
+ !current_tab->GetFavIcon().isNull());
+ }
+ }
+
+ // We don't need to process INVALIDATE_STATE, since that's not visible.
+ }
+
+ scheduled_updates_.clear();
}
-bool Browser::IsApplication() const {
- return type_ == BrowserType::APPLICATION;
+void Browser::RemoveScheduledUpdatesFor(TabContents* contents) {
+ if (!contents)
+ return;
+
+ // Remove any pending UI updates for the detached tab.
+ UpdateVector::iterator cur_update = scheduled_updates_.begin();
+ while (cur_update != scheduled_updates_.end()) {
+ if (cur_update->source == contents) {
+ cur_update = scheduled_updates_.erase(cur_update);
+ } else {
+ ++cur_update;
+ }
+ }
}
-void Browser::ContentsStateChanged(TabContents* source) {
- int index = tabstrip_model_.GetIndexOfTabContents(source);
- if (index != TabStripModel::kNoTab)
- tabstrip_model_.UpdateTabContentsStateAt(index);
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Getters for UI (private):
+
+LocationBarView* Browser::GetLocationBarView() const {
+ return window_->GetLocationBarView();
}
-bool Browser::ShouldDisplayURLField() {
- return !IsApplication();
+GoButton* Browser::GetGoButton() {
+ return window_->GetGoButton();
}
-void Browser::FocusLocationBar() {
- LocationBarView* location_bar = GetLocationBarView();
- if (location_bar)
- location_bar->location_entry()->SetFocus();
+StatusBubble* Browser::GetStatusBubble() {
+ return window_->GetStatusBubble();
}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Session restore functions (private):
+
void Browser::SyncHistoryWithTabs(int index) {
if (!profile()->HasSessionService())
return;
@@ -884,33 +2336,33 @@ void Browser::SyncHistoryWithTabs(int index) {
}
}
-void Browser::ToolbarSizeChanged(TabContents* source, bool is_animating) {
- if (source == GetSelectedTabContents() || source == NULL) {
- // This will refresh the shelf if needed.
- window_->SelectedTabToolbarSizeChanged(is_animating);
- }
-}
-
-bool Browser::ShouldCloseWindow() {
- if (HasCompletedUnloadProcessing()) {
- return true;
- }
- is_attempting_to_close_browser_ = true;
+NavigationController* Browser::BuildRestoredNavigationController(
+ const std::vector<TabNavigation>& navigations,
+ int selected_navigation) {
+ if (!navigations.empty()) {
+ DCHECK(selected_navigation >= 0 &&
+ selected_navigation < static_cast<int>(navigations.size()));
+ // We should have a valid URL, if we don't fall back to the default.
+ GURL url = navigations[selected_navigation].url;
+ if (url.is_empty())
+ url = GetHomePage();
- for (int i = 0; i < tab_count(); ++i) {
- if (tabstrip_model_.TabHasUnloadListener(i)) {
- TabContents* tab = GetTabContentsAt(i);
- tabs_needing_before_unload_fired_.push_back(tab);
- }
+ // Create a NavigationController. This constructor creates the appropriate
+ // set of TabContents.
+ return new NavigationController(
+ profile_, navigations, selected_navigation, GetTopLevelHWND());
+ } else {
+ // No navigations. Create a tab with about:blank.
+ TabContents* contents =
+ CreateTabContentsForURL(GURL("about:blank"), GURL(), profile_,
+ PageTransition::START_PAGE, false, NULL);
+ return new NavigationController(contents, profile_);
}
-
- if (tabs_needing_before_unload_fired_.empty())
- return true;
-
- ProcessPendingTabs();
- return false;
}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, OnBeforeUnload handling (private):
+
void Browser::ProcessPendingTabs() {
DCHECK(is_attempting_to_close_browser_);
@@ -960,41 +2412,6 @@ void Browser::CancelWindowClose() {
is_attempting_to_close_browser_ = false;
}
-void Browser::BeforeUnloadFired(TabContents* tab,
- bool proceed,
- bool* proceed_to_fire_unload) {
- if (!is_attempting_to_close_browser_) {
- *proceed_to_fire_unload = proceed;
- return;
- }
-
- if (!proceed) {
- CancelWindowClose();
- *proceed_to_fire_unload = false;
- return;
- }
-
- if (RemoveFromVector(&tabs_needing_before_unload_fired_, tab)) {
- // Now that beforeunload has fired, put the tab on the queue to fire unload.
- tabs_needing_unload_fired_.push_back(tab);
- ProcessPendingTabs();
- // We want to handle firing the unload event ourselves since we want to
- // fire all the beforeunload events before attempting to fire the unload
- // events should the user cancel closing the browser.
- *proceed_to_fire_unload = false;
- return;
- }
-
- *proceed_to_fire_unload = true;
-}
-
-void Browser::ClearUnloadState(TabContents* tab) {
- DCHECK(is_attempting_to_close_browser_);
- RemoveFromVector(&tabs_needing_before_unload_fired_, tab);
- RemoveFromVector(&tabs_needing_unload_fired_, tab);
- ProcessPendingTabs();
-}
-
bool Browser::RemoveFromVector(UnloadListenerVector* vector, TabContents* tab) {
DCHECK(is_attempting_to_close_browser_);
@@ -1009,306 +2426,15 @@ bool Browser::RemoveFromVector(UnloadListenerVector* vector, TabContents* tab) {
return false;
}
-void Browser::OnWindowClosing() {
- if (!ShouldCloseWindow())
- return;
-
- if (BrowserList::size() == 1)
- browser_shutdown::OnShutdownStarting(browser_shutdown::WINDOW_CLOSE);
-
- // Don't use HasSessionService here, we want to force creation of the
- // session service so that user can restore what was open.
- SessionService* session_service = profile()->GetSessionService();
- if (session_service)
- session_service->WindowClosing(session_id());
-
- CloseAllTabs();
-}
-
-// Tab Creation Functions
-
-TabContents* Browser::AddTabWithURL(
- const GURL& url, const GURL& referrer, PageTransition::Type transition,
- bool foreground, SiteInstance* instance) {
- if (type_ == BrowserType::APPLICATION && tabstrip_model_.count() == 1) {
- NOTREACHED() << "Cannot add a tab in a mono tab application.";
- return NULL;
- }
-
- GURL url_to_load = url;
- if (url_to_load.is_empty())
- url_to_load = GetHomePage();
- TabContents* contents =
- CreateTabContentsForURL(url_to_load, referrer, profile_, transition,
- false, instance);
- tabstrip_model_.AddTabContents(contents, -1, transition, foreground);
- // By default, content believes it is not hidden. When adding contents
- // in the background, tell it that it's hidden.
- if (!foreground)
- contents->WasHidden();
- return contents;
-}
-
-TabContents* Browser::AddWebApplicationTab(Profile* profile,
- WebApp* web_app,
- bool lazy) {
- DCHECK(web_app);
-
- // TODO(acw): Do we need an "application launched" transition type?
- // TODO(creis): Should we reuse the current instance (ie. process) here?
- TabContents* contents =
- CreateTabContentsForURL(web_app->url(), GURL(), profile,
- PageTransition::LINK, lazy, NULL);
- if (contents->AsWebContents())
- contents->AsWebContents()->SetWebApp(web_app);
-
- if (lazy) {
- contents->controller()->LoadURLLazily(
- web_app->url(), GURL(), PageTransition::LINK, web_app->name(), NULL);
- }
- tabstrip_model_.AddTabContents(contents, -1, PageTransition::LINK, !lazy);
- return contents;
-}
-
-TabContents* Browser::AddTabWithNavigationController(
- NavigationController* ctrl, PageTransition::Type type) {
- TabContents* tc = ctrl->active_contents();
- tabstrip_model_.AddTabContents(tc, -1, type, true);
- return tc;
-}
-
-NavigationController* Browser::AddRestoredTab(
- const std::vector<TabNavigation>& navigations,
- int tab_index,
- int selected_navigation,
- bool select) {
- NavigationController* restored_controller =
- BuildRestoredNavigationController(navigations, selected_navigation);
-
- tabstrip_model_.InsertTabContentsAt(
- tab_index,
- restored_controller->active_contents(),
- select, false);
- if (profile_->HasSessionService()) {
- SessionService* session_service = profile_->GetSessionService();
- if (session_service)
- session_service->TabRestored(restored_controller);
- }
- return restored_controller;
-}
-
-void Browser::ReplaceRestoredTab(
- const std::vector<TabNavigation>& navigations,
- int selected_navigation) {
- NavigationController* restored_controller =
- BuildRestoredNavigationController(navigations, selected_navigation);
-
- tabstrip_model_.ReplaceNavigationControllerAt(
- tabstrip_model_.selected_index(),
- restored_controller);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Browser, TabStripModelDelegate implementation:
-
-void Browser::CreateNewStripWithContents(TabContents* detached_contents,
- const gfx::Point& drop_point) {
- DCHECK(type_ == BrowserType::TABBED_BROWSER);
-
- // Create an empty new browser window the same size as the old one.
- // TODO(beng): move elsewhere
- CRect browser_rect;
- GetWindowRect(reinterpret_cast<HWND>(window_->GetNativeHandle()),
- &browser_rect);
- gfx::Rect rect(0, 0);
- if (drop_point.x() != 0 || drop_point.y() != 0) {
- rect.SetRect(drop_point.x(), drop_point.y(), browser_rect.Width(),
- browser_rect.Height());
- }
- Browser* new_window =
- new Browser(rect, SW_SHOWNORMAL, profile_, BrowserType::TABBED_BROWSER,
- std::wstring());
- // Append the TabContents before showing it so the window doesn't flash
- // black.
- new_window->tabstrip_model()->AppendTabContents(detached_contents, true);
- new_window->Show();
-
- // When we detach a tab we need to make sure any associated Find window moves
- // along with it to its new home (basically we just make new_window the parent
- // of the Find window).
- // TODO(brettw) this could probably be improved, see
- // WebContentsView::ReparentFindWindow for more.
- if (detached_contents->AsWebContents())
- detached_contents->AsWebContents()->view()->ReparentFindWindow(new_window);
-}
-
-int Browser::GetDragActions() const {
- int result = 0;
- if (BrowserList::GetBrowserCountForType(profile_,
- BrowserType::TABBED_BROWSER) > 1 ||
- tab_count() > 1)
- result |= TAB_TEAROFF_ACTION;
- if (tab_count() > 1)
- result |= TAB_MOVE_ACTION;
- return result;
-}
-
-TabContents* Browser::CreateTabContentsForURL(
- const GURL& url, const GURL& referrer, Profile* profile,
- PageTransition::Type transition, bool defer_load,
- SiteInstance* instance) const {
- // Create an appropriate tab contents.
- GURL real_url = url;
- TabContentsType type = TabContents::TypeForURL(&real_url);
- DCHECK(type != TAB_CONTENTS_UNKNOWN_TYPE);
-
- TabContents* contents =
- TabContents::CreateWithType(type, GetTopLevelHWND(), profile, instance);
- contents->SetupController(profile);
-
- if (!defer_load) {
- // Load the initial URL before adding the new tab contents to the tab strip
- // so that the tab contents has navigation state.
- contents->controller()->LoadURL(url, referrer, transition);
- }
-
- return contents;
-}
-
-void Browser::ValidateLoadingAnimations() {
- // TODO(beng): Remove this, per http://crbug.com/3297
- if (window_)
- window_->ValidateThrobber();
-}
-
-void Browser::CloseFrameAfterDragSession() {
- // This is scheduled to run after we return to the message loop because
- // otherwise the frame will think the drag session is still active and ignore
- // the request.
- MessageLoop::current()->PostTask(FROM_HERE,
- method_factory_.NewRunnableMethod(&Browser::CloseFrame));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Browser, TabStripModelObserver implementation:
-
-void Browser::TabInsertedAt(TabContents* contents,
- int index,
- bool foreground) {
- contents->set_delegate(this);
- contents->controller()->SetWindowID(session_id());
-
- SyncHistoryWithTabs(tabstrip_model_.GetIndexOfTabContents(contents));
-
- // When a tab is dropped into a tab strip we need to make sure that the
- // associated Find window is moved along with it. We therefore change the
- // parent of the Find window (if the parent is already correctly set this
- // does nothing).
- // TODO(brettw) this could probably be improved, see
- // WebContentsView::ReparentFindWindow for more.
- if (contents->AsWebContents())
- contents->AsWebContents()->view()->ReparentFindWindow(this);
-
- // If the tab crashes in the beforeunload or unload handler, it won't be
- // able to ack. But we know we can close it.
- NotificationService::current()->
- AddObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED,
- Source<TabContents>(contents));
-}
-
-void Browser::TabClosingAt(TabContents* contents, int index) {
- NavigationController* controller = contents->controller();
- DCHECK(controller);
- NotificationService::current()->
- Notify(NOTIFY_TAB_CLOSING,
- Source<NavigationController>(controller),
- NotificationService::NoDetails());
-
- // Sever the TabContents' connection back to us.
- contents->set_delegate(NULL);
-}
-
-void Browser::TabDetachedAt(TabContents* contents, int index) {
- contents->set_delegate(NULL);
- if (!tabstrip_model_.closing_all())
- SyncHistoryWithTabs(0);
-
- RemoveScheduledUpdatesFor(contents);
-
- NotificationService::current()->
- RemoveObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED,
- Source<TabContents>(contents));
-}
-
-void Browser::TabSelectedAt(TabContents* old_contents,
- TabContents* new_contents,
- int index,
- bool user_gesture) {
- DCHECK(old_contents != new_contents);
-
- // If we have any update pending, do it now.
- if (!chrome_updater_factory_.empty() && old_contents)
- ProcessPendingUIUpdates();
-
- LocationBarView* location_bar = GetLocationBarView();
- if (old_contents) {
- // Save what the user's currently typing, so it can be restored when we
- // switch back to this tab.
- if (location_bar)
- location_bar->location_entry()->SaveStateToTab(old_contents);
- }
-
- // Propagate the profile to the location bar.
- UpdateToolBar(true);
-
- // Force the go/stop button to change.
- if (new_contents->AsWebContents()) {
- GetGoButton()->ChangeMode(
- new_contents->is_loading() ? GoButton::MODE_STOP : GoButton::MODE_GO);
- } else {
- GetGoButton()->ChangeMode(GoButton::MODE_GO);
- }
-
- // Update other parts of the toolbar.
- UpdateNavigationCommands();
-
- // Reset the status bubble.
- GetStatusBubble()->Hide();
-
- // Show the loading state (if any).
- GetStatusBubble()->SetStatus(GetSelectedTabContents()->GetStatusText());
-
- // Update sessions. Don't force creation of sessions. If sessions doesn't
- // exist, the change will be picked up by sessions when created.
- if (profile_->HasSessionService()) {
- SessionService* session_service = profile_->GetSessionService();
- if (session_service && !tabstrip_model_.closing_all()) {
- session_service->SetSelectedTabInWindow(session_id(),
- tabstrip_model_.selected_index());
- }
- }
-}
-
-void Browser::TabMoved(TabContents* contents,
- int from_index,
- int to_index) {
- DCHECK(from_index >= 0 && to_index >= 0);
- // Notify the history service.
- SyncHistoryWithTabs(std::min(from_index, to_index));
+void Browser::ClearUnloadState(TabContents* tab) {
+ DCHECK(is_attempting_to_close_browser_);
+ RemoveFromVector(&tabs_needing_before_unload_fired_, tab);
+ RemoveFromVector(&tabs_needing_unload_fired_, tab);
+ ProcessPendingTabs();
}
-void Browser::TabStripEmpty() {
- // Close the frame after we return to the message loop (not immediately,
- // otherwise it will destroy this object before the stack has a chance to
- // cleanly unwind.)
- // Note: This will be called several times if TabStripEmpty is called several
- // times. This is because it does not close the window if tabs are
- // still present.
- // NOTE: If you change to be immediate (no invokeLater) then you'll need to
- // update BrowserList::CloseAllBrowsers.
- MessageLoop::current()->PostTask(FROM_HERE,
- method_factory_.NewRunnableMethod(&Browser::CloseFrame));
-}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, Assorted utility functions (private):
Browser* Browser::GetOrCreateTabbedBrowser() {
Browser* browser = BrowserList::FindBrowserWithType(
@@ -1320,93 +2446,6 @@ Browser* Browser::GetOrCreateTabbedBrowser() {
return browser;
}
-void Browser::RemoveScheduledUpdatesFor(TabContents* contents) {
- if (!contents)
- return;
-
- // Remove any pending UI updates for the detached tab.
- UpdateVector::iterator cur_update = scheduled_updates_.begin();
- while (cur_update != scheduled_updates_.end()) {
- if (cur_update->source == contents) {
- cur_update = scheduled_updates_.erase(cur_update);
- } else {
- ++cur_update;
- }
- }
-}
-
-void Browser::ShowNativeUITab(const GURL& url) {
- int i, c;
- TabContents* tc;
- for (i = 0, c = tabstrip_model_.count(); i < c; ++i) {
- tc = tabstrip_model_.GetTabContentsAt(i);
- if (tc->type() == TAB_CONTENTS_NATIVE_UI &&
- tc->GetURL() == url) {
- tabstrip_model_.SelectTabContentsAt(i, false);
- return;
- }
- }
-
- TabContents* contents = CreateTabContentsForURL(url, GURL(), profile_,
- PageTransition::LINK, false,
- NULL);
- AddNewContents(NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true);
-}
-
-NavigationController* Browser::BuildRestoredNavigationController(
- const std::vector<TabNavigation>& navigations,
- int selected_navigation) {
- if (!navigations.empty()) {
- DCHECK(selected_navigation >= 0 &&
- selected_navigation < static_cast<int>(navigations.size()));
- // We should have a valid URL, if we don't fall back to the default.
- GURL url = navigations[selected_navigation].url;
- if (url.is_empty())
- url = GetHomePage();
-
- // Create a NavigationController. This constructor creates the appropriate
- // set of TabContents.
- return new NavigationController(
- profile_, navigations, selected_navigation, GetTopLevelHWND());
- } else {
- // No navigations. Create a tab with about:blank.
- TabContents* contents =
- CreateTabContentsForURL(GURL("about:blank"), GURL(), profile_,
- PageTransition::START_PAGE, false, NULL);
- return new NavigationController(contents, profile_);
- }
-}
-
-// static
-void Browser::OpenURLOffTheRecord(Profile* profile, const GURL& url) {
- Profile* off_the_record_profile = profile->GetOffTheRecordProfile();
- Browser* browser = BrowserList::FindBrowserWithType(
- off_the_record_profile, BrowserType::TABBED_BROWSER);
- if (browser == NULL) {
- browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, off_the_record_profile,
- BrowserType::TABBED_BROWSER, L"");
- }
- // TODO(eroman): should we have referrer here?
- browser->AddTabWithURL(url, GURL(), PageTransition::LINK, true, NULL);
- browser->Show();
- browser->window()->Activate();
-}
-
-void Browser::ConvertToTabbedBrowser() {
- if (type() != BrowserType::BROWSER) {
- NOTREACHED();
- return;
- }
-
- int tab_strip_index = tabstrip_model_.selected_index();
- TabContents* contents = tabstrip_model_.DetachTabContentsAt(tab_strip_index);
- Browser* browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_,
- BrowserType::TABBED_BROWSER, L"");
- browser->AddNewContents(
- NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true);
- browser->Show();
-}
-
void Browser::BuildPopupWindow(TabContents* source,
TabContents* new_contents,
const gfx::Rect& initial_pos) {
@@ -1419,28 +2458,22 @@ void Browser::BuildPopupWindow(TabContents* source,
browser->Show();
}
-void Browser::ConvertContentsToApplication(TabContents* contents) {
- if (!contents->AsWebContents() || !contents->AsWebContents()->web_app()) {
- NOTREACHED();
- return;
- }
-
- int index = tabstrip_model_.GetIndexOfTabContents(contents);
- if (index < 0)
- return;
+GURL Browser::GetHomePage() {
+ if (profile_->GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage)) {
+ return NewTabUIURL();
+ } else {
+ GURL home_page = GURL(URLFixerUpper::FixupURL(
+ profile_->GetPrefs()->GetString(prefs::kHomePage),
+ std::wstring()));
+ if (!home_page.is_valid())
+ return NewTabUIURL();
- WebApp* app = contents->AsWebContents()->web_app();
- const std::wstring& app_name =
- app->name().empty() ? ComputeApplicationNameFromURL(app->url()) :
- app->name();
- RegisterAppPrefs(app_name);
+ return home_page;
+ }
+}
- tabstrip_model_.DetachTabContentsAt(index);
- Browser* browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile_,
- BrowserType::APPLICATION, app_name);
- browser->AddNewContents(
- NULL, contents, NEW_FOREGROUND_TAB, gfx::Rect(), true);
- browser->Show();
+void Browser::CloseFrame() {
+ window_->Close();
}
// static
@@ -1453,21 +2486,6 @@ std::wstring Browser::ComputeApplicationNameFromURL(const GURL& url) {
}
// static
-void Browser::OpenWebApplication(Profile* profile,
- WebApp* app,
- int show_command) {
- const std::wstring& app_name =
- app->name().empty() ? ComputeApplicationNameFromURL(app->url()) :
- app->name();
-
- RegisterAppPrefs(app_name);
- Browser* browser = new Browser(gfx::Rect(), show_command, profile,
- BrowserType::APPLICATION, app_name);
- browser->AddWebApplicationTab(profile, app, false);
- browser->Show();
-}
-
-// static
void Browser::RegisterAppPrefs(const std::wstring& app_name) {
// A set of apps that we've already started.
static std::set<std::wstring>* g_app_names = NULL;
@@ -1490,82 +2508,3 @@ void Browser::RegisterAppPrefs(const std::wstring& app_name) {
prefs->RegisterDictionaryPref(window_pref.c_str());
}
-NavigationController* Browser::GetSelectedNavigationController() const {
- TabContents* tc = GetSelectedTabContents();
- if (tc)
- return tc->controller();
- else
- return NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NEW FRAME TODO(beng): clean up this file
-// DO NOT PLACE METHODS NOT RELATED TO NEW FRAMES BELOW THIS LINE.
-
-void Browser::SaveWindowPosition(const gfx::Rect& bounds, bool maximized) {
- // We don't save window position for popups.
- if (type() == BrowserType::BROWSER)
- return;
-
- // First save to local state, this is for remembering on subsequent starts.
- PrefService* prefs = g_browser_process->local_state();
- DCHECK(prefs);
- std::wstring name(prefs::kBrowserWindowPlacement);
- if (!app_name_.empty()) {
- name.append(L"_");
- name.append(app_name_);
- }
-
- DictionaryValue* win_pref = prefs->GetMutableDictionary(name.c_str());
- DCHECK(win_pref);
- win_pref->SetInteger(L"top", bounds.y());
- win_pref->SetInteger(L"left", bounds.x());
- win_pref->SetInteger(L"bottom", bounds.bottom());
- win_pref->SetInteger(L"right", bounds.right());
- win_pref->SetBoolean(L"maximized", maximized);
-
- // Then save to the session storage service, used when reloading a past
- // session. Note that we don't want to be the ones who cause lazy
- // initialization of the session service. This function gets called during
- // initial window showing, and we don't want to bring in the session service
- // this early.
- if (profile()->HasSessionService()) {
- SessionService* session_service = profile()->GetSessionService();
- if (session_service)
- session_service->SetWindowBounds(session_id_, bounds, maximized);
- }
-}
-
-void Browser::RestoreWindowPosition(gfx::Rect* bounds, bool* maximized) {
- DCHECK(bounds && maximized);
- WindowSizer::GetBrowserWindowBounds(app_name_, *bounds, bounds, maximized);
-}
-
-SkBitmap Browser::GetCurrentPageIcon() const {
- TabContents* contents = tabstrip_model_.GetSelectedTabContents();
- return contents ? contents->GetFavIcon() : SkBitmap();
-}
-
-std::wstring Browser::GetCurrentPageTitle() const {
- TabContents* contents = tabstrip_model_.GetSelectedTabContents();
- std::wstring title;
- if (contents) {
- title = contents->GetTitle();
- FormatTitleForDisplay(&title);
- }
- if (title.empty())
- title = l10n_util::GetString(IDS_TAB_UNTITLED_TITLE);
-
- return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, title);
-}
-
-// static
-void Browser::FormatTitleForDisplay(std::wstring* title) {
- size_t current_index = 0;
- size_t match_index;
- while ((match_index = title->find(L'\n', current_index)) !=
- std::wstring::npos) {
- title->replace(match_index, 1, L"");
- current_index = match_index;
- }
-}