Commit message: None
CVE: CVE-2017-5069
CWE: CWE-79
Vulnerability description: Incorrect MIME type of XSS-Protection reports in Blink in Google Chrome prior to 58.0.3029.81 for Linux, Windows, and Mac, and 58.0.3029.83 for Android, allowed a remote attacker to circumvent Cross-Origin Resource Sharing checks via a crafted HTML page.

Project: Chrome

  void ActivateProfile() {
    if (profile_to_activate_) {
      Browser* browser = chrome::FindBrowserWithProfile(profile_to_activate_);
      if (browser)
        browser->window()->Activate();
      profile_to_activate_ = nullptr;
    }
    activated_profile_ = true;
  }

Project: Chrome

bool StartupBrowserCreator::ActivatedProfile() {
  return profile_launch_observer.Get().activated_profile();
}

Project: Chrome

void StartupBrowserCreator::AddFirstRunTab(const GURL& url) {
  first_run_tabs_.push_back(url);
}

Project: Chrome

  void AddLaunched(Profile* profile) {
    launched_profiles_.insert(profile);
    if (chrome::FindBrowserWithProfile(profile)) {
      opened_profiles_.insert(profile);
    }
  }

Project: Chrome

bool CanOpenProfileOnStartup(Profile* profile) {
#if defined(OS_CHROMEOS)
  return true;
#else
  ProfileAttributesEntry* entry = nullptr;
  if (g_browser_process->profile_manager()
          ->GetProfileAttributesStorage()
          .GetProfileAttributesWithPath(profile->GetPath(), &entry) &&
      entry->IsSigninRequired()) {
    return false;
  }

  return (!profile->IsGuestSession() && !profile->IsSystemProfile()) ||
         (chrome::GetBrowserCount(profile->GetOffTheRecordProfile()) > 0);
#endif
}

Project: Chrome

  void Clear() {
    launched_profiles_.clear();
    opened_profiles_.clear();
  }

Project: Chrome

void DumpBrowserHistograms(const base::FilePath& output_file) {
  std::string output_string(
      base::StatisticsRecorder::ToJSON(base::JSON_VERBOSITY_LEVEL_FULL));

  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  base::WriteFile(output_file, output_string.data(),
                  static_cast<int>(output_string.size()));
}

Project: Chrome

Profile* GetFallbackStartupProfile() {
  ProfileManager* profile_manager = g_browser_process->profile_manager();

  auto* storage = &profile_manager->GetProfileAttributesStorage();
  for (Profile* profile : ProfileManager::GetLastOpenedProfiles()) {
    ProfileAttributesEntry* entry;
    bool has_entry = storage->GetProfileAttributesWithPath(profile->GetPath(),
                                                           &entry);
    if (!has_entry || !entry->IsSigninRequired())
      return profile;
  }

  Profile* guest_profile =
      profile_manager->GetProfile(ProfileManager::GetGuestProfilePath());
  Profile* system_profile =
      profile_manager->GetProfile(ProfileManager::GetSystemProfilePath());
  if (guest_profile && system_profile)
    return guest_profile;

  for (ProfileAttributesEntry* entry : storage->GetAllProfilesAttributes()) {
    if (!entry->IsSigninRequired()) {
      Profile* profile = profile_manager->GetProfile(entry->GetPath());
      if (profile)
        return profile;
    }
  }

  return nullptr;
}

Project: Chrome

Profile* GetStartupProfile(const base::FilePath& user_data_dir,
                           const base::CommandLine& command_line) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();

  base::FilePath profile_path =
      GetStartupProfilePath(user_data_dir, command_line);
  Profile* profile = profile_manager->GetProfile(profile_path);

  auto* storage = &profile_manager->GetProfileAttributesStorage();
  ProfileAttributesEntry* entry;
  bool has_entry = storage->GetProfileAttributesWithPath(profile_path, &entry);
  if (has_entry && (!entry->IsSigninRequired() || !profile)) {
    return profile;
  }

  return profile_manager->GetProfile(ProfileManager::GetSystemProfilePath()) ?
         profile_manager->GetProfile(ProfileManager::GetGuestProfilePath()) :
         nullptr;
}

Project: Chrome

