[Offline Pages] Adds InstanceID token support.

The prefetch service cannot depend on InstanceIDProfileService directly,
because the GCMProfileService depends on it.  Therefore, we implement a proxy
that can summon an InstanceIDProfileService on demand and return a
token.  Because tokens are short lived in the prefetch system we don't
need any further APIs from InstanceID.

BUG=701939

Change-Id: I8f4c7b8d08edb155b8e53ee39adaeaa8d120711b
Reviewed-on: https://chromium-review.googlesource.com/522143
Commit-Queue: Justin DeWitt <[email protected]>
Reviewed-by: Jian Li <[email protected]>
Cr-Commit-Position: refs/heads/master@{#477956}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
index 297ec35..437bdd5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
@@ -39,7 +39,8 @@
 /** Unit tests for {@link PrefetchBackgroundTask}. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
+        "enable-features=OfflinePagesPrefetching"})
 public class PrefetchBackgroundTaskTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
@@ -293,4 +294,4 @@
         assertEquals(5, mScheduler.addCount());
         assertEquals(5, mScheduler.removeCount());
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 58cab9d..4224c4d 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2196,6 +2196,8 @@
       "offline_pages/background_loader_offliner.h",
       "offline_pages/prefetch/offline_metrics_collector_impl.cc",
       "offline_pages/prefetch/offline_metrics_collector_impl.h",
+      "offline_pages/prefetch/prefetch_instance_id_proxy.cc",
+      "offline_pages/prefetch/prefetch_instance_id_proxy.h",
       "offline_pages/prefetch/prefetch_service_factory.cc",
       "offline_pages/prefetch/prefetch_service_factory.h",
     ]
diff --git a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc
index 6fe9189..231be79f 100644
--- a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc
+++ b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/common/pref_names.h"
+#include "components/offline_pages/core/offline_page_feature.h"
 #include "components/offline_pages/core/prefetch/prefetch_service.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
@@ -38,6 +39,9 @@
 static jboolean StartPrefetchTask(JNIEnv* env,
                                   const JavaParamRef<jobject>& jcaller,
                                   const JavaParamRef<jobject>& jprofile) {
+  if (!IsPrefetchingOfflinePagesEnabled())
+    return false;
+
   Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
   DCHECK(profile);
 
diff --git a/chrome/browser/gcm/gcm_profile_service_factory.cc b/chrome/browser/gcm/gcm_profile_service_factory.cc
index 8a35e4d..1781c63 100644
--- a/chrome/browser/gcm/gcm_profile_service_factory.cc
+++ b/chrome/browser/gcm/gcm_profile_service_factory.cc
@@ -28,6 +28,8 @@
 
 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
 #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h"
+#include "components/gcm_driver/gcm_driver.h"
+#include "components/offline_pages/core/offline_page_feature.h"
 #include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h"
 #include "components/offline_pages/core/prefetch/prefetch_service.h"
 #endif
@@ -97,13 +99,15 @@
       blocking_task_runner));
 #endif
 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
-  offline_pages::PrefetchService* prefetch_service =
-      offline_pages::PrefetchServiceFactory::GetForBrowserContext(context);
-  if (prefetch_service != nullptr) {
-    offline_pages::PrefetchGCMHandler* prefetch_gcm_handler =
-        prefetch_service->GetPrefetchGCMHandler();
-    service->driver()->AddAppHandler(prefetch_gcm_handler->GetAppId(),
-                                     prefetch_gcm_handler->AsGCMAppHandler());
+  if (offline_pages::IsPrefetchingOfflinePagesEnabled()) {
+    offline_pages::PrefetchService* prefetch_service =
+        offline_pages::PrefetchServiceFactory::GetForBrowserContext(context);
+    if (prefetch_service != nullptr) {
+      offline_pages::PrefetchGCMHandler* prefetch_gcm_handler =
+          prefetch_service->GetPrefetchGCMHandler();
+      service->driver()->AddAppHandler(prefetch_gcm_handler->GetAppId(),
+                                       prefetch_gcm_handler->AsGCMAppHandler());
+    }
   }
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
 
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.cc b/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.cc
new file mode 100644
index 0000000..ccfd588
--- /dev/null
+++ b/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.cc
@@ -0,0 +1,72 @@
+// Copyright 2017 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 "chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/gcm/instance_id/instance_id_profile_service.h"
+#include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
+#include "components/gcm_driver/instance_id/instance_id_driver.h"
+#include "components/offline_pages/core/offline_page_feature.h"
+
+using instance_id::InstanceID;
+using instance_id::InstanceIDProfileService;
+using instance_id::InstanceIDProfileServiceFactory;
+
+namespace {
+
+const char kScopeGCM[] = "GCM";
+
+// TODO(dewittj): Add prod sender ID when finalized.
+const char kStagingSenderId[] = "208433663017";
+
+}  // namespace
+
+namespace offline_pages {
+
+PrefetchInstanceIDProxy::PrefetchInstanceIDProxy(
+    const std::string& app_id,
+    content::BrowserContext* context)
+    : app_id_(app_id), context_(context), weak_factory_(this) {
+  DCHECK(IsPrefetchingOfflinePagesEnabled());
+}
+
+PrefetchInstanceIDProxy::~PrefetchInstanceIDProxy() = default;
+
+void PrefetchInstanceIDProxy::GetGCMToken(
+    InstanceID::GetTokenCallback callback) {
+  if (!token_.empty()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(&PrefetchInstanceIDProxy::GotGCMToken,
+                              weak_factory_.GetWeakPtr(), callback, token_,
+                              InstanceID::SUCCESS));
+    return;
+  }
+
+  InstanceIDProfileService* service =
+      InstanceIDProfileServiceFactory::GetForProfile(context_);
+  DCHECK(service);
+
+  InstanceID* instance_id = service->driver()->GetInstanceID(app_id_);
+  DCHECK(instance_id);
+
+  instance_id->GetToken(kStagingSenderId, kScopeGCM,
+                        std::map<std::string, std::string>(),
+                        base::Bind(&PrefetchInstanceIDProxy::GotGCMToken,
+                                   weak_factory_.GetWeakPtr(), callback));
+}
+
+void PrefetchInstanceIDProxy::GotGCMToken(InstanceID::GetTokenCallback callback,
+                                          const std::string& token,
+                                          InstanceID::Result result) {
+  DVLOG(1) << "Got an Instance ID token for GCM: " << token
+           << " with result: " << result;
+  callback.Run(token, result);
+}
+
+}  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h b/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h
new file mode 100644
index 0000000..94ab94b4
--- /dev/null
+++ b/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h
@@ -0,0 +1,50 @@
+// Copyright 2017 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 CHROME_BROWSER_OFFLINE_PAGES_PREFETCH_PREFETCH_INSTANCE_ID_PROXY_H_
+#define CHROME_BROWSER_OFFLINE_PAGES_PREFETCH_PREFETCH_INSTANCE_ID_PROXY_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
+#include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace offline_pages {
+
+// A factory that can create prefetching InstanceID tokens from a
+// BrowserContext, requesting the InstanceIDProfileService on demand.
+class PrefetchInstanceIDProxy : public PrefetchGCMAppHandler::TokenFactory {
+ public:
+  PrefetchInstanceIDProxy(const std::string& app_id,
+                          content::BrowserContext* context);
+  ~PrefetchInstanceIDProxy() override;
+
+  // PrefetchGCMAppHandler::TokenFactory implementation.
+  void GetGCMToken(instance_id::InstanceID::GetTokenCallback callback) override;
+
+ private:
+  void GotGCMToken(instance_id::InstanceID::GetTokenCallback callback,
+                   const std::string& token,
+                   instance_id::InstanceID::Result result);
+  std::string app_id_;
+  std::string token_;
+
+  // Unowned, the owner should make sure that this class does not outlive the
+  // browser context.
+  content::BrowserContext* context_;
+
+  base::WeakPtrFactory<PrefetchInstanceIDProxy> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefetchInstanceIDProxy);
+};
+
+}  // namespace offline_pages
+
+#endif  // CHROME_BROWSER_OFFLINE_PAGES_PREFETCH_PREFETCH_INSTANCE_ID_PROXY_H_
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy_unittest.cc b/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy_unittest.cc
new file mode 100644
index 0000000..1c21f0c9
--- /dev/null
+++ b/chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2017 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 "chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "chrome/browser/gcm/fake_gcm_profile_service.h"
+#include "chrome/browser/gcm/gcm_profile_service_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
+#include "components/offline_pages/core/offline_page_feature.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_ANDROID)
+#include "components/gcm_driver/instance_id/instance_id_android.h"
+#include "components/gcm_driver/instance_id/scoped_use_fake_instance_id_android.h"
+#endif  // OS_ANDROID
+
+using instance_id::InstanceID;
+
+namespace offline_pages {
+namespace {
+const char kAppIdForTest[] = "com.google.test.PrefetchInstanceIDProxyTest";
+}
+
+class PrefetchInstanceIDProxyTest : public testing::Test {
+ public:
+  PrefetchInstanceIDProxyTest() = default;
+  ~PrefetchInstanceIDProxyTest() override = default;
+
+  // testing::Test:
+  void SetUp() override;
+  void TearDown() override;
+
+  void WaitForAsyncOperation();
+
+  // Sync wrapper for async version.
+  std::string GetToken();
+
+  PrefetchInstanceIDProxy* proxy() { return proxy_.get(); }
+
+ private:
+  void GetTokenCompleted(const std::string& token, InstanceID::Result result);
+
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+  std::unique_ptr<PrefetchInstanceIDProxy> proxy_;
+
+  gcm::FakeGCMProfileService* gcm_profile_service_;
+
+#if defined(OS_ANDROID)
+  instance_id::InstanceIDAndroid::ScopedBlockOnAsyncTasksForTesting
+      block_async_;
+  instance_id::ScopedUseFakeInstanceIDAndroid use_fake_;
+#endif  // OS_ANDROID
+
+  std::string token_;
+  InstanceID::Result result_ = InstanceID::UNKNOWN_ERROR;
+
+  bool async_operation_completed_ = false;
+  base::Closure async_operation_completed_callback_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefetchInstanceIDProxyTest);
+};
+
+void PrefetchInstanceIDProxyTest::SetUp() {
+  scoped_feature_list_.InitAndEnableFeature(kPrefetchingOfflinePagesFeature);
+  proxy_ = base::MakeUnique<PrefetchInstanceIDProxy>(kAppIdForTest, &profile_);
+  gcm_profile_service_ = static_cast<gcm::FakeGCMProfileService*>(
+      gcm::GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+          &profile_, &gcm::FakeGCMProfileService::Build));
+}
+
+void PrefetchInstanceIDProxyTest::TearDown() {
+  base::RunLoop().RunUntilIdle();
+}
+
+void PrefetchInstanceIDProxyTest::WaitForAsyncOperation() {
+  // No need to wait if async operation is not needed.
+  if (async_operation_completed_)
+    return;
+  base::RunLoop run_loop;
+  async_operation_completed_callback_ = run_loop.QuitClosure();
+  run_loop.Run();
+}
+
+std::string PrefetchInstanceIDProxyTest::GetToken() {
+  async_operation_completed_ = false;
+  token_.clear();
+  result_ = InstanceID::UNKNOWN_ERROR;
+
+  proxy()->GetGCMToken(base::Bind(
+      &PrefetchInstanceIDProxyTest::GetTokenCompleted, base::Unretained(this)));
+  WaitForAsyncOperation();
+  return token_;
+}
+
+void PrefetchInstanceIDProxyTest::GetTokenCompleted(const std::string& token,
+                                                    InstanceID::Result result) {
+  DCHECK(!async_operation_completed_);
+  async_operation_completed_ = true;
+  token_ = token;
+  result_ = result;
+  if (!async_operation_completed_callback_.is_null())
+    async_operation_completed_callback_.Run();
+}
+
+TEST_F(PrefetchInstanceIDProxyTest, GetToken) {
+  std::string token = GetToken();
+  EXPECT_NE("", token);
+}
+
+}  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
index 07f1c0e..3a7657453 100644
--- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
+++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h"
+#include "chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h"
 #include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h"
@@ -37,8 +38,10 @@
 
 KeyedService* PrefetchServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  auto prefetch_gcm_app_handler = base::MakeUnique<PrefetchGCMAppHandler>();
   auto prefetch_dispatcher = base::MakeUnique<PrefetchDispatcherImpl>();
+  auto prefetch_gcm_app_handler = base::MakeUnique<PrefetchGCMAppHandler>(
+      base::MakeUnique<PrefetchInstanceIDProxy>(kPrefetchingOfflinePagesAppId,
+                                                context));
   auto offline_metrics_collector =
       base::MakeUnique<OfflineMetricsCollectorImpl>();
   auto suggested_articles_observer =
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 78d723e..b11a3f2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3476,6 +3476,7 @@
       "../browser/android/offline_pages/test_request_coordinator_builder.cc",
       "../browser/android/offline_pages/test_request_coordinator_builder.h",
       "../browser/offline_pages/background_loader_offliner_unittest.cc",
+      "../browser/offline_pages/prefetch/prefetch_instance_id_proxy_unittest.cc",
     ]
     deps += [
       "//components/offline_pages/content/background_loader:test_support",
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn
index a8da79a..1a1db04 100644
--- a/components/offline_pages/core/prefetch/BUILD.gn
+++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -73,6 +73,7 @@
   deps = [
     ":prefetch",
     "//base",
+    "//components/gcm_driver/instance_id",
     "//components/keyed_service/core",
     "//components/offline_pages/core",
   ]
diff --git a/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.cc b/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.cc
index e6baf08..475255e 100644
--- a/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.cc
+++ b/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.cc
@@ -8,14 +8,20 @@
 #include "components/offline_pages/core/prefetch/prefetch_service.h"
 
 namespace offline_pages {
-namespace {
 const char kPrefetchingOfflinePagesAppId[] =
     "com.google.chrome.OfflinePagePrefetch";
-}
 
-PrefetchGCMAppHandler::PrefetchGCMAppHandler() {}
+PrefetchGCMAppHandler::PrefetchGCMAppHandler(
+    std::unique_ptr<TokenFactory> token_factory)
+    : token_factory_(std::move(token_factory)) {}
+
 PrefetchGCMAppHandler::~PrefetchGCMAppHandler() = default;
 
+void PrefetchGCMAppHandler::GetGCMToken(
+    instance_id::InstanceID::GetTokenCallback callback) {
+  token_factory_->GetGCMToken(callback);
+}
+
 void PrefetchGCMAppHandler::ShutdownHandler() {
   NOTIMPLEMENTED();
 }
diff --git a/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h b/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h
index beea579..fe214cc 100644
--- a/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h
+++ b/components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h
@@ -7,23 +7,33 @@
 
 #include <string>
 
-#include "components/gcm_driver/common/gcm_messages.h"
 #include "components/gcm_driver/gcm_app_handler.h"
-#include "components/gcm_driver/gcm_driver.h"
-#include "components/gcm_driver/gcm_profile_service.h"
+#include "components/gcm_driver/instance_id/instance_id.h"
 #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h"
-#include "url/gurl.h"
 
 namespace offline_pages {
 
+extern const char kPrefetchingOfflinePagesAppId[];
+
 // Receives GCM messages and other channel status messages on behalf of the
 // prefetch system.
 class PrefetchGCMAppHandler : public gcm::GCMAppHandler,
                               public PrefetchGCMHandler {
  public:
-  PrefetchGCMAppHandler();
+  class TokenFactory {
+   public:
+    virtual ~TokenFactory() = default;
+
+    virtual void GetGCMToken(
+        instance_id::InstanceID::GetTokenCallback callback) = 0;
+  };
+
+  PrefetchGCMAppHandler(std::unique_ptr<TokenFactory> token_factory);
   ~PrefetchGCMAppHandler() override;
 
+  // PrefetchGCMHandler implementation.
+  void GetGCMToken(instance_id::InstanceID::GetTokenCallback callback) override;
+
   // gcm::GCMAppHandler implementation.
   void ShutdownHandler() override;
   void OnStoreReset() override;
@@ -42,6 +52,8 @@
   std::string GetAppId() const override;
 
  private:
+  std::unique_ptr<TokenFactory> token_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(PrefetchGCMAppHandler);
 };
 
diff --git a/components/offline_pages/core/prefetch/prefetch_gcm_handler.h b/components/offline_pages/core/prefetch/prefetch_gcm_handler.h
index 7ce70f41..8ab1ebc 100644
--- a/components/offline_pages/core/prefetch/prefetch_gcm_handler.h
+++ b/components/offline_pages/core/prefetch/prefetch_gcm_handler.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+#include "components/gcm_driver/instance_id/instance_id.h"
+
 namespace gcm {
 class GCMAppHandler;
 }  // namespace gcm
@@ -19,6 +21,7 @@
 // controls the lifetime of all major subcomponents of the prefetching system.
 class PrefetchGCMHandler {
  public:
+  PrefetchGCMHandler() = default;
   virtual ~PrefetchGCMHandler() = default;
 
   // Returns the GCMAppHandler for this object.  Can return |nullptr| in unit
@@ -28,8 +31,10 @@
   // The app ID to register with at the GCM layer.
   virtual std::string GetAppId() const = 0;
 
-  // TODO(dewittj): Add methods for acquiring an Instance ID token to this
-  // interface.
+  // Gets a token suitable for sending to Offline Page Service for notifications
+  // when work is completed.
+  virtual void GetGCMToken(
+      instance_id::InstanceID::GetTokenCallback callback) = 0;
 };
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
index 927500e..07124ca 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "components/offline_pages/core/prefetch/offline_metrics_collector.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
diff --git a/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.cc b/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.cc
index 3a658df..f48abaf 100644
--- a/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.cc
+++ b/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.cc
@@ -17,4 +17,6 @@
   return "com.google.test.PrefetchAppId";
 }
 
+void TestPrefetchGCMHandler::GetGCMToken(
+    instance_id::InstanceID::GetTokenCallback callback) {}
 }  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h b/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h
index c6274c8..9688f91d 100644
--- a/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h
+++ b/components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "components/gcm_driver/instance_id/instance_id.h"
 #include "components/offline_pages/core/prefetch/prefetch_gcm_handler.h"
 
 namespace offline_pages {
@@ -19,6 +20,7 @@
 
   gcm::GCMAppHandler* AsGCMAppHandler() override;
   std::string GetAppId() const override;
+  void GetGCMToken(instance_id::InstanceID::GetTokenCallback callback) override;
 };
 
 }  // namespace offline_pages