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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/TabBase.java

Issue 148523013: [Android] Rename TabBase to Tab (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2014_01_22_tabbase
Patch Set: sync Created 6 years, 9 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 2012 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;
6
7 import android.app.Activity;
8 import android.content.Context;
9 import android.graphics.Bitmap;
10 import android.graphics.Color;
11 import android.view.ContextMenu;
12 import android.view.View;
13
14 import org.chromium.base.CalledByNative;
15 import org.chromium.base.ObserverList;
16 import org.chromium.chrome.browser.banners.AppBannerManager;
17 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItemDelegate;
18 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
19 import org.chromium.chrome.browser.contextmenu.ContextMenuParams;
20 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
21 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulatorWrapper;
22 import org.chromium.chrome.browser.contextmenu.EmptyChromeContextMenuItemDelegat e;
23 import org.chromium.chrome.browser.infobar.AutoLoginProcessor;
24 import org.chromium.chrome.browser.infobar.InfoBarContainer;
25 import org.chromium.chrome.browser.profiles.Profile;
26 import org.chromium.chrome.browser.ui.toolbar.ToolbarModelSecurityLevel;
27 import org.chromium.content.browser.ContentView;
28 import org.chromium.content.browser.ContentViewClient;
29 import org.chromium.content.browser.ContentViewCore;
30 import org.chromium.content.browser.NavigationClient;
31 import org.chromium.content.browser.NavigationHistory;
32 import org.chromium.content.browser.PageInfo;
33 import org.chromium.content.browser.WebContentsObserverAndroid;
34 import org.chromium.content_public.browser.WebContents;
35 import org.chromium.ui.base.Clipboard;
36 import org.chromium.ui.base.WindowAndroid;
37
38 import java.util.concurrent.atomic.AtomicInteger;
39
40 /**
41 * The basic Java representation of a tab. Contains and manages a {@link Conten tView}.
42 *
43 * TabBase provides common functionality for ChromiumTestshell's Tab as well as Chrome on Android's
44 * tab. It is intended to be extended either on Java or both Java and C++, with ownership managed
45 * by this base class.
46 *
47 * Extending just Java:
48 * - Just extend the class normally. Do not override initializeNative().
49 * Extending Java and C++:
50 * - Because of the inner-workings of JNI, the subclass is responsible for cons tructing the native
51 * subclass, which in turn constructs TabAndroid (the native counterpart to T abBase), which in
52 * turn sets the native pointer for TabBase. For destruction, subclasses in Java must clear
53 * their own native pointer reference, but TabBase#destroy() will handle dele ting the native
54 * object.
55 */
56 public abstract class TabBase implements NavigationClient {
57 public static final int INVALID_TAB_ID = -1;
58
59 /** Used for automatically generating tab ids. */
60 private static final AtomicInteger sIdCounter = new AtomicInteger();
61
62 private long mNativeTabAndroid;
63
64 /** Unique id of this tab (within its container). */
65 private final int mId;
66
67 /** Whether or not this tab is an incognito tab. */
68 private final boolean mIncognito;
69
70 /** An Application {@link Context}. Unlike {@link #mContext}, this is the o nly one that is
71 * publicly exposed to help prevent leaking the {@link Activity}. */
72 private final Context mApplicationContext;
73
74 /** The {@link Context} used to create {@link View}s and other Android compo nents. Unlike
75 * {@link #mApplicationContext}, this is not publicly exposed to help preven t leaking the
76 * {@link Activity}. */
77 private final Context mContext;
78
79 /** Gives {@link TabBase} a way to interact with the Android window. */
80 private final WindowAndroid mWindowAndroid;
81
82 /** The current native page (e.g. chrome-native://newtab), or {@code null} i f there is none. */
83 private NativePage mNativePage;
84
85 /** The {@link ContentView} showing the current page or {@code null} if the tab is frozen. */
86 private ContentView mContentView;
87
88 /** InfoBar container to show InfoBars for this tab. */
89 private InfoBarContainer mInfoBarContainer;
90
91 /** Manages app banners shown for this tab. */
92 private AppBannerManager mAppBannerManager;
93
94 /** The sync id of the TabBase if session sync is enabled. */
95 private int mSyncId;
96
97 /**
98 * The {@link ContentViewCore} for the current page, provided for convenienc e. This always
99 * equals {@link ContentView#getContentViewCore()}, or {@code null} if mCont entView is
100 * {@code null}.
101 */
102 private ContentViewCore mContentViewCore;
103
104 /**
105 * A list of TabBase observers. These are used to broadcast TabBase events to listeners.
106 */
107 private final ObserverList<TabObserver> mObservers = new ObserverList<TabObs erver>();
108
109 // Content layer Observers and Delegates
110 private ContentViewClient mContentViewClient;
111 private WebContentsObserverAndroid mWebContentsObserver;
112 private VoiceSearchTabHelper mVoiceSearchTabHelper;
113 private TabBaseChromeWebContentsDelegateAndroid mWebContentsDelegate;
114
115 /**
116 * A default {@link ChromeContextMenuItemDelegate} that supports some of the context menu
117 * functionality.
118 */
119 protected class TabBaseChromeContextMenuItemDelegate
120 extends EmptyChromeContextMenuItemDelegate {
121 private final Clipboard mClipboard;
122
123 /**
124 * Builds a {@link TabBaseChromeContextMenuItemDelegate} instance.
125 */
126 public TabBaseChromeContextMenuItemDelegate() {
127 mClipboard = new Clipboard(getApplicationContext());
128 }
129
130 @Override
131 public boolean isIncognito() {
132 return mIncognito;
133 }
134
135 @Override
136 public void onSaveToClipboard(String text, boolean isUrl) {
137 mClipboard.setText(text, text);
138 }
139
140 @Override
141 public void onSaveImageToClipboard(String url) {
142 mClipboard.setHTMLText("<img src=\"" + url + "\">", url, url);
143 }
144 }
145
146 /**
147 * A basic {@link ChromeWebContentsDelegateAndroid} that forwards some calls to the registered
148 * {@link TabObserver}s. Meant to be overridden by subclasses.
149 */
150 public class TabBaseChromeWebContentsDelegateAndroid
151 extends ChromeWebContentsDelegateAndroid {
152 @Override
153 public void onLoadProgressChanged(int progress) {
154 for (TabObserver observer : mObservers) {
155 observer.onLoadProgressChanged(TabBase.this, progress);
156 }
157 }
158
159 @Override
160 public void onUpdateUrl(String url) {
161 for (TabObserver observer : mObservers) observer.onUpdateUrl(TabBase .this, url);
162 }
163
164 @Override
165 public void showRepostFormWarningDialog(final ContentViewCore contentVie wCore) {
166 RepostFormWarningDialog warningDialog = new RepostFormWarningDialog(
167 new Runnable() {
168 @Override
169 public void run() {
170 contentViewCore.cancelPendingReload();
171 }
172 }, new Runnable() {
173 @Override
174 public void run() {
175 contentViewCore.continuePendingReload();
176 }
177 });
178 Activity activity = (Activity) mContext;
179 warningDialog.show(activity.getFragmentManager(), null);
180 }
181
182 @Override
183 public void toggleFullscreenModeForTab(boolean enableFullscreen) {
184 for (TabObserver observer : mObservers) {
185 observer.onToggleFullscreenMode(TabBase.this, enableFullscreen);
186 }
187 }
188
189 @Override
190 public void navigationStateChanged(int flags) {
191 if ((flags & INVALIDATE_TYPE_TITLE) != 0) {
192 for (TabObserver observer : mObservers) observer.onTitleUpdated( TabBase.this);
193 }
194 if ((flags & INVALIDATE_TYPE_URL) != 0) {
195 for (TabObserver observer : mObservers) observer.onUrlUpdated(Ta bBase.this);
196 }
197 }
198 }
199
200 private class TabBaseContextMenuPopulator extends ContextMenuPopulatorWrappe r {
201 public TabBaseContextMenuPopulator(ContextMenuPopulator populator) {
202 super(populator);
203 }
204
205 @Override
206 public void buildContextMenu(ContextMenu menu, Context context, ContextM enuParams params) {
207 super.buildContextMenu(menu, context, params);
208 for (TabObserver observer : mObservers) observer.onContextMenuShown( TabBase.this, menu);
209 }
210 }
211
212 private class TabBaseWebContentsObserverAndroid extends WebContentsObserverA ndroid {
213 public TabBaseWebContentsObserverAndroid(ContentViewCore contentViewCore ) {
214 super(contentViewCore);
215 }
216
217 @Override
218 public void navigationEntryCommitted() {
219 if (getNativePage() != null) {
220 pushNativePageStateToNavigationEntry();
221 }
222 }
223
224 @Override
225 public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
226 String description, String failingUrl) {
227 for (TabObserver observer : mObservers) {
228 observer.onDidFailLoad(TabBase.this, isProvisionalLoad, isMainFr ame, errorCode,
229 description, failingUrl);
230 }
231 }
232 }
233
234 /**
235 * Creates an instance of a {@link TabBase} with no id.
236 * @param incognito Whether or not this tab is incognito.
237 * @param context An instance of a {@link Context}.
238 * @param window An instance of a {@link WindowAndroid}.
239 */
240 public TabBase(boolean incognito, Context context, WindowAndroid window) {
241 this(INVALID_TAB_ID, incognito, context, window);
242 }
243
244 /**
245 * Creates an instance of a {@link TabBase}.
246 * @param id The id this tab should be identified with.
247 * @param incognito Whether or not this tab is incognito.
248 * @param context An instance of a {@link Context}.
249 * @param window An instance of a {@link WindowAndroid}.
250 */
251 public TabBase(int id, boolean incognito, Context context, WindowAndroid win dow) {
252 // We need a valid Activity Context to build the ContentView with.
253 assert context == null || context instanceof Activity;
254
255 mId = generateValidId(id);
256 mIncognito = incognito;
257 // TODO(dtrainor): Only store application context here.
258 mContext = context;
259 mApplicationContext = context != null ? context.getApplicationContext() : null;
260 mWindowAndroid = window;
261 }
262
263 /**
264 * Adds a {@link TabObserver} to be notified on {@link TabBase} changes.
265 * @param observer The {@link TabObserver} to add.
266 */
267 public final void addObserver(TabObserver observer) {
268 mObservers.addObserver(observer);
269 }
270
271 /**
272 * Removes a {@link TabObserver}.
273 * @param observer The {@link TabObserver} to remove.
274 */
275 public final void removeObserver(TabObserver observer) {
276 mObservers.removeObserver(observer);
277 }
278
279 /**
280 * @return Whether or not this tab has a previous navigation entry.
281 */
282 public boolean canGoBack() {
283 return mContentViewCore != null && mContentViewCore.canGoBack();
284 }
285
286 /**
287 * @return Whether or not this tab has a navigation entry after the current one.
288 */
289 public boolean canGoForward() {
290 return mContentViewCore != null && mContentViewCore.canGoForward();
291 }
292
293 /**
294 * Goes to the navigation entry before the current one.
295 */
296 public void goBack() {
297 if (mContentViewCore != null) mContentViewCore.goBack();
298 }
299
300 /**
301 * Goes to the navigation entry after the current one.
302 */
303 public void goForward() {
304 if (mContentViewCore != null) mContentViewCore.goForward();
305 }
306
307 @Override
308 public NavigationHistory getDirectedNavigationHistory(boolean isForward, int itemLimit) {
309 if (mContentViewCore != null) {
310 return mContentViewCore.getDirectedNavigationHistory(isForward, item Limit);
311 } else {
312 return new NavigationHistory();
313 }
314 }
315
316 @Override
317 public void goToNavigationIndex(int index) {
318 if (mContentViewCore != null) mContentViewCore.goToNavigationIndex(index );
319 }
320
321 /**
322 * Loads the current navigation if there is a pending lazy load (after tab r estore).
323 */
324 public void loadIfNecessary() {
325 if (mContentViewCore != null) mContentViewCore.loadIfNecessary();
326 }
327
328 /**
329 * Requests the current navigation to be loaded upon the next call to loadIf Necessary().
330 */
331 protected void requestRestoreLoad() {
332 if (mContentViewCore != null) mContentViewCore.requestRestoreLoad();
333 }
334
335 /**
336 * @return Whether or not the {@link TabBase} is currently showing an inters titial page, such as
337 * a bad HTTPS page.
338 */
339 public boolean isShowingInterstitialPage() {
340 ContentViewCore contentViewCore = getContentViewCore();
341 return contentViewCore != null && contentViewCore.isShowingInterstitialP age();
342 }
343
344 /**
345 * @return Whether or not the tab has something valid to render.
346 */
347 public boolean isReady() {
348 return mNativePage != null || (mContentViewCore != null && mContentViewC ore.isReady());
349 }
350
351 /**
352 * @return The {@link View} displaying the current page in the tab. This mig ht be a
353 * {@link ContentView} but could potentially be any instance of {@li nk View}. This can
354 * be {@code null}, if the tab is frozen or being initialized or des troyed.
355 */
356 public View getView() {
357 PageInfo pageInfo = getPageInfo();
358 return pageInfo != null ? pageInfo.getView() : null;
359 }
360
361 /**
362 * @return The width of the content of this tab. Can be 0 if there is no co ntent.
363 */
364 public int getWidth() {
365 View view = getView();
366 return view != null ? view.getWidth() : 0;
367 }
368
369 /**
370 * @return The height of the content of this tab. Can be 0 if there is no c ontent.
371 */
372 public int getHeight() {
373 View view = getView();
374 return view != null ? view.getHeight() : 0;
375 }
376
377 /**
378 * @return The application {@link Context} associated with this tab.
379 */
380 protected Context getApplicationContext() {
381 return mApplicationContext;
382 }
383
384 /**
385 * @return The infobar container.
386 */
387 public final InfoBarContainer getInfoBarContainer() {
388 return mInfoBarContainer;
389 }
390
391 /**
392 * Create an {@code AutoLoginProcessor} to decide how to handle login
393 * requests.
394 */
395 protected abstract AutoLoginProcessor createAutoLoginProcessor();
396
397 /**
398 * Prints the current page.
399 *
400 * @return Whether the printing process is started successfully.
401 **/
402 public boolean print() {
403 assert mNativeTabAndroid != 0;
404 return nativePrint(mNativeTabAndroid);
405 }
406
407 /**
408 * Reloads the current page content if it is a {@link ContentView}.
409 */
410 public void reload() {
411 // TODO(dtrainor): Should we try to rebuild the ContentView if it's froz en?
412 if (mContentViewCore != null) mContentViewCore.reload(true);
413 }
414
415 /**
416 * Reloads the current page content if it is a {@link ContentView}.
417 * This version ignores the cache and reloads from the network.
418 */
419 public void reloadIgnoringCache() {
420 if (mContentViewCore != null) mContentViewCore.reloadIgnoringCache(true) ;
421 }
422
423 /** Stop the current navigation. */
424 public void stopLoading() {
425 if (mContentViewCore != null) mContentViewCore.stopLoading();
426 }
427
428 /**
429 * @return The background color of the tab.
430 */
431 public int getBackgroundColor() {
432 return getPageInfo() != null ? getPageInfo().getBackgroundColor() : Colo r.WHITE;
433 }
434
435 /**
436 * @return The web contents associated with this tab.
437 */
438 public WebContents getWebContents() {
439 if (mNativeTabAndroid == 0) return null;
440 return nativeGetWebContents(mNativeTabAndroid);
441 }
442
443 /**
444 * @return The profile associated with this tab.
445 */
446 public Profile getProfile() {
447 if (mNativeTabAndroid == 0) return null;
448 return nativeGetProfileAndroid(mNativeTabAndroid);
449 }
450
451 /**
452 * @return The id representing this tab.
453 */
454 @CalledByNative
455 public int getId() {
456 return mId;
457 }
458
459 /**
460 * @return Whether or not this tab is incognito.
461 */
462 public boolean isIncognito() {
463 return mIncognito;
464 }
465
466 /**
467 * @return The {@link ContentView} associated with the current page, or {@co de null} if
468 * there is no current page or the current page is displayed using s omething besides a
469 * {@link ContentView}.
470 */
471 public ContentView getContentView() {
472 return mNativePage == null ? mContentView : null;
473 }
474
475 /**
476 * @return The {@link ContentViewCore} associated with the current page, or {@code null} if
477 * there is no current page or the current page is displayed using s omething besides a
478 * {@link ContentView}.
479 */
480 public ContentViewCore getContentViewCore() {
481 return mNativePage == null ? mContentViewCore : null;
482 }
483
484 /**
485 * @return A {@link PageInfo} describing the current page. This is always n ot {@code null}
486 * except during initialization, destruction, and when the tab is fr ozen.
487 */
488 public PageInfo getPageInfo() {
489 return mNativePage != null ? mNativePage : mContentView;
490 }
491
492 /**
493 * @return The {@link NativePage} associated with the current page, or {@cod e null} if there is
494 * no current page or the current page is displayed using something besides
495 * {@link NativePage}.
496 */
497 public NativePage getNativePage() {
498 return mNativePage;
499 }
500
501 /**
502 * @return Whether or not the {@link TabBase} represents a {@link NativePage }.
503 */
504 public boolean isNativePage() {
505 return mNativePage != null;
506 }
507
508 /**
509 * Set whether or not the {@link ContentViewCore} should be using a desktop user agent for the
510 * currently loaded page.
511 * @param useDesktop If {@code true}, use a desktop user agent. Otherwi se use a mobile one.
512 * @param reloadOnChange Reload the page if the user agent has changed.
513 */
514 public void setUseDesktopUserAgent(boolean useDesktop, boolean reloadOnChang e) {
515 if (mContentViewCore != null) {
516 mContentViewCore.setUseDesktopUserAgent(useDesktop, reloadOnChange);
517 }
518 }
519
520 /**
521 * @return Whether or not the {@link ContentViewCore} is using a desktop use r agent.
522 */
523 public boolean getUseDesktopUserAgent() {
524 return mContentViewCore != null && mContentViewCore.getUseDesktopUserAge nt();
525 }
526
527 /**
528 * @return The current {ToolbarModelSecurityLevel} for the tab.
529 */
530 public int getSecurityLevel() {
531 if (mNativeTabAndroid == 0) return ToolbarModelSecurityLevel.NONE;
532 return nativeGetSecurityLevel(mNativeTabAndroid);
533 }
534
535 /**
536 * @return The sync id of the tab if session sync is enabled, {@code 0} othe rwise.
537 */
538 @CalledByNative
539 protected int getSyncId() {
540 return mSyncId;
541 }
542
543 /**
544 * @param syncId The sync id of the tab if session sync is enabled.
545 */
546 @CalledByNative
547 protected void setSyncId(int syncId) {
548 mSyncId = syncId;
549 }
550
551 /**
552 * @return An {@link ObserverList.RewindableIterator} instance that points t o all of
553 * the current {@link TabObserver}s on this class. Note that callin g
554 * {@link java.util.Iterator#remove()} will throw an
555 * {@link UnsupportedOperationException}.
556 */
557 protected ObserverList.RewindableIterator<TabObserver> getTabObservers() {
558 return mObservers.rewindableIterator();
559 }
560
561 /**
562 * @return The {@link ContentViewClient} currently bound to any {@link Conte ntViewCore}
563 * associated with the current page. There can still be a {@link Co ntentViewClient}
564 * even when there is no {@link ContentViewCore}.
565 */
566 protected ContentViewClient getContentViewClient() {
567 return mContentViewClient;
568 }
569
570 /**
571 * @param client The {@link ContentViewClient} to be bound to any current or new
572 * {@link ContentViewCore}s associated with this {@link TabBas e}.
573 */
574 protected void setContentViewClient(ContentViewClient client) {
575 if (mContentViewClient == client) return;
576
577 ContentViewClient oldClient = mContentViewClient;
578 mContentViewClient = client;
579
580 if (mContentViewCore == null) return;
581
582 if (mContentViewClient != null) {
583 mContentViewCore.setContentViewClient(mContentViewClient);
584 } else if (oldClient != null) {
585 // We can't set a null client, but we should clear references to the last one.
586 mContentViewCore.setContentViewClient(new ContentViewClient());
587 }
588 }
589
590 /**
591 * Triggers the showing logic for the view backing this tab.
592 */
593 protected void show() {
594 if (mContentViewCore != null) mContentViewCore.onShow();
595 }
596
597 /**
598 * Triggers the hiding logic for the view backing the tab.
599 */
600 protected void hide() {
601 if (mContentViewCore != null) mContentViewCore.onHide();
602 }
603
604 /**
605 * Shows the given {@code nativePage} if it's not already showing.
606 * @param nativePage The {@link NativePage} to show.
607 */
608 protected void showNativePage(NativePage nativePage) {
609 if (mNativePage == nativePage) return;
610 NativePage previousNativePage = mNativePage;
611 mNativePage = nativePage;
612 pushNativePageStateToNavigationEntry();
613 for (TabObserver observer : mObservers) observer.onContentChanged(this);
614 destroyNativePageInternal(previousNativePage);
615 }
616
617 /**
618 * Hides the current {@link NativePage}, if any, and shows the {@link Conten tView}.
619 */
620 protected void showRenderedPage() {
621 if (mNativePage == null) return;
622 NativePage previousNativePage = mNativePage;
623 mNativePage = null;
624 for (TabObserver observer : mObservers) observer.onContentChanged(this);
625 destroyNativePageInternal(previousNativePage);
626 }
627
628 /**
629 * Initializes this {@link TabBase}.
630 */
631 public void initialize() {
632 initializeNative();
633 }
634
635 /**
636 * Builds the native counterpart to this class. Meant to be overridden by s ubclasses to build
637 * subclass native counterparts instead. Subclasses should not call this vi a super and instead
638 * rely on the native class to create the JNI association.
639 */
640 protected void initializeNative() {
641 if (mNativeTabAndroid == 0) nativeInit();
642 assert mNativeTabAndroid != 0;
643 }
644
645 /**
646 * A helper method to initialize a {@link ContentView} without any native We bContents pointer.
647 */
648 protected final void initContentView() {
649 initContentView(ContentViewUtil.createNativeWebContents(mIncognito));
650 }
651
652 /**
653 * Completes the {@link ContentView} specific initialization around a native WebContents
654 * pointer. {@link #getPageInfo()} will still return the {@link NativePage} if there is one.
655 * All initialization that needs to reoccur after a web contents swap should be added here.
656 * <p />
657 * NOTE: If you attempt to pass a native WebContents that does not have the same incognito
658 * state as this tab this call will fail.
659 *
660 * @param nativeWebContents The native web contents pointer.
661 */
662 protected void initContentView(long nativeWebContents) {
663 NativePage previousNativePage = mNativePage;
664 mNativePage = null;
665 destroyNativePageInternal(previousNativePage);
666
667 mContentView = ContentView.newInstance(mContext, nativeWebContents, getW indowAndroid());
668
669 mContentViewCore = mContentView.getContentViewCore();
670 mWebContentsDelegate = createWebContentsDelegate();
671 mWebContentsObserver = new TabBaseWebContentsObserverAndroid(mContentVie wCore);
672 mVoiceSearchTabHelper = new VoiceSearchTabHelper(mContentViewCore);
673
674 if (mContentViewClient != null) mContentViewCore.setContentViewClient(mC ontentViewClient);
675
676 assert mNativeTabAndroid != 0;
677 nativeInitWebContents(
678 mNativeTabAndroid, mIncognito, mContentViewCore, mWebContentsDel egate,
679 new TabBaseContextMenuPopulator(createContextMenuPopulator()));
680
681 // In the case where restoring a Tab or showing a prerendered one we alr eady have a
682 // valid infobar container, no need to recreate one.
683 if (mInfoBarContainer == null) {
684 // The InfoBarContainer needs to be created after the ContentView ha s been natively
685 // initialized.
686 mInfoBarContainer = new InfoBarContainer(
687 (Activity) mContext, createAutoLoginProcessor(), getId(), ge tContentView(),
688 nativeWebContents);
689 } else {
690 mInfoBarContainer.onParentViewChanged(getId(), getContentView());
691 }
692
693 if (AppBannerManager.isEnabled() && mAppBannerManager == null) {
694 mAppBannerManager = new AppBannerManager(this);
695 }
696
697 for (TabObserver observer : mObservers) observer.onContentChanged(this);
698 }
699
700 /**
701 * Cleans up all internal state, destroying any {@link NativePage} or {@link ContentView}
702 * currently associated with this {@link TabBase}. This also destroys the n ative counterpart
703 * to this class, which means that all subclasses should erase their native pointers after
704 * this method is called. Once this call is made this {@link TabBase} shoul d no longer be used.
705 */
706 public void destroy() {
707 for (TabObserver observer : mObservers) observer.onDestroyed(this);
708
709 NativePage currentNativePage = mNativePage;
710 mNativePage = null;
711 destroyNativePageInternal(currentNativePage);
712 destroyContentView(true);
713
714 // Destroys the native tab after destroying the ContentView but before d estroying the
715 // InfoBarContainer. The native tab should be destroyed before the infob ar container as
716 // destroying the native tab cleanups up any remaining infobars. The inf obar container
717 // expects all infobars to be cleaned up before its own destruction.
718 assert mNativeTabAndroid != 0;
719 nativeDestroy(mNativeTabAndroid);
720 assert mNativeTabAndroid == 0;
721
722 if (mInfoBarContainer != null) {
723 mInfoBarContainer.destroy();
724 mInfoBarContainer = null;
725 }
726 }
727
728 /**
729 * @return Whether or not this Tab has a live native component.
730 */
731 public boolean isInitialized() {
732 return mNativeTabAndroid != 0;
733 }
734
735 /**
736 * @return The url associated with the tab.
737 */
738 @CalledByNative
739 public String getUrl() {
740 return mContentView != null ? mContentView.getUrl() : "";
741 }
742
743 /**
744 * @return The tab title.
745 */
746 @CalledByNative
747 public String getTitle() {
748 return getPageInfo() != null ? getPageInfo().getTitle() : "";
749 }
750
751 /**
752 * @return The bitmap of the favicon scaled to 16x16dp. null if no favicon
753 * is specified or it requires the default favicon.
754 * TODO(bauerb): Upstream implementation.
755 */
756 public Bitmap getFavicon() {
757 return null;
758 }
759
760 /**
761 * Restores the tab if it is frozen or crashed.
762 * @return true iff tab restore was triggered.
763 */
764 @CalledByNative
765 public boolean restoreIfNeeded() {
766 return false;
767 }
768
769 private void destroyNativePageInternal(NativePage nativePage) {
770 if (nativePage == null) return;
771 assert getPageInfo() != nativePage : "Attempting to destroy active page. ";
772
773 nativePage.destroy();
774 }
775
776 /**
777 * Destroys the current {@link ContentView}.
778 * @param deleteNativeWebContents Whether or not to delete the native WebCon tents pointer.
779 */
780 protected final void destroyContentView(boolean deleteNativeWebContents) {
781 if (mContentView == null) return;
782
783 destroyContentViewInternal(mContentView);
784
785 if (mInfoBarContainer != null && mInfoBarContainer.getParent() != null) {
786 mInfoBarContainer.removeFromParentView();
787 }
788 if (mContentViewCore != null) mContentViewCore.destroy();
789
790 mContentView = null;
791 mContentViewCore = null;
792 mWebContentsDelegate = null;
793 mWebContentsObserver = null;
794 mVoiceSearchTabHelper = null;
795
796 assert mNativeTabAndroid != 0;
797 nativeDestroyWebContents(mNativeTabAndroid, deleteNativeWebContents);
798 }
799
800 /**
801 * Gives subclasses the chance to clean up some state associated with this { @link ContentView}.
802 * This is because {@link #getContentView()} can return {@code null} if a {@ link NativePage}
803 * is showing.
804 * @param contentView The {@link ContentView} that should have associated st ate cleaned up.
805 */
806 protected void destroyContentViewInternal(ContentView contentView) {
807 }
808
809 /**
810 * A helper method to allow subclasses to build their own delegate.
811 * @return An instance of a {@link TabBaseChromeWebContentsDelegateAndroid}.
812 */
813 protected TabBaseChromeWebContentsDelegateAndroid createWebContentsDelegate( ) {
814 return new TabBaseChromeWebContentsDelegateAndroid();
815 }
816
817 /**
818 * A helper method to allow subclasses to build their own menu populator.
819 * @return An instance of a {@link ContextMenuPopulator}.
820 */
821 protected ContextMenuPopulator createContextMenuPopulator() {
822 return new ChromeContextMenuPopulator(new TabBaseChromeContextMenuItemDe legate());
823 }
824
825 /**
826 * @return The {@link WindowAndroid} associated with this {@link TabBase}.
827 */
828 public WindowAndroid getWindowAndroid() {
829 return mWindowAndroid;
830 }
831
832 /**
833 * @return The current {@link TabBaseChromeWebContentsDelegateAndroid} insta nce.
834 */
835 protected TabBaseChromeWebContentsDelegateAndroid getChromeWebContentsDelega teAndroid() {
836 return mWebContentsDelegate;
837 }
838
839 /**
840 * Called when the favicon of the content this tab represents changes.
841 */
842 @CalledByNative
843 protected void onFaviconUpdated() {
844 for (TabObserver observer : mObservers) observer.onFaviconUpdated(this);
845 }
846
847 /**
848 * Called when the navigation entry containing the historyitem changed,
849 * for example because of a scroll offset or form field change.
850 */
851 @CalledByNative
852 protected void onNavEntryChanged() {
853 }
854
855 /**
856 * @return The native pointer representing the native side of this {@link Ta bBase} object.
857 */
858 @CalledByNative
859 protected long getNativePtr() {
860 return mNativeTabAndroid;
861 }
862
863 /** This is currently called when committing a pre-rendered page. */
864 @CalledByNative
865 private void swapWebContents(
866 final long newWebContents, boolean didStartLoad, boolean didFinishLo ad) {
867 int originalWidth = 0;
868 int originalHeight = 0;
869 if (mContentViewCore != null) {
870 originalWidth = mContentViewCore.getViewportWidthPix();
871 originalHeight = mContentViewCore.getViewportHeightPix();
872 mContentViewCore.onHide();
873 }
874 destroyContentView(false);
875 NativePage previousNativePage = mNativePage;
876 mNativePage = null;
877 initContentView(newWebContents);
878 // Size of the new ContentViewCore is zero at this point. If we don't ca ll onSizeChanged(),
879 // next onShow() call would send a resize message with the current Conte ntViewCore size
880 // (zero) to the renderer process, although the new size will be set soo n.
881 // However, this size fluttering may confuse Blink and rendered result c an be broken
882 // (see http://crbug.com/340987).
883 mContentViewCore.onSizeChanged(originalWidth, originalHeight, 0, 0);
884 mContentViewCore.onShow();
885 mContentViewCore.attachImeAdapter();
886 for (TabObserver observer : mObservers) observer.onContentChanged(this);
887 destroyNativePageInternal(previousNativePage);
888 for (TabObserver observer : mObservers) {
889 observer.onWebContentsSwapped(this, didStartLoad, didFinishLoad);
890 }
891 }
892
893 @CalledByNative
894 private void clearNativePtr() {
895 assert mNativeTabAndroid != 0;
896 mNativeTabAndroid = 0;
897 }
898
899 @CalledByNative
900 private void setNativePtr(long nativePtr) {
901 assert mNativeTabAndroid == 0;
902 mNativeTabAndroid = nativePtr;
903 }
904
905 @CalledByNative
906 private long getNativeInfoBarContainer() {
907 return getInfoBarContainer().getNative();
908 }
909
910 /**
911 * Validates {@code id} and increments the internal counter to make sure fut ure ids don't
912 * collide.
913 * @param id The current id. Maybe {@link #INVALID_TAB_ID}.
914 * @return A new id if {@code id} was {@link #INVALID_TAB_ID}, or {@code i d}.
915 */
916 private static int generateValidId(int id) {
917 if (id == INVALID_TAB_ID) id = generateNextId();
918 incrementIdCounterTo(id + 1);
919
920 return id;
921 }
922
923 /**
924 * @return An unused id.
925 */
926 private static int generateNextId() {
927 return sIdCounter.getAndIncrement();
928 }
929
930 private void pushNativePageStateToNavigationEntry() {
931 assert mNativeTabAndroid != 0 && getNativePage() != null;
932 nativeSetActiveNavigationEntryTitleForUrl(mNativeTabAndroid, getNativePa ge().getUrl(),
933 getNativePage().getTitle());
934 }
935
936 /**
937 * Ensures the counter is at least as high as the specified value. The coun ter should always
938 * point to an unused ID (which will be handed out next time a request comes in). Exposed so
939 * that anything externally loading tabs and ids can set enforce new tabs st art at the correct
940 * id.
941 * TODO(aurimas): Investigate reducing the visiblity of this method.
942 * @param id The minimum id we should hand out to the next new tab.
943 */
944 public static void incrementIdCounterTo(int id) {
945 int diff = id - sIdCounter.get();
946 if (diff <= 0) return;
947 // It's possible idCounter has been incremented between the get above an d the add below
948 // but that's OK, because in the worst case we'll overly increment idCou nter.
949 sIdCounter.addAndGet(diff);
950 }
951
952 private native void nativeInit();
953 private native void nativeDestroy(long nativeTabAndroid);
954 private native void nativeInitWebContents(long nativeTabAndroid, boolean inc ognito,
955 ContentViewCore contentViewCore, ChromeWebContentsDelegateAndroid de legate,
956 ContextMenuPopulator contextMenuPopulator);
957 private native void nativeDestroyWebContents(long nativeTabAndroid, boolean deleteNative);
958 private native WebContents nativeGetWebContents(long nativeTabAndroid);
959 private native Profile nativeGetProfileAndroid(long nativeTabAndroid);
960 private native int nativeGetSecurityLevel(long nativeTabAndroid);
961 private native void nativeSetActiveNavigationEntryTitleForUrl(long nativeTab Android, String url,
962 String title);
963 private native boolean nativePrint(long nativeTabAndroid);
964 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698