chromiumUI中从处理url键盘输入到内建url页面内容准备的函数调用过程

(22) 2024-05-01 14:01:01

前言

在chromium中输入url时, 想看看在哪处理的键盘输入。
还想看看, 输入内建url时,从键盘处理到url页面数据准备的全过程。
在chromium工程中可以看到内建url索引页面的url内容

Z:\chromium\src\chrome\common\webui_url_constants.cc
const char kChromeUIChromeURLsURL[] = "chrome://chrome-urls/";

所有可用的chromium buildin url list

在chromium的url输入框,输入以下url, 会显示出chromium所有的内建url
chrome://chrome-urls/

List of Chrome URLs
chrome://about
chrome://accessibility
chrome://appcache-internals
chrome://apps
chrome://blob-internals
chrome://bluetooth-internals
chrome://bookmarks
chrome://chrome
chrome://chrome-urls
chrome://components
chrome://conflicts
chrome://crashes
chrome://credits
chrome://device-log
chrome://devices
chrome://dino
chrome://discards
chrome://dns
chrome://download-internals
chrome://downloads
chrome://extensions
chrome://flags
chrome://flash
chrome://gcm-internals
chrome://gpu
chrome://help
chrome://histograms
chrome://history
chrome://indexeddb-internals
chrome://inspect
chrome://interventions-internals
chrome://invalidations
chrome://local-state
chrome://media-engagement
chrome://media-internals
chrome://nacl
chrome://net-export
chrome://net-internals
chrome://network-error
chrome://network-errors
chrome://newtab
chrome://ntp-tiles-internals
chrome://omnibox
chrome://password-manager-internals
chrome://policy
chrome://predictors
chrome://print
chrome://quota-internals
chrome://safe-browsing
chrome://serviceworker-internals
chrome://settings
chrome://signin-internals
chrome://site-engagement
chrome://suggestions
chrome://supervised-user-internals
chrome://sync-internals
chrome://system
chrome://taskscheduler-internals
chrome://terms
chrome://thumbnails
chrome://tracing
chrome://translate-internals
chrome://usb-internals
chrome://user-actions
chrome://version
chrome://webrtc-internals
chrome://webrtc-logs
For Debug
The following pages are for debugging purposes only. Because they crash or hang the renderer, they're not linked directly; you can type them into the address bar if you need them.

chrome://badcastcrash/
chrome://inducebrowsercrashforrealz/
chrome://crash/
chrome://crashdump/
chrome://kill/
chrome://hang/
chrome://shorthang/
chrome://gpuclean/
chrome://gpucrash/
chrome://gpuhang/
chrome://memory-exhaust/
chrome://ppapiflashcrash/
chrome://ppapiflashhang/
chrome://quit/
chrome://restart/

实验

// Z:\chromium\src\ui\views\win\hwnd_message_handler.cc
// @note ls 在chromiumUI中输入按下任意键的处理函数
LRESULT HWNDMessageHandler::OnKeyEvent(UINT message,
                                       WPARAM w_param,
                                       LPARAM l_param) {
  MSG msg = {
      hwnd(), message, w_param, l_param, static_cast<DWORD>(GetMessageTime())};
  ui::KeyEvent key(msg);
  base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
  delegate_->HandleKeyEvent(&key);
  if (!ref)
    return 0;
  if (!key.handled())
    SetMsgHandled(FALSE);
  return 0;
}

// Z:\chromium\src\ui\views\widget\desktop_aura\desktop_window_tree_host_win.cc
// 在chromiumUI中按下任意键, 来到这
void DesktopWindowTreeHostWin::HandleKeyEvent(ui::KeyEvent* event) {
  SendEventToSink(event);
}
// Z:\chromium\src\chrome\browser\ui\exclusive_access\exclusive_access_manager.cc
bool ExclusiveAccessManager::HandleUserKeyEvent(
    const content::NativeWebKeyboardEvent& event) {
  if (event.windows_key_code != ui::VKEY_ESCAPE) {
    OnUserInput(); // this
    return false;
  }

  // Give the |keyboard_lock_controller_| first chance at handling the ESC event
  // as there are specific UX behaviors that occur when that mode is active
  // which are coordinated by that class.  Return false as we don't want to
  // prevent the event from propagating to the webpage.
  if (keyboard_lock_controller_.HandleKeyEvent(event))
    return false;

  bool handled = false;
  handled = fullscreen_controller_.HandleUserPressedEscape();
  handled |= mouse_lock_controller_.HandleUserPressedEscape();
  handled |= keyboard_lock_controller_.HandleUserPressedEscape();
  return handled;
}

// Z:\chromium\src\ui\views\controls\textfield\textfield.cc
bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
  ui::TextEditCommand edit_command = scheduled_text_edit_command_;
  scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND;

  // Since HandleKeyEvent() might destroy |this|, get a weak pointer and verify
  // it isn't null before proceeding.
  base::WeakPtr<Textfield> textfield(weak_ptr_factory_.GetWeakPtr());

  bool handled = controller_ && controller_->HandleKeyEvent(this, event);

  if (!textfield)
    return handled;

#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
  ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
      ui::GetTextEditKeyBindingsDelegate();
  std::vector<ui::TextEditCommandAuraLinux> commands;
  if (!handled && delegate && delegate->MatchEvent(event, &commands)) {
    for (size_t i = 0; i < commands.size(); ++i) {
      if (IsTextEditCommandEnabled(commands[i].command())) {
        ExecuteTextEditCommand(commands[i].command());
        handled = true;
      }
    }
    return handled;
  }
