Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / webstore_private / webstore_private_api.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h"
6
7 #include "base/bind_helpers.h"
8 #include "base/command_line.h"
9 #include "base/lazy_instance.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/about_flags.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/extensions/crx_installer.h"
20 #include "chrome/browser/extensions/extension_function_dispatcher.h"
21 #include "chrome/browser/extensions/extension_service.h"
22 #include "chrome/browser/extensions/extension_system.h"
23 #include "chrome/browser/extensions/extension_util.h"
24 #include "chrome/browser/extensions/webstore_installer.h"
25 #include "chrome/browser/gpu/gpu_feature_checker.h"
26 #include "chrome/browser/profiles/profile_manager.h"
27 #include "chrome/browser/signin/signin_manager.h"
28 #include "chrome/browser/signin/signin_manager_factory.h"
29 #include "chrome/browser/sync/profile_sync_service.h"
30 #include "chrome/browser/sync/profile_sync_service_factory.h"
31 #include "chrome/browser/ui/app_list/app_list_service.h"
32 #include "chrome/browser/ui/app_list/app_list_util.h"
33 #include "chrome/browser/ui/browser.h"
34 #include "chrome/common/extensions/extension_constants.h"
35 #include "chrome/common/extensions/extension_l10n_util.h"
36 #include "chrome/common/pref_names.h"
37 #include "content/public/browser/gpu_data_manager.h"
38 #include "content/public/browser/notification_details.h"
39 #include "content/public/browser/notification_source.h"
40 #include "content/public/browser/web_contents.h"
41 #include "extensions/browser/extension_prefs.h"
42 #include "extensions/common/error_utils.h"
43 #include "extensions/common/extension.h"
44 #include "grit/chromium_strings.h"
45 #include "grit/generated_resources.h"
46 #include "ui/base/l10n/l10n_util.h"
47
48 using content::GpuDataManager;
49
50 namespace extensions {
51
52 namespace BeginInstallWithManifest3 =
53     api::webstore_private::BeginInstallWithManifest3;
54 namespace CompleteInstall = api::webstore_private::CompleteInstall;
55 namespace GetBrowserLogin = api::webstore_private::GetBrowserLogin;
56 namespace GetIsLauncherEnabled = api::webstore_private::GetIsLauncherEnabled;
57 namespace GetStoreLogin = api::webstore_private::GetStoreLogin;
58 namespace GetWebGLStatus = api::webstore_private::GetWebGLStatus;
59 namespace InstallBundle = api::webstore_private::InstallBundle;
60 namespace IsInIncognitoMode = api::webstore_private::IsInIncognitoMode;
61 namespace SetStoreLogin = api::webstore_private::SetStoreLogin;
62
63 namespace {
64
65 // Holds the Approvals between the time we prompt and start the installs.
66 class PendingApprovals {
67  public:
68   PendingApprovals();
69   ~PendingApprovals();
70
71   void PushApproval(scoped_ptr<WebstoreInstaller::Approval> approval);
72   scoped_ptr<WebstoreInstaller::Approval> PopApproval(
73       Profile* profile, const std::string& id);
74  private:
75   typedef ScopedVector<WebstoreInstaller::Approval> ApprovalList;
76
77   ApprovalList approvals_;
78
79   DISALLOW_COPY_AND_ASSIGN(PendingApprovals);
80 };
81
82 PendingApprovals::PendingApprovals() {}
83 PendingApprovals::~PendingApprovals() {}
84
85 void PendingApprovals::PushApproval(
86     scoped_ptr<WebstoreInstaller::Approval> approval) {
87   approvals_.push_back(approval.release());
88 }
89
90 scoped_ptr<WebstoreInstaller::Approval> PendingApprovals::PopApproval(
91     Profile* profile, const std::string& id) {
92   for (size_t i = 0; i < approvals_.size(); ++i) {
93     WebstoreInstaller::Approval* approval = approvals_[i];
94     if (approval->extension_id == id &&
95         profile->IsSameProfile(approval->profile)) {
96       approvals_.weak_erase(approvals_.begin() + i);
97       return scoped_ptr<WebstoreInstaller::Approval>(approval);
98     }
99   }
100   return scoped_ptr<WebstoreInstaller::Approval>();
101 }
102
103 // Uniquely holds the profile and extension id of an install between the time we
104 // prompt and complete the installs.
105 class PendingInstalls {
106  public:
107   PendingInstalls();
108   ~PendingInstalls();
109
110   bool InsertInstall(Profile* profile, const std::string& id);
111   void EraseInstall(Profile* profile, const std::string& id);
112  private:
113   typedef std::pair<Profile*, std::string> ProfileAndExtensionId;
114   typedef std::vector<ProfileAndExtensionId> InstallList;
115
116   InstallList::iterator FindInstall(Profile* profile, const std::string& id);
117
118   InstallList installs_;
119
120   DISALLOW_COPY_AND_ASSIGN(PendingInstalls);
121 };
122
123 PendingInstalls::PendingInstalls() {}
124 PendingInstalls::~PendingInstalls() {}
125
126 // Returns true and inserts the profile/id pair if it is not present. Otherwise
127 // returns false.
128 bool PendingInstalls::InsertInstall(Profile* profile, const std::string& id) {
129   if (FindInstall(profile, id) != installs_.end())
130     return false;
131   installs_.push_back(make_pair(profile, id));
132   return true;
133 }
134
135 // Removes the given profile/id pair.
136 void PendingInstalls::EraseInstall(Profile* profile, const std::string& id) {
137   InstallList::iterator it = FindInstall(profile, id);
138   if (it != installs_.end())
139     installs_.erase(it);
140 }
141
142 PendingInstalls::InstallList::iterator PendingInstalls::FindInstall(
143     Profile* profile,
144     const std::string& id) {
145   for (size_t i = 0; i < installs_.size(); ++i) {
146     ProfileAndExtensionId install = installs_[i];
147     if (install.second == id && profile->IsSameProfile(install.first))
148       return (installs_.begin() + i);
149   }
150   return installs_.end();
151 }
152
153 static base::LazyInstance<PendingApprovals> g_pending_approvals =
154     LAZY_INSTANCE_INITIALIZER;
155 static base::LazyInstance<PendingInstalls> g_pending_installs =
156     LAZY_INSTANCE_INITIALIZER;
157
158 // A preference set by the web store to indicate login information for
159 // purchased apps.
160 const char kWebstoreLogin[] = "extensions.webstore_login";
161 const char kAlreadyInstalledError[] = "This item is already installed";
162 const char kCannotSpecifyIconDataAndUrlError[] =
163     "You cannot specify both icon data and an icon url";
164 const char kInvalidIconUrlError[] = "Invalid icon url";
165 const char kInvalidIdError[] = "Invalid id";
166 const char kInvalidManifestError[] = "Invalid manifest";
167 const char kNoPreviousBeginInstallWithManifestError[] =
168     "* does not match a previous call to beginInstallWithManifest3";
169 const char kUserCancelledError[] = "User cancelled install";
170
171 WebstoreInstaller::Delegate* test_webstore_installer_delegate = NULL;
172
173 // We allow the web store to set a string containing login information when a
174 // purchase is made, so that when a user logs into sync with a different
175 // account we can recognize the situation. The Get function returns the login if
176 // there was previously stored data, or an empty string otherwise. The Set will
177 // overwrite any previous login.
178 std::string GetWebstoreLogin(Profile* profile) {
179   if (profile->GetPrefs()->HasPrefPath(kWebstoreLogin))
180     return profile->GetPrefs()->GetString(kWebstoreLogin);
181   return std::string();
182 }
183
184 void SetWebstoreLogin(Profile* profile, const std::string& login) {
185   profile->GetPrefs()->SetString(kWebstoreLogin, login);
186 }
187
188 void RecordWebstoreExtensionInstallResult(bool success) {
189   UMA_HISTOGRAM_BOOLEAN("Webstore.ExtensionInstallResult", success);
190 }
191
192 }  // namespace
193
194 // static
195 void WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(
196     WebstoreInstaller::Delegate* delegate) {
197   test_webstore_installer_delegate = delegate;
198 }
199
200 // static
201 scoped_ptr<WebstoreInstaller::Approval>
202 WebstorePrivateApi::PopApprovalForTesting(
203     Profile* profile, const std::string& extension_id) {
204   return g_pending_approvals.Get().PopApproval(profile, extension_id);
205 }
206
207 WebstorePrivateInstallBundleFunction::WebstorePrivateInstallBundleFunction() {}
208 WebstorePrivateInstallBundleFunction::~WebstorePrivateInstallBundleFunction() {}
209
210 bool WebstorePrivateInstallBundleFunction::RunImpl() {
211   scoped_ptr<InstallBundle::Params> params(
212       InstallBundle::Params::Create(*args_));
213   EXTENSION_FUNCTION_VALIDATE(params);
214
215   BundleInstaller::ItemList items;
216   if (!ReadBundleInfo(*params, &items))
217     return false;
218
219   bundle_ = new BundleInstaller(GetCurrentBrowser(), items);
220
221   AddRef();  // Balanced in OnBundleInstallCompleted / OnBundleInstallCanceled.
222
223   bundle_->PromptForApproval(this);
224   return true;
225 }
226
227 bool WebstorePrivateInstallBundleFunction::
228     ReadBundleInfo(const InstallBundle::Params& params,
229     BundleInstaller::ItemList* items) {
230   for (size_t i = 0; i < params.details.size(); ++i) {
231     BundleInstaller::Item item;
232     item.id = params.details[i]->id;
233     item.manifest = params.details[i]->manifest;
234     item.localized_name = params.details[i]->localized_name;
235     items->push_back(item);
236   }
237
238   return true;
239 }
240
241 void WebstorePrivateInstallBundleFunction::OnBundleInstallApproved() {
242   bundle_->CompleteInstall(
243       &(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()),
244       this);
245 }
246
247 void WebstorePrivateInstallBundleFunction::OnBundleInstallCanceled(
248     bool user_initiated) {
249   if (user_initiated)
250     error_ = "user_canceled";
251   else
252     error_ = "unknown_error";
253
254   SendResponse(false);
255
256   Release();  // Balanced in RunImpl().
257 }
258
259 void WebstorePrivateInstallBundleFunction::OnBundleInstallCompleted() {
260   SendResponse(true);
261
262   Release();  // Balanced in RunImpl().
263 }
264
265 WebstorePrivateBeginInstallWithManifest3Function::
266     WebstorePrivateBeginInstallWithManifest3Function() {}
267
268 WebstorePrivateBeginInstallWithManifest3Function::
269     ~WebstorePrivateBeginInstallWithManifest3Function() {}
270
271 bool WebstorePrivateBeginInstallWithManifest3Function::RunImpl() {
272   params_ = BeginInstallWithManifest3::Params::Create(*args_);
273   EXTENSION_FUNCTION_VALIDATE(params_);
274
275   if (!extensions::Extension::IdIsValid(params_->details.id)) {
276     SetResultCode(INVALID_ID);
277     error_ = kInvalidIdError;
278     return false;
279   }
280
281   if (params_->details.icon_data && params_->details.icon_url) {
282     SetResultCode(ICON_ERROR);
283     error_ = kCannotSpecifyIconDataAndUrlError;
284     return false;
285   }
286
287   GURL icon_url;
288   if (params_->details.icon_url) {
289     std::string tmp_url;
290     icon_url = source_url().Resolve(*params_->details.icon_url);
291     if (!icon_url.is_valid()) {
292       SetResultCode(INVALID_ICON_URL);
293       error_ = kInvalidIconUrlError;
294       return false;
295     }
296   }
297
298   std::string icon_data = params_->details.icon_data ?
299       *params_->details.icon_data : std::string();
300
301   Profile* profile = GetProfile();
302   if (util::IsExtensionInstalledPermanently(params_->details.id, profile) ||
303       !g_pending_installs.Get().InsertInstall(profile, params_->details.id)) {
304     SetResultCode(ALREADY_INSTALLED);
305     error_ = kAlreadyInstalledError;
306     return false;
307   }
308
309   net::URLRequestContextGetter* context_getter = NULL;
310   if (!icon_url.is_empty())
311     context_getter = GetProfile()->GetRequestContext();
312
313   scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
314       this, params_->details.id, params_->details.manifest, icon_data, icon_url,
315           context_getter);
316
317   // The helper will call us back via OnWebstoreParseSuccess or
318   // OnWebstoreParseFailure.
319   helper->Start();
320
321   // Matched with a Release in OnWebstoreParseSuccess/OnWebstoreParseFailure.
322   AddRef();
323
324   // The response is sent asynchronously in OnWebstoreParseSuccess/
325   // OnWebstoreParseFailure.
326   return true;
327 }
328
329 const char* WebstorePrivateBeginInstallWithManifest3Function::
330     ResultCodeToString(ResultCode code) {
331   switch (code) {
332     case ERROR_NONE:
333       return "";
334     case UNKNOWN_ERROR:
335       return "unknown_error";
336     case USER_CANCELLED:
337       return "user_cancelled";
338     case MANIFEST_ERROR:
339       return "manifest_error";
340     case ICON_ERROR:
341       return "icon_error";
342     case INVALID_ID:
343       return "invalid_id";
344     case PERMISSION_DENIED:
345       return "permission_denied";
346     case INVALID_ICON_URL:
347       return "invalid_icon_url";
348     case SIGNIN_FAILED:
349       return "signin_failed";
350     case ALREADY_INSTALLED:
351       return "already_installed";
352   }
353   NOTREACHED();
354   return "";
355 }
356
357 void WebstorePrivateBeginInstallWithManifest3Function::SetResultCode(
358     ResultCode code) {
359   results_ = BeginInstallWithManifest3::Results::Create(
360       ResultCodeToString(code));
361 }
362
363 void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
364     const std::string& id,
365     const SkBitmap& icon,
366     base::DictionaryValue* parsed_manifest) {
367   CHECK_EQ(params_->details.id, id);
368   CHECK(parsed_manifest);
369   icon_ = icon;
370   parsed_manifest_.reset(parsed_manifest);
371
372   std::string localized_name = params_->details.localized_name ?
373       *params_->details.localized_name : std::string();
374
375   std::string error;
376   dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
377       parsed_manifest_.get(),
378       Extension::FROM_WEBSTORE,
379       id,
380       localized_name,
381       std::string(),
382       &error);
383
384   if (!dummy_extension_.get()) {
385     OnWebstoreParseFailure(params_->details.id,
386                            WebstoreInstallHelper::Delegate::MANIFEST_ERROR,
387                            kInvalidManifestError);
388     return;
389   }
390
391   SigninManagerBase* signin_manager =
392       SigninManagerFactory::GetForProfile(GetProfile());
393   if (dummy_extension_->is_platform_app() &&
394       signin_manager &&
395       signin_manager->GetAuthenticatedUsername().empty() &&
396       signin_manager->AuthInProgress()) {
397     signin_tracker_.reset(new SigninTracker(GetProfile(), this));
398     return;
399   }
400
401   SigninCompletedOrNotNeeded();
402 }
403
404 void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseFailure(
405     const std::string& id,
406     WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code,
407     const std::string& error_message) {
408   CHECK_EQ(params_->details.id, id);
409
410   // Map from WebstoreInstallHelper's result codes to ours.
411   switch (result_code) {
412     case WebstoreInstallHelper::Delegate::UNKNOWN_ERROR:
413       SetResultCode(UNKNOWN_ERROR);
414       break;
415     case WebstoreInstallHelper::Delegate::ICON_ERROR:
416       SetResultCode(ICON_ERROR);
417       break;
418     case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
419       SetResultCode(MANIFEST_ERROR);
420       break;
421     default:
422       CHECK(false);
423   }
424   error_ = error_message;
425   g_pending_installs.Get().EraseInstall(GetProfile(), id);
426   SendResponse(false);
427
428   // Matches the AddRef in RunImpl().
429   Release();
430 }
431
432 void WebstorePrivateBeginInstallWithManifest3Function::SigninFailed(
433     const GoogleServiceAuthError& error) {
434   signin_tracker_.reset();
435
436   SetResultCode(SIGNIN_FAILED);
437   error_ = error.ToString();
438   g_pending_installs.Get().EraseInstall(GetProfile(), params_->details.id);
439   SendResponse(false);
440
441   // Matches the AddRef in RunImpl().
442   Release();
443 }
444
445 void WebstorePrivateBeginInstallWithManifest3Function::SigninSuccess() {
446   signin_tracker_.reset();
447
448   SigninCompletedOrNotNeeded();
449 }
450
451 void WebstorePrivateBeginInstallWithManifest3Function::MergeSessionComplete(
452     const GoogleServiceAuthError& error) {
453   // TODO(rogerta): once the embeded inline flow is enabled, the code in
454   // WebstorePrivateBeginInstallWithManifest3Function::SigninSuccess()
455   // should move to here.
456 }
457
458 void WebstorePrivateBeginInstallWithManifest3Function::
459     SigninCompletedOrNotNeeded() {
460   content::WebContents* web_contents = GetAssociatedWebContents();
461   if (!web_contents)  // The browser window has gone away.
462     return;
463   install_prompt_.reset(new ExtensionInstallPrompt(web_contents));
464   install_prompt_->ConfirmWebstoreInstall(
465       this,
466       dummy_extension_.get(),
467       &icon_,
468       ExtensionInstallPrompt::GetDefaultShowDialogCallback());
469   // Control flow finishes up in InstallUIProceed or InstallUIAbort.
470 }
471
472 void WebstorePrivateBeginInstallWithManifest3Function::InstallUIProceed() {
473   // This gets cleared in CrxInstaller::ConfirmInstall(). TODO(asargent) - in
474   // the future we may also want to add time-based expiration, where a whitelist
475   // entry is only valid for some number of minutes.
476   scoped_ptr<WebstoreInstaller::Approval> approval(
477       WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
478           GetProfile(), params_->details.id, parsed_manifest_.Pass(), false));
479   approval->use_app_installed_bubble = params_->details.app_install_bubble;
480   approval->enable_launcher = params_->details.enable_launcher;
481   // If we are enabling the launcher, we should not show the app list in order
482   // to train the user to open it themselves at least once.
483   approval->skip_post_install_ui = params_->details.enable_launcher;
484   approval->dummy_extension = dummy_extension_;
485   approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
486   g_pending_approvals.Get().PushApproval(approval.Pass());
487
488   SetResultCode(ERROR_NONE);
489   SendResponse(true);
490
491   // The Permissions_Install histogram is recorded from the ExtensionService
492   // for all extension installs, so we only need to record the web store
493   // specific histogram here.
494   ExtensionService::RecordPermissionMessagesHistogram(
495       dummy_extension_.get(), "Extensions.Permissions_WebStoreInstall");
496
497   // Matches the AddRef in RunImpl().
498   Release();
499 }
500
501 void WebstorePrivateBeginInstallWithManifest3Function::InstallUIAbort(
502     bool user_initiated) {
503   error_ = kUserCancelledError;
504   SetResultCode(USER_CANCELLED);
505   g_pending_installs.Get().EraseInstall(GetProfile(), params_->details.id);
506   SendResponse(false);
507
508   // The web store install histograms are a subset of the install histograms.
509   // We need to record both histograms here since CrxInstaller::InstallUIAbort
510   // is never called for web store install cancellations.
511   std::string histogram_name = user_initiated ?
512       "Extensions.Permissions_WebStoreInstallCancel" :
513       "Extensions.Permissions_WebStoreInstallAbort";
514   ExtensionService::RecordPermissionMessagesHistogram(dummy_extension_.get(),
515                                                       histogram_name.c_str());
516
517   histogram_name = user_initiated ?
518       "Extensions.Permissions_InstallCancel" :
519       "Extensions.Permissions_InstallAbort";
520   ExtensionService::RecordPermissionMessagesHistogram(dummy_extension_.get(),
521                                                       histogram_name.c_str());
522
523   // Matches the AddRef in RunImpl().
524   Release();
525 }
526
527 WebstorePrivateCompleteInstallFunction::
528     WebstorePrivateCompleteInstallFunction() {}
529
530 WebstorePrivateCompleteInstallFunction::
531     ~WebstorePrivateCompleteInstallFunction() {}
532
533 bool WebstorePrivateCompleteInstallFunction::RunImpl() {
534   scoped_ptr<CompleteInstall::Params> params(
535       CompleteInstall::Params::Create(*args_));
536   EXTENSION_FUNCTION_VALIDATE(params);
537   if (!extensions::Extension::IdIsValid(params->expected_id)) {
538     error_ = kInvalidIdError;
539     return false;
540   }
541
542   approval_ = g_pending_approvals.Get()
543                   .PopApproval(GetProfile(), params->expected_id)
544                   .Pass();
545   if (!approval_) {
546     error_ = ErrorUtils::FormatErrorMessage(
547         kNoPreviousBeginInstallWithManifestError, params->expected_id);
548     return false;
549   }
550
551   // Balanced in OnExtensionInstallSuccess() or OnExtensionInstallFailure().
552   AddRef();
553   AppListService* app_list_service =
554       AppListService::Get(GetCurrentBrowser()->host_desktop_type());
555
556   if (approval_->enable_launcher)
557     app_list_service->EnableAppList(GetProfile());
558
559   if (IsAppLauncherEnabled() && approval_->manifest->is_app()) {
560     // Show the app list to show download is progressing. Don't show the app
561     // list on first app install so users can be trained to open it themselves.
562     if (approval_->enable_launcher)
563       app_list_service->CreateForProfile(GetProfile());
564     else
565       app_list_service->ShowForProfile(GetProfile());
566   }
567
568   // The extension will install through the normal extension install flow, but
569   // the whitelist entry will bypass the normal permissions install dialog.
570   scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
571       GetProfile(),
572       this,
573       &(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()),
574       params->expected_id,
575       approval_.Pass(),
576       WebstoreInstaller::INSTALL_SOURCE_OTHER);
577   installer->Start();
578
579   return true;
580 }
581
582 void WebstorePrivateCompleteInstallFunction::OnExtensionInstallSuccess(
583     const std::string& id) {
584   if (test_webstore_installer_delegate)
585     test_webstore_installer_delegate->OnExtensionInstallSuccess(id);
586
587   VLOG(1) << "Install success, sending response";
588   g_pending_installs.Get().EraseInstall(GetProfile(), id);
589   SendResponse(true);
590
591   RecordWebstoreExtensionInstallResult(true);
592
593   // Matches the AddRef in RunImpl().
594   Release();
595 }
596
597 void WebstorePrivateCompleteInstallFunction::OnExtensionInstallFailure(
598     const std::string& id,
599     const std::string& error,
600     WebstoreInstaller::FailureReason reason) {
601   if (test_webstore_installer_delegate) {
602     test_webstore_installer_delegate->OnExtensionInstallFailure(
603         id, error, reason);
604   }
605
606   error_ = error;
607   VLOG(1) << "Install failed, sending response";
608   g_pending_installs.Get().EraseInstall(GetProfile(), id);
609   SendResponse(false);
610
611   RecordWebstoreExtensionInstallResult(false);
612
613   // Matches the AddRef in RunImpl().
614   Release();
615 }
616
617 WebstorePrivateEnableAppLauncherFunction::
618     WebstorePrivateEnableAppLauncherFunction() {}
619
620 WebstorePrivateEnableAppLauncherFunction::
621     ~WebstorePrivateEnableAppLauncherFunction() {}
622
623 bool WebstorePrivateEnableAppLauncherFunction::RunImpl() {
624   AppListService::Get(GetCurrentBrowser()->host_desktop_type())->
625       EnableAppList(GetProfile());
626   return true;
627 }
628
629 bool WebstorePrivateGetBrowserLoginFunction::RunImpl() {
630   GetBrowserLogin::Results::Info info;
631   info.login = GetProfile()->GetOriginalProfile()->GetPrefs()->GetString(
632       prefs::kGoogleServicesUsername);
633   results_ = GetBrowserLogin::Results::Create(info);
634   return true;
635 }
636
637 bool WebstorePrivateGetStoreLoginFunction::RunImpl() {
638   results_ = GetStoreLogin::Results::Create(GetWebstoreLogin(GetProfile()));
639   return true;
640 }
641
642 bool WebstorePrivateSetStoreLoginFunction::RunImpl() {
643   scoped_ptr<SetStoreLogin::Params> params(
644       SetStoreLogin::Params::Create(*args_));
645   EXTENSION_FUNCTION_VALIDATE(params);
646   SetWebstoreLogin(GetProfile(), params->login);
647   return true;
648 }
649
650 WebstorePrivateGetWebGLStatusFunction::WebstorePrivateGetWebGLStatusFunction() {
651   feature_checker_ = new GPUFeatureChecker(
652       gpu::GPU_FEATURE_TYPE_WEBGL,
653       base::Bind(&WebstorePrivateGetWebGLStatusFunction::OnFeatureCheck,
654           base::Unretained(this)));
655 }
656
657 WebstorePrivateGetWebGLStatusFunction::
658     ~WebstorePrivateGetWebGLStatusFunction() {}
659
660 void WebstorePrivateGetWebGLStatusFunction::CreateResult(bool webgl_allowed) {
661   results_ = GetWebGLStatus::Results::Create(GetWebGLStatus::Results::
662       ParseWebgl_status(webgl_allowed ? "webgl_allowed" : "webgl_blocked"));
663 }
664
665 bool WebstorePrivateGetWebGLStatusFunction::RunImpl() {
666   feature_checker_->CheckGPUFeatureAvailability();
667   return true;
668 }
669
670 void WebstorePrivateGetWebGLStatusFunction::
671     OnFeatureCheck(bool feature_allowed) {
672   CreateResult(feature_allowed);
673   SendResponse(true);
674 }
675
676 bool WebstorePrivateGetIsLauncherEnabledFunction::RunImpl() {
677   results_ = GetIsLauncherEnabled::Results::Create(IsAppLauncherEnabled());
678   return true;
679 }
680
681 bool WebstorePrivateIsInIncognitoModeFunction::RunImpl() {
682   results_ = IsInIncognitoMode::Results::Create(
683       GetProfile() != GetProfile()->GetOriginalProfile());
684   return true;
685 }
686
687 }  // namespace extensions