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
;
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
;
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
;
116 icon_resource_id
= IDR_EXTENSION_DEFAULT_ICON
;
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();
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
;
158 BrowserContextKeyedAPIFactory
<DeveloperPrivateAPI
>*
159 DeveloperPrivateAPI::GetFactoryInstance() {
160 return g_factory
.Pointer();
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
) {
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(
209 const content::NotificationSource
& source
,
210 const content::NotificationDetails
& details
) {
211 const char* event_name
= NULL
;
212 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
214 CHECK(profile_
->IsSameProfile(profile
));
215 developer::EventData event_data
;
216 const Extension
* extension
= NULL
;
219 case chrome::NOTIFICATION_EXTENSION_INSTALLED
:
220 event_data
.event_type
= developer::EVENT_TYPE_INSTALLED
;
222 content::Details
<const InstalledExtensionInfo
>(details
)->extension
;
224 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED
:
225 event_data
.event_type
= developer::EVENT_TYPE_UNINSTALLED
;
226 extension
= content::Details
<const Extension
>(details
).ptr();
228 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
:
229 event_data
.event_type
= developer::EVENT_TYPE_LOADED
;
230 extension
= content::Details
<const Extension
>(details
).ptr();
232 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED
:
233 event_data
.event_type
= developer::EVENT_TYPE_UNLOADED
;
235 content::Details
<const UnloadedExtensionInfo
>(details
)->extension
;
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());
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());
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
267 if (extension_ids_
.find(error
->extension_id()) != extension_ids_
.end())
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
);
310 developer_private_event_router_
->RemoveExtensionId(details
.extension_id
);
316 bool DeveloperPrivateAutoUpdateFunction::RunSync() {
317 ExtensionUpdater
* updater
= GetExtensionUpdater(GetProfile());
319 updater
->CheckNow(ExtensionUpdater::CheckParams());
320 SetResult(new base::FundamentalValue(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();
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
;
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
;
359 if (Manifest::IsUnpackedLocation(item
.location())) {
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();
373 switch ((*iter
)->type()) {
374 case ExtensionError::MANIFEST_ERROR
:
375 info
->manifest_errors
.push_back(
376 make_linked_ptr((*iter
)->ToValue().release()));
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()));
389 case ExtensionError::NUM_ERROR_TYPES
:
396 for (std::vector
<extensions::InstallWarning
>::const_iterator it
=
397 item
.install_warnings().begin();
398 it
!= item
.install_warnings().end();
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()));
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
);
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()) {
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
,
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
)
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(),
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();
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(),
513 host
->GetRoutingID(),
514 process
->GetBrowserContext()->IsOffTheRecord(),
515 is_background_page
&& has_generated_background_page
));
519 linked_ptr
<developer::ItemInspectView
> DeveloperPrivateGetItemsInfoFunction::
520 constructInspectView(
522 int render_process_id
,
525 bool generated_background_page
) {
526 linked_ptr
<developer::ItemInspectView
> view(new developer::ItemInspectView());
528 if (url
.scheme() == kExtensionScheme
) {
530 view
->path
= url
.path().substr(1);
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
;
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(
553 process_manager
->GetRenderViewHostsForExtension(extension
->id()),
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
),
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(
580 process_manager
->GetRenderViewHostsForExtension(extension
->id()),
583 if (BackgroundInfo::HasLazyBackgroundPage(extension
) &&
584 extension_is_enabled
&&
585 !process_manager
->GetBackgroundHostForExtension(extension
->id())) {
586 result
.push_back(constructInspectView(
587 BackgroundInfo::GetBackgroundURL(extension
),
591 BackgroundInfo::HasGeneratedBackgroundPage(extension
)));
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())
639 item_list
.push_back(make_linked_ptr
<developer::ItemInfo
>(
641 item
, service
->IsExtensionEnabled(item
.id())).release()));
644 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE
,
645 base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread
,
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
);
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 : "
676 util::SetAllowFileAccess(extension
->id(), GetProfile(), params
->allow
);
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
);
698 util::SetIsIncognitoEnabled(extension
->id(), GetProfile(), params
->allow
);
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
);
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());
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_
);
730 // Released by InstallUIAbort or InstallUIProceed.
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
);
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_
);
759 void DeveloperPrivateShowPermissionsDialogFunction::InstallUIAbort(
760 bool user_initiated
) {
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
);
785 LOG(ERROR
) << "Did not find extension with id " << extension_id
;
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();
798 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(GetProfile());
799 if (prefs
->DidExtensionEscalatePermissions(extension_id
)) {
800 AppWindowRegistry
* registry
= AppWindowRegistry::Get(GetProfile());
802 AppWindow
* app_window
=
803 registry
->GetAppWindowForRenderViewHost(render_view_host());
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.
819 requirements_checker_
->Check(
821 base::Bind(&DeveloperPrivateEnableFunction::OnRequirementsChecked
,
822 this, extension_id
));
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);
831 service
->DisableExtension(extension_id
, Extension::DISABLE_USER_ACTION
);
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
);
843 ExtensionErrorReporter::GetInstance()->ReportError(
844 base::UTF8ToUTF16(JoinString(requirements_errors
, ' ')),
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
);
871 // Wakes up the background page and opens the inspect window.
872 devtools_util::InspectBackgroundPage(extension
, GetProfile());
877 base::StringToInt(options
.render_view_id
, &render_view_id
);
878 content::RenderViewHost
* host
= content::RenderViewHost::FromID(
879 render_process_id
, render_view_id
);
882 // This can happen if the host has gone away since the page was displayed.
886 DevToolsWindow::OpenDevToolsWindow(host
);
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.
898 bool result
= ShowPicker(
899 ui::SelectFileDialog::SELECT_FOLDER
,
900 DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
902 ui::SelectFileDialog::FileTypeInfo(),
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
);
916 void DeveloperPrivateLoadUnpackedFunction::FileSelectionCanceled() {
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());
929 AppWindow
* app_window
=
930 registry
->GetAppWindowForRenderViewHost(render_view_host());
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
939 new EntryPicker(this,
940 app_window
->web_contents(),
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
);
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
;
976 response
.status
= developer::PACK_STATUS_ERROR
;
978 results_
= developer::PackDirectory::Results::Create(response
);
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
);
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
);
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
);
1021 // Balanced in OnPackSuccess / OnPackFailure.
1024 pack_job_
= new PackExtensionJob(this, root_directory
, key_file
, flags
);
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.");
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.");
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
,
1085 project_base_path_
));
1087 // Check if the DirecotryEntry is the instance of chrome filesystem.
1088 if (!app_file_handler_util::ValidateFileEntryAndGetPath(filesystem_name
,
1091 &project_base_path_
,
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"));
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
,
1148 if (status
!= base::File::FILE_OK
) {
1149 DLOG(ERROR
) << "Error in copying files from sync filesystem.";
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
));
1169 std::string
origin_url(
1170 Extension::GetBaseURLFromExtensionId(extension_id()).spec());
1171 fileapi::FileSystemURL
url(sync_file_system::CreateSyncableFileSystemURL(
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(
1179 base::Bind(&DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback
,
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
,
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.");
1210 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE
,
1211 base::Bind(&DeveloperPrivateLoadDirectoryFunction::CopyFile
,
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.");
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
,
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;
1273 // Balanced by FileSelected / FileSelectionCanceled.
1275 bool result
= ShowPicker(
1277 DeveloperPrivateAPI::Get(GetProfile())->GetLastUnpackedDirectory(),
1284 void DeveloperPrivateChoosePathFunction::FileSelected(
1285 const base::FilePath
& path
) {
1286 SetResult(new base::StringValue(base::UTF16ToUTF8(path
.LossyDisplayName())));
1291 void DeveloperPrivateChoosePathFunction::FileSelectionCanceled() {
1292 SendResponse(false);
1296 DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {}
1298 bool DeveloperPrivateIsProfileManagedFunction::RunSync() {
1299 SetResult(new base::FundamentalValue(GetProfile()->IsManaged()));
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
)) {
1324 AddRef(); // Balanced in LaunchCallback().
1325 error_ui_util::HandleRequestFileSource(
1328 base::Bind(&DeveloperPrivateRequestFileSourceFunction::LaunchCallback
,
1329 base::Unretained(this)));
1333 void DeveloperPrivateRequestFileSourceFunction::LaunchCallback(
1334 const base::DictionaryValue
& results
) {
1335 SetResult(results
.DeepCopy());
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
)) {
1354 error_ui_util::HandleOpenDevTools(dict
);
1361 } // namespace extensions