#endif

  if (edit_command == ui::TextEditCommand::INVALID_COMMAND)
    edit_command = GetCommandForKeyEvent(event);

  if (!handled && IsTextEditCommandEnabled(edit_command)) {
    ExecuteTextEditCommand(edit_command);
    handled = true;
  }
  return handled;
}
// Z:\chromium\src\chrome\browser\ui\views\omnibox\omnibox_view_views.cc
bool OmniboxViewViews::HandleKeyEvent(views::Textfield* textfield,
                                      const ui::KeyEvent& event) {
  if (event.type() == ui::ET_KEY_RELEASED) {
    // The omnibox contents may change while the control key is pressed.
    if (event.key_code() == ui::VKEY_CONTROL)
      model()->OnControlKeyChanged(false);
    else if (event.key_code() == ui::VKEY_SHIFT)
      OnShiftKeyChanged(false);

    return false;
  }

  // Skip processing of [Alt]+<num-pad digit> Unicode alt key codes.
  // Otherwise, if num-lock is off, the events are handled as [Up], [Down], etc.
  if (event.IsUnicodeKeyCode())
    return false;

  const bool shift = event.IsShiftDown();
  const bool control = event.IsControlDown();
  const bool alt = event.IsAltDown() || event.IsAltGrDown();
#if defined(OS_MACOSX)
  const bool command = event.IsCommandDown();
#else
  const bool command = false;
#endif
  switch (event.key_code()) {
    case ui::VKEY_RETURN:
      // url输入栏回车,会在这最终处理
      if (model()->popup_model()->SelectedLineHasTabMatch() &&
          model()->popup_model()->selected_line_state() ==
              OmniboxPopupModel::TAB_SWITCH) {
        popup_view_->OpenMatch(WindowOpenDisposition::SWITCH_TO_TAB);
      } else {
        if (alt) {
          model()->AcceptInput(WindowOpenDisposition::NEW_FOREGROUND_TAB,
                               false);
        } else if (command) {
          model()->AcceptInput(WindowOpenDisposition::NEW_BACKGROUND_TAB,
                               false);
        } else {
          // 开始处理url栏回车
          model()->AcceptInput(WindowOpenDisposition::CURRENT_TAB, false);
        }
      }
      return true;

    case ui::VKEY_ESCAPE:
      return model()->OnEscapeKeyPressed();

    case ui::VKEY_CONTROL:
      model()->OnControlKeyChanged(true);
      break;

    case ui::VKEY_SHIFT:
      OnShiftKeyChanged(true);
      break;

    case ui::VKEY_DELETE:
      if (shift && model()->popup_model()->IsOpen())
        model()->popup_model()->TryDeletingCurrentItem();
      break;

    case ui::VKEY_UP:
      if (IsTextEditCommandEnabled(ui::TextEditCommand::MOVE_UP)) {
        ExecuteTextEditCommand(ui::TextEditCommand::MOVE_UP);
        return true;
      }
      break;

    case ui::VKEY_DOWN:
      if (IsTextEditCommandEnabled(ui::TextEditCommand::MOVE_DOWN)) {
        ExecuteTextEditCommand(ui::TextEditCommand::MOVE_DOWN);
        return true;
      }
      break;

    case ui::VKEY_PRIOR:
      if (control || alt || shift)
        return false;
      model()->OnUpOrDownKeyPressed(-1 * model()->result().size());
      return true;

    case ui::VKEY_NEXT:
      if (control || alt || shift)
        return false;
      model()->OnUpOrDownKeyPressed(model()->result().size());
      return true;

    case ui::VKEY_V:
      if (control && !alt &&
          IsTextEditCommandEnabled(ui::TextEditCommand::PASTE)) {
        ExecuteTextEditCommand(ui::TextEditCommand::PASTE);
        return true;
      }
      break;

    case ui::VKEY_INSERT:
      if (shift && !control &&
          IsTextEditCommandEnabled(ui::TextEditCommand::PASTE)) {
        ExecuteTextEditCommand(ui::TextEditCommand::PASTE);
        return true;
      }
      break;

    case ui::VKEY_BACK:
      // No extra handling is needed in keyword search mode, if there is a
      // non-empty selection, or if the cursor is not leading the text.
      if (model()->is_keyword_hint() || model()->keyword().empty() ||
          HasSelection() || GetCursorPosition() != 0)
        return false;
      model()->ClearKeyword();
      return true;

    case ui::VKEY_HOME:
      // The Home key indicates that the user wants to move the cursor to the
      // beginning of the full URL, so it should always trigger an unelide.
      if (UnapplySteadyStateElisions(UnelisionGesture::HOME_KEY_PRESSED)) {
        if (shift) {
          // After uneliding, we need to move the end of the selection range
          // to the beginning of the full unelided URL.
          size_t start, end;
          GetSelectionBounds(&start, &end);
          SelectRange(gfx::Range(start, 0));
        } else {
          // After uneliding, move the caret to the beginning of the full
          // unelided URL.
          SetCaretPos(0);
        }

        TextChanged();
        return true;
      }
      break;

    default:
      break;
  }

  return HandleEarlyTabActions(event);
}

// Z:\chromium\src\chrome\browser\autocomplete\chrome_autocomplete_provider_client.cc
// 在url输入栏键入字符后,会有自动完成的预备操作
std::vector<base::string16>
ChromeAutocompleteProviderClient::GetBuiltinsToProvideAsUserTypes() {
  std::vector<base::string16> builtins_to_provide;
  builtins_to_provide.push_back(
      base::ASCIIToUTF16(chrome::kChromeUIChromeURLsURL));
#if !defined(OS_ANDROID)
  builtins_to_provide.push_back(
      base::ASCIIToUTF16(chrome::kChromeUISettingsURL));
#endif
  builtins_to_provide.push_back(
      base::ASCIIToUTF16(chrome::kChromeUIVersionURL));
  return builtins_to_provide;
}

// url输入框的接收输入的处理
void OmniboxEditModel::AcceptInput(WindowOpenDisposition disposition,
                                   bool for_drop) {
  // Get the URL and transition type for the selected entry.
  GURL alternate_nav_url;
  AutocompleteMatch match = CurrentMatch(&alternate_nav_url);

  // If CTRL is down it means the user wants to append ".com" to the text they
  // typed. If we can successfully generate a URL_WHAT_YOU_TYPED match doing
  // that, then we use this. These matches are marked as generated by the
  // HistoryURLProvider so we only generate them if this provider is present.
  if (control_key_state_ == DOWN_WITHOUT_CHANGE && !is_keyword_selected() &&
      autocomplete_controller()->history_url_provider()) {
    // Generate a new AutocompleteInput, copying the latest one but using "com"
    // as the desired TLD. Then use this autocomplete input to generate a
    // URL_WHAT_YOU_TYPED AutocompleteMatch. Note that using the most recent
    // input instead of the currently visible text means we'll ignore any
    // visible inline autocompletion: if a user types "foo" and is autocompleted
    // to "foodnetwork.com", ctrl-enter will navigate to "foo.com", not
    // "foodnetwork.com".  At the time of writing, this behavior matches
    // Internet Explorer, but not Firefox.
    AutocompleteInput input(
        has_temporary_text_ ? view_->GetText() : input_.text(),
        input_.cursor_position(), "com", input_.current_page_classification(),
        client_->GetSchemeClassifier());
    input.set_prevent_inline_autocomplete(input_.prevent_inline_autocomplete());
    input.set_prefer_keyword(input_.prefer_keyword());
    input.set_allow_exact_keyword_match(input_.allow_exact_keyword_match());
    input.set_want_asynchronous_matches(input_.want_asynchronous_matches());
    input.set_from_omnibox_focus(input_.from_omnibox_focus());
    input_ = input;
    AutocompleteMatch url_match(
        autocomplete_controller()->history_url_provider()->SuggestExactInput(
            input_, input_.canonicalized_url(), false));

    if (url_match.destination_url.is_valid()) {
      // We have a valid URL, we use this newly generated AutocompleteMatch.
      match = url_match;
      alternate_nav_url = GURL();
    }
  }

  if (!match.destination_url.is_valid())
    return;

  if (ui::PageTransitionCoreTypeIs(match.transition,
                                   ui::PAGE_TRANSITION_TYPED) &&
      (match.destination_url == PermanentURL())) {
    // When the user hit enter on the existing permanent URL, treat it like a
    // reload for scoring purposes.  We could detect this by just checking
    // user_input_in_progress_, but it seems better to treat "edits" that end
    // up leaving the URL unchanged (e.g. deleting the last character and then
    // retyping it) as reloads too.  We exclude non-TYPED transitions because if
    // the transition is GENERATED, the user input something that looked
    // different from the current URL, even if it wound up at the same place
    // (e.g. manually retyping the same search query), and it seems wrong to
    // treat this as a reload.
    match.transition = ui::PAGE_TRANSITION_RELOAD;
  } else if (for_drop ||
             ((paste_state_ != NONE) &&
              (match.type == AutocompleteMatchType::URL_WHAT_YOU_TYPED))) {
    // When the user pasted in a URL and hit enter, score it like a link click
    // rather than a normal typed URL, so it doesn't get inline autocompleted
    // as aggressively later.
    match.transition = ui::PAGE_TRANSITION_LINK;
  }

  client_->OnInputAccepted(match);

  DCHECK(popup_model());
  // 打开内建url
  view_->OpenMatch(match, disposition, alternate_nav_url, base::string16(),
                   popup_model()->selected_line());
}

