diff options
Diffstat (limited to 'chrome/browser/browser_commands.cc')
-rw-r--r-- | chrome/browser/browser_commands.cc | 1142 |
1 files changed, 1142 insertions, 0 deletions
diff --git a/chrome/browser/browser_commands.cc b/chrome/browser/browser_commands.cc new file mode 100644 index 0000000..0d65b0b --- /dev/null +++ b/chrome/browser/browser_commands.cc @@ -0,0 +1,1142 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/browser.h" + +#include <commdlg.h> +#include <shellapi.h> + +#include <map> +#include <iostream> +#include <fstream> + +#include "base/command_line.h" +#include "base/file_version_info.h" +#include "base/gfx/png_encoder.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/win_util.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/character_encoding.h" +#include "chrome/browser/chrome_frame.h" +#include "chrome/browser/dom_ui/new_tab_ui.h" +#include "chrome/browser/download_tab_view.h" +#include "chrome/browser/history_tab_ui.h" +#include "chrome/browser/interstitial_page_delegate.h" +#include "chrome/browser/navigation_controller.h" +#include "chrome/browser/navigation_entry.h" +#include "chrome/browser/network_status_view.h" +#include "chrome/browser/options_window.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/session_startup_pref.h" +#include "chrome/browser/tab_restore_service.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_bubble_view.h" +#include "chrome/browser/views/bug_report_view.h" +#include "chrome/browser/views/clear_browsing_data.h" +#include "chrome/browser/views/importer_view.h" +#include "chrome/browser/views/info_bubble.h" +#include "chrome/browser/views/first_run_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/toolbar_star_toggle.h" +#include "chrome/browser/views/toolbar_view.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/text_zoom.h" +#include "chrome/common/win_util.h" +#include "chrome/views/window.h" +#include "net/base/escape.h" +#include "net/base/net_util.h" +#include "generated_resources.h" + +/////////////////////////////////////////////////////////////////////////////// +// Event handling and updating +// +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, + GetType() == BrowserType::TABBED_BROWSER); + controller_.UpdateCommandEnabled(IDC_GO, true); + controller_.UpdateCommandEnabled(IDC_NEWTAB, true); + controller_.UpdateCommandEnabled(IDC_CLOSETAB, !IsApplication()); + 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, false); + 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_DOWNLOADS, 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, + GetType() != BrowserType::TABBED_BROWSER); + controller_.UpdateCommandEnabled(IDC_SHOW_AS_TAB, + GetType() == BrowserType::BROWSER); + controller_.UpdateCommandEnabled( + IDC_RESTORE_TAB, (!profile_->IsOffTheRecord() && + GetType() == 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); +} + +bool Browser::SupportsCommand(int id) const { + return controller_.SupportsCommand(id); +} + +bool Browser::ExecuteWindowsAppCommand(int app_command) { + switch (app_command) { + case APPCOMMAND_BROWSER_BACKWARD: + controller_.ExecuteCommand(IDC_BACK); + return true; + case APPCOMMAND_BROWSER_FORWARD: + controller_.ExecuteCommand(IDC_FORWARD); + return true; + case APPCOMMAND_BROWSER_REFRESH: + controller_.ExecuteCommand(IDC_RELOAD); + return true; + case APPCOMMAND_BROWSER_HOME: + controller_.ExecuteCommand(IDC_HOME); + return true; + case APPCOMMAND_BROWSER_STOP: + controller_.ExecuteCommand(IDC_STOP); + return true; + case APPCOMMAND_BROWSER_SEARCH: + controller_.ExecuteCommand(IDC_FOCUS_SEARCH); + return true; + case APPCOMMAND_CLOSE: + controller_.ExecuteCommand(IDC_CLOSETAB); + return true; + case APPCOMMAND_NEW: + controller_.ExecuteCommand(IDC_NEWTAB); + return true; + case APPCOMMAND_OPEN: + controller_.ExecuteCommand(IDC_OPENFILE); + return true; + case APPCOMMAND_PRINT: + controller_.ExecuteCommand(IDC_PRINT); + return true; + + // TODO(pkasting): http://b/1113069 Handle all these. + case APPCOMMAND_HELP: + case APPCOMMAND_SAVE: + case APPCOMMAND_UNDO: + case APPCOMMAND_REDO: + case APPCOMMAND_COPY: + case APPCOMMAND_CUT: + case APPCOMMAND_PASTE: + case APPCOMMAND_SPELL_CHECK: + default: + return false; + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// CommandController implementation +// + +bool Browser::GetContextualLabel(int id, std::wstring* out) const { + return false; +} + +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->IsLoading()); + } + case IDC_CLOSETAB: { + return !IsApplication(); + } + default: + return controller_.IsCommandEnabled(id); + } +} + +void Browser::ExecuteCommand(int id) { + if (!IsCommandEnabled(id)) { + NOTREACHED() << id; + return; + } + // This might happen during QMU testing. + if (!GetSelectedTabContents()) + return; + + 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()->AcceptInput(CURRENT_TAB, false); + } + break; + + case IDC_NEWTAB: + UserMetrics::RecordAction(L"NewTab", profile_); + if (GetType() == BrowserType::TABBED_BROWSER) { + AddBlankTab(true); + } else { + Browser* b = GetOrCreateTabbedBrowser(); + DCHECK(b); + b->Show(); + b->MoveToFront(true); + 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_, SW_SHOWNORMAL); + break; + + case IDC_CLOSEWINDOW: + UserMetrics::RecordAction(L"CloseWindow", profile_); + frame_->Close(); + break; + + case IDC_FOCUS_LOCATION: + UserMetrics::RecordAction(L"FocusLocation", profile_); + { + LocationBarView* lbv = GetLocationBarView(); + if (lbv) { + AutocompleteEdit* ae = lbv->location_entry(); + ae->SetFocus(); + ae->SelectAll(true); + } + } + break; + + case IDC_FOCUS_SEARCH: + UserMetrics::RecordAction(L"FocusSearch", profile_); + { + LocationBarView* lbv = GetLocationBarView(); + if (lbv) { + AutocompleteEdit* ae = lbv->location_entry(); + ae->SetUserText(L"?"); + ae->SetFocus(); + } + } + break; + + case IDC_FOCUS_TOOLBAR: + UserMetrics::RecordAction(L"FocusToolbar", profile_); + { + ChromeViews::View* tb = GetToolbar(); + if (tb) { + tb->RequestFocus(); + } + } + break; + + case IDC_STAR: + UserMetrics::RecordAction(L"Star", profile_); + StarCurrentTabContents(); + break; + + case IDC_OPENURL: + UserMetrics::RecordAction(L"LoadURL", profile_); + { + LocationBarView* lbv = GetLocationBarView(); + if (lbv) { + OpenURL(GURL(lbv->location_input()), lbv->disposition(), + lbv->transition()); + } else { + OpenURL(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_); + if (!AdvanceFindSelection(true)) + OpenFindInPageWindow(); + break; + + case IDC_FIND_PREVIOUS: + UserMetrics::RecordAction(L"FindPrevious", profile_); + if (!AdvanceFindSelection(false)) + OpenFindInPageWindow(); + 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; + } + + 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(); + DCHECK(current_tab->controller()->GetLastCommittedEntry()); + GURL url("view-source:" + + current_tab->controller()->GetLastCommittedEntry()->GetURL().spec()); + + AddTabWithURL(url, 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->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::OpenURLOffTheRecord(profile_, NewTabUIURL()); + 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_); + AboutChromeView* about_view = new AboutChromeView(profile_); + ChromeViews::Window* about_dialog = + ChromeViews::Window::CreateChromeWindow(GetTopLevelHWND(), + gfx::Rect(), + about_view, + about_view); + about_dialog->Show(); + about_view->SetDialog(about_dialog); + 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(); + DCHECK(current_tab); + current_tab->AlterTextSize(text_zoom::TEXT_LARGER); + break; + } + + case IDC_ZOOM_MINUS: { + UserMetrics::RecordAction(L"ZoomMinus", profile_); + TabContents* current_tab = GetSelectedTabContents(); + DCHECK(current_tab); + current_tab->AlterTextSize(text_zoom::TEXT_SMALLER); + break; + } + + case IDC_ZOOM_NORMAL: { + UserMetrics::RecordAction(L"ZoomNormal", profile_); + TabContents* current_tab = GetSelectedTabContents(); + DCHECK(current_tab); + current_tab->AlterTextSize(text_zoom::TEXT_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 cur_encoding_name = + CharacterEncoding::GetCanonicalEncodingNameByCommandId(id); + TabContents* current_tab = GetSelectedTabContents(); + if (!cur_encoding_name.empty() && current_tab) + current_tab->SetPageEncoding(cur_encoding_name); + // Update user recently selected encoding list. + 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_); + + // Invert the current pref. + PrefService* prefs = profile_->GetPrefs(); + prefs->SetBoolean(prefs::kShowBookmarkBar, + !prefs->GetBoolean(prefs::kShowBookmarkBar)); + prefs->ScheduleSavePersistentPrefs(g_browser_process->file_thread()); + + // And notify the notification service. + Source<Profile> source(profile_); + NotificationService::current()->Notify( + NOTIFY_BOOKMARK_BAR_VISIBILITY_PREF_CHANGED, source, + NotificationService::NoDetails()); + break; + } + + case IDC_SHOW_HISTORY: + UserMetrics::RecordAction(L"ShowHistory", profile_); + ShowNativeUI(HistoryTabUI::GetURL()); + break; + + case IDC_SHOW_DOWNLOADS: + UserMetrics::RecordAction(L"ShowDownloads", profile_); + ShowNativeUI(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.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, PageTransition::AUTO_BOOKMARK, true, NULL); + break; + } + + default: + LOG(WARNING) << "Received Unimplemented Command: " << id << + " from window " << GetTopLevelHWND(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Command Execution +// + +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 we are showing an interstitial page, we don't need to navigate back + // to the previous page as it is already available in a render view host + // of the WebContents. This makes the back more snappy and avoids potential + // reloading of POST pages. + if (web_contents && web_contents->IsShowingInterstitialPage()) { + // Let the delegate decide (if any) if it wants to handle the back + // navigation (it may have extra things to do). + if (web_contents->interstitial_page_delegate() && + web_contents->interstitial_page_delegate()->GoBack()) { + return; + } + // TODO(jcampan): #1283764 once we refactored and only use the + // interstitial delegate, the code below should go away. + NavigationEntry* prev_nav_entry = web_contents->controller()-> + GetEntryAtOffset(-1); + DCHECK(prev_nav_entry); + // We do a normal back if: + // - the page is not a WebContents, its TabContents might have to be + // recreated. + // - we have not yet visited that navigation entry (typically session + // restore), in which case the page is not already available. + if (prev_nav_entry->GetType() == TAB_CONTENTS_WEB && + !prev_nav_entry->restored()) { + // It is the job of the code that shows the interstitial to listen for + // notifications of the interstitial getting hidden and appropriately + // dealing with the navigation entries. + web_contents->HideInterstitialPage(false, false); + return; + } + } + } + NavigationController* nc = GetSelectedNavigationController(); + if (nc && nc->CanGoBack()) + nc->GoBack(); +} + +void Browser::GoForward() { + NavigationController* nc = GetSelectedNavigationController(); + if (nc && nc->CanGoForward()) + nc->GoForward(); +} + +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::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->IsShowingInterstitialPage()) { + NavigationEntry* entry = current_tab->controller()->GetActiveEntry(); + DCHECK(entry); // Should exist if interstitial is showing. + OpenURL(entry->GetURL(), 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(); + } +} + +void Browser::Home() { + GURL homepage_url(URLFixerUpper::FixupURL( + profile_->GetPrefs()->GetString(prefs::kHomePage), + std::wstring())); + if (!homepage_url.is_valid()) + homepage_url = NewTabUIURL(); + + GetSelectedTabContents()->controller()->LoadURL( + homepage_url, PageTransition::AUTO_BOOKMARK); +} + +void Browser::StarCurrentTabContents() { + TabContents* tab = GetSelectedTabContents(); + if (!tab || !tab->AsWebContents()) + return; + + WebContents* rvh = tab->AsWebContents(); + BookmarkBarModel* model = tab->profile()->GetBookmarkBarModel(); + 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->GetDisplayURL(); + if (url.is_empty() || !url.is_valid()) + return; + + if (toolbar_.star_button()) { + if (!toolbar_.star_button()->is_bubble_showing()) { + const bool newly_bookmarked = (model->GetNodeByURL(url) == NULL); + if (newly_bookmarked) { + model->SetURLStarred(url, entry->GetTitle(), true); + if (!model->GetNodeByURL(url)) { + // Starring failed. This shouldn't happen. + NOTREACHED(); + return; + } + } + toolbar_.star_button()->ShowStarBubble(url, newly_bookmarked); + } + } else if (model->GetNodeByURL(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::OpenFindInPageWindow() { + TabContents* current_tab = GetSelectedTabContents(); + if (current_tab && current_tab->AsWebContents()) + current_tab->AsWebContents()->OpenFindInPageWindow(*this); +} + +void Browser::AdoptFindWindow(TabContents* tab_contents) { + if (tab_contents->AsWebContents()) + tab_contents->AsWebContents()->ReparentFindWindow(GetTopLevelHWND()); +} + +bool Browser::AdvanceFindSelection(bool forward_direction) { + TabContents* current_tab = GetSelectedTabContents(); + if (current_tab && current_tab->AsWebContents()) { + current_tab->AsWebContents()->AdvanceFindSelection(forward_direction); + } + + return false; +} + +void Browser::OpenDebuggerWindow() { +#ifndef CHROME_DEBUGGER_DISABLED + TabContents* current_tab = GetSelectedTabContents(); + if (!current_tab) + return; + + if (current_tab->AsWebContents()) { + if (DebuggerWindow::DoesDebuggerExist()) { + // 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 + return; + } + if (!debugger_window_.get()) { + debugger_window_ = new DebuggerWindow(); + } + debugger_window_->Show(current_tab); + } +#endif +} + +void Browser::OpenKeywordEditor() { + KeywordEditorView::Show(profile()); +} + +void Browser::OpenImportSettingsDialog() { + ImporterView* importer_view = new ImporterView(profile_); + ChromeViews::Window* importer_dialog = + ChromeViews::Window::CreateChromeWindow(GetTopLevelHWND(), gfx::Rect(), + importer_view, importer_view); + importer_dialog->Show(); + importer_view->set_dialog(importer_dialog); +} + +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()->GetURL()); + } + } + + // 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); + + // 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 + ChromeViews::Window* bug_report_dialog = + ChromeViews::Window::CreateChromeWindow(GetTopLevelHWND(), gfx::Rect(), + bug_report_view, bug_report_view); + bug_report_dialog->Show(); + bug_report_view->set_dialog(bug_report_dialog); +} + +void Browser::OpenClearBrowsingDataDialog() { + ClearBrowsingDataView* clear_browsing_data_view = + new ClearBrowsingDataView(profile_); + ChromeViews::Window* clear_browsing_data_dialog = + ChromeViews::Window::CreateChromeWindow( + GetTopLevelHWND(), gfx::Rect(), + clear_browsing_data_view, clear_browsing_data_view); + clear_browsing_data_dialog->Show(); + clear_browsing_data_view->SetDialog(clear_browsing_data_dialog); +} + +void Browser::RunSimpleFrameMenu(const CPoint& pt, HWND hwnd) { + bool for_popup = !IsApplication(); + EncodingMenuControllerDelegate d(this, &controller_); + + // The menu's anchor point is different based on the UI layout. + Menu::AnchorPoint anchor; + if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) + anchor = Menu::TOPRIGHT; + else + anchor = Menu::TOPLEFT; + + Menu m(&d, anchor, hwnd); + m.AppendMenuItemWithLabel(IDC_BACK, + l10n_util::GetString(IDS_CONTENT_CONTEXT_BACK)); + m.AppendMenuItemWithLabel(IDC_FORWARD, + l10n_util::GetString( + IDS_CONTENT_CONTEXT_FORWARD)); + m.AppendMenuItemWithLabel(IDC_RELOAD, + l10n_util::GetString(IDS_APP_MENU_RELOAD)); + m.AppendSeparator(); + m.AppendMenuItemWithLabel(IDC_DUPLICATE, + l10n_util::GetString(IDS_APP_MENU_DUPLICATE)); + m.AppendMenuItemWithLabel(IDC_COPY_URL, + l10n_util::GetString(IDS_APP_MENU_COPY_URL)); + if (for_popup) { + m.AppendMenuItemWithLabel(IDC_SHOW_AS_TAB, + l10n_util::GetString(IDS_SHOW_AS_TAB)); + } + m.AppendMenuItemWithLabel(IDC_NEWTAB, + l10n_util::GetString(IDS_APP_MENU_NEW_WEB_PAGE)); + m.AppendSeparator(); + m.AppendMenuItemWithLabel(IDC_CUT, l10n_util::GetString(IDS_CUT)); + m.AppendMenuItemWithLabel(IDC_COPY, l10n_util::GetString(IDS_COPY)); + m.AppendMenuItemWithLabel(IDC_PASTE, l10n_util::GetString(IDS_PASTE)); + m.AppendSeparator(); + m.AppendMenuItemWithLabel(IDC_FIND, l10n_util::GetString(IDS_FIND_IN_PAGE)); + m.AppendMenuItemWithLabel(IDC_SAVEPAGE, l10n_util::GetString(IDS_SAVEPAGEAS)); + m.AppendMenuItemWithLabel(IDC_PRINT, l10n_util::GetString(IDS_PRINT)); + m.AppendSeparator(); + Menu* zoom_menu = m.AppendSubMenu(IDC_ZOOM, + l10n_util::GetString(IDS_ZOOM)); + zoom_menu->AppendMenuItemWithLabel(IDC_ZOOM_PLUS, + l10n_util::GetString(IDS_ZOOM_PLUS)); + zoom_menu->AppendMenuItemWithLabel(IDC_ZOOM_NORMAL, + l10n_util::GetString(IDS_ZOOM_NORMAL)); + zoom_menu->AppendMenuItemWithLabel(IDC_ZOOM_MINUS, + l10n_util::GetString(IDS_ZOOM_MINUS)); + + // Create encoding menu. + Menu* encoding_menu = m.AppendSubMenu(IDC_ENCODING, + l10n_util::GetString(IDS_ENCODING)); + EncodingMenuControllerDelegate::BuildEncodingMenu(profile_, encoding_menu); + + m.AppendSeparator(); + m.AppendMenuItemWithLabel(IDC_CLOSE_WEB_APP, l10n_util::GetString(IDS_CLOSE)); + m.RunMenuAt(pt.x, pt.y); +} + +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(); + } +} + +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); + DCHECK(contents); + + Browser* new_browser = NULL; + + BrowserType::Type t; + + // Is this an application? + if (type_ == BrowserType::TABBED_BROWSER) + t = BrowserType::TABBED_BROWSER; + else + t = BrowserType::APPLICATION; + + new_browser = new Browser(gfx::Rect(), SW_SHOWNORMAL, profile(), t, + app_name_); + + // We need to show the browser now. Otherwise HWNDViewContainer assumes + // the tab contents is invisible and won't size it. + new_browser->Show(); + + // The page transition below is only for the purpose of inserting the tab. + TabContents* new_contents = new_browser->AddTabWithNavigationController( + contents->controller()->Clone(new_browser->GetTopLevelHWND()), + PageTransition::LINK); + if (profile_->HasSessionService()) { + SessionService* session_service = profile_->GetSessionService(); + if (session_service) + session_service->TabRestored(new_contents->controller()); + } + + new_browser->MoveToFront(true); +} + +//////////////////////////////////////////////////////////////////////////////// +// Browser, SelectFileDialog::Listener implementation: + +void Browser::FileSelected(const std::wstring& path, void* params) { + GURL file_url = net_util::FilePathToFileURL(path); + if (!file_url.is_empty()) + OpenURL(file_url, CURRENT_TAB, PageTransition::TYPED); +} |