base::FilePath GetStartupProfilePath(const base::FilePath& user_data_dir,
                                     const base::CommandLine& command_line) {
#if defined(OS_WIN)
  if (command_line.HasSwitch(switches::kNotificationLaunchId)) {
    std::string profile_id = NotificationLaunchId::GetProfileIdFromLaunchId(
        command_line.GetSwitchValueNative(switches::kNotificationLaunchId));
    if (!profile_id.empty()) {
      return user_data_dir.Append(
          base::FilePath(base::UTF8ToUTF16(profile_id)));
    }
  }
#endif  // defined(OS_WIN)

  if (IsGuestModeEnforced(command_line, /* show_warning= */ false))
    return profiles::GetDefaultProfileDir(user_data_dir);

  if (command_line.HasSwitch(switches::kProfileDirectory)) {
    return user_data_dir.Append(
        command_line.GetSwitchValuePath(switches::kProfileDirectory));
  }

  return g_browser_process->profile_manager()->GetLastUsedProfileDir(
      user_data_dir);
}

Project: Chrome

std::vector<GURL> StartupBrowserCreator::GetURLsFromCommandLine(
    const base::CommandLine& command_line,
    const base::FilePath& cur_dir,
    Profile* profile) {
  DCHECK(profile);

  std::vector<GURL> urls;

  const base::CommandLine::StringVector& params = command_line.GetArgs();
  for (size_t i = 0; i < params.size(); ++i) {
    base::FilePath param = base::FilePath(params[i]);
    if ((param.value().size() > 2) && (param.value()[0] == '?') &&
        (param.value()[1] == ' ')) {
      GURL url(GetDefaultSearchURLForSearchTerms(
          TemplateURLServiceFactory::GetForProfile(profile),
          param.LossyDisplayName().substr(2)));
      if (url.is_valid()) {
        urls.push_back(url);
        continue;
      }
    }


    GURL url = GURL(param.MaybeAsASCII());

    if (!url.is_valid() || url.SchemeIsFile()) {
      base::ThreadRestrictions::ScopedAllowIO allow_io;
      url = url_formatter::FixupRelativeFile(cur_dir, param);
    }
    if (!url.is_valid())
      continue;

    const GURL settings_url = GURL(chrome::kChromeUISettingsURL);
    bool url_points_to_an_approved_settings_page = false;
#if defined(OS_CHROMEOS)
    url_points_to_an_approved_settings_page =
        url.GetOrigin() == settings_url.GetOrigin();
#else
    const GURL reset_settings_url =
        settings_url.Resolve(chrome::kResetProfileSettingsSubPage);
    url_points_to_an_approved_settings_page = url == reset_settings_url;
#if defined(OS_WIN)
    const GURL reset_settings_url_with_cct_hash = reset_settings_url.Resolve(
        std::string("#") +
        settings::ResetSettingsHandler::kCctResetSettingsHash);
    url_points_to_an_approved_settings_page =
        url_points_to_an_approved_settings_page ||
        url == reset_settings_url_with_cct_hash;
#endif  // defined(OS_WIN)
#endif  // defined(OS_CHROMEOS)

    ChildProcessSecurityPolicy* policy =
        ChildProcessSecurityPolicy::GetInstance();
    if (policy->IsWebSafeScheme(url.scheme()) ||
        url.SchemeIs(url::kFileScheme) ||
        url_points_to_an_approved_settings_page ||
        (url.spec().compare(url::kAboutBlankURL) == 0)) {
      urls.push_back(url);
    }
  }
  return urls;
}

Project: Chrome

  bool HasBeenLaunched(const Profile* profile) const {
    return launched_profiles_.find(profile) != launched_profiles_.end();
  }

Project: Chrome

bool HasPendingUncleanExit(Profile* profile) {
  return profile->GetLastSessionExitType() == Profile::EXIT_CRASHED &&
      !profile_launch_observer.Get().HasBeenLaunched(profile);
}

Project: Chrome

bool StartupBrowserCreator::InSynchronousProfileLaunch() {
  return in_synchronous_profile_launch_;
}

Project: Chrome