void OmniboxView::OpenMatch(const AutocompleteMatch& match,
                            WindowOpenDisposition disposition,
                            const GURL& alternate_nav_url,
                            const base::string16& pasted_text,
                            size_t selected_line) {
  // Invalid URLs such as chrome://history can end up here.
  if (!match.destination_url.is_valid() || !model_)
    return;
   
  // open buildin url
  model_->OpenMatch(
      match, disposition, alternate_nav_url, pasted_text, selected_line);

void OmniboxEditModel::OpenMatch(AutocompleteMatch match,
                                 WindowOpenDisposition disposition,
                                 const GURL& alternate_nav_url,
                                 const base::string16& pasted_text,
                                 size_t index) {
  const base::TimeTicks& now(base::TimeTicks::Now());
  base::TimeDelta elapsed_time_since_user_first_modified_omnibox(
      now - time_user_first_modified_omnibox_);
  autocomplete_controller()->UpdateMatchDestinationURLWithQueryFormulationTime(
      elapsed_time_since_user_first_modified_omnibox, &match);

  base::string16 input_text(pasted_text);
  if (input_text.empty())
    input_text = user_input_in_progress_ ? user_text_ : url_for_editing_;
  // Create a dummy AutocompleteInput for use in calling SuggestExactInput()
  // to create an alternate navigational match.
  AutocompleteInput alternate_input(input_text, ClassifyPage(),
                                    client_->GetSchemeClassifier());
  // Somehow we can occasionally get here with no active tab.  It's not
  // clear why this happens.
  alternate_input.set_current_url(client_->GetURL());
  alternate_input.set_current_title(client_->GetTitle());
  std::unique_ptr<OmniboxNavigationObserver> observer(
      client_->CreateOmniboxNavigationObserver(
          input_text, match,
          autocomplete_controller()->history_url_provider()->SuggestExactInput(
              alternate_input, alternate_nav_url, false)));

  base::TimeDelta elapsed_time_since_last_change_to_default_match(
      now - autocomplete_controller()->last_time_default_match_changed());
  DCHECK(match.provider);
  // These elapsed times don't really make sense for matches that come from
  // omnibox focus (because the user did not modify the omnibox), so for those
  // we set the elapsed times to something that will be ignored by
  // metrics_log.cc.  They also don't necessarily make sense if the omnibox
  // dropdown is closed or the user used a paste-and-go action.  (In most
  // cases when this happens, the user never modified the omnibox.)
  const bool popup_open = PopupIsOpen();
  if (input_.from_omnibox_focus() || !popup_open || !pasted_text.empty()) {
    const base::TimeDelta default_time_delta =
        base::TimeDelta::FromMilliseconds(-1);
    elapsed_time_since_user_first_modified_omnibox = default_time_delta;
    elapsed_time_since_last_change_to_default_match = default_time_delta;
  }
  // If the popup is closed or this is a paste-and-go action (meaning the
  // contents of the dropdown are ignored regardless), we record for logging
  // purposes a selected_index of 0 and a suggestion list as having a single
  // entry of the match used.
  const bool dropdown_ignored = !popup_open || !pasted_text.empty();
  ACMatches fake_single_entry_matches;
  fake_single_entry_matches.push_back(match);
  AutocompleteResult fake_single_entry_result;
  fake_single_entry_result.AppendMatches(input_, fake_single_entry_matches);
  OmniboxLog log(
      input_.from_omnibox_focus() ? base::string16() : input_text,
      just_deleted_text_,
      input_.type(),
      popup_open,
      dropdown_ignored ? 0 : index,
      disposition,
      !pasted_text.empty(),
      SessionID::InvalidValue(), // don't know tab ID; set later if appropriate
      ClassifyPage(),
      elapsed_time_since_user_first_modified_omnibox,
      match.allowed_to_be_default_match ? match.inline_autocompletion.length() :
          base::string16::npos,
      elapsed_time_since_last_change_to_default_match,
      dropdown_ignored ? fake_single_entry_result : result());
  DCHECK(dropdown_ignored ||
         (log.elapsed_time_since_user_first_modified_omnibox >=
          log.elapsed_time_since_last_change_to_default_match))
      << "We should've got the notification that the user modified the "
      << "omnibox text at same time or before the most recent time the "
      << "default match changed.";

  if ((disposition == WindowOpenDisposition::CURRENT_TAB) &&
      client_->CurrentPageExists()) {
    // If we know the destination is being opened in the current tab,
    // we can easily get the tab ID.  (If it's being opened in a new
    // tab, we don't know the tab ID yet.)
    log.tab_id = client_->GetSessionID();
  }
  autocomplete_controller()->AddProvidersInfo(&log.providers_info);
  client_->OnURLOpenedFromOmnibox(&log);
  OmniboxEventGlobalTracker::GetInstance()->OnURLOpened(&log);
  LOCAL_HISTOGRAM_BOOLEAN("Omnibox.EventCount", true);
  if (!last_omnibox_focus_.is_null()) {
    // Only record focus to open time when a focus actually happened (as
    // opposed to, say, dragging a link onto the omnibox).
    UMA_HISTOGRAM_MEDIUM_TIMES(kFocusToOpenTimeHistogram,
                               now - last_omnibox_focus_);
  }

  TemplateURLService* service = client_->GetTemplateURLService();
  TemplateURL* template_url = match.GetTemplateURL(service, false);
  if (template_url) {
    if (ui::PageTransitionTypeIncludingQualifiersIs(
            match.transition, ui::PAGE_TRANSITION_KEYWORD)) {
      // The user is using a non-substituting keyword or is explicitly in
      // keyword mode.

      // Don't increment usage count for extension keywords.
      if (client_->ProcessExtensionKeyword(template_url, match, disposition,
                                           observer.get())) {
        if (disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB)
          view_->RevertAll();
        return;
      }

      base::RecordAction(base::UserMetricsAction("AcceptedKeyword"));
      client_->GetTemplateURLService()->IncrementUsageCount(template_url);
    } else {
      DCHECK(ui::PageTransitionTypeIncludingQualifiersIs(
          match.transition, ui::PAGE_TRANSITION_GENERATED));
      // NOTE: We purposefully don't increment the usage count of the default
      // search engine here like we do for explicit keywords above; see comments
      // in template_url.h.
    }

    SearchEngineType search_engine_type = match.destination_url.is_valid() ?
        TemplateURLPrepopulateData::GetEngineType(match.destination_url) :
        SEARCH_ENGINE_OTHER;
    UMA_HISTOGRAM_ENUMERATION("Omnibox.SearchEngineType", search_engine_type,
                              SEARCH_ENGINE_MAX);
  } else {
    // |match| is a URL navigation, not a search.
    // For logging the below histogram, only record uses that depend on the
    // omnibox suggestion system, i.e., TYPED navigations.  That is, exclude
    // omnibox URL interactions that are treated as reloads or link-following
    // (i.e., cut-and-paste of URLs).
    if (ui::PageTransitionTypeIncludingQualifiersIs(match.transition,
                                                    ui::PAGE_TRANSITION_TYPED))
      navigation_metrics::RecordOmniboxURLNavigation(match.destination_url);
  }

  if (disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB) {
    base::AutoReset<bool> tmp(&in_revert_, true);
    view_->RevertAll();  // Revert the box to its unedited state.
  }

  // Track whether the destination URL sends us to a search results page
  // using the default search provider.
  TemplateURLService* template_url_service = client_->GetTemplateURLService();
  if (template_url_service &&
      template_url_service->IsSearchResultsPageFromDefaultSearchProvider(
          match.destination_url)) {
    base::RecordAction(
        base::UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP"));
  }
  if (match.destination_url.is_valid()) {
    // This calls RevertAll again.
    base::AutoReset<bool> tmp(&in_revert_, true);
    controller_->OnAutocompleteAccept(
        match.destination_url, disposition,
        ui::PageTransitionFromInt(
            match.transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR),
        match.type);

    // The observer should have been synchronously notified of a pending load.
    if (observer && observer->HasSeenPendingLoad())
      ignore_result(observer.release());  // The observer will delete itself.
  }

  BookmarkModel* bookmark_model = client_->GetBookmarkModel();
  if (bookmark_model && bookmark_model->IsBookmarked(match.destination_url))
    client_->OnBookmarkLaunched();
}

// if input is buildin url, process here
void ChromeOmniboxEditController::OnAutocompleteAccept(
    const GURL& destination_url,
    WindowOpenDisposition disposition,
    ui::PageTransition transition,
    AutocompleteMatchType::Type match_type) {
  OmniboxEditController::OnAutocompleteAccept(destination_url, disposition,
                                              transition, match_type);
  if (command_updater_)
    command_updater_->ExecuteCommand(IDC_OPEN_CURRENT_URL); // 打开url

#if BUILDFLAG(ENABLE_EXTENSIONS)
  extensions::MaybeShowExtensionControlledSearchNotification(
      GetWebContents(), match_type);
#endif
}

// only save Autocomplete parameter
void OmniboxEditController::OnAutocompleteAccept(
    const GURL& destination_url,
    WindowOpenDisposition disposition,
    ui::PageTransition transition,
    AutocompleteMatchType::Type type) {
  destination_url_ = destination_url; // chrome://version/
  disposition_ = disposition; // CURRENT_TAB
  transition_ = transition; // 0x02000001
}

bool BrowserCommandController::ExecuteCommand(int id) {
  return ExecuteCommandWithDisposition(id, WindowOpenDisposition::CURRENT_TAB);
}

所有浏览器命令都在这处理了

// Z:\chromium\src\chrome\browser\ui\browser_command_controller.cc
bool BrowserCommandController::ExecuteCommandWithDisposition(
    int id, WindowOpenDisposition disposition) {
  // Doesn't go through the command_updater_ to avoid dealing with having a
  // naming collision for ExecuteCommandWithDisposition (both
  // CommandUpdaterDelegate and CommandUpdater declare this function so we
  // choose to not implement CommandUpdaterDelegate inside this class and
  // therefore command_updater_ doesn't have the delegate set).
  if (!SupportsCommand(id) || !IsCommandEnabled(id))
    return false;

  // No commands are enabled if there is not yet any selected tab.
  // TODO(pkasting): It seems like we should not need this, because either
  // most/all commands should not have been enabled yet anyway or the ones that
  // are enabled should be global, or safe themselves against having no selected
  // tab.  However, Ben says he tried removing this before and got lots of
  // crashes, e.g. from Windows sending WM_COMMANDs at random times during
  // window construction.  This probably could use closer examination someday.
  if (browser_->tab_strip_model()->active_index() == TabStripModel::kNoTab)
    return true;

  DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command "
                                                << id;

  // The order of commands in this switch statement must match the function
  // declaration order in browser.h!
  switch (id) {
    // Navigation commands
    case IDC_BACK:
      GoBack(browser_, disposition);
      break;
    case IDC_FORWARD:
      GoForward(browser_, disposition);
      break;
    case IDC_RELOAD:
      Reload(browser_, disposition);
      break;
    case IDC_RELOAD_CLEARING_CACHE:
      ClearCache(browser_);
      FALLTHROUGH;
    case IDC_RELOAD_BYPASSING_CACHE:
      ReloadBypassingCache(browser_, disposition);
      break;
    case IDC_HOME:
      Home(browser_, disposition);
      break;
    case IDC_OPEN_CURRENT_URL:
      OpenCurrentURL(browser_); // open url
      break;
    case IDC_STOP:
      Stop(browser_);
      break;

     // Window management commands
    case IDC_NEW_WINDOW:
      NewWindow(browser_);
      break;
    case IDC_NEW_INCOGNITO_WINDOW:
      NewIncognitoWindow(browser_);
      break;
    case IDC_CLOSE_WINDOW:
      base::RecordAction(base::UserMetricsAction("CloseWindowByKey"));
      CloseWindow(browser_);
      break;
    case IDC_NEW_TAB: {
      NewTab(browser_);
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
      // This is not in NewTab() to avoid tracking programmatic creation of new
      // tabs by extensions.
      auto* new_tab_tracker =
          feature_engagement::NewTabTrackerFactory::GetInstance()
              ->GetForProfile(profile());

      new_tab_tracker->OnNewTabOpened();
      new_tab_tracker->CloseBubble();
#endif
      break;
    }
    case IDC_CLOSE_TAB:
      base::RecordAction(base::UserMetricsAction("CloseTabByKey"));
      CloseTab(browser_);
      break;
    case IDC_SELECT_NEXT_TAB:
      base::RecordAction(base::UserMetricsAction("Accel_SelectNextTab"));
      SelectNextTab(browser_);
      break;
    case IDC_SELECT_PREVIOUS_TAB:
      base::RecordAction(base::UserMetricsAction("Accel_SelectPreviousTab"));
      SelectPreviousTab(browser_);
      break;
    case IDC_MOVE_TAB_NEXT:
      MoveTabNext(browser_);
      break;
    case IDC_MOVE_TAB_PREVIOUS:
      MoveTabPrevious(browser_);
      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:
      base::RecordAction(base::UserMetricsAction("Accel_SelectNumberedTab"));
      SelectNumberedTab(browser_, id - IDC_SELECT_TAB_0);
      break;
    case IDC_SELECT_LAST_TAB:
      base::RecordAction(base::UserMetricsAction("Accel_SelectNumberedTab"));
      SelectLastTab(browser_);
      break;
    case IDC_DUPLICATE_TAB:
      DuplicateTab(browser_);
      break;
    case IDC_RESTORE_TAB:
      RestoreTab(browser_);
      break;
    case IDC_SHOW_AS_TAB:
      ConvertPopupToTabbedBrowser(browser_);
      break;
    case IDC_FULLSCREEN:
      chrome::ToggleFullscreenMode(browser_);
      break;
    case IDC_OPEN_IN_PWA_WINDOW:
      base::RecordAction(base::UserMetricsAction("OpenActiveTabInPwaWindow"));
      ReparentSecureActiveTabIntoPwaWindow(browser_);
      break;

#if defined(OS_CHROMEOS)
    case IDC_VISIT_DESKTOP_OF_LRU_USER_2:
    case IDC_VISIT_DESKTOP_OF_LRU_USER_3:
      ExecuteVisitDesktopCommand(id, window()->GetNativeWindow());
      break;
#endif

#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    case IDC_MINIMIZE_WINDOW:
      browser_->window()->Minimize();
      break;
    case IDC_MAXIMIZE_WINDOW:
      browser_->window()->Maximize();
      break;
    case IDC_RESTORE_WINDOW:
      browser_->window()->Restore();
      break;
    case IDC_USE_SYSTEM_TITLE_BAR: {
      PrefService* prefs = profile()->GetPrefs();
      prefs->SetBoolean(prefs::kUseCustomChromeFrame,
                        !prefs->GetBoolean(prefs::kUseCustomChromeFrame));
      break;
    }
#endif

#if defined(OS_MACOSX)
    case IDC_TOGGLE_FULLSCREEN_TOOLBAR:
      chrome::ToggleFullscreenToolbar(browser_);
      break;
    case IDC_TOGGLE_JAVASCRIPT_APPLE_EVENTS: {
      PrefService* prefs = profile()->GetPrefs();
      prefs->SetBoolean(prefs::kAllowJavascriptAppleEvents,
                        !prefs->GetBoolean(prefs::kAllowJavascriptAppleEvents));
      break;
    }
#endif
    case IDC_EXIT:
      Exit();
      break;

    // Page-related commands
    case IDC_SAVE_PAGE:
      SavePage(browser_);
      break;
    case IDC_BOOKMARK_PAGE:
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
      feature_engagement::BookmarkTrackerFactory::GetInstance()
          ->GetForProfile(profile())
          ->OnBookmarkAdded();
#endif
      BookmarkCurrentPageAllowingExtensionOverrides(browser_);
      break;
    case IDC_BOOKMARK_ALL_TABS:
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
      feature_engagement::BookmarkTrackerFactory::GetInstance()
          ->GetForProfile(profile())
          ->OnBookmarkAdded();
#endif
      BookmarkAllTabs(browser_);
      break;
    case IDC_VIEW_SOURCE:
      browser_->tab_strip_model()
          ->GetActiveWebContents()
          ->GetMainFrame()
          ->ViewSource();
      break;
    case IDC_EMAIL_PAGE_LOCATION:
      EmailPageLocation(browser_);
      break;
    case IDC_PRINT:
      Print(browser_);
      break;

#if BUILDFLAG(ENABLE_PRINTING)
    case IDC_BASIC_PRINT:
      base::RecordAction(base::UserMetricsAction("Accel_Advanced_Print"));
      BasicPrint(browser_);
      break;
#endif  // ENABLE_PRINTING

    case IDC_SAVE_CREDIT_CARD_FOR_PAGE:
      SaveCreditCard(browser_);
      break;
    case IDC_TRANSLATE_PAGE:
      Translate(browser_);
      break;
    case IDC_MANAGE_PASSWORDS_FOR_PAGE:
      ManagePasswordsForPage(browser_);
      break;

    // Clipboard commands
    case IDC_CUT:
    case IDC_COPY:
    case IDC_PASTE:
      CutCopyPaste(browser_, id);
      break;

    // Find-in-page
    case IDC_FIND:
      Find(browser_);
      break;
    case IDC_FIND_NEXT:
      FindNext(browser_);
      break;
    case IDC_FIND_PREVIOUS:
      FindPrevious(browser_);
      break;

    // Zoom
    case IDC_ZOOM_PLUS:
      Zoom(browser_, content::PAGE_ZOOM_IN);
      break;
    case IDC_ZOOM_NORMAL:
      Zoom(browser_, content::PAGE_ZOOM_RESET);
      break;
    case IDC_ZOOM_MINUS:
      Zoom(browser_, content::PAGE_ZOOM_OUT);
      break;

    // Focus various bits of UI
    case IDC_FOCUS_TOOLBAR:
      base::RecordAction(base::UserMetricsAction("Accel_Focus_Toolbar"));
      FocusToolbar(browser_);
      break;
    case IDC_FOCUS_LOCATION:
      base::RecordAction(base::UserMetricsAction("Accel_Focus_Location"));
      FocusLocationBar(browser_);
      break;
    case IDC_FOCUS_SEARCH:
      base::RecordAction(base::UserMetricsAction("Accel_Focus_Search"));
      FocusSearch(browser_);
      break;
    case IDC_FOCUS_MENU_BAR:
      FocusAppMenu(browser_);
      break;
    case IDC_FOCUS_BOOKMARKS:
      base::RecordAction(base::UserMetricsAction("Accel_Focus_Bookmarks"));
      FocusBookmarksToolbar(browser_);
      break;
    case IDC_FOCUS_INACTIVE_POPUP_FOR_ACCESSIBILITY:
      FocusInactivePopupForAccessibility(browser_);
      break;
    case IDC_FOCUS_NEXT_PANE:
      FocusNextPane(browser_);
      break;
    case IDC_FOCUS_PREVIOUS_PANE:
      FocusPreviousPane(browser_);
      break;

    // Show various bits of UI
    case IDC_OPEN_FILE:
      browser_->OpenFile();
      break;
    case IDC_CREATE_HOSTED_APP:
      CreateBookmarkAppFromCurrentWebContents(browser_);
      break;
    case IDC_DEV_TOOLS:
      ToggleDevToolsWindow(browser_, DevToolsToggleAction::Show());
      break;
    case IDC_DEV_TOOLS_CONSOLE:
      ToggleDevToolsWindow(browser_, DevToolsToggleAction::ShowConsolePanel());
      break;
    case IDC_DEV_TOOLS_DEVICES:
      InspectUI::InspectDevices(browser_);
      break;
    case IDC_DEV_TOOLS_INSPECT:
      ToggleDevToolsWindow(browser_, DevToolsToggleAction::Inspect());
      break;
    case IDC_DEV_TOOLS_TOGGLE:
      ToggleDevToolsWindow(browser_, DevToolsToggleAction::Toggle());
      break;
    case IDC_TASK_MANAGER:
      OpenTaskManager(browser_);
      break;
#if defined(OS_CHROMEOS)
    case IDC_TAKE_SCREENSHOT:
      TakeScreenshot();
      break;
#endif
#if defined(GOOGLE_CHROME_BUILD)
    case IDC_FEEDBACK:
      OpenFeedbackDialog(browser_, kFeedbackSourceBrowserCommand);
      break;
#endif
    case IDC_SHOW_BOOKMARK_BAR:
      ToggleBookmarkBar(browser_);
      break;
    case IDC_PROFILING_ENABLED:
      Profiling::Toggle();
      break;

    case IDC_SHOW_BOOKMARK_MANAGER:
      ShowBookmarkManager(browser_);
      break;
    case IDC_SHOW_APP_MENU:
      base::RecordAction(base::UserMetricsAction("Accel_Show_App_Menu"));
      ShowAppMenu(browser_);
      break;
    case IDC_SHOW_AVATAR_MENU:
      ShowAvatarMenu(browser_);
      break;
    case IDC_SHOW_HISTORY:
      ShowHistory(browser_);
      break;
    case IDC_SHOW_DOWNLOADS:
      ShowDownloads(browser_);
      break;
    case IDC_MANAGE_EXTENSIONS:
      ShowExtensions(browser_, std::string());
      break;
    case IDC_OPTIONS:
      ShowSettings(browser_);
      break;
    case IDC_EDIT_SEARCH_ENGINES:
      ShowSearchEngineSettings(browser_);
      break;
    case IDC_VIEW_PASSWORDS:
      ShowPasswordManager(browser_);
      break;
    case IDC_CLEAR_BROWSING_DATA:
      ShowClearBrowsingDataDialog(browser_);
      break;
    case IDC_IMPORT_SETTINGS:
      ShowImportDialog(browser_);
      break;
    case IDC_TOGGLE_REQUEST_TABLET_SITE:
      ToggleRequestTabletSite(browser_);
      break;
    case IDC_ABOUT:
      ShowAboutChrome(browser_);
      break;
    case IDC_UPGRADE_DIALOG:
      OpenUpdateChromeDialog(browser_);
      break;
    case IDC_VIEW_INCOMPATIBILITIES:
      ShowConflicts(browser_);
      break;
    case IDC_HELP_PAGE_VIA_KEYBOARD:
      ShowHelp(browser_, HELP_SOURCE_KEYBOARD);
      break;
    case IDC_HELP_PAGE_VIA_MENU:
      ShowHelp(browser_, HELP_SOURCE_MENU);
      break;
    case IDC_SHOW_BETA_FORUM:
      ShowBetaForum(browser_);
      break;
    case IDC_SHOW_SIGNIN:
      ShowBrowserSigninOrSettings(
          browser_, signin_metrics::AccessPoint::ACCESS_POINT_MENU);
      break;
    case IDC_DISTILL_PAGE:
      DistillCurrentPage(browser_);
      break;
    case IDC_ROUTE_MEDIA:
      RouteMedia(browser_);
      break;
    case IDC_WINDOW_MUTE_SITE:
      MuteSite(browser_);
      break;
    case IDC_WINDOW_PIN_TAB:
      PinTab(browser_);
      break;

    // Hosted App commands
    case IDC_COPY_URL:
      CopyURL(browser_);
      break;
    case IDC_OPEN_IN_CHROME:
      OpenInChrome(browser_);
      break;
    case IDC_SITE_SETTINGS:
      ShowSiteSettings(
          browser_,
          browser_->tab_strip_model()->GetActiveWebContents()->GetVisibleURL());
      break;
    case IDC_HOSTED_APP_MENU_APP_INFO:
      ShowPageInfoDialog(browser_->tab_strip_model()->GetActiveWebContents(),
                         bubble_anchor_util::kAppMenuButton);
      break;

    default:
      LOG(WARNING) << "Received Unimplemented Command: " << id;
      break;
  }

  return true;
}

// Z:\chromium\src\chrome\browser\ui\browser_commands.cc
void OpenCurrentURL(Browser* browser) {
  base::RecordAction(UserMetricsAction("LoadURL"));
  LocationBar* location_bar = browser->window()->GetLocationBar();
  if (!location_bar)
    return;

  GURL url(location_bar->GetDestinationURL());

  // 构造要导航的url参数
  NavigateParams params(browser, url, location_bar->GetPageTransition());
  params.disposition = location_bar->GetWindowOpenDisposition();
  // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
  // inherit the opener. In some cases the tabstrip will determine the group
  // should be inherited, in which case the group is inherited instead of the
  // opener.
  params.tabstrip_add_types =
      TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
  Navigate(&params); // 导航到目标url

#if BUILDFLAG(ENABLE_EXTENSIONS)
  DCHECK(extensions::ExtensionSystem::Get(
      browser->profile())->extension_service());
  const extensions::Extension* extension =
      extensions::ExtensionRegistry::Get(browser->profile())
          ->enabled_extensions().GetAppByURL(url);
  if (extension) {
    extensions::RecordAppLaunchType(extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
                                    extension->GetType());
  }
#endif
}

// Z:\chromium\src\chrome\browser\ui\browser_navigator.cc
void Navigate(NavigateParams* params) {
  Browser* source_browser = params->browser;
  if (source_browser)
    params->initiating_profile = source_browser->profile();
  DCHECK(params->initiating_profile);

  if (!AdjustNavigateParamsForURL(params))
    return;

#if BUILDFLAG(ENABLE_EXTENSIONS)
  const extensions::Extension* extension =
    extensions::ExtensionRegistry::Get(params->initiating_profile)->
        enabled_extensions().GetExtensionOrAppByURL(params->url);
  // Platform apps cannot navigate. Block the request.
  if (extension && extension->is_platform_app())
    params->url = GURL(chrome::kExtensionInvalidRequestURL);
#endif

  // The browser window may want to adjust the disposition.
  if (params->disposition == WindowOpenDisposition::NEW_POPUP &&
      source_browser && source_browser->window()) {
    params->disposition =
        source_browser->window()->GetDispositionForPopupBounds(
            params->window_bounds);
  }
  // Trying to open a background tab when in an app browser results in
  // focusing a regular browser window an opening a tab in the background
  // of that window. Change the disposition to NEW_FOREGROUND_TAB so that
  // the new tab is focused.
  if (source_browser && source_browser->is_app() &&
      params->disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
    params->disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
  }

  // If no source WebContents was specified, we use the selected one from
  // the target browser. This must happen first, before
  // GetBrowserForDisposition() has a chance to replace |params->browser| with
  // another one.
  if (!params->source_contents && params->browser) {
    params->source_contents =
        params->browser->tab_strip_model()->GetActiveWebContents();
  }

  WebContents* contents_to_navigate_or_insert =
      params->contents_to_insert.get();
  if (params->switch_to_singleton_tab) {
    DCHECK_EQ(params->disposition, WindowOpenDisposition::SINGLETON_TAB);
    contents_to_navigate_or_insert = params->switch_to_singleton_tab;
  }
  int singleton_index;
  std::tie(params->browser, singleton_index) =
      GetBrowserAndTabForDisposition(*params);
  if (!params->browser)
    return;
  if (singleton_index != -1) {
    contents_to_navigate_or_insert =
        params->browser->tab_strip_model()->GetWebContentsAt(singleton_index);
  }
#if defined(OS_CHROMEOS)
  if (source_browser && source_browser != params->browser) {
    // When the newly created browser was spawned by a browser which visits
    // another user's desktop, it should be shown on the same desktop as the
    // originating one. (This is part of the desktop separation per profile).
    MultiUserWindowManager* manager = MultiUserWindowManager::GetInstance();
    // Some unit tests have no manager instantiated.
    if (manager) {
      aura::Window* src_window = source_browser->window()->GetNativeWindow();
      aura::Window* new_window = params->browser->window()->GetNativeWindow();
      const AccountId& src_account_id =
          manager->GetUserPresentingWindow(src_window);
      if (src_account_id != manager->GetUserPresentingWindow(new_window)) {
        // Once the window gets presented, it should be shown on the same
        // desktop as the desktop of the creating browser. Note that this
        // command will not show the window if it wasn't shown yet by the
        // browser creation.
        manager->ShowWindowForUser(new_window, src_account_id);
      }
    }
  }
#endif

  // Navigate() must not return early after this point.

  if (GetSourceProfile(params) != params->browser->profile()) {
    // A tab is being opened from a link from a different profile, we must reset
    // source information that may cause state to be shared.
    params->opener = nullptr;
    params->source_contents = nullptr;
    params->source_site_instance = nullptr;
    params->referrer = content::Referrer();
  }

  // Make sure the Browser is shown if params call for it.
  ScopedBrowserShower shower(params, &contents_to_navigate_or_insert);

  // Makes sure any WebContents created by this function is destroyed if
  // not properly added to a tab strip.
  std::unique_ptr<WebContents> contents_to_insert =
      std::move(params->contents_to_insert);

  // Some dispositions need coercion to base types.
  NormalizeDisposition(params);

  // If a new window has been created, it needs to be shown.
  if (params->window_action == NavigateParams::NO_ACTION &&
      source_browser != params->browser &&
      params->browser->tab_strip_model()->empty()) {
    params->window_action = NavigateParams::SHOW_WINDOW;
  }

  // If we create a popup window from a non user-gesture, don't activate it.
  if (params->window_action == NavigateParams::SHOW_WINDOW &&
      params->disposition == WindowOpenDisposition::NEW_POPUP &&
      params->user_gesture == false) {
    params->window_action = NavigateParams::SHOW_WINDOW_INACTIVE;
  }

  // Determine if the navigation was user initiated. If it was, we need to
  // inform the target WebContents, and we may need to update the UI.
  bool user_initiated =
      params->transition & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR ||
      ui::PageTransitionCoreTypeIs(params->transition,
                                   ui::PAGE_TRANSITION_TYPED) ||
      ui::PageTransitionCoreTypeIs(params->transition,
                                   ui::PAGE_TRANSITION_AUTO_BOOKMARK) ||
      ui::PageTransitionCoreTypeIs(params->transition,
                                   ui::PAGE_TRANSITION_GENERATED) ||
      ui::PageTransitionCoreTypeIs(params->transition,
                                   ui::PAGE_TRANSITION_AUTO_TOPLEVEL) ||
      ui::PageTransitionCoreTypeIs(params->transition,
                                   ui::PAGE_TRANSITION_RELOAD) ||
      ui::PageTransitionCoreTypeIs(params->transition,
                                   ui::PAGE_TRANSITION_KEYWORD);

  // Did we use a prerender?
  bool swapped_in_prerender = false;

  // If no target WebContents was specified (and we didn't seek and find a
  // singleton), we need to construct one if we are supposed to target a new
  // tab.
  if (!contents_to_navigate_or_insert) {
    DCHECK(!params->url.is_empty());
    if (params->disposition != WindowOpenDisposition::CURRENT_TAB) {
      contents_to_insert = CreateTargetContents(*params, params->url);
      contents_to_navigate_or_insert = contents_to_insert.get();
    } else {
      // ... otherwise if we're loading in the current tab, the target is the
      // same as the source.
      DCHECK(params->source_contents);
      contents_to_navigate_or_insert = params->source_contents;

      prerender::PrerenderManager::Params prerender_params(
          params, params->source_contents);

      // Prerender can only swap in CURRENT_TAB navigations; others have
      // different sessionStorage namespaces.
      swapped_in_prerender = SwapInPrerender(params->url, &prerender_params);
      if (swapped_in_prerender)
        contents_to_navigate_or_insert = prerender_params.replaced_contents;
    }

    if (user_initiated)
      contents_to_navigate_or_insert->NavigatedByUser();

    if (!swapped_in_prerender) {
      // Try to handle non-navigational URLs that popup dialogs and such, these
      // should not actually navigate.
      if (!HandleNonNavigationAboutURL(params->url)) {
        // Perform the actual navigation, tracking whether it came from the
        // renderer.

        LoadURLInContents(contents_to_navigate_or_insert, params->url, params);
      }
    }
  } else {
    // |contents_to_navigate_or_insert| was specified non-NULL, and so we assume
    // it has already been navigated appropriately. We need to do nothing more
    // other than add it to the appropriate tabstrip.
  }

  // If the user navigated from the omnibox, and the selected tab is going to
  // lose focus, then make sure the focus for the source tab goes away from the
  // omnibox.
  if (params->source_contents &&
      (params->disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
       params->disposition == WindowOpenDisposition::NEW_WINDOW) &&
      (params->tabstrip_add_types & TabStripModel::ADD_INHERIT_OPENER))
    params->source_contents->Focus();

  if (params->source_contents == contents_to_navigate_or_insert ||
      (swapped_in_prerender &&
       params->disposition == WindowOpenDisposition::CURRENT_TAB)) {
    // The navigation occurred in the source tab.
    params->browser->UpdateUIForNavigationInTab(
        contents_to_navigate_or_insert, params->transition,
        params->window_action, user_initiated);
  } else if (singleton_index == -1) {
    // If some non-default value is set for the index, we should tell the
    // TabStripModel to respect it.
    if (params->tabstrip_index != -1)
      params->tabstrip_add_types |= TabStripModel::ADD_FORCE_INDEX;

    DCHECK(contents_to_insert);
    // The navigation should insert a new tab into the target Browser.
    params->browser->tab_strip_model()->AddWebContents(
        std::move(contents_to_insert), params->tabstrip_index,
        params->transition, params->tabstrip_add_types);
  }

  if (singleton_index >= 0) {
    // If switching browsers, make sure it is shown.
    if (params->disposition == WindowOpenDisposition::SWITCH_TO_TAB &&
        params->browser != source_browser)
      params->window_action = NavigateParams::SHOW_WINDOW;

    if (contents_to_navigate_or_insert->IsCrashed()) {
      contents_to_navigate_or_insert->GetController().Reload(
          content::ReloadType::NORMAL, true);
    } else if (params->path_behavior == NavigateParams::IGNORE_AND_NAVIGATE &&
               contents_to_navigate_or_insert->GetURL() != params->url) {
      LoadURLInContents(contents_to_navigate_or_insert, params->url, params);
    }

    // If the singleton tab isn't already selected, select it.
    if (params->source_contents != contents_to_navigate_or_insert) {
      // Use the index before the potential close below, because it could
      // make the index refer to a different tab.
      params->browser->tab_strip_model()->ActivateTabAt(singleton_index,
                                                        user_initiated);
      if (params->disposition == WindowOpenDisposition::SWITCH_TO_TAB) {
        // Close orphaned NTP (and the like) with no history when the user
        // switches away from them.
        if (params->source_contents->GetController().CanGoBack() ||
            (params->source_contents->GetLastCommittedURL().spec() !=
                 chrome::kChromeUINewTabURL &&
             params->source_contents->GetLastCommittedURL().spec() !=
                 chrome::kChromeSearchLocalNtpUrl &&
             params->source_contents->GetLastCommittedURL().spec() !=
                 url::kAboutBlankURL))
          params->source_contents->Focus();
        else
          params->source_contents->Close();
      }
    }
  }

  if (params->disposition != WindowOpenDisposition::CURRENT_TAB) {
    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_TAB_ADDED,
        content::Source<content::WebContentsDelegate>(params->browser),
        content::Details<WebContents>(contents_to_navigate_or_insert));
  }

  params->navigated_or_inserted_contents = contents_to_navigate_or_insert;
}

输入chrome://version时,已经在Z:\chromium\src\chrome\browser\ui\webui\version_ui.cc中下断点,命中后WebUIDataSource* CreateVersionUIDataSource(),看调用链。

>	chrome.dll!`anonymous namespace'::CreateVersionUIDataSource() 行 80	C++
 	chrome.dll!VersionUI::VersionUI(content::WebUI * web_ui) 行 184	C++
 	chrome.dll!`anonymous namespace'::NewWebUI<VersionUI>(content::WebUI * web_ui, const GURL & url) 行 230	C++
 	chrome.dll!ChromeWebUIControllerFactory::CreateWebUIControllerForURL(content::WebUI * web_ui, const GURL & url) 行 689	C++
 	content.dll!content::WebUIControllerFactoryRegistry::CreateWebUIControllerForURL(content::WebUI * web_ui, const GURL & url) 行 47	C++
 	content.dll!content::WebContentsImpl::CreateWebUI(const GURL & url) 行 6060	C++
 	content.dll!content::WebContentsImpl::CreateWebUIForRenderFrameHost(const GURL & url) 行 5779	C++
 	content.dll!content::RenderFrameHostImpl::UpdatePendingWebUI(const GURL & dest_url, int entry_bindings) 行 4167	C++
 	content.dll!content::RenderFrameHostManager::GetFrameHostForNavigation(const content::NavigationRequest & request) 行 585	C++
 	content.dll!content::RenderFrameHostManager::DidCreateNavigationRequest(content::NavigationRequest * request) 行 483	C++
 	content.dll!content::FrameTreeNode::CreatedNavigationRequest(std::unique_ptr<content::NavigationRequest,std::default_delete<content::NavigationRequest> > navigation_request) 行 452	C++
 	content.dll!content::NavigatorImpl::RequestNavigation(content::FrameTreeNode * frame_tree_node, const GURL & dest_url, const content::Referrer & dest_referrer, const content::FrameNavigationEntry & frame_entry, const content::NavigationEntryImpl & entry, content::ReloadType reload_type, int previews_state, bool is_same_document_history_load, bool is_history_navigation_in_new_child, const scoped_refptr<network::ResourceRequestBody> & post_body, base::TimeTicks navigation_start, std::unique_ptr<content::NavigationUIData,std::default_delete<content::NavigationUIData> > navigation_ui_data) 行 998	C++
 	content.dll!content::NavigatorImpl::NavigateToEntry(content::FrameTreeNode * frame_tree_node, const content::FrameNavigationEntry & frame_entry, const content::NavigationEntryImpl & entry, content::ReloadType reload_type, bool is_same_document_history_load, bool is_history_navigation_in_new_child, bool is_pending_entry, const scoped_refptr<network::ResourceRequestBody> & post_body, std::unique_ptr<content::NavigationUIData,std::default_delete<content::NavigationUIData> > navigation_ui_data) 行 344	C++
 	content.dll!content::NavigatorImpl::NavigateToPendingEntry(content::FrameTreeNode * frame_tree_node, const content::FrameNavigationEntry & frame_entry, content::ReloadType reload_type, bool is_same_document_history_load, std::unique_ptr<content::NavigationUIData,std::default_delete<content::NavigationUIData> > navigation_ui_data) 行 388	C++
 	content.dll!content::NavigationControllerImpl::NavigateToPendingEntryInternal(content::ReloadType reload_type, std::unique_ptr<content::NavigationUIData,std::default_delete<content::NavigationUIData> > navigation_ui_data) 行 2311	C++
 	content.dll!content::NavigationControllerImpl::NavigateToPendingEntry(content::ReloadType reload_type, std::unique_ptr<content::NavigationUIData,std::default_delete<content::NavigationUIData> > navigation_ui_data) 行 2265	C++
 	content.dll!content::NavigationControllerImpl::LoadEntry(std::unique_ptr<content::NavigationEntryImpl,std::default_delete<content::NavigationEntryImpl> > entry, std::unique_ptr<content::NavigationUIData,std::default_delete<content::NavigationUIData> > navigation_ui_data) 行 517	C++
 	content.dll!content::NavigationControllerImpl::LoadURLWithParams(const content::NavigationController::LoadURLParams & params) 行 877	C++
 	chrome.dll!`anonymous namespace'::LoadURLInContents(content::WebContents * target_contents, const GURL & url, NavigateParams * params) 行 342	C++
 	chrome.dll!Navigate(NavigateParams * params) 行 621	C++
 	chrome.dll!chrome::OpenCurrentURL(Browser * browser) 行 536	C++
 	chrome.dll!chrome::BrowserCommandController::ExecuteCommandWithDisposition(int id, WindowOpenDisposition disposition) 行 331	C++
 	chrome.dll!chrome::BrowserCommandController::ExecuteCommand(int id) 行 281	C++
 	chrome.dll!ChromeOmniboxEditController::OnAutocompleteAccept(const GURL & destination_url, WindowOpenDisposition disposition, ui::PageTransition transition, AutocompleteMatchType::Type match_type) 行 29	C++
 	chrome.dll!OmniboxEditModel::OpenMatch(AutocompleteMatch match, WindowOpenDisposition disposition, const GURL & alternate_nav_url, const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & pasted_text, unsigned __int64 index) 行 729	C++
 	chrome.dll!OmniboxView::OpenMatch(const AutocompleteMatch & match, WindowOpenDisposition disposition, const GURL & alternate_nav_url, const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & pasted_text, unsigned __int64 selected_line) 行 97	C++
 	chrome.dll!OmniboxEditModel::AcceptInput(WindowOpenDisposition disposition, bool for_drop) 行 539	C++
 	chrome.dll!OmniboxViewViews::HandleKeyEvent(views::Textfield * textfield, const ui::KeyEvent & event) 行 1170	C++
 	views.dll!views::Textfield::OnKeyPressed(const ui::KeyEvent & event) 行 711	C++
 	views.dll!views::View::OnKeyEvent(ui::KeyEvent * event) 行 1081	C++
 	events.dll!ui::EventHandler::OnEvent(ui::Event * event) 行 25	C++
 	events.dll!ui::EventDispatcher::DispatchEvent(ui::EventHandler * handler, ui::Event * event) 行 192	C++
 	events.dll!ui::EventDispatcher::ProcessEvent(ui::EventTarget * target, ui::Event * event) 行 140	C++
 	events.dll!ui::EventDispatcherDelegate::DispatchEventToTarget(ui::EventTarget * target, ui::Event * event) 行 87	C++
 	events.dll!ui::EventDispatcherDelegate::DispatchEvent(ui::EventTarget * target, ui::Event * event) 行 58	C++
 	events.dll!ui::EventProcessor::OnEventFromSource(ui::Event * event) 行 57	C++
 	events.dll!ui::EventSource::DeliverEventToSink(ui::Event * event) 行 107	C++
 	events.dll!ui::EventSource::SendEventToSinkFromRewriter(ui::Event * event, const ui::EventRewriter * rewriter) 行 86	C++
 	events.dll!ui::EventSource::SendEventToSink(ui::Event * event) 行 44	C++
 	views.dll!views::Widget::OnKeyEvent(ui::KeyEvent * event) 行 1169	C++
 	views.dll!views::DesktopNativeWidgetAura::OnKeyEvent(ui::KeyEvent * event) 行 1061	C++
 	events.dll!ui::EventHandler::OnEvent(ui::Event * event) 行 25	C++
 	events.dll!ui::EventDispatcher::DispatchEvent(ui::EventHandler * handler, ui::Event * event) 行 192	C++
 	events.dll!ui::EventDispatcher::ProcessEvent(ui::EventTarget * target, ui::Event * event) 行 140	C++
 	events.dll!ui::EventDispatcherDelegate::DispatchEventToTarget(ui::EventTarget * target, ui::Event * event) 行 87	C++
 	events.dll!ui::EventDispatcherDelegate::DispatchEvent(ui::EventTarget * target, ui::Event * event) 行 58	C++
 	events.dll!ui::EventProcessor::OnEventFromSource(ui::Event * event) 行 57	C++
 	aura.dll!aura::WindowTreeHost::DispatchKeyEventPostIME(ui::KeyEvent * event) 行 254	C++
 	ui_base_ime.dll!ui::InputMethodBase::DispatchKeyEventPostIME(ui::KeyEvent * event) 行 169	C++
 	ui_base_ime.dll!ui::InputMethodWin::ProcessUnhandledKeyEvent(ui::KeyEvent * event, const std::vector<tagMSG,std::allocator<tagMSG> > * char_msgs) 行 195	C++
 	ui_base_ime.dll!ui::InputMethodWin::DispatchKeyEvent(ui::KeyEvent * event) 行 179	C++
 	aura.dll!aura::WindowEventDispatcher::PreDispatchKeyEvent(ui::KeyEvent * event) 行 1076	C++
 	aura.dll!aura::WindowEventDispatcher::PreDispatchEvent(ui::EventTarget * target, ui::Event * event) 行 604	C++
 	events.dll!ui::EventDispatcherDelegate::DispatchEvent(ui::EventTarget * target, ui::Event * event) 行 55	C++
 	events.dll!ui::EventProcessor::OnEventFromSource(ui::Event * event) 行 57	C++
 	events.dll!ui::EventSource::DeliverEventToSink(ui::Event * event) 行 107	C++
 	events.dll!ui::EventSource::SendEventToSinkFromRewriter(ui::Event * event, const ui::EventRewriter * rewriter) 行 86	C++
 	events.dll!ui::EventSource::SendEventToSink(ui::Event * event) 行 44	C++
 	views.dll!views::DesktopWindowTreeHostWin::HandleKeyEvent(ui::KeyEvent * event) 行 888	C++
 	views.dll!views::HWNDMessageHandler::OnKeyEvent(unsigned int message, unsigned __int64 w_param, __int64 l_param) 行 1759	C++
 	views.dll!views::HWNDMessageHandler::_ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned __int64 wParam, __int64 lParam, __int64 & lResult, unsigned long dwMsgMapID) 行 350	C++
 	views.dll!views::HWNDMessageHandler::OnWndProc(unsigned int message, unsigned __int64 w_param, __int64 l_param) 行 934	C++
 	gfx.dll!gfx::WindowImpl::WndProc(HWND__ * hwnd, unsigned int message, unsigned __int64 w_param, __int64 l_param) 行 303	C++
 	gfx.dll!base::win::WrappedWindowProc<&gfx::WindowImpl::WndProc>(HWND__ * hwnd, unsigned int message, unsigned __int64 wparam, __int64 lparam) 行 76	C++
 	[外部代码]	
 	base.dll!base::MessagePumpForUI::ProcessMessageHelper(const tagMSG & msg) 行 380	C++
 	base.dll!base::MessagePumpForUI::ProcessNextWindowsMessage() 行 348	C++
 	base.dll!base::MessagePumpForUI::DoRunLoop() 行 173	C++
 	base.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) 行 58	C++
 	base.dll!base::MessageLoop::Run(bool application_tasks_allowed) 行 273	C++
 	base.dll!base::RunLoop::Run() 行 105	C++
 	chrome.dll!ChromeBrowserMainParts::MainMessageLoopRun(int * result_code) 行 2155	C++
 	content.dll!content::BrowserMainLoop::RunMainMessageLoopParts() 行 978	C++
 	content.dll!content::BrowserMainRunnerImpl::Run() 行 170	C++
 	content.dll!content::BrowserMain(const content::MainFunctionParams & parameters, std::unique_ptr<content::BrowserProcessSubThread,std::default_delete<content::BrowserProcessSubThread> > service_manager_thread) 行 51	C++
 	content.dll!content::RunBrowserProcessMain(const content::MainFunctionParams & main_function_params, content::ContentMainDelegate * delegate, std::unique_ptr<content::BrowserProcessSubThread,std::default_delete<content::BrowserProcessSubThread> > service_manager_thread) 行 620	C++
 	content.dll!content::ContentMainRunnerImpl::Run() 行 964	C++
 	content.dll!content::ContentServiceManagerMainDelegate::RunEmbedderProcess() 行 53	C++
 	embedder.dll!service_manager::Main(const service_manager::MainParams & params) 行 459	C++
 	content.dll!content::ContentMain(const content::ContentMainParams & params) 行 20	C++
 	chrome.dll!ChromeMain(HINSTANCE__ * instance, sandbox::SandboxInterfaceInfo * sandbox_info, __int64 exe_entry_point_ticks) 行 101	C++
 	chrome.exe!MainDllLoader::Launch(HINSTANCE__ * instance, base::TimeTicks exe_entry_point_ticks) 行 201	C++
 	chrome.exe!wWinMain(HINSTANCE__ * instance, HINSTANCE__ * prev, wchar_t *, int) 行 277	C++
 	[外部代码]	

不往下追了,通过单步,断点,调用链相结合,知道了从chromium浏览器的url输入栏输入url +回车,到建立buildin url 页面的过程。

THE END

发表回复