108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)/*
208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Copyright (C) 2012 The Android Open Source Project
308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) *
408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * you may not use this file except in compliance with the License.
608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * You may obtain a copy of the License at
708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) *
808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) *
1008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
1108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
1208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * See the License for the specific language governing permissions and
1408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * limitations under the License.
1508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) */
1608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
1708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)package com.android.server.webkit;
1808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
19dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdochimport android.content.BroadcastReceiver;
20dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdochimport android.content.Context;
21dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdochimport android.content.Intent;
22dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdochimport android.content.IntentFilter;
2308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Binder;
2408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.os.Process;
25810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucciimport android.util.Slog;
2608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)import android.webkit.IWebViewUpdateService;
27dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdochimport android.webkit.WebViewFactory;
2808cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
294dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)import com.android.server.SystemService;
304dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)
3108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)/**
3208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * Private service to wait for the updatable WebView to be ready for use.
3308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) * @hide
3408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles) */
354dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)public class WebViewUpdateService extends SystemService {
3608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
3708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private static final String TAG = "WebViewUpdateService";
38e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci    private static final int WAIT_TIMEOUT_MS = 5000; // Same as KEY_DISPATCHING_TIMEOUT.
3908cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
4008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private boolean mRelroReady32Bit = false;
4108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    private boolean mRelroReady64Bit = false;
4208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
43dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    private BroadcastReceiver mWebViewUpdatedReceiver;
44dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch
45dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    public WebViewUpdateService(Context context) {
464dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        super(context);
474dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)    }
484dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)
494dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)    @Override
504dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)    public void onStart() {
51dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        mWebViewUpdatedReceiver = new BroadcastReceiver() {
52dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                @Override
53dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                public void onReceive(Context context, Intent intent) {
54dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                    String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName();
55dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                    if (webviewPackage.equals(intent.getDataString())) {
56dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                        onWebViewUpdateInstalled();
57dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                    }
58dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch                }
59dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        };
60dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        IntentFilter filter = new IntentFilter();
61dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
62dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        filter.addDataScheme("package");
634dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
644dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)
654dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        publishBinderService("webviewupdate", new BinderService());
6608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
6708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
684dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)    private void onWebViewUpdateInstalled() {
69e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci        Slog.d(TAG, "WebView Package updated!");
7008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
7108cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        synchronized (this) {
724dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            mRelroReady32Bit = false;
734dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            mRelroReady64Bit = false;
7408cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
755ced502fba5a69dc1d2e55b3d7e5fd429280d6aeBen Murdoch        WebViewFactory.onWebViewUpdateInstalled();
7608cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)    }
7708cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)
784dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)    private class BinderService extends IWebViewUpdateService.Stub {
79810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci
804dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        /**
814dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)         * The shared relro process calls this to notify us that it's done trying to create a relro
824dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)         * file. This method gets called even if the relro creation has failed or the process
834dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)         * crashed.
844dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)         */
854dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        @Override // Binder call
864dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        public void notifyRelroCreationCompleted(boolean is64Bit, boolean success) {
874dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            // Verify that the caller is either the shared relro process (nominal case) or the
884dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            // system server (only in the case the relro process crashes and we get here via the
894dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            // crashHandler).
904dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            if (Binder.getCallingUid() != Process.SHARED_RELRO_UID &&
914dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                    Binder.getCallingUid() != Process.SYSTEM_UID) {
924dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                return;
934dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            }
944dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)
954dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            synchronized (WebViewUpdateService.this) {
964dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                if (is64Bit) {
974dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                    mRelroReady64Bit = true;
984dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                } else {
994dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                    mRelroReady32Bit = true;
10008cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)                }
1014dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                WebViewUpdateService.this.notifyAll();
10208cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)            }
10308cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)        }
104dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch
1054dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        /**
1064dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)         * WebViewFactory calls this to block WebView loading until the relro file is created.
1074dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)         */
1084dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        @Override // Binder call
1094dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)        public void waitForRelroCreationCompleted(boolean is64Bit) {
110e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            // The WebViewUpdateService depends on the prepareWebViewInSystemServer call, which
111e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            // happens later (during the PHASE_ACTIVITY_MANAGER_READY) in SystemServer.java. If
112e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            // another service there tries to bring up a WebView in the between, the wait below
113e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            // would deadlock without the check below.
114e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            if (Binder.getCallingPid() == Process.myPid()) {
115e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                throw new IllegalStateException("Cannot create a WebView from the SystemServer");
1164dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            }
117dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch
118e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            final long NS_PER_MS = 1000000;
119e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
1206a0d43f09d8329bfe4709c05d2ce060cfbfba8b8Torne (Richard Coles)            boolean relroReady = (is64Bit ? mRelroReady64Bit : mRelroReady32Bit);
1214dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            synchronized (WebViewUpdateService.this) {
122e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                while (!relroReady) {
123e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                    final long timeNowMs = System.nanoTime() / NS_PER_MS;
124e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                    if (timeNowMs >= timeoutTimeMs) break;
125e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                    try {
126e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                        WebViewUpdateService.this.wait(timeoutTimeMs - timeNowMs);
127e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                    } catch (InterruptedException e) {}
128e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci                    relroReady = (is64Bit ? mRelroReady64Bit : mRelroReady32Bit);
1294dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)                }
1304dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)            }
131e76e81a227a29db5223d231ec88ecb02fa4d6835Primiano Tucci            if (!relroReady) Slog.w(TAG, "creating relro file timed out");
132dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch        }
133dc00a84af15ff3594a6dfa512be21095bf9fee82Ben Murdoch    }
1344dbeb359b2cfeb63d6ec3ecb702f2bd836db058aTorne (Richard Coles)
13508cfaf672604422dd355d6703aec78f3aa5ee74eTorne (Richard Coles)}
136