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
5package org.chromium.content_shell;
6
7import android.app.Activity;
8import android.content.Context;
9import android.util.AttributeSet;
10import android.view.LayoutInflater;
11import android.view.View;
12import android.widget.FrameLayout;
13
14import org.chromium.base.CalledByNative;
15import org.chromium.base.JNINamespace;
16import org.chromium.base.ThreadUtils;
17import org.chromium.content.browser.ActivityContentVideoViewClient;
18import org.chromium.content.browser.ContentVideoViewClient;
19import org.chromium.content.browser.ContentViewClient;
20import org.chromium.content.browser.ContentViewCore;
21import org.chromium.content.browser.ContentViewRenderView;
22import org.chromium.ui.base.WindowAndroid;
23
24/**
25 * Container and generator of ShellViews.
26 */
27@JNINamespace("content")
28public class ShellManager extends FrameLayout {
29
30    public static final String DEFAULT_SHELL_URL = "http://www.google.com";
31    private static boolean sStartup = true;
32    private WindowAndroid mWindow;
33    private Shell mActiveShell;
34
35    private String mStartupUrl = DEFAULT_SHELL_URL;
36
37    // The target for all content rendering.
38    private ContentViewRenderView mContentViewRenderView;
39    private ContentViewClient mContentViewClient;
40
41    /**
42     * Constructor for inflating via XML.
43     */
44    public ShellManager(final Context context, AttributeSet attrs) {
45        super(context, attrs);
46        nativeInit(this);
47        mContentViewClient = new ContentViewClient() {
48            @Override
49            public ContentVideoViewClient getContentVideoViewClient() {
50                return new ActivityContentVideoViewClient((Activity) context) {
51                    @Override
52                    public boolean onShowCustomView(View view) {
53                        boolean success = super.onShowCustomView(view);
54                        setOverlayVideoMode(true);
55                        return success;
56                    }
57
58                    @Override
59                    public void onDestroyContentVideoView() {
60                        super.onDestroyContentVideoView();
61                        setOverlayVideoMode(false);
62                    }
63                };
64            }
65        };
66    }
67
68    /**
69     * @param window The window used to generate all shells.
70     */
71    public void setWindow(WindowAndroid window) {
72        assert window != null;
73        mWindow = window;
74        mContentViewRenderView = new ContentViewRenderView(getContext()) {
75            @Override
76            protected void onReadyToRender() {
77                if (sStartup) {
78                    mActiveShell.loadUrl(mStartupUrl);
79                    sStartup = false;
80                }
81            }
82        };
83        mContentViewRenderView.onNativeLibraryLoaded(window);
84    }
85
86    /**
87     * @return The window used to generate all shells.
88     */
89    public WindowAndroid getWindow() {
90        return mWindow;
91    }
92
93    /**
94     * Sets the startup URL for new shell windows.
95     */
96    public void setStartupUrl(String url) {
97        mStartupUrl = url;
98    }
99
100    /**
101     * @return The currently visible shell view or null if one is not showing.
102     */
103    public Shell getActiveShell() {
104        return mActiveShell;
105    }
106
107    /**
108     * Creates a new shell pointing to the specified URL.
109     * @param url The URL the shell should load upon creation.
110     */
111    public void launchShell(String url) {
112        ThreadUtils.assertOnUiThread();
113        Shell previousShell = mActiveShell;
114        nativeLaunchShell(url);
115        if (previousShell != null) previousShell.close();
116    }
117
118    /**
119     * Enter or leave overlay video mode.
120     * @param enabled Whether overlay mode is enabled.
121     */
122    public void setOverlayVideoMode(boolean enabled) {
123        if (mContentViewRenderView == null) return;
124        mContentViewRenderView.setOverlayVideoMode(enabled);
125    }
126
127    @SuppressWarnings("unused")
128    @CalledByNative
129    private Object createShell(long nativeShellPtr) {
130        assert mContentViewRenderView != null;
131        LayoutInflater inflater =
132                (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
133        Shell shellView = (Shell) inflater.inflate(R.layout.shell_view, null);
134        shellView.initialize(nativeShellPtr, mWindow, mContentViewClient);
135
136        // TODO(tedchoc): Allow switching back to these inactive shells.
137        if (mActiveShell != null) removeShell(mActiveShell);
138
139        showShell(shellView);
140        return shellView;
141    }
142
143    private void showShell(Shell shellView) {
144        shellView.setContentViewRenderView(mContentViewRenderView);
145        addView(shellView, new FrameLayout.LayoutParams(
146                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
147        mActiveShell = shellView;
148        ContentViewCore contentViewCore = mActiveShell.getContentViewCore();
149        if (contentViewCore != null) {
150            mContentViewRenderView.setCurrentContentViewCore(contentViewCore);
151            contentViewCore.onShow();
152        }
153    }
154
155    @CalledByNative
156    private void removeShell(Shell shellView) {
157        if (shellView == mActiveShell) mActiveShell = null;
158        if (shellView.getParent() == null) return;
159        ContentViewCore contentViewCore = shellView.getContentViewCore();
160        if (contentViewCore != null) contentViewCore.onHide();
161        shellView.setContentViewRenderView(null);
162        removeView(shellView);
163    }
164
165    private static native void nativeInit(Object shellManagerInstance);
166    private static native void nativeLaunchShell(String url);
167}
168