Enable Enterprise enrollment on desktop builds.
[chromium-blink-merge.git] / chrome / browser / extensions / api / developer_private / developer_private_api.cc
blob5f9ce42c067715a70843a29d98ccac44d2a6897b
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.
5 #include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
7 #include "apps/app_load_service.h"
8 #include "apps/app_restore_service.h"
9 #include "apps/app_window.h"
10 #include "apps/app_window_registry.h"
11 #include "apps/saved_files_service.h"
12 #include "base/base64.h"
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/file_util.h"
16 #include "base/files/file_enumerator.h"
17 #include "base/i18n/file_util_icu.h"
18 #include "base/lazy_instance.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/devtools/devtools_window.h"
24 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
25 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
26 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
27 #include "chrome/browser/extensions/devtools_util.h"
28 #include "chrome/browser/extensions/extension_disabled_ui.h"
29 #include "chrome/browser/extensions/extension_error_reporter.h"
30 #include "chrome/browser/extensions/extension_service.h"
31 #include "chrome/browser/extensions/extension_util.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_error_ui_util.h"
40 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
41 #include "chrome/common/extensions/api/developer_private.h"
42 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
43 #include "chrome/common/extensions/manifest_url_handler.h"
44 #include "chrome/common/url_constants.h"
45 #include "content/public/browser/browser_thread.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/render_process_host.h"
48 #include "content/public/browser/render_view_host.h"
49 #include "content/public/browser/site_instance.h"
50 #include "content/public/browser/storage_partition.h"
51 #include "content/public/browser/web_contents.h"
52 #include "extensions/browser/extension_error.h"
53 #include "extensions/browser/extension_prefs.h"
54 #include "extensions/browser/extension_registry.h"
55 #include "extensions/browser/extension_system.h"
56 #include "extensions/browser/management_policy.h"
57 #include "extensions/browser/view_type_utils.h"
58 #include "extensions/common/constants.h"
59 #include "extensions/common/extension_resource.h"
60 #include "extensions/common/extension_set.h"
61 #include "extensions/common/install_warning.h"
62 #include "extensions/common/manifest.h"
63 #include "extensions/common/manifest_handlers/background_info.h"
64 #include "extensions/common/manifest_handlers/icons_handler.h"
65 #include "extensions/common/manifest_handlers/incognito_info.h"
66 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
67 #include "extensions/common/switches.h"
68 #include "grit/chromium_strings.h"
69 #include "grit/generated_resources.h"
70 #include "grit/theme_resources.h"
71 #include "net/base/net_util.h"
72 #include "ui/base/l10n/l10n_util.h"
73 #include "ui/base/resource/resource_bundle.h"
74 #include "ui/base/webui/web_ui_util.h"
75 #include "webkit/browser/fileapi/external_mount_points.h"
76 #include "webkit/browser/fileapi/file_system_context.h"
77 #include "webkit/browser/fileapi/file_system_operation.h"
78 #include "webkit/browser/fileapi/file_system_operation_runner.h"
79 #include "webkit/common/blob/shareable_file_reference.h"
81 using apps::AppWindow;
82 using apps::AppWindowRegistry;
83 using content::RenderViewHost;
85 namespace extensions {
87 namespace developer_private = api::developer_private;
89 namespace {
91 const base::FilePath::CharType kUnpackedAppsFolder[]
92 = FILE_PATH_LITERAL("apps_target");
94 ExtensionUpdater* GetExtensionUpdater(Profile* profile) {
95 return profile->GetExtensionService()->updater();
98 GURL GetImageURLFromData(std::string contents) {
99 std::string contents_base64;
100 base::Base64Encode(contents, &contents_base64);
102 // TODO(dvh): make use of content::kDataScheme. Filed as crbug/297301.
103 const char kDataURLPrefix[] = "data:image;base64,";
104 return GURL(kDataURLPrefix + contents_base64);
107 GURL GetDefaultImageURL(developer_private::ItemType type) {
108 int icon_resource_id;
109 switch (type) {
110 case developer::ITEM_TYPE_LEGACY_PACKAGED_APP:
111 case developer::ITEM_TYPE_HOSTED_APP:
112 case developer::ITEM_TYPE_PACKAGED_APP:
113 icon_resource_id = IDR_APP_DEFAULT_ICON;
114 break;
115 default:
116 icon_resource_id = IDR_EXTENSION_DEFAULT_ICON;
117 break;
120 return GetImageURLFromData(
121 ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
122 icon_resource_id, ui::SCALE_FACTOR_100P).as_string());
125 // TODO(dvh): This code should be refactored and moved to
126 // extensions::ImageLoader. Also a resize should be performed to avoid
127 // potential huge URLs: crbug/297298.
128 GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) {
129 std::string contents;
130 if (path.empty() || !base::ReadFileToString(path, &contents))
131 return GetDefaultImageURL(type);
133 return GetImageURLFromData(contents);
136 std::string GetExtensionID(const RenderViewHost* render_view_host) {
137 if (!render_view_host->GetSiteInstance())
138 return std::string();
140 return render_view_host->GetSiteInstance()->GetSiteURL().host();
143 } // namespace
145 namespace AllowFileAccess = api::developer_private::AllowFileAccess;
146 namespace AllowIncognito = api::developer_private::AllowIncognito;
147 namespace ChoosePath = api::developer_private::ChoosePath;
148 namespace Enable = api::developer_private::Enable;
149 namespace GetItemsInfo = api::developer_private::GetItemsInfo;
150 namespace Inspect = api::developer_private::Inspect;
151 namespace PackDirectory = api::developer_private::PackDirectory;
152 namespace Reload = api::developer_private::Reload;
154 static base::LazyInstance<BrowserContextKeyedAPIFactory<DeveloperPrivateAPI> >
155 g_factory = LAZY_INSTANCE_INITIALIZER;
157 // static
158 BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>*
159 DeveloperPrivateAPI::GetFactoryInstance() {
160 return g_factory.Pointer();
163 // static
164 DeveloperPrivateAPI* DeveloperPrivateAPI::Get(
165 content::BrowserContext* context) {
166 return GetFactoryInstance()->Get(context);
169 DeveloperPrivateAPI::DeveloperPrivateAPI(content::BrowserContext* context)
170 : profile_(Profile::FromBrowserContext(context)) {
171 RegisterNotifications();
174 DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile)
175 : profile_(profile) {
176 int types[] = {chrome::NOTIFICATION_EXTENSION_INSTALLED,
177 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
178 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
179 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
180 chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
181 chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED};
183 CHECK(registrar_.IsEmpty());
184 for (size_t i = 0; i < arraysize(types); ++i) {
185 registrar_.Add(this,
186 types[i],
187 content::Source<Profile>(profile_));
190 ErrorConsole::Get(profile)->AddObserver(this);
193 DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() {
194 ErrorConsole::Get(profile_)->RemoveObserver(this);
197 void DeveloperPrivateEventRouter::AddExtensionId(
198 const std::string& extension_id) {
199 extension_ids_.insert(extension_id);
202 void DeveloperPrivateEventRouter::RemoveExtensionId(
203 const std::string& extension_id) {
204 extension_ids_.erase(extension_id);
207 void DeveloperPrivateEventRouter::Observe(
208 int type,
209 const content::NotificationSource& source,
210 const content::NotificationDetails& details) {
211 const char* event_name = NULL;
212 Profile* profile = content::Source<Profile>(source).ptr();
213 CHECK(profile);
214 CHECK(profile_->IsSameProfile(profile));
215 developer::EventData event_data;
216 const Extension* extension = NULL;
218 switch (type) {
219 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
220 event_data.event_type = developer::EVENT_TYPE_INSTALLED;
221 extension =
222 content::Details<const InstalledExtensionInfo>(details)->extension;
223 break;
224 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
225 event_data.event_type = developer::EVENT_TYPE_UNINSTALLED;
226 extension = content::Details<const Extension>(details).ptr();
227 break;
228 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED:
229 event_data.event_type = developer::EVENT_TYPE_LOADED;
230 extension = content::Details<const Extension>(details).ptr();
231 break;
232 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED:
233 event_data.event_type = developer::EVENT_TYPE_UNLOADED;
234 extension =
235 content::Details<const UnloadedExtensionInfo>(details)->extension;
236 break;
237 case chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED:
238 event_data.event_type = developer::EVENT_TYPE_VIEW_UNREGISTERED;
239 event_data.item_id = GetExtensionID(
240 content::Details<const RenderViewHost>(details).ptr());
241 break;
242 case chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED:
243 event_data.event_type = developer::EVENT_TYPE_VIEW_REGISTERED;
244 event_data.item_id = GetExtensionID(
245 content::Details<const RenderViewHost>(details).ptr());
246 break;
247 default:
248 NOTREACHED();
249 return;
252 if (extension)
253 event_data.item_id = extension->id();
255 scoped_ptr<base::ListValue> args(new base::ListValue());
256 args->Append(event_data.ToValue().release());
258 event_name = developer_private::OnItemStateChanged::kEventName;
259 scoped_ptr<Event> event(new Event(event_name, args.Pass()));
260 EventRouter::Get(profile)->BroadcastEvent(event.Pass());
263 void DeveloperPrivateEventRouter::OnErrorAdded(const ExtensionError* error) {
264 // We don't want to handle errors thrown by extensions subscribed to these
265 // events (currently only the Apps Developer Tool), because doing so risks
266 // entering a loop.
267 if (extension_ids_.find(error->extension_id()) != extension_ids_.end())
268 return;
270 developer::EventData event_data;
271 event_data.event_type = developer::EVENT_TYPE_ERROR_ADDED;
272 event_data.item_id = error->extension_id();
274 scoped_ptr<base::ListValue> args(new base::ListValue);
275 args->Append(event_data.ToValue().release());
277 EventRouter::Get(profile_)->BroadcastEvent(scoped_ptr<Event>(new Event(
278 developer_private::OnItemStateChanged::kEventName, args.Pass())));
281 void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) {
282 last_unpacked_directory_ = path;
285 void DeveloperPrivateAPI::RegisterNotifications() {
286 EventRouter::Get(profile_)->RegisterObserver(
287 this, developer_private::OnItemStateChanged::kEventName);
290 DeveloperPrivateAPI::~DeveloperPrivateAPI() {}
292 void DeveloperPrivateAPI::Shutdown() {}
294 void DeveloperPrivateAPI::OnListenerAdded(
295 const EventListenerInfo& details) {
296 if (!developer_private_event_router_) {
297 developer_private_event_router_.reset(
298 new DeveloperPrivateEventRouter(profile_));
301 developer_private_event_router_->AddExtensionId(details.extension_id);
304 void DeveloperPrivateAPI::OnListenerRemoved(
305 const EventListenerInfo& details) {
306 if (!EventRouter::Get(profile_)->HasEventListener(
307 developer_private::OnItemStateChanged::kEventName)) {
308 developer_private_event_router_.reset(NULL);
309 } else {
310 developer_private_event_router_->RemoveExtensionId(details.extension_id);
314 namespace api {
316 bool DeveloperPrivateAutoUpdateFunction::RunSync() {
317 ExtensionUpdater* updater = GetExtensionUpdater(GetProfile());
318 if (updater)
319 updater->CheckNow(ExtensionUpdater::CheckParams());
320 SetResult(new base::FundamentalValue(true));
321 return true;
324 DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() {}
326 scoped_ptr<developer::ItemInfo>
327 DeveloperPrivateGetItemsInfoFunction::CreateItemInfo(const Extension& item,
328 bool item_is_enabled) {
329 scoped_ptr<developer::ItemInfo> info(new developer::ItemInfo());
331 ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
332 ExtensionService* service = system->extension_service();
333 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
335 info->id = item.id();
336 info->name = item.name();
337 info->enabled = service->IsExtensionEnabled(info->id);
338 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&item);
339 info->version = item.VersionString();
340 info->description = item.description();
342 if (item.is_app()) {
343 if (item.is_legacy_packaged_app())
344 info->type = developer::ITEM_TYPE_LEGACY_PACKAGED_APP;
345 else if (item.is_hosted_app())
346 info->type = developer::ITEM_TYPE_HOSTED_APP;
347 else if (item.is_platform_app())
348 info->type = developer::ITEM_TYPE_PACKAGED_APP;
349 else
350 NOTREACHED();
351 } else if (item.is_theme()) {
352 info->type = developer::ITEM_TYPE_THEME;
353 } else if (item.is_extension()) {
354 info->type = developer::ITEM_TYPE_EXTENSION;
355 } else {
356 NOTREACHED();
359 if (Manifest::IsUnpackedLocation(item.location())) {
360 info->path.reset(
361 new std::string(base::UTF16ToUTF8(item.path().LossyDisplayName())));
362 // If the ErrorConsole is enabled and the extension is unpacked, use the
363 // more detailed errors from the ErrorConsole. Otherwise, use the install
364 // warnings (using both is redundant).
365 ErrorConsole* error_console = ErrorConsole::Get(GetProfile());
366 if (error_console->IsEnabledForAppsDeveloperTools() &&
367 item.location() == Manifest::UNPACKED) {
368 const ErrorList& errors = error_console->GetErrorsForExtension(item.id());
369 if (!errors.empty()) {
370 for (ErrorList::const_iterator iter = errors.begin();
371 iter != errors.end();
372 ++iter) {
373 switch ((*iter)->type()) {
374 case ExtensionError::MANIFEST_ERROR:
375 info->manifest_errors.push_back(
376 make_linked_ptr((*iter)->ToValue().release()));
377 break;
378 case ExtensionError::RUNTIME_ERROR: {
379 const RuntimeError* error =
380 static_cast<const RuntimeError*>(*iter);
381 scoped_ptr<base::DictionaryValue> value = error->ToValue();
382 bool can_inspect = content::RenderViewHost::FromID(
383 error->render_process_id(),
384 error->render_view_id()) != NULL;
385 value->SetBoolean("canInspect", can_inspect);
386 info->runtime_errors.push_back(make_linked_ptr(value.release()));
387 break;
389 case ExtensionError::NUM_ERROR_TYPES:
390 NOTREACHED();
391 break;
395 } else {
396 for (std::vector<extensions::InstallWarning>::const_iterator it =
397 item.install_warnings().begin();
398 it != item.install_warnings().end();
399 ++it) {
400 scoped_ptr<developer::InstallWarning> warning(
401 new developer::InstallWarning);
402 warning->message = it->message;
403 info->install_warnings.push_back(make_linked_ptr(warning.release()));
408 info->incognito_enabled = util::IsIncognitoEnabled(item.id(), GetProfile());
409 info->wants_file_access = item.wants_file_access();
410 info->allow_file_access = util::AllowFileAccess(item.id(), GetProfile());
411 info->allow_reload = Manifest::IsUnpackedLocation(item.location());
412 info->is_unpacked = Manifest::IsUnpackedLocation(item.location());
413 info->terminated = registry->terminated_extensions().Contains(item.id());
414 info->allow_incognito = item.can_be_incognito_enabled();
416 info->homepage_url.reset(new std::string(
417 ManifestURL::GetHomepageURL(&item).spec()));
418 if (!ManifestURL::GetOptionsPage(&item).is_empty()) {
419 info->options_url.reset(
420 new std::string(ManifestURL::GetOptionsPage(&item).spec()));
423 if (!ManifestURL::GetUpdateURL(&item).is_empty()) {
424 info->update_url.reset(
425 new std::string(ManifestURL::GetUpdateURL(&item).spec()));
428 if (item.is_app()) {
429 info->app_launch_url.reset(new std::string(
430 extensions::AppLaunchInfo::GetFullLaunchURL(&item).spec()));
433 info->may_disable = system->management_policy()->
434 UserMayModifySettings(&item, NULL);
435 info->is_app = item.is_app();
436 info->views = GetInspectablePagesForExtension(&item, item_is_enabled);
438 return info.Pass();
441 void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread(
442 ItemInfoList item_list,
443 const std::map<std::string, ExtensionResource> idToIcon) {
444 for (ItemInfoList::iterator iter = item_list.begin();
445 iter != item_list.end(); ++iter) {
446 developer_private::ItemInfo* info = iter->get();
447 std::map<std::string, ExtensionResource>::const_iterator resource_ptr
448 = idToIcon.find(info->id);
449 if (resource_ptr != idToIcon.end()) {
450 info->icon_url =
451 ToDataURL(resource_ptr->second.GetFilePath(), info->type).spec();
455 results_ = developer::GetItemsInfo::Results::Create(item_list);
456 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
457 base::Bind(&DeveloperPrivateGetItemsInfoFunction::SendResponse,
458 this,
459 true));
462 void DeveloperPrivateGetItemsInfoFunction::
463 GetInspectablePagesForExtensionProcess(
464 const Extension* extension,
465 const std::set<content::RenderViewHost*>& views,
466 ItemInspectViewList* result) {
467 bool has_generated_background_page =
468 BackgroundInfo::HasGeneratedBackgroundPage(extension);
469 for (std::set<content::RenderViewHost*>::const_iterator iter = views.begin();
470 iter != views.end(); ++iter) {
471 content::RenderViewHost* host = *iter;
472 content::WebContents* web_contents =
473 content::WebContents::FromRenderViewHost(host);
474 ViewType host_type = GetViewType(web_contents);
475 if (VIEW_TYPE_EXTENSION_POPUP == host_type ||
476 VIEW_TYPE_EXTENSION_DIALOG == host_type)
477 continue;
479 content::RenderProcessHost* process = host->GetProcess();
480 bool is_background_page =
481 (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension));
482 result->push_back(constructInspectView(
483 web_contents->GetURL(),
484 process->GetID(),
485 host->GetRoutingID(),
486 process->GetBrowserContext()->IsOffTheRecord(),
487 is_background_page && has_generated_background_page));
491 void DeveloperPrivateGetItemsInfoFunction::GetAppWindowPagesForExtensionProfile(
492 const Extension* extension,
493 ItemInspectViewList* result) {
494 AppWindowRegistry* registry = AppWindowRegistry::Get(GetProfile());
495 if (!registry) return;
497 const AppWindowRegistry::AppWindowList windows =
498 registry->GetAppWindowsForApp(extension->id());
500 bool has_generated_background_page =
501 BackgroundInfo::HasGeneratedBackgroundPage(extension);
502 for (AppWindowRegistry::const_iterator it = windows.begin();
503 it != windows.end();
504 ++it) {
505 content::WebContents* web_contents = (*it)->web_contents();
506 RenderViewHost* host = web_contents->GetRenderViewHost();
507 content::RenderProcessHost* process = host->GetProcess();
508 bool is_background_page =
509 (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension));
510 result->push_back(constructInspectView(
511 web_contents->GetURL(),
512 process->GetID(),
513 host->GetRoutingID(),
514 process->GetBrowserContext()->IsOffTheRecord(),
515 is_background_page && has_generated_background_page));
519 linked_ptr<developer::ItemInspectView> DeveloperPrivateGetItemsInfoFunction::
520 constructInspectView(
521 const GURL& url,
522 int render_process_id,
523 int render_view_id,
524 bool incognito,
525 bool generated_background_page) {
526 linked_ptr<developer::ItemInspectView> view(new developer::ItemInspectView());
528 if (url.scheme() == kExtensionScheme) {
529 // No leading slash.
530 view->path = url.path().substr(1);
531 } else {
532 // For live pages, use the full URL.
533 view->path = url.spec();
536 view->render_process_id = render_process_id;
537 view->render_view_id = render_view_id;
538 view->incognito = incognito;
539 view->generated_background_page = generated_background_page;
540 return view;
543 ItemInspectViewList DeveloperPrivateGetItemsInfoFunction::
544 GetInspectablePagesForExtension(
545 const Extension* extension,
546 bool extension_is_enabled) {
547 ItemInspectViewList result;
548 // Get the extension process's active views.
549 extensions::ProcessManager* process_manager =
550 ExtensionSystem::Get(GetProfile())->process_manager();
551 GetInspectablePagesForExtensionProcess(
552 extension,
553 process_manager->GetRenderViewHostsForExtension(extension->id()),
554 &result);
556 // Get app window views.
557 GetAppWindowPagesForExtensionProfile(extension, &result);
559 // Include a link to start the lazy background page, if applicable.
560 if (BackgroundInfo::HasLazyBackgroundPage(extension) &&
561 extension_is_enabled &&
562 !process_manager->GetBackgroundHostForExtension(extension->id())) {
563 result.push_back(constructInspectView(
564 BackgroundInfo::GetBackgroundURL(extension),
567 false,
568 BackgroundInfo::HasGeneratedBackgroundPage(extension)));
571 ExtensionService* service = GetProfile()->GetExtensionService();
572 // Repeat for the incognito process, if applicable. Don't try to get
573 // app windows for incognito process.
574 if (service->profile()->HasOffTheRecordProfile() &&
575 IncognitoInfo::IsSplitMode(extension)) {
576 process_manager = ExtensionSystem::Get(
577 service->profile()->GetOffTheRecordProfile())->process_manager();
578 GetInspectablePagesForExtensionProcess(
579 extension,
580 process_manager->GetRenderViewHostsForExtension(extension->id()),
581 &result);
583 if (BackgroundInfo::HasLazyBackgroundPage(extension) &&
584 extension_is_enabled &&
585 !process_manager->GetBackgroundHostForExtension(extension->id())) {
586 result.push_back(constructInspectView(
587 BackgroundInfo::GetBackgroundURL(extension),
590 false,
591 BackgroundInfo::HasGeneratedBackgroundPage(extension)));
595 return result;
598 bool DeveloperPrivateGetItemsInfoFunction::RunImpl() {
599 scoped_ptr<developer::GetItemsInfo::Params> params(
600 developer::GetItemsInfo::Params::Create(*args_));
601 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
603 bool include_disabled = params->include_disabled;
604 bool include_terminated = params->include_terminated;
606 extensions::ExtensionSet items;
608 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
610 items.InsertAll(registry->enabled_extensions());
612 if (include_disabled) {
613 items.InsertAll(registry->disabled_extensions());
616 if (include_terminated) {
617 items.InsertAll(registry->terminated_extensions());
620 ExtensionService* service =
621 ExtensionSystem::Get(GetProfile())->extension_service();
622 std::map<std::string, ExtensionResource> id_to_icon;
623 ItemInfoList item_list;
625 for (extensions::ExtensionSet::const_iterator iter = items.begin();
626 iter != items.end(); ++iter) {
627 const Extension& item = *iter->get();
629 ExtensionResource item_resource =
630 IconsInfo::GetIconResource(&item,
631 extension_misc::EXTENSION_ICON_MEDIUM,
632 ExtensionIconSet::MATCH_BIGGER);
633 id_to_icon[item.id()] = item_resource;
635 // Don't show component extensions and invisible apps.
636 if (item.ShouldNotBeVisible())
637 continue;
639 item_list.push_back(make_linked_ptr<developer::ItemInfo>(
640 CreateItemInfo(
641 item, service->IsExtensionEnabled(item.id())).release()));
644 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
645 base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread,
646 this,
647 item_list,
648 id_to_icon));
650 return true;
653 DeveloperPrivateGetItemsInfoFunction::~DeveloperPrivateGetItemsInfoFunction() {}
655 bool DeveloperPrivateAllowFileAccessFunction::RunSync() {
656 scoped_ptr<AllowFileAccess::Params> params(
657 AllowFileAccess::Params::Create(*args_));
658 EXTENSION_FUNCTION_VALIDATE(params.get());
660 EXTENSION_FUNCTION_VALIDATE(user_gesture_);
662 ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
663 ManagementPolicy* management_policy = system->management_policy();
664 ExtensionService* service = GetProfile()->GetExtensionService();
665 const Extension* extension = service->GetInstalledExtension(params->item_id);
666 bool result = true;
668 if (!extension) {
669 result = false;
670 } else if (!management_policy->UserMayModifySettings(extension, NULL)) {
671 LOG(ERROR) << "Attempt to change allow file access of an extension that "
672 << "non-usermanagable was made. Extension id : "
673 << extension->id();
674 result = false;
675 } else {
676 util::SetAllowFileAccess(extension->id(), GetProfile(), params->allow);
677 result = true;
680 return result;
683 DeveloperPrivateAllowFileAccessFunction::
684 ~DeveloperPrivateAllowFileAccessFunction() {}
686 bool DeveloperPrivateAllowIncognitoFunction::RunSync() {
687 scoped_ptr<AllowIncognito::Params> params(
688 AllowIncognito::Params::Create(*args_));
689 EXTENSION_FUNCTION_VALIDATE(params.get());
691 ExtensionService* service = GetProfile()->GetExtensionService();
692 const Extension* extension = service->GetInstalledExtension(params->item_id);
693 bool result = true;
695 if (!extension)
696 result = false;
697 else
698 util::SetIsIncognitoEnabled(extension->id(), GetProfile(), params->allow);
700 return result;
703 DeveloperPrivateAllowIncognitoFunction::
704 ~DeveloperPrivateAllowIncognitoFunction() {}
706 bool DeveloperPrivateReloadFunction::RunSync() {
707 scoped_ptr<Reload::Params> params(Reload::Params::Create(*args_));
708 EXTENSION_FUNCTION_VALIDATE(params.get());
710 ExtensionService* service = GetProfile()->GetExtensionService();
711 CHECK(!params->item_id.empty());
712 service->ReloadExtension(params->item_id);
713 return true;
716 bool DeveloperPrivateShowPermissionsDialogFunction::RunSync() {
717 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &extension_id_));
718 ExtensionService* service = GetProfile()->GetExtensionService();
719 CHECK(!extension_id_.empty());
720 AppWindowRegistry* registry = AppWindowRegistry::Get(GetProfile());
721 DCHECK(registry);
722 AppWindow* app_window =
723 registry->GetAppWindowForRenderViewHost(render_view_host());
724 prompt_.reset(new ExtensionInstallPrompt(app_window->web_contents()));
725 const Extension* extension = service->GetInstalledExtension(extension_id_);
727 if (!extension)
728 return false;
730 // Released by InstallUIAbort or InstallUIProceed.
731 AddRef();
732 std::vector<base::FilePath> retained_file_paths;
733 if (extension->HasAPIPermission(extensions::APIPermission::kFileSystem)) {
734 std::vector<apps::SavedFileEntry> retained_file_entries =
735 apps::SavedFilesService::Get(GetProfile())
736 ->GetAllFileEntries(extension_id_);
737 for (size_t i = 0; i < retained_file_entries.size(); i++) {
738 retained_file_paths.push_back(retained_file_entries[i].path);
741 prompt_->ReviewPermissions(this, extension, retained_file_paths);
742 return true;
745 DeveloperPrivateReloadFunction::~DeveloperPrivateReloadFunction() {}
747 // This is called when the user clicks "Revoke File Access."
748 void DeveloperPrivateShowPermissionsDialogFunction::InstallUIProceed() {
749 apps::SavedFilesService::Get(GetProfile())
750 ->ClearQueue(GetProfile()->GetExtensionService()->GetExtensionById(
751 extension_id_, true));
752 if (apps::AppRestoreService::Get(GetProfile())
753 ->IsAppRestorable(extension_id_))
754 apps::AppLoadService::Get(GetProfile())->RestartApplication(extension_id_);
755 SendResponse(true);
756 Release();
759 void DeveloperPrivateShowPermissionsDialogFunction::InstallUIAbort(
760 bool user_initiated) {
761 SendResponse(true);
762 Release();
765 DeveloperPrivateShowPermissionsDialogFunction::
766 DeveloperPrivateShowPermissionsDialogFunction() {}
768 DeveloperPrivateShowPermissionsDialogFunction::
769 ~DeveloperPrivateShowPermissionsDialogFunction() {}
771 DeveloperPrivateEnableFunction::DeveloperPrivateEnableFunction() {}
773 bool DeveloperPrivateEnableFunction::RunSync() {
774 scoped_ptr<Enable::Params> params(Enable::Params::Create(*args_));
775 EXTENSION_FUNCTION_VALIDATE(params.get());
777 std::string extension_id = params->item_id;
779 ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
780 ManagementPolicy* policy = system->management_policy();
781 ExtensionService* service = GetProfile()->GetExtensionService();
783 const Extension* extension = service->GetInstalledExtension(extension_id);
784 if (!extension) {
785 LOG(ERROR) << "Did not find extension with id " << extension_id;
786 return false;
788 bool enable = params->enable;
789 if (!policy->UserMayModifySettings(extension, NULL) ||
790 (!enable && policy->MustRemainEnabled(extension, NULL)) ||
791 (enable && policy->MustRemainDisabled(extension, NULL, NULL))) {
792 LOG(ERROR) << "Attempt to change enable state denied by management policy. "
793 << "Extension id: " << extension_id.c_str();
794 return false;
797 if (enable) {
798 ExtensionPrefs* prefs = ExtensionPrefs::Get(GetProfile());
799 if (prefs->DidExtensionEscalatePermissions(extension_id)) {
800 AppWindowRegistry* registry = AppWindowRegistry::Get(GetProfile());
801 CHECK(registry);
802 AppWindow* app_window =
803 registry->GetAppWindowForRenderViewHost(render_view_host());
804 if (!app_window) {
805 return false;
808 ShowExtensionDisabledDialog(
809 service, app_window->web_contents(), extension);
810 } else if ((prefs->GetDisableReasons(extension_id) &
811 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) &&
812 !requirements_checker_.get()) {
813 // Recheck the requirements.
814 scoped_refptr<const Extension> extension =
815 service->GetExtensionById(extension_id, true);
816 requirements_checker_.reset(new RequirementsChecker);
817 // Released by OnRequirementsChecked.
818 AddRef();
819 requirements_checker_->Check(
820 extension,
821 base::Bind(&DeveloperPrivateEnableFunction::OnRequirementsChecked,
822 this, extension_id));
823 } else {
824 service->EnableExtension(extension_id);
826 // Make sure any browser action contained within it is not hidden.
827 ExtensionActionAPI::SetBrowserActionVisibility(
828 prefs, extension->id(), true);
830 } else {
831 service->DisableExtension(extension_id, Extension::DISABLE_USER_ACTION);
833 return true;
836 void DeveloperPrivateEnableFunction::OnRequirementsChecked(
837 std::string extension_id,
838 std::vector<std::string> requirements_errors) {
839 if (requirements_errors.empty()) {
840 ExtensionService* service = GetProfile()->GetExtensionService();
841 service->EnableExtension(extension_id);
842 } else {
843 ExtensionErrorReporter::GetInstance()->ReportError(
844 base::UTF8ToUTF16(JoinString(requirements_errors, ' ')),
845 true); // Be noisy.
847 Release();
850 DeveloperPrivateEnableFunction::~DeveloperPrivateEnableFunction() {}
852 bool DeveloperPrivateInspectFunction::RunSync() {
853 scoped_ptr<developer::Inspect::Params> params(
854 developer::Inspect::Params::Create(*args_));
855 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
856 const developer::InspectOptions& options = params->options;
858 int render_process_id;
859 base::StringToInt(options.render_process_id, &render_process_id);
861 if (render_process_id == -1) {
862 // This is a lazy background page. Identify if it is a normal
863 // or incognito background page.
864 ExtensionService* service = GetProfile()->GetExtensionService();
865 if (options.incognito)
866 service = ExtensionSystem::Get(
867 service->profile()->GetOffTheRecordProfile())->extension_service();
868 const Extension* extension = service->extensions()->GetByID(
869 options.extension_id);
870 DCHECK(extension);
871 // Wakes up the background page and opens the inspect window.
872 devtools_util::InspectBackgroundPage(extension, GetProfile());
873 return false;
876 int render_view_id;
877 base::StringToInt(options.render_view_id, &render_view_id);
878 content::RenderViewHost* host = content::RenderViewHost::FromID(
879 render_process_id, render_view_id);
881 if (!host) {
882 // This can happen if the host has gone away since the page was displayed.
883 return false;
886 DevToolsWindow::OpenDevToolsWindow(host);
887 return true;
890 DeveloperPrivateInspectFunction::~DeveloperPrivateInspectFunction() {}
892 bool DeveloperPrivateLoadUnpackedFunction::RunImpl() {
893 base::string16 select_title =
894 l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
896 // Balanced in FileSelected / FileSelectionCanceled.
897 AddRef();
898 bool result = ShowPicker(
899 ui::SelectFileDialog::SELECT_FOLDER,
900 DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
901 select_title,
902 ui::SelectFileDialog::FileTypeInfo(),
904 return result;
907 void DeveloperPrivateLoadUnpackedFunction::FileSelected(
908 const base::FilePath& path) {
909 ExtensionService* service = GetProfile()->GetExtensionService();
910 UnpackedInstaller::Create(service)->Load(path);
911 DeveloperPrivateAPI::Get(GetProfile())->SetLastUnpackedDirectory(path);
912 SendResponse(true);
913 Release();
916 void DeveloperPrivateLoadUnpackedFunction::FileSelectionCanceled() {
917 SendResponse(false);
918 Release();
921 bool DeveloperPrivateChooseEntryFunction::ShowPicker(
922 ui::SelectFileDialog::Type picker_type,
923 const base::FilePath& last_directory,
924 const base::string16& select_title,
925 const ui::SelectFileDialog::FileTypeInfo& info,
926 int file_type_index) {
927 AppWindowRegistry* registry = AppWindowRegistry::Get(GetProfile());
928 DCHECK(registry);
929 AppWindow* app_window =
930 registry->GetAppWindowForRenderViewHost(render_view_host());
931 if (!app_window) {
932 return false;
935 // The entry picker will hold a reference to this function instance,
936 // and subsequent sending of the function response) until the user has
937 // selected a file or cancelled the picker. At that point, the picker will
938 // delete itself.
939 new EntryPicker(this,
940 app_window->web_contents(),
941 picker_type,
942 last_directory,
943 select_title,
944 info,
945 file_type_index);
946 return true;
949 bool DeveloperPrivateChooseEntryFunction::RunImpl() { return false; }
951 DeveloperPrivateChooseEntryFunction::~DeveloperPrivateChooseEntryFunction() {}
953 void DeveloperPrivatePackDirectoryFunction::OnPackSuccess(
954 const base::FilePath& crx_file,
955 const base::FilePath& pem_file) {
956 developer::PackDirectoryResponse response;
957 response.message = base::UTF16ToUTF8(
958 PackExtensionJob::StandardSuccessMessage(crx_file, pem_file));
959 response.status = developer::PACK_STATUS_SUCCESS;
960 results_ = developer::PackDirectory::Results::Create(response);
961 SendResponse(true);
962 Release();
965 void DeveloperPrivatePackDirectoryFunction::OnPackFailure(
966 const std::string& error,
967 ExtensionCreator::ErrorType error_type) {
968 developer::PackDirectoryResponse response;
969 response.message = error;
970 if (error_type == ExtensionCreator::kCRXExists) {
971 response.item_path = item_path_str_;
972 response.pem_path = key_path_str_;
973 response.override_flags = ExtensionCreator::kOverwriteCRX;
974 response.status = developer::PACK_STATUS_WARNING;
975 } else {
976 response.status = developer::PACK_STATUS_ERROR;
978 results_ = developer::PackDirectory::Results::Create(response);
979 SendResponse(true);
980 Release();
983 bool DeveloperPrivatePackDirectoryFunction::RunImpl() {
984 scoped_ptr<PackDirectory::Params> params(
985 PackDirectory::Params::Create(*args_));
986 EXTENSION_FUNCTION_VALIDATE(params.get());
988 int flags = params->flags;
989 item_path_str_ = params->path;
990 key_path_str_ = params->private_key_path;
992 base::FilePath root_directory =
993 base::FilePath::FromUTF8Unsafe(item_path_str_);
995 base::FilePath key_file = base::FilePath::FromUTF8Unsafe(key_path_str_);
997 developer::PackDirectoryResponse response;
998 if (root_directory.empty()) {
999 if (item_path_str_.empty())
1000 response.message = l10n_util::GetStringUTF8(
1001 IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_REQUIRED);
1002 else
1003 response.message = l10n_util::GetStringUTF8(
1004 IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID);
1006 response.status = developer::PACK_STATUS_ERROR;
1007 results_ = developer::PackDirectory::Results::Create(response);
1008 SendResponse(true);
1009 return true;
1012 if (!key_path_str_.empty() && key_file.empty()) {
1013 response.message = l10n_util::GetStringUTF8(
1014 IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID);
1015 response.status = developer::PACK_STATUS_ERROR;
1016 results_ = developer::PackDirectory::Results::Create(response);
1017 SendResponse(true);
1018 return true;
1021 // Balanced in OnPackSuccess / OnPackFailure.
1022 AddRef();
1024 pack_job_ = new PackExtensionJob(this, root_directory, key_file, flags);
1025 pack_job_->Start();
1026 return true;
1029 DeveloperPrivatePackDirectoryFunction::DeveloperPrivatePackDirectoryFunction()
1032 DeveloperPrivatePackDirectoryFunction::~DeveloperPrivatePackDirectoryFunction()
1035 DeveloperPrivateLoadUnpackedFunction::~DeveloperPrivateLoadUnpackedFunction() {}
1037 bool DeveloperPrivateLoadDirectoryFunction::RunImpl() {
1038 // TODO(grv) : add unittests.
1039 std::string directory_url_str;
1040 std::string filesystem_name;
1041 std::string filesystem_path;
1043 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
1044 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
1045 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &directory_url_str));
1047 // Directory url is non empty only for syncfilesystem.
1048 if (directory_url_str != "") {
1049 context_ = content::BrowserContext::GetStoragePartition(
1050 GetProfile(), render_view_host()->GetSiteInstance())
1051 ->GetFileSystemContext();
1053 fileapi::FileSystemURL directory_url =
1054 context_->CrackURL(GURL(directory_url_str));
1056 if (!directory_url.is_valid() && directory_url.type() ==
1057 fileapi::kFileSystemTypeSyncable) {
1058 SetError("DirectoryEntry of unsupported filesystem.");
1059 return false;
1062 size_t pos = 0;
1063 // Parse the project directory name from the project url. The project url is
1064 // expected to have project name as the suffix.
1065 if ((pos = directory_url_str.rfind("/")) == std::string::npos) {
1066 SetError("Invalid Directory entry.");
1067 return false;
1070 std::string project_name;
1071 project_name = directory_url_str.substr(pos + 1);
1072 project_base_url_ = directory_url_str.substr(0, pos + 1);
1074 base::FilePath project_path(GetProfile()->GetPath());
1075 project_path = project_path.Append(kUnpackedAppsFolder);
1076 project_path = project_path.Append(
1077 base::FilePath::FromUTF8Unsafe(project_name));
1079 project_base_path_ = project_path;
1081 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
1082 base::Bind(&DeveloperPrivateLoadDirectoryFunction::
1083 ClearExistingDirectoryContent,
1084 this,
1085 project_base_path_));
1086 } else {
1087 // Check if the DirecotryEntry is the instance of chrome filesystem.
1088 if (!app_file_handler_util::ValidateFileEntryAndGetPath(filesystem_name,
1089 filesystem_path,
1090 render_view_host_,
1091 &project_base_path_,
1092 &error_))
1093 return false;
1095 Load();
1098 return true;
1101 void DeveloperPrivateLoadDirectoryFunction::Load() {
1102 ExtensionService* service = GetProfile()->GetExtensionService();
1103 UnpackedInstaller::Create(service)->Load(project_base_path_);
1105 // TODO(grv) : The unpacked installer should fire an event when complete
1106 // and return the extension_id.
1107 SetResult(new base::StringValue("-1"));
1108 SendResponse(true);
1111 void DeveloperPrivateLoadDirectoryFunction::ClearExistingDirectoryContent(
1112 const base::FilePath& project_path) {
1114 // Clear the project directory before copying new files.
1115 base::DeleteFile(project_path, true/*recursive*/);
1117 pending_copy_operations_count_ = 1;
1119 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
1120 base::Bind(&DeveloperPrivateLoadDirectoryFunction::
1121 ReadSyncFileSystemDirectory,
1122 this, project_path, project_path.BaseName()));
1125 void DeveloperPrivateLoadDirectoryFunction::ReadSyncFileSystemDirectory(
1126 const base::FilePath& project_path,
1127 const base::FilePath& destination_path) {
1129 current_path_ = context_->CrackURL(GURL(project_base_url_)).path();
1131 GURL project_url = GURL(project_base_url_ + destination_path.MaybeAsASCII());
1133 fileapi::FileSystemURL url = context_->CrackURL(project_url);
1135 context_->operation_runner()->ReadDirectory(
1136 url, base::Bind(&DeveloperPrivateLoadDirectoryFunction::
1137 ReadSyncFileSystemDirectoryCb,
1138 this, project_path, destination_path));
1141 void DeveloperPrivateLoadDirectoryFunction::ReadSyncFileSystemDirectoryCb(
1142 const base::FilePath& project_path,
1143 const base::FilePath& destination_path,
1144 base::File::Error status,
1145 const fileapi::FileSystemOperation::FileEntryList& file_list,
1146 bool has_more) {
1148 if (status != base::File::FILE_OK) {
1149 DLOG(ERROR) << "Error in copying files from sync filesystem.";
1150 return;
1153 // We add 1 to the pending copy operations for both files and directories. We
1154 // release the directory copy operation once all the files under the directory
1155 // are added for copying. We do that to ensure that pendingCopyOperationsCount
1156 // does not become zero before all copy operations are finished.
1157 // In case the directory happens to be executing the last copy operation it
1158 // will call SendResponse to send the response to the API. The pending copy
1159 // operations of files are released by the CopyFile function.
1160 pending_copy_operations_count_ += file_list.size();
1162 for (size_t i = 0; i < file_list.size(); ++i) {
1163 if (file_list[i].is_directory) {
1164 ReadSyncFileSystemDirectory(project_path.Append(file_list[i].name),
1165 destination_path.Append(file_list[i].name));
1166 continue;
1169 std::string origin_url(
1170 Extension::GetBaseURLFromExtensionId(extension_id()).spec());
1171 fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
1172 GURL(origin_url),
1173 current_path_.Append(destination_path.Append(file_list[i].name))));
1174 base::FilePath target_path = project_path;
1175 target_path = target_path.Append(file_list[i].name);
1177 context_->operation_runner()->CreateSnapshotFile(
1178 url,
1179 base::Bind(&DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback,
1180 this,
1181 target_path));
1184 if (!has_more) {
1185 // Directory copy operation released here.
1186 pending_copy_operations_count_--;
1188 if (!pending_copy_operations_count_) {
1189 content::BrowserThread::PostTask(
1190 content::BrowserThread::UI, FROM_HERE,
1191 base::Bind(&DeveloperPrivateLoadDirectoryFunction::SendResponse,
1192 this,
1193 success_));
1198 void DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback(
1199 const base::FilePath& target_path,
1200 base::File::Error result,
1201 const base::File::Info& file_info,
1202 const base::FilePath& src_path,
1203 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
1204 if (result != base::File::FILE_OK) {
1205 SetError("Error in copying files from sync filesystem.");
1206 success_ = false;
1207 return;
1210 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
1211 base::Bind(&DeveloperPrivateLoadDirectoryFunction::CopyFile,
1212 this,
1213 src_path,
1214 target_path));
1217 void DeveloperPrivateLoadDirectoryFunction::CopyFile(
1218 const base::FilePath& src_path,
1219 const base::FilePath& target_path) {
1220 if (!base::CreateDirectory(target_path.DirName())) {
1221 SetError("Error in copying files from sync filesystem.");
1222 success_ = false;
1225 if (success_)
1226 base::CopyFile(src_path, target_path);
1228 CHECK(pending_copy_operations_count_ > 0);
1229 pending_copy_operations_count_--;
1231 if (!pending_copy_operations_count_) {
1232 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
1233 base::Bind(&DeveloperPrivateLoadDirectoryFunction::Load,
1234 this));
1238 DeveloperPrivateLoadDirectoryFunction::DeveloperPrivateLoadDirectoryFunction()
1239 : pending_copy_operations_count_(0), success_(true) {}
1241 DeveloperPrivateLoadDirectoryFunction::~DeveloperPrivateLoadDirectoryFunction()
1244 bool DeveloperPrivateChoosePathFunction::RunImpl() {
1245 scoped_ptr<developer::ChoosePath::Params> params(
1246 developer::ChoosePath::Params::Create(*args_));
1247 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
1249 ui::SelectFileDialog::Type type = ui::SelectFileDialog::SELECT_FOLDER;
1250 ui::SelectFileDialog::FileTypeInfo info;
1251 if (params->select_type == developer::SELECT_TYPE_FILE) {
1252 type = ui::SelectFileDialog::SELECT_OPEN_FILE;
1254 base::string16 select_title;
1256 int file_type_index = 0;
1257 if (params->file_type == developer::FILE_TYPE_LOAD) {
1258 select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
1259 } else if (params->file_type == developer::FILE_TYPE_PEM) {
1260 select_title = l10n_util::GetStringUTF16(
1261 IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
1262 info.extensions.push_back(std::vector<base::FilePath::StringType>());
1263 info.extensions.front().push_back(FILE_PATH_LITERAL("pem"));
1264 info.extension_description_overrides.push_back(
1265 l10n_util::GetStringUTF16(
1266 IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
1267 info.include_all_files = true;
1268 file_type_index = 1;
1269 } else {
1270 NOTREACHED();
1273 // Balanced by FileSelected / FileSelectionCanceled.
1274 AddRef();
1275 bool result = ShowPicker(
1276 type,
1277 DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
1278 select_title,
1279 info,
1280 file_type_index);
1281 return result;
1284 void DeveloperPrivateChoosePathFunction::FileSelected(
1285 const base::FilePath& path) {
1286 SetResult(new base::StringValue(base::UTF16ToUTF8(path.LossyDisplayName())));
1287 SendResponse(true);
1288 Release();
1291 void DeveloperPrivateChoosePathFunction::FileSelectionCanceled() {
1292 SendResponse(false);
1293 Release();
1296 DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {}
1298 bool DeveloperPrivateIsProfileManagedFunction::RunSync() {
1299 SetResult(new base::FundamentalValue(GetProfile()->IsManaged()));
1300 return true;
1303 DeveloperPrivateIsProfileManagedFunction::
1304 ~DeveloperPrivateIsProfileManagedFunction() {
1307 DeveloperPrivateRequestFileSourceFunction::
1308 DeveloperPrivateRequestFileSourceFunction() {}
1310 DeveloperPrivateRequestFileSourceFunction::
1311 ~DeveloperPrivateRequestFileSourceFunction() {}
1313 bool DeveloperPrivateRequestFileSourceFunction::RunImpl() {
1314 scoped_ptr<developer::RequestFileSource::Params> params(
1315 developer::RequestFileSource::Params::Create(*args_));
1316 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
1318 base::DictionaryValue* dict = NULL;
1319 if (!params->dict->GetAsDictionary(&dict)) {
1320 NOTREACHED();
1321 return false;
1324 AddRef(); // Balanced in LaunchCallback().
1325 error_ui_util::HandleRequestFileSource(
1326 dict,
1327 GetProfile(),
1328 base::Bind(&DeveloperPrivateRequestFileSourceFunction::LaunchCallback,
1329 base::Unretained(this)));
1330 return true;
1333 void DeveloperPrivateRequestFileSourceFunction::LaunchCallback(
1334 const base::DictionaryValue& results) {
1335 SetResult(results.DeepCopy());
1336 SendResponse(true);
1337 Release(); // Balanced in RunImpl().
1340 DeveloperPrivateOpenDevToolsFunction::DeveloperPrivateOpenDevToolsFunction() {}
1341 DeveloperPrivateOpenDevToolsFunction::~DeveloperPrivateOpenDevToolsFunction() {}
1343 bool DeveloperPrivateOpenDevToolsFunction::RunImpl() {
1344 scoped_ptr<developer::OpenDevTools::Params> params(
1345 developer::OpenDevTools::Params::Create(*args_));
1346 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
1348 base::DictionaryValue* dict = NULL;
1349 if (!params->dict->GetAsDictionary(&dict)) {
1350 NOTREACHED();
1351 return false;
1354 error_ui_util::HandleOpenDevTools(dict);
1356 return true;
1359 } // namespace api
1361 } // namespace extensions