Add PredictorFactory.

The PredictorFactory contains all the predictors names and types constants.
The factory proposes two static methods:
1. A method to get a PredictorType when passing a predictor name
2. A method to get a unique instance of a predictor when passing a
   PredictorType

Each predictor now returns the constant stored in the factory when
calling GetName()

Bug: 981147
Change-Id: Ib1069b069d8eb4fb45313aa4b9fbddd49f8bf84e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1688283
Reviewed-by: Navid Zolghadr <nzolghadr@chromium.org>
Reviewed-by: Ella Ge <eirage@chromium.org>
Commit-Queue: Axel Antoine <axantoine@google.com>
Cr-Commit-Position: refs/heads/master@{#675857}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 9c0059d1..2b2f9eb2 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -142,6 +142,7 @@
 #include "ui/display/display_features.h"
 #include "ui/display/display_switches.h"
 #include "ui/events/blink/blink_features.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 #include "ui/events/event_switches.h"
 #include "ui/gfx/switches.h"
 #include "ui/gl/buildflags.h"
@@ -985,22 +986,34 @@
 #endif  // defined(OS_ANDROID)
 
 const FeatureEntry::FeatureParam kResamplingInputEventsLSQEnabled[] = {
-    {"predictor", "lsq"}};
-
+    {"predictor", ui::input_prediction::kScrollPredictorNameLsq}};
 const FeatureEntry::FeatureParam kResamplingInputEventsKalmanEnabled[] = {
-    {"predictor", "kalman"}};
-
+    {"predictor", ui::input_prediction::kScrollPredictorNameKalman}};
 const FeatureEntry::FeatureParam
     kResamplingInputEventsKalmanTimeFilteredEnabled[] = {
-        {"predictor", "kalman_time_filtered"}};
+        {"predictor",
+         ui::input_prediction::kScrollPredictorNameKalmanTimeFiltered}};
+const FeatureEntry::FeatureParam kResamplingInputEventsLinearFirstEnabled[] = {
+    {"predictor", ui::input_prediction::kScrollPredictorNameLinearFirst}};
+const FeatureEntry::FeatureParam kResamplingInputEventsLinearSecondEnabled[] = {
+    {"predictor", ui::input_prediction::kScrollPredictorNameLinearSecond}};
 
 const FeatureEntry::FeatureVariation kResamplingInputEventsFeatureVariations[] =