bool IsGuestModeEnforced(const base::CommandLine& command_line,
                         bool show_warning) {
#if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX)
  PrefService* service = g_browser_process->local_state();
  DCHECK(service);

  if (command_line.HasSwitch(switches::kGuest) ||
      service->GetBoolean(prefs::kBrowserGuestModeEnforced)) {
    if (service->GetBoolean(prefs::kBrowserGuestModeEnabled))
      return true;
    if (show_warning) {
      LOG(WARNING) << "Guest mode disabled by policy, launching a normal "
                   << "browser session.";
    }
  }
#endif
  return false;
}

Project: Chrome

bool StartupBrowserCreator::LaunchBrowser(
    const base::CommandLine& command_line,
    Profile* profile,
    const base::FilePath& cur_dir,
    chrome::startup::IsProcessStartup process_startup,
    chrome::startup::IsFirstRun is_first_run) {
  DCHECK(profile);
  in_synchronous_profile_launch_ =
      process_startup == chrome::startup::IS_PROCESS_STARTUP;

  if (IncognitoModePrefs::ShouldLaunchIncognito(command_line,
                                                profile->GetPrefs())) {
    profile = profile->GetOffTheRecordProfile();
  } else if (command_line.HasSwitch(switches::kIncognito)) {
    LOG(WARNING) << "Incognito mode disabled by policy, launching a normal "
                 << "browser session.";
  }

  if (IsGuestModeEnforced(command_line, /* show_warning= */ true)) {
    profile = g_browser_process->profile_manager()
                  ->GetProfile(ProfileManager::GetGuestProfilePath())
                  ->GetOffTheRecordProfile();
  }

#if defined(OS_WIN)
  if (command_line.HasSwitch(credential_provider::kGcpwSigninSwitch))
    profile = profile->GetOffTheRecordProfile();
#endif

  if (!IsSilentLaunchEnabled(command_line, profile)) {
    StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
    const std::vector<GURL> urls_to_launch =
        GetURLsFromCommandLine(command_line, cur_dir, profile);
    const bool launched =
        lwp.Launch(profile, urls_to_launch, in_synchronous_profile_launch_);
    in_synchronous_profile_launch_ = false;
    if (!launched) {
      LOG(ERROR) << "launch error";
      return false;
    }
  } else {
    in_synchronous_profile_launch_ = false;
  }

  profile_launch_observer.Get().AddLaunched(profile);

  return true;
}

Project: Chrome

bool StartupBrowserCreator::LaunchBrowserForLastProfiles(
    const base::CommandLine& command_line,
    const base::FilePath& cur_dir,
    bool process_startup,
    Profile* last_used_profile,
    const Profiles& last_opened_profiles) {
  chrome::startup::IsProcessStartup is_process_startup = process_startup ?
      chrome::startup::IS_PROCESS_STARTUP :
      chrome::startup::IS_NOT_PROCESS_STARTUP;
  chrome::startup::IsFirstRun is_first_run = first_run::IsChromeFirstRun() ?
      chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;

  bool was_windows_notification_launch = false;
#if defined(OS_WIN)
  was_windows_notification_launch =
      command_line.HasSwitch(switches::kNotificationLaunchId);
#endif  // defined(OS_WIN)

  if (last_opened_profiles.empty() || was_windows_notification_launch) {
    if (CanOpenProfileOnStartup(last_used_profile)) {
      Profile* profile_to_open =
          last_used_profile->IsGuestSession()
              ? last_used_profile->GetOffTheRecordProfile()
              : last_used_profile;

      return LaunchBrowser(command_line, profile_to_open, cur_dir,
                           is_process_startup, is_first_run);
    }

    ShowUserManagerOnStartup(command_line);
    return true;
  }
  return ProcessLastOpenedProfiles(command_line, cur_dir, is_process_startup,
                                   is_first_run, last_used_profile,
                                   last_opened_profiles);
}

Project: Chrome

  void MaybeActivateProfile() {
    if (!profile_to_activate_)
      return;
    auto i = launched_profiles_.begin();
    for (; i != launched_profiles_.end(); ++i) {
      if (opened_profiles_.find(*i) == opened_profiles_.end())
        return;
    }
    base::PostTask(FROM_HERE, {BrowserThread::UI},
                   base::BindOnce(&ProfileLaunchObserver::ActivateProfile,
                                  base::Unretained(this)));
    registrar_.RemoveAll();
    BrowserList::RemoveObserver(this);
  }

Project: Chrome

