blob: ccbe26b6792b55cc7e1f7ee45cbc2a413912e60b [file] [log] [blame]
// Copyright 2015 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.
// This file can be empty. Its purpose is to contain the relatively short lived
// definitions required for experimental flags.
#include "ios/chrome/browser/experimental_flags.h"
#include <dispatch/dispatch.h>
#import <Foundation/Foundation.h>
#include <string>
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_util.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/enhanced_bookmarks/enhanced_bookmark_switches_ios.h"
#include "components/variations/variations_associated_data.h"
#include "ios/chrome/browser/chrome_switches.h"
#include "ios/web/public/web_view_creation_util.h"
namespace {
NSString* const kEnableAlertOnBackgroundUpload =
@"EnableAlertsOnBackgroundUpload";
NSString* const kEnableViewCopyPasswords = @"EnableViewCopyPasswords";
NSString* const kHeuristicsForPasswordGeneration =
@"HeuristicsForPasswordGeneration";
const char* const kWKWebViewTrialName = "IOSUseWKWebView";
enum class WKWebViewEligibility {
// UNSET indicates that no explicit call to set eligibility has been made,
// nor has a default value been assumed due to checking eligibility.
UNSET,
ELIGIBLE,
INELIGIBLE
};
WKWebViewEligibility g_wkwebview_trial_eligibility =
WKWebViewEligibility::UNSET;
} // namespace
namespace experimental_flags {
bool IsAlertOnBackgroundUploadEnabled() {
return [[NSUserDefaults standardUserDefaults]
boolForKey:kEnableAlertOnBackgroundUpload];
}
bool IsBookmarkCollectionEnabled() {
// kEnhancedBookmarksExperiment flag could have values "", "1" and "0".
// "" - default, "0" - user opted out, "1" - user opted in. Tests also use
// the command line flag to force enhanced bookmark to be on.
// If none is specified, the finch experiment is checked. If not disabled in
// finch, the default is opt-in.
std::string switch_value =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kEnhancedBookmarksExperiment);
if (switch_value == "1")
return true;
if (switch_value == "0")
return false;
// Check if the finch experiment is turned on.
std::string group_name =
base::FieldTrialList::FindFullName("IOSNewBookmarksUI");
return !base::StartsWith(group_name, "Disabled",
base::CompareCase::INSENSITIVE_ASCII);
}
void SetWKWebViewTrialEligibility(bool eligible) {
// It's critical that the enabled state be consistently reported throughout
// the life of the app, so ensure that this has not already been set.
DCHECK(g_wkwebview_trial_eligibility == WKWebViewEligibility::UNSET);
g_wkwebview_trial_eligibility = eligible ? WKWebViewEligibility::ELIGIBLE
: WKWebViewEligibility::INELIGIBLE;
}
bool IsLRUSnapshotCacheEnabled() {
// Check if the experimental flag is forced on or off.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableLRUSnapshotCache)) {
return true;
} else if (command_line->HasSwitch(switches::kDisableLRUSnapshotCache)) {
return false;
}
// Check if the finch experiment is turned on.
std::string group_name =
base::FieldTrialList::FindFullName("IOSLRUSnapshotCache");
return base::StartsWith(group_name, "Enabled",
base::CompareCase::INSENSITIVE_ASCII);
}
// Helper method that returns true if it is safe to check the finch group for
// the IOSUseWKWebView experiment. Some users are ineligible to be in the
// trial, so for those users, this method returns false. If this method returns
// false, do not check for the current finch group, as doing so will incorrectly
// mark the current user as being in the experiment.
bool CanCheckWKWebViewExperiment() {
// True if this user is eligible for the WKWebView experiment and it is ok to
// check the experiment group.
static bool ok_to_check_finch = false;
static dispatch_once_t once;
dispatch_once(&once, ^{
// If g_wkwebview_trial_eligibility hasn't been set, default it to
// ineligible. This ensures future calls to try to set it will DCHECK.
if (g_wkwebview_trial_eligibility == WKWebViewEligibility::UNSET) {
g_wkwebview_trial_eligibility = WKWebViewEligibility::INELIGIBLE;
}
// If WKWebView isn't supported, don't activate the experiment at all. This
// avoids someone being slotted into the WKWebView bucket (and thus
// reporting as WKWebView), but actually running UIWebView.
if (!web::IsWKWebViewSupported()) {
ok_to_check_finch = false;
return;
}
// Check for a flag forcing a specific group. Even ineligible users can be
// opted into WKWebView if an override flag is set.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
bool trial_overridden =
command_line->HasSwitch(switches::kEnableIOSWKWebView) ||
command_line->HasSwitch(switches::kDisableIOSWKWebView);
// If the user isn't eligible for the trial (i.e., their state is such that
// they should not be automatically selected for the group), and there's no
// explicit override, don't check the group (again, to avoid having them
// report as part of a group at all).
if (g_wkwebview_trial_eligibility == WKWebViewEligibility::INELIGIBLE &&
!trial_overridden) {
ok_to_check_finch = false;
return;
}
ok_to_check_finch = true;
});
return ok_to_check_finch;
}
bool IsWKWebViewEnabled() {
if (!CanCheckWKWebViewExperiment()) {
return false;
}
// Now that it's been established that user is a candidate, set up the trial
// by checking the group.
std::string group_name =
base::FieldTrialList::FindFullName(kWKWebViewTrialName);
// Check if the experimental flag is turned on.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableIOSWKWebView))
return true;
else if (command_line->HasSwitch(switches::kDisableIOSWKWebView))
return false;
// Check if the finch experiment is turned on.
return !base::StartsWith(group_name, "Disabled",
base::CompareCase::INSENSITIVE_ASCII) &&
!base::StartsWith(group_name, "Control",
base::CompareCase::INSENSITIVE_ASCII);
}
bool IsTargetedToWKWebViewExperimentControlGroup() {
base::FieldTrial* trial = base::FieldTrialList::Find(kWKWebViewTrialName);
if (!trial)
return false;
std::string group_name = trial->GetGroupNameWithoutActivation();
return base::StartsWith(group_name, "Control",
base::CompareCase::INSENSITIVE_ASCII);
}
bool IsInWKWebViewExperimentControlGroup() {
if (!CanCheckWKWebViewExperiment()) {
return false;
}
std::string group_name =
base::FieldTrialList::FindFullName(kWKWebViewTrialName);
return base::StartsWith(group_name, "Control",
base::CompareCase::INSENSITIVE_ASCII);
}
std::string GetWKWebViewSearchParams() {
if (!CanCheckWKWebViewExperiment()) {
return std::string();
}
return variations::GetVariationParamValue(kWKWebViewTrialName, "esrch");
}
bool IsViewCopyPasswordsEnabled() {
NSString* viewCopyPasswordFlag = [[NSUserDefaults standardUserDefaults]
objectForKey:kEnableViewCopyPasswords];
if ([viewCopyPasswordFlag isEqualToString:@"Enabled"])
return true;
return false;
}
bool IsPasswordGenerationEnabled() {
// This call activates the field trial, if needed, so it must come before any
// early returns.
std::string group_name =
base::FieldTrialList::FindFullName("PasswordGeneration");
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableIOSPasswordGeneration))
return true;
if (command_line->HasSwitch(switches::kDisableIOSPasswordGeneration))
return false;
return group_name != "Disabled";
}
bool UseOnlyLocalHeuristicsForPasswordGeneration() {
if ([[NSUserDefaults standardUserDefaults]
boolForKey:kHeuristicsForPasswordGeneration]) {
return true;
}
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
return command_line->HasSwitch(
autofill::switches::kLocalHeuristicsOnlyForPasswordGeneration);
}
bool IsTabSwitcherEnabled() {
// Check if the experimental flag is forced on or off.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableTabSwitcher)) {
return true;
} else if (command_line->HasSwitch(switches::kDisableTabSwitcher)) {
return false;
}
// Check if the finch experiment is turned on.
std::string group_name = base::FieldTrialList::FindFullName("IOSTabSwitcher");
return base::StartsWith(group_name, "Enabled",
base::CompareCase::INSENSITIVE_ASCII);
}
} // namespace experimental_flags