-    {{"lsq", kResamplingInputEventsLSQEnabled,
+    {{ui::input_prediction::kScrollPredictorNameLsq,
+      kResamplingInputEventsLSQEnabled,
       base::size(kResamplingInputEventsLSQEnabled), nullptr},
-     {"kalman", kResamplingInputEventsKalmanEnabled,
+     {ui::input_prediction::kScrollPredictorNameKalman,
+      kResamplingInputEventsKalmanEnabled,
       base::size(kResamplingInputEventsKalmanEnabled), nullptr},
-     {"kalman time filtered", kResamplingInputEventsKalmanTimeFilteredEnabled,
-      base::size(kResamplingInputEventsKalmanTimeFilteredEnabled), nullptr}};
+     {ui::input_prediction::kScrollPredictorNameKalmanTimeFiltered,
+      kResamplingInputEventsKalmanTimeFilteredEnabled,
+      base::size(kResamplingInputEventsKalmanTimeFilteredEnabled), nullptr},
+     {ui::input_prediction::kScrollPredictorNameLinearFirst,
+      kResamplingInputEventsLinearFirstEnabled,
+      base::size(kResamplingInputEventsLinearFirstEnabled), nullptr},
+     {ui::input_prediction::kScrollPredictorNameLinearSecond,
+      kResamplingInputEventsLinearSecondEnabled,
+      base::size(kResamplingInputEventsLinearSecondEnabled), nullptr}};
 
 #if defined(OS_ANDROID)
 const FeatureEntry::FeatureParam kBottomOfflineIndicatorEnabled[] = {
diff --git a/content/renderer/input/input_event_prediction.cc b/content/renderer/input/input_event_prediction.cc
index 0f8b0b2..17bfa4b 100644
--- a/content/renderer/input/input_event_prediction.cc
+++ b/content/renderer/input/input_event_prediction.cc
@@ -9,9 +9,6 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "content/public/common/content_features.h"
-#include "ui/events/blink/prediction/empty_predictor.h"
-#include "ui/events/blink/prediction/kalman_predictor.h"
-#include "ui/events/blink/prediction/least_squares_predictor.h"
 
 using blink::WebInputEvent;
 using blink::WebMouseEvent;
@@ -23,12 +20,6 @@
 
 namespace {
 
-constexpr char kPredictor[] = "predictor";
-constexpr char kInputEventPredictorTypeLsq[] = "lsq";
-constexpr char kInputEventPredictorTypeEmpty[] = "empty";
-constexpr char kInputEventPredictorTypeKalmanTimeFiltered[] =
-    "kalman_time_filtered";
-
 constexpr uint32_t kPredictEventCount = 3;
 constexpr base::TimeDelta kPredictionInterval =
     base::TimeDelta::FromMilliseconds(8);
@@ -37,33 +28,28 @@
 
 InputEventPrediction::InputEventPrediction(bool enable_resampling)
     : enable_resampling_(enable_resampling) {
-  SetUpPredictorType();
-}
-
-InputEventPrediction::~InputEventPrediction() {}
-
-void InputEventPrediction::SetUpPredictorType() {
   // When resampling is enabled, set predictor type by resampling flag params;
   // otherwise, get predictor type parameters from kInputPredictorTypeChoice
   // flag.
-  std::string predictor_type =
-      enable_resampling_ ? GetFieldTrialParamValueByFeature(
-                               features::kResamplingInputEvents, kPredictor)
-                         : GetFieldTrialParamValueByFeature(
-                               features::kInputPredictorTypeChoice, kPredictor);
+  std::string predictor_name =
+      enable_resampling_
+          ? GetFieldTrialParamValueByFeature(features::kResamplingInputEvents,
+                                             "predictor")
+          : GetFieldTrialParamValueByFeature(
+                features::kInputPredictorTypeChoice, "predictor");
 
-  if (predictor_type == kInputEventPredictorTypeLsq)
-    selected_predictor_type_ = PredictorType::kLsq;
-  else if (predictor_type == kInputEventPredictorTypeEmpty)
-    selected_predictor_type_ = PredictorType::kEmpty;
-  else if (predictor_type == kInputEventPredictorTypeKalmanTimeFiltered)
-    selected_predictor_type_ = PredictorType::kKalmanTimeFiltered;
+  if (predictor_name.empty())
+    selected_predictor_type_ =
+        ui::input_prediction::PredictorType::kScrollPredictorTypeKalman;
   else
-    selected_predictor_type_ = PredictorType::kKalman;
+    selected_predictor_type_ =
+        ui::PredictorFactory::GetPredictorTypeFromName(predictor_name);
 
   mouse_predictor_ = CreatePredictor();
 }
 
+InputEventPrediction::~InputEventPrediction() {}
+
 void InputEventPrediction::HandleEvents(
     blink::WebCoalescedInputEvent& coalesced_event,
     base::TimeTicks frame_time) {
@@ -102,18 +88,7 @@
 
 std::unique_ptr<ui::InputPredictor> InputEventPrediction::CreatePredictor()
     const {
-  switch (selected_predictor_type_) {
-    case PredictorType::kEmpty:
-      return std::make_unique<ui::EmptyPredictor>();
-    case PredictorType::kLsq:
-      return std::make_unique<ui::LeastSquaresPredictor>();
-    case PredictorType::kKalman:
-      return std::make_unique<ui::KalmanPredictor>(
-          false /* enable_time_filtering */);
-    case PredictorType::kKalmanTimeFiltered:
-      return std::make_unique<ui::KalmanPredictor>(
-          true /* enable_time_filtering */);
-  }
+  return ui::PredictorFactory::GetPredictor(selected_predictor_type_);
 }
 
 void InputEventPrediction::UpdatePrediction(const WebInputEvent& event) {
diff --git a/content/renderer/input/input_event_prediction.h b/content/renderer/input/input_event_prediction.h
index 383650c..553d23a 100644
--- a/content/renderer/input/input_event_prediction.h
+++ b/content/renderer/input/input_event_prediction.h
@@ -11,6 +11,7 @@
 #include "content/renderer/input/scoped_web_input_event_with_latency_info.h"
 #include "ui/events/blink/blink_features.h"
 #include "ui/events/blink/prediction/input_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 #include "ui/events/event.h"
 
 using blink::WebInputEvent;
@@ -44,13 +45,6 @@
   FRIEND_TEST_ALL_PREFIXES(InputEventPredictionTest, PredictorType);
   FRIEND_TEST_ALL_PREFIXES(InputEventPredictionTest, ResamplingDisabled);
 
-  enum class PredictorType { kEmpty, kLsq, kKalman, kKalmanTimeFiltered };
-
-  // Initialize selected_predictor_type_ from field trial parameters of
-  // kResamplingInputEvent flag if resampling is enable. Otherwise set it
-  // from kInputPredictorTypeChoice.
-  void SetUpPredictorType();
-
   // The following functions are for handling multiple TouchPoints in a
   // WebTouchEvent. They should be more neat when WebTouchEvent is elimated.
   // Cast events from WebInputEvent to WebPointerProperties. Call
@@ -93,7 +87,7 @@
 
   // Store the field trial parameter used for choosing different types of
   // predictor.
-  PredictorType selected_predictor_type_;
+  ui::input_prediction::PredictorType selected_predictor_type_;
 
   bool enable_resampling_ = false;
 
diff --git a/content/renderer/input/input_event_prediction_unittest.cc b/content/renderer/input/input_event_prediction_unittest.cc
index 1fd67a6..9f5a1170 100644
--- a/content/renderer/input/input_event_prediction_unittest.cc
+++ b/content/renderer/input/input_event_prediction_unittest.cc
@@ -12,19 +12,25 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/blink/prediction/empty_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
+namespace content {
+
+namespace {
 using blink::WebInputEvent;
 using blink::WebMouseEvent;
 using blink::WebPointerProperties;
 using blink::WebTouchEvent;
-
-namespace content {
+using ui::input_prediction::PredictorType;
+}  // namespace
 
 class InputEventPredictionTest : public testing::Test {
  public:
   InputEventPredictionTest() {
     // Default to enable resampling with empty predictor for testing.
-    ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "empty");
+    ConfigureFieldTrialAndInitialize(
+        features::kResamplingInputEvents,
+        ui::input_prediction::kScrollPredictorNameEmpty);
   }
 
   int GetPredictorMapSize() const {
@@ -89,33 +95,40 @@
   // Resampling is default to true for InputEventPredictionTest.
   EXPECT_TRUE(event_predictor_->enable_resampling_);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kEmpty);
+            PredictorType::kScrollPredictorTypeEmpty);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "empty");
+  ConfigureFieldTrialAndInitialize(
+      features::kResamplingInputEvents,
+      ui::input_prediction::kScrollPredictorNameEmpty);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kEmpty);
+            PredictorType::kScrollPredictorTypeEmpty);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "kalman");
+  ConfigureFieldTrialAndInitialize(
+      features::kResamplingInputEvents,
+      ui::input_prediction::kScrollPredictorNameKalman);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kKalman);
+            PredictorType::kScrollPredictorTypeKalman);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "lsq");
+  ConfigureFieldTrialAndInitialize(
+      features::kResamplingInputEvents,
+      ui::input_prediction::kScrollPredictorNameLsq);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kLsq);
+            PredictorType::kScrollPredictorTypeLsq);
 
