- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / setup / chrome_frame_ready_mode.cc
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/installer/setup/chrome_frame_ready_mode.h"
6
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "base/win/registry.h"
15 #include "chrome/installer/setup/install.h"
16 #include "chrome/installer/setup/install_worker.h"
17 #include "chrome/installer/util/browser_distribution.h"
18 #include "chrome/installer/util/google_update_constants.h"
19 #include "chrome/installer/util/helper.h"
20 #include "chrome/installer/util/install_util.h"
21 #include "chrome/installer/util/installation_state.h"
22 #include "chrome/installer/util/installer_state.h"
23 #include "chrome/installer/util/master_preferences.h"
24 #include "chrome/installer/util/master_preferences_constants.h"
25 #include "chrome/installer/util/product.h"
26 #include "chrome/installer/util/util_constants.h"
27 #include "chrome/installer/util/work_item.h"
28 #include "chrome/installer/util/work_item_list.h"
29
30 namespace installer {
31
32 // If Chrome is not multi-installed at the appropriate level, error.
33 // If Chrome Frame is already multi-installed at the appropriate level, noop.
34 // If Chrome Frame is single-installed at the appropriate level, error.
35 // Add uninstall for Chrome Frame.
36 // Update uninstall for Chrome.
37 // Update ChannelInfo for all multi-installed products.
38 // Remove ready-mode.
39 InstallStatus ChromeFrameReadyModeOptIn(
40     const InstallationState& machine_state,
41     const InstallerState& installer_state) {
42   VLOG(1) << "Opting into Chrome Frame";
43   InstallStatus status = INSTALL_REPAIRED;
44
45   // Make sure Chrome and Chrome Frame are both multi-installed.
46   const ProductState* chrome_state =
47       machine_state.GetProductState(installer_state.system_install(),
48                                     BrowserDistribution::CHROME_BROWSER);
49   const ProductState* cf_state =
50       machine_state.GetProductState(installer_state.system_install(),
51                                     BrowserDistribution::CHROME_FRAME);
52   if (chrome_state == NULL) {
53     LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome.";
54     return CHROME_NOT_INSTALLED;
55   }
56   if (!chrome_state->is_multi_install()) {
57     LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome.";
58     return NON_MULTI_INSTALLATION_EXISTS;
59   }
60   if (cf_state == NULL) {
61     LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome Frame.";
62     return CHROME_NOT_INSTALLED;
63   }
64   if (!cf_state->is_multi_install()) {
65     LOG(ERROR) << "Chrome Frame opt-in requires multi-install of Chrome Frame.";
66     return NON_MULTI_INSTALLATION_EXISTS;
67   }
68
69   // Create a new InstallerState to be used for this operation.
70   InstallerState opt_in_state(installer_state.level());
71
72   // Add the two products we're going to operate on.
73   const Product* chrome =
74       opt_in_state.AddProductFromState(BrowserDistribution::CHROME_BROWSER,
75                                        *chrome_state);
76   Product* cf =
77       opt_in_state.AddProductFromState(BrowserDistribution::CHROME_FRAME,
78                                        *cf_state);
79   // DCHECKs will fire in this case if it ever happens (it won't).
80   if (chrome == NULL || cf == NULL)
81     return READY_MODE_OPT_IN_FAILED;
82
83   // Turn off ready-mode on Chrome Frame, thereby making it fully installed.
84   if (!cf->SetOption(kOptionReadyMode, false)) {
85     LOG(WARNING)
86         << "Chrome Frame is already fully installed; opting-in nonetheless.";
87   }
88
89   // Update Chrome's uninstallation commands to only uninstall Chrome, and add
90   // an entry to the Add/Remove Programs dialog for GCF.
91   DCHECK(cf->ShouldCreateUninstallEntry() || opt_in_state.is_msi());
92
93   scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
94
95   // This creates the uninstallation entry for GCF.
96   AddUninstallShortcutWorkItems(opt_in_state, cf_state->GetSetupPath(),
97       cf_state->version(), *cf, item_list.get());
98   // This updates the Chrome uninstallation entries.
99   AddUninstallShortcutWorkItems(opt_in_state, chrome_state->GetSetupPath(),
100       chrome_state->version(), *chrome, item_list.get());
101
102   // Add a work item to delete the ChromeFrameReadyMode registry value.
103   HKEY root = opt_in_state.root_key();
104   item_list->AddDeleteRegValueWorkItem(root,
105       opt_in_state.multi_package_binaries_distribution()->GetStateKey(),
106       kChromeFrameReadyModeField);
107
108   // Update the Google Update channel ("ap") value.
109   AddGoogleUpdateWorkItems(machine_state, opt_in_state, item_list.get());
110
111   // Delete the command elevation registry keys
112   std::wstring version_key(cf->distribution()->GetVersionKey());
113   item_list->AddDeleteRegValueWorkItem(
114       root, version_key, google_update::kRegCFTempOptOutCmdField);
115   item_list->AddDeleteRegValueWorkItem(
116       root, version_key, google_update::kRegCFEndTempOptOutCmdField);
117   item_list->AddDeleteRegValueWorkItem(root, version_key,
118                                        google_update::kRegCFOptOutCmdField);
119   item_list->AddDeleteRegValueWorkItem(root, version_key,
120                                        google_update::kRegCFOptInCmdField);
121
122   if (!item_list->Do()) {
123     LOG(ERROR) << "Failed to opt into GCF";
124     item_list->Rollback();
125     status = READY_MODE_OPT_IN_FAILED;
126   }
127
128   return status;
129 }
130
131 const wchar_t kPostPlatformUAKey[] =
132     L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\"
133     L"User Agent\\Post Platform";
134 const wchar_t kChromeFramePrefix[] = L"chromeframe/";
135
136 InstallStatus ChromeFrameReadyModeTempOptOut(
137     const InstallationState& machine_state,
138     const InstallerState& installer_state) {
139   VLOG(1) << "Temporarily opting out of Chrome Frame";
140   InstallStatus status = INSTALL_REPAIRED;
141
142   // Make sure Chrome Frame is multi-installed.
143   const ProductState* cf_state =
144       machine_state.GetProductState(installer_state.system_install(),
145                                     BrowserDistribution::CHROME_FRAME);
146   if (cf_state == NULL) {
147     LOG(ERROR)
148         << "Chrome Frame temp opt-out requires multi-install of Chrome Frame.";
149     return CHROME_NOT_INSTALLED;
150   }
151   if (!cf_state->is_multi_install()) {
152     LOG(ERROR)
153         << "Chrome Frame temp opt-out requires multi-install of Chrome Frame.";
154     return NON_MULTI_INSTALLATION_EXISTS;
155   }
156
157   scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
158
159   HKEY root = installer_state.root_key();
160
161   // Add a work item to delete the ChromeFrame user agent registry value.
162   base::win::RegistryValueIterator values(root, kPostPlatformUAKey);
163   while (values.Valid()) {
164     const wchar_t* name = values.Name();
165     if (StartsWith(name, kChromeFramePrefix, true)) {
166       item_list->AddDeleteRegValueWorkItem(root, kPostPlatformUAKey, name);
167     }
168     ++values;
169   }
170
171   // Add a work item to update the Ready Mode state flag
172   int64 timestamp = base::Time::Now().ToInternalValue();
173   BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
174       BrowserDistribution::CHROME_BINARIES);
175   item_list->AddSetRegValueWorkItem(root, dist->GetStateKey(),
176                                     kChromeFrameReadyModeField, timestamp,
177                                     true);
178
179   if (!item_list->Do()) {
180     LOG(ERROR) << "Failed to temporarily opt out of GCF";
181     item_list->Rollback();
182     status = READY_MODE_TEMP_OPT_OUT_FAILED;
183   }
184
185   return status;
186 }
187
188 InstallStatus ChromeFrameReadyModeEndTempOptOut(
189     const InstallationState& machine_state,
190     const InstallerState& installer_state) {
191   VLOG(1) << "Ending temporary opt-out of Chrome Frame";
192   InstallStatus status = INSTALL_REPAIRED;
193
194   // Make sure Chrome Frame is multi-installed.
195   const ProductState* cf_state =
196       machine_state.GetProductState(installer_state.system_install(),
197                                     BrowserDistribution::CHROME_FRAME);
198   if (cf_state == NULL) {
199     LOG(ERROR)
200         << "Chrome Frame temp opt-out requires multi-install of Chrome Frame.";
201     return CHROME_NOT_INSTALLED;
202   }
203   if (!cf_state->is_multi_install()) {
204     LOG(ERROR)
205         << "Chrome Frame temp opt-out requires multi-install of Chrome Frame.";
206     return NON_MULTI_INSTALLATION_EXISTS;
207   }
208
209   // Replace the ChromeFrame user agent string in the registry, modify the
210   // ReadyMode state flag.
211   const Version& installed_version = cf_state->version();
212
213   scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
214
215   HKEY root = installer_state.root_key();
216
217   std::wstring chrome_frame_ua_value_name(kChromeFramePrefix);
218   chrome_frame_ua_value_name += ASCIIToWide(installed_version.GetString());
219
220   // Store the Chrome Frame user agent string
221   item_list->AddSetRegValueWorkItem(root, kPostPlatformUAKey,
222                                     chrome_frame_ua_value_name, L"", true);
223   // Add a work item to update the Ready Mode state flag
224   BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
225       BrowserDistribution::CHROME_BINARIES);
226   item_list->AddSetRegValueWorkItem(root, dist->GetStateKey(),
227                                     kChromeFrameReadyModeField,
228                                     static_cast<int64>(1), true);
229
230   if (!item_list->Do()) {
231     LOG(ERROR) << "Failed to end temporary opt out of GCF";
232     item_list->Rollback();
233     status = READY_MODE_END_TEMP_OPT_OUT_FAILED;
234   }
235
236   return status;
237 }
238
239 }  // namespace installer