[M108 Migration][VD] Support set time and time zone offset 99/289099/9
authorfang fengrong <fr.fang@samsung.com>
Thu, 2 Mar 2023 08:34:51 +0000 (16:34 +0800)
committerBot Blink <blinkbot@samsung.com>
Wed, 8 Mar 2023 05:13:07 +0000 (05:13 +0000)
It is required for HbbTV to run Ligada tests. However Ligada tests
rely on stream time that can be old, like 2011. Ligada tests compare
time offset via Javascript codes(new Date()). So the time offset has
to be applied on render process side. Ligada tests also use the time
offset for certificates expiration validating.
ICS app also calls the APIs.

References:
https://review.tizen.org/gerrit/#/c/282681

Change-Id: I1f03d6fde935a28c7eaa114fb22bbcf29c5bddfe
Signed-off-by: fang fengrong <fr.fang@samsung.com>
29 files changed:
base/time/time.cc
base/time/time.h
base/time/time_exploded_posix.cc
base/time/time_now_posix.cc
content/common/zygote/zygote_commands_linux.h
content/common/zygote/zygote_communication_linux.cc
content/common/zygote/zygote_communication_linux.h
content/zygote/zygote_linux.cc
content/zygote/zygote_linux.h
net/cookies/canonical_cookie.cc
services/device/device_service.cc
services/device/device_service.h
services/device/public/mojom/BUILD.gn
services/device/public/mojom/device_service.mojom
services/device/time_zone_monitor/time_zone_monitor.cc
services/device/time_zone_monitor/time_zone_monitor.h
tizen_src/ewk/efl_integration/browser_context_efl.cc
tizen_src/ewk/efl_integration/browser_context_efl.h
tizen_src/ewk/efl_integration/common/content_switches_efl.cc
tizen_src/ewk/efl_integration/common/content_switches_efl.h
tizen_src/ewk/efl_integration/common/render_messages_ewk.h
tizen_src/ewk/efl_integration/content_browser_client_efl.cc
tizen_src/ewk/efl_integration/eweb_context.cc
tizen_src/ewk/efl_integration/eweb_context.h
tizen_src/ewk/efl_integration/private/ewk_context_private.cc
tizen_src/ewk/efl_integration/private/ewk_context_private.h
tizen_src/ewk/efl_integration/public/ewk_context.cc
tizen_src/ewk/efl_integration/renderer/render_thread_observer_efl.cc
tizen_src/ewk/efl_integration/renderer/render_thread_observer_efl.h

index 50ae8df..a03d13c 100644 (file)
 #include "build/build_config.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+namespace {