void StartupBrowserCreator::OpenStartupPages(Browser* browser,
                                             bool process_startup) {
  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
  chrome::startup::IsFirstRun is_first_run =
      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
                                    : chrome::startup::IS_NOT_FIRST_RUN;
  StartupBrowserCreatorImpl startup_browser_creator_impl(
      base::FilePath(), command_line, is_first_run);
  SessionStartupPref session_startup_pref =
      StartupBrowserCreator::GetSessionStartupPref(command_line,
                                                   browser->profile());
  startup_browser_creator_impl.OpenURLsInBrowser(browser, process_startup,
                                                 session_startup_pref.urls);
}

Project: Chrome

void StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
    const base::CommandLine& command_line,
    const base::FilePath& cur_dir,
    const base::FilePath& profile_path) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  Profile* profile = profile_manager->GetProfileByPath(profile_path);

  if (!profile) {
    profile_manager->CreateProfileAsync(
        profile_path,
        base::BindRepeating(&ProcessCommandLineOnProfileCreated, command_line,
                            cur_dir),
        base::string16(), std::string());
    return;
  }
  StartupBrowserCreator startup_browser_creator;
  startup_browser_creator.ProcessCmdLineImpl(
      command_line, cur_dir, /*process_startup=*/false, profile, Profiles());
}

Project: Chrome

void StartupBrowserCreator::ProcessCommandLineOnProfileCreated(
    const base::CommandLine& command_line,
    const base::FilePath& cur_dir,
    Profile* profile,
    Profile::CreateStatus status) {
  if (status != Profile::CREATE_STATUS_INITIALIZED)
    return;
  StartupBrowserCreator startup_browser_creator;
  startup_browser_creator.ProcessCmdLineImpl(command_line, cur_dir, false,
                                             profile, Profiles());
}

Project: Chrome

bool StartupBrowserCreator::ProcessLastOpenedProfiles(
    const base::CommandLine& command_line,
    const base::FilePath& cur_dir,
    chrome::startup::IsProcessStartup is_process_startup,
    chrome::startup::IsFirstRun is_first_run,
    Profile* last_used_profile,
    const Profiles& last_opened_profiles) {
  base::CommandLine command_line_without_urls(command_line.GetProgram());
  for (auto& switch_pair : command_line.GetSwitches()) {
    command_line_without_urls.AppendSwitchNative(switch_pair.first,
                                                 switch_pair.second);
  }

  size_t DEBUG_num_profiles_on_entry = last_opened_profiles.size();
  base::debug::Alias(&DEBUG_num_profiles_on_entry);
  int DEBUG_loop_counter = 0;
  base::debug::Alias(&DEBUG_loop_counter);

  base::debug::Alias(&last_opened_profiles);
  const Profile* DEBUG_profile_0 = nullptr;
  const Profile* DEBUG_profile_1 = nullptr;
  if (!last_opened_profiles.empty())
    DEBUG_profile_0 = last_opened_profiles[0];
  if (last_opened_profiles.size() > 1)
    DEBUG_profile_1 = last_opened_profiles[1];
  base::debug::Alias(&DEBUG_profile_0);
  base::debug::Alias(&DEBUG_profile_1);

  size_t DEBUG_num_profiles_at_loop_start = std::numeric_limits<size_t>::max();
  base::debug::Alias(&DEBUG_num_profiles_at_loop_start);

  auto DEBUG_it_begin = last_opened_profiles.begin();
  base::debug::Alias(&DEBUG_it_begin);
  auto DEBUG_it_end = last_opened_profiles.end();
  base::debug::Alias(&DEBUG_it_end);

  for (auto it = last_opened_profiles.begin(); it != last_opened_profiles.end();
       ++it, ++DEBUG_loop_counter) {
    DEBUG_num_profiles_at_loop_start = last_opened_profiles.size();
    DCHECK(!(*it)->IsGuestSession());

#if !defined(OS_CHROMEOS)
    if (!CanOpenProfileOnStartup(*it))
      continue;

    if (last_used_profile->IsGuestSession())
      last_used_profile = *it;
#endif

    SessionStartupPref startup_pref = GetSessionStartupPref(command_line, *it);
    if (*it != last_used_profile &&
        startup_pref.type == SessionStartupPref::DEFAULT &&
        !HasPendingUncleanExit(*it)) {
      continue;
    }
    if (!LaunchBrowser((*it == last_used_profile) ? command_line
                                                  : command_line_without_urls,
                       *it, cur_dir, is_process_startup, is_first_run)) {
      return false;
    }
    is_process_startup = chrome::startup::IS_NOT_PROCESS_STARTUP;
  }

#if !defined(OS_CHROMEOS)
  if (is_process_startup == chrome::startup::IS_PROCESS_STARTUP)
    ShowUserManagerOnStartup(command_line);
  else
#endif
    profile_launch_observer.Get().set_profile_to_activate(last_used_profile);
  return true;
}

