blob: 85180d72fadf6bc03c057e796a1e1faf7263bdfa [file] [log] [blame]
Scott Violet009c09c2020-01-18 00:57:181// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "weblayer/browser/browser_impl.h"
6
7#include <algorithm>
8
Scott Violet87450ce2020-01-23 01:56:259#include "base/path_service.h"
10#include "components/base32/base32.h"
11#include "content/public/browser/browser_context.h"
Scott Violet009c09c2020-01-18 00:57:1812#include "weblayer/browser/profile_impl.h"
Scott Violet87450ce2020-01-23 01:56:2513#include "weblayer/browser/session_service.h"
Scott Violet009c09c2020-01-18 00:57:1814#include "weblayer/browser/tab_impl.h"
Scott Violet87450ce2020-01-23 01:56:2515#include "weblayer/common/weblayer_paths.h"
Scott Violet009c09c2020-01-18 00:57:1816#include "weblayer/public/browser_observer.h"
17
18#if defined(OS_ANDROID)
19#include "base/android/callback_android.h"
20#include "base/android/jni_string.h"
21#include "base/json/json_writer.h"
22#include "weblayer/browser/java/jni/BrowserImpl_jni.h"
23#endif
24
25namespace weblayer {
26
Scott Violet87450ce2020-01-23 01:56:2527std::unique_ptr<Browser> Browser::Create(Profile* profile,
28 const std::string& persistence_id) {
29 return std::make_unique<BrowserImpl>(static_cast<ProfileImpl*>(profile),
30 persistence_id);
Scott Violet009c09c2020-01-18 00:57:1831}
32
33#if defined(OS_ANDROID)
34BrowserImpl::BrowserImpl(ProfileImpl* profile,
Scott Violet87450ce2020-01-23 01:56:2535 const std::string& persistence_id,
Scott Violet009c09c2020-01-18 00:57:1836 const base::android::JavaParamRef<jobject>& java_impl)
Scott Violet87450ce2020-01-23 01:56:2537 : BrowserImpl(profile, persistence_id) {
Scott Violet009c09c2020-01-18 00:57:1838 java_impl_ = java_impl;
39}
40#endif
41
Scott Violet87450ce2020-01-23 01:56:2542BrowserImpl::BrowserImpl(ProfileImpl* profile,
43 const std::string& persistence_id)
44 : profile_(profile), persistence_id_(persistence_id) {
45 if (!persistence_id.empty())
46 CreateSessionServiceAndRestore();
47}
Scott Violet009c09c2020-01-18 00:57:1848
49BrowserImpl::~BrowserImpl() {
50 while (!tabs_.empty()) {
51 Tab* last_tab = tabs_.back();
52 RemoveTab(last_tab);
53 DCHECK(!base::Contains(tabs_, last_tab));
54 }
55}
56
Scott Violet58ad5a32020-01-23 22:07:2757TabImpl* BrowserImpl::CreateTabForSessionRestore(
58 std::unique_ptr<content::WebContents> web_contents) {
59 TabImpl* tab = new TabImpl(profile_, std::move(web_contents));
60#if defined(OS_ANDROID)
61 // The Java side takes ownership of Tab.
62 Java_BrowserImpl_createTabForSessionRestore(
63 base::android::AttachCurrentThread(), java_impl_,
64 reinterpret_cast<jlong>(tab));
65#endif
66 AddTab(tab);
67 return tab;
68}
69
Scott Violet009c09c2020-01-18 00:57:1870#if defined(OS_ANDROID)
71void BrowserImpl::AddTab(JNIEnv* env,
72 const base::android::JavaParamRef<jobject>& caller,
73 long native_tab) {
74 AddTab(reinterpret_cast<TabImpl*>(native_tab));
75}
76
77void BrowserImpl::RemoveTab(JNIEnv* env,
78 const base::android::JavaParamRef<jobject>& caller,
79 long native_tab) {
80 RemoveTab(reinterpret_cast<TabImpl*>(native_tab));
81}
82
83base::android::ScopedJavaLocalRef<jobjectArray> BrowserImpl::GetTabs(
84 JNIEnv* env,
85 const base::android::JavaParamRef<jobject>& caller) {
86 base::android::ScopedJavaLocalRef<jclass> clazz =
87 base::android::GetClass(env, "org/chromium/weblayer_private/TabImpl");
88 jobjectArray tabs = env->NewObjectArray(tabs_.size(), clazz.obj(),
89 nullptr /* initialElement */);
90 base::android::CheckException(env);
91
92 for (size_t i = 0; i < tabs_.size(); ++i) {
93 TabImpl* tab = static_cast<TabImpl*>(tabs_[i]);
94 env->SetObjectArrayElement(tabs, i, tab->GetJavaTab().obj());
95 }
96 return base::android::ScopedJavaLocalRef<jobjectArray>(env, tabs);
97}
98
99void BrowserImpl::SetActiveTab(
100 JNIEnv* env,
101 const base::android::JavaParamRef<jobject>& caller,
102 long native_tab) {
103 SetActiveTab(reinterpret_cast<TabImpl*>(native_tab));
104}
105
106base::android::ScopedJavaLocalRef<jobject> BrowserImpl::GetActiveTab(
107 JNIEnv* env,
108 const base::android::JavaParamRef<jobject>& caller) {
109 if (!active_tab_)
110 return nullptr;
111 return base::android::ScopedJavaLocalRef<jobject>(active_tab_->GetJavaTab());
112}
Scott Violet58ad5a32020-01-23 22:07:27113
114void BrowserImpl::PrepareForShutdown(
115 JNIEnv* env,
116 const base::android::JavaParamRef<jobject>& caller) {
117 PrepareForShutdown();
118}
119
120base::android::ScopedJavaLocalRef<jstring> BrowserImpl::GetPersistenceId(
121 JNIEnv* env,
122 const base::android::JavaParamRef<jobject>& caller) {
123 return base::android::ScopedJavaLocalRef<jstring>(
124 base::android::ConvertUTF8ToJavaString(env, persistence_id_));
125}
126
Scott Violet009c09c2020-01-18 00:57:18127#endif
128
129void BrowserImpl::AddTab(Tab* tab) {
130 DCHECK(tab);
131 TabImpl* tab_impl = static_cast<TabImpl*>(tab);
132 if (tab_impl->browser() != this && tab_impl->browser())
133 tab_impl->browser()->RemoveTab(tab);
134 tabs_.push_back(tab);
135 tab_impl->set_browser(this);
136#if defined(OS_ANDROID)
137 Java_BrowserImpl_onTabAdded(base::android::AttachCurrentThread(), java_impl_,
138 tab ? tab_impl->GetJavaTab() : nullptr);
139#endif
140 for (BrowserObserver& obs : browser_observers_)
141 obs.OnTabAdded(tab);
142}
143
144void BrowserImpl::RemoveTab(Tab* tab) {
145 TabImpl* tab_impl = static_cast<TabImpl*>(tab);
146 DCHECK_EQ(this, tab_impl->browser());
147 static_cast<TabImpl*>(tab)->set_browser(nullptr);
148 tabs_.erase(std::find(tabs_.begin(), tabs_.end(), tab));
149 const bool active_tab_changed = active_tab_ == tab;
150 if (active_tab_changed)
151 active_tab_ = nullptr;
152#if defined(OS_ANDROID)
153 if (active_tab_changed) {
154 Java_BrowserImpl_onActiveTabChanged(
155 base::android::AttachCurrentThread(), java_impl_,
156 active_tab_ ? static_cast<TabImpl*>(active_tab_)->GetJavaTab()
157 : nullptr);
158 }
159 Java_BrowserImpl_onTabRemoved(base::android::AttachCurrentThread(),
160 java_impl_,
161 tab ? tab_impl->GetJavaTab() : nullptr);
162#endif
163 if (active_tab_changed) {
164 for (BrowserObserver& obs : browser_observers_)
165 obs.OnActiveTabChanged(active_tab_);
166 }
167 for (BrowserObserver& obs : browser_observers_)
168 obs.OnTabRemoved(tab, active_tab_changed);
169}
170
171void BrowserImpl::SetActiveTab(Tab* tab) {
172 if (GetActiveTab() == tab)
173 return;
174 // TODO: currently the java side sets visibility, this code likely should
175 // too and it should be removed from the java side.
176 active_tab_ = static_cast<TabImpl*>(tab);
177#if defined(OS_ANDROID)
178 Java_BrowserImpl_onActiveTabChanged(
179 base::android::AttachCurrentThread(), java_impl_,
180 active_tab_ ? active_tab_->GetJavaTab() : nullptr);
181#endif
182 for (BrowserObserver& obs : browser_observers_)
183 obs.OnActiveTabChanged(active_tab_);
184 if (active_tab_)
185 active_tab_->web_contents()->GetController().LoadIfNecessary();
186}
187
188Tab* BrowserImpl::GetActiveTab() {
189 return active_tab_;
190}
191
192const std::vector<Tab*>& BrowserImpl::GetTabs() {
193 return tabs_;
194}
195
Scott Violet87450ce2020-01-23 01:56:25196void BrowserImpl::PrepareForShutdown() {
197 session_service_.reset();
198}
199
Scott Violet58ad5a32020-01-23 22:07:27200const std::string& BrowserImpl::GetPersistenceId() {
201 return persistence_id_;
202}
203
Scott Violet009c09c2020-01-18 00:57:18204void BrowserImpl::AddObserver(BrowserObserver* observer) {
205 browser_observers_.AddObserver(observer);
206}
207
208void BrowserImpl::RemoveObserver(BrowserObserver* observer) {
209 browser_observers_.RemoveObserver(observer);
210}
211
Scott Violet87450ce2020-01-23 01:56:25212base::FilePath BrowserImpl::GetSessionServiceDataPath() {
213 base::FilePath base_path;
214 if (profile_->GetBrowserContext()->IsOffTheRecord()) {
215 CHECK(base::PathService::Get(DIR_USER_DATA, &base_path));
216 base_path = base_path.AppendASCII("Incognito Restore Data");
217 } else {
218 base_path = profile_->data_path().AppendASCII("Restore Data");
219 }
220 const std::string encoded_name = base32::Base32Encode(persistence_id_);
221 return base_path.AppendASCII("State" + encoded_name);
222}
223
224void BrowserImpl::CreateSessionServiceAndRestore() {
225 session_service_ =
226 std::make_unique<SessionService>(GetSessionServiceDataPath(), this);
227}
228
Scott Violet009c09c2020-01-18 00:57:18229#if defined(OS_ANDROID)
230static jlong JNI_BrowserImpl_CreateBrowser(
231 JNIEnv* env,
232 jlong profile,
Scott Violet58ad5a32020-01-23 22:07:27233 const base::android::JavaParamRef<jstring>& persistence_id,
Scott Violet009c09c2020-01-18 00:57:18234 const base::android::JavaParamRef<jobject>& java_impl) {
Scott Violet87450ce2020-01-23 01:56:25235 return reinterpret_cast<intptr_t>(new BrowserImpl(
Scott Violet58ad5a32020-01-23 22:07:27236 reinterpret_cast<ProfileImpl*>(profile),
237 persistence_id.obj()
238 ? base::android::ConvertJavaStringToUTF8(persistence_id)
239 : std::string(),
240 java_impl));
Scott Violet009c09c2020-01-18 00:57:18241}
242
243static void JNI_BrowserImpl_DeleteBrowser(JNIEnv* env, jlong browser) {
244 delete reinterpret_cast<BrowserImpl*>(browser);
245}
246#endif
247
248} // namespace weblayer