1 | // Copyright (c) 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.testshell; |
6 | |
7 | import android.content.Context; |
8 | import android.text.TextUtils; |
9 | |
10 | import org.chromium.base.ObserverList; |
11 | import org.chromium.chrome.browser.ChromeWebContentsDelegateAndroid; |
12 | import org.chromium.chrome.browser.ContentViewUtil; |
13 | import org.chromium.chrome.browser.TabBase; |
14 | import org.chromium.content.browser.ContentView; |
15 | import org.chromium.content.browser.LoadUrlParams; |
16 | import org.chromium.content.common.CleanupReference; |
17 | import org.chromium.ui.WindowAndroid; |
18 | |
19 | /** |
20 | * TestShell's implementation of a tab. This mirrors how Chrome for Android subclasses |
21 | * and extends {@link TabBase}. |
22 | */ |
23 | public class TestShellTab extends TabBase { |
24 | private ChromeWebContentsDelegateAndroid mWebContentsDelegate; |
25 | private ContentView mContentView; |
26 | private int mNativeTestShellTab; |
27 | private final ObserverList<TestShellTabObserver> mObservers = |
28 | new ObserverList<TestShellTabObserver>(); |
29 | |
30 | private CleanupReference mCleanupReference; |
31 | |
32 | // Tab state |
33 | private boolean mIsLoading = false; |
34 | |
35 | /** |
36 | * @param context The Context the view is running in. |
37 | * @param url The URL to start this tab with. |
38 | * @param window The WindowAndroid should represent this tab. |
39 | */ |
40 | public TestShellTab(Context context, String url, WindowAndroid window) { |
41 | super(window); |
42 | init(context); |
43 | loadUrlWithSanitization(url); |
44 | } |
45 | |
46 | /** |
47 | * @param context The Context the view is running in. |
48 | */ |
49 | private void init(Context context) { |
50 | // Build the WebContents and the ContentView/ContentViewCore |
51 | int nativeWebContentsPtr = ContentViewUtil.createNativeWebContents(false); |
52 | mContentView = ContentView.newInstance(context, nativeWebContentsPtr, getWindowAndroid()); |
53 | mNativeTestShellTab = nativeInit(nativeWebContentsPtr, |
54 | getWindowAndroid().getNativePointer()); |
55 | |
56 | // Build the WebContentsDelegate |
57 | mWebContentsDelegate = new TabBaseChromeWebContentsDelegateAndroid(); |
58 | nativeInitWebContentsDelegate(mNativeTestShellTab, mWebContentsDelegate); |
59 | |
60 | // To be called after everything is initialized. |
61 | mCleanupReference = new CleanupReference(this, |
62 | new DestroyRunnable(mNativeTestShellTab)); |
63 | } |
64 | |
65 | /** |
66 | * Should be called when the tab is no longer needed. Once this is called this tab should not |
67 | * be used. |
68 | */ |
69 | public void destroy() { |
70 | for (TestShellTabObserver observer : mObservers) { |
71 | observer.onCloseTab(TestShellTab.this); |
72 | } |
73 | destroyContentView(); |
74 | if (mNativeTestShellTab != 0) { |
75 | mCleanupReference.cleanupNow(); |
76 | mNativeTestShellTab = 0; |
77 | } |
78 | } |
79 | |
80 | /** |
81 | * @param observer The {@link TestShellTabObserver} that should be notified of changes. |
82 | */ |
83 | public void addObserver(TestShellTabObserver observer) { |
84 | mObservers.addObserver(observer); |
85 | } |
86 | |
87 | /** |
88 | * @param observer The {@link TestShellTabObserver} that should no longer be notified of |
89 | * changes. |
90 | */ |
91 | public void removeObserver(TestShellTabObserver observer) { |
92 | mObservers.removeObserver(observer); |
93 | } |
94 | |
95 | /** |
96 | * @return Whether or not the tab is currently loading. |
97 | */ |
98 | public boolean isLoading() { |
99 | return mIsLoading; |
100 | } |
101 | |
102 | /** |
103 | * @return The {@link ContentView} represented by this tab. |
104 | */ |
105 | public ContentView getContentView() { |
106 | return mContentView; |
107 | } |
108 | |
109 | |
110 | private void destroyContentView() { |
111 | if (mContentView == null) return; |
112 | |
113 | mContentView.destroy(); |
114 | mContentView = null; |
115 | } |
116 | |
117 | /** |
118 | * Navigates this Tab's {@link ContentView} to a sanitized version of {@code url}. |
119 | * @param url The potentially unsanitized URL to navigate to. |
120 | */ |
121 | public void loadUrlWithSanitization(String url) { |
122 | if (url == null) return; |
123 | |
124 | // Sanitize the URL. |
125 | url = nativeFixupUrl(mNativeTestShellTab, url); |
126 | |
127 | // Invalid URLs will just return empty. |
128 | if (TextUtils.isEmpty(url)) return; |
129 | |
130 | if (TextUtils.equals(url, mContentView.getUrl())) { |
131 | mContentView.reload(); |
132 | } else { |
133 | mContentView.loadUrl(new LoadUrlParams(url)); |
134 | } |
135 | } |
136 | |
137 | private static final class DestroyRunnable implements Runnable { |
138 | private final int mNativeTestShellTab; |
139 | private DestroyRunnable(int nativeTestShellTab) { |
140 | mNativeTestShellTab = nativeTestShellTab; |
141 | } |
142 | @Override |
143 | public void run() { |
144 | nativeDestroy(mNativeTestShellTab); |
145 | } |
146 | } |
147 | |
148 | private class TabBaseChromeWebContentsDelegateAndroid |
149 | extends ChromeWebContentsDelegateAndroid { |
150 | @Override |
151 | public void onLoadProgressChanged(int progress) { |
152 | for (TestShellTabObserver observer : mObservers) { |
153 | observer.onLoadProgressChanged(TestShellTab.this, progress); |
154 | } |
155 | } |
156 | |
157 | @Override |
158 | public void onUpdateUrl(String url) { |
159 | for (TestShellTabObserver observer : mObservers) { |
160 | observer.onUpdateUrl(TestShellTab.this, url); |
161 | } |
162 | } |
163 | |
164 | @Override |
165 | public void onLoadStarted() { |
166 | mIsLoading = true; |
167 | } |
168 | |
169 | @Override |
170 | public void onLoadStopped() { |
171 | mIsLoading = false; |
172 | } |
173 | } |
174 | |
175 | private native int nativeInit(int webContentsPtr, int windowAndroidPtr); |
176 | private static native void nativeDestroy(int nativeTestShellTab); |
177 | private native void nativeInitWebContentsDelegate(int nativeTestShellTab, |
178 | ChromeWebContentsDelegateAndroid chromeWebContentsDelegateAndroid); |
179 | private native String nativeFixupUrl(int nativeTestShellTab, String url); |
180 | } |