-  // Default to kKalman.
+  // Default to Kalman predictor.
   ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "");
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kKalman);
+            PredictorType::kScrollPredictorTypeKalman);
 
-  ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, "lsq");
+  ConfigureFieldTrialAndInitialize(
+      features::kInputPredictorTypeChoice,
+      ui::input_prediction::kScrollPredictorNameLsq);
   EXPECT_FALSE(event_predictor_->enable_resampling_);
-  // When enable_resampling_ is true, kInputPredictorTypeChoice flag have no
+  // When enable_resampling_ is true, kInputPredictorTypeChoice flag has no
   // effect.
-  event_predictor_->enable_resampling_ = true;
-  event_predictor_->SetUpPredictorType();
+  event_predictor_ = std::make_unique<InputEventPrediction>(true);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kKalman);
+            PredictorType::kScrollPredictorTypeKalman);
 }
 
 TEST_F(InputEventPredictionTest, MouseEvent) {
@@ -274,7 +287,7 @@
   ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, "");
   EXPECT_FALSE(event_predictor_->enable_resampling_);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
-            InputEventPrediction::PredictorType::kKalman);
+            PredictorType::kScrollPredictorTypeKalman);
 
   // Send 3 mouse move to get kalman predictor ready.
   WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
@@ -306,7 +319,9 @@
 
 // Test that when dt > 20ms, no resampling, but has predicted points.
 TEST_F(InputEventPredictionTest, NoResampleWhenExceedMaxResampleTime) {
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "kalman");
+  ConfigureFieldTrialAndInitialize(
+      features::kResamplingInputEvents,
+      ui::input_prediction::kScrollPredictorNameKalman);
 
   base::TimeTicks event_time = ui::EventTimeForNow();
   // Send 3 mouse move each has 8ms interval to get kalman predictor ready.
