Enable magic window mode with new Gvr

Magic window mode was disabled(not reporting phone sensor
data) here: https://codereview.chromium.org/2367673002/
The reason was new API requires an Activity instead of a
context like before. This CL moves the initialization of
GVR to chrome so CTA is available.

BUG=389343

Review-Url: https://codereview.chromium.org/2398103002
Cr-Commit-Position: refs/heads/master@{#425035}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index aca7c21..31dc981 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -416,7 +416,7 @@
             }
             mMergeTabsOnResume = false;
         }
-        if (mVrShellDelegate.isInVR()) mVrShellDelegate.resumeVR();
+        mVrShellDelegate.maybeResumeVR();
 
         mLocaleManager.setSnackbarManager(getSnackbarManager());
         mLocaleManager.startObservingPhoneChanges();
@@ -426,7 +426,7 @@
     public void onPauseWithNative() {
         mTabModelSelectorImpl.commitAllTabClosures();
         CookiesFetcher.persistCookies(this);
-        if (mVrShellDelegate.isInVR()) mVrShellDelegate.pauseVR();
+        mVrShellDelegate.maybePauseVR();
 
         mLocaleManager.setSnackbarManager(null);
         mLocaleManager.stopObservingPhoneChanges();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java
new file mode 100644
index 0000000..99f30f2f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java
@@ -0,0 +1,57 @@
+// Copyright 2016 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.
+
+package org.chromium.chrome.browser.vr_shell;
+
+import android.app.Activity;
+import android.os.StrictMode;
+
+import com.google.vr.ndk.base.GvrLayout;
+
+import org.chromium.base.Log;
+import org.chromium.base.annotations.UsedByReflection;
+
+/**
+ * Creates an active GvrContext from a detached GvrLayout. This is used by magic window mode.
+ */
+@UsedByReflection("VrShellDelegate.java")
+public class NonPresentingGvrContext implements NonPresentingGvrContextInterface {
+    private static final String TAG = "NPGvrContext";
+    private GvrLayout mGvrLayout;
+
+    @UsedByReflection("VrShellDelegate.java")
+    public NonPresentingGvrContext(Activity activity) {
+        mGvrLayout = new GvrLayout(activity);
+    }
+
+    @Override
+    public long getNativeGvrContext() {
+        long nativeGvrContext = 0;
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        try {
+            nativeGvrContext = mGvrLayout.getGvrApi().getNativeGvrContext();
+        } catch (Exception ex) {
+            Log.e(TAG, "Unable to instantiate GvrApi", ex);
+            return 0;
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+        return nativeGvrContext;
+    }
+
+    @Override
+    public void resume() {
+        mGvrLayout.onResume();
+    }
+
+    @Override
+    public void pause() {
+        mGvrLayout.onPause();
+    }
+
+    @Override
+    public void shutdown() {
+        mGvrLayout.shutdown();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextInterface.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextInterface.java
new file mode 100644
index 0000000..614e6fe6
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextInterface.java
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+package org.chromium.chrome.browser.vr_shell;
+
+/**
+ * Abstracts away the NonPresentingGvrContext class, which may or may not be present at runtime
+ * depending on compile flags.
+ */
+public interface NonPresentingGvrContextInterface {
+    /**
+     * Returns the native gvr context.
+     */
+    long getNativeGvrContext();
+
+    /**
+     * Must be called when activity resumes.
+     */
+    void resume();
+
+    /**
+     * Must be called when activity pauses.
+     */
+    void pause();
+
+    /**
+     * Shutdown the native gvr context.
+     */
+    void shutdown();
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 85cef3a..4ff15e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -32,10 +32,12 @@
 
     private ChromeTabbedActivity mActivity;
 
-    private boolean mVrShellEnabled;
+    private boolean mVrEnabled;
 
     private Class<? extends VrShellInterface> mVrShellClass;
+    private Class<? extends NonPresentingGvrContextInterface> mNonPresentingGvrContextClass;
     private VrShellInterface mVrShell;
+    private NonPresentingGvrContextInterface mNonPresentingGvrContext;
     private boolean mInVr;
     private int mRestoreSystemUiVisibilityFlag = -1;
     private String mVrExtra;
@@ -44,14 +46,13 @@
     public VrShellDelegate(ChromeTabbedActivity activity) {
         mActivity = activity;
 
-        mVrShellClass = maybeFindVrShell();
-        if (mVrShellClass != null) {
-            mVrShellEnabled = true;
+        mVrEnabled = maybeFindVrClasses();
+        if (mVrEnabled) {
             try {
                 mVrExtra = (String) mVrShellClass.getField("VR_EXTRA").get(null);
             } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException e) {
                 Log.e(TAG, "Unable to read VR_EXTRA field", e);
-                mVrShellEnabled = false;
+                mVrEnabled = false;
             }
         }
     }
@@ -61,18 +62,24 @@
      * class can be initialized.
      */
     public void onNativeLibraryReady() {
-        if (mVrShellEnabled) {
+        if (mVrEnabled) {
             mNativeVrShellDelegate = nativeInit();
         }
     }
 
     @SuppressWarnings("unchecked")
-    private Class<? extends VrShellInterface> maybeFindVrShell() {
+    private boolean maybeFindVrClasses() {
         try {
-            return (Class<? extends VrShellInterface>) Class
-                    .forName("org.chromium.chrome.browser.vr_shell.VrShell");
+            mVrShellClass = (Class<? extends VrShellInterface>) Class.forName(
+                    "org.chromium.chrome.browser.vr_shell.VrShell");
+            mNonPresentingGvrContextClass =
+                    (Class<? extends NonPresentingGvrContextInterface>) Class.forName(
+                            "org.chromium.chrome.browser.vr_shell.NonPresentingGvrContext");
+            return true;
         } catch (ClassNotFoundException e) {
-            return null;
+            mVrShellClass = null;
+            mNonPresentingGvrContextClass = null;
+            return false;
         }
     }
 
@@ -86,7 +93,7 @@
      */
     @CalledByNative
     public boolean enterVRIfNecessary(boolean inWebVR) {
-        if (!mVrShellEnabled || mNativeVrShellDelegate == 0) return false;
+        if (!mVrEnabled || mNativeVrShellDelegate == 0) return false;
         Tab tab = mActivity.getActivityTab();
         // TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be
         // entered without any current tabs.
@@ -124,23 +131,44 @@
     /**
      * Resumes VR Shell.
      */
-    public void resumeVR() {
-        setupVrModeWindowFlags();
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
-        try {
-            mVrShell.resume();
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "Unable to resume VrShell", e);
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
+    public void maybeResumeVR() {
+        // TODO(bshe): Ideally, we do not need two gvr context exist at the same time. We can
+        // probably shutdown non presenting gvr when presenting and create a new one after exit
+        // presenting. See crbug.com/655242
+        if (mNonPresentingGvrContext != null) {
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+            try {
+                mNonPresentingGvrContext.resume();
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Unable to resume mNonPresentingGvrContext", e);
+            } finally {
+                StrictMode.setThreadPolicy(oldPolicy);
+            }
+        }
+
+        if (mInVr) {
+            setupVrModeWindowFlags();
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+            try {
+                mVrShell.resume();
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Unable to resume VrShell", e);
+            } finally {
+                StrictMode.setThreadPolicy(oldPolicy);
+            }
         }
     }
 
     /**
      * Pauses VR Shell.
      */
-    public void pauseVR() {
-        mVrShell.pause();
+    public void maybePauseVR() {
+        if (mNonPresentingGvrContext != null) {
+            mNonPresentingGvrContext.pause();
+        }
+        if (mInVr) {
+            mVrShell.pause();
+        }
     }
 
     /**
@@ -159,6 +187,30 @@
         return true;
     }
 
+    @CalledByNative
+    private long createNonPresentingNativeContext() {
+        if (!mVrEnabled) return 0;
+
+        try {
+            Constructor<?> nonPresentingGvrContextConstructor =
+                    mNonPresentingGvrContextClass.getConstructor(Activity.class);
+            mNonPresentingGvrContext =
+                    (NonPresentingGvrContextInterface)
+                            nonPresentingGvrContextConstructor.newInstance(mActivity);
+        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+                | InvocationTargetException | NoSuchMethodException e) {
+            Log.e(TAG, "Unable to instantiate NonPresentingGvrContext", e);
+            return 0;
+        }
+        return mNonPresentingGvrContext.getNativeGvrContext();
+    }
+
+    @CalledByNative
+    private void shutdownNonPresentingNativeContext() {
+        mNonPresentingGvrContext.shutdown();
+        mNonPresentingGvrContext = null;
+    }
+
     /**
      * Exits VR Shell, performing all necessary cleanup.
      */
@@ -256,7 +308,7 @@
      * @return Whether or not VR Shell is currently enabled.
      */
     public boolean isVrShellEnabled() {
-        return mVrShellEnabled;
+        return mVrEnabled;
     }
 
     /**
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 64e6b67..e9185f68 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -981,6 +981,7 @@
   "java/src/org/chromium/chrome/browser/util/PlatformUtil.java",
   "java/src/org/chromium/chrome/browser/util/UrlUtilities.java",
   "java/src/org/chromium/chrome/browser/util/ViewUtils.java",
+  "java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContextInterface.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrShellInterface.java",
   "java/src/org/chromium/chrome/browser/webapps/ActivityAssigner.java",
@@ -1084,6 +1085,7 @@
 ]
 
 chrome_vr_java_sources = [
+  "java/src/org/chromium/chrome/browser/vr_shell/NonPresentingGvrContext.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrShell.java",
   "java/src/org/chromium/chrome/browser/vr_shell/VrWindowAndroid.java",
 ]
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.cc b/chrome/browser/android/vr_shell/vr_shell_delegate.cc
index 606a6417..af69ba1 100644
--- a/chrome/browser/android/vr_shell/vr_shell_delegate.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_delegate.cc
@@ -13,6 +13,32 @@
 
 namespace vr_shell {
 
+// A non presenting delegate for magic window mode.
+class GvrNonPresentingDelegate : public device::GvrDelegate {
+ public:
+  explicit GvrNonPresentingDelegate(jlong context) {
+    gvr_api_ =
+        gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context));
+  }
+
+  virtual ~GvrNonPresentingDelegate() = default;
+
+  // GvrDelegate implementation
+  void SetWebVRSecureOrigin(bool secure_origin) override {}
+  void SubmitWebVRFrame() override {}
+  void UpdateWebVRTextureBounds(int eye,
+                                float left,
+                                float top,
+                                float width,
+                                float height) override {}
+  void SetGvrPoseForWebVr(const gvr::Mat4f& pose,
+                          uint32_t pose_index) override {}
+  gvr::GvrApi* gvr_api() override { return gvr_api_.get(); }
+
+ private:
+  std::unique_ptr<gvr::GvrApi> gvr_api_;
+};
+
 VrShellDelegate::VrShellDelegate(JNIEnv* env, jobject obj)
     : device_provider_(nullptr) {
   j_vr_shell_delegate_.Reset(env, obj);
@@ -62,6 +88,26 @@
   Java_VrShellDelegate_exitWebVR(env, j_vr_shell_delegate_.obj());
 }
 
+device::GvrDelegate* VrShellDelegate::GetNonPresentingDelegate() {
+  if (!non_presenting_delegate_) {
+    JNIEnv* env = AttachCurrentThread();
+    jlong context = Java_VrShellDelegate_createNonPresentingNativeContext(
+        env, j_vr_shell_delegate_.obj());
+    if (!context)
+      return nullptr;
+
+    non_presenting_delegate_.reset(new GvrNonPresentingDelegate(context));
+  }
+  return non_presenting_delegate_.get();
+}
+
+void VrShellDelegate::DestroyNonPresentingDelegate() {
+  non_presenting_delegate_.reset(nullptr);
+  JNIEnv* env = AttachCurrentThread();
+  Java_VrShellDelegate_shutdownNonPresentingNativeContext(
+      env, j_vr_shell_delegate_.obj());
+}
+
 void VrShellDelegate::OnVrShellReady(VrShell* vr_shell) {
   if (device_provider_)
     device_provider_->OnGvrDelegateReady(vr_shell);
diff --git a/chrome/browser/android/vr_shell/vr_shell_delegate.h b/chrome/browser/android/vr_shell/vr_shell_delegate.h
index 99fb77afd..bf591cc 100644
--- a/chrome/browser/android/vr_shell/vr_shell_delegate.h
+++ b/chrome/browser/android/vr_shell/vr_shell_delegate.h
@@ -29,11 +29,14 @@
   // device::vrDelegateProvider implementation
   bool RequestWebVRPresent(device::GvrDeviceProvider* device_provider) override;
   void ExitWebVRPresent() override;
+  device::GvrDelegate* GetNonPresentingDelegate() override;
+  void DestroyNonPresentingDelegate() override;
 
   // Called from VRShell
   void OnVrShellReady(VrShell* vr_shell);
 
  private:
+  std::unique_ptr<device::GvrDelegate> non_presenting_delegate_;
   base::android::ScopedJavaGlobalRef<jobject> j_vr_shell_delegate_;
   device::GvrDeviceProvider* device_provider_;
 
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 682cc46..ee8ea271 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -56,10 +56,6 @@
     "//ui/android:ui_java",
   ]
 
-  if (enable_webvr) {
-    deps += [ "//device/vr:java" ]
-  }
-
   srcjar_deps = [
     ":common_aidl",
     ":content_public_android_java_enums_srcjar",
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index 860b4881..317c898 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -45,7 +45,6 @@
     ]
 
     deps += [
-      ":jni_headers",
       "//device/gamepad",
       "//third_party/WebKit/public:blink_headers",
       "//third_party/gvr-android-sdk:libgvr",
@@ -79,22 +78,3 @@
 
   use_new_wrapper_types = false
 }
-
-if (is_android) {
-  java_sources_needing_jni =
-      [ "android/java/src/org/chromium/device/vr/GvrDeviceProvider.java" ]
-
-  generate_jni("jni_headers") {
-    sources = java_sources_needing_jni
-    jni_package = "vr"
-  }
-
-  android_library("java") {
-    java_files = java_sources_needing_jni
-    deps = [
-      "//base:base_java",
-      "//third_party/android_protobuf:protobuf_nano_javalib",
-      "//third_party/gvr-android-sdk:gvr_common_java",
-    ]
-  }
-}
diff --git a/device/vr/android/gvr/gvr_delegate.h b/device/vr/android/gvr/gvr_delegate.h
index 18be9b8..d7b4297 100644
--- a/device/vr/android/gvr/gvr_delegate.h
+++ b/device/vr/android/gvr/gvr_delegate.h
@@ -15,18 +15,6 @@
 
 namespace device {
 
-class DEVICE_VR_EXPORT GvrDelegateProvider {
- public:
-  static void SetInstance(GvrDelegateProvider* delegate_provider);
-  static GvrDelegateProvider* GetInstance();
-
-  virtual bool RequestWebVRPresent(GvrDeviceProvider* device_provider) = 0;
-  virtual void ExitWebVRPresent() = 0;
-
- private:
-  static GvrDelegateProvider* delegate_provider_;
-};
-
 class DEVICE_VR_EXPORT GvrDelegate {
  public:
   virtual void SetWebVRSecureOrigin(bool secure_origin) = 0;
@@ -41,6 +29,20 @@
   virtual gvr::GvrApi* gvr_api() = 0;
 };
 
+class DEVICE_VR_EXPORT GvrDelegateProvider {
+ public:
+  static void SetInstance(GvrDelegateProvider* delegate_provider);
+  static GvrDelegateProvider* GetInstance();
+
+  virtual bool RequestWebVRPresent(GvrDeviceProvider* device_provider) = 0;
+  virtual void ExitWebVRPresent() = 0;
+  virtual GvrDelegate* GetNonPresentingDelegate() = 0;
+  virtual void DestroyNonPresentingDelegate() = 0;
+
+ private:
+  static GvrDelegateProvider* delegate_provider_;
+};
+
 }  // namespace device
 
 #endif  // DEVICE_VR_ANDROID_GVR_DELEGATE_H
diff --git a/device/vr/android/gvr/gvr_device_provider.cc b/device/vr/android/gvr/gvr_device_provider.cc
index 1025ca4..252aa117 100644
--- a/device/vr/android/gvr/gvr_device_provider.cc
+++ b/device/vr/android/gvr/gvr_device_provider.cc
@@ -14,7 +14,6 @@
 #include "device/vr/android/gvr/gvr_device.h"
 #include "device/vr/android/gvr/gvr_gamepad_data_fetcher.h"
 #include "device/vr/vr_device_manager.h"
-#include "jni/GvrDeviceProvider_jni.h"
 #include "third_party/gvr-android-sdk/src/ndk/include/vr/gvr/capi/include/gvr.h"
 #include "third_party/gvr-android-sdk/src/ndk/include/vr/gvr/capi/include/gvr_controller.h"
 #include "third_party/gvr-android-sdk/src/ndk/include/vr/gvr/capi/include/gvr_types.h"
@@ -24,62 +23,16 @@
 
 namespace device {
 
-// A temporary delegate till a VrShell instance becomes available.
-class GvrNonPresentingDelegate : public GvrDelegate {
- public:
-  GvrNonPresentingDelegate() { Initialize(); }
-
-  virtual ~GvrNonPresentingDelegate() { Shutdown(); }
-
-  void Initialize() {
-    if (j_device_.is_null()) {
-      JNIEnv* env = AttachCurrentThread();
-
-      j_device_.Reset(
-          Java_GvrDeviceProvider_create(env, GetApplicationContext()));
-      jlong context =
-          Java_GvrDeviceProvider_getNativeContext(env, j_device_.obj());
-
-      if (!context)
-        return;
-
-      gvr_api_ =
-          gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(context));
-    }
-  }
-
-  void Shutdown() {
-    if (!j_device_.is_null()) {
-      gvr_api_ = nullptr;
-      JNIEnv* env = AttachCurrentThread();
-      Java_GvrDeviceProvider_shutdown(env, j_device_.obj());
-      j_device_ = nullptr;
-    }
-  }
-
-  // GvrDelegate implementation
-  void SetWebVRSecureOrigin(bool secure_origin) override {}
-  void SubmitWebVRFrame() override {}
-  void UpdateWebVRTextureBounds(int eye,
-                                float left,
-                                float top,
-                                float width,
-                                float height) override {}
-  void SetGvrPoseForWebVr(const gvr::Mat4f& pose,
-                          uint32_t pose_index) override {}
-
-  gvr::GvrApi* gvr_api() override { return gvr_api_.get(); }
-
- private:
-  base::android::ScopedJavaGlobalRef<jobject> j_device_;
-  std::unique_ptr<gvr::GvrApi> gvr_api_;
-};
-
 GvrDeviceProvider::GvrDeviceProvider()
     : VRDeviceProvider(),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
 GvrDeviceProvider::~GvrDeviceProvider() {
+  device::GvrDelegateProvider* delegate_provider =
+      device::GvrDelegateProvider::GetInstance();
+  if (delegate_provider)
+    delegate_provider->DestroyNonPresentingDelegate();
+
   ExitPresent();
 }
 
@@ -96,17 +49,25 @@
 }
 
 void GvrDeviceProvider::Initialize() {
+  device::GvrDelegateProvider* delegate_provider =
+      device::GvrDelegateProvider::GetInstance();
+  if (!delegate_provider)
+    return;
+
   if (!vr_device_) {
-    vr_device_.reset(new GvrDevice(this, nullptr));
+    vr_device_.reset(
+        new GvrDevice(this, delegate_provider->GetNonPresentingDelegate()));
     client_->OnDeviceConnectionStatusChanged(vr_device_.get(), true);
   }
 }
 
 bool GvrDeviceProvider::RequestPresent() {
-  GvrDelegateProvider* delegate_provider = GvrDelegateProvider::GetInstance();
+  device::GvrDelegateProvider* delegate_provider =
+      device::GvrDelegateProvider::GetInstance();
   if (!delegate_provider)
     return false;
 
+  // RequestWebVRPresent is async as a render thread may be created.
   return delegate_provider->RequestWebVRPresent(this);
 }
 
@@ -116,14 +77,17 @@
   if (!vr_device_)
     return;
 
-  vr_device_->SetDelegate(nullptr);
+  device::GvrDelegateProvider* delegate_provider =
+      device::GvrDelegateProvider::GetInstance();
+  if (!delegate_provider)
+    return;
+
+  vr_device_->SetDelegate(delegate_provider->GetNonPresentingDelegate());
 
   GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory(
       GAMEPAD_SOURCE_GVR);
 
-  GvrDelegateProvider* delegate_provider = GvrDelegateProvider::GetInstance();
-  if (delegate_provider)
-    delegate_provider->ExitWebVRPresent();
+  delegate_provider->ExitWebVRPresent();
 
   if (client_)
     client_->OnPresentEnded(vr_device_.get());
@@ -137,12 +101,10 @@
 }
 
 void GvrDeviceProvider::OnGvrDelegateRemoved() {
+  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
   if (!vr_device_)
     return;
-
-  main_thread_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&GvrDeviceProvider::ExitPresent, base::Unretained(this)));
+  ExitPresent();
 }
 
 void GvrDeviceProvider::GvrDelegateReady(GvrDelegate* delegate) {
diff --git a/device/vr/android/gvr/gvr_device_provider.h b/device/vr/android/gvr/gvr_device_provider.h
index bb64966..23f8cb0 100644
--- a/device/vr/android/gvr/gvr_device_provider.h
+++ b/device/vr/android/gvr/gvr_device_provider.h
@@ -18,7 +18,6 @@
 
 class GvrDelegate;
 class GvrDevice;
-class GvrNonPresentingDelegate;
 
 class DEVICE_VR_EXPORT GvrDeviceProvider : public VRDeviceProvider {
  public:
diff --git a/device/vr/android/java/src/org/chromium/device/vr/GvrDeviceProvider.java b/device/vr/android/java/src/org/chromium/device/vr/GvrDeviceProvider.java
deleted file mode 100644
index ba4f44c..0000000
--- a/device/vr/android/java/src/org/chromium/device/vr/GvrDeviceProvider.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2016 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.
-
-package org.chromium.device.vr;
-
-import android.content.Context;
-import android.os.StrictMode;
-
-import com.google.vr.ndk.base.GvrLayout;
-
-import org.chromium.base.Log;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * This is the implementation of the C++ counterpart GvrDeviceProvider.
- */
-@JNINamespace("device")
-class GvrDeviceProvider {
-    private static final String TAG = "GvrDeviceProvider";
-    private final GvrLayout mLayout;
-
-    private GvrDeviceProvider(Context context) {
-        mLayout = new GvrLayout(context);
-    }
-
-    @CalledByNative
-    private static GvrDeviceProvider create(Context context) {
-        return new GvrDeviceProvider(context);
-    }
-
-    @CalledByNative
-    private long getNativeContext() {
-        long nativeGvrContext = 0;
-
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-
-        try {
-            nativeGvrContext = mLayout.getGvrApi().getNativeGvrContext();
-        } catch (Exception ex) {
-            Log.e(TAG, "Unable to instantiate GvrApi", ex);
-            return 0;
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
-
-        return nativeGvrContext;
-    }
-
-    @CalledByNative
-    private void shutdown() {
-        mLayout.shutdown();
-    }
-}