// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/uwp/application_uwp.h"

#include <D3D11.h>
#include <D3D11_1.h>
#include <WinSock2.h>
#include <collection.h>
#include <mfapi.h>
#include <ppltasks.h>
#include <windows.graphics.display.core.h>
#include <windows.h>
#include <windows.system.display.h>

#include <cstdlib>
#include <memory>
#include <string>
#include <vector>

#include "starboard/common/device_type.h"
#include "starboard/common/file.h"
#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/queue.h"
#include "starboard/common/semaphore.h"
#include "starboard/common/string.h"
#include "starboard/common/system_property.h"
#include "starboard/common/thread.h"
#include "starboard/common/time.h"
#include "starboard/configuration_constants.h"
#include "starboard/event.h"
#include "starboard/input.h"
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
#include "starboard/shared/starboard/media/key_system_supportability_cache.h"
#include "starboard/shared/starboard/media/mime_supportability_cache.h"
#include "starboard/shared/starboard/net_args.h"
#include "starboard/shared/starboard/net_log.h"
#include "starboard/shared/uwp/analog_thumbstick_input_thread.h"
#include "starboard/shared/uwp/app_accessors.h"
#include "starboard/shared/uwp/async_utils.h"
#include "starboard/shared/uwp/extended_resources_manager.h"
#include "starboard/shared/uwp/log_file_impl.h"
#include "starboard/shared/uwp/watchdog_log.h"
#include "starboard/shared/uwp/window_internal.h"
#include "starboard/shared/win32/thread_private.h"
#include "starboard/shared/win32/video_decoder.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/system.h"

