summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 16:16:33 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 16:16:33 +0000
commitea4a9412740c21369fce50ac8fd6322334beca1c (patch)
tree364c8019b8faf7fd2100ab34966b8d5b2241d23e
parent3bd61de09a1aadbf57d61ace0d478b59bfd375f3 (diff)
downloadchromium_src-ea4a9412740c21369fce50ac8fd6322334beca1c.zip
chromium_src-ea4a9412740c21369fce50ac8fd6322334beca1c.tar.gz
chromium_src-ea4a9412740c21369fce50ac8fd6322334beca1c.tar.bz2
<html>
<style type="text/css"> <!-- body { font-family: arial,sans-serif; background-color: #fff; margin-top: 2; } .c { width: 4; height: 4; } a:link { color: #00c; } a:visited { color: #551a8b; } a:active { color: #f00; } .form-noindent { background-color: #fff; border: 1px solid #c3d9ff; } --> </style> <style type="text/css"><!-- .gaia.le.lbl { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.le.fpwd { font-family: Arial, Helvetica, sans-serif; font-size: 70%; } .gaia.le.chusr { font-family: Arial, Helvetica, sans-serif; font-size: 70%; } .gaia.le.val { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.le.rem { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.captchahtml.desc { font-family: arial, sans-serif; font-size: smaller; } .gaia.captchahtml.cmt { font-family: arial, sans-serif; font-size: smaller; font-style: italic; } --></style> <head> <title>Google Accounts</title> <style type="text/css"><!-- body { font-family: arial, sans-serif; margin: 0; padding: 13px 15px 15px; } .body { margin: 0; } div.errorbox-good {} div.errorbox-bad {} div.errormsg { color: red; font-size: smaller; font-family: arial,sans-serif;} font.errormsg { color: red; font-size: smaller; font-family: arial,sans-serif;} div.topbar { font-size:smaller; margin-right: -5px; text-align:right; white-space:nowrap; } div.header { margin-bottom: 9px; margin-left: -2px; position:relative; zoom: 1 } div.header img.logo { border: 0; float:left; } div.header div.headercontent { float:right; margin-top:17px; } div.header:after{ content:"."; display:block; height:0; clear:both; visibility:hidden; } div.pagetitle { font-weight:bold; } .footer { color: #666; font-size: smaller; margin-top: 40px; text-align: center; } table#signupform { left: -5px; top: -7px; position:relative; } table#signupform td{ padding: 7px 5px; } table#signupform td table td{ padding: 1px; } hr { border: 0; background-color:#DDDDDD; height: 1px; width: 100%; text-align: left; margin: 5px; } --></style> </head> <body dir="ltr" onLoad= "gaia_setFocus();" > <div id="main"> <?sc # for new logo transition ?> <div class=header> <a href='https://www.google.com/accounts/'> <img class=logo src='https://www.google.com/intl/en/images/logos/accounts_logo.gif' alt="Google" /> </img> </a> </div> <div id=maincontent> <table border="0" width="100%" cellpadding=0 cellspacing=0> <tr> <td width="75%" valign="top"> <h3> Chromium Code Reviews uses Google Accounts for Sign In. </h3> <p><font size=-1> Google is not affiliated with the contents of <b>Chromium Code Reviews</b> or its owners. If you sign in, Google will share your email address with <b>Chromium Code Reviews</b>, but not your password or any other personal information. </font></p> <p><font size=-1> <b>Chromium Code Reviews</b> may use your email address to personalize your experience on their website. </font></p> </td> <td style="padding-left: 10px;" valign="top" align="center"> <div id="rhs"> <div id="rhs_login_signup_box"> <script><!-- function gaia_onLoginSubmit() { if (window.gaiacb_onLoginSubmit) { return gaiacb_onLoginSubmit(); } else { return true; } } function gaia_setFocus() { var f = null; if (document.getElementById) { f = document.getElementById("gaia_loginform"); } else if (window.gaia_loginform) { f = window.gaia_loginform; } if (f) { if (f.Email && (f.Email.value == null || f.Email.value == "")) { f.Email.focus(); } else if (f.Passwd) { f.Passwd.focus(); } } } --></script> <style type="text/css"><!-- div.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif; } font.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif; } --></style> <style type="text/css"><!-- .gaia.le.lbl { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.le.fpwd { font-family: Arial, Helvetica, sans-serif; font-size: 70%; } .gaia.le.chusr { font-family: Arial, Helvetica, sans-serif; font-size: 70%; } .gaia.le.val { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.le.rem { font-family: Arial, Helvetica, sans-serif; font-size: smaller; } .gaia.captchahtml.desc { font-family: arial, sans-serif; font-size: smaller; } .gaia.captchahtml.cmt { font-family: arial, sans-serif; font-size: smaller; font-style: italic; } --></style> <form id="gaia_loginform" action="https://www.google.com/accounts/ServiceLoginAuth?service=ah&amp;sig=d71ef8b8d6150b23958ad03b3bf546b7" method="post" onsubmit= "return(gaia_onLoginSubmit());" > <div id="gaia_loginbox"> <table class="form-noindent" cellspacing="3" cellpadding="5" width="100%" border="0"> <tr> <td valign="top" style="text-align:center" nowrap="nowrap" bgcolor="#e8eefa"> <input type="hidden" name="ltmpl" value="gm"> <div class="loginBox"> <table id="gaia_table" align="center" border="0" cellpadding="1" cellspacing="0"> <tr> <td colspan="2" align="center"> <font size="-1"> Sign in with your </font> <table> <tr> <td valign="top"> <img src="google_transparent.gif" alt="Google"> </img> </td> <td valign="middle"> <font size="+0"><b>Account</b></font> </td> </tr> </table> </td> </tr> <script type="text/javascript"><!-- function onPreCreateAccount() { return true; } function onPreLogin() { if (window["onlogin"] != null) { return onlogin(); } else { return true; } } --></script> <tr> <td colspan="2" align="center"> </td> </tr> <tr> <td nowrap="nowrap"> <div align="right"> <span class="gaia le lbl"> Email: </span> </div> </td> <td> <input type="hidden" name="continue" id="continue" value="http://codereview.chromium.org/_ah/login?continue=http://codereview.chromium.org/210007/description" /> <input type="hidden" name="service" id="service" value="ah" /> <input type="hidden" name="ltmpl" id="ltmpl" value="gm" /> <input type="hidden" name="ltmpl" id="ltmpl" value="gm" /> <input type="hidden" name="ahname" id="ahname" value="Chromium Code Reviews" /> <input type="hidden" name="GALX" value="LfA4LnZj1gM" /> <input type="text" name="Email" id="Email" size="18" value="" class='gaia le val' /> </td> </tr> <tr> <td></td> <td align="left"> </td> </tr> <tr> <td align="right" nowrap="nowrap"> <span class="gaia le lbl"> Password: </span> </td> <td> <input type="password" name="Passwd" id="Passwd" size="18" class="gaia le val" /> </td> </tr> <tr> <td> </td> <td align="left"> </td> </tr> <tr> <td align="right" valign="top"> <input type="checkbox" name="PersistentCookie" id="PersistentCookie" value="yes" checked='checked' /> <input type="hidden" name='rmShown' value="1" /> </td> <td> <label for="PersistentCookie" class="gaia le rem"> Stay signed in </label> </td> </tr> <tr> <td> </td> <td align="left"> <input type="submit" class="gaia le button" name="signIn" value="Sign in" /> </td> </tr> <tr id="ga-fprow"> <td colspan="2" height="33.0" class="gaia le fpwd" align="center" valign="bottom"> <a href="http://www.google.com/support/accounts/bin/answer.py?answer=48598&amp;hl=en&amp;ctx=ch_ServiceLogin&amp;p=ah&amp;fpUrl=https%3A%2F%2Fwww.google.com%2Faccounts%2FForgotPasswd%3FfpOnly%3D1%26continue%3Dhttp%253A%252F%252Fcodereview.chromium.org%252F_ah%252Flogin%253Fcontinue%253Dhttp%253A%252F%252Fcodereview.chromium.org%252F210007%252Fdescription%26service%3Dah%26ltmpl%3Dgm" target=_top> Can&#39;t access your account? </a> </td> </tr> </table> </div> </td> </tr> </table> </div> <input type="hidden" name="asts" id="asts" value=""> </form> <form id="gaia_universallogin" action="https://www.google.com/accounts/ServiceLoginAuth?service=ah&amp;sig=d71ef8b8d6150b23958ad03b3bf546b7" method="post" onsubmit="return(gaia_onLoginSubmit());"> <input type="hidden" name="continue" id="continue" value="http://codereview.chromium.org/_ah/login?continue=http://codereview.chromium.org/210007/description" /> <input type="hidden" name="service" id="service" value="ah" /> <input type="hidden" name="ltmpl" id="ltmpl" value="gm" /> <input type="hidden" name="ltmpl" id="ltmpl" value="gm" /> <input type="hidden" name="ahname" id="ahname" value="Chromium Code Reviews" /> <input type="hidden" name="ltmpl" id="ltmpl" value="gm" /> </form> <br/> <table class="form-noindent" border="0" cellpadding="6" cellspacing="3" width="100%"> <tr> <td bgcolor="#e8eefa" align="center" style="font-size:83%"> <b>Don't have a Google Account? </b><br/> <a href='https://www.google.com/accounts/NewAccount?continue=http%3A%2F%2Fcodereview.chromium.org%2F_ah%2Flogin%3Fcontinue%3Dhttp%3A%2F%2Fcodereview.chromium.org%2F210007%2Fdescription&amp;service=ah&amp;ltmpl=gm&amp;sig=909f6cca8e55250406f8bfbd303ab4a9' > <b>Create an account now</b> </a> </td> </tr> </table> </div> <br/> </div> </td> </tr> </table> </div> <div class="footer"> &copy;2009 Google - <a href='http://www.google.com/'>Google Home</a> - <a href='https://www.google.com/accounts/TOS?hl=en'>Terms of Service</a> - <a href='http://www.google.com/intl/en/privacy.html'>Privacy Policy</a> - <a href='http://www.google.com/support/accounts?hl=en'>Help</a> </div> </div> </body> </html> Review URL: http://codereview.chromium.org/210007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26685 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_init.cc11
-rw-r--r--chrome/common/chrome_switches.cc4
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--chrome/installer/setup/setup_main.cc7
-rw-r--r--chrome/installer/setup/uninstall.cc46
-rw-r--r--chrome/installer/setup/uninstall.h5
-rw-r--r--chrome/installer/util/shell_util.cc35
-rw-r--r--chrome/installer/util/shell_util.h11
8 files changed, 44 insertions, 76 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index e7e1ae5..1f0f5b1 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -827,17 +827,6 @@ bool BrowserInit::ProcessCmdLineImpl(const CommandLine& command_line,
profile, expected_tabs);
}
- if (command_line.HasSwitch(switches::kInstallExtension)) {
- std::wstring path_string =
- command_line.GetSwitchValue(switches::kInstallExtension);
- FilePath path = FilePath::FromWStringHack(path_string);
- profile->GetExtensionsService()->InstallExtension(path);
-
- // If the chrome process was already running, install the extension without
- // popping up another browser window.
- silent_launch = !process_startup;
- }
-
if (command_line.HasSwitch(switches::kExplicitlyAllowedPorts)) {
std::wstring allowed_ports =
command_line.GetSwitchValue(switches::kExplicitlyAllowedPorts);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 978c7c6..e320f82 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -394,10 +394,6 @@ const wchar_t kDisableExtensions[] = L"disable-extensions";
// Frequency in seconds for Extensions auto-update.
const wchar_t kExtensionsUpdateFrequency[] = L"extensions-update-frequency";
-// Install the extension specified in the argument. This is for MIME type
-// handling so that users can double-click on an extension.
-const wchar_t kInstallExtension[] = L"install-extension";
-
// Load an extension from the specified directory.
const wchar_t kLoadExtension[] = L"load-extension";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 733d706..1d25d7c 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -146,7 +146,6 @@ extern const wchar_t kSdchFilter[];
extern const wchar_t kEnableUserScripts[];
extern const wchar_t kDisableExtensions[];
extern const wchar_t kExtensionsUpdateFrequency[];
-extern const wchar_t kInstallExtension[];
extern const wchar_t kLoadExtension[];
extern const wchar_t kPackExtension[];
extern const wchar_t kPackExtensionKey[];
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 14dbf5e..8b70a1b 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -281,9 +281,11 @@ installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line,
if (install_status == installer_util::FIRST_INSTALL_SUCCESS) {
LOG(INFO) << "First install successful.";
// We never want to launch Chrome in system level install mode.
- if (!system_level && !installer_util::GetDistroBooleanPreference(prefs,
- installer_util::master_preferences::kDoNotLaunchChrome))
+ if (!system_level && !installer_util::GetDistroBooleanPreference(
+ prefs, installer_util::master_preferences::kDoNotLaunchChrome))
installer::LaunchChrome(system_level);
+ } else if (install_status == installer_util::NEW_VERSION_UPDATED) {
+ installer_setup::RemoveLegacyRegistryKeys();
}
}
}
@@ -328,6 +330,7 @@ installer_util::InstallStatus UninstallChrome(const CommandLine& cmd_line,
bool remove_all = !cmd_line.HasSwitch(
installer_util::switches::kDoNotRemoveSharedItems);
+
return installer_setup::UninstallChrome(cmd_line.program(), system_install,
remove_all, force,
cmd_line, cmd_params);
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 206cf72..978c056 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -279,18 +279,6 @@ bool installer_setup::DeleteChromeRegistrationKeys(HKEY root,
html_prog_id.append(browser_entry_suffix);
DeleteRegistryKey(key, html_prog_id);
- // Delete Software\Classes\ChromeExt,
- std::wstring ext_prog_id(ShellUtil::kRegClasses);
- file_util::AppendToPath(&ext_prog_id, ShellUtil::kChromeExtProgId);
- ext_prog_id.append(browser_entry_suffix);
- DeleteRegistryKey(key, ext_prog_id);
-
- // Delete Software\Classes\.crx,
- std::wstring ext_association(ShellUtil::kRegClasses);
- ext_association.append(L"\\.");
- ext_association.append(chrome::kExtensionFileExtension);
- DeleteRegistryKey(key, ext_association);
-
// Delete Software\Clients\StartMenuInternet\Chromium
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
std::wstring set_access_key(ShellUtil::kRegStartMenuInternet);
@@ -334,6 +322,40 @@ bool installer_setup::DeleteChromeRegistrationKeys(HKEY root,
return true;
}
+void installer_setup::RemoveLegacyRegistryKeys() {
+ // We used to register Chrome to handle crx files, but this turned out
+ // to be not worth the hassle. Remove these old registry entries if
+ // they exist. See: http://codereview.chromium.org/210007
+
+#if defined(GOOGLE_CHROME_BUILD)
+const wchar_t kChromeExtProgId[] = L"ChromeExt";
+#else
+const wchar_t kChromeExtProgId[] = L"ChromiumExt";
+#endif
+
+ HKEY roots[] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
+ for (size_t i = 0; i < arraysize(roots); ++i) {
+ RegKey key(roots[i], L"", KEY_ALL_ACCESS);
+
+ std::wstring suffix;
+ if (roots[i] == HKEY_LOCAL_MACHINE &&
+ !ShellUtil::GetUserSpecificDefaultBrowserSuffix(&suffix))
+ suffix = L"";
+
+ // Delete Software\Classes\ChromeExt,
+ std::wstring ext_prog_id(ShellUtil::kRegClasses);
+ file_util::AppendToPath(&ext_prog_id, kChromeExtProgId);
+ ext_prog_id.append(suffix);
+ DeleteRegistryKey(key, ext_prog_id);
+
+ // Delete Software\Classes\.crx,
+ std::wstring ext_association(ShellUtil::kRegClasses);
+ ext_association.append(L"\\.");
+ ext_association.append(chrome::kExtensionFileExtension);
+ DeleteRegistryKey(key, ext_association);
+ }
+}
+
installer_util::InstallStatus installer_setup::UninstallChrome(
const std::wstring& exe_path, bool system_uninstall,
bool remove_all, bool force_uninstall,
diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h
index 1047f90..a2320ad 100644
--- a/chrome/installer/setup/uninstall.h
+++ b/chrome/installer/setup/uninstall.h
@@ -24,6 +24,11 @@ bool DeleteChromeRegistrationKeys(HKEY root,
const std::wstring& browser_entry_suffix,
installer_util::InstallStatus& exit_code);
+// Removes any legacy registry keys from earlier versions of Chrome that are no
+// longer needed. This is used during autoupdate since we don't do full
+// uninstalls/reinstalls to update.
+void RemoveLegacyRegistryKeys();
+
// This function uninstalls Chrome.
//
// exe_path: Path to the executable (setup.exe) as it will be copied
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index f21aeab..c4705a8 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -59,19 +59,6 @@ class RegistryEntry {
entries->push_front(new RegistryEntry(
chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));
- // Chrome Extension ProgId
- std::wstring ext_prog_id(ShellUtil::kRegClasses);
- file_util::AppendToPath(&ext_prog_id, ShellUtil::kChromeExtProgId);
- ext_prog_id.append(suffix);
- entries->push_front(new RegistryEntry(
- ext_prog_id, ShellUtil::kChromeExtProgIdDesc));
- entries->push_front(new RegistryEntry(
- ext_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
- std::wstring install_cmd =
- ShellUtil::GetChromeInstallExtensionCmd(chrome_exe);
- entries->push_front(new RegistryEntry(
- ext_prog_id + ShellUtil::kRegShellOpen, install_cmd));
-
return true;
}
@@ -127,11 +114,6 @@ class RegistryEntry {
capabilities + L"\\URLAssociations",
ShellUtil::kProtocolAssociations[i], html_prog_id));
}
- std::wstring ext_prog_id(ShellUtil::kChromeExtProgId);
- ext_prog_id.append(suffix);
- entries->push_front(new RegistryEntry(
- capabilities + L"\\FileAssociations",
- chrome::kExtensionFileExtension, ext_prog_id));
FilePath chrome_path(chrome_exe);
std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey);
@@ -158,14 +140,6 @@ class RegistryEntry {
entries->push_front(new RegistryEntry(ext_key, html_prog_id));
}
- // .crx file type extension.
- std::wstring ext_key(ShellUtil::kRegClasses);
- ext_key.append(L".");
- ext_key.append(chrome::kExtensionFileExtension);
- std::wstring ext_prog_id(ShellUtil::kChromeExtProgId);
- ext_prog_id.append(suffix);
- entries->push_front(new RegistryEntry(ext_key, ext_prog_id));
-
// Protocols associations.
std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
std::wstring chrome_icon = ShellUtil::GetChromeIcon(chrome_exe);
@@ -420,11 +394,9 @@ const wchar_t* ShellUtil::kAppPathsRegistryKey =
const wchar_t* ShellUtil::kAppPathsRegistryPathName = L"Path";
#if defined(GOOGLE_CHROME_BUILD)
-const wchar_t* ShellUtil::kChromeExtProgId = L"ChromeExt";
const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML";
const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML Document";
#else
-const wchar_t* ShellUtil::kChromeExtProgId = L"ChromiumExt";
const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromiumHTML";
const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML Document";
#endif
@@ -435,8 +407,6 @@ const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https",
NULL};
const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol";
-const wchar_t* ShellUtil::kChromeExtProgIdDesc = L"Chrome Extension Installer";
-
bool ShellUtil::AdminNeededForRegistryCleanup(const std::wstring& suffix) {
bool cleanup_needed = false;
std::list<RegistryEntry*> entries;
@@ -526,11 +496,6 @@ std::wstring ShellUtil::GetChromeIcon(const std::wstring& chrome_exe) {
return chrome_icon;
}
-std::wstring ShellUtil::GetChromeInstallExtensionCmd(
- const std::wstring& chrome_exe) {
- return L"\"" + chrome_exe + L"\" --install-extension=\"%1\"";
-}
-
std::wstring ShellUtil::GetChromeShellOpenCmd(const std::wstring& chrome_exe) {
return L"\"" + chrome_exe + L"\" -- \"%1\"";
}
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h
index 99f88b8..9514c1f 100644
--- a/chrome/installer/util/shell_util.h
+++ b/chrome/installer/util/shell_util.h
@@ -71,12 +71,6 @@ class ShellUtil {
// Registry value name that is needed for ChromeHTML ProgId
static const wchar_t* kRegUrlProtocol;
- // Name that we give to Chrome extension file association handler ProgId.
- static const wchar_t* kChromeExtProgId;
-
- // Description of Chrome file/URL association handler ProgId.
- static const wchar_t* kChromeExtProgIdDesc;
-
// Checks if we need Admin rights for registry cleanup by checking if any
// entry exists in HKLM.
static bool AdminNeededForRegistryCleanup(const std::wstring& suffix);
@@ -118,11 +112,6 @@ class ShellUtil {
// chrome_exe: the full path to chrome.exe
static std::wstring GetChromeShellOpenCmd(const std::wstring& chrome_exe);
- // This method returns the command to open .crx files using chrome in order
- // to install them as extensions. Similar to above method.
- static std::wstring GetChromeInstallExtensionCmd(
- const std::wstring& chrome_exe);
-
// Returns the localized name of Chrome shortcut. If |alternate| is true
// it returns a second localized text that is better suited for certain
// scenarios.