94b1465516639ae31347c20c9fb21aecd4d8cef0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / tizen / tizen_locale_listener.cc
1 // Copyright (c) 2014 Intel Corporation. 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 "xwalk/runtime/browser/tizen/tizen_locale_listener.h"
6
7 #include <vconf.h>
8 #include <algorithm>
9
10 #include "base/logging.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "xwalk/runtime/browser/xwalk_runner_tizen.h"
13 #include "xwalk/application/browser/application_system.h"
14 #include "xwalk/application/browser/application_service.h"
15
16 namespace xwalk {
17 namespace {
18 const char kTizenDefaultLocale[] = "en-GB";
19 const char kTizenLocaleListenerThreadName[] = "TizenLocaleListener";
20
21 bool TizenLocaleToBCP47Locale(const std::string& tizen_locale,
22                               std::string* out_BCP47_locale) {
23   if (tizen_locale.empty())
24     return false;
25
26   // Tizen locale format [language[_territory][.codeset][@modifier]] .
27   // Conver to BCP47 format language[-territory] .
28   *out_BCP47_locale = tizen_locale.substr(0, tizen_locale.find_first_of("."));
29   std::replace(out_BCP47_locale->begin(), out_BCP47_locale->end(), '_', '-');
30   return true;
31 }
32
33 void OnVconfLangSetChanged(keynode_t *key, void *user_data) {
34   if (vconf_keynode_get_type(key) != VCONF_TYPE_STRING)
35     return;
36   TizenLocaleListener* tizen_locale_listener =
37       static_cast<TizenLocaleListener*>(user_data);
38
39   std::string locale;
40   if (TizenLocaleToBCP47Locale(vconf_keynode_get_str(key), &locale)) {
41     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
42         base::Bind(&TizenLocaleListener::SetLocale,
43                    base::Unretained(tizen_locale_listener),
44                    locale));
45   }
46 }
47
48 std::string GetSystemLocale() {
49   std::string tizen_locale;
50   char* langset = vconf_get_str(VCONFKEY_LANGSET);
51   if (langset) {
52     tizen_locale = langset;
53   } else {
54     LOG(ERROR) << "Can not get VCONFKEY_LANGSET from vconf or "
55                << "VCONFKEY_LANGSET vlaue is not a string value";
56   }
57   free(langset);
58
59   // Tizen take en-GB as default.
60   std::string BCP47_locale(kTizenDefaultLocale);
61   TizenLocaleToBCP47Locale(tizen_locale, &BCP47_locale);
62   return BCP47_locale;
63 }
64
65 }  // namespace
66
67 TizenLocaleListener::TizenLocaleListener()
68     : SimpleThread(kTizenLocaleListenerThreadName),
69       locale_(GetSystemLocale()) {
70   vconf_notify_key_changed(VCONFKEY_LANGSET, OnVconfLangSetChanged, this);
71   main_loop_ = g_main_loop_new(NULL, FALSE);
72   Start();
73 }
74
75 TizenLocaleListener::~TizenLocaleListener() {
76   g_main_loop_quit(main_loop_);
77   g_main_loop_unref(main_loop_);
78   SimpleThread::Join();
79   vconf_ignore_key_changed(VCONFKEY_LANGSET, OnVconfLangSetChanged);
80 }
81
82 void TizenLocaleListener::Run() {
83   g_main_loop_run(main_loop_);
84 }
85
86 std::string TizenLocaleListener::GetLocale() const {
87   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
88   // Note: we can only get locale from main thread for thread safe.
89   return locale_;
90 }
91
92 void TizenLocaleListener::SetLocale(const std::string& locale) {
93   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
94   // Note: we can only set locale from main thread for thread safe.
95   // If you need set locale from other thread, please PostTask to main thread.
96   if (locale_ == locale)
97     return;
98
99   LOG(INFO) << "Locale change from " << locale_ << " to " << locale;
100   locale_ = locale;
101
102   application::ApplicationSystem* application_system_ =
103       XWalkRunnerTizen::GetInstance()->app_system();
104   if (application_system_)
105     application_system_->application_service()->ChangeLocale(locale);
106 }
107
108 }  // namespace xwalk