- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / developer_private / developer_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/developer_private/developer_private_api.h"
6
7 #include "apps/app_load_service.h"
8 #include "apps/app_restore_service.h"
9 #include "apps/saved_files_service.h"
10 #include "apps/shell_window.h"
11 #include "apps/shell_window_registry.h"
12 #include "base/base64.h"
13 #include "base/command_line.h"
14 #include "base/file_util.h"
15 #include "base/files/file_enumerator.h"
16 #include "base/i18n/file_util_icu.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/values.h"
20 #include "chrome/browser/chrome_notification_types.h"
21 #include "chrome/browser/devtools/devtools_window.h"
22 #include "chrome/browser/extensions/api/developer_private/developer_private_api_factory.h"
23 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
24 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
25 #include "chrome/browser/extensions/devtools_util.h"
26 #include "chrome/browser/extensions/extension_disabled_ui.h"
27 #include "chrome/browser/extensions/extension_error_reporter.h"
28 #include "chrome/browser/extensions/extension_service.h"
29 #include "chrome/browser/extensions/extension_system.h"
30 #include "chrome/browser/extensions/extension_util.h"
31 #include "chrome/browser/extensions/management_policy.h"
32 #include "chrome/browser/extensions/unpacked_installer.h"
33 #include "chrome/browser/extensions/updater/extension_updater.h"
34 #include "chrome/browser/platform_util.h"
35 #include "chrome/browser/profiles/profile.h"
36 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
37 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
38 #include "chrome/browser/ui/chrome_select_file_policy.h"
39 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
40 #include "chrome/common/extensions/api/developer_private.h"
41 #include "chrome/common/extensions/background_info.h"
42 #include "chrome/common/extensions/incognito_handler.h"
43 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
44 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
45 #include "chrome/common/extensions/manifest_handlers/offline_enabled_info.h"
46 #include "chrome/common/extensions/manifest_url_handler.h"
47 #include "chrome/common/url_constants.h"
48 #include "content/public/browser/browser_thread.h"
49 #include "content/public/browser/notification_service.h"
50 #include "content/public/browser/render_process_host.h"
51 #include "content/public/browser/render_view_host.h"
52 #include "content/public/browser/site_instance.h"
53 #include "content/public/browser/storage_partition.h"
54 #include "content/public/browser/web_contents.h"
55 #include "extensions/browser/view_type_utils.h"
56 #include "extensions/common/constants.h"
57 #include "extensions/common/extension_resource.h"
58 #include "extensions/common/install_warning.h"
59 #include "extensions/common/switches.h"
60 #include "grit/chromium_strings.h"
61 #include "grit/generated_resources.h"
62 #include "grit/theme_resources.h"
63 #include "net/base/net_util.h"
64 #include "ui/base/l10n/l10n_util.h"
65 #include "ui/base/resource/resource_bundle.h"
66 #include "ui/base/webui/web_ui_util.h"
67 #include "webkit/browser/fileapi/file_system_context.h"
68 #include "webkit/browser/fileapi/file_system_operation.h"
69 #include "webkit/browser/fileapi/file_system_operation_runner.h"
70 #include "webkit/common/blob/shareable_file_reference.h"
71
72 using apps::ShellWindow;
73 using apps::ShellWindowRegistry;
74 using content::RenderViewHost;
75
76 namespace extensions {
77
78 namespace developer_private = api::developer_private;
79
80 namespace {
81
82 const base::FilePath::CharType kUnpackedAppsFolder[]
83     = FILE_PATH_LITERAL("apps_target");
84
85 ExtensionUpdater* GetExtensionUpdater(Profile* profile) {
86     return profile->GetExtensionService()->updater();
87 }
88
89 GURL GetImageURLFromData(std::string contents) {
90   std::string contents_base64;
91   if (!base::Base64Encode(contents, &contents_base64))
92     return GURL();
93
94   // TODO(dvh): make use of chrome::kDataScheme. Filed as crbug/297301.
95   const char kDataURLPrefix[] = "data:image;base64,";
96   return GURL(kDataURLPrefix + contents_base64);
97 }
98
99 GURL GetDefaultImageURL(developer_private::ItemType type) {
100   int icon_resource_id;
101   switch (type) {
102     case developer::ITEM_TYPE_LEGACY_PACKAGED_APP:
103     case developer::ITEM_TYPE_HOSTED_APP:
104     case developer::ITEM_TYPE_PACKAGED_APP:
105       icon_resource_id = IDR_APP_DEFAULT_ICON;
106       break;
107     default:
108       icon_resource_id = IDR_EXTENSION_DEFAULT_ICON;
109       break;
110   }
111
112   return GetImageURLFromData(
113       ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
114           icon_resource_id, ui::SCALE_FACTOR_100P).as_string());
115 }
116
117 // TODO(dvh): This code should be refactored and moved to
118 // extensions::ImageLoader. Also a resize should be performed to avoid
119 // potential huge URLs: crbug/297298.
120 GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) {
121   std::string contents;
122   if (path.empty() || !base::ReadFileToString(path, &contents))
123     return GetDefaultImageURL(type);
124
125   return GetImageURLFromData(contents);
126 }
127
128 std::vector<base::FilePath> ListFolder(const base::FilePath path) {
129   base::FileEnumerator files(path, false,
130       base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES);
131   std::vector<base::FilePath> paths;
132
133   for (base::FilePath current_path = files.Next(); !current_path.empty();
134        current_path = files.Next()) {
135     paths.push_back(current_path);
136   }
137   return paths;
138 }
139
140 bool ValidateFolderName(const base::FilePath::StringType& name) {
141   base::FilePath::StringType name_sanitized(name);
142   file_util::ReplaceIllegalCharactersInPath(&name_sanitized, '_');
143   return name == name_sanitized;
144 }
145
146 const Extension* GetExtensionByPath(const ExtensionSet* extensions,
147                                     const base::FilePath& path) {
148   base::FilePath extension_path = base::MakeAbsoluteFilePath(path);
149   for (ExtensionSet::const_iterator iter = extensions->begin();
150        iter != extensions->end(); ++iter) {
151     if ((*iter)->path() == extension_path)
152       return iter->get();
153   }
154   return NULL;
155 }
156
157 std::string GetExtensionID(const RenderViewHost* render_view_host) {
158   if (!render_view_host->GetSiteInstance())
159     return std::string();
160
161   return render_view_host->GetSiteInstance()->GetSiteURL().host();
162 }
163
164 }  // namespace
165
166 namespace AllowFileAccess = api::developer_private::AllowFileAccess;
167 namespace AllowIncognito = api::developer_private::AllowIncognito;
168 namespace ChoosePath = api::developer_private::ChoosePath;
169 namespace Enable = api::developer_private::Enable;
170 namespace GetItemsInfo = api::developer_private::GetItemsInfo;
171 namespace Inspect = api::developer_private::Inspect;
172 namespace PackDirectory = api::developer_private::PackDirectory;
173 namespace Reload = api::developer_private::Reload;
174
175 DeveloperPrivateAPI* DeveloperPrivateAPI::Get(Profile* profile) {
176   return DeveloperPrivateAPIFactory::GetForProfile(profile);
177 }
178
179 DeveloperPrivateAPI::DeveloperPrivateAPI(Profile* profile) : profile_(profile) {
180   RegisterNotifications();
181 }
182
183 DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile)
184 : profile_(profile) {
185   int types[] = {
186     chrome::NOTIFICATION_EXTENSION_INSTALLED,
187     chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
188     chrome::NOTIFICATION_EXTENSION_LOADED,
189     chrome::NOTIFICATION_EXTENSION_UNLOADED,
190     chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
191     chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED
192   };
193
194   CHECK(registrar_.IsEmpty());
195   for (size_t i = 0; i < arraysize(types); ++i) {
196     registrar_.Add(this,
197                    types[i],
198                    content::Source<Profile>(profile_));
199   }
200 }
201
202
203 DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() {}
204
205 void DeveloperPrivateEventRouter::Observe(
206     int type,
207     const content::NotificationSource& source,
208     const content::NotificationDetails& details) {
209   const char* event_name = NULL;
210   Profile* profile = content::Source<Profile>(source).ptr();
211   CHECK(profile);
212   CHECK(profile_->IsSameProfile(profile));
213   developer::EventData event_data;
214   const Extension* extension = NULL;
215
216   switch (type) {
217     case chrome::NOTIFICATION_EXTENSION_INSTALLED:
218       event_data.event_type = developer::EVENT_TYPE_INSTALLED;
219       extension =
220           content::Details<const InstalledExtensionInfo>(details)->extension;
221       break;
222     case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
223       event_data.event_type = developer::EVENT_TYPE_UNINSTALLED;
224       extension = content::Details<const Extension>(details).ptr();
225       break;
226     case chrome::NOTIFICATION_EXTENSION_LOADED:
227       event_data.event_type = developer::EVENT_TYPE_LOADED;
228       extension = content::Details<const Extension>(details).ptr();
229       break;
230     case chrome::NOTIFICATION_EXTENSION_UNLOADED:
231       event_data.event_type = developer::EVENT_TYPE_UNLOADED;
232       extension =
233           content::Details<const UnloadedExtensionInfo>(details)->extension;
234       break;
235     case chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED:
236       event_data.event_type = developer::EVENT_TYPE_VIEW_UNREGISTERED;
237       event_data.item_id = GetExtensionID(
238           content::Details<const RenderViewHost>(details).ptr());
239       break;
240     case chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED:
241       event_data.event_type = developer::EVENT_TYPE_VIEW_REGISTERED;
242       event_data.item_id = GetExtensionID(
243           content::Details<const RenderViewHost>(details).ptr());
244       break;
245     default:
246       NOTREACHED();
247       return;
248   }
249
250   if (extension)
251     event_data.item_id = extension->id();
252
253   scoped_ptr<ListValue> args(new ListValue());
254   args->Append(event_data.ToValue().release());
255
256   event_name = developer_private::OnItemStateChanged::kEventName;
257   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
258   ExtensionSystem::Get(profile)->event_router()->BroadcastEvent(event.Pass());
259 }
260
261 void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) {
262   last_unpacked_directory_ = path;
263 }
264
265 void DeveloperPrivateAPI::RegisterNotifications() {
266   ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
267       this, developer_private::OnItemStateChanged::kEventName);
268 }
269
270 DeveloperPrivateAPI::~DeveloperPrivateAPI() {}
271
272 void DeveloperPrivateAPI::Shutdown() {}
273
274 void DeveloperPrivateAPI::OnListenerAdded(
275     const EventListenerInfo& details) {
276   if (!developer_private_event_router_)
277     developer_private_event_router_.reset(
278         new DeveloperPrivateEventRouter(profile_));
279 }
280
281 void DeveloperPrivateAPI::OnListenerRemoved(
282     const EventListenerInfo& details) {
283   if (!ExtensionSystem::Get(profile_)->event_router()->HasEventListener(
284           developer_private::OnItemStateChanged::kEventName))
285     developer_private_event_router_.reset(NULL);
286 }
287
288 namespace api {
289
290 bool DeveloperPrivateAutoUpdateFunction::RunImpl() {
291   ExtensionUpdater* updater = GetExtensionUpdater(GetProfile());
292   if (updater)
293     updater->CheckNow(ExtensionUpdater::CheckParams());
294   SetResult(new base::FundamentalValue(true));
295   return true;
296 }
297
298 DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() {}
299
300 scoped_ptr<developer::ItemInfo>
301   DeveloperPrivateGetItemsInfoFunction::CreateItemInfo(
302       const Extension& item,
303       bool item_is_enabled) {
304   scoped_ptr<developer::ItemInfo> info(new developer::ItemInfo());
305
306   ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
307   ExtensionService* service = GetProfile()->GetExtensionService();
308
309   info->id = item.id();
310   info->name = item.name();
311   info->enabled = service->IsExtensionEnabled(info->id);
312   info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&item);
313   info->version = item.VersionString();
314   info->description = item.description();
315
316   if (item.is_app()) {
317     if (item.is_legacy_packaged_app())
318       info->type = developer::ITEM_TYPE_LEGACY_PACKAGED_APP;
319     else if (item.is_hosted_app())
320       info->type = developer::ITEM_TYPE_HOSTED_APP;
321     else if (item.is_platform_app())
322       info->type = developer::ITEM_TYPE_PACKAGED_APP;
323     else
324       NOTREACHED();
325   } else if (item.is_theme()) {
326     info->type = developer::ITEM_TYPE_THEME;
327   } else if (item.is_extension()) {
328     info->type = developer::ITEM_TYPE_EXTENSION;
329   } else {
330     NOTREACHED();
331   }
332
333   if (Manifest::IsUnpackedLocation(item.location())) {
334     info->path.reset(
335         new std::string(UTF16ToUTF8(item.path().LossyDisplayName())));
336     for (std::vector<extensions::InstallWarning>::const_iterator it =
337              item.install_warnings().begin();
338          it != item.install_warnings().end(); ++it) {
339       developer::InstallWarning* warning = new developer::InstallWarning();
340       warning->message = it->message;
341       info->install_warnings.push_back(make_linked_ptr(warning));
342     }
343   }
344
345   info->incognito_enabled =
346       extension_util::IsIncognitoEnabled(item.id(),service);
347   info->wants_file_access = item.wants_file_access();
348   info->allow_file_access = extension_util::AllowFileAccess(&item, service);
349   info->allow_reload = Manifest::IsUnpackedLocation(item.location());
350   info->is_unpacked = Manifest::IsUnpackedLocation(item.location());
351   info->terminated = service->terminated_extensions()->Contains(item.id());
352   info->allow_incognito = item.can_be_incognito_enabled();
353
354   info->homepage_url.reset(new std::string(
355       ManifestURL::GetHomepageURL(&item).spec()));
356   if (!ManifestURL::GetOptionsPage(&item).is_empty()) {
357     info->options_url.reset(
358         new std::string(ManifestURL::GetOptionsPage(&item).spec()));
359   }
360
361   if (!ManifestURL::GetUpdateURL(&item).is_empty()) {
362     info->update_url.reset(
363         new std::string(ManifestURL::GetUpdateURL(&item).spec()));
364   }
365
366   if (item.is_app()) {
367     info->app_launch_url.reset(new std::string(
368         extensions::AppLaunchInfo::GetFullLaunchURL(&item).spec()));
369   }
370
371   info->may_disable = system->management_policy()->
372       UserMayModifySettings(&item, NULL);
373   info->is_app = item.is_app();
374   info->views = GetInspectablePagesForExtension(&item, item_is_enabled);
375
376   return info.Pass();
377 }
378
379 void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread(
380     ItemInfoList item_list,
381     const std::map<std::string, ExtensionResource> idToIcon) {
382   for (ItemInfoList::iterator iter = item_list.begin();
383        iter != item_list.end(); ++iter) {
384     developer_private::ItemInfo* info = iter->get();
385     std::map<std::string, ExtensionResource>::const_iterator resource_ptr
386         = idToIcon.find(info->id);
387     if (resource_ptr != idToIcon.end()) {
388       info->icon_url =
389           ToDataURL(resource_ptr->second.GetFilePath(), info->type).spec();
390     }
391   }
392
393   results_ = developer::GetItemsInfo::Results::Create(item_list);
394   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
395       base::Bind(&DeveloperPrivateGetItemsInfoFunction::SendResponse,
396                  this,
397                  true));
398 }
399
400 void DeveloperPrivateGetItemsInfoFunction::
401     GetInspectablePagesForExtensionProcess(
402         const Extension* extension,
403         const std::set<content::RenderViewHost*>& views,
404         ItemInspectViewList* result) {
405   bool has_generated_background_page =
406       BackgroundInfo::HasGeneratedBackgroundPage(extension);
407   for (std::set<content::RenderViewHost*>::const_iterator iter = views.begin();
408        iter != views.end(); ++iter) {
409     content::RenderViewHost* host = *iter;
410     content::WebContents* web_contents =
411         content::WebContents::FromRenderViewHost(host);
412     ViewType host_type = GetViewType(web_contents);
413     if (VIEW_TYPE_EXTENSION_POPUP == host_type ||
414         VIEW_TYPE_EXTENSION_DIALOG == host_type)
415       continue;
416
417     content::RenderProcessHost* process = host->GetProcess();
418     bool is_background_page =
419         (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension));
420     result->push_back(constructInspectView(
421         web_contents->GetURL(),
422         process->GetID(),
423         host->GetRoutingID(),
424         process->GetBrowserContext()->IsOffTheRecord(),
425         is_background_page && has_generated_background_page));
426   }
427 }
428
429 void DeveloperPrivateGetItemsInfoFunction::
430     GetShellWindowPagesForExtensionProfile(
431         const Extension* extension,
432         ItemInspectViewList* result) {
433   ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
434   if (!registry) return;
435
436   const ShellWindowRegistry::ShellWindowList windows =
437       registry->GetShellWindowsForApp(extension->id());
438
439   bool has_generated_background_page =
440       BackgroundInfo::HasGeneratedBackgroundPage(extension);
441   for (ShellWindowRegistry::const_iterator it = windows.begin();
442        it != windows.end(); ++it) {
443     content::WebContents* web_contents = (*it)->web_contents();
444     RenderViewHost* host = web_contents->GetRenderViewHost();
445     content::RenderProcessHost* process = host->GetProcess();
446     bool is_background_page =
447         (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension));
448     result->push_back(constructInspectView(
449         web_contents->GetURL(),
450         process->GetID(),
451         host->GetRoutingID(),
452         process->GetBrowserContext()->IsOffTheRecord(),
453         is_background_page && has_generated_background_page));
454   }
455 }
456
457 linked_ptr<developer::ItemInspectView> DeveloperPrivateGetItemsInfoFunction::
458     constructInspectView(
459         const GURL& url,
460         int render_process_id,
461         int render_view_id,
462         bool incognito,
463         bool generated_background_page) {
464   linked_ptr<developer::ItemInspectView> view(new developer::ItemInspectView());
465
466   if (url.scheme() == kExtensionScheme) {
467     // No leading slash.
468     view->path = url.path().substr(1);
469   } else {
470     // For live pages, use the full URL.
471     view->path = url.spec();
472   }
473
474   view->render_process_id = render_process_id;
475   view->render_view_id = render_view_id;
476   view->incognito = incognito;
477   view->generated_background_page = generated_background_page;
478   return view;
479 }
480
481 ItemInspectViewList DeveloperPrivateGetItemsInfoFunction::
482     GetInspectablePagesForExtension(
483         const Extension* extension,
484         bool extension_is_enabled) {
485
486   ItemInspectViewList result;
487   // Get the extension process's active views.
488   ExtensionProcessManager* process_manager =
489       ExtensionSystem::Get(GetProfile())->process_manager();
490   GetInspectablePagesForExtensionProcess(
491       extension,
492       process_manager->GetRenderViewHostsForExtension(extension->id()),
493       &result);
494
495   // Get shell window views
496   GetShellWindowPagesForExtensionProfile(extension, &result);
497
498   // Include a link to start the lazy background page, if applicable.
499   if (BackgroundInfo::HasLazyBackgroundPage(extension) &&
500       extension_is_enabled &&
501       !process_manager->GetBackgroundHostForExtension(extension->id())) {
502     result.push_back(constructInspectView(
503         BackgroundInfo::GetBackgroundURL(extension),
504         -1,
505         -1,
506         false,
507         BackgroundInfo::HasGeneratedBackgroundPage(extension)));
508   }
509
510   ExtensionService* service = GetProfile()->GetExtensionService();
511   // Repeat for the incognito process, if applicable. Don't try to get
512   // shell windows for incognito process.
513   if (service->profile()->HasOffTheRecordProfile() &&
514       IncognitoInfo::IsSplitMode(extension)) {
515     process_manager = ExtensionSystem::Get(
516         service->profile()->GetOffTheRecordProfile())->process_manager();
517     GetInspectablePagesForExtensionProcess(
518         extension,
519         process_manager->GetRenderViewHostsForExtension(extension->id()),
520         &result);
521
522     if (BackgroundInfo::HasLazyBackgroundPage(extension) &&
523         extension_is_enabled &&
524         !process_manager->GetBackgroundHostForExtension(extension->id())) {
525     result.push_back(constructInspectView(
526         BackgroundInfo::GetBackgroundURL(extension),
527         -1,
528         -1,
529         false,
530         BackgroundInfo::HasGeneratedBackgroundPage(extension)));
531     }
532   }
533
534   return result;
535 }
536
537 bool DeveloperPrivateGetItemsInfoFunction::RunImpl() {
538   scoped_ptr<developer::GetItemsInfo::Params> params(
539       developer::GetItemsInfo::Params::Create(*args_));
540   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
541
542   bool include_disabled = params->include_disabled;
543   bool include_terminated = params->include_terminated;
544
545   ExtensionSet items;
546
547   ExtensionService* service = GetProfile()->GetExtensionService();
548
549   items.InsertAll(*service->extensions());
550
551   if (include_disabled) {
552     items.InsertAll(*service->disabled_extensions());
553   }
554
555   if (include_terminated) {
556     items.InsertAll(*service->terminated_extensions());
557   }
558
559   std::map<std::string, ExtensionResource> id_to_icon;
560   ItemInfoList item_list;
561
562   for (ExtensionSet::const_iterator iter = items.begin();
563        iter != items.end(); ++iter) {
564     const Extension& item = *iter->get();
565
566     ExtensionResource item_resource =
567         IconsInfo::GetIconResource(&item,
568                                    extension_misc::EXTENSION_ICON_MEDIUM,
569                                    ExtensionIconSet::MATCH_BIGGER);
570     id_to_icon[item.id()] = item_resource;
571
572     // Don't show component extensions and invisible apps.
573     if (item.ShouldNotBeVisible())
574       continue;
575
576     item_list.push_back(make_linked_ptr<developer::ItemInfo>(
577         CreateItemInfo(
578             item, service->IsExtensionEnabled(item.id())).release()));
579   }
580
581   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
582       base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread,
583                  this,
584                  item_list,
585                  id_to_icon));
586
587   return true;
588 }
589
590 DeveloperPrivateGetItemsInfoFunction::~DeveloperPrivateGetItemsInfoFunction() {}
591
592 bool DeveloperPrivateAllowFileAccessFunction::RunImpl() {
593   scoped_ptr<AllowFileAccess::Params> params(
594       AllowFileAccess::Params::Create(*args_));
595   EXTENSION_FUNCTION_VALIDATE(params.get());
596
597   EXTENSION_FUNCTION_VALIDATE(user_gesture_);
598
599   ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
600   ManagementPolicy* management_policy = system->management_policy();
601   ExtensionService* service = GetProfile()->GetExtensionService();
602   const Extension* extension = service->GetInstalledExtension(params->item_id);
603   bool result = true;
604
605   if (!extension) {
606     result = false;
607   } else if (!management_policy->UserMayModifySettings(extension, NULL)) {
608     LOG(ERROR) << "Attempt to change allow file access of an extension that "
609                << "non-usermanagable was made. Extension id : "
610                << extension->id();
611     result = false;
612   } else {
613     extension_util::SetAllowFileAccess(extension, service, params->allow);
614     result = true;
615   }
616
617   return result;
618 }
619
620 DeveloperPrivateAllowFileAccessFunction::
621     ~DeveloperPrivateAllowFileAccessFunction() {}
622
623 bool DeveloperPrivateAllowIncognitoFunction::RunImpl() {
624   scoped_ptr<AllowIncognito::Params> params(
625       AllowIncognito::Params::Create(*args_));
626   EXTENSION_FUNCTION_VALIDATE(params.get());
627
628   ExtensionService* service = GetProfile()->GetExtensionService();
629   const Extension* extension = service->GetInstalledExtension(params->item_id);
630   bool result = true;
631
632   if (!extension)
633     result = false;
634   else
635     extension_util::SetIsIncognitoEnabled(
636         extension->id(),service, params->allow);
637
638   return result;
639 }
640
641 DeveloperPrivateAllowIncognitoFunction::
642     ~DeveloperPrivateAllowIncognitoFunction() {}
643
644
645 bool DeveloperPrivateReloadFunction::RunImpl() {
646   scoped_ptr<Reload::Params> params(Reload::Params::Create(*args_));
647   EXTENSION_FUNCTION_VALIDATE(params.get());
648
649   ExtensionService* service = GetProfile()->GetExtensionService();
650   CHECK(!params->item_id.empty());
651   service->ReloadExtension(params->item_id);
652   return true;
653 }
654
655 bool DeveloperPrivateShowPermissionsDialogFunction::RunImpl() {
656   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id_));
657   ExtensionService* service = GetProfile()->GetExtensionService();
658   CHECK(!extension_id_.empty());
659   ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
660   DCHECK(registry);
661   ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
662       render_view_host());
663   prompt_.reset(new ExtensionInstallPrompt(shell_window->web_contents()));
664   const Extension* extension = service->GetInstalledExtension(extension_id_);
665
666   if (!extension)
667     return false;
668
669   // Released by InstallUIAbort or InstallUIProceed.
670   AddRef();
671   std::vector<base::FilePath> retained_file_paths;
672   if (extension->HasAPIPermission(extensions::APIPermission::kFileSystem)) {
673     std::vector<apps::SavedFileEntry> retained_file_entries =
674         apps::SavedFilesService::Get(GetProfile())
675             ->GetAllFileEntries(extension_id_);
676     for (size_t i = 0; i < retained_file_entries.size(); i++) {
677       retained_file_paths.push_back(retained_file_entries[i].path);
678     }
679   }
680   prompt_->ReviewPermissions(this, extension, retained_file_paths);
681   return true;
682 }
683
684 DeveloperPrivateReloadFunction::~DeveloperPrivateReloadFunction() {}
685
686 // This is called when the user clicks "Revoke File Access."
687 void DeveloperPrivateShowPermissionsDialogFunction::InstallUIProceed() {
688   apps::SavedFilesService::Get(GetProfile())
689       ->ClearQueue(GetProfile()->GetExtensionService()->GetExtensionById(
690             extension_id_, true));
691   if (apps::AppRestoreService::Get(GetProfile())
692           ->IsAppRestorable(extension_id_))
693     apps::AppLoadService::Get(GetProfile())->RestartApplication(extension_id_);
694   SendResponse(true);
695   Release();
696 }
697
698 void DeveloperPrivateShowPermissionsDialogFunction::InstallUIAbort(
699     bool user_initiated) {
700   SendResponse(true);
701   Release();
702 }
703
704 DeveloperPrivateShowPermissionsDialogFunction::
705     DeveloperPrivateShowPermissionsDialogFunction() {}
706
707 DeveloperPrivateShowPermissionsDialogFunction::
708     ~DeveloperPrivateShowPermissionsDialogFunction() {}
709
710 DeveloperPrivateEnableFunction::DeveloperPrivateEnableFunction() {}
711
712 bool DeveloperPrivateEnableFunction::RunImpl() {
713   scoped_ptr<Enable::Params> params(Enable::Params::Create(*args_));
714   EXTENSION_FUNCTION_VALIDATE(params.get());
715
716   std::string extension_id = params->item_id;
717
718   ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
719   ManagementPolicy* policy = system->management_policy();
720   ExtensionService* service = GetProfile()->GetExtensionService();
721
722   const Extension* extension = service->GetInstalledExtension(extension_id);
723   if (!extension) {
724     LOG(ERROR) << "Did not find extension with id " << extension_id;
725     return false;
726   }
727   bool enable = params->enable;
728   if (!policy->UserMayModifySettings(extension, NULL) ||
729       (!enable && policy->MustRemainEnabled(extension, NULL)) ||
730       (enable && policy->MustRemainDisabled(extension, NULL, NULL))) {
731     LOG(ERROR) << "Attempt to change enable state denied by management policy. "
732                << "Extension id: " << extension_id.c_str();
733     return false;
734   }
735
736   if (enable) {
737     ExtensionPrefs* prefs = service->extension_prefs();
738     if (prefs->DidExtensionEscalatePermissions(extension_id)) {
739       ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
740       CHECK(registry);
741       ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
742           render_view_host());
743       if (!shell_window) {
744         return false;
745       }
746
747       ShowExtensionDisabledDialog(
748           service, shell_window->web_contents(), extension);
749     } else if ((prefs->GetDisableReasons(extension_id) &
750                   Extension::DISABLE_UNSUPPORTED_REQUIREMENT) &&
751                !requirements_checker_.get()) {
752       // Recheck the requirements.
753       scoped_refptr<const Extension> extension =
754           service->GetExtensionById(extension_id,
755                                      true );// include_disabled
756       requirements_checker_.reset(new RequirementsChecker);
757       // Released by OnRequirementsChecked.
758       AddRef();
759       requirements_checker_->Check(
760           extension,
761           base::Bind(&DeveloperPrivateEnableFunction::OnRequirementsChecked,
762                      this, extension_id));
763     } else {
764       service->EnableExtension(extension_id);
765
766       // Make sure any browser action contained within it is not hidden.
767       ExtensionActionAPI::SetBrowserActionVisibility(
768           prefs, extension->id(), true);
769     }
770   } else {
771     service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
772   }
773   return true;
774 }
775
776 void DeveloperPrivateEnableFunction::OnRequirementsChecked(
777     std::string extension_id,
778     std::vector<std::string> requirements_errors) {
779   if (requirements_errors.empty()) {
780     ExtensionService* service = GetProfile()->GetExtensionService();
781     service->EnableExtension(extension_id);
782   } else {
783     ExtensionErrorReporter::GetInstance()->ReportError(
784         UTF8ToUTF16(JoinString(requirements_errors, ' ')),
785         true /* be noisy */);
786   }
787   Release();
788 }
789
790 DeveloperPrivateEnableFunction::~DeveloperPrivateEnableFunction() {}
791
792 bool DeveloperPrivateInspectFunction::RunImpl() {
793   scoped_ptr<developer::Inspect::Params> params(
794       developer::Inspect::Params::Create(*args_));
795   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
796   const developer::InspectOptions& options = params->options;
797
798   int render_process_id;
799   base::StringToInt(options.render_process_id, &render_process_id);
800
801   if (render_process_id == -1) {
802     // This is a lazy background page. Identify if it is a normal
803     // or incognito background page.
804     ExtensionService* service = GetProfile()->GetExtensionService();
805     if (options.incognito)
806       service = ExtensionSystem::Get(
807           service->profile()->GetOffTheRecordProfile())->extension_service();
808     const Extension* extension = service->extensions()->GetByID(
809         options.extension_id);
810     DCHECK(extension);
811     // Wakes up the background page and  opens the inspect window.
812     devtools_util::InspectBackgroundPage(extension, GetProfile());
813     return false;
814   }
815
816   int render_view_id;
817   base::StringToInt(options.render_view_id, &render_view_id);
818   content::RenderViewHost* host = content::RenderViewHost::FromID(
819       render_process_id, render_view_id);
820
821   if (!host) {
822     // This can happen if the host has gone away since the page was displayed.
823     return false;
824   }
825
826   DevToolsWindow::OpenDevToolsWindow(host);
827   return true;
828 }
829
830 DeveloperPrivateInspectFunction::~DeveloperPrivateInspectFunction() {}
831
832 bool DeveloperPrivateLoadUnpackedFunction::RunImpl() {
833   string16 select_title =
834       l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
835
836   // Balanced in FileSelected / FileSelectionCanceled.
837   AddRef();
838   bool result = ShowPicker(
839       ui::SelectFileDialog::SELECT_FOLDER,
840       DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
841       select_title,
842       ui::SelectFileDialog::FileTypeInfo(),
843       0);
844   return result;
845 }
846
847 void DeveloperPrivateLoadUnpackedFunction::FileSelected(
848     const base::FilePath& path) {
849   ExtensionService* service = GetProfile()->GetExtensionService();
850   UnpackedInstaller::Create(service)->Load(path);
851   DeveloperPrivateAPI::Get(GetProfile())->SetLastUnpackedDirectory(path);
852   SendResponse(true);
853   Release();
854 }
855
856 void DeveloperPrivateLoadUnpackedFunction::FileSelectionCanceled() {
857   SendResponse(false);
858   Release();
859 }
860
861 bool DeveloperPrivateChooseEntryFunction::ShowPicker(
862     ui::SelectFileDialog::Type picker_type,
863     const base::FilePath& last_directory,
864     const string16& select_title,
865     const ui::SelectFileDialog::FileTypeInfo& info,
866     int file_type_index) {
867   ShellWindowRegistry* registry = ShellWindowRegistry::Get(GetProfile());
868   DCHECK(registry);
869   ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
870       render_view_host());
871   if (!shell_window) {
872     return false;
873   }
874
875   // The entry picker will hold a reference to this function instance,
876   // and subsequent sending of the function response) until the user has
877   // selected a file or cancelled the picker. At that point, the picker will
878   // delete itself.
879   new EntryPicker(this, shell_window->web_contents(), picker_type,
880   last_directory, select_title, info, file_type_index);
881   return true;
882 }
883
884 bool DeveloperPrivateChooseEntryFunction::RunImpl() { return false; }
885
886 DeveloperPrivateChooseEntryFunction::~DeveloperPrivateChooseEntryFunction() {}
887
888 void DeveloperPrivatePackDirectoryFunction::OnPackSuccess(
889     const base::FilePath& crx_file,
890     const base::FilePath& pem_file) {
891   developer::PackDirectoryResponse response;
892   response.message =
893       UTF16ToUTF8(PackExtensionJob::StandardSuccessMessage(crx_file, pem_file));
894   response.status = developer::PACK_STATUS_SUCCESS;
895   results_ = developer::PackDirectory::Results::Create(response);
896   SendResponse(true);
897   Release();
898 }
899
900 void DeveloperPrivatePackDirectoryFunction::OnPackFailure(
901     const std::string& error,
902     ExtensionCreator::ErrorType error_type) {
903   developer::PackDirectoryResponse response;
904   response.message = error;
905   if (error_type == ExtensionCreator::kCRXExists) {
906     response.item_path = item_path_str_;
907     response.pem_path = key_path_str_;
908     response.override_flags = ExtensionCreator::kOverwriteCRX;
909     response.status = developer::PACK_STATUS_WARNING;
910   } else {
911     response.status = developer::PACK_STATUS_ERROR;
912   }
913   results_ = developer::PackDirectory::Results::Create(response);
914   SendResponse(true);
915   Release();
916 }
917
918 bool DeveloperPrivatePackDirectoryFunction::RunImpl() {
919   scoped_ptr<PackDirectory::Params> params(
920       PackDirectory::Params::Create(*args_));
921   EXTENSION_FUNCTION_VALIDATE(params.get());
922
923   int flags = params->flags;
924   item_path_str_ = params->path;
925   key_path_str_ = params->private_key_path;
926
927   base::FilePath root_directory =
928       base::FilePath::FromUTF8Unsafe(item_path_str_);
929
930   base::FilePath key_file = base::FilePath::FromUTF8Unsafe(key_path_str_);
931
932   developer::PackDirectoryResponse response;
933   if (root_directory.empty()) {
934     if (item_path_str_.empty())
935       response.message = l10n_util::GetStringUTF8(
936           IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED);
937     else
938       response.message = l10n_util::GetStringUTF8(
939           IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID);
940
941     response.status = developer::PACK_STATUS_ERROR;
942     results_ = developer::PackDirectory::Results::Create(response);
943     SendResponse(true);
944     return true;
945   }
946
947   if (!key_path_str_.empty() && key_file.empty()) {
948     response.message = l10n_util::GetStringUTF8(
949         IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID);
950     response.status = developer::PACK_STATUS_ERROR;
951     results_ = developer::PackDirectory::Results::Create(response);
952     SendResponse(true);
953     return true;
954   }
955
956   // Balanced in OnPackSuccess / OnPackFailure.
957   AddRef();
958
959   pack_job_ = new PackExtensionJob(this, root_directory, key_file, flags);
960   pack_job_->Start();
961   return true;
962 }
963
964 DeveloperPrivatePackDirectoryFunction::DeveloperPrivatePackDirectoryFunction()
965 {}
966
967 DeveloperPrivatePackDirectoryFunction::~DeveloperPrivatePackDirectoryFunction()
968 {}
969
970 DeveloperPrivateLoadUnpackedFunction::~DeveloperPrivateLoadUnpackedFunction() {}
971
972 bool DeveloperPrivateExportSyncfsFolderToLocalfsFunction::RunImpl() {
973   // TODO(grv) : add unittests.
974   base::FilePath::StringType project_name;
975   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &project_name));
976   if (!ValidateFolderName(project_name)) {
977     DLOG(INFO) << "Invalid project_name : [" << project_name << "]";
978     return false;
979   }
980
981   context_ = content::BrowserContext::GetStoragePartition(
982       GetProfile(), render_view_host()->GetSiteInstance())
983                  ->GetFileSystemContext();
984
985   base::FilePath project_path(GetProfile()->GetPath());
986   project_path = project_path.Append(kUnpackedAppsFolder);
987   project_path = project_path.Append(project_name);
988
989   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
990       base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
991                      ClearPrexistingDirectoryContent,
992                  this,
993                  project_path));
994
995   return true;
996 }
997
998 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
999     ClearPrexistingDirectoryContent(const base::FilePath& project_path) {
1000
1001   // Clear the project directory before copying new files.
1002   base::DeleteFile(project_path, true/*recursive*/);
1003
1004   pendingCopyOperationsCount_ = 1;
1005
1006   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
1007       base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1008                  ReadSyncFileSystemDirectory,
1009                  this, project_path, project_path.BaseName()));
1010 }
1011
1012 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1013     ReadSyncFileSystemDirectory(const base::FilePath& project_path,
1014                                 const base::FilePath& destination_path) {
1015   std::string origin_url(
1016       Extension::GetBaseURLFromExtensionId(extension_id()).spec());
1017   fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
1018       GURL(origin_url),
1019       destination_path));
1020
1021   context_->operation_runner()->ReadDirectory(
1022       url, base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1023                       ReadSyncFileSystemDirectoryCb,
1024                       this, project_path, destination_path));
1025 }
1026
1027 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1028     ReadSyncFileSystemDirectoryCb(
1029     const base::FilePath& project_path,
1030     const base::FilePath& destination_path,
1031     base::PlatformFileError status,
1032     const fileapi::FileSystemOperation::FileEntryList& file_list,
1033     bool has_more) {
1034
1035   if (status != base::PLATFORM_FILE_OK) {
1036     DLOG(ERROR) << "Error in copying files from sync filesystem.";
1037     return;
1038   }
1039
1040   // We add 1 to the pending copy operations for both files and directories. We
1041   // release the directory copy operation once all the files under the directory
1042   // are added for copying. We do that to ensure that pendingCopyOperationsCount
1043   // does not become zero before all copy operations are finished.
1044   // In case the directory happens to be executing the last copy operation it
1045   // will call SendResponse to send the response to the API. The pending copy
1046   // operations of files are released by the CopyFile function.
1047   pendingCopyOperationsCount_ += file_list.size();
1048
1049   for (size_t i = 0; i < file_list.size(); ++i) {
1050     if (file_list[i].is_directory) {
1051       ReadSyncFileSystemDirectory(project_path.Append(file_list[i].name),
1052                                   destination_path.Append(file_list[i].name));
1053       continue;
1054     }
1055
1056     std::string origin_url(
1057         Extension::GetBaseURLFromExtensionId(extension_id()).spec());
1058     fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
1059         GURL(origin_url),
1060         destination_path.Append(file_list[i].name)));
1061     base::FilePath target_path = project_path;
1062     target_path = target_path.Append(file_list[i].name);
1063
1064     context_->operation_runner()->CreateSnapshotFile(
1065         url,
1066         base::Bind(
1067             &DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1068                 SnapshotFileCallback,
1069             this,
1070             target_path));
1071
1072   }
1073
1074   // Directory copy operation released here.
1075   pendingCopyOperationsCount_--;
1076
1077   if (!pendingCopyOperationsCount_) {
1078     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1079         base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1080                        SendResponse,
1081                    this,
1082                    success_));
1083   }
1084 }
1085
1086 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::SnapshotFileCallback(
1087     const base::FilePath& target_path,
1088     base::PlatformFileError result,
1089     const base::PlatformFileInfo& file_info,
1090     const base::FilePath& src_path,
1091     const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
1092   if (result != base::PLATFORM_FILE_OK) {
1093     SetError("Error in copying files from sync filesystem.");
1094     success_ = false;
1095     return;
1096   }
1097
1098   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
1099       base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile,
1100                  this,
1101                  src_path,
1102                  target_path));
1103 }
1104
1105 void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile(
1106     const base::FilePath& src_path,
1107     const base::FilePath& target_path) {
1108   if (!file_util::CreateDirectory(target_path.DirName())) {
1109     SetError("Error in copying files from sync filesystem.");
1110     success_ = false;
1111   }
1112
1113   if (success_)
1114     base::CopyFile(src_path, target_path);
1115
1116   CHECK(pendingCopyOperationsCount_ > 0);
1117   pendingCopyOperationsCount_--;
1118
1119   if (!pendingCopyOperationsCount_) {
1120     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1121         base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1122                        SendResponse,
1123                    this,
1124                    success_));
1125   }
1126 }
1127
1128 DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1129     DeveloperPrivateExportSyncfsFolderToLocalfsFunction()
1130     : pendingCopyOperationsCount_(0), success_(true) {}
1131
1132 DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
1133     ~DeveloperPrivateExportSyncfsFolderToLocalfsFunction() {}
1134
1135 bool DeveloperPrivateLoadProjectFunction::RunImpl() {
1136   // TODO(grv) : add unit tests.
1137   base::FilePath::StringType project_name;
1138   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &project_name));
1139   if (!ValidateFolderName(project_name)) {
1140     DLOG(INFO) << "Invalid project_name : [" << project_name << "]";
1141     return false;
1142   }
1143
1144   base::FilePath path(GetProfile()->GetPath());
1145   path = path.Append(kUnpackedAppsFolder);
1146   // TODO(grv) : Sanitize / check project_name.
1147   path = path.Append(project_name);
1148   ExtensionService* service = GetProfile()->GetExtensionService();
1149   UnpackedInstaller::Create(service)->Load(path);
1150
1151   const ExtensionSet* extensions = service->extensions();
1152   // Released by GetUnpackedExtension.
1153   AddRef();
1154   content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
1155       base::Bind(&DeveloperPrivateLoadProjectFunction::GetUnpackedExtension,
1156                  this, path, extensions));
1157   return true;
1158 }
1159
1160 void DeveloperPrivateLoadProjectFunction::GetUnpackedExtension(
1161     const base::FilePath& path,
1162     const ExtensionSet* extensions) {
1163   const Extension* extension = GetExtensionByPath(extensions, path);
1164   bool success = true;
1165   if (extension) {
1166     SetResult(new base::StringValue(extension->id()));
1167   } else {
1168     SetError("unable to load the project");
1169     success = false;
1170   }
1171   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1172       base::Bind(&DeveloperPrivateLoadProjectFunction::SendResponse,
1173                  this,
1174                  success));
1175   Release();
1176 }
1177
1178 DeveloperPrivateLoadProjectFunction::DeveloperPrivateLoadProjectFunction() {}
1179
1180 DeveloperPrivateLoadProjectFunction::~DeveloperPrivateLoadProjectFunction() {}
1181
1182 bool DeveloperPrivateChoosePathFunction::RunImpl() {
1183
1184   scoped_ptr<developer::ChoosePath::Params> params(
1185       developer::ChoosePath::Params::Create(*args_));
1186   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
1187
1188   ui::SelectFileDialog::Type type = ui::SelectFileDialog::SELECT_FOLDER;
1189   ui::SelectFileDialog::FileTypeInfo info;
1190   if (params->select_type == developer::SELECT_TYPE_FILE) {
1191     type = ui::SelectFileDialog::SELECT_OPEN_FILE;
1192   }
1193   string16 select_title;
1194
1195   int file_type_index = 0;
1196   if (params->file_type == developer::FILE_TYPE_LOAD)
1197     select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
1198   else if (params->file_type== developer::FILE_TYPE_PEM) {
1199     select_title = l10n_util::GetStringUTF16(
1200         IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
1201     info.extensions.push_back(std::vector<base::FilePath::StringType>());
1202     info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
1203     info.extension_description_overrides.push_back(
1204         l10n_util::GetStringUTF16(
1205             IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
1206     info.include_all_files = true;
1207     file_type_index = 1;
1208   } else {
1209     NOTREACHED();
1210   }
1211
1212   // Balanced by FileSelected / FileSelectionCanceled.
1213   AddRef();
1214   bool result = ShowPicker(
1215       type,
1216       DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
1217       select_title,
1218       info,
1219       file_type_index);
1220   return result;
1221 }
1222
1223 void DeveloperPrivateChoosePathFunction::FileSelected(
1224     const base::FilePath& path) {
1225   SetResult(new base::StringValue(UTF16ToUTF8(path.LossyDisplayName())));
1226   SendResponse(true);
1227   Release();
1228 }
1229
1230 void DeveloperPrivateChoosePathFunction::FileSelectionCanceled() {
1231   SendResponse(false);
1232   Release();
1233 }
1234
1235 DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {}
1236
1237 bool DeveloperPrivateGetStringsFunction::RunImpl() {
1238   base::DictionaryValue* dict = new base::DictionaryValue();
1239   SetResult(dict);
1240
1241   webui::SetFontAndTextDirection(dict);
1242
1243   #define   SET_STRING(id, idr) \
1244     dict->SetString(id, l10n_util::GetStringUTF16(idr))
1245   SET_STRING("extensionSettings", IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE);
1246
1247   SET_STRING("appsDevtoolSearch", IDS_APPS_DEVTOOL_SEARCH);
1248   SET_STRING("appsDevtoolApps", IDS_APPS_DEVTOOL_APPS_INSTALLED);
1249   SET_STRING("appsDevtoolExtensions", IDS_APPS_DEVTOOL_EXTENSIONS_INSTALLED);
1250   SET_STRING("appsDevtoolNoExtensions", IDS_EXTENSIONS_NONE_INSTALLED);
1251   SET_STRING("appsDevtoolUnpacked", IDS_APPS_DEVTOOL_UNPACKED_INSTALLED);
1252   SET_STRING("appsDevtoolInstalled", IDS_APPS_DEVTOOL_INSTALLED);
1253   SET_STRING("appsDevtoolNoPackedApps", IDS_APPS_DEVTOOL_NO_PACKED_APPS);
1254   SET_STRING("appsDevtoolNoUnpackedApps", IDS_APPS_DEVTOOL_NO_UNPACKED_APPS);
1255   SET_STRING("appsDevtoolNoPackedExtensions",
1256       IDS_APPS_DEVTOOL_NO_PACKED_EXTENSIONS);
1257   SET_STRING("appsDevtoolNoUnpackedExtensions",
1258       IDS_APPS_DEVTOOL_NO_UNPACKED_EXTENSIONS);
1259   SET_STRING("appsDevtoolUpdating", IDS_APPS_DEVTOOL_UPDATING);
1260   SET_STRING("extensionSettingsGetMoreExtensions", IDS_GET_MORE_EXTENSIONS);
1261   SET_STRING("extensionSettingsExtensionId", IDS_EXTENSIONS_ID);
1262   SET_STRING("extensionSettingsExtensionPath", IDS_EXTENSIONS_PATH);
1263   SET_STRING("extensionSettingsInspectViews", IDS_EXTENSIONS_INSPECT_VIEWS);
1264   SET_STRING("extensionSettingsInstallWarnings",
1265              IDS_EXTENSIONS_INSTALL_WARNINGS);
1266   SET_STRING("viewIncognito", IDS_EXTENSIONS_VIEW_INCOGNITO);
1267   SET_STRING("viewInactive", IDS_EXTENSIONS_VIEW_INACTIVE);
1268   SET_STRING("backgroundPage", IDS_EXTENSIONS_BACKGROUND_PAGE);
1269   SET_STRING("extensionSettingsEnable", IDS_EXTENSIONS_ENABLE);
1270   SET_STRING("extensionSettingsEnabled", IDS_EXTENSIONS_ENABLED);
1271   SET_STRING("extensionSettingsRemove", IDS_EXTENSIONS_REMOVE);
1272   SET_STRING("extensionSettingsEnableIncognito",
1273              IDS_EXTENSIONS_ENABLE_INCOGNITO);
1274   SET_STRING("extensionSettingsAllowFileAccess",
1275              IDS_EXTENSIONS_ALLOW_FILE_ACCESS);
1276   SET_STRING("extensionSettingsReloadTerminated",
1277              IDS_EXTENSIONS_RELOAD_TERMINATED);
1278   SET_STRING("extensionSettingsReloadUnpacked",
1279              IDS_APPS_DEV_TOOLS_RELOAD_UNPACKED);
1280   SET_STRING("extensionSettingsLaunch", IDS_EXTENSIONS_LAUNCH);
1281   SET_STRING("extensionSettingsOptions", IDS_EXTENSIONS_OPTIONS_LINK);
1282   SET_STRING("extensionSettingsPermissions", IDS_EXTENSIONS_PERMISSIONS_LINK);
1283   SET_STRING("extensionSettingsVisitWebsite", IDS_EXTENSIONS_VISIT_WEBSITE);
1284   SET_STRING("extensionSettingsVisitWebStore", IDS_EXTENSIONS_VISIT_WEBSTORE);
1285   SET_STRING("extensionSettingsPolicyControlled",
1286              IDS_EXTENSIONS_POLICY_CONTROLLED);
1287   SET_STRING("extensionSettingsManagedMode",
1288              IDS_EXTENSIONS_LOCKED_MANAGED_USER);
1289   SET_STRING("extensionSettingsShowButton", IDS_EXTENSIONS_SHOW_BUTTON);
1290   SET_STRING("appsDevtoolLoadUnpackedButton",
1291              IDS_APPS_DEVTOOL_LOAD_UNPACKED_BUTTON);
1292   SET_STRING("appsDevtoolPackButton", IDS_APPS_DEVTOOL_PACK_BUTTON);
1293   SET_STRING("extensionSettingsCommandsLink",
1294              IDS_EXTENSIONS_COMMANDS_CONFIGURE);
1295   SET_STRING("appsDevtoolUpdateButton", IDS_APPS_DEVTOOL_UPDATE_BUTTON);
1296   SET_STRING("extensionSettingsWarningsTitle", IDS_EXTENSION_WARNINGS_TITLE);
1297   SET_STRING("extensionSettingsShowDetails", IDS_EXTENSIONS_SHOW_DETAILS);
1298   SET_STRING("extensionSettingsHideDetails", IDS_EXTENSIONS_HIDE_DETAILS);
1299   SET_STRING("extensionUninstall", IDS_EXTENSIONS_UNINSTALL);
1300   SET_STRING("extensionsPermissionsHeading",
1301              IDS_EXTENSIONS_PERMISSIONS_HEADING);
1302   SET_STRING("extensionsPermissionsClose", IDS_EXTENSIONS_PERMISSIONS_CLOSE);
1303   SET_STRING("extensionDisabled", IDS_EXTENSIONS_DISABLED);
1304   SET_STRING("extensionSettingsShowLogsButton", IDS_EXTENSIONS_SHOW_LOGS);
1305   SET_STRING("extensionSettingsMoreDetailsButton", IDS_EXTENSIONS_MORE_DETAILS);
1306   SET_STRING("extensionSettingsVersion", IDS_EXTENSIONS_VERSION);
1307   SET_STRING("extensionSettingsDelete", IDS_EXTENSIONS_ADT_DELETE);
1308   SET_STRING("extensionSettingsPack", IDS_EXTENSIONS_PACK);
1309
1310 // Pack Extension strings
1311   SET_STRING("packExtensionOverlay", IDS_EXTENSION_PACK_DIALOG_TITLE);
1312   SET_STRING("packExtensionHeading", IDS_EXTENSION_ADT_PACK_DIALOG_HEADING);
1313   SET_STRING("packButton", IDS_EXTENSION_ADT_PACK_BUTTON);
1314   SET_STRING("ok", IDS_OK);
1315   SET_STRING("cancel", IDS_CANCEL);
1316   SET_STRING("packExtensionRootDir",
1317      IDS_EXTENSION_PACK_DIALOG_ROOT_DIRECTORY_LABEL);
1318   SET_STRING("packExtensionPrivateKey",
1319      IDS_EXTENSION_PACK_DIALOG_PRIVATE_KEY_LABEL);
1320   SET_STRING("packExtensionBrowseButton", IDS_EXTENSION_PACK_DIALOG_BROWSE);
1321   SET_STRING("packExtensionProceedAnyway", IDS_EXTENSION_PROCEED_ANYWAY);
1322   SET_STRING("packExtensionWarningTitle", IDS_EXTENSION_PACK_WARNING_TITLE);
1323   SET_STRING("packExtensionErrorTitle", IDS_EXTENSION_PACK_ERROR_TITLE);
1324   SET_STRING("packAppOverlay", IDS_EXTENSION_PACK_APP_DIALOG_TITLE);
1325   SET_STRING("packAppHeading", IDS_EXTENSION_ADT_PACK_APP_DIALOG_HEADING);
1326
1327 // Delete confirmation dialog.
1328   SET_STRING("deleteConfirmationDeleteButton",
1329       IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_BUTTON);
1330   SET_STRING("deleteConfirmationTitle",
1331       IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_TITLE);
1332   SET_STRING("deleteConfirmationMessageApp",
1333       IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_MESSAGE_APP);
1334   SET_STRING("deleteConfirmationMessageExtension",
1335       IDS_APPS_DEVTOOL_DELETE_CONFIRMATION_MESSAGE_EXTENSION);
1336
1337 // Dialog when profile is managed.
1338   SET_STRING("managedProfileDialogCloseButton",
1339       IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_CLOSE_BUTTON);
1340   SET_STRING("managedProfileDialogTitle",
1341       IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_TITLE);
1342   SET_STRING("managedProfileDialogDescription",
1343       IDS_APPS_DEVTOOL_MANAGED_PROFILE_DIALOG_DESCRIPTION);
1344
1345   #undef   SET_STRING
1346   return true;
1347 }
1348
1349 DeveloperPrivateGetStringsFunction::~DeveloperPrivateGetStringsFunction() {}
1350
1351 bool DeveloperPrivateIsProfileManagedFunction::RunImpl() {
1352   SetResult(new base::FundamentalValue(GetProfile()->IsManaged()));
1353   return true;
1354 }
1355
1356 DeveloperPrivateIsProfileManagedFunction::
1357     ~DeveloperPrivateIsProfileManagedFunction() {
1358 }
1359
1360 } // namespace api
1361
1362 } // namespace extensions