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