Chromium Code Reviews| 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 // This file defines specific implementation of BrowserDistribution class for | 5 // This file defines specific implementation of BrowserDistribution class for |
| 6 // Google Chrome. | 6 // Google Chrome. |
| 7 | 7 |
| 8 #include "chrome/installer/util/google_chrome_distribution.h" | 8 #include "chrome/installer/util/google_chrome_distribution.h" |
| 9 | 9 |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 const wchar_t kCommandExecuteImplUuid[] = | 53 const wchar_t kCommandExecuteImplUuid[] = |
| 54 L"{5C65F4B0-3651-4514-B207-D10CB699B14B}"; | 54 L"{5C65F4B0-3651-4514-B207-D10CB699B14B}"; |
| 55 const wchar_t kDelegateExecuteLibUuid[] = | 55 const wchar_t kDelegateExecuteLibUuid[] = |
| 56 L"{4E805ED8-EBA0-4601-9681-12815A56EBFD}"; | 56 L"{4E805ED8-EBA0-4601-9681-12815A56EBFD}"; |
| 57 const wchar_t kDelegateExecuteLibVersion[] = L"1.0"; | 57 const wchar_t kDelegateExecuteLibVersion[] = L"1.0"; |
| 58 const wchar_t kICommandExecuteImplUuid[] = | 58 const wchar_t kICommandExecuteImplUuid[] = |
| 59 L"{0BA0D4E9-2259-4963-B9AE-A839F7CB7544}"; | 59 L"{0BA0D4E9-2259-4963-B9AE-A839F7CB7544}"; |
| 60 | 60 |
| 61 // The following strings are the possible outcomes of the toast experiment | 61 // The following strings are the possible outcomes of the toast experiment |
| 62 // as recorded in the |client| field. | 62 // as recorded in the |client| field. |
| 63 const wchar_t kToastExpControlGroup[] = L"01"; | 63 const wchar_t kToastExpControlGroup[] = L"01"; |
| 64 const wchar_t kToastExpCancelGroup[] = L"02"; | 64 const wchar_t kToastExpCancelGroup[] = L"02"; |
| 65 const wchar_t kToastExpUninstallGroup[] = L"04"; | 65 const wchar_t kToastExpUninstallGroup[] = L"04"; |
| 66 const wchar_t kToastExpTriesOkGroup[] = L"18"; | 66 const wchar_t kToastExpTriesOkGroup[] = L"18"; |
| 67 const wchar_t kToastExpTriesErrorGroup[] = L"28"; | 67 const wchar_t kToastExpTriesOkDefaultGroup[] = L"28"; |
|
Finnur
2012/07/26 12:27:07
This would change the result code that gets sent b
Mark Larson
2012/07/26 16:32:13
I'm also concerned about how this will show up on
cpu_(ooo_6.6-7.5)
2012/07/27 03:06:23
Done.
| |
| 68 const wchar_t kToastActiveGroup[] = L"40"; | 68 const wchar_t kToastExpTriesErrorGroup[] = L"48"; |
| 69 const wchar_t kToastUDDirFailure[] = L"40"; | 69 const wchar_t kToastActiveGroup[] = L"40"; |
| 70 const wchar_t kToastExpBaseGroup[] = L"80"; | 70 const wchar_t kToastUDDirFailure[] = L"40"; |
| 71 const wchar_t kToastExpBaseGroup[] = L"80"; | |
| 71 | 72 |
| 72 // Substitute the locale parameter in uninstall URL with whatever | 73 // Substitute the locale parameter in uninstall URL with whatever |
| 73 // Google Update tells us is the locale. In case we fail to find | 74 // Google Update tells us is the locale. In case we fail to find |
| 74 // the locale, we use US English. | 75 // the locale, we use US English. |
| 75 string16 LocalizeUrl(const wchar_t* url) { | 76 string16 LocalizeUrl(const wchar_t* url) { |
| 76 string16 language; | 77 string16 language; |
| 77 if (!GoogleUpdateSettings::GetLanguage(&language)) | 78 if (!GoogleUpdateSettings::GetLanguage(&language)) |
| 78 language = L"en-US"; // Default to US English. | 79 language = L"en-US"; // Default to US English. |
| 79 return ReplaceStringPlaceholders(url, language.c_str(), NULL); | 80 return ReplaceStringPlaceholders(url, language.c_str(), NULL); |
| 80 } | 81 } |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 // This struct determines which experiment flavors we show for each locale and | 617 // This struct determines which experiment flavors we show for each locale and |
| 617 // brand. | 618 // brand. |
| 618 // | 619 // |
| 619 // The big experiment in Dec 2009 used TGxx and THxx. | 620 // The big experiment in Dec 2009 used TGxx and THxx. |
| 620 // The big experiment in Feb 2010 used TKxx and TLxx. | 621 // The big experiment in Feb 2010 used TKxx and TLxx. |
| 621 // The big experiment in Apr 2010 used TMxx and TNxx. | 622 // The big experiment in Apr 2010 used TMxx and TNxx. |
| 622 // The big experiment in Oct 2010 used TVxx TWxx TXxx TYxx. | 623 // The big experiment in Oct 2010 used TVxx TWxx TXxx TYxx. |
| 623 // The big experiment in Feb 2011 used SJxx SKxx SLxx SMxx. | 624 // The big experiment in Feb 2011 used SJxx SKxx SLxx SMxx. |
| 624 // Note: the plugin infobar experiment uses PIxx codes. | 625 // Note: the plugin infobar experiment uses PIxx codes. |
| 625 using namespace attrition_experiments; | 626 using namespace attrition_experiments; |
| 627 struct FlavorDetails { | |
| 628 int heading_id; | |
| 629 int flags; | |
| 630 }; | |
|
Finnur
2012/07/26 12:27:07
This struct should probably move to line 617, as t
| |
| 631 | |
| 626 static const struct UserExperimentDetails { | 632 static const struct UserExperimentDetails { |
| 627 const wchar_t* locale; // Locale to show this experiment for (* for all). | 633 const wchar_t* locale; // Locale to show this experiment for (* for all). |
| 628 const wchar_t* brands; // Brand codes show this experiment for (* for all). | 634 const wchar_t* brands; // Brand codes show this experiment for (* for all). |
| 629 int control_group; // Size of the control group, in percentages. | 635 int control_group; // Size of the control group, in percentages. |
| 630 const wchar_t prefix1; // The first letter for the experiment code. | 636 const wchar_t* prefix; // The two letter experiment code. The second letter |
| 631 const wchar_t prefix2; // The second letter for the experiment code. This | 637 // will be incremented with the flavor. |
| 632 // will be incremented by one for each additional | 638 FlavorDetails flavors[kMax]; |
| 633 // experiment flavor beyond the first. | 639 } kExperiments[] = { |
| 634 int flavors; // Numbers of flavors for this experiment. Should | 640 // The first match from top to bottom is used so this list should be ordered |
| 635 // always be positive and never exceed the number | 641 // most-specific rule first. |
| 636 // of headings (below). | 642 { L"*", L"CHMA", // all locales, CHMA brand. |
|
Finnur
2012/07/26 12:27:07
nit: Capitalize first letter of comments in this l
cpu_(ooo_6.6-7.5)
2012/07/27 03:06:23
Done.
| |
| 637 int headings[kMax]; // A list of IDs per experiment. 0 == no heading. | 643 25, // 25 percent control group. |
| 638 } kExperimentFlavors[] = { | 644 L"ZA", // experiment is ZAxx, ZBxx, ZCxx, ZDxx etc. |
| 639 // This list should be ordered most-specific rule first (catch-all, like all | 645 // Three flavors. |
| 640 // brands or all locales should be last). | 646 { { IDS_TRY_TOAST_HEADING3, kDontBugMeAsButton | kUninstall | kWhyLink }, |
|
Finnur
2012/07/26 12:27:07
I thought we'd decided not to have a Why link, sin
cpu_(ooo_6.6-7.5)
2012/07/27 03:06:23
No idea. Can you please raise the issue in the bug
Finnur
2012/07/29 19:09:44
OK, I refreshed my memory by looking up the bug...
| |
| 641 | 647 { IDS_TRY_TOAST_HEADING3, 0 }, |
|
Finnur
2012/07/26 12:27:07
I'm confused about what these enums mean. What doe
cpu_(ooo_6.6-7.5)
2012/07/27 03:06:23
it means don't bug me is a radio button, because t
| |
| 642 // The experiment with the more compact bubble. This one is a bit special | 648 { IDS_TRY_TOAST_HEADING3, kMakeDefault }, |
| 643 // because it is split into two: CAxx is regular style bubble and CBxx is | 649 { 0, 0 }, |
| 644 // compact style bubble. See |compact_bubble| below. | 650 } |
| 645 {L"en-US", kBrief, 1, L'C', L'A', 2, { kEnUs3, kEnUs3, 0, 0 } }, | 651 }, |
| 646 | 652 { L"*", L"GGRV", // all locales, GGRV is enterprise. |
| 647 // Catch-all rules. | 653 0, // 0 percent control group. |
| 648 {kAll, kAll, 1, L'B', L'A', 1, {kEnUs3, 0, 0, 0} }, | 654 L"EA", // experiment is EAxx, EBxx, etc. |
|
Finnur
2012/07/26 12:27:07
Just curious... There's no experiment, so why have
cpu_(ooo_6.6-7.5)
2012/07/27 03:06:23
No very good reason: In case we f*ck up we can see
Finnur
2012/07/29 19:09:44
Fair enough. Consider documenting on line 624?
On
cpu_(ooo_6.6-7.5)
2012/07/31 04:04:09
Others missing. I'll change here after I talk to l
| |
| 655 // No flavors means no experiment. | |
| 656 { { 0, 0 }, | |
| 657 { 0, 0 }, | |
| 658 { 0, 0 }, | |
| 659 { 0, 0 } | |
| 660 } | |
| 661 } | |
| 649 }; | 662 }; |
| 650 | 663 |
| 651 string16 locale; | 664 string16 locale; |
| 652 GoogleUpdateSettings::GetLanguage(&locale); | 665 GoogleUpdateSettings::GetLanguage(&locale); |
| 653 if (locale.empty() || (locale == ASCIIToWide("en"))) | 666 if (locale.empty() || (locale == ASCIIToWide("en"))) |
| 654 locale = ASCIIToWide("en-US"); | 667 locale = ASCIIToWide("en-US"); |
| 655 | 668 |
| 656 string16 brand; | 669 string16 brand; |
| 657 if (!GoogleUpdateSettings::GetBrand(&brand)) | 670 if (!GoogleUpdateSettings::GetBrand(&brand)) |
| 658 brand = ASCIIToWide(""); // Could still be viable for catch-all rules. | 671 brand = ASCIIToWide(""); // Could still be viable for catch-all rules. |
| 659 if (brand == kEnterprise) | |
| 660 return false; | |
| 661 | 672 |
| 662 for (int i = 0; i < arraysize(kExperimentFlavors); ++i) { | 673 for (int i = 0; i < arraysize(kExperiments); ++i) { |
| 663 // A maximum of four flavors are supported at the moment. | 674 if (kExperiments[i].locale != locale && |
| 664 CHECK_LE(kExperimentFlavors[i].flavors, kMax); | 675 kExperiments[i].locale != ASCIIToWide("*")) |
| 665 CHECK_GT(kExperimentFlavors[i].flavors, 0); | |
| 666 // Make sure each experiment has valid headings. | |
| 667 for (int f = 0; f < kMax; ++f) { | |
| 668 if (f < kExperimentFlavors[i].flavors) { | |
| 669 CHECK_GT(kExperimentFlavors[i].headings[f], 0); | |
| 670 } else { | |
| 671 CHECK_EQ(kExperimentFlavors[i].headings[f], 0); | |
| 672 } | |
| 673 } | |
| 674 // The prefix has to be a valid two letter combo. | |
| 675 CHECK(kExperimentFlavors[i].prefix1 >= 'A'); | |
| 676 CHECK(kExperimentFlavors[i].prefix2 >= 'A'); | |
| 677 CHECK(kExperimentFlavors[i].prefix2 + | |
| 678 kExperimentFlavors[i].flavors - 1 <= 'Z'); | |
| 679 | |
| 680 if (kExperimentFlavors[i].locale != locale && | |
| 681 kExperimentFlavors[i].locale != ASCIIToWide("*")) | |
| 682 continue; | 676 continue; |
| 683 | 677 |
| 684 std::vector<string16> brand_codes; | 678 std::vector<string16> brand_codes; |
| 685 base::SplitString(kExperimentFlavors[i].brands, L',', &brand_codes); | 679 base::SplitString(kExperiments[i].brands, L',', &brand_codes); |
| 686 if (brand_codes.empty()) | 680 if (brand_codes.empty()) |
| 687 return false; | 681 return false; |
| 688 for (std::vector<string16>::iterator it = brand_codes.begin(); | 682 for (std::vector<string16>::iterator it = brand_codes.begin(); |
| 689 it != brand_codes.end(); ++it) { | 683 it != brand_codes.end(); ++it) { |
| 690 if (*it != brand && *it != L"*") | 684 if (*it != brand && *it != L"*") |
| 691 continue; | 685 continue; |
| 686 // We have found our match. | |
| 687 const UserExperimentDetails& match = kExperiments[i]; | |
| 688 // Find out how many flavors we have. Zero means no experiment. | |
| 689 int num_flavors = 0; | |
| 690 while (match.flavors[num_flavors].heading_id) { ++num_flavors; } | |
| 691 if (!num_flavors) | |
| 692 return false; | |
| 692 | 693 |
| 693 // We have found our match. | |
| 694 if (flavor < 0) | 694 if (flavor < 0) |
| 695 flavor = base::RandInt(0, kExperimentFlavors[i].flavors - 1); | 695 flavor = base::RandInt(0, num_flavors - 1); |
| 696 experiment->flavor = flavor; | 696 experiment->flavor = flavor; |
| 697 experiment->heading = kExperimentFlavors[i].headings[flavor]; | 697 experiment->heading = match.flavors[flavor].heading_id; |
| 698 experiment->control_group = kExperimentFlavors[i].control_group; | 698 experiment->control_group = match.control_group; |
| 699 experiment->prefix.resize(2); | 699 const wchar_t prefix[] = { match.prefix[0], match.prefix[1] + flavor, 0 }; |
| 700 experiment->prefix[0] = kExperimentFlavors[i].prefix1; | 700 experiment->prefix = prefix; |
| 701 experiment->prefix[1] = kExperimentFlavors[i].prefix2 + flavor; | 701 experiment->flags = match.flavors[flavor].flags; |
| 702 experiment->compact_bubble = (brand == kBrief) && (flavor == 1); | |
| 703 return true; | 702 return true; |
| 704 } | 703 } |
| 705 } | 704 } |
| 706 | 705 |
| 707 return false; | 706 return false; |
| 708 } | 707 } |
| 709 | 708 |
| 710 // Currently we only have one experiment: the inactive user toast. Which only | 709 // Currently we only have one experiment: the inactive user toast. Which only |
| 711 // applies for users doing upgrades. | 710 // applies for users doing upgrades. |
| 712 | 711 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 829 // The command line should now have the url added as: | 828 // The command line should now have the url added as: |
| 830 // "chrome.exe -- <url>" | 829 // "chrome.exe -- <url>" |
| 831 DCHECK_NE(string16::npos, | 830 DCHECK_NE(string16::npos, |
| 832 options.GetCommandLineString().find(L" -- " + url)); | 831 options.GetCommandLineString().find(L" -- " + url)); |
| 833 } | 832 } |
| 834 // Launch chrome now. It will show the toast UI. | 833 // Launch chrome now. It will show the toast UI. |
| 835 int32 exit_code = 0; | 834 int32 exit_code = 0; |
| 836 if (!installation.LaunchChromeAndWait(application_path, options, &exit_code)) | 835 if (!installation.LaunchChromeAndWait(application_path, options, &exit_code)) |
| 837 return; | 836 return; |
| 838 | 837 |
| 839 // The chrome process has exited, figure out what happened. | 838 // The chrome process has exited, figure out what happened. |
|
Mark Larson
2012/07/26 16:32:13
Don't we need something here that sets outcome to
cpu_(ooo_6.6-7.5)
2012/07/27 03:06:23
Yes, I am trying to figure how to do this. Stay tu
cpu_(ooo_6.6-7.5)
2012/07/31 04:04:09
Done.
| |
| 840 const wchar_t* outcome = NULL; | 839 const wchar_t* outcome = NULL; |
| 841 switch (exit_code) { | 840 switch (exit_code) { |
| 842 case content::RESULT_CODE_NORMAL_EXIT: | 841 case content::RESULT_CODE_NORMAL_EXIT: |
| 843 outcome = kToastExpTriesOkGroup; | 842 outcome = kToastExpTriesOkGroup; |
| 844 break; | 843 break; |
| 845 case chrome::RESULT_CODE_NORMAL_EXIT_CANCEL: | 844 case chrome::RESULT_CODE_NORMAL_EXIT_CANCEL: |
| 846 outcome = kToastExpCancelGroup; | 845 outcome = kToastExpCancelGroup; |
| 847 break; | 846 break; |
| 848 case chrome::RESULT_CODE_NORMAL_EXIT_EXP2: | 847 case chrome::RESULT_CODE_NORMAL_EXIT_EXP2: |
| 849 outcome = kToastExpUninstallGroup; | 848 outcome = kToastExpUninstallGroup; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 862 // we waited for chrome to exit so the uninstall would not detect chrome | 861 // we waited for chrome to exit so the uninstall would not detect chrome |
| 863 // running. | 862 // running. |
| 864 bool system_level_toast = CommandLine::ForCurrentProcess()->HasSwitch( | 863 bool system_level_toast = CommandLine::ForCurrentProcess()->HasSwitch( |
| 865 installer::switches::kSystemLevelToast); | 864 installer::switches::kSystemLevelToast); |
| 866 | 865 |
| 867 CommandLine cmd(InstallUtil::GetChromeUninstallCmd(system_level_toast, | 866 CommandLine cmd(InstallUtil::GetChromeUninstallCmd(system_level_toast, |
| 868 GetType())); | 867 GetType())); |
| 869 base::LaunchProcess(cmd, base::LaunchOptions(), NULL); | 868 base::LaunchProcess(cmd, base::LaunchOptions(), NULL); |
| 870 } | 869 } |
| 871 #endif | 870 #endif |
| OLD | NEW |