WebViewUpdateService.java revision 810c052d9b117217152c2a609ccec056a2a61d1e
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.webkit; 18 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.os.Binder; 24import android.os.Process; 25import android.util.Log; 26import android.util.Slog; 27import android.webkit.IWebViewUpdateService; 28import android.webkit.WebViewFactory; 29 30/** 31 * Private service to wait for the updatable WebView to be ready for use. 32 * @hide 33 */ 34// TODO This should be implemented using the new pattern for system services. 35// See comments in CL 509840. 36public class WebViewUpdateService extends IWebViewUpdateService.Stub { 37 38 private static final String TAG = "WebViewUpdateService"; 39 40 private boolean mRelroReady32Bit = false; 41 private boolean mRelroReady64Bit = false; 42 43 private BroadcastReceiver mWebViewUpdatedReceiver; 44 45 public WebViewUpdateService(Context context) { 46 mWebViewUpdatedReceiver = new BroadcastReceiver() { 47 @Override 48 public void onReceive(Context context, Intent intent) { 49 String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName(); 50 if (webviewPackage.equals(intent.getDataString())) { 51 onWebViewUpdateInstalled(); 52 } 53 } 54 }; 55 IntentFilter filter = new IntentFilter(); 56 filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 57 filter.addDataScheme("package"); 58 context.registerReceiver(mWebViewUpdatedReceiver, filter); 59 } 60 61 /** 62 * The shared relro process calls this to notify us that it's done trying to create a relro 63 * file. This method gets called even if the relro creation has failed or the process crashed. 64 */ 65 @Override // Binder call 66 public void notifyRelroCreationCompleted(boolean is64Bit, boolean success) { 67 // Verify that the caller is either the shared relro process (nominal case) or the system 68 // server (only in the case the relro process crashes and we get here via the crashHandler). 69 if (Binder.getCallingUid() != Process.SHARED_RELRO_UID && 70 Binder.getCallingUid() != Process.SYSTEM_UID) { 71 return; 72 } 73 74 synchronized (this) { 75 if (is64Bit) { 76 mRelroReady64Bit = true; 77 } else { 78 mRelroReady32Bit = true; 79 } 80 this.notifyAll(); 81 } 82 } 83 84 /** 85 * WebViewFactory calls this to block WebView loading until the relro file is created. 86 */ 87 @Override // Binder call 88 public void waitForRelroCreationCompleted(boolean is64Bit) { 89 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 90 Slog.wtf(TAG, "Trying to load WebView from the SystemServer", 91 new IllegalStateException()); 92 } 93 94 synchronized (this) { 95 if (is64Bit) { 96 while (!mRelroReady64Bit) { 97 try { 98 this.wait(); 99 } catch (InterruptedException e) {} 100 } 101 } else { 102 while (!mRelroReady32Bit) { 103 try { 104 this.wait(); 105 } catch (InterruptedException e) {} 106 } 107 } 108 } 109 } 110 111 private void onWebViewUpdateInstalled() { 112 Log.d(TAG, "WebView Package updated!"); 113 114 synchronized (this) { 115 mRelroReady32Bit = false; 116 mRelroReady64Bit = false; 117 } 118 WebViewFactory.prepareWebViewInSystemServer(); 119 } 120} 121