chromium/ash/system/phonehub/multidevice_feature_opt_in_view.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/phonehub/multidevice_feature_opt_in_view.h"

#include <memory>
#include <string>

#include "ash/constants/ash_features.h"
#include "ash/public/cpp/new_window_delegate.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/phonehub/phone_hub_metrics.h"
#include "ash/system/phonehub/phone_hub_tray.h"
#include "ash/system/phonehub/phone_hub_view_ids.h"
#include "ash/system/status_area_widget.h"
#include "chromeos/ash/components/multidevice/logging/logging.h"
#include "chromeos/ash/components/phonehub/multidevice_feature_access_manager.h"
#include "chromeos/ash/components/phonehub/util/histogram_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"

namespace ash {

using ash::phonehub::util::LogPermissionOnboardingPromoAction;
using ash::phonehub::util::LogPermissionOnboardingPromoShown;
using ash::phonehub::util::PermissionsOnboardingScreenEvent;
using ash::phonehub::util::PermissionsOnboardingSetUpMode;
using multidevice_setup::mojom::Feature;

namespace {

// URL of the multidevice settings page with the URL parameter that will
// start up the opt-in-flow.
// TODO: Update this URL once the new access setup dialog has been updated
constexpr char kMultideviceSettingsUrl[] =
    "chrome://os-settings/multidevice/"
    "features?showPhonePermissionSetupDialog&mode=%d";

PermissionsOnboardingSetUpMode GetPermissionSetupMode(
    phonehub::MultideviceFeatureAccessManager*
        multidevice_feature_access_manager) {
  bool can_request_notification_access =
      multidevice_feature_access_manager->GetNotificationAccessStatus() ==
      phonehub::MultideviceFeatureAccessManager::AccessStatus::
          kAvailableButNotGranted;
  bool can_request_apps_acess =
      features::IsEcheSWAEnabled() &&
      multidevice_feature_access_manager->IsAccessRequestAllowed(
          Feature::kEche) &&
      multidevice_feature_access_manager->GetAppsAccessStatus() ==
          phonehub::MultideviceFeatureAccessManager::AccessStatus::
              kAvailableButNotGranted;
  bool can_request_camera_roll_access =
      features::IsPhoneHubCameraRollEnabled() &&
      multidevice_feature_access_manager->IsAccessRequestAllowed(
          Feature::kPhoneHubCameraRoll) &&
      multidevice_feature_access_manager->GetCameraRollAccessStatus() ==
          phonehub::MultideviceFeatureAccessManager::AccessStatus::
              kAvailableButNotGranted;

  PA_LOG(INFO) << "MultideviceFeatureOptInView can_request_notification_access:"
               << can_request_notification_access
               << ", can_request_apps_acess:" << can_request_apps_acess
               << ", can_request_camera_roll_access:"
               << can_request_camera_roll_access;
  if (can_request_notification_access && can_request_camera_roll_access &&
      can_request_apps_acess) {
    return PermissionsOnboardingSetUpMode::kAllPermissions;
  } else if (can_request_notification_access && can_request_apps_acess &&
             !can_request_camera_roll_access) {
    return PermissionsOnboardingSetUpMode::kNotificationAndMessagingApps;
  } else if (can_request_apps_acess && can_request_camera_roll_access &&
             !can_request_notification_access) {
    return PermissionsOnboardingSetUpMode::kMessagingAppsAndCameraRoll;
  } else if (can_request_notification_access &&
             can_request_camera_roll_access && !can_request_apps_acess) {
    return PermissionsOnboardingSetUpMode::kNotificationAndCameraRoll;
  } else if (!can_request_notification_access &&
             !can_request_camera_roll_access && can_request_apps_acess) {
    return PermissionsOnboardingSetUpMode::kMessagingApps;
  } else if (!can_request_notification_access && !can_request_apps_acess &&
             can_request_camera_roll_access) {
    return PermissionsOnboardingSetUpMode::kCameraRoll;
  } else if (!can_request_camera_roll_access && !can_request_apps_acess &&
             can_request_notification_access) {
    return PermissionsOnboardingSetUpMode::kNotification;
  }

  return PermissionsOnboardingSetUpMode::kNone;
}

std::string GetMultiDeviceSettingUrl(
    PermissionsOnboardingSetUpMode permission_setup_mode) {
  return base::StringPrintf(kMultideviceSettingsUrl,
                            static_cast<int>(permission_setup_mode));
}

}  // namespace

MultideviceFeatureOptInView::MultideviceFeatureOptInView(
    phonehub::MultideviceFeatureAccessManager*
        multidevice_feature_access_manager)
    : SubFeatureOptInView(
          PhoneHubViewID::kMultideviceFeatureOptInView,
          GetPermissionSetupMode(multidevice_feature_access_manager)),
      multidevice_feature_access_manager_(multidevice_feature_access_manager) {
  DCHECK(multidevice_feature_access_manager_);
  setup_mode_ = GetPermissionSetupMode(multidevice_feature_access_manager_);
  access_manager_observation_.Observe(
      multidevice_feature_access_manager_.get());
  // Checks and updates its visibility upon creation.
  UpdateVisibility(/*was_visible=*/false);
}

MultideviceFeatureOptInView::~MultideviceFeatureOptInView() = default;

void MultideviceFeatureOptInView::SetUpButtonPressed() {
  // Opens the set up dialog in settings to start the opt in flow.
  LogPermissionOnboardingPromoAction(
      PermissionsOnboardingScreenEvent::kSetUpOrDone);
  // This intentionally uses GetInstance() to open an OS Settings page in ash.
  std::string url = GetMultiDeviceSettingUrl(setup_mode_);
  PA_LOG(INFO) << "MultideviceFeatureOptInView SetUpButtonPressed target url:"
               << url;
  NewWindowDelegate::GetInstance()->OpenUrl(
      GURL(url), NewWindowDelegate::OpenUrlFrom::kUserInteraction,
      NewWindowDelegate::Disposition::kNewForegroundTab);
  ClosePhoneHubBubble();
}

void MultideviceFeatureOptInView::DismissButtonPressed() {
  // Dismiss this view if user chose to opt out and update the bubble size.
  LogPermissionOnboardingPromoAction(
      PermissionsOnboardingScreenEvent::kDismissOrCancel);
  SetVisible(false);
  multidevice_feature_access_manager_->DismissSetupRequiredUi();
}

void MultideviceFeatureOptInView::OnNotificationAccessChanged() {
  UpdateVisibility(/*was_visible=*/GetVisible());
}

void MultideviceFeatureOptInView::OnCameraRollAccessChanged() {
  UpdateVisibility(/*was_visible=*/GetVisible());
}

void MultideviceFeatureOptInView::UpdateVisibility(bool was_visible) {
  DCHECK(multidevice_feature_access_manager_);
  // Refresh the permission status if changed
  phonehub::util::PermissionsOnboardingSetUpMode current_mode =
      GetPermissionSetupMode(multidevice_feature_access_manager_);
  if (current_mode != setup_mode_) {
    setup_mode_ = current_mode;
    SetSetUpMode(setup_mode_);
  }
  SetVisible(setup_mode_ != PermissionsOnboardingSetUpMode::kNone &&
             !multidevice_feature_access_manager_
                  ->HasMultideviceFeatureSetupUiBeenDismissed());
  if (!was_visible && GetVisible()) {
    LogPermissionOnboardingPromoShown(setup_mode_);
  }
  PreferredSizeChanged();
}

void MultideviceFeatureOptInView::ClosePhoneHubBubble() {
  // Close Phone Hub bubble in current display.
  views::Widget* const widget = GetWidget();
  // |widget| is null when this function is called before the view is added to a
  // widget (in unit tests).
  if (!widget) {
    return;
  }
  int64_t current_display_id =
      display::Screen::GetScreen()
          ->GetDisplayNearestWindow(widget->GetNativeWindow())
          .id();
  Shell::GetRootWindowControllerWithDisplayId(current_display_id)
      ->GetStatusAreaWidget()
      ->phone_hub_tray()
      ->CloseBubble();
}

BEGIN_METADATA(MultideviceFeatureOptInView)
END_METADATA

}  // namespace ash