+double time_offset_ = 0.0;
+}  // namespace
+#endif
+
 namespace base {
 
 namespace {
@@ -417,4 +423,15 @@ std::string TimeFormatHTTP(base::Time time) {
       exploded.hour, exploded.minute, exploded.second);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+// Static
+double Time::TimeOffset() {
+  return time_offset_;
+}
+
+// Static
+void Time::SetTimeOffset(double time_offset) {
+  time_offset_ = time_offset;
+}
+#endif
 }  // namespace base
index 4d46222..5b6c333 100644 (file)
@@ -788,6 +788,13 @@ class BASE_EXPORT Time : public time_internal::TimeBase<Time> {
   // `TimeDelta::FromMiseconds()` for `TimeDelta`. http://crbug.com/634507
   static constexpr Time FromInternalValue(int64_t us) { return Time(us); }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  // Gets time offset
+  static double TimeOffset();
+  // Sets time offset
+  static void SetTimeOffset(double time_offset);
+#endif
+
  private:
   friend class time_internal::TimeBase<Time>;
 
index 8cc7376..2cad323 100644 (file)
@@ -280,6 +280,9 @@ bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
     converted_time.LocalExplode(&to_exploded);
 
   if (ExplodedMostlyEquals(to_exploded, exploded)) {
+#if BUILDFLAG(IS_TIZEN_TV)
+    converted_time -= Microseconds(TimeOffset());
+#endif
     *time = converted_time;
     return true;
   }
index b0ecb39..98f3232 100644 (file)
@@ -82,9 +82,16 @@ Time TimeNowIgnoringOverride() {
   // Combine seconds and microseconds in a 64-bit field containing microseconds
   // since the epoch.  That's enough for nearly 600 centuries.  Adjust from
   // Unix (1970) to Windows (1601) epoch.
+#if BUILDFLAG(IS_TIZEN_TV)
+  return Time() +
+         Microseconds((tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
+                      Time::kTimeTToMicrosecondsOffset +
+                      Time::TimeOffset() * Time::kMicrosecondsPerMillisecond);
+#else
   return Time() +
          Microseconds((tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
                       Time::kTimeTToMicrosecondsOffset);
+#endif
 }
 
 Time TimeNowFromSystemTimeIgnoringOverride() {
index 1ac1707..9215c67 100644 (file)
@@ -65,6 +65,9 @@ enum {
   // Drop privilege of zygote process.
   kZygoteCommandDropProcessPrivileges = 7,
 #endif
+#if BUILDFLAG(IS_TIZEN_TV)
+  kZygoteCommandSetTimeZoneOffset = 8,
+#endif
 };
 
 }  // namespace content
index 38fe7b2..9e2d158 100644 (file)
@@ -362,4 +362,18 @@ pid_t ZygoteCommunication::GetZygotePid() {
   return pid_;
 }
 #endif
+
+#if BUILDFLAG(IS_TIZEN_TV)
+void ZygoteCommunication::SetTimeZoneOffset(
+    const std::string& time_zone_offset) {
+  DCHECK(init_);
+  base::Pickle pickle;
+
+  pickle.WriteInt(kZygoteCommandSetTimeZoneOffset);
+  pickle.WriteString(time_zone_offset);
+  base::AutoLock lock(control_lock_);
+  if (!SendMessage(pickle, NULL))
+    LOG(ERROR) << "Failed to send SetTimeZoneOffset message to zygote";
+}
+#endif
 }  // namespace content
index 30f3e3e..e076d7d 100644 (file)
@@ -82,6 +82,10 @@ class CONTENT_EXPORT ZygoteCommunication {
   pid_t GetZygotePid();
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void SetTimeZoneOffset(const std::string&);
+#endif
+
  private:
   // Should be called every time a Zygote child is born.
   void ZygoteChildBorn(pid_t process);
index 044ebdb..d4d170f 100644 (file)
 #include "sandbox/policy/sandbox.h"
 #include "third_party/icu/source/i18n/unicode/timezone.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "third_party/icu/source/i18n/unicode/timezone.h"
+#endif
+
 // See
 // https://chromium.googlesource.com/chromium/src/+/main/docs/linux/zygote.md
 
@@ -276,6 +280,11 @@ bool Zygote::HandleRequestFromBrowser(int fd) {
       case kZygoteCommandReinitializeLogging:
         HandleReinitializeLoggingRequest(iter, std::move(fds));
         return false;
+#if BUILDFLAG(IS_TIZEN_TV)
+      case kZygoteCommandSetTimeZoneOffset:
+        HandleSetTimeZoneOffset(iter);
+        return false;
+#endif
       default:
         NOTREACHED();
         break;
@@ -695,4 +704,13 @@ void Zygote::HandleReinitializeLoggingRequest(base::PickleIterator iter,
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void Zygote::HandleSetTimeZoneOffset(base::PickleIterator iter) {
+  std::string time_zone_offset;
+  if (!iter.ReadString(&time_zone_offset))
+    return;
+  icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(
+      icu::UnicodeString::fromUTF8(time_zone_offset)));
+}
+#endif
 }  // namespace content
index a877168..70b6be9 100644 (file)
@@ -134,6 +134,10 @@ class Zygote {
   // Attempt to reap all outstanding children in |to_reap_|.
   void ReapChildren();
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void HandleSetTimeZoneOffset(base::PickleIterator iter);
+#endif
+
   // The Zygote needs to keep some information about each process. Most
   // notably what the PID of the process is inside the PID namespace of
   // the Zygote and whether or not a process was started by the
index ada61ec..b754ec2 100644 (file)
@@ -567,7 +567,17 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create(
   std::string cookie_path = CanonPathWithString(
       url, parsed_cookie.HasPath() ? parsed_cookie.Path() : std::string());
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  /* creation_time is associated with base::Time::Now() which includes
+   * TimeOffset.
+   * Remove offset so we have true UTC and mimic a server time by default.
+   */
+  Time cookie_server_time(creation_time -
+                          base::Microseconds(Time::TimeOffset()));
+#else
   Time cookie_server_time(creation_time);
+#endif
+
   if (server_time.has_value() && !server_time->is_null())
     cookie_server_time = server_time.value();
 
index eb98315..0086887 100644 (file)
@@ -422,4 +422,10 @@ service_manager::InterfaceProvider* DeviceService::GetJavaInterfaceProvider() {
 }
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void DeviceService::UpdateTimeZone(const std::string& timezone) {
+  if (time_zone_monitor_)
+    time_zone_monitor_->UpdateTimeZone(timezone);
+}
+#endif
 }  // namespace device
index ddf60de..9fb1bc2 100644 (file)
@@ -147,6 +147,10 @@ class DeviceService : public mojom::DeviceService {
   static void OverrideNFCProviderBinderForTesting(NFCProviderBinder binder);
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void UpdateTimeZone(const std::string& timezone) override;
+#endif
+
  private:
   // mojom::DeviceService implementation:
   void BindFingerprint(
index cabd499..78bfb47 100644 (file)
@@ -103,6 +103,10 @@ mojom("device_service") {
     enabled_features += [ "enable_device_posture" ]
   }
 
+  if (tizen_product_tv) {
+    enabled_features += [ "tizen_product_tv" ]
+  }
+
   public_deps = [
     ":generic_sensor",
     ":mojom",
index f8f1b90..3a93640 100644 (file)
@@ -109,4 +109,8 @@ interface DeviceService {
 
   // Binds a UsbDeviceManagerTest endpoint.
   BindUsbDeviceManagerTest(pending_receiver<UsbDeviceManagerTest> receiver);
+
+  // Update to specified TimeZone
+  [EnableIf=tizen_product_tv]
+  UpdateTimeZone(string timezone);
 };
index 7e16851..027f04f 100644 (file)
@@ -73,4 +73,11 @@ void TimeZoneMonitor::AddClient(
   clients_.Add(std::move(client));
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void TimeZoneMonitor::UpdateTimeZone(std::string time_zone_str) {
+  std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone(
+      icu::UnicodeString::fromUTF8(time_zone_str)));
+  UpdateIcuAndNotifyClients(std::move(timezone));
+}
+#endif
 }  // namespace device
index 49e1709..7f7f429 100644 (file)
@@ -61,6 +61,10 @@ class TimeZoneMonitor : public device::mojom::TimeZoneMonitor {
 
   void Bind(mojo::PendingReceiver<device::mojom::TimeZoneMonitor> receiver);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void UpdateTimeZone(std::string time_zone);
+#endif
+
  protected:
   TimeZoneMonitor();
 
index 42e40e8..4df6dcc 100644 (file)
@@ -15,6 +15,7 @@
 #include "browser/background_sync_controller_efl.h"
 #include "browser/geolocation/geolocation_permission_context_efl.h"
 #include "browser/webdata/web_data_service_factory.h"
+#include "common/render_messages_ewk.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
@@ -27,6 +28,7 @@
 #include "content/common/paths_efl.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "eweb_context.h"
 #include "network_delegate_efl.h"
 #include "permission_controller_delegate_efl.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "content/common/zygote/zygote_communication_linux.h"
+#include "content/public/browser/device_service.h"
+#include "content/public/common/zygote/zygote_handle.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
+#endif
+
 using namespace autofill::prefs;
 using namespace password_manager::prefs;
 using std::pair;
@@ -59,6 +68,55 @@ net::ScopedCERTCertificateList GetCertListFromFile(
   return cert_list;
 }
 
+void SendToAllRenderers(IPC::Message* message) {
+  content::RenderProcessHost::iterator it =
+      content::RenderProcessHost::AllHostsIterator();
+  while (!it.IsAtEnd()) {
+    it.GetCurrentValue()->Send(new IPC::Message(*message));
+    it.Advance();
+  }
+  delete message;
+}
+
+#if BUILDFLAG(IS_TIZEN_TV)
+void FormatHour(long time, std::ostringstream& ost) {
+  static const double kMinutesPerHour = 60.0;
+  ost.width(2);
+  ost.fill('0');
+  ost << (int)(time / kMinutesPerHour);
+  ost << ":";
+  ost.width(2);
+  ost.fill('0');
+  ost << (int)(time % static_cast<int>(kMinutesPerHour));
+}
+
+std::string CreateTimeZoneID(double time_zone_offset,
+                             double daylight_saving_time) {
+  static const double kMilliSecondsPerMinute = 60.0 * 1000.0;
+  static const char* kMinusSign = "-";
+  static const char* kPlusSign = "+";
+
+  long time_zone = (long)(time_zone_offset / kMilliSecondsPerMinute);
+  const long daylight_saving =
+      (long)(daylight_saving_time / kMilliSecondsPerMinute);
+
+  if (!time_zone && (daylight_saving <= 0))
+    return std::string();
+
+  std::ostringstream ost;
+  const char* sign = kMinusSign;
+
+  long total_offset = time_zone + daylight_saving;
+  if (total_offset < 0) {
+    total_offset *= -1;
+    sign = kPlusSign;
+  }
+  ost << "GMT" << sign;
+  FormatHour(total_offset, ost);
+
+  return ost.str();
+}
+#endif
 }  // namespace
 
 namespace content {
@@ -366,4 +424,67 @@ SpecialStoragePolicyEfl* BrowserContextEfl::GetSpecialStoragePolicyEfl() {
     special_storage_policy_efl_ = new SpecialStoragePolicyEfl();
   return special_storage_policy_efl_.get();
 }
+
+#if BUILDFLAG(IS_TIZEN_TV)
+void BrowserContextEfl::SetTimeOffset(double time_offset) {
+  if (time_offset_ == time_offset)
+    return;
+  time_offset_ = time_offset;
+  base::Time::SetTimeOffset(time_offset);
+  SendToAllRenderers(new EwkViewMsg_SetTimeOffset(time_offset_));
+}
+
+double BrowserContextEfl::GetTimeOffset() {
+  return time_offset_;
+}
+
+void BrowserContextEfl::SetTimeZoneOffset(double time_zone_offset,
+                                          double daylight_saving_time) {
+  if (time_zone_offset_ == time_zone_offset &&
+      daylight_saving_time_ == daylight_saving_time)
+    return;
+
+  std::string zone_id_str =
+      CreateTimeZoneID(time_zone_offset, daylight_saving_time);
+  if (zone_id_str.empty())
+    return;
+
+  time_zone_offset_ = time_zone_offset;
+  daylight_saving_time_ = daylight_saving_time;
+
+  /**
+  For China is UTC+8:00 or GMT+8:00
+  TZ needs to set it with opposite sign as follows:
+  TZ=UTC-8:00; export TZ
+  or,
+  TZ=GMT-8:00; export TZ
+  or,
+  TZ=Asia/Shanghai;export TZ
+  For US EST (GMT-5:00, New York):
+  TZ=UTC+5:00; export TZ
+  or,
+  TZ=GMT+5:00; export TZ
+  or,
+  TZ=America/New_York;export TZ
+  */
+  setenv("TZ", zone_id_str.c_str(), 1);
+  tzset();
+
+  // correct opposite sign from TZ
+  double total_offset = time_zone_offset + daylight_saving_time;
+  if (total_offset >= 0) {
+    if (zone_id_str.find("-") != std::string::npos)
+      zone_id_str.replace(zone_id_str.find("-"), 1, "+");
+  } else {
+    if (zone_id_str.find("+") != std::string::npos)
+      zone_id_str.replace(zone_id_str.find("+"), 1, "-");
+  }
+  LOG(INFO) << "timezone reset to " << zone_id_str;
+  icu::TimeZone::adoptDefault(
+      icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(zone_id_str)));
+
+  GetGenericZygote()->SetTimeZoneOffset(zone_id_str);
+  GetDeviceService().UpdateTimeZone(zone_id_str);
+}
+#endif
 }
index 8ddf8c8..f87cf20 100644 (file)
@@ -140,6 +140,12 @@ class BrowserContextEfl : public BrowserContext,
 
   void CreateNetworkDelegate();
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  double GetTimeOffset();
+  void SetTimeOffset(double);
+  void SetTimeZoneOffset(double time_zone_offset, double daylight_saving_time);
+#endif
+
  private:
   // certificate_path should be either be a directory with CA certs, a CA cert
   // file or a colon-separated list of those. CA cert files should have *.crt
@@ -163,6 +169,11 @@ class BrowserContextEfl : public BrowserContext,
   std::unique_ptr<PermissionControllerDelegate> permission_controller_delegate_;
   scoped_refptr<SpecialStoragePolicyEfl> special_storage_policy_efl_;
   std::string certificate_path_;
+#if BUILDFLAG(IS_TIZEN_TV)
+  double time_offset_ = 0.0;
+  double time_zone_offset_ = 0.0;
+  double daylight_saving_time_ = 0.0;
+#endif
 };
 }
 
index b54374c..96605e6 100644 (file)
@@ -23,6 +23,8 @@ const char kImplLibraryUpgrade[] = "impl-library-upgrade";
 const char kCORSEnabledURLSchemes[] = "cors-enabled-url-schemes";
 // JS plugin mime types
 const char kJSPluginMimeTypes[] = "jsplugin-mime-types";
+// Time offset
+const char kTimeOffset[] = "time-offset";
 #endif
 
 // Widget Info
index 9cf5369..6bb1a84 100644 (file)
@@ -28,6 +28,8 @@ CONTENT_EXPORT extern const char kImplLibraryUpgrade[];
 CONTENT_EXPORT extern const char kCORSEnabledURLSchemes[];
 // JS plugin mime types
 CONTENT_EXPORT extern const char kJSPluginMimeTypes[];
+// Enables time offset
+CONTENT_EXPORT extern const char kTimeOffset[];
 #endif
 CONTENT_EXPORT extern const char kTizenAppId[];
 CONTENT_EXPORT extern const char kTizenAppVersion[];
index c3430cd..ca3ed44 100644 (file)
@@ -261,4 +261,5 @@ IPC_MESSAGE_CONTROL1(HbbtvMsg_RegisterJSPluginMimeTypes,
 IPC_MESSAGE_CONTROL1(HbbtvMsg_RegisterURLSchemesAsCORSEnabled,
                      std::string /* scheme */)
 
+IPC_MESSAGE_CONTROL1(EwkViewMsg_SetTimeOffset, double /* time offset */)
 #endif
index 320bbee..e40da0e 100644 (file)
@@ -132,6 +132,14 @@ void AppendExtraCommandLineSwitchesInternal(base::CommandLine* command_line,
     command_line->AppendSwitchASCII(switches::kCORSEnabledURLSchemes,
                                     cors_enabled_url_schemes);
   }
+
+  const double time_offset =
+      static_cast<BrowserContextEfl*>(host->GetBrowserContext())
+          ->GetTimeOffset();
+  if (time_offset) {
+    command_line->AppendSwitchASCII(switches::kTimeOffset,
+                                    base::NumberToString(time_offset));
+  }
 #endif
 
   const std::string& injectedBundlePath = context->GetInjectedBundlePath();
index 0296654..ff0aaef 100644 (file)
@@ -1012,6 +1012,15 @@ void EWebContext::RegisterURLSchemesAsCORSEnabled(
 
   HbbtvWidgetHost::Get().RegisterURLSchemesAsCORSEnabled(schemes);
 }
+
+void EWebContext::SetTimeOffset(double time_offset) {
+  browser_context_->SetTimeOffset(time_offset);
+}
+
+void EWebContext::SetTimeZoneOffset(double time_zone_offset,
+                                    double daylight_saving_time) {
+  browser_context_->SetTimeZoneOffset(time_zone_offset, daylight_saving_time);
+}
 #endif
 
 void EWebContext::SetMaxRefreshRate(int max_refresh_rate) {
index c97389e..067c619 100644 (file)
@@ -204,6 +204,8 @@ class EWebContext {
   Ewk_Application_Type GetApplicationType() const { return application_type_; }
   void RegisterJSPluginMimeTypes(const Eina_List*);
   void RegisterURLSchemesAsCORSEnabled(const Eina_List* schemes_list);
+  void SetTimeOffset(double time_offset);
+  void SetTimeZoneOffset(double time_zone_offset, double daylight_saving_time);
 #endif
 
   void EnableAppControl(bool enabled);
index b685586..fa25e07 100644 (file)
@@ -348,6 +348,15 @@ void Ewk_Context::RegisterURLSchemesAsCORSEnabled(
     const Eina_List* schemes_list) {
   impl->RegisterURLSchemesAsCORSEnabled(schemes_list);
 }
+
+void Ewk_Context::SetTimeOffset(double time_offset) {
+  impl->SetTimeOffset(time_offset);
+}
+
+void Ewk_Context::SetTimeZoneOffset(double time_zone_offset,
+                                    double daylight_saving_time) {
+  impl->SetTimeZoneOffset(time_zone_offset, daylight_saving_time);
+}
 #endif
 
 void Ewk_Context::SetMaxRefreshRate(int max_refresh_rate) {
index 83991a0..cfe7fbb 100644 (file)
@@ -163,6 +163,10 @@ struct Ewk_Context : public base::RefCounted<Ewk_Context> {
   void RegisterJSPluginMimeTypes(const Eina_List*);
   // Registers url scheme as CORS enabled for HBBTV
   void RegisterURLSchemesAsCORSEnabled(const Eina_List* schemes_list);
+  // Sets time offset for HBBTV
+  void SetTimeOffset(double time_offset);
+  // Sets time zone offset for HBBTV
+  void SetTimeZoneOffset(double time_zone_offset, double daylight_saving_time);
 #endif
 
   void EnableAppControl(bool enabled);
index 28b632e..77e6450 100644 (file)
@@ -1079,10 +1079,29 @@ Ewk_Application_Type ewk_context_application_type_get(Ewk_Context* ewkContext) {
 #endif
 }
 
-void ewk_context_time_offset_set(Ewk_Context* context, double time_offset) {}
+void ewk_context_time_offset_set(Ewk_Context* context, double time_offset) {
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN(context);
+  LOG(INFO) << __FUNCTION__ << ", time_offset: " << time_offset;
+  context->SetTimeOffset(time_offset);
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV");
+#endif
+}
+
 void ewk_context_timezone_offset_set(Ewk_Context* context,
                                      double time_zone_offset,
-                                     double daylight_saving_time) {}
+                                     double daylight_saving_time) {
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN(context);
+  LOG(INFO) << __FUNCTION__ << ", time_zone_offset: " << time_zone_offset
+            << ", daylight_saving_time: " << daylight_saving_time;
+  context->SetTimeZoneOffset(time_zone_offset, daylight_saving_time);
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV");
+#endif
+}
+
 void ewk_context_default_zoom_factor_set(Ewk_Context* context,
                                          double zoom_factor) {
   EINA_SAFETY_ON_NULL_RETURN(context);
index db31c3f..a4d90fe 100644 (file)
@@ -19,7 +19,9 @@
 // XXX:  config.h needs to be included before internal blink headers.
 // XXX2: It'd be great if we did not include internal blibk headers.
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
-
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "base/strings/string_number_conversions.h"
+#endif
 using blink::WebCache;
 using blink::WebRuntimeFeatures;
 using content::RenderThread;
@@ -34,6 +36,15 @@ RenderThreadObserverEfl::RenderThreadObserverEfl(
   if (command_line.HasSwitch(switches::kEnableViewMode))
     WebRuntimeFeatures::EnableCSSViewModeMediaFeature(true);
 #endif
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (command_line.HasSwitch(switches::kTimeOffset)) {
+    std::string time_offset =
+        command_line.GetSwitchValueASCII(switches::kTimeOffset);
+    double offset = 0.0;
+    if (base::StringToDouble(time_offset, &offset))
+      OnSetTimeOffset(offset);
+  }
+#endif
 }
 
 bool RenderThreadObserverEfl::OnControlMessageReceived(const IPC::Message& message)
@@ -45,6 +56,9 @@ bool RenderThreadObserverEfl::OnControlMessageReceived(const IPC::Message& messa
     IPC_MESSAGE_HANDLER(EwkProcessMsg_SetExtensibleAPI, OnSetExtensibleAPI)
     IPC_MESSAGE_HANDLER(EwkProcessMsg_UpdateTizenExtensible,
                         OnUpdateTizenExtensible)
+#if BUILDFLAG(IS_TIZEN_TV)
+    IPC_MESSAGE_HANDLER(EwkViewMsg_SetTimeOffset, OnSetTimeOffset)
+#endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -67,4 +81,14 @@ void RenderThreadObserverEfl::OnSetExtensibleAPI(const std::string& api_name,
 void RenderThreadObserverEfl::OnUpdateTizenExtensible(
     const std::map<std::string, bool>& params) {
   TizenExtensible::GetInstance()->UpdateTizenExtensible(params);
-}
\ No newline at end of file
+}
+
+#if BUILDFLAG(IS_TIZEN_TV)
+void RenderThreadObserverEfl::OnSetTimeOffset(double time_offset) {
+  if (time_offset_ == time_offset)
+    return;
+
+  time_offset_ = time_offset;
+  base::Time::SetTimeOffset(time_offset);
+}
+#endif
\ No newline at end of file
index 8f95e3a..144fa6e 100644 (file)
@@ -22,12 +22,18 @@ public:
   explicit RenderThreadObserverEfl(ContentRendererClientEfl* content_client);
   bool OnControlMessageReceived(const IPC::Message& message) override;
   void OnClearCache();
+#if BUILDFLAG(IS_TIZEN_TV)
+  void OnSetTimeOffset(double time_offset);
+#endif
 
-private:
+ private:
   void OnSetCache(int64_t cache_total_capacity);
   ContentRendererClientEfl* content_client_;
   void OnSetExtensibleAPI(const std::string& api_name, bool enable);
   void OnUpdateTizenExtensible(const std::map<std::string, bool>& params);
+#if BUILDFLAG(IS_TIZEN_TV)
+  double time_offset_ = 0.0;
+#endif
 };
 
 #endif