diff --git a/ui/events/blink/BUILD.gn b/ui/events/blink/BUILD.gn
index 8693184..301418e 100644
--- a/ui/events/blink/BUILD.gn
+++ b/ui/events/blink/BUILD.gn
@@ -48,6 +48,8 @@
     "prediction/least_squares_predictor.h",
     "prediction/linear_predictor.cc",
     "prediction/linear_predictor.h",
+    "prediction/predictor_factory.cc",
+    "prediction/predictor_factory.h",
     "scroll_predictor.cc",
     "scroll_predictor.h",
     "synchronous_input_handler_proxy.h",
diff --git a/ui/events/blink/prediction/empty_predictor.cc b/ui/events/blink/prediction/empty_predictor.cc
index 50247b3..4d33485 100644
--- a/ui/events/blink/prediction/empty_predictor.cc
+++ b/ui/events/blink/prediction/empty_predictor.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ui/events/blink/prediction/empty_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 namespace ui {
 
@@ -13,7 +14,7 @@
 EmptyPredictor::~EmptyPredictor() = default;
 
 const char* EmptyPredictor::GetName() const {
-  return "Empty";
+  return input_prediction::kScrollPredictorNameEmpty;
 }
 
 void EmptyPredictor::Reset() {
diff --git a/ui/events/blink/prediction/kalman_predictor.cc b/ui/events/blink/prediction/kalman_predictor.cc
index 41904cc..249c93d 100644
--- a/ui/events/blink/prediction/kalman_predictor.cc
+++ b/ui/events/blink/prediction/kalman_predictor.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ui/events/blink/prediction/kalman_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 namespace {
 
@@ -24,7 +25,9 @@
 KalmanPredictor::~KalmanPredictor() = default;
 
 const char* KalmanPredictor::GetName() const {
-  return "Kalman";
+  return enable_time_filtering_
+             ? input_prediction::kScrollPredictorNameKalmanTimeFiltered
+             : input_prediction::kScrollPredictorNameKalman;
 }
 
 void KalmanPredictor::Reset() {
diff --git a/ui/events/blink/prediction/least_squares_predictor.cc b/ui/events/blink/prediction/least_squares_predictor.cc
index 55d13a9..786c141 100644
--- a/ui/events/blink/prediction/least_squares_predictor.cc
+++ b/ui/events/blink/prediction/least_squares_predictor.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ui/events/blink/prediction/least_squares_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 namespace ui {
 
@@ -39,7 +40,7 @@
 LeastSquaresPredictor::~LeastSquaresPredictor() {}
 
 const char* LeastSquaresPredictor::GetName() const {
-  return "LSQ";
+  return input_prediction::kScrollPredictorNameLsq;
 }
 
 void LeastSquaresPredictor::Reset() {
diff --git a/ui/events/blink/prediction/linear_predictor.cc b/ui/events/blink/prediction/linear_predictor.cc
index 07faff3..4c6682d8 100644
--- a/ui/events/blink/prediction/linear_predictor.cc
+++ b/ui/events/blink/prediction/linear_predictor.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ui/events/blink/prediction/linear_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 namespace ui {
 
@@ -13,10 +14,9 @@
 LinearPredictor::~LinearPredictor() {}
 
 const char* LinearPredictor::GetName() const {
-  if (equation_order_ == EquationOrder::kFirstOrder)
-    return "LinearFirst";
-  else
-    return "LinearSecond";
+  return equation_order_ == EquationOrder::kFirstOrder
+             ? input_prediction::kScrollPredictorNameLinearFirst
+             : input_prediction::kScrollPredictorNameLinearSecond;
 }
 
 void LinearPredictor::Reset() {
diff --git a/ui/events/blink/prediction/linear_predictor_unittest.cc b/ui/events/blink/prediction/linear_predictor_unittest.cc
index 57a4ff6..9b0b3fd9 100644
--- a/ui/events/blink/prediction/linear_predictor_unittest.cc
+++ b/ui/events/blink/prediction/linear_predictor_unittest.cc
@@ -5,6 +5,7 @@
 #include "ui/events/blink/prediction/linear_predictor.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 namespace ui {
 namespace test {
@@ -36,13 +37,15 @@
 // Test if the output name of the predictor is taking account of the
 // equation order
 TEST_F(LinearPredictorFirstOrderTest, GetName) {
-  ASSERT_STREQ(predictor_->GetName(), "LinearFirst");
+  EXPECT_EQ(predictor_->GetName(),
+            input_prediction::kScrollPredictorNameLinearFirst);
 }
 
 // Test if the output name of the predictor is taking account of the
 // equation order
 TEST_F(LinearPredictorSecondOrderTest, GetName) {
-  ASSERT_STREQ(predictor_->GetName(), "LinearSecond");
+  EXPECT_EQ(predictor_->GetName(),
+            input_prediction::kScrollPredictorNameLinearSecond);
 }
 
 // Test that the number of events required to compute a prediction is correct
diff --git a/ui/events/blink/prediction/predictor_factory.cc b/ui/events/blink/prediction/predictor_factory.cc
new file mode 100644
index 0000000..b0f617c
--- /dev/null
+++ b/ui/events/blink/prediction/predictor_factory.cc
@@ -0,0 +1,65 @@
+// Copyright 2019 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.
+
+#include "ui/events/blink/prediction/predictor_factory.h"
+#include "ui/events/blink/blink_features.h"
+#include "ui/events/blink/prediction/empty_predictor.h"
+#include "ui/events/blink/prediction/kalman_predictor.h"
+#include "ui/events/blink/prediction/least_squares_predictor.h"
+#include "ui/events/blink/prediction/linear_predictor.h"
+
+namespace ui {
+
+namespace input_prediction {
+
+const char kScrollPredictorNameLsq[] = "lsq";
+const char kScrollPredictorNameKalman[] = "kalman";
+const char kScrollPredictorNameKalmanTimeFiltered[] = "kalman_time_filtered";
+const char kScrollPredictorNameLinearFirst[] = "linear_first";
+const char kScrollPredictorNameLinearSecond[] = "linear_second";
+const char kScrollPredictorNameEmpty[] = "empty";
+
+}  // namespace input_prediction
+
+namespace {
+using input_prediction::PredictorType;
+}
+
+PredictorType PredictorFactory::GetPredictorTypeFromName(
+    const std::string& predictor_name) {
+  if (predictor_name == input_prediction::kScrollPredictorNameLsq)
+    return PredictorType::kScrollPredictorTypeLsq;
+  else if (predictor_name == input_prediction::kScrollPredictorNameKalman)
+    return PredictorType::kScrollPredictorTypeKalman;
+  else if (predictor_name ==
+           input_prediction::kScrollPredictorNameKalmanTimeFiltered)
+    return PredictorType::kScrollPredictorTypeKalmanTimeFiltered;
+  else if (predictor_name == input_prediction::kScrollPredictorNameLinearFirst)
+    return PredictorType::kScrollPredictorTypeLinearFirst;
+  else if (predictor_name == input_prediction::kScrollPredictorNameLinearSecond)
+    return PredictorType::kScrollPredictorTypeLinearSecond;
+  else
+    return PredictorType::kScrollPredictorTypeEmpty;
+}
+
+std::unique_ptr<InputPredictor> PredictorFactory::GetPredictor(
+    PredictorType predictor_type) {
+  if (predictor_type == PredictorType::kScrollPredictorTypeLsq)
+    return std::make_unique<LeastSquaresPredictor>();
+  else if (predictor_type == PredictorType::kScrollPredictorTypeKalman)
+    return std::make_unique<KalmanPredictor>(false /* enable_time_filtering */);
+  else if (predictor_type ==
+           PredictorType::kScrollPredictorTypeKalmanTimeFiltered)
+    return std::make_unique<KalmanPredictor>(true /* enable_time_filtering */);
+  else if (predictor_type == PredictorType::kScrollPredictorTypeLinearFirst)
+    return std::make_unique<LinearPredictor>(
+        LinearPredictor::EquationOrder::kFirstOrder);
+  else if (predictor_type == PredictorType::kScrollPredictorTypeLinearSecond)
+    return std::make_unique<LinearPredictor>(
+        LinearPredictor::EquationOrder::kSecondOrder);
+  else
+    return std::make_unique<EmptyPredictor>();
+}
+
+}  // namespace ui
diff --git a/ui/events/blink/prediction/predictor_factory.h b/ui/events/blink/prediction/predictor_factory.h
new file mode 100644
index 0000000..1d21781
--- /dev/null
+++ b/ui/events/blink/prediction/predictor_factory.h
@@ -0,0 +1,50 @@
+// Copyright 2019 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.
+
+#ifndef UI_EVENTS_BLINK_PREDICTION_PREDICTOR_FACTORY_H_
+#define UI_EVENTS_BLINK_PREDICTION_PREDICTOR_FACTORY_H_
+
+#include "ui/events/blink/prediction/input_predictor.h"
+
+namespace ui {
+
+namespace input_prediction {
+
+extern const char kScrollPredictorNameLsq[];
+extern const char kScrollPredictorNameKalman[];
+extern const char kScrollPredictorNameKalmanTimeFiltered[];
+extern const char kScrollPredictorNameLinearFirst[];
+extern const char kScrollPredictorNameLinearSecond[];
+extern const char kScrollPredictorNameEmpty[];
+
+enum class PredictorType {
+  kScrollPredictorTypeLsq,
+  kScrollPredictorTypeKalman,
+  kScrollPredictorTypeKalmanTimeFiltered,
+  kScrollPredictorTypeLinearFirst,
+  kScrollPredictorTypeLinearSecond,
+  kScrollPredictorTypeEmpty
+};
+}  // namespace input_prediction
+
+class PredictorFactory {
+ public:
+  // Returns the PredictorType associated to the given predictor
+  // name if found, otherwise returns kScrollPredictorTypeEmpty
+  static input_prediction::PredictorType GetPredictorTypeFromName(
+      const std::string& predictor_name);
+
+  // Returns the predictor designed by its type if found, otherwise returns
+  // PredictorEmpty
+  static std::unique_ptr<InputPredictor> GetPredictor(
+      input_prediction::PredictorType predictor_type);
+
+ private:
+  PredictorFactory() = delete;
+  ~PredictorFactory() = delete;
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_BLINK_PREDICTION_PREDICTOR_FACTORY_H_
\ No newline at end of file
diff --git a/ui/events/blink/scroll_predictor.cc b/ui/events/blink/scroll_predictor.cc
index ace376d8..df24ae692 100644
--- a/ui/events/blink/scroll_predictor.cc
+++ b/ui/events/blink/scroll_predictor.cc
@@ -8,48 +8,20 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/trace_event/trace_event.h"
-#include "ui/events/blink/prediction/empty_predictor.h"
-#include "ui/events/blink/prediction/kalman_predictor.h"
-#include "ui/events/blink/prediction/least_squares_predictor.h"
-#include "ui/events/blink/prediction/linear_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 using blink::WebInputEvent;
 using blink::WebGestureEvent;
 
 namespace ui {
 
-namespace {
-
-constexpr char kPredictor[] = "predictor";
-constexpr char kScrollPredictorTypeLsq[] = "lsq";
-constexpr char kScrollPredictorTypeKalman[] = "kalman";
-constexpr char kScrollPredictorTypeKalmanTimeFiltered[] =
-    "kalman_time_filtered";
-constexpr char kScrollPredictorLinearFirst[] = "linearFirst";
-constexpr char kScrollPredictorLinearSecond[] = "linearSecond";
-
-}  // namespace
-
 ScrollPredictor::ScrollPredictor() {
-  std::string predictor_type = GetFieldTrialParamValueByFeature(
-      features::kResamplingScrollEvents, kPredictor);
+  std::string predictor_name = GetFieldTrialParamValueByFeature(
+      features::kResamplingScrollEvents, "predictor");
 
-  if (predictor_type == kScrollPredictorTypeLsq)
-    predictor_ = std::make_unique<LeastSquaresPredictor>();
-  else if (predictor_type == kScrollPredictorTypeKalman)
-    predictor_ =
-        std::make_unique<KalmanPredictor>(false /* enable_time_filtering */);
-  else if (predictor_type == kScrollPredictorTypeKalmanTimeFiltered)
-    predictor_ =
-        std::make_unique<KalmanPredictor>(true /* enable_time_filtering */);
-  else if (predictor_type == kScrollPredictorLinearFirst)
-    predictor_ = std::make_unique<LinearPredictor>(
-        LinearPredictor::EquationOrder::kFirstOrder);
-  else if (predictor_type == kScrollPredictorLinearSecond)
-    predictor_ = std::make_unique<LinearPredictor>(
-        LinearPredictor::EquationOrder::kSecondOrder);
-  else
-    predictor_ = std::make_unique<EmptyPredictor>();
+  input_prediction::PredictorType predictor_type =
+      ui::PredictorFactory::GetPredictorTypeFromName(predictor_name);
+  predictor_ = ui::PredictorFactory::GetPredictor(predictor_type);
 }
 
 ScrollPredictor::~ScrollPredictor() = default;
diff --git a/ui/events/blink/scroll_predictor_unittest.cc b/ui/events/blink/scroll_predictor_unittest.cc
index a2056e1..a38c192 100644
--- a/ui/events/blink/scroll_predictor_unittest.cc
+++ b/ui/events/blink/scroll_predictor_unittest.cc
@@ -13,14 +13,16 @@
 #include "ui/events/blink/prediction/empty_predictor.h"
 #include "ui/events/blink/prediction/kalman_predictor.h"
 #include "ui/events/blink/prediction/least_squares_predictor.h"
-
-using blink::WebInputEvent;
-using blink::WebGestureEvent;
+#include "ui/events/blink/prediction/linear_predictor.h"
+#include "ui/events/blink/prediction/predictor_factory.h"
 
 namespace ui {
 namespace test {
 namespace {
 
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+
 constexpr double kEpsilon = 0.001;
 
 }  // namespace
@@ -116,7 +118,7 @@
               GetFieldTrialParamValueByFeature(feature, "predictor"));
   }
 
-  void VerifyPredictorType(const std::string& expected_type) {
+  void VerifyPredictorType(const char* expected_type) {
     EXPECT_EQ(expected_type, scroll_predictor_->predictor_->GetName());
   }
 
@@ -370,23 +372,31 @@
 }
 
 TEST_F(ScrollPredictorTest, ScrollPredictorTypeSelection) {
-  // Empty Predictor when kResamplingScrollEvents not enabled.
+  // Empty Predictor when kResamplingScrollEvents is disabled.
   scroll_predictor_ = std::make_unique<ScrollPredictor>();
-  VerifyPredictorType("Empty");
+  VerifyPredictorType(input_prediction::kScrollPredictorNameEmpty);
 
   // When resampling is enabled, predictor type is set from
   // kResamplingScrollEvents.
-  ConfigureFieldTrial(features::kResamplingScrollEvents, "empty");
+  ConfigureFieldTrial(features::kResamplingScrollEvents,
+                      input_prediction::kScrollPredictorNameEmpty);
   scroll_predictor_ = std::make_unique<ScrollPredictor>();
-  VerifyPredictorType("Empty");
+  VerifyPredictorType(input_prediction::kScrollPredictorNameEmpty);
 
-  ConfigureFieldTrial(features::kResamplingScrollEvents, "lsq");
+  ConfigureFieldTrial(features::kResamplingScrollEvents,
+                      input_prediction::kScrollPredictorNameLsq);
   scroll_predictor_ = std::make_unique<ScrollPredictor>();
-  VerifyPredictorType("LSQ");
+  VerifyPredictorType(input_prediction::kScrollPredictorNameLsq);
 
-  ConfigureFieldTrial(features::kResamplingScrollEvents, "kalman");
+  ConfigureFieldTrial(features::kResamplingScrollEvents,
+                      input_prediction::kScrollPredictorNameKalman);
   scroll_predictor_ = std::make_unique<ScrollPredictor>();
-  VerifyPredictorType("Kalman");
+  VerifyPredictorType(input_prediction::kScrollPredictorNameKalman);
+
+  ConfigureFieldTrial(features::kResamplingScrollEvents,
+                      input_prediction::kScrollPredictorNameLinearFirst);
+  scroll_predictor_ = std::make_unique<ScrollPredictor>();
+  VerifyPredictorType(input_prediction::kScrollPredictorNameLinearFirst);
 }
 
 }  // namespace test