namespace starboard {

using Microsoft::WRL::ComPtr;
using shared::starboard::Application;
using shared::starboard::CommandLine;
using shared::starboard::kNetArgsCommandSwitchWait;
using shared::starboard::kNetLogCommandSwitchWait;
using shared::starboard::NetArgsWaitForPayload;
using shared::starboard::NetLogFlushThenClose;
using shared::starboard::NetLogWaitForClientConnected;
using shared::uwp::ApplicationUwp;
using shared::uwp::RunInMainThreadAsync;
using shared::uwp::WaitForResult;
using shared::win32::platformStringToString;
using shared::win32::stringToPlatformString;
using shared::win32::wchar_tToUTF8;
using ::starboard::shared::starboard::media::KeySystemSupportabilityCache;
using ::starboard::shared::starboard::media::MimeSupportabilityCache;
using Windows::ApplicationModel::SuspendingDeferral;
using Windows::ApplicationModel::SuspendingEventArgs;
using Windows::ApplicationModel::Activation::ActivationKind;
using Windows::ApplicationModel::Activation::DialReceiverActivatedEventArgs;
using Windows::ApplicationModel::Activation::IActivatedEventArgs;
using Windows::ApplicationModel::Activation::IProtocolActivatedEventArgs;
using Windows::ApplicationModel::Core::CoreApplication;
using Windows::ApplicationModel::Core::CoreApplicationView;
using Windows::ApplicationModel::Core::IFrameworkView;
using Windows::ApplicationModel::Core::IFrameworkViewSource;
using Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionReason;
using Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionResult;
using Windows::ApplicationModel::ExtendedExecution::
    ExtendedExecutionRevokedEventArgs;
using Windows::ApplicationModel::ExtendedExecution::ExtendedExecutionSession;
using Windows::Devices::Enumeration::DeviceInformation;
using Windows::Devices::Enumeration::DeviceInformationUpdate;
using Windows::Devices::Enumeration::DeviceWatcher;
using Windows::Devices::Enumeration::DeviceWatcherStatus;
using Windows::Foundation::EventHandler;
using Windows::Foundation::IAsyncOperation;
using Windows::Foundation::TimeSpan;
using Windows::Foundation::TypedEventHandler;
using Windows::Foundation::Uri;
using Windows::Foundation::Collections::IVectorView;
using Windows::Foundation::Metadata::ApiInformation;
using Windows::Globalization::Calendar;
using Windows::Graphics::Display::AdvancedColorInfo;
using Windows::Graphics::Display::AdvancedColorKind;
using Windows::Graphics::Display::DisplayInformation;
using Windows::Graphics::Display::HdrMetadataFormat;
using Windows::Graphics::Display::Core::HdmiDisplayColorSpace;
using Windows::Graphics::Display::Core::HdmiDisplayHdr2086Metadata;
using Windows::Graphics::Display::Core::HdmiDisplayHdrOption;
using Windows::Graphics::Display::Core::HdmiDisplayInformation;
using Windows::Graphics::Display::Core::HdmiDisplayMode;
using Windows::Media::Protection::HdcpProtection;
using Windows::Media::Protection::HdcpSession;
using Windows::Media::Protection::HdcpSetProtectionResult;
using Windows::Security::Authentication::Web::Core::WebTokenRequestResult;
using Windows::Security::Authentication::Web::Core::WebTokenRequestStatus;
using Windows::Security::Credentials::WebAccountProvider;
using Windows::Storage::FileAttributes;
using Windows::Storage::KnownFolders;
using Windows::Storage::StorageFile;
using Windows::Storage::StorageFolder;
using Windows::System::UserAuthenticationStatus;
using Windows::System::Threading::ThreadPoolTimer;
using Windows::System::Threading::TimerElapsedHandler;
using Windows::UI::Core::CoreDispatcherPriority;
using Windows::UI::Core::CoreProcessEventsOption;
using Windows::UI::Core::CoreWindow;
using Windows::UI::Core::DispatchedHandler;
using Windows::UI::Core::KeyEventArgs;
using Windows::UI::ViewManagement::ApplicationView;
using Windows::UI::ViewManagement::ApplicationViewScaling;

namespace {

const Platform::String ^ kGenericPnpMonitorAqs = ref new Platform::String(
    L"System.Devices.InterfaceClassGuid:=\"{e6f07b5f-ee97-4a90-b076-"
    L"33f57bf4eaa7}\" AND "
    L"System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#"
    L"True");

const uint32_t kYuv420BitsPerPixelForHdr10Mode = 24;
const uint32_t kHdr4kRefreshRateMaximum = 60;
const uint32_t k4kResolutionWidth = 3840;
const uint32_t k4kResolutionHeight = 2160;

// Per Microsoft, HdcpProtection::On means HDCP 1.x required.
const HdcpProtection kHDCPProtectionMode = HdcpProtection::On;

const int kWinSockVersionMajor = 2;
const int kWinSockVersionMinor = 2;

const char kDialParamPrefix[] = "cobalt-dial:?";
const char kLogPathSwitch[] = "xb1_log_file";
// A special log that the app will periodically write to. This allows
// tests to determine if the app is still alive.
const char kWatchDogLog[] = "xb1_watchdog_log";
const char kStarboardArgumentsPath[] = "arguments\\starboard_arguments.txt";
const int64_t kMaxArgumentFileSizeBytes = 4 * 1024 * 1024;

int main_return_value = 0;

// IDisplayRequest is both "non-agile" and apparently
// incompatible with Platform::Agile (it doesn't fully implement
// a thread marshaller). We must neither use ComPtr or Platform::Agile
// here. We manually create, access release on the main app thread only.
ABI::Windows::System::Display::IDisplayRequest* display_request = nullptr;

// If an argv[0] is required, fill it in with the result of
// GetModuleFileName()
std::string GetArgvZero() {
  const size_t kMaxModuleNameSize = kSbFileMaxName;
  std::vector<wchar_t> buffer(kMaxModuleNameSize);
  DWORD result = GetModuleFileName(NULL, buffer.data(), buffer.size());
  std::string arg;
  if (result == 0) {
    arg = "unknown";
  } else {
    arg = wchar_tToUTF8(buffer.data(), result).c_str();
  }
  return arg;
}

int MakeDeviceId() {
  // TODO: Devices MIGHT have colliding hashcodes. Some other unique int
  // ID generation tool would be better.
  using Windows::Security::ExchangeActiveSyncProvisioning::
      EasClientDeviceInformation;
  auto device_information = ref new EasClientDeviceInformation();
  Platform::String ^ device_id_string = device_information->Id.ToString();
  return device_id_string->GetHashCode();
}

#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)

void SplitArgumentsIntoVector(std::string* args,
                              std::vector<std::string>* result) {
  SB_DCHECK(args);
  SB_DCHECK(result);
  while (!args->empty()) {
    size_t next = args->find(';');
    result->push_back(args->substr(0, next));
    if (next == std::string::npos) {
      return;
    }
    *args = args->substr(next + 1);
  }
}

// Parses a starboard: URI scheme by splitting args at ';' boundaries.
std::vector<std::string> ParseStarboardUri(const std::string& uri) {
  std::vector<std::string> result;
  result.push_back(GetArgvZero());

  size_t index = uri.find(':');
  if (index == std::string::npos) {
    return result;
  }

  std::string args = uri.substr(index + 1);
  SplitArgumentsIntoVector(&args, &result);

  return result;
}

void AddArgumentsFromFile(const char* path, std::vector<std::string>* args) {
  ScopedFile file(path, kSbFileOpenOnly | kSbFileRead);
  if (!file.IsValid()) {
    SB_LOG(INFO) << path << " is not valid for arguments.";
    return;
  }

  int64_t file_size = file.GetSize();
  if (file_size > kMaxArgumentFileSizeBytes) {
    SB_DLOG(ERROR) << "The arguments file is too big.";
    return;
  }

  if (file_size <= 0) {
    SB_DLOG(INFO) << "Arguments file is empty.";
    return;
  }

  std::string argument_string(file_size, '\0');
  int return_value = file.ReadAll(&argument_string[0], file_size);
  if (return_value < 0) {
    SB_DLOG(ERROR) << "Error while reading arguments from file.";
    return;
  }
  argument_string.resize(return_value);

  SplitArgumentsIntoVector(&argument_string, args);
}

void TryAddCommandArgsFromStarboardFile(std::vector<std::string>* args) {
  std::vector<char> content_directory(kSbFileMaxName);
  content_directory[0] = '\0';

  if (!SbSystemGetPath(kSbSystemPathContentDirectory, content_directory.data(),
                       content_directory.size())) {
    return;
  }

  std::string arguments_file_path(static_cast<char*>(content_directory.data()));
  arguments_file_path += kSbFileSepString;
  arguments_file_path += kStarboardArgumentsPath;

  AddArgumentsFromFile(arguments_file_path.c_str(), args);
}

void AddCommandArgsFromNetArgs(int64_t timeout,
                               std::vector<std::string>* args) {
  // Detect if NetArgs is enabled for this run. If so then receive and
  // then merge the arguments into this run.
  SB_LOG(INFO) << "Waiting for net args...";
  std::vector<std::string> net_args = NetArgsWaitForPayload(timeout);
  if (!net_args.empty()) {
    std::stringstream ss;
    ss << "Found Net Args:\n";
    for (const std::string& s : net_args) {
      ss << "  " << s << "\n";
    }
    SB_LOG(INFO) << ss.str();
  }
  // Merge command arguments.
  args->insert(args->end(), net_args.begin(), net_args.end());
}

#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)

std::unique_ptr<Application::Event> MakeDeepLinkEvent(
    const std::string& uri_string) {
  SB_LOG(INFO) << "Navigate to: [" << uri_string << "]";
  const size_t kMaxDeepLinkSize = 128 * 1024;
  const std::size_t uri_size = uri_string.size();
  if (uri_size > kMaxDeepLinkSize) {
    SB_NOTREACHED() << "App launch data too big: " << uri_size;
    return nullptr;
  }

  const int kBufferSize = static_cast<int>(uri_string.size()) + 1;
  char* deep_link = new char[kBufferSize];
  SB_DCHECK(deep_link);
  starboard::strlcpy(deep_link, uri_string.c_str(), kBufferSize);

  return std::unique_ptr<Application::Event>(
      new Application::Event(kSbEventTypeLink, deep_link,
                             Application::DeleteArrayDestructor<const char*>));
}

// Returns if |full_string| ends with |substring|.
bool ends_with(const std::string& full_string, const std::string& substring) {
  if (substring.length() > full_string.length()) {
    return false;
  }
  return std::equal(substring.rbegin(), substring.rend(), full_string.rbegin());
}

std::string GetBinaryName() {
  std::string full_binary_path = GetArgvZero();
  std::string::size_type index = full_binary_path.rfind(kSbFileSepChar);
  if (index == std::string::npos) {
    return full_binary_path;
  }

  return full_binary_path.substr(index + 1);
}

void OnDeviceAdded(DeviceWatcher ^, DeviceInformation ^) {
  SB_LOG(INFO) << "DisplayStatusWatcher::OnDeviceAdded";
  // We need delay to give time for the display initializing after connect.
  SbThreadSleep(15'000);

  MimeSupportabilityCache::GetInstance()->ClearCachedMimeSupportabilities();

  ApplicationUwp::Get()->Inject(
      new ApplicationUwp::Event(kSbEventTypeUnfreeze, NULL, NULL));
  ApplicationUwp::Get()->Inject(
      new ApplicationUwp::Event(kSbEventTypeReveal, NULL, NULL));
  ApplicationUwp::Get()->Inject(
      new ApplicationUwp::Event(kSbEventTypeFocus, NULL, NULL));
}

void OnDeviceRemoved(DeviceWatcher ^, DeviceInformationUpdate ^) {
  // Without signing on OnDeviceRemoved, callback OnDeviceAdded doesn't work.
  SB_LOG(INFO) << "DisplayStatusWatcher::OnDeviceRemoved";

  MimeSupportabilityCache::GetInstance()->ClearCachedMimeSupportabilities();

  ApplicationUwp::Get()->Inject(
      new ApplicationUwp::Event(kSbEventTypeBlur, NULL, NULL));
  ApplicationUwp::Get()->Inject(
      new ApplicationUwp::Event(kSbEventTypeConceal, NULL, NULL));
  ApplicationUwp::Get()->Inject(
      new ApplicationUwp::Event(kSbEventTypeFreeze, NULL, NULL));
}

}  // namespace

namespace shared {
namespace win32 {
// Called into drm_system_playready.cc
extern void DrmSystemOnUwpResume();
}  // namespace win32
}  // namespace shared

ref class App sealed : public IFrameworkView {
 public:
  App(int64_t start_time)
      : application_start_time_{start_time},
        previously_activated_(false),
#if SB_API_VERSION >= 15
        application_(SbEventHandle),
#endif  // SB_API_VERSION >= 15
        is_online_(true) {
  }

  // IFrameworkView methods.
  virtual void Initialize(CoreApplicationView ^ application_view) {
    // The following incantation creates a DisplayRequest and obtains
    // its underlying COM interface.
    ComPtr<IInspectable> inspectable = reinterpret_cast<IInspectable*>(
        ref new Windows::System::Display::DisplayRequest());
    ComPtr<ABI::Windows::System::Display::IDisplayRequest> dr;
    inspectable.As(&dr);
    display_request = dr.Detach();

    SbAudioSinkPrivate::Initialize();
    Windows::Networking::Connectivity::NetworkInformation::
        NetworkStatusChanged += ref new Windows::Networking::Connectivity::
            NetworkStatusChangedEventHandler(this,
                                             &App::OnNetworkStatusChanged);
    CoreApplication::Suspending +=
        ref new EventHandler<SuspendingEventArgs ^>(this, &App::OnSuspending);
    CoreApplication::Resuming +=
        ref new EventHandler<Object ^>(this, &App::OnResuming);
    application_view->Activated +=
        ref new TypedEventHandler<CoreApplicationView ^, IActivatedEventArgs ^>(
            this, &App::OnActivated);

    MimeSupportabilityCache::GetInstance()->SetCacheEnabled(true);
    KeySystemSupportabilityCache::GetInstance()->SetCacheEnabled(true);
  }

  virtual void SetWindow(CoreWindow ^ window) {
    ApplicationUwp::Get()->SetCoreWindow(window);
    window->KeyUp += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(
        this, &App::OnKeyUp);
    window->KeyDown += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(
        this, &App::OnKeyDown);
  }

  virtual void Load(Platform::String ^ entry_point) {
    entry_point_ = wchar_tToUTF8(entry_point->Data());
  }

  virtual void Run() {
#if SB_API_VERSION >= 15
    main_return_value =
        SbRunStarboardMain(static_cast<int>(argv_.size()),
                           const_cast<char**>(argv_.data()), SbEventHandle);
#else
    main_return_value = application_.Run(static_cast<int>(argv_.size()),
                                         const_cast<char**>(argv_.data()));
#endif  // SB_API_VERSION >= 15
  }
  virtual void Uninitialize() {
    SbAudioSinkPrivate::TearDown();
    display_request->Release();
    display_request = nullptr;
  }

  void CompleteSuspendDeferral() {
    if (suspend_deferral_ != nullptr) {
      // Completing the deferral results in the app being suspended by the OS.
      SB_LOG(INFO) << "App is ready to be suspended.";
      suspend_deferral_->Complete();
      suspend_deferral_ = nullptr;
    }
  }

  void ExtendedExecutionSessionRevoked(Object ^ sender,
                                       ExtendedExecutionRevokedEventArgs ^
                                           args) {
    CompleteSuspendDeferral();
  }

  void ForceQuit() {
    SB_LOG(ERROR) << "Application is not safe to suspend, forcing exit.";
    ApplicationUwp::Get()->DispatchAndDelete(
        new ApplicationUwp::Event(kSbEventTypeStop, NULL, NULL));
    auto extended_resources_manager =
        shared::uwp::ExtendedResourcesManager::GetInstance();
    if (extended_resources_manager) {
      extended_resources_manager->Quit();
    }
  }

  void OnNetworkStatusChanged(Object ^ sender) {
    auto connection_profile = Windows::Networking::Connectivity::
        NetworkInformation::GetInternetConnectionProfile();
    bool is_online =
        connection_profile &&
        connection_profile->GetNetworkConnectivityLevel() !=
            Windows::Networking::Connectivity::NetworkConnectivityLevel::None;

    // Only inject event if the online status changed.
    if (is_online != is_online_) {
      auto* application = starboard::shared::starboard::Application::Get();

      // Verify we have an application and dispatcher before injecting events.
      if (application == nullptr) {
        SB_LOG(ERROR) << "OnNetworkStatusChanged has no application.";
        SB_DCHECK(false);
        return;
      }
      if (starboard::shared::uwp::GetDispatcher().Get() == nullptr) {
        SB_LOG(ERROR) << "OnNetworkStatusChanged has no dispatcher.";
        SB_DCHECK(false);
        return;
      }

      if (is_online) {
        application->InjectOsNetworkConnectedEvent();
      } else {
        application->InjectOsNetworkDisconnectedEvent();
      }
      is_online_ = is_online;
    }
  }

  void OnSuspending(Platform::Object ^ sender, SuspendingEventArgs ^ args) {
    // Request deferral of the suspending operation. This ensures that the app
    // does not immediately get suspended when this function returns.
    suspend_deferral_ = args->SuspendingOperation->GetDeferral();

    auto extended_resources_manager =
        shared::uwp::ExtendedResourcesManager::GetInstance();
    bool is_safe_to_suspend = extended_resources_manager->IsSafeToSuspend();

    // Request extended execution during which we will suspend the app and
    // release extended resources.
    auto session = ref new ExtendedExecutionSession();
    session->Reason = ExtendedExecutionReason::SavingData;
    session->Description = "Suspending...";

    // If the extended execution session gets revoked, we have to complete
    // the deferral.
    Windows::Foundation::EventRegistrationToken revoked_token =
        session->Revoked +=
        ref new TypedEventHandler<Object ^,
                                  ExtendedExecutionRevokedEventArgs ^>(
            this, &App::ExtendedExecutionSessionRevoked);
    Concurrency::create_task(session->RequestExtensionAsync())
        .then([this, is_safe_to_suspend,
               extended_resources_manager](ExtendedExecutionResult result) {
          // Suspend the app and release extended resources during the extended
          // session.

          // Note if we dispatch "suspend" here before pause, application.cc
          // will inject the "pause" which will cause us to go async which
          // will cause us to not have completed the suspend operation before
          // returning, which UWP requires.
          ApplicationUwp::Get()->DispatchAndDelete(
              new ApplicationUwp::Event(kSbEventTypeBlur, NULL, NULL));
          ApplicationUwp::Get()->DispatchAndDelete(
              new ApplicationUwp::Event(kSbEventTypeConceal, NULL, NULL));
          ApplicationUwp::Get()->DispatchAndDelete(
              new ApplicationUwp::Event(kSbEventTypeFreeze, NULL, NULL));
          extended_resources_manager->ReleaseExtendedResources();
          if (!extended_resources_manager->IsSafeToSuspend()) {
            ForceQuit();
          }
        })
        .then([this, is_safe_to_suspend, session, revoked_token]() {
          // The extended session has completed, we are ready to be suspended
          // now.
          session->Revoked -= revoked_token;
          delete session;

          CompleteSuspendDeferral();
        });
    if (!is_safe_to_suspend) {
      ForceQuit();
    }
  }

  void OnResuming(Platform::Object ^ sender, Platform::Object ^ args) {
    SB_LOG(INFO) << "Resuming application.";
    ApplicationUwp::Get()->DispatchAndDelete(
        new ApplicationUwp::Event(kSbEventTypeUnfreeze, NULL, NULL));
    ApplicationUwp::Get()->DispatchAndDelete(
        new ApplicationUwp::Event(kSbEventTypeReveal, NULL, NULL));
    ApplicationUwp::Get()->DispatchAndDelete(
        new ApplicationUwp::Event(kSbEventTypeFocus, NULL, NULL));
    shared::win32::DrmSystemOnUwpResume();
    shared::uwp::ExtendedResourcesManager::GetInstance()
        ->AcquireExtendedResources();
  }

  void OnKeyUp(CoreWindow ^ sender, KeyEventArgs ^ args) {
    ApplicationUwp::Get()->OnKeyEvent(sender, args, true);
  }

  void OnKeyDown(CoreWindow ^ sender, KeyEventArgs ^ args) {
    ApplicationUwp::Get()->OnKeyEvent(sender, args, false);
  }

  void OnActivated(CoreApplicationView ^ application_view,
                   IActivatedEventArgs ^ args) {
    SB_LOG(INFO) << "OnActivated";
    shared::uwp::ExtendedResourcesManager::GetInstance()
        ->AcquireExtendedResources();

    std::string start_url = entry_point_;
    bool command_line_set = false;

    // Please see application lifecycle description:
    // https://docs.microsoft.com/en-us/windows/uwp/launch-resume/app-lifecycle
    // Note that this document was written for Xaml apps not core apps,
    // so for us the precise API is a little different.
    // The substance is that, while OnActivated is definitely called the
    // first time the application is started, it may additionally called
    // in other cases while the process is already running. Starboard
    // applications cannot fully restart in a process lifecycle,
    // so we interpret the first activation and the subsequent ones differently.
    if (args->Kind == ActivationKind::Protocol) {
      Uri ^ uri = dynamic_cast<IProtocolActivatedEventArgs ^>(args)->Uri;

#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
      // The starboard: scheme provides commandline arguments, but that's
      // only allowed during a process's first activation.
      std::string scheme = platformStringToString(uri->SchemeName);
      if (!previously_activated_ && ends_with(scheme, "-starboard")) {
        std::string uri_string = wchar_tToUTF8(uri->RawUri->Data());
        // args_ is a vector of std::string, but argv_ is a vector of
        // char* into args_ so as to compose a char**.
        args_ = ParseStarboardUri(uri_string);
        for (const std::string& arg : args_) {
          argv_.push_back(arg.c_str());
        }

        ApplicationUwp::Get()->SetCommandLine(static_cast<int>(argv_.size()),
                                              argv_.data());
        command_line_set = true;
      }
#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
      if (uri->SchemeName->Equals("youtube") ||
          uri->SchemeName->Equals("youtube-tv") ||
          uri->SchemeName->Equals("ms-xbl-07459769")) {
        std::string uri_string = platformStringToString(uri->RawUri);

        // Strip the protocol from the uri.
        size_t index = uri_string.find(':');
        if (index != std::string::npos) {
          uri_string = uri_string.substr(index + 1);
        }

        ProcessDeepLinkUri(&uri_string);
      }
    } else if (args->Kind == ActivationKind::DialReceiver) {
      DialReceiverActivatedEventArgs ^ dial_args =
          dynamic_cast<DialReceiverActivatedEventArgs ^>(args);
      SB_CHECK(dial_args);
      Platform::String ^ arguments = dial_args->Arguments;
      if (previously_activated_) {
        std::string uri_string =
            kDialParamPrefix + platformStringToString(arguments);
        ProcessDeepLinkUri(&uri_string);
      } else {
        std::string activation_args = "--url=";
        activation_args.append(start_url);
        activation_args.append("?");
        activation_args.append(platformStringToString(arguments));
        SB_DLOG(INFO) << "Dial Activation url: " << activation_args;
        args_.push_back(GetArgvZero());
        args_.push_back(activation_args);
        // Set partition URL in case start_url is the main app first run
        // special case.
        std::string partition_arg = "--local_storage_partition_url=";
        partition_arg.append(entry_point_);
        args_.push_back(partition_arg);
        for (const std::string& arg : args_) {
          argv_.push_back(arg.c_str());
        }
        ApplicationUwp::Get()->SetCommandLine(static_cast<int>(argv_.size()),
                                              argv_.data());
        command_line_set = true;
      }
    }
    previous_activation_kind_ = args->Kind;

    if (!previously_activated_) {
      if (!command_line_set) {
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
        TryAddCommandArgsFromStarboardFile(&args_);
        CommandLine cmd_line(args_);
        if (cmd_line.HasSwitch(kNetArgsCommandSwitchWait)) {
          // Wait for net args is flaky and needs extended wait time on Xbox.
          int64_t timeout_usec = 30'000'000;  // 30 seconds
          std::string val = cmd_line.GetSwitchValue(kNetArgsCommandSwitchWait);
          if (!val.empty()) {
            timeout_usec = atoi(val.c_str());
          }
          AddCommandArgsFromNetArgs(timeout_usec, &args_);
        }
#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)

        if (!CommandLine(args_).HasSwitch("url")) {
          args_.push_back(GetArgvZero());
          std::string start_url_arg = "--url=";
          start_url_arg.append(start_url);
          args_.push_back(start_url_arg);
          std::string partition_arg = "--local_storage_partition_url=";
          partition_arg.append(entry_point_);
          args_.push_back(partition_arg);
        }

        for (auto& arg : args_) {
          argv_.push_back(arg.c_str());
        }

        ApplicationUwp::Get()->SetCommandLine(static_cast<int>(argv_.size()),
                                              argv_.data());
      }

      ApplicationUwp* application_uwp = ApplicationUwp::Get();
      const CommandLine* command_line = application_uwp->GetCommandLine();

#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
      if (command_line->HasSwitch(kWatchDogLog)) {
        // Launch a thread.
        std::string switch_val = command_line->GetSwitchValue(kWatchDogLog);
        auto uwp_dir =
            Windows::Storage::ApplicationData::Current->LocalCacheFolder;
        std::stringstream ss;
        ss << platformStringToString(uwp_dir->Path) << "/" << switch_val;
        shared::uwp::StartWatchdogLog(ss.str());
      }

      if (command_line->HasSwitch(kNetLogCommandSwitchWait)) {
        int64_t timeout_usec = 1'000'000;  // 1 second
        std::string val =
            command_line->GetSwitchValue(kNetLogCommandSwitchWait);
        if (!val.empty()) {
          timeout_usec = atoi(val.c_str());
        }
        NetLogWaitForClientConnected(timeout_usec);
      }

      if (command_line->HasSwitch(kLogPathSwitch)) {
        std::stringstream ss;
        ss << platformStringToString(
            Windows::Storage::ApplicationData::Current->LocalCacheFolder->Path);
        ss << "\\"
           << "" << command_line->GetSwitchValue(kLogPathSwitch);
        std::string full_path_log_file = ss.str();
        shared::uwp::OpenLogFileWin32(full_path_log_file.c_str());
      } else {
#if !defined(COBALT_BUILD_TYPE_GOLD)
        // Log to a file on the last removable device available (probably the
        // most recently added removable device).
        if (KnownFolders::RemovableDevices != nullptr) {
          concurrency::create_task(
              KnownFolders::RemovableDevices->GetFoldersAsync())
              .then(
                  [](concurrency::task<IVectorView<StorageFolder ^> ^> result) {
                    IVectorView<StorageFolder ^> ^ results;
                    try {
                      results = result.get();
                    } catch (Platform::Exception ^) {
                      SB_LOG(ERROR)
                          << "Unable to open log file in RemovableDevices";
                      return;
                    }

                    if (results->Size == 0) {
                      return;
                    }

                    StorageFolder ^ folder = results->GetAt(results->Size - 1);
                    Calendar ^ now = ref new Calendar();
                    char filename[128];
                    snprintf(filename, sizeof(filename),
                             "cobalt_log_%04d%02d%02d_%02d%02d%02d.txt",
                             now->Year, now->Month, now->Day,
                             now->Hour + now->FirstHourInThisPeriod,
                             now->Minute, now->Second);
                    shared::uwp::OpenLogFileUWP(folder, filename);
                  });
        }
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
      }
#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
      SB_LOG(INFO) << "Starting " << GetBinaryName();

      CoreWindow::GetForCurrentThread()->Activate();
      // Call DispatchStart async so the UWP system thinks we're activated.
      // Some tools seem to want the application to be activated before
      // interacting with them, some things are disallowed during activation
      // (such as exiting), and DispatchStart (for example) runs
      // automated tests synchronously.
      RunInMainThreadAsync([this]() {
        ApplicationUwp::Get()->DispatchStart(application_start_time_);
      });
    }
    previously_activated_ = true;
  }

 private:
  void ProcessDeepLinkUri(std::string* uri_string) {
    SB_DCHECK(uri_string);
    if (previously_activated_) {
      std::unique_ptr<Application::Event> event =
          MakeDeepLinkEvent(*uri_string);
      SB_DCHECK(event);
      ApplicationUwp::Get()->Inject(event.release());
    } else {
      ApplicationUwp::Get()->SetStartLink(uri_string->c_str());
    }
  }

  std::string entry_point_;
  bool is_online_;
  bool previously_activated_;
  // Only valid if previously_activated_ is true
  ActivationKind previous_activation_kind_;
  std::vector<std::string> args_;
  std::vector<const char*> argv_;

  shared::uwp::ApplicationUwp application_;
  SuspendingDeferral ^ suspend_deferral_ = nullptr;
  int64_t application_start_time_;
};

ref class Direct3DApplicationSource sealed : IFrameworkViewSource {
 public:
  Direct3DApplicationSource(int64_t start_time)
      : application_start_time_{start_time} {}
  virtual IFrameworkView ^ CreateView() {
    return ref new App(application_start_time_);
  } private : int64_t application_start_time_;
};

namespace shared {
namespace uwp {

void DisplayStatusWatcher::CreateWatcher() {
  Platform::Collections::Vector<Platform::String ^> ^ requestedProperties =
      ref new Platform::Collections::Vector<Platform::String ^>();
  requestedProperties->Append("System.Devices.InterfaceClassGuid");
  requestedProperties->Append("System.ItemNameDisplay");
  watcher_ = DeviceInformation::CreateWatcher(
      const_cast<Platform::String ^>(kGenericPnpMonitorAqs),
      requestedProperties);
  SB_CHECK(watcher_);
  watcher_->Added +=
      ref new TypedEventHandler<DeviceWatcher ^, DeviceInformation ^>(
          &OnDeviceAdded);
  watcher_->Removed +=
      ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>(
          &OnDeviceRemoved);
  watcher_->Start();
}

bool DisplayStatusWatcher::IsWatcherStarted() {
  SB_CHECK(watcher_);
  DeviceWatcherStatus status = watcher_->Status;
  return (status == DeviceWatcherStatus::Started) ||
         (status == DeviceWatcherStatus::EnumerationCompleted);
}

void DisplayStatusWatcher::StopWatcher() {
  SB_CHECK(watcher_);
  if (IsWatcherStarted()) {
    watcher_->Stop();
  }
}

#if SB_API_VERSION >= 15
ApplicationUwp::ApplicationUwp(SbEventHandleCallback sb_event_handle_callback)
    : shared::starboard::Application(sb_event_handle_callback),
      window_(kSbWindowInvalid),
#else
ApplicationUwp::ApplicationUwp()
    : window_(kSbWindowInvalid),
#endif  // SB_API_VERSION >= 15
      localized_strings_(SbSystemGetLocaleId()),
      device_id_(MakeDeviceId()) {
  SbWindowOptions options;
  SbWindowSetDefaultOptions(&options);
  window_size_ = options.size;
  analog_thumbstick_thread_.reset(new AnalogThumbstickThread(this));
}

ApplicationUwp::~ApplicationUwp() {
  SB_CHECK(watcher_);
  {
    ScopedLock lock(time_event_mutex_);
    timer_event_map_.clear();
  }
  watcher_->StopWatcher();
  analog_thumbstick_thread_.reset(nullptr);
}

void ApplicationUwp::Initialize() {}

void ApplicationUwp::Teardown() {
  CloseWatchdogLog();
}

Application::Event* ApplicationUwp::GetNextEvent() {
  SB_NOTREACHED();
  return nullptr;
}

SbWindow ApplicationUwp::CreateWindowForUWP(const SbWindowOptions*) {
  // TODO: Determine why SB_DCHECK(IsCurrentThread()) fails in nplb, fix it,
  // and add back this check.

  if (SbWindowIsValid(window_)) {
    return kSbWindowInvalid;
  }

  if (!watcher_) {
    watcher_ = ref new shared::uwp::DisplayStatusWatcher();
    watcher_->CreateWatcher();
  }

  window_size_ = GetPreferredWindowSize();

  window_ = new SbWindowPrivate(window_size_.width, window_size_.height);
  return window_;
}

SbWindowSize ApplicationUwp::GetVisibleAreaSize() {
  SbWindowSize size{};
  if (SbWindowGetSize(window_, &size)) {
    return size;
  }
  return window_size_;
}

SbWindowSize ApplicationUwp::GetPreferredWindowSize() {
  bool scale_enabled = true;
  if (ApiInformation::IsApiContractPresent(
          "Windows.UI.ViewManagement.ViewManagementViewScalingContract", 1)) {
    // Use unscaled layout where possible
    scale_enabled = !ApplicationViewScaling::TrySetDisableLayoutScaling(true);
  }

  auto app_view = ApplicationView::GetForCurrentView();
  bool is_fullscreen = app_view->IsFullScreenMode;

  if (!is_fullscreen && scale_enabled &&
      ApiInformation::IsApiContractPresent(
          "Windows.Xbox.ApplicationResourcesContract", 1)) {
    // Always use full screen mode for XBox
    is_fullscreen = app_view->TryEnterFullScreenMode();
  }

  UpdateDisplayPreferredMode();
  int width = 0;
  int height = 0;
  auto display_mode = ApplicationUwp::Get()->GetPreferredModeHdr();
  if (!display_mode) {
    display_mode = ApplicationUwp::Get()->GetPreferredModeHdmi();
  }
  if (display_mode) {
    width = display_mode->ResolutionWidthInRawPixels;
    height = display_mode->ResolutionHeightInRawPixels;
  } else {
    auto bounds = app_view->VisibleBounds;
    auto scaleFactor =
        DisplayInformation::GetForCurrentView()->RawPixelsPerViewPixel;
    width = bounds.Width * scaleFactor;
    height = bounds.Height * scaleFactor;
  }
  SB_LOG(INFO) << "Preferred window size is " << width << " x " << height
               << "\nScaling is " << (scale_enabled ? "enabled" : "disabled")
               << "\nFull Screen mode is " << (is_fullscreen ? "ON" : "OFF");

  return SbWindowSize{width, height};
}

bool ApplicationUwp::DestroyWindow(SbWindow window) {
  // TODO: Determine why SB_DCHECK(IsCurrentThread()) fails in nplb, fix it,
  // and add back this check.

  if (!SbWindowIsValid(window)) {
    SB_DLOG(ERROR) << __FUNCTION__ << ": Invalid context.";
    return false;
  }

  auto app_view = ApplicationView::GetForCurrentView();
  if (app_view->IsFullScreenMode &&
      ApiInformation::IsApiContractPresent(
          "Windows.Xbox.ApplicationResourcesContract", 1)) {
    app_view->ExitFullScreenMode();
  }

  SB_DCHECK(window_ == window);
  delete window;
  window_ = kSbWindowInvalid;

  return true;
}

void ApplicationUwp::UpdateDisplayPreferredMode() {
  ScopedLock lock(preferred_display_mode_mutex_);
  preferred_display_mode_hdmi_ = nullptr;
  preferred_display_mode_hdr_ = nullptr;
  if (!ApiInformation::IsTypePresent(
          "Windows.Graphics.Display.Core.HdmiDisplayInformation")) {
    return;
  }

  auto hdmi_display_info = HdmiDisplayInformation::GetForCurrentView();
  if (!hdmi_display_info) {
    return;
  }

  preferred_display_mode_hdmi_ = hdmi_display_info->GetCurrentDisplayMode();
  for (auto mode : hdmi_display_info->GetSupportedDisplayModes()) {
    // Check that resolution matches the preferred display mode.
    if (mode->ResolutionWidthInRawPixels !=
            preferred_display_mode_hdmi_->ResolutionWidthInRawPixels ||
        mode->ResolutionHeightInRawPixels !=
            preferred_display_mode_hdmi_->ResolutionHeightInRawPixels) {
      continue;
    }
    // Verify HDR metadata and transfer function are supported.
    if (!mode->Is2086MetadataSupported || !mode->IsSmpte2084Supported) {
      continue;
    }
    // Verify we have enough bits per pixel and the correct color space for HDR.
    if (mode->BitsPerPixel < kYuv420BitsPerPixelForHdr10Mode ||
        mode->ColorSpace != HdmiDisplayColorSpace::BT2020) {
      continue;
    }
    // We don't serve 4k HDR videos over 60fps, skipping display modes that will
    // consume more power than needed.
    if (mode->ResolutionWidthInRawPixels >= k4kResolutionWidth &&
        mode->ResolutionHeightInRawPixels >= k4kResolutionHeight &&
        mode->RefreshRate > kHdr4kRefreshRateMaximum) {
      continue;
    }
    if (!preferred_display_mode_hdr_ ||
        preferred_display_mode_hdr_->RefreshRate < mode->RefreshRate) {
      preferred_display_mode_hdr_ = mode;
    }
  }
}

bool ApplicationUwp::DispatchNextEvent() {
  core_window_->Activate();
  core_window_->Dispatcher->ProcessEvents(
      CoreProcessEventsOption::ProcessUntilQuit);
  return false;
}

Windows::Media::Protection::HdcpSession ^ ApplicationUwp::GetHdcpSession() {
  if (!hdcp_session_) {
    hdcp_session_ = ref new HdcpSession();
  }
  return hdcp_session_;
}

void ApplicationUwp::ResetHdcpSession() {
  // delete will call the destructor, but not free memory.
  // The destructor is called explicitly so that HDCP session can be
  // torn down immediately.
  if (hdcp_session_) {
    delete hdcp_session_;
    hdcp_session_ = nullptr;
  }
}

void ApplicationUwp::Inject(Application::Event* event) {
  RunInMainThreadAsync([this, event]() {
    bool result = DispatchAndDelete(event);
    if (!result) {
      NetLogFlushThenClose();
      CoreApplication::Exit();
    }
  });
}

void ApplicationUwp::InjectKeypress(SbKey key) {
  if (!SbWindowIsValid(window_)) {
    return;
  }
  std::unique_ptr<SbInputData> press_data(new SbInputData());
  std::unique_ptr<SbInputData> unpress_data(new SbInputData());

  memset(press_data.get(), 0, sizeof(*press_data));
  press_data->window = window_;
  press_data->device_type = kSbInputDeviceTypeKeyboard;
  press_data->device_id = device_id();
  press_data->key = key;
  press_data->type = kSbInputEventTypePress;

  *unpress_data = *press_data;
  unpress_data->type = kSbInputEventTypeUnpress;

  Inject(new Event(kSbEventTypeInput, press_data.release(),
                   &Application::DeleteDestructor<SbInputData>));
  Inject(new Event(kSbEventTypeInput, unpress_data.release(),
                   &Application::DeleteDestructor<SbInputData>));
}

void ApplicationUwp::InjectTimedEvent(Application::TimedEvent* timed_event) {
  int64_t delay_usec = timed_event->target_time - CurrentMonotonicTime();
  if (delay_usec < 0) {
    delay_usec = 0;
  }

  // TimeSpan ticks are, like FILETIME, 100ns
  const int64_t kTicksPerUsec = 10;

  TimeSpan timespan;
  timespan.Duration = delay_usec * kTicksPerUsec;

  ScopedLock lock(time_event_mutex_);
  ThreadPoolTimer ^ timer = ThreadPoolTimer::CreateTimer(
      ref new TimerElapsedHandler([this, timed_event](ThreadPoolTimer ^ timer) {
        RunInMainThreadAsync([this, timed_event]() {
          // Even if the event is canceled, the callback can still fire.
          // Thus, the existence of event in timer_event_map_ is used
          // as a source of truth.
          std::size_t number_erased = 0;
          {
            ScopedLock lock(time_event_mutex_);
            number_erased = timer_event_map_.erase(timed_event->id);
          }
          if (number_erased > 0) {
            timed_event->callback(timed_event->context);
          }
        });
      }),
      timespan);
  timer_event_map_.emplace(timed_event->id, timer);
}

void ApplicationUwp::CancelTimedEvent(SbEventId event_id) {
  ScopedLock lock(time_event_mutex_);
  auto it = timer_event_map_.find(event_id);
  if (it == timer_event_map_.end()) {
    return;
  }
  it->second->Cancel();
  timer_event_map_.erase(it);
}

Application::TimedEvent* ApplicationUwp::GetNextDueTimedEvent() {
  SB_NOTIMPLEMENTED();
  return nullptr;
}

int64_t ApplicationUwp::GetNextTimedEventTargetTime() {
  SB_NOTIMPLEMENTED();
  return 0;
}

void ApplicationUwp::OnJoystickUpdate(SbKey key, SbInputVector input_vector) {
  if (!SbWindowIsValid(window_)) {
    return;
  }
  scoped_ptr<SbInputData> data(new SbInputData());
  memset(data.get(), 0, sizeof(*data));
  data->window = window_;
  data->type = kSbInputEventTypeMove;
  data->device_type = kSbInputDeviceTypeGamepad;
  data->device_id = device_id();
  data->key = key;
  data->character = 0;

  data->key_modifiers = kSbKeyModifiersNone;
  data->position = input_vector;

  SbKeyLocation key_location = kSbKeyLocationUnspecified;
  switch (key) {
    case kSbKeyGamepadLeftStickLeft:
    case kSbKeyGamepadLeftStickUp: {
      key_location = kSbKeyLocationLeft;
      break;
    }
    case kSbKeyGamepadRightStickLeft:
    case kSbKeyGamepadRightStickUp: {
      key_location = kSbKeyLocationRight;
      break;
    }
    default: {
      SB_NOTREACHED();
      break;
    }
  }

  data->key_location = key_location;
  Inject(new Event(kSbEventTypeInput, data.release(),
                   &Application::DeleteDestructor<SbInputData>));
}

Platform::String ^
    ApplicationUwp::GetString(const char* id, const char* fallback) const {
  return stringToPlatformString(localized_strings_.GetString(id, fallback));
}

bool ApplicationUwp::IsHdcpOn() {
  ScopedLock lock(hdcp_session_mutex_);

  return GetHdcpSession()->IsEffectiveProtectionAtLeast(kHDCPProtectionMode);
}

bool ApplicationUwp::TurnOnHdcp() {
  HdcpSetProtectionResult protection_result;
  {
    ScopedLock lock(hdcp_session_mutex_);

    protection_result = WaitForResult(
        GetHdcpSession()->SetDesiredMinProtectionAsync(kHDCPProtectionMode));
  }

  if (IsHdcpOn()) {
    return true;
  }

  // If the operation did not have intended result, log something.
  switch (protection_result) {
    case HdcpSetProtectionResult::Success:
      SB_LOG(INFO) << "Successfully set HDCP.";
      break;
    case HdcpSetProtectionResult::NotSupported:
      SB_LOG(INFO) << "HDCP is not supported.";
      break;
    case HdcpSetProtectionResult::TimedOut:
      SB_LOG(INFO) << "Setting HDCP timed out.";
      break;
    case HdcpSetProtectionResult::UnknownFailure:
      SB_LOG(INFO) << "Unknown failure returned while setting HDCP.";
      break;
  }

  return false;
}

bool ApplicationUwp::TurnOffHdcp() {
  {
    ScopedLock lock(hdcp_session_mutex_);
    ResetHdcpSession();
  }
  bool success = !IsHdcpOn();
  return success;
}

// TODO: Consolidate this function with TurnOfHdcp() and TurnOffHdcp().
bool ApplicationUwp::SetOutputProtection(bool should_enable_dhcp) {
  bool is_hdcp_on = IsHdcpOn();

  if (is_hdcp_on == should_enable_dhcp) {
    return true;
  }

  SB_LOG(INFO) << "Attempting to "
               << (should_enable_dhcp ? "enable" : "disable")
               << " output protection.  Current status: "
               << (is_hdcp_on ? "enabled" : "disabled");
  int64_t tick = CurrentMonotonicTime();

  bool hdcp_success = false;
  if (should_enable_dhcp) {
    hdcp_success = TurnOnHdcp();
  } else {
    hdcp_success = TurnOffHdcp();
  }

  is_hdcp_on = (hdcp_success ? should_enable_dhcp : !should_enable_dhcp);

  int64_t tock = CurrentMonotonicTime();
  SB_LOG(INFO) << "Output protection is "
               << (is_hdcp_on ? "enabled" : "disabled")
               << ".  Toggling HDCP took " << (tock - tick) / 1000
               << " milliseconds.";
  return hdcp_success;
}

Platform::Agile<Windows::UI::Core::CoreDispatcher> GetDispatcher() {
  return ApplicationUwp::Get()->GetDispatcher();
}

Platform::Agile<Windows::Media::SystemMediaTransportControls>
GetTransportControls() {
  return ApplicationUwp::Get()->GetTransportControls();
}

void DisplayRequestActive() {
  RunInMainThreadAsync([]() {
    if (display_request != nullptr) {
      display_request->RequestActive();
    }
  });
}

void DisplayRequestRelease() {
  RunInMainThreadAsync([]() {
    if (display_request != nullptr) {
      display_request->RequestRelease();
    }
  });
}

void InjectKeypress(SbKey key) {
  ApplicationUwp::Get()->InjectKeypress(key);
}

namespace {

// Calls CoreApplication::Run() on a new thread to free up the main thread.
// This allows all extended resources related operations to be run on the main
// thread.
class CoreApplicationThread : public ::starboard::Thread {
 public:
  explicit CoreApplicationThread(int64_t start_time)
      : application_start_time_{start_time}, Thread("core_app") {}
  void Run() override {
    CoreApplication::Run(
        ref new Direct3DApplicationSource(application_start_time_));
    ExtendedResourcesManager::GetInstance()->Quit();
  }