Project: Chrome

bool StartupBrowserCreator::ProcessLoadApps(
    const base::CommandLine& command_line,
    const base::FilePath& cur_dir,
    Profile* profile) {
  base::CommandLine::StringType path_list =
      command_line.GetSwitchValueNative(extensions::switches::kLoadApps);

  base::StringTokenizerT<base::CommandLine::StringType,
                         base::CommandLine::StringType::const_iterator>
      tokenizer(path_list, FILE_PATH_LITERAL(","));

  if (!tokenizer.GetNext())
    return false;

  base::FilePath app_absolute_dir =
      base::MakeAbsoluteFilePath(base::FilePath(tokenizer.token()));
  if (!apps::AppLoadService::Get(profile)->LoadAndLaunch(
          app_absolute_dir, command_line, cur_dir)) {
    return false;
  }

  while (tokenizer.GetNext()) {
    app_absolute_dir =
        base::MakeAbsoluteFilePath(base::FilePath(tokenizer.token()));

    if (!apps::AppLoadService::Get(profile)->Load(app_absolute_dir)) {
      return false;
    }
  }

  return true;
}

Project: Chrome

  ProfileLaunchObserver() {
    registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
                   content::NotificationService::AllSources());
    BrowserList::AddObserver(this);
  }

Project: Chrome

void StartupBrowserCreator::RegisterLocalStatePrefs(
    PrefRegistrySimple* registry) {
#if !defined(OS_CHROMEOS)
  registry->RegisterBooleanPref(prefs::kPromotionalTabsEnabled, true);
  registry->RegisterBooleanPref(prefs::kCommandLineFlagSecurityWarningsEnabled,
                                true);
#endif
  registry->RegisterBooleanPref(prefs::kSuppressUnsupportedOSWarning, false);
  registry->RegisterBooleanPref(prefs::kWasRestarted, false);
}

Project: Chrome

void StartupBrowserCreator::RegisterProfilePrefs(PrefRegistrySimple* registry) {
  registry->RegisterBooleanPref(prefs::kHasSeenWelcomePage, true);
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
  registry->RegisterStringPref(prefs::kNaviOnboardGroup, "");
#endif  // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
}

Project: Chrome

void ShowUserManagerOnStartup(const base::CommandLine& command_line) {
#if !defined(OS_CHROMEOS)
  UserManager::Show(base::FilePath(),
                    profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
#endif  // !defined(OS_CHROMEOS)
}

Project: Chrome

bool StartupBrowserCreator::Start(const base::CommandLine& cmd_line,
                                  const base::FilePath& cur_dir,
                                  Profile* last_used_profile,
                                  const Profiles& last_opened_profiles) {
  TRACE_EVENT0("startup", "StartupBrowserCreator::Start");
  SCOPED_UMA_HISTOGRAM_TIMER("Startup.StartupBrowserCreator_Start");
  return ProcessCmdLineImpl(cmd_line, cur_dir, true, last_used_profile,
                            last_opened_profiles);
}

Project: Chrome

bool StartupBrowserCreator::WasRestarted() {
  static bool was_restarted = false;

  if (!was_restarted_read_) {
    PrefService* pref_service = g_browser_process->local_state();
    was_restarted = pref_service->GetBoolean(prefs::kWasRestarted);
    pref_service->SetBoolean(prefs::kWasRestarted, false);
    was_restarted_read_ = true;
  }
  return was_restarted;
}

Project: Chrome

  bool activated_profile() { return activated_profile_; }

Project: Chrome

  void set_profile_to_activate(Profile* profile) {
    profile_to_activate_ = profile;
    MaybeActivateProfile();
  }