summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc6
-rw-r--r--chrome/browser/extensions/extension_i18n_api.cc59
-rw-r--r--chrome/browser/extensions/extension_i18n_api.h18
-rw-r--r--chrome/browser/extensions/extension_i18n_apitest.cc9
-rw-r--r--chrome/chrome.gyp3
-rw-r--r--chrome/common/common_resources.grd2
-rwxr-xr-xchrome/common/extensions/api/extension_api.json22
-rw-r--r--chrome/common/extensions/docs/i18n.html1
-rw-r--r--chrome/renderer/extensions/extension_api_client_unittest.cc16
-rw-r--r--chrome/test/data/extensions/api_test/i18n/manifest.json6
-rw-r--r--chrome/test/data/extensions/api_test/i18n/test.html1
-rw-r--r--chrome/test/data/extensions/api_test/i18n/test.js14
-rw-r--r--chrome/test/data/extensions/samples/i18n/manifest.json6
-rw-r--r--chrome/test/data/extensions/samples/i18n/toolstrip.html29
14 files changed, 191 insertions, 1 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index d0281c3..276dd16 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/extensions/extension_bookmarks_module.h"
#include "chrome/browser/extensions/extension_bookmarks_module_constants.h"
#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/extensions/extension_i18n_api.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extension_page_actions_module.h"
#include "chrome/browser/extensions/extension_page_actions_module_constants.h"
@@ -69,6 +70,7 @@ void FactoryRegistry::ResetFunctions() {
// Register all functions here.
namespace bookmarks = extension_bookmarks_module_constants;
+ namespace i18n = extension_i18n_api_functions;
namespace page_actions = extension_page_actions_module_constants;
namespace tabs = extension_tabs_module_constants;
namespace test = extension_test_api_functions;
@@ -142,6 +144,10 @@ void FactoryRegistry::ResetFunctions() {
factories_[toolstrip::kCollapseFunction] =
&NewExtensionFunction<ToolstripCollapseFunction>;
+ // I18N.
+ factories_[i18n::kGetAcceptLanguagesFunction] =
+ &NewExtensionFunction<GetAcceptLanguagesFunction>;
+
// Test.
factories_[test::kPassFunction] =
&NewExtensionFunction<ExtensionTestPassFunction>;
diff --git a/chrome/browser/extensions/extension_i18n_api.cc b/chrome/browser/extensions/extension_i18n_api.cc
new file mode 100644
index 0000000..01048e9
--- /dev/null
+++ b/chrome/browser/extensions/extension_i18n_api.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2009 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_i18n_api.h"
+
+#include "chrome/browser/profile.h"
+#include "chrome/common/pref_names.h"
+
+namespace extension_i18n_api_functions {
+ const char kGetAcceptLanguagesFunction[] = "i18n.getAcceptLanguages";
+} // namespace extension_i18n_api_functions
+
+namespace {
+ // Errors.
+ const char kEmptyAcceptLanguagesError[] = "accept-languages is empty.";
+} // namespace
+
+bool GetAcceptLanguagesFunction::RunImpl() {
+ std::wstring acceptLanguages =
+ profile()->GetPrefs()->GetString(prefs::kAcceptLanguages);
+ // Currently, there are 2 ways to set browser's accept-languages: through UI
+ // or directly modify the preference file. The accept-languages set through
+ // UI is guranteed to be valid, and the accept-languages string returned from
+ // profile()->GetPrefs()->GetString(prefs::kAcceptLanguages) is guranteed to
+ // be valid and well-formed, which means each accept-langauge is a valid
+ // code, and accept-languages are seperatd by "," without surrrounding
+ // spaces. But we do not do any validation (either the format or the validity
+ // of the language code) on accept-languages set through editing preference
+ // file directly. So, here, we're adding extra checks to be resistant to
+ // crashes caused by data corruption.
+ result_.reset(new ListValue());
+ if (acceptLanguages.empty()) {
+ error_ = kEmptyAcceptLanguagesError;
+ return false;
+ }
+ size_t begin = 0;
+ size_t end;
+ std::wstring acceptLang;
+ while (1) {
+ end = acceptLanguages.find(',', begin);
+ if (end > begin) {
+ // Guard against a malformed value with multiple "," in a row.
+ acceptLang = acceptLanguages.substr(begin, end - begin);
+ static_cast<ListValue*>(result_.get())->
+ Append(Value::CreateStringValue(acceptLang));
+ }
+ begin = end + 1;
+ // 'begin >= acceptLanguages.length()' to guard against a value
+ // ending with ','.
+ if (end == std::wstring::npos || begin >= acceptLanguages.length())
+ break;
+ }
+ if (static_cast<ListValue*>(result_.get())->GetSize() == 0) {
+ error_ = kEmptyAcceptLanguagesError;
+ return false;
+ }
+ return true;
+}
diff --git a/chrome/browser/extensions/extension_i18n_api.h b/chrome/browser/extensions/extension_i18n_api.h
new file mode 100644
index 0000000..8fc18ac
--- /dev/null
+++ b/chrome/browser/extensions/extension_i18n_api.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2009 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_EXTENSION_I18N_API_H__
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_I18N_API_H__
+
+#include "chrome/browser/extensions/extension_function.h"
+
+namespace extension_i18n_api_functions {
+ extern const char kGetAcceptLanguagesFunction[];
+}; // namespace extension_i18n_api_functions
+
+class GetAcceptLanguagesFunction : public SyncExtensionFunction {
+ virtual bool RunImpl();
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_I18N_API_H__
diff --git a/chrome/browser/extensions/extension_i18n_apitest.cc b/chrome/browser/extensions/extension_i18n_apitest.cc
new file mode 100644
index 0000000..2798a72
--- /dev/null
+++ b/chrome/browser/extensions/extension_i18n_apitest.cc
@@ -0,0 +1,9 @@
+// Copyright (c) 2009 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"
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, I18N) {
+ ASSERT_TRUE(RunExtensionTest("i18n")) << message_;
+}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 9260fdd..8f592ac 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -75,6 +75,7 @@
'browser/extensions/extension_startup_unittest.cc',
'browser/extensions/extension_storage_apitest.cc',
'browser/extensions/extension_tabs_apitest.cc',
+ 'browser/extensions/extension_i18n_apitest.cc',
'browser/views/browser_views_accessibility_browsertest.cc',
'browser/views/find_bar_win_browsertest.cc',
# TODO(jam): http://crbug.com/15101 These tests fail on Linux and Mac.
@@ -1140,6 +1141,8 @@
'browser/extensions/extension_message_service.h',
'browser/extensions/extension_browser_event_router.cc',
'browser/extensions/extension_browser_event_router.h',
+ 'browser/extensions/extension_i18n_api.cc',
+ 'browser/extensions/extension_i18n_api.h',
'browser/extensions/extension_page_actions_module.cc',
'browser/extensions/extension_page_actions_module.h',
'browser/extensions/extension_page_actions_module_constants.cc',
diff --git a/chrome/common/common_resources.grd b/chrome/common/common_resources.grd
index ed07464..6f3b735 100644
--- a/chrome/common/common_resources.grd
+++ b/chrome/common/common_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. rw2 -->
+without changes to the corresponding grd file. xji -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/common_resources.h" type="rc_header">
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 91ceeba4..ffbae24 100755
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -1019,6 +1019,28 @@
"events": []
},
{
+ "namespace": "i18n",
+ "types": [],
+ "functions": [
+ {
+ "name": "getAcceptLanguages",
+ "type": "function",
+ "description": "Get accept languages of browser",
+ "parameters": [
+ {
+ "type": "function",
+ "name": "callback",
+ "parameters": [
+ {"name": "languages", "type": "array", "items": {"type": "string"}, "description": "Array of the accept languages of the browser, such as en-US,en,zh-CN"}
+ ]
+ }
+ ]
+ }
+ ],
+ "events": [
+ ]
+ },
+ {
"namespace": "devtools",
"types": [
],
diff --git a/chrome/common/extensions/docs/i18n.html b/chrome/common/extensions/docs/i18n.html
new file mode 100644
index 0000000..2cfcd5f
--- /dev/null
+++ b/chrome/common/extensions/docs/i18n.html
@@ -0,0 +1 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note: 1) The <head> information in this page is significant, should be uniform across api docs and should be edited only with knowledge of the templating mechanism. 2) The <body> tag *must* retain id="body" 3) All <body>.innerHTML is genereated as an rendering step. If viewed in a browser, it will be re-generated from the template, json schema and authored overview content. 4) The <body>.innerHTML is also generated by an offline step so that this page may easily be indexed by search engines. TODO(rafaelw): Abstract this into a "pageshell" that becomes the single version of page template shell and the "instance" pages (bookmarks.html, etc...) can be generated with a build step. --><!-- <html> must retain id="template --><html xmlns="http://www.w3.org/1999/xhtml" jstcache="0"><!-- <head> data is significant and loads the needed libraries and styles --><head jstcache="0"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" jstcache="0"> <title jscontent="getPageTitle()" jstcache="1">chrome.i18n</title> <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css" jstcache="0"> <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js" jstcache="0"> </script> <script type="text/javascript" src="js/api_page_generator.js" jstcache="0"></script> <script type="text/javascript" src="js/bootstrap.js" jstcache="0"></script> </head><!-- <body> content is completely generated. Do not edit, as it will be and rewritten. --><body jstcache="0"> <div id="container" jstcache="0"> <a name="top" jstcache="0"> </a> <!-- API HEADER --> <div id="pageHeader" jstcache="0"> <div id="searchbox" jstcache="0"> <form action="http://www.google.com/cse" id="cse-search-box" jstcache="0"> <div jstcache="0"> <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno" jstcache="0"> <input type="hidden" name="ie" value="UTF-8" jstcache="0"> <input type="text" name="q" size="31" jstcache="0"> <input type="submit" name="sa" value="Search" jstcache="0"> </div> </form> <script type="text/javascript" src="http://www.google.com/jsapi" jstcache="0"></script> <script type="text/javascript" jstcache="0">google.load("elements", "1", {packages: "transliteration"});</script> <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse-search-box&amp;t13n_langs=en" jstcache="0"></script> <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en" jstcache="0"></script> </div> <div id="pageTitle" jstcache="0"> <h1 jscontent="getPageTitle()" jstcache="1">chrome.i18n</h1> </div> </div> <!-- /pageHeader --> <div id="pageContent" jstcache="0"> <!-- SIDENAV --> <div id="leftNav" jstcache="0"> <ul jstcache="0"> <li jstcache="0"> <a href="index.html" jstcache="0">Home</a></li> <li jstcache="0"> <a href="getstarted.html" jstcache="0">Getting Started</a></li> <li jstcache="0"> <a href="overview.html" jstcache="0">Overview</a></li> <li jstcache="0"> <a href="devguide.html" jstcache="0"><div jstcache="0">Developer's Guide</div></a> <ul jstcache="0"> <li jstcache="0"><a href="toolstrip.html" jstcache="0">Toolstrips</a></li> <li jstcache="0"><a href="pageActions.html" jstcache="0">Page Actions</a></li> <li jstcache="0"><a href="background_pages.html" jstcache="0">Background Pages</a></li> <li jstcache="0"><a href="content_scripts.html" jstcache="0">Content Scripts</a></li> <li jstcache="0"><a href="events.html" jstcache="0">Events</a></li> <li jstcache="0"><a href="tabs.html" jstcache="0">Tabs</a></li> <li jstcache="0"><a href="windows.html" jstcache="0">Windows</a></li> <li jstcache="0"><a href="bookmarks.html" jstcache="0">Bookmarks</a></li> <li jstcache="0"><a href="themes.html" jstcache="0">Themes</a></li> <li jstcache="0"><a href="npapi.html" jstcache="0">NPAPI Plugins</a></li> <li jstcache="0"><a href="packaging.html" jstcache="0">Packaging</a></li> <li jstcache="0">Autoupdate</li> </ul> </li> <li jstcache="0"><a href="tutorials.html" jstcache="0"><div jstcache="0">Tutorials</div></a> <ul jstcache="0"> <li jstcache="0"><a href="tut_debugging.html" jstcache="0">Debugging</a></li> </ul> </li> <li jstcache="0">Reference <ul jstcache="0"> <li jstcache="0"> Formats <ul jstcache="0"> <li jstcache="0"><a href="manifest.html" jstcache="0">Manifest Files</a></li> <li jstcache="0"><a href="match_patterns.html" jstcache="0">Match Patterns</a></li> <li jstcache="0">Packages (.crx)</li> </ul> </li> <li jstcache="0"> <a href="api_index.html" jstcache="0">chrome.* APIs</a> </li> <li jstcache="0"> <a href="api_other.html" jstcache="0">Other APIs</a> </li> </ul> </li> <li jstcache="0"><a href="http://dev.chromium.org/developers/design-documents/extensions/samples" jstcache="0">Samples</a></li> </ul> </div> <div id="mainColumn" jstcache="0"> <!-- TABLE OF CONTENTS --> <div id="toc" jsdisplay="showPageTOC()" jstcache="2"> <p jstcache="0">Contents</p> <ol jstcache="0"> <li jsselect="getStaticTOC()" jstcache="9" jsinstance="*0" style="display: none; "> <a jscontent="name" jsvalues=".href:'#' + href" jstcache="14">h2Name</a> <ol jstcache="0"> <li jsselect="$this.children" jstcache="22"> <a jscontent="name" jsvalues=".href:'#' + href" jstcache="14">h3Name</a> </li> </ol> </li> <div jsselect="apiDefinition" jstcache="3"> <li jstcache="0"> <a href="#apiReference" jscontent="'API reference: ' + getModuleName()" jstcache="4">API reference: chrome.i18n</a> <ol jstcache="0"> <li jsdisplay="$this.properties" jstcache="5" style="display: none; "> <a href="#properties" jstcache="0">Properties</a> <ol jstcache="0"> <li jsselect="getPropertyListFromObject($this)" jstcache="10"> <a jscontent="name" jsvalues=".href:'#property-' + name" href="#property-anchor" jstcache="41">propertyName</a> </li> </ol> </li> <li jsdisplay="functions &amp;&amp; functions.length &gt; 0" jstcache="6"> <a href="#methods" jstcache="0">Methods</a> <ol jstcache="0"> <li jsselect="functions" jstcache="11" jsinstance="*0"> <a jscontent="name" jsvalues=".href:'#method-' + name" href="#method-getAcceptLanguages" jstcache="42">getAcceptLanguages</a> </li> </ol> </li> <li jsdisplay="events &amp;&amp; events.length &gt; 0" jstcache="7" style="display: none; "> <a href="#events" jstcache="0">Events</a> <ol jstcache="0"> <li jsselect="events" jstcache="12"> <a jscontent="name" jsvalues=".href:'#event-' + name" href="#event-anchor" jstcache="43">eventName</a> </li> </ol> </li> <li jsdisplay="types &amp;&amp; types.length &gt; 0" jstcache="8" style="display: none; "> <a href="#types" jstcache="0">Types</a> <ol jstcache="0"> <li jsselect="types" jstcache="13"> <a jscontent="id" jsvalues=".href:'#type-' + id" href="#id-anchor" jstcache="44">id</a> </li> </ol> </li> </ol> </li> </div> </ol> </div> <!-- /TABLE OF CONTENTS --> <!-- STATIC CONTENT PLACEHOLDER --> <div id="static" jstcache="0"></div> <!-- API PAGE --> <div class="apiPage" jsselect="apiDefinition" jstcache="3"> <a name="apiReference" jstcache="0"></a> <h2 jscontent="'API reference: ' + getModuleName()" jstcache="4">API reference: chrome.i18n</h2> <!-- PROPERTIES --> <div jsdisplay="$this.properties" class="apiGroup" jstcache="5" style="display: none; "> <a name="properties" jstcache="0"></a> <h3 id="properties" jstcache="0">Properties</h3> <div jsselect="getPropertyListFromObject($this)" jstcache="10"> <a jsvalues=".name:'property-' + name" jstcache="15"></a> <h4 jscontent="name" jstcache="16">getLastError</h4> <div class="summary" jstcache="0"> <!-- Note: intentionally longer 80 columns --> <span jscontent="getModuleName() + '.'" jstcache="23">chrome.extension</span><span jscontent="$this.name" jstcache="24">lastError</span> </div> <div transclude="valueTemplate" jstcache="17"> </div> </div> </div> <!-- /apiGroup --> <!-- METHODS --> <div jsdisplay="functions &amp;&amp; functions.length &gt; 0" class="apiGroup" id="methods" jstcache="6"> <a name="methods" jstcache="0"></a> <h3 jstcache="0">Methods</h3> <!-- iterates over all functions --> <div class="apiItem" jsselect="functions" jstcache="11" jsinstance="*0"> <a jsvalues=".name:'method-' + name" jstcache="18" name="method-getAcceptLanguages"></a> <!-- method-anchor --> <h4 jscontent="name" jstcache="16">getAcceptLanguages</h4> <div class="summary" jstcache="0"><span jsdisplay="returns" jscontent="getTypeName(returns)" jstcache="25" style="display: none; ">void</span> <!-- Note: intentionally longer 80 columns --> <span jscontent="getFullyQualifiedFunctionName($this)" jstcache="26">chrome.i18n.getAcceptLanguages</span>(<span jsselect="parameters" jsvalues="class:optional ? 'optional' : ''" jstcache="27" jsinstance="*0" class="null"><span jsdisplay="$index" jstcache="33" style="display: none; ">, </span><span jscontent="getTypeName($this)" jstcache="34">function</span> <var jstcache="0"><span jscontent="name" jstcache="16">callback</span></var></span>)</div> <div class="description" jstcache="0"> <p class="todo" jsdisplay="!description" jstcache="28" style="display: none; ">Undocumented.</p> <p jsdisplay="description" jsvalues=".innerHTML:description" jstcache="29">Get accept languages of browser</p> <!-- PARAMETERS --> <h4 jstcache="0">Parameters</h4> <dl jstcache="0"> <div jsselect="parameters" jstcache="35" jsinstance="*0"> <!-- VALUE: This is a subtemplate that is used elsewhere via jsTemplate *transclude* --> <div id="valueTemplate" jstcache="0"> <dt jstcache="0"> <var jsdisplay="$this.name" jscontent="$this.name" jstcache="45">callback</var> <em jstcache="0"> <!-- TYPE --> <div style="display:inline" jstcache="0"> ( <span class="optional" jsdisplay="optional" jstcache="46" style="display: none; ">optional</span> <span id="typeTemplate" jstcache="0"> <span jsdisplay="getTypeRef($this)" jstcache="47" style="display: none; "> <a jsvalues=".href: getTypeRefPage($this) + '#type-' + getTypeRef($this)" jscontent="getTypeRef($this)" jstcache="49"> Type</a> </span> <span jsdisplay="!getTypeRef($this)" jstcache="48"> <span jsdisplay="isArray($this)" jstcache="50" style="display: none; "> array of <span jsselect="items" jstcache="52"><span transclude="typeTemplate" jstcache="53"></span></span> </span> <span jsdisplay="!isArray($this)" jscontent="getTypeName($this)" jstcache="51">function</span> </span> </span> ) </div> </em> </dt> <dd class="todo" jsdisplay="!$this.description" jstcache="38"> Undocumented. </dd> <dd jsdisplay="$this.description" jsvalues=".innerHTML:$this.description" jstcache="39" style="display: none; "> Description of this parameter from the json schema. </dd> <!-- OBJECT PROPERTIES --> <dd jsdisplay="shouldExpandObject($this)" jstcache="40" style="display: none; "> <dl jstcache="0"> <div jsselect="getPropertyListFromObject($this)" jstcache="10"> <div transclude="valueTemplate" jstcache="17"> </div> </div> </dl> </dd> </div> <!-- /VALUE --> </div> </dl> <!-- RETURNS --> <h4 jsdisplay="returns" jstcache="30" style="display: none; ">Returns</h4> <dl jstcache="0"> <div jsselect="returns" jstcache="36" style="display: none; "> <div transclude="valueTemplate" jstcache="17"> </div> </div> </dl> <!-- CALLBACK --> <div jsdisplay="hasCallback(parameters)" jstcache="31"> <div jsselect="getCallbackParameters(parameters)" jstcache="37"> <h4 jstcache="0">Callback function</h4> <p jstcache="0"> If you specify the <em jstcache="0">callback</em> parameter, it should specify a function that looks like this: </p> <!-- Note: intentionally longer 80 columns --> <pre jstcache="0">function(<span jscontent="getSignatureString(parameters)" jstcache="32">array of string languages</span>) <span class="subdued" jstcache="0">{...}</span>);</pre> <dl jstcache="0"> <div jsselect="parameters" jstcache="35" jsinstance="*0"> <div jstcache="0"> <dt jstcache="0"> <var jsdisplay="$this.name" jscontent="$this.name" jstcache="45">languages</var> <em jstcache="0"> <!-- TYPE --> <div style="display:inline" jstcache="0"> ( <span class="optional" jsdisplay="optional" jstcache="46" style="display: none; ">optional</span> <span id="typeTemplate" jstcache="0"> <span jsdisplay="getTypeRef($this)" jstcache="47" style="display: none; "> <a jsvalues=".href: getTypeRefPage($this) + '#type-' + getTypeRef($this)" jscontent="getTypeRef($this)" jstcache="49"> Type</a> </span> <span jsdisplay="!getTypeRef($this)" jstcache="48"> <span jsdisplay="isArray($this)" jstcache="50" style=""> array of <span jsselect="items" jstcache="52"><span jstcache="0"> <span jsdisplay="getTypeRef($this)" jstcache="47" style="display: none; "> <a jsvalues=".href: getTypeRefPage($this) + '#type-' + getTypeRef($this)" jscontent="getTypeRef($this)" jstcache="49"> Type</a> </span> <span jsdisplay="!getTypeRef($this)" jstcache="48"> <span jsdisplay="isArray($this)" jstcache="50" style="display: none; "> array of <span jsselect="items" jstcache="52"><span transclude="typeTemplate" jstcache="53"></span></span> </span> <span jsdisplay="!isArray($this)" jscontent="getTypeName($this)" jstcache="51">string</span> </span> </span></span> </span> <span jsdisplay="!isArray($this)" jscontent="getTypeName($this)" jstcache="51" style="display: none; ">function</span> </span> </span> ) </div> </em> </dt> <dd class="todo" jsdisplay="!$this.description" jstcache="38" style="display: none; "> Undocumented. </dd> <dd jsdisplay="$this.description" jsvalues=".innerHTML:$this.description" jstcache="39" style="">Array of the accept languages of the browser, such as en-US,en,zh-CN</dd> <!-- OBJECT PROPERTIES --> <dd jsdisplay="shouldExpandObject($this)" jstcache="40" style="display: none; "> <dl jstcache="0"> <div jsselect="getPropertyListFromObject($this)" jstcache="10"> <div transclude="valueTemplate" jstcache="17"> </div> </div> </dl> </dd> </div> </div> </dl> </div> </div> </div> <!-- /description --> </div> <!-- /apiItem --> </div> <!-- /apiGroup --> <!-- EVENTS --> <div jsdisplay="events &amp;&amp; events.length &gt; 0" class="apiGroup" jstcache="7" style="display: none; "> <a name="events" jstcache="0"></a> <h3 id="events" jstcache="0">Events</h3> <!-- iterates over all events --> <div jsselect="events" class="apiItem" jstcache="12"> <a jsvalues=".name:'event-' + name" jstcache="19"></a> <h4 jscontent="name" jstcache="16">event name</h4> <div class="summary" jstcache="0"> <!-- Note: intentionally longer 80 columns --> <span jscontent="getModuleName() + '.'" class="subdued" jstcache="23">chrome.bookmarks</span><span jscontent="name" jstcache="16">onEvent</span><span class="subdued" jstcache="0">.addListener</span>(function(<span jscontent="getSignatureString(parameters)" jstcache="32">Type param1, Type param2</span>) <span class="subdued" jstcache="0">{...}</span>); </div> <div class="description" jstcache="0"> <p class="todo" jsdisplay="!description" jstcache="28">Undocumented.</p> <p jsdisplay="description" jsvalues=".innerHTML:description" jstcache="29"> A description from the json schema def of the event goes here. </p> <!-- PARAMETERS --> <h4 jstcache="0">Parameters</h4> <dl jstcache="0"> <div jsselect="parameters" jstcache="35"> <div transclude="valueTemplate" jstcache="17"> </div> </div> </dl> </div> <!-- /decription --> </div> <!-- /apiItem --> </div> <!-- /apiGroup --> <!-- TYPES --> <div jsdisplay="types &amp;&amp; types.length &gt; 0" class="apiGroup" jstcache="8" style="display: none; "> <a name="types" jstcache="0"></a> <h3 id="types" jstcache="0">Types</h3> <!-- iterates over all types --> <div jsselect="types" class="apiItem" jstcache="13"> <a jsvalues=".name:'type-' + id" jstcache="20"></a> <h4 jscontent="id" jstcache="21">type name</h4> <div transclude="valueTemplate" jstcache="17"> </div> </div> <!-- /apiItem --> </div> <!-- /apiGroup --> </div> <!-- /apiPage --> </div> <!-- /mainColumn --> </div> <!-- /pageContent --> <div id="pageFooter" --="" jstcache="0"> <p jstcache="0"> Except as otherwise <a href="http://code.google.com/policies.html#restrictions" jstcache="0">noted</a>, the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/" jstcache="0">Creative Commons Attribution 3.0 License</a>, and code samples are licensed under the <a rel="license" href="http://code.google.com/google_bsd_license.html" jstcache="0">BSD License</a>. </p> <p jstcache="0"> ©2009 Google </p> </div> <!-- /pageFooter --> </div> <!-- /container --> </body></html>
diff --git a/chrome/renderer/extensions/extension_api_client_unittest.cc b/chrome/renderer/extensions/extension_api_client_unittest.cc
index 874f2bf..f248460 100644
--- a/chrome/renderer/extensions/extension_api_client_unittest.cc
+++ b/chrome/renderer/extensions/extension_api_client_unittest.cc
@@ -588,3 +588,19 @@ TEST_F(ExtensionAPIClientTest, CollapseToolstrip) {
"Uncaught Error: Invalid value for argument 1. "
"Expected 'function' but got 'integer'.");
}
+
+// I18N API
+TEST_F(ExtensionAPIClientTest, GetAcceptLanguages) {
+ ExpectJsFail("chrome.i18n.getAcceptLanguages(32, function(){})",
+ "Uncaught Error: Too many arguments.");
+
+ ExpectJsFail("chrome.i18n.getAcceptLanguages()",
+ "Uncaught Error: Parameter 0 is required.");
+
+ ExpectJsFail("chrome.i18n.getAcceptLanguages('abc')",
+ "Uncaught Error: Invalid value for argument 0. "
+ "Expected 'function' but got 'string'.");
+
+ ExpectJsPass("chrome.i18n.getAcceptLanguages(function(){})",
+ "i18n.getAcceptLanguages", "null");
+}
diff --git a/chrome/test/data/extensions/api_test/i18n/manifest.json b/chrome/test/data/extensions/api_test/i18n/manifest.json
new file mode 100644
index 0000000..3653d29
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/i18n/manifest.json
@@ -0,0 +1,6 @@
+{
+ "name": "chrome.i18n",
+ "version": "0.1",
+ "description": "end-to-end browser test for chrome.i18n API",
+ "background_page": "test.html"
+}
diff --git a/chrome/test/data/extensions/api_test/i18n/test.html b/chrome/test/data/extensions/api_test/i18n/test.html
new file mode 100644
index 0000000..46f4d74
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/i18n/test.html
@@ -0,0 +1 @@
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/i18n/test.js b/chrome/test/data/extensions/api_test/i18n/test.js
new file mode 100644
index 0000000..ab12d90
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/i18n/test.js
@@ -0,0 +1,14 @@
+// i18n api test
+// browser_tests.exe --gtest_filter=ExtensionApiTest.I18N
+
+var testCallback = chrome.test.testCallback;
+
+chrome.test.runTests([
+ function getAcceptLanguages() {
+ chrome.i18n.getAcceptLanguages(chrome.test.callbackPass(function(results) {
+ chrome.test.assertEq(results.length, 2);
+ chrome.test.assertEq(results[0], "en-US");
+ chrome.test.assertEq(results[1], "en");
+ }));
+ }
+]);
diff --git a/chrome/test/data/extensions/samples/i18n/manifest.json b/chrome/test/data/extensions/samples/i18n/manifest.json
new file mode 100644
index 0000000..ec642b1
--- /dev/null
+++ b/chrome/test/data/extensions/samples/i18n/manifest.json
@@ -0,0 +1,6 @@
+{
+ "name": "AcceptLanguage",
+ "description": "Returns accept languages of the browser",
+ "version": "0.1",
+ "toolstrips": ["toolstrip.html"]
+}
diff --git a/chrome/test/data/extensions/samples/i18n/toolstrip.html b/chrome/test/data/extensions/samples/i18n/toolstrip.html
new file mode 100644
index 0000000..3a11625
--- /dev/null
+++ b/chrome/test/data/extensions/samples/i18n/toolstrip.html
@@ -0,0 +1,29 @@
+<!--
+Copyright (c) 2009 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.
+-->
+
+<html>
+ <head>
+ <script>
+ function getAcceptLanguages() {
+ chrome.i18n.getAcceptLanguages(function(languageList) {
+ var languages = "";
+ for (var i = 0; i < languageList.length; i++) {
+ if (i == languageList.length - 1)
+ languages += languageList[i];
+ else
+ languages += languageList[i] + ",";
+ }
+ document.getElementById("languageSpan").innerHTML = languages;
+ })
+ }
+ </script>
+ </head>
+ <body>
+ <div class="toolstrip-button" onclick="getAcceptLanguages();">
+ <span id="languageSpan">GetAcceptLanguage</span>
+ </div>
+ </body>
+</html>