 private:
  int64_t application_start_time_;
};

}  // namespace

int InternalMain() {
  volatile auto start_time = CurrentMonotonicTime();
  if (!IsDebuggerPresent()) {
    // By default, a Windows application will display a dialog box
    // when it crashes. This is extremely undesirable when run offline.
    // The following configures messages to be print to the console instead.
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
  }

  WSAData wsaData;
  int init_result = WSAStartup(
      MAKEWORD(kWinSockVersionMajor, kWinSockVersionMajor), &wsaData);

  SB_CHECK(init_result == 0);
  // WSAStartup returns the highest version that is supported up to the version
  // we request.
  SB_CHECK(LOBYTE(wsaData.wVersion) == kWinSockVersionMajor &&
           HIBYTE(wsaData.wVersion) == kWinSockVersionMinor);

  HRESULT hr = MFStartup(MF_VERSION);
  SB_DCHECK(SUCCEEDED(hr));

#if defined(COBALT_BUILD_TYPE_GOLD)
  // Early exit for gold builds on desktop as a security measure.
#if SB_API_VERSION < 15
  if (SbSystemGetDeviceType() == kSbSystemDeviceTypeDesktopPC) {
    return main_return_value;
  }
#else
  if (GetSystemPropertyString(kSbSystemPropertyDeviceType) ==
      kSystemDeviceTypeDesktopPC) {
    return main_return_value;
  }
#endif
#endif  // defined(COBALT_BUILD_TYPE_GOLD)

  shared::win32::RegisterMainThread();

  ExtendedResourcesManager extended_resources_manager;
  CoreApplicationThread thread(start_time);

  thread.Start();
  extended_resources_manager.Run();

  NetLogFlushThenClose();
  CoreApplication::Exit();

  MFShutdown();
  WSACleanup();

  return main_return_value;
}

#if SB_API_VERSION >= 15
extern "C" int SbRunStarboardMain(int argc,
                                  char** argv,
                                  SbEventHandleCallback callback) {
  return ApplicationUwp::Get()->Run(argc, argv);
}
#endif  // SB_API_VERSION >= 15

}  // namespace uwp
}  // namespace shared
}  // namespace starboard

[Platform::MTAThread] int main(Platform::Array<Platform::String ^> ^ args) {
  return starboard::shared::uwp::InternalMain();
}
