Add chrome.i18nPrivate.getStrings for translations in component extensions

This common API will allow the deduplication of several existing
getStrings APIs. This CL also replaces the existing
chrome.identityPrivate.getStrings API with the common API.

BUG=529546
NOPRESUBMIT=true
(Disabling to allow a rename in the histogram enum)

Review URL: https://codereview.chromium.org/1319293004

Cr-Commit-Position: refs/heads/master@{#349341}
diff --git a/chrome/browser/extensions/api/identity_private/identity_private_api.cc b/chrome/browser/extensions/api/identity_private/identity_private_api.cc
deleted file mode 100644
index 5c0e7f1..0000000
--- a/chrome/browser/extensions/api/identity_private/identity_private_api.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/identity_private/identity_private_api.h"
-
-#include <string>
-
-#include "base/values.h"
-#include "chrome/grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace extensions {
-
-IdentityPrivateGetStringsFunction::IdentityPrivateGetStringsFunction() {}
-
-IdentityPrivateGetStringsFunction::~IdentityPrivateGetStringsFunction() {}
-
-bool IdentityPrivateGetStringsFunction::RunSync() {
-  base::DictionaryValue* dict = new base::DictionaryValue;
-  SetResult(dict);
-
-  dict->SetString(
-      "window-title",
-      l10n_util::GetStringUTF16(IDS_EXTENSION_CONFIRM_PERMISSIONS));
-
-  return true;
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/identity_private/identity_private_api.h b/chrome/browser/extensions/api/identity_private/identity_private_api.h
deleted file mode 100644
index 893f580..0000000
--- a/chrome/browser/extensions/api/identity_private/identity_private_api.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_PRIVATE_IDENTITY_PRIVATE_API_H_
-#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_PRIVATE_IDENTITY_PRIVATE_API_H_
-
-#include "extensions/browser/extension_function.h"
-
-namespace extensions {
-
-class IdentityPrivateGetStringsFunction : public SyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("identityPrivate.getStrings",
-                             IDENTITYPRIVATE_GETSTRINGS);
-  IdentityPrivateGetStringsFunction();
-
- protected:
-  ~IdentityPrivateGetStringsFunction() override;
-
-  // ExtensionFunction:
-  bool RunSync() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(IdentityPrivateGetStringsFunction);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_PRIVATE_IDENTITY_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/resources_private/OWNERS b/chrome/browser/extensions/api/resources_private/OWNERS
new file mode 100644
index 0000000..b0baa268
--- /dev/null
+++ b/chrome/browser/extensions/api/resources_private/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_api.cc b/chrome/browser/extensions/api/resources_private/resources_private_api.cc
new file mode 100644
index 0000000..a4b720e
--- /dev/null
+++ b/chrome/browser/extensions/api/resources_private/resources_private_api.cc
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/resources_private/resources_private_api.h"
+
+#include <string>
+
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/extensions/api/resources_private.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+
+// To add a new component to this API, simply:
+// 1. Add your component to the Component enum in
+//      chrome/common/extensions/api/resources_private.idl
+// 2. Create an AddStringsForMyComponent(base::DictionaryValue * dict) method.
+// 3. Tie in that method to the switch statement in Run()
+
+namespace extensions {
+
+namespace {
+
+void AddStringsForIdentity(base::DictionaryValue* dict) {
+  dict->SetString("window-title",
+                  l10n_util::GetStringUTF16(IDS_EXTENSION_CONFIRM_PERMISSIONS));
+}
+
+}  // namespace
+
+namespace get_strings = api::resources_private::GetStrings;
+
+ResourcesPrivateGetStringsFunction::ResourcesPrivateGetStringsFunction() {}
+
+ResourcesPrivateGetStringsFunction::~ResourcesPrivateGetStringsFunction() {}
+
+ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
+  scoped_ptr<get_strings::Params> params(get_strings::Params::Create(*args_));
+  scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+
+  api::resources_private::Component component = params->component;
+
+  switch (component) {
+    case api::resources_private::COMPONENT_IDENTITY:
+      AddStringsForIdentity(dict.get());
+      break;
+    case api::resources_private::COMPONENT_NONE:
+      NOTREACHED();
+  }
+
+  const std::string& app_locale = g_browser_process->GetApplicationLocale();
+  webui::SetLoadTimeDataDefaults(app_locale, dict.get());
+
+  return RespondNow(OneArgument(dict.Pass()));
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_api.h b/chrome/browser/extensions/api/resources_private/resources_private_api.h
new file mode 100644
index 0000000..5cd94e8
--- /dev/null
+++ b/chrome/browser/extensions/api/resources_private/resources_private_api.h
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
+
+#include "extensions/browser/extension_function.h"
+
+namespace extensions {
+
+class ResourcesPrivateGetStringsFunction : public UIThreadExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("resourcesPrivate.getStrings",
+                             RESOURCESPRIVATE_GETSTRINGS);
+  ResourcesPrivateGetStringsFunction();
+
+ protected:
+  ~ResourcesPrivateGetStringsFunction() override;
+
+  // Override from ExtensionFunction:
+  ExtensionFunction::ResponseAction Run() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ResourcesPrivateGetStringsFunction);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_RESOURCES_PRIVATE_RESOURCES_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc b/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc
new file mode 100644
index 0000000..9647f7e
--- /dev/null
+++ b/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_apitest.h"
+
+class ResourcesPrivateApiTest : public ExtensionApiTest {
+ public:
+  ResourcesPrivateApiTest() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ResourcesPrivateApiTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ResourcesPrivateApiTest, GetStrings) {
+  ASSERT_TRUE(RunComponentExtensionTest("resources_private/get_strings"));
+}
diff --git a/chrome/browser/extensions/api/identity_private/OWNERS b/chrome/browser/resources/identity_scope_approval_dialog/OWNERS
similarity index 100%
rename from chrome/browser/extensions/api/identity_private/OWNERS
rename to chrome/browser/resources/identity_scope_approval_dialog/OWNERS
diff --git a/chrome/browser/resources/identity_scope_approval_dialog/manifest.json b/chrome/browser/resources/identity_scope_approval_dialog/manifest.json
index c3fd839..4b24695 100644
--- a/chrome/browser/resources/identity_scope_approval_dialog/manifest.json
+++ b/chrome/browser/resources/identity_scope_approval_dialog/manifest.json
@@ -9,6 +9,7 @@
   "permissions": [
     "chrome://theme/",
     "identityPrivate",
+    "resourcesPrivate",
     "webview"
   ],
 
diff --git a/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js b/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js
index b2e5feb..4d86772e 100644
--- a/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js
+++ b/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js
@@ -47,7 +47,7 @@
     window.close();
   };
 
-  chrome.identityPrivate.getStrings(function(strings) {
+  chrome.resourcesPrivate.getStrings('identity', function(strings) {
     document.title = strings['window-title'];
   });
 });
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index b8b59bf..b1ee111 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -305,8 +305,6 @@
       'browser/extensions/api/identity/identity_signin_flow.h',
       'browser/extensions/api/identity/web_auth_flow.cc',
       'browser/extensions/api/identity/web_auth_flow.h',
-      'browser/extensions/api/identity_private/identity_private_api.cc',
-      'browser/extensions/api/identity_private/identity_private_api.h',
       'browser/extensions/api/idltest/idltest_api.cc',
       'browser/extensions/api/idltest/idltest_api.h',
       'browser/extensions/api/image_writer_private/destroy_partitions_operation.cc',
@@ -441,6 +439,8 @@
       'browser/extensions/api/proxy/proxy_api_helpers.h',
       'browser/extensions/api/reading_list_private/reading_list_private_api.cc',
       'browser/extensions/api/reading_list_private/reading_list_private_api.h',
+      'browser/extensions/api/resources_private/resources_private_api.cc',
+      'browser/extensions/api/resources_private/resources_private_api.h',
       'browser/extensions/api/runtime/chrome_runtime_api_delegate.cc',
       'browser/extensions/api/runtime/chrome_runtime_api_delegate.h',
       'browser/extensions/api/screenlock_private/screenlock_private_api.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 8e63fdc8..5cc396cb 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -191,6 +191,7 @@
       'browser/extensions/api/processes/processes_apitest.cc',
       'browser/extensions/api/proxy/proxy_apitest.cc',
       'browser/extensions/api/reading_list_private/reading_list_private_apitest.cc',
+      'browser/extensions/api/resources_private/resources_private_apitest.cc',
       'browser/extensions/api/screenlock_private/screenlock_private_apitest.cc',
       'browser/extensions/api/search_engines_private/search_engines_private_apitest.cc',
       'browser/extensions/api/sessions/sessions_apitest.cc',
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index ad7b36c8..a06156d 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -691,6 +691,10 @@
     "dependencies": ["permission:readingListPrivate"],
     "contexts": ["blessed_extension"]
   },
+  "resourcesPrivate": {
+    "dependencies": ["permission:resourcesPrivate"],
+    "contexts": ["blessed_extension"]
+  },
   "rtcPrivate": {
     "dependencies": ["permission:rtcPrivate"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 73e179d..74f16ea 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -887,6 +887,13 @@
       "3F65507A3B39259B38C8173C6FFA3D12DF64CCE9"  // http://crbug.com/371562
     ]
   },
+  "resourcesPrivate": {
+    "channel": "stable",
+    "extension_types": [
+      "extension", "legacy_packaged_app", "platform_app"
+    ],
+    "location": "component"
+  },
   "rtcPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app"],
diff --git a/chrome/common/extensions/api/identity_private.idl b/chrome/common/extensions/api/identity_private.idl
index 4017caa..33856ef 100644
--- a/chrome/common/extensions/api/identity_private.idl
+++ b/chrome/common/extensions/api/identity_private.idl
@@ -5,15 +5,6 @@
 // identityPrivate.
 namespace identityPrivate {
 
-  callback GetStringsCallback = void (object result);
-
-  interface Functions {
-    // Gets localized strings required to render the API.
-    //
-    // |callback| : Called with a dictionary mapping names to resource strings.
-    static void getStrings(GetStringsCallback callback);
-  };
-
   interface Events {
     // Fired when a web flow dialog should be displayed.
     static void onWebFlowRequest(DOMString key, DOMString url, DOMString mode);
diff --git a/chrome/common/extensions/api/resources_private.idl b/chrome/common/extensions/api/resources_private.idl
new file mode 100644
index 0000000..10177af
--- /dev/null
+++ b/chrome/common/extensions/api/resources_private.idl
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// resourcesPrivate.
+namespace resourcesPrivate {
+  enum Component { identity };
+
+  callback GetStringsCallback = void (object result);
+
+  interface Functions {
+    // Gets localized strings for a component extension. Includes default WebUI
+    // loadTimeData values for text and language settings (fontsize, fontfamily,
+    // language, textdirection). See
+    // chrome/browser/extensions/api/resources_private/resources_private_api.cc
+    // for instructions on adding a new component to this API.
+    //
+    // |component| : Internal chrome component to get strings for.
+    // |callback| : Called with a dictionary mapping names to strings.
+    static void getStrings(Component component,
+                           GetStringsCallback callback);
+  };
+};
diff --git a/chrome/common/extensions/api/schemas.gypi b/chrome/common/extensions/api/schemas.gypi
index 346cee6..5879b667 100644
--- a/chrome/common/extensions/api/schemas.gypi
+++ b/chrome/common/extensions/api/schemas.gypi
@@ -70,6 +70,7 @@
       'permissions.json',
       'preferences_private.json',
       'reading_list_private.json',
+      'resources_private.idl',
       'screenlock_private.idl',
       'search_engines_private.idl',
       'sessions.json',
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index c75fa83b..2a04437 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -201,6 +201,8 @@
        APIPermissionInfo::kFlagCannotBeOptional},
       {APIPermission::kLanguageSettingsPrivate, "languageSettingsPrivate",
        APIPermissionInfo::kFlagCannotBeOptional},
+      {APIPermission::kResourcesPrivate, "resourcesPrivate",
+       APIPermissionInfo::kFlagCannotBeOptional},
 
       // Full url access permissions.
       {APIPermission::kDebugger, "debugger",
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index fd656429..68b43330 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -812,6 +812,7 @@
   skip.insert(APIPermission::kPrincipalsPrivate);
   skip.insert(APIPermission::kImageWriterPrivate);
   skip.insert(APIPermission::kReadingListPrivate);
+  skip.insert(APIPermission::kResourcesPrivate);
   skip.insert(APIPermission::kRtcPrivate);
   skip.insert(APIPermission::kStreamsPrivate);
   skip.insert(APIPermission::kSystemPrivate);
diff --git a/chrome/test/data/extensions/api_test/resources_private/get_strings/background.js b/chrome/test/data/extensions/api_test/resources_private/get_strings/background.js
new file mode 100644
index 0000000..5e7b824
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/resources_private/get_strings/background.js
@@ -0,0 +1,16 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.test.runTests([
+  function testGetStrings() {
+    chrome.resourcesPrivate.getStrings(
+        "identity", chrome.test.callbackPass(function(data) {
+          // String from the identity component.
+          chrome.test.assertTrue('window-title' in data);
+          // String from the loadTimeData defaults.
+          chrome.test.assertTrue('language' in data);
+          chrome.test.succeed();
+        }));
+  }
+]);
diff --git a/chrome/test/data/extensions/api_test/resources_private/get_strings/manifest.json b/chrome/test/data/extensions/api_test/resources_private/get_strings/manifest.json
new file mode 100644
index 0000000..6dbc0974
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/resources_private/get_strings/manifest.json
@@ -0,0 +1,10 @@
+{
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHKqRS2RUwmWJCzsOFjSRfd7f69w/yEWuddTD61QwwfeOpaA2+ZiQugaMb5HpLCbFNVBwHXKO1UxWF18YPHYMzMtDfbgjIxtQg3YRPCuicHR0qoo4jfzn9gY+6KW4csS4AH6/Tj700s5SvG25Ty6P6v9p9ZHPEVX9DeYeSllCWdwIDAQAB",
+  "name": "chrome.resourcesPrivate.getStrings test",
+  "version": "1",
+  "manifest_version": 2,
+  "background": {
+    "scripts": ["background.js"]
+  },
+  "permissions": ["resourcesPrivate"]
+}
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 53b98cd..fcaba05 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -528,7 +528,7 @@
   RUNTIME_GETPLATFORMINFO,
   DELETED_WEBVIEW_INSERTCSS,
   METRICSPRIVATE_GETISCRASHRECORDINGENABLED,
-  IDENTITYPRIVATE_GETSTRINGS,
+  DELETED_IDENTITYPRIVATE_GETSTRINGS,
   NOTIFICATIONS_GET_ALL,
   USB_LISTINTERFACES,
   FILESYSTEM_RETAINENTRY,
@@ -1142,6 +1142,7 @@
   CERTIFICATEPROVIDERINTERNAL_REPORTCERTIFICATES,
   BLUETOOTHPRIVATE_PAIR,
   EASYUNLOCKPRIVATE_FINDSETUPCONNECTION,
+  RESOURCESPRIVATE_GETSTRINGS,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index a025966..2a0fbc21 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -242,6 +242,7 @@
     kLanguageSettingsPrivate,
     kEnterpriseDeviceAttributes,
     kCertificateProvider,
+    kResourcesPrivate,
     // Last entry: Add new entries above and ensure to update the
     // "ExtensionPermission3" enum in tools/metrics/histograms/histograms.xml
     // (by running update_extension_permission.py).
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f73ddd4..dbc11e1 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -58659,7 +58659,7 @@
   <int value="467" label="RUNTIME_GETPLATFORMINFO"/>
   <int value="468" label="DELETED_WEBVIEW_INSERTCSS"/>
   <int value="469" label="METRICSPRIVATE_GETISCRASHRECORDINGENABLED"/>
-  <int value="470" label="IDENTITYPRIVATE_GETSTRINGS"/>
+  <int value="470" label="DELETED_IDENTITYPRIVATE_GETSTRINGS"/>
   <int value="471" label="NOTIFICATIONS_GET_ALL"/>
   <int value="472" label="USB_LISTINTERFACES"/>
   <int value="473" label="FILESYSTEM_RETAINENTRY"/>
@@ -59296,6 +59296,7 @@
   <int value="1081" label="CERTIFICATEPROVIDERINTERNAL_REPORTCERTIFICATES"/>
   <int value="1082" label="BLUETOOTHPRIVATE_PAIR"/>
   <int value="1083" label="EASYUNLOCKPRIVATE_FINDSETUPCONNECTION"/>
+  <int value="1084" label="RESOURCESPRIVATE_GETSTRINGS"/>
 </enum>
 
 <enum name="ExtensionInstallCause" type="int">
@@ -59701,6 +59702,8 @@
   <int value="194" label="kPasswordsPrivate"/>
   <int value="195" label="kLanguageSettingsPrivate"/>
   <int value="196" label="kEnterpriseDeviceAttributes"/>
+  <int value="197" label="kCertificateProvider"/>
+  <int value="198" label="kResourcesPrivate"/>
 </enum>
 
 <enum name="ExtensionServiceVerifyAllSuccess" type="int">