Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/webapps/WebappActivity.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 package org.chromium.chrome.browser.webapps;
6
7 import android.content.Context;
8 import android.content.Intent;
9 import android.graphics.Bitmap;
10 import android.net.Uri;
11 import android.os.AsyncTask;
12 import android.os.Bundle;
13 import android.text.TextUtils;
14 import android.util.Log;
15 import android.view.View;
16
17 import com.google.android.apps.chrome.R;
18
19 import org.chromium.base.ActivityState;
20 import org.chromium.base.ApiCompatibilityUtils;
21 import org.chromium.base.ApplicationStatus;
22 import org.chromium.base.VisibleForTesting;
23 import org.chromium.chrome.browser.EmptyTabObserver;
24 import org.chromium.chrome.browser.ShortcutHelper;
25 import org.chromium.chrome.browser.Tab;
26 import org.chromium.chrome.browser.TabObserver;
27 import org.chromium.chrome.browser.UrlUtilities;
28 import org.chromium.chrome.browser.document.DocumentUtils;
29 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
30 import org.chromium.chrome.browser.ssl.ConnectionSecurityHelperSecurityLevel;
31 import org.chromium.chrome.browser.util.FeatureUtilities;
32 import org.chromium.content.browser.ScreenOrientationProvider;
33 import org.chromium.content_public.browser.LoadUrlParams;
34 import org.chromium.content_public.browser.WebContentsObserver;
35 import org.chromium.net.NetworkChangeNotifier;
36 import org.chromium.ui.base.PageTransition;
37
38 import java.io.File;
39
40 /**
41 * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear).
42 */
43 public class WebappActivity extends FullScreenActivity {
44 public static final String WEBAPP_SCHEME = "webapp";
45
46 private static final String TAG = "WebappActivity";
47 private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000 ;
48
49 private final WebappInfo mWebappInfo;
50 private AsyncTask<Void, Void, Void> mCleanupTask;
51
52 private WebContentsObserver mWebContentsObserver;
53
54 private WebappUrlBar mUrlBar;
55
56 private boolean mIsInitialized;
57 private Integer mBrandColor;
58
59 /**
60 * Construct all the variables that shouldn't change. We do it here both to clarify when the
61 * objects are created and to ensure that they exist throughout the parallel ized initialization
62 * of the WebappActivity.
63 */
64 public WebappActivity() {
65 mWebappInfo = WebappInfo.createEmpty();
66 }
67
68 @Override
69 protected void onNewIntent(Intent intent) {
70 if (intent == null) return;
71 super.onNewIntent(intent);
72
73 WebappInfo newWebappInfo = WebappInfo.create(intent);
74 if (newWebappInfo == null) {
75 Log.e(TAG, "Failed to parse new Intent: " + intent);
76 finish();
77 } else if (!TextUtils.equals(mWebappInfo.id(), newWebappInfo.id())) {
78 mWebappInfo.copy(newWebappInfo);
79 resetSavedInstanceState();
80 if (mIsInitialized) initializeUI(null);
81 }
82 }
83
84 private void initializeUI(Bundle savedInstanceState) {
85 // We do not load URL when restoring from saved instance states.
86 if (savedInstanceState == null && mWebappInfo.isInitialized()) {
87 if (TextUtils.isEmpty(getActivityTab().getUrl())) {
88 getActivityTab().loadUrl(new LoadUrlParams(
89 mWebappInfo.uri().toString(), PageTransition.AUTO_TOPLEV EL));
90 }
91 } else {
92 if (NetworkChangeNotifier.isOnline()) getActivityTab().reloadIgnorin gCache();
93 }
94
95 mWebContentsObserver = createWebContentsObserver();
96 getActivityTab().addObserver(createTabObserver());
97 updateTaskDescription();
98 removeWindowBackground();
99 }
100
101 @Override
102 public void preInflationStartup() {
103 WebappInfo info = WebappInfo.create(getIntent());
104 if (info != null) mWebappInfo.copy(info);
105 mCleanupTask = new WebappDirectoryManager(getActivityDirectory(),
106 WEBAPP_SCHEME, FeatureUtilities.isDocumentModeEligible(this));
107
108 ScreenOrientationProvider.lockOrientation((byte) mWebappInfo.orientation (), this);
109 super.preInflationStartup();
110 }
111
112 @Override
113 public void finishNativeInitialization() {
114 if (!mWebappInfo.isInitialized()) finish();
115 super.finishNativeInitialization();
116 initializeUI(getSavedInstanceState());
117 mIsInitialized = true;
118 }
119
120 @Override
121 protected void onSaveInstanceState(Bundle outState) {
122 super.onSaveInstanceState(outState);
123 mWebappInfo.writeToBundle(outState);
124 if (getActivityTab() != null) getActivityTab().saveInstanceState(outStat e);
125 }
126
127 @Override
128 public void onStartWithNative() {
129 super.onStartWithNative();
130 if (mCleanupTask.getStatus() == AsyncTask.Status.PENDING) mCleanupTask.e xecute();
131 }
132
133 @Override
134 public void onStopWithNative() {
135 super.onStopWithNative();
136 mCleanupTask.cancel(true);
137 if (getActivityTab() != null) getActivityTab().saveState(getActivityDire ctory());
138 if (getFullscreenManager() != null) {
139 getFullscreenManager().setPersistentFullscreenMode(false);
140 }
141 }
142
143 @Override
144 public void onResume() {
145 if (!isFinishing() && getIntent() != null) {
146 // Avoid situations where Android starts two Activities with the sam e data.
147 DocumentUtils.finishOtherTasksWithData(getIntent().getData(), getTas kId());
148 }
149 super.onResume();
150 }
151 @Override
152 protected int getControlContainerLayoutId() {
153 return R.layout.webapp_control_container;
154 }
155
156 @Override
157 public void postInflationStartup() {
158 super.postInflationStartup();
159 WebappControlContainer controlContainer =
160 (WebappControlContainer) findViewById(R.id.control_container);
161 mUrlBar = (WebappUrlBar) controlContainer.findViewById(R.id.webapp_url_b ar);
162 }
163
164 /**
165 * @return Structure containing data about the webapp currently displayed.
166 */
167 WebappInfo getWebappInfo() {
168 return mWebappInfo;
169 }
170
171 private void updateUrlBar() {
172 Tab tab = getActivityTab();
173 if (tab == null || mUrlBar == null) return;
174 mUrlBar.update(tab.getUrl(), tab.getSecurityLevel());
175 }
176
177 private WebContentsObserver createWebContentsObserver() {
178 // TODO: Move to TabObserver eventually.
179 return new WebContentsObserver(getActivityTab().getWebContents()) {
180 @Override
181 public void didNavigateMainFrame(String url, String baseUrl,
182 boolean isNavigationToDifferentPage, boolean isNavigationInP age,
183 int statusCode) {
184 updateUrlBar();
185 }
186
187 @Override
188 public void didAttachInterstitialPage() {
189 updateUrlBar();
190
191 int state = ApplicationStatus.getStateForActivity(WebappActivity .this);
192 if (state == ActivityState.PAUSED || state == ActivityState.STOP PED
193 || state == ActivityState.DESTROYED) {
194 return;
195 }
196
197 // Kick the interstitial navigation to Chrome.
198 Intent intent = new Intent(
199 Intent.ACTION_VIEW, Uri.parse(getActivityTab().getUrl()) );
200 intent.setPackage(getPackageName());
201 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
202 startActivity(intent);
203
204 // Pretend like the navigation never happened. We delay so that this happens while
205 // the Activity is in the background.
206 mHandler.postDelayed(new Runnable() {
207 @Override
208 public void run() {
209 getActivityTab().goBack();
210 }
211 }, MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL);
212 }
213
214 @Override
215 public void didDetachInterstitialPage() {
216 updateUrlBar();
217 }
218 };
219 }
220
221 private boolean isWebappDomain() {
222 return UrlUtilities.sameDomainOrHost(
223 getActivityTab().getUrl(), getWebappInfo().uri().toString(), tru e);
224 }
225
226 protected TabObserver createTabObserver() {
227 return new EmptyTabObserver() {
228 @Override
229 public void onSSLStateUpdated(Tab tab) {
230 updateUrlBar();
231 }
232
233 @Override
234 public void onDidStartProvisionalLoadForFrame(
235 Tab tab, long frameId, long parentFrameId, boolean isMainFra me,
236 String validatedUrl, boolean isErrorPage, boolean isIframeSr cdoc) {
237 if (isMainFrame) updateUrlBar();
238 }
239
240 @Override
241 public void onDidChangeThemeColor(int color) {
242 if (!isWebappDomain()) return;
243 mBrandColor = color;
244 updateTaskDescription();
245 }
246
247 @Override
248 public void onTitleUpdated(Tab tab) {
249 if (!isWebappDomain()) return;
250 updateTaskDescription();
251 }
252
253 @Override
254 public void onFaviconUpdated(Tab tab) {
255 if (!isWebappDomain()) return;
256 updateTaskDescription();
257 }
258 };
259 }
260
261 private void updateTaskDescription() {
262 String title = mWebappInfo.title() == null
263 ? getActivityTab().getTitle() : mWebappInfo.title();
264 Bitmap icon = mWebappInfo.icon() == null
265 ? getActivityTab().getFavicon() : mWebappInfo.icon();
266 int color = mBrandColor == null
267 ? getResources().getColor(R.color.default_primary_color) : mBran dColor;
268
269 DocumentUtils.updateTaskDescription(this, title, icon, color, mBrandColo r == null);
270 }
271
272 /**
273 * Get the active directory by this web app.
274 *
275 * @return The directory used for the current web app.
276 */
277 @Override
278 protected File getActivityDirectory() {
279 return WebappDirectoryManager.getWebappDirectory(mWebappInfo.id());
280 }
281
282 @VisibleForTesting
283 WebappUrlBar getUrlBarForTests() {
284 return mUrlBar;
285 }
286
287 @VisibleForTesting
288 boolean isUrlBarVisible() {
289 return findViewById(R.id.control_container).getVisibility() == View.VISI BLE;
290 }
291
292 @Override
293 protected final ChromeFullscreenManager createFullscreenManager(View control Container) {
294 return new ChromeFullscreenManager(this, controlContainer, getTabModelSe lector(),
295 getControlContainerHeightResource(), false /* supportsBrowserOve rride */);
296 }
297
298 @Override
299 protected int getControlContainerHeightResource() {
300 return R.dimen.webapp_control_container_height;
301 }
302
303 // Implements {@link FullScreenActivityTab.TopControlsVisibilityDelegate}.
304 @Override
305 public boolean shouldShowTopControls(String url, int securityLevel) {
306 boolean visible = false; // do not show top controls when URL is not re ady yet.
307 if (!TextUtils.isEmpty(url)) {
308 boolean isSameWebsite =
309 UrlUtilities.sameDomainOrHost(mWebappInfo.uri().toString(), url, true);
310 visible = !isSameWebsite
311 || securityLevel == ConnectionSecurityHelperSecurityLevel.SE CURITY_ERROR
312 || securityLevel == ConnectionSecurityHelperSecurityLevel.SE CURITY_WARNING;
313 }
314
315 return visible;
316 }
317
318 // We're temporarily disable CS on webapp since there are some issues. (http ://crbug.com/471950)
319 // TODO(changwan): re-enable it once the issues are resolved.
320 @Override
321 protected boolean isContextualSearchAllowed() {
322 return false;
323 }
324
325 /**
326 * Launches the URL in its own WebappActivity.
327 * @param context Context to use for launching the webapp.
328 * @param id ID of the webapp.
329 * @param url URL for the webapp.
330 * @param icon Base64 encoded Bitmap representing the webapp.
331 * @param title String to show in Recents.
332 * @param orientation Default orientation for the activity.
333 */
334 public static void launchInstance(Context context, String id, String url, St ring icon,
335 String title, int orientation) {
336 String activityName = WebappActivity.class.getName();
337 if (!FeatureUtilities.isDocumentModeEligible(context)) {
338 // Specifically assign the app to a particular WebappActivity instan ce.
339 int activityIndex = ActivityAssigner.instance(context).assign(id);
340 activityName += String.valueOf(activityIndex);
341 }
342
343 // Fire an intent to launch the Webapp in an unmapped Activity.
344 Intent webappIntent = new Intent();
345 webappIntent.setClassName(context, activityName);
346 webappIntent.putExtra(ShortcutHelper.EXTRA_ICON, icon);
347 webappIntent.putExtra(ShortcutHelper.EXTRA_ID, id);
348 webappIntent.putExtra(ShortcutHelper.EXTRA_URL, url);
349 webappIntent.putExtra(ShortcutHelper.EXTRA_TITLE, title);
350 webappIntent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, orientation);
351
352 // On L, firing intents with the exact same data should relaunch a parti cular Activity.
353 webappIntent.setAction(Intent.ACTION_VIEW);
354 webappIntent.setData(Uri.parse(WEBAPP_SCHEME + "://" + id));
355 webappIntent.setFlags(ApiCompatibilityUtils.getActivityNewDocumentFlag() );
356
357 context.startActivity(webappIntent);
358 }
359 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698