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