OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/first_run/first_run.h" | 5 #include "chrome/browser/first_run/first_run.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | 8 #include <memory> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" | 48 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" |
49 #include "chrome/common/chrome_constants.h" | 49 #include "chrome/common/chrome_constants.h" |
50 #include "chrome/common/chrome_paths.h" | 50 #include "chrome/common/chrome_paths.h" |
51 #include "chrome/common/chrome_switches.h" | 51 #include "chrome/common/chrome_switches.h" |
52 #include "chrome/common/pref_names.h" | 52 #include "chrome/common/pref_names.h" |
53 #include "chrome/common/url_constants.h" | 53 #include "chrome/common/url_constants.h" |
54 #include "chrome/grit/locale_settings.h" | 54 #include "chrome/grit/locale_settings.h" |
55 #include "chrome/installer/util/master_preferences.h" | 55 #include "chrome/installer/util/master_preferences.h" |
56 #include "chrome/installer/util/master_preferences_constants.h" | 56 #include "chrome/installer/util/master_preferences_constants.h" |
57 #include "chrome/installer/util/util_constants.h" | 57 #include "chrome/installer/util/util_constants.h" |
58 #include "components/pref_registry/pref_registry_syncable.h" | |
58 #include "components/prefs/pref_service.h" | 59 #include "components/prefs/pref_service.h" |
59 #include "components/search_engines/template_url_service.h" | 60 #include "components/search_engines/template_url_service.h" |
60 #include "components/signin/core/browser/signin_manager.h" | 61 #include "components/signin/core/browser/signin_manager.h" |
61 #include "components/signin/core/browser/signin_tracker.h" | 62 #include "components/signin/core/browser/signin_tracker.h" |
62 #include "content/public/browser/navigation_entry.h" | 63 #include "content/public/browser/navigation_entry.h" |
63 #include "content/public/browser/notification_observer.h" | 64 #include "content/public/browser/notification_observer.h" |
64 #include "content/public/browser/notification_registrar.h" | 65 #include "content/public/browser/notification_registrar.h" |
65 #include "content/public/browser/notification_service.h" | 66 #include "content/public/browser/notification_service.h" |
66 #include "content/public/browser/notification_types.h" | 67 #include "content/public/browser/notification_types.h" |
67 #include "content/public/browser/user_metrics.h" | 68 #include "content/public/browser/user_metrics.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 | 192 |
192 void DoDelayedInstallExtensionsIfNeeded( | 193 void DoDelayedInstallExtensionsIfNeeded( |
193 installer::MasterPreferences* install_prefs) { | 194 installer::MasterPreferences* install_prefs) { |
194 base::DictionaryValue* extensions = 0; | 195 base::DictionaryValue* extensions = 0; |
195 if (install_prefs->GetExtensionsBlock(&extensions)) { | 196 if (install_prefs->GetExtensionsBlock(&extensions)) { |
196 DVLOG(1) << "Extensions block found in master preferences"; | 197 DVLOG(1) << "Extensions block found in master preferences"; |
197 DoDelayedInstallExtensions(); | 198 DoDelayedInstallExtensions(); |
198 } | 199 } |
199 } | 200 } |
200 | 201 |
201 // Sets the |items| bitfield according to whether the import data specified by | |
202 // |import_type| should be be auto imported or not. | |
203 void SetImportItem(PrefService* user_prefs, | |
204 const char* pref_path, | |
205 int import_items, | |
206 int dont_import_items, | |
207 importer::ImportItem import_type, | |
208 int* items) { | |
209 // Work out whether an item is to be imported according to what is specified | |
210 // in master preferences. | |
211 bool should_import = false; | |
212 bool master_pref_set = | |
213 ((import_items | dont_import_items) & import_type) != 0; | |
214 bool master_pref = ((import_items & ~dont_import_items) & import_type) != 0; | |
215 | |
216 if (import_type == importer::HISTORY || | |
217 (import_type != importer::FAVORITES && | |
218 first_run::internal::IsOrganicFirstRun())) { | |
219 // History is always imported unless turned off in master_preferences. | |
220 // Search engines and home page are imported in organic builds only | |
221 // unless turned off in master_preferences. | |
222 should_import = !master_pref_set || master_pref; | |
223 } else { | |
224 // Bookmarks are never imported, unless turned on in master_preferences. | |
225 // Search engine and home page import behaviour is similar in non organic | |
226 // builds. | |
227 should_import = master_pref_set && master_pref; | |
228 } | |
229 | |
230 // If an import policy is set, import items according to policy. If no master | |
231 // preference is set, but a corresponding recommended policy is set, import | |
232 // item according to recommended policy. If both a master preference and a | |
233 // recommended policy is set, the master preference wins. If neither | |
234 // recommended nor managed policies are set, import item according to what we | |
235 // worked out above. | |
236 if (master_pref_set) | |
237 user_prefs->SetBoolean(pref_path, should_import); | |
238 | |
239 if (!user_prefs->FindPreference(pref_path)->IsDefaultValue()) { | |
240 if (user_prefs->GetBoolean(pref_path)) | |
241 *items |= import_type; | |
242 } else { | |
243 // no policy (recommended or managed) is set | |
244 if (should_import) | |
245 *items |= import_type; | |
246 } | |
247 | |
248 user_prefs->ClearPref(pref_path); | |
249 } | |
250 | |
251 // Launches the import, via |importer_host|, from |source_profile| into | 202 // Launches the import, via |importer_host|, from |source_profile| into |
252 // |target_profile| for the items specified in the |items_to_import| bitfield. | 203 // |target_profile| for the items specified in the |items_to_import| bitfield. |
253 // This may be done in a separate process depending on the platform, but it will | 204 // This may be done in a separate process depending on the platform, but it will |
254 // always block until done. | 205 // always block until done. |
255 void ImportFromSourceProfile(const importer::SourceProfile& source_profile, | 206 void ImportFromSourceProfile(const importer::SourceProfile& source_profile, |
256 Profile* target_profile, | 207 Profile* target_profile, |
257 uint16_t items_to_import) { | 208 uint16_t items_to_import) { |
258 // Deletes itself. | 209 // Deletes itself. |
259 ExternalProcessImporterHost* importer_host = | 210 ExternalProcessImporterHost* importer_host = |
260 new ExternalProcessImporterHost; | 211 new ExternalProcessImporterHost; |
(...skipping 30 matching lines...) Expand all Loading... | |
291 #endif | 242 #endif |
292 source_profile.source_path = base::FilePath(import_bookmarks_path_str); | 243 source_profile.source_path = base::FilePath(import_bookmarks_path_str); |
293 | 244 |
294 ImportFromSourceProfile(source_profile, profile, importer::FAVORITES); | 245 ImportFromSourceProfile(source_profile, profile, importer::FAVORITES); |
295 g_auto_import_state |= first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED; | 246 g_auto_import_state |= first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED; |
296 } | 247 } |
297 | 248 |
298 // Imports settings from the first profile in |importer_list|. | 249 // Imports settings from the first profile in |importer_list|. |
299 void ImportSettings(Profile* profile, | 250 void ImportSettings(Profile* profile, |
300 std::unique_ptr<ImporterList> importer_list, | 251 std::unique_ptr<ImporterList> importer_list, |
301 int items_to_import) { | 252 uint16_t items_to_import) { |
253 DCHECK(items_to_import); | |
302 const importer::SourceProfile& source_profile = | 254 const importer::SourceProfile& source_profile = |
303 importer_list->GetSourceProfileAt(0); | 255 importer_list->GetSourceProfileAt(0); |
304 // If no items to import then skip entirely. | |
305 if (!items_to_import) | |
306 return; | |
307 | 256 |
308 // Ensure that importers aren't requested to import items that they do not | 257 // Ensure that importers aren't requested to import items that they do not |
309 // support. If there is no overlap, skip. | 258 // support. If there is no overlap, skip. |
310 items_to_import &= source_profile.services_supported; | 259 items_to_import &= source_profile.services_supported; |
311 if (items_to_import) { | 260 if (items_to_import) |
312 ImportFromSourceProfile(source_profile, profile, items_to_import); | 261 ImportFromSourceProfile(source_profile, profile, items_to_import); |
313 } | |
314 | 262 |
315 g_auto_import_state |= first_run::AUTO_IMPORT_PROFILE_IMPORTED; | 263 g_auto_import_state |= first_run::AUTO_IMPORT_PROFILE_IMPORTED; |
316 } | 264 } |
317 | 265 |
318 GURL UrlFromString(const std::string& in) { | 266 GURL UrlFromString(const std::string& in) { |
319 return GURL(in); | 267 return GURL(in); |
320 } | 268 } |
321 | 269 |
322 void ConvertStringVectorToGURLVector( | 270 void ConvertStringVectorToGURLVector( |
323 const std::vector<std::string>& src, | 271 const std::vector<std::string>& src, |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 | 436 |
489 namespace first_run { | 437 namespace first_run { |
490 namespace internal { | 438 namespace internal { |
491 | 439 |
492 void SetupMasterPrefsFromInstallPrefs( | 440 void SetupMasterPrefsFromInstallPrefs( |
493 const installer::MasterPreferences& install_prefs, | 441 const installer::MasterPreferences& install_prefs, |
494 MasterPrefs* out_prefs) { | 442 MasterPrefs* out_prefs) { |
495 ConvertStringVectorToGURLVector( | 443 ConvertStringVectorToGURLVector( |
496 install_prefs.GetFirstRunTabs(), &out_prefs->new_tabs); | 444 install_prefs.GetFirstRunTabs(), &out_prefs->new_tabs); |
497 | 445 |
498 bool value = false; | |
499 if (install_prefs.GetBool( | |
500 installer::master_preferences::kDistroImportSearchPref, &value)) { | |
501 if (value) { | |
502 out_prefs->do_import_items |= importer::SEARCH_ENGINES; | |
503 } else { | |
504 out_prefs->dont_import_items |= importer::SEARCH_ENGINES; | |
505 } | |
506 } | |
507 | |
508 // If we're suppressing the first-run bubble, set that preference now. | 446 // If we're suppressing the first-run bubble, set that preference now. |
509 // Otherwise, wait until the user has completed first run to set it, so the | 447 // Otherwise, wait until the user has completed first run to set it, so the |
510 // user is guaranteed to see the bubble iff they have completed the first run | 448 // user is guaranteed to see the bubble iff they have completed the first run |
511 // process. | 449 // process. |
450 bool value = false; | |
512 if (install_prefs.GetBool( | 451 if (install_prefs.GetBool( |
513 installer::master_preferences::kDistroSuppressFirstRunBubble, | 452 installer::master_preferences::kDistroSuppressFirstRunBubble, |
514 &value) && value) | 453 &value) && |
454 value) { | |
515 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS); | 455 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS); |
516 | |
517 if (install_prefs.GetBool( | |
518 installer::master_preferences::kDistroImportHistoryPref, | |
519 &value)) { | |
520 if (value) { | |
521 out_prefs->do_import_items |= importer::HISTORY; | |
522 } else { | |
523 out_prefs->dont_import_items |= importer::HISTORY; | |
524 } | |
525 } | |
526 | |
527 std::string not_used; | |
528 out_prefs->homepage_defined = install_prefs.GetString( | |
529 prefs::kHomePage, ¬_used); | |
530 | |
531 if (install_prefs.GetBool( | |
532 installer::master_preferences::kDistroImportHomePagePref, | |
533 &value)) { | |
534 if (value) { | |
535 out_prefs->do_import_items |= importer::HOME_PAGE; | |
536 } else { | |
537 out_prefs->dont_import_items |= importer::HOME_PAGE; | |
538 } | |
539 } | |
540 | |
541 // Bookmarks are never imported unless specifically turned on. | |
542 if (install_prefs.GetBool( | |
543 installer::master_preferences::kDistroImportBookmarksPref, | |
544 &value)) { | |
545 if (value) | |
546 out_prefs->do_import_items |= importer::FAVORITES; | |
547 else | |
548 out_prefs->dont_import_items |= importer::FAVORITES; | |
549 } | 456 } |
550 | 457 |
551 if (install_prefs.GetBool( | 458 if (install_prefs.GetBool( |
552 installer::master_preferences::kMakeChromeDefaultForUser, | 459 installer::master_preferences::kMakeChromeDefaultForUser, |
553 &value) && value) { | 460 &value) && value) { |
554 out_prefs->make_chrome_default_for_user = true; | 461 out_prefs->make_chrome_default_for_user = true; |
555 } | 462 } |
556 | 463 |
557 if (install_prefs.GetBool( | 464 if (install_prefs.GetBool( |
558 installer::master_preferences::kSuppressFirstRunDefaultBrowserPrompt, | 465 installer::master_preferences::kSuppressFirstRunDefaultBrowserPrompt, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 FirstRunState DetermineFirstRunState(bool has_sentinel, | 516 FirstRunState DetermineFirstRunState(bool has_sentinel, |
610 bool force_first_run, | 517 bool force_first_run, |
611 bool no_first_run) { | 518 bool no_first_run) { |
612 return (force_first_run || (!has_sentinel && !no_first_run)) | 519 return (force_first_run || (!has_sentinel && !no_first_run)) |
613 ? FIRST_RUN_TRUE | 520 ? FIRST_RUN_TRUE |
614 : FIRST_RUN_FALSE; | 521 : FIRST_RUN_FALSE; |
615 } | 522 } |
616 | 523 |
617 } // namespace internal | 524 } // namespace internal |
618 | 525 |
619 MasterPrefs::MasterPrefs() | 526 MasterPrefs::MasterPrefs() = default; |
620 : homepage_defined(false), | |
621 do_import_items(0), | |
622 dont_import_items(0), | |
623 make_chrome_default_for_user(false), | |
624 suppress_first_run_default_browser_prompt(false), | |
625 welcome_page_on_os_upgrade_enabled(true) {} | |
626 | 527 |
627 MasterPrefs::~MasterPrefs() {} | 528 MasterPrefs::~MasterPrefs() = default; |
529 | |
530 void RegisterProfilePrefs( | |
531 user_prefs::PrefRegistrySyncable* registry) { | |
532 registry->RegisterBooleanPref(prefs::kImportAutofillFormData, false); | |
msw
2017/03/21 22:41:29
q: Was changing the default true->false for all th
msw
2017/03/21 22:43:57
Ha! I answered my own question by reading the CL t
gab
2017/03/21 22:53:41
Right, used to be tangled up but was just separate
| |
533 registry->RegisterBooleanPref(prefs::kImportBookmarks, false); | |
534 registry->RegisterBooleanPref(prefs::kImportHistory, false); | |
535 registry->RegisterBooleanPref(prefs::kImportHomepage, false); | |
536 registry->RegisterBooleanPref(prefs::kImportSavedPasswords, false); | |
537 registry->RegisterBooleanPref(prefs::kImportSearchEngine, false); | |
538 } | |
628 | 539 |
629 bool IsChromeFirstRun() { | 540 bool IsChromeFirstRun() { |
630 if (g_first_run == internal::FIRST_RUN_UNKNOWN) { | 541 if (g_first_run == internal::FIRST_RUN_UNKNOWN) { |
631 const base::CommandLine* command_line = | 542 const base::CommandLine* command_line = |
632 base::CommandLine::ForCurrentProcess(); | 543 base::CommandLine::ForCurrentProcess(); |
633 g_first_run = internal::DetermineFirstRunState( | 544 g_first_run = internal::DetermineFirstRunState( |
634 internal::IsFirstRunSentinelPresent(), | 545 internal::IsFirstRunSentinelPresent(), |
635 command_line->HasSwitch(switches::kForceFirstRun), | 546 command_line->HasSwitch(switches::kForceFirstRun), |
636 command_line->HasSwitch(switches::kNoFirstRun)); | 547 command_line->HasSwitch(switches::kNoFirstRun)); |
637 } | 548 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
749 DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); | 660 DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); |
750 | 661 |
751 internal::SetupMasterPrefsFromInstallPrefs(*install_prefs, out_prefs); | 662 internal::SetupMasterPrefsFromInstallPrefs(*install_prefs, out_prefs); |
752 } | 663 } |
753 | 664 |
754 return FIRST_RUN_PROCEED; | 665 return FIRST_RUN_PROCEED; |
755 } | 666 } |
756 | 667 |
757 void AutoImport( | 668 void AutoImport( |
758 Profile* profile, | 669 Profile* profile, |
759 bool homepage_defined, | |
760 int import_items, | |
761 int dont_import_items, | |
762 const std::string& import_bookmarks_path) { | 670 const std::string& import_bookmarks_path) { |
763 base::FilePath local_state_path; | 671 g_auto_import_state |= AUTO_IMPORT_CALLED; |
764 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); | |
765 bool local_state_file_exists = base::PathExists(local_state_path); | |
766 | 672 |
767 // It may be possible to do the if block below asynchronously. In which case, | 673 // Use |profile|'s PrefService to determine what to import. It will reflect in |
768 // get rid of this RunLoop. http://crbug.com/366116. | 674 // order: |
769 base::RunLoop run_loop; | 675 // 1) Policies. |
770 std::unique_ptr<ImporterList> importer_list(new ImporterList()); | 676 // 2) Master preferences (used to initialize user prefs in |
771 importer_list->DetectSourceProfiles( | 677 // ProcessMasterPreferences()). |
772 g_browser_process->GetApplicationLocale(), | 678 // 3) Recommended policies. |
773 false, // include_interactive_profiles? | 679 // 4) Registered default. |
774 run_loop.QuitClosure()); | 680 PrefService* prefs = profile->GetPrefs(); |
775 run_loop.Run(); | 681 uint16_t items_to_import = 0; |
682 static constexpr struct { | |
683 const char* pref_path; | |
684 importer::ImportItem bit; | |
685 } kImportItems[] = { | |
686 {prefs::kImportAutofillFormData, importer::AUTOFILL_FORM_DATA}, | |
687 {prefs::kImportBookmarks, importer::FAVORITES}, | |
688 {prefs::kImportHistory, importer::HISTORY}, | |
689 {prefs::kImportHomepage, importer::HOME_PAGE}, | |
690 {prefs::kImportSavedPasswords, importer::PASSWORDS}, | |
691 {prefs::kImportSearchEngine, importer::SEARCH_ENGINES}, | |
692 }; | |
776 | 693 |
777 // Do import if there is an available profile for us to import. | 694 for (const auto& import_item : kImportItems) { |
778 if (importer_list->count() > 0) { | 695 if (prefs->GetBoolean(import_item.pref_path)) |
779 if (internal::IsOrganicFirstRun()) { | 696 items_to_import |= import_item.bit; |
780 // Home page is imported in organic builds only unless turned off or | |
781 // defined in master_preferences. | |
782 if (homepage_defined) { | |
783 dont_import_items |= importer::HOME_PAGE; | |
784 if (import_items & importer::HOME_PAGE) | |
785 import_items &= ~importer::HOME_PAGE; | |
786 } | |
787 // Search engines are not imported automatically in organic builds if the | |
788 // user already has a user preferences directory. | |
789 if (local_state_file_exists) { | |
790 dont_import_items |= importer::SEARCH_ENGINES; | |
791 if (import_items & importer::SEARCH_ENGINES) | |
792 import_items &= ~importer::SEARCH_ENGINES; | |
793 } | |
794 } | |
795 | |
796 PrefService* user_prefs = profile->GetPrefs(); | |
797 int items = 0; | |
798 | |
799 SetImportItem(user_prefs, | |
800 prefs::kImportHistory, | |
801 import_items, | |
802 dont_import_items, | |
803 importer::HISTORY, | |
804 &items); | |
805 SetImportItem(user_prefs, | |
806 prefs::kImportHomepage, | |
807 import_items, | |
808 dont_import_items, | |
809 importer::HOME_PAGE, | |
810 &items); | |
811 SetImportItem(user_prefs, | |
812 prefs::kImportSearchEngine, | |
813 import_items, | |
814 dont_import_items, | |
815 importer::SEARCH_ENGINES, | |
816 &items); | |
817 SetImportItem(user_prefs, | |
818 prefs::kImportBookmarks, | |
819 import_items, | |
820 dont_import_items, | |
821 importer::FAVORITES, | |
822 &items); | |
823 | |
824 importer::LogImporterUseToMetrics( | |
825 "AutoImport", importer_list->GetSourceProfileAt(0).importer_type); | |
826 | |
827 ImportSettings(profile, std::move(importer_list), items); | |
828 } | 697 } |
829 | 698 |
830 if (!import_bookmarks_path.empty()) { | 699 if (items_to_import) { |
831 ImportFromFile(profile, import_bookmarks_path); | 700 // It may be possible to do the if block below asynchronously. In which |
701 // case, get rid of this RunLoop. http://crbug.com/366116. | |
702 base::RunLoop run_loop; | |
703 auto importer_list = base::MakeUnique<ImporterList>(); | |
704 importer_list->DetectSourceProfiles( | |
705 g_browser_process->GetApplicationLocale(), | |
706 false, // include_interactive_profiles? | |
707 run_loop.QuitClosure()); | |
708 run_loop.Run(); | |
709 | |
710 if (importer_list->count() > 0) { | |
711 importer::LogImporterUseToMetrics( | |
712 "AutoImport", importer_list->GetSourceProfileAt(0).importer_type); | |
713 | |
714 ImportSettings(profile, std::move(importer_list), items_to_import); | |
715 } | |
832 } | 716 } |
833 | 717 |
834 content::RecordAction(UserMetricsAction("FirstRunDef_Accept")); | 718 if (!import_bookmarks_path.empty()) |
835 | 719 ImportFromFile(profile, import_bookmarks_path); |
836 g_auto_import_state |= AUTO_IMPORT_CALLED; | |
837 } | 720 } |
838 | 721 |
839 void DoPostImportTasks(Profile* profile, bool make_chrome_default_for_user) { | 722 void DoPostImportTasks(Profile* profile, bool make_chrome_default_for_user) { |
840 // Only set default browser after import as auto import relies on the current | 723 // Only set default browser after import as auto import relies on the current |
841 // default browser to know what to import from. | 724 // default browser to know what to import from. |
842 ProcessDefaultBrowserPolicy(make_chrome_default_for_user); | 725 ProcessDefaultBrowserPolicy(make_chrome_default_for_user); |
843 | 726 |
844 // Display the first run bubble if there is a default search provider. | 727 // Display the first run bubble if there is a default search provider. |
845 TemplateURLService* template_url = | 728 TemplateURLService* template_url = |
846 TemplateURLServiceFactory::GetForProfile(profile); | 729 TemplateURLServiceFactory::GetForProfile(profile); |
847 if (template_url && template_url->GetDefaultSearchProvider()) | 730 if (template_url && template_url->GetDefaultSearchProvider()) |
848 FirstRunBubbleLauncher::ShowFirstRunBubbleSoon(); | 731 FirstRunBubbleLauncher::ShowFirstRunBubbleSoon(); |
849 SetShouldShowWelcomePage(); | 732 SetShouldShowWelcomePage(); |
850 SetShouldDoPersonalDataManagerFirstRun(); | 733 SetShouldDoPersonalDataManagerFirstRun(); |
851 | 734 |
852 internal::DoPostImportPlatformSpecificTasks(profile); | 735 internal::DoPostImportPlatformSpecificTasks(profile); |
853 } | 736 } |
854 | 737 |
855 uint16_t auto_import_state() { | 738 uint16_t auto_import_state() { |
856 return g_auto_import_state; | 739 return g_auto_import_state; |
857 } | 740 } |
858 | 741 |
859 } // namespace first_run | 742 } // namespace first_run |
OLD | NEW |