| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.android_webview; |
| |
| import android.content.Context; |
| import android.os.StrictMode; |
| |
| import org.chromium.android_webview.policy.AwPolicyProvider; |
| import org.chromium.base.CommandLine; |
| import org.chromium.base.ContextUtils; |
| import org.chromium.base.Log; |
| import org.chromium.base.PathUtils; |
| import org.chromium.base.ThreadUtils; |
| import org.chromium.base.library_loader.LibraryLoader; |
| import org.chromium.base.library_loader.LibraryProcessType; |
| import org.chromium.base.library_loader.ProcessInitException; |
| import org.chromium.content.browser.BrowserStartupController; |
| import org.chromium.content.browser.ChildProcessCreationParams; |
| import org.chromium.policy.CombinedPolicyProvider; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.RandomAccessFile; |
| import java.nio.channels.FileLock; |
| |
| /** |
| * Wrapper for the steps needed to initialize the java and native sides of webview chromium. |
| */ |
| public abstract class AwBrowserProcess { |
| public static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "webview"; |
| |
| private static final String TAG = "AwBrowserProcess"; |
| private static final String EXCLUSIVE_LOCK_FILE = "webview_data.lock"; |
| private static FileLock sExclusiveFileLock; |
| |
| /** |
| * Loads the native library, and performs basic static construction of objects needed |
| * to run webview in this process. Does not create threads; safe to call from zygote. |
| * Note: it is up to the caller to ensure this is only called once. |
| */ |
| public static void loadLibrary() { |
| Context appContext = ContextUtils.getApplicationContext(); |
| PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX, appContext); |
| try { |
| LibraryLoader libraryLoader = LibraryLoader.get(LibraryProcessType.PROCESS_WEBVIEW); |
| libraryLoader.loadNow(appContext); |
| // Switch the command line implementation from Java to native. |
| // It's okay for the WebView to do this before initialization because we have |
| // setup the JNI bindings by this point. |
| libraryLoader.switchCommandLineForWebView(); |
| } catch (ProcessInitException e) { |
| throw new RuntimeException("Cannot load WebView", e); |
| } |
| } |
| |
| /** |
| * Configures child process launcher. This is required only if child services are used in |
| * WebView. |
| */ |
| public static void configureChildProcessLauncher(String packageName, int extraBindFlags) { |
| ChildProcessCreationParams.set( |
| new ChildProcessCreationParams(packageName, extraBindFlags, |
| LibraryProcessType.PROCESS_WEBVIEW_CHILD)); |
| } |
| |
| /** |
| * Starts the chromium browser process running within this process. Creates threads |
| * and performs other per-app resource allocations; must not be called from zygote. |
| * Note: it is up to the caller to ensure this is only called once. |
| */ |
| public static void start() { |
| tryObtainingDataDirLockOrDie(); |
| // We must post to the UI thread to cover the case that the user |
| // has invoked Chromium startup by using the (thread-safe) |
| // CookieManager rather than creating a WebView. |
| ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| @Override |
| public void run() { |
| Context appContext = ContextUtils.getApplicationContext(); |
| // The policies are used by browser startup, so we need to register the policy |
| // providers before starting the browser process. This only registers java objects |
| // and doesn't need the native library. |
| CombinedPolicyProvider.get().registerProvider(new AwPolicyProvider(appContext)); |
| |
| try { |
| BrowserStartupController.get(appContext, LibraryProcessType.PROCESS_WEBVIEW) |
| .startBrowserProcessesSync(!CommandLine.getInstance().hasSwitch( |
| AwSwitches.WEBVIEW_SANDBOXED_RENDERER)); |
| } catch (ProcessInitException e) { |
| throw new RuntimeException("Cannot initialize WebView", e); |
| } |
| } |
| }); |
| } |
| |
| private static void tryObtainingDataDirLockOrDie() { |
| StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); |
| StrictMode.allowThreadDiskWrites(); |
| try { |
| String dataPath = PathUtils.getDataDirectory(); |
| File lockFile = new File(dataPath, EXCLUSIVE_LOCK_FILE); |
| boolean success = false; |
| try { |
| // Note that the file is not closed intentionally. |
| RandomAccessFile file = new RandomAccessFile(lockFile, "rw"); |
| sExclusiveFileLock = file.getChannel().tryLock(); |
| success = sExclusiveFileLock != null; |
| } catch (IOException e) { |
| Log.w(TAG, "Failed to create lock file " + lockFile, e); |
| } |
| if (!success) { |
| Log.w(TAG, "The app may have another WebView opened in a separate process. " |
| + "This is not recommended and may stop working in future versions."); |
| } |
| } finally { |
| StrictMode.setThreadPolicy(oldPolicy); |
| } |
| } |
| } |