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