EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.chrome.browser.sync]

COVERAGE SUMMARY FOR SOURCE FILE [ChromiumSyncAdapter.java]

nameclass, %method, %block, %line, %
ChromiumSyncAdapter.java60%  (3/5)53%  (10/19)60%  (195/324)54%  (31.6/59)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ChromiumSyncAdapter$20%   (0/1)0%   (0/2)0%   (0/14)0%   (0/3)
ChromiumSyncAdapter$2 (ChromiumSyncAdapter, BrowserStartupController$StartupC... 0%   (0/1)0%   (0/9)0%   (0/1)
run (): void 0%   (0/1)0%   (0/5)0%   (0/2)
     
class ChromiumSyncAdapter$30%   (0/1)0%   (0/2)0%   (0/13)0%   (0/3)
ChromiumSyncAdapter$3 (ChromiumSyncAdapter, BrowserStartupController$StartupC... 0%   (0/1)0%   (0/9)0%   (0/1)
run (): void 0%   (0/1)0%   (0/4)0%   (0/2)
     
class ChromiumSyncAdapter100% (1/1)60%  (6/10)57%  (102/180)53%  (20.6/39)
access$200 (ChromiumSyncAdapter, BrowserStartupController$StartupCallback): void 0%   (0/1)0%   (0/4)0%   (0/1)
requestSync (String, long, String): void 0%   (0/1)0%   (0/8)0%   (0/2)
requestSyncForAllTypes (): void 0%   (0/1)0%   (0/5)0%   (0/2)
startBrowserProcessesSync (BrowserStartupController$StartupCallback): void 0%   (0/1)0%   (0/33)0%   (0/7)
startBrowserProcess (BrowserStartupController$StartupCallback, SyncResult, Se... 100% (1/1)35%  (8/23)43%  (3/7)
onPerformSync (Account, Bundle, String, ContentProviderClient, SyncResult): void 100% (1/1)70%  (31/44)73%  (8/11)
ChromiumSyncAdapter (Context, Application): void 100% (1/1)100% (12/12)100% (4/4)
access$000 (ChromiumSyncAdapter): boolean 100% (1/1)100% (3/3)100% (1/1)
access$100 (ChromiumSyncAdapter): Application 100% (1/1)100% (3/3)100% (1/1)
getStartupCallback (Context, Account, Bundle, SyncResult, Semaphore): Browser... 100% (1/1)100% (45/45)100% (5/5)
     
class ChromiumSyncAdapter$4100% (1/1)67%  (2/3)78%  (68/87)67%  (8/12)
onFailure (): void 0%   (0/1)0%   (0/19)0%   (0/4)
ChromiumSyncAdapter$4 (ChromiumSyncAdapter, boolean, String, long, String, Se... 100% (1/1)100% (30/30)100% (1/1)
onSuccess (boolean): void 100% (1/1)100% (38/38)100% (7/7)
     
class ChromiumSyncAdapter$1100% (1/1)100% (2/2)83%  (25/30)83%  (5/6)
run (): void 100% (1/1)76%  (16/21)80%  (4/5)
ChromiumSyncAdapter$1 (ChromiumSyncAdapter, BrowserStartupController$StartupC... 100% (1/1)100% (9/9)100% (1/1)

1// Copyright 2013 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.chrome.browser.sync;
6 
7import android.accounts.Account;
8import android.app.Application;
9import android.content.AbstractThreadedSyncAdapter;
10import android.content.ContentProviderClient;
11import android.content.Context;
12import android.content.SyncResult;
13import android.os.Bundle;
14import android.os.Handler;
15import android.util.Log;
16 
17import com.google.common.annotations.VisibleForTesting;
18 
19import org.chromium.base.ThreadUtils;
20import org.chromium.content.browser.AndroidBrowserProcess;
21import org.chromium.content.browser.BrowserStartupController;
22import org.chromium.content.common.ProcessInitException;
23 
24import java.util.concurrent.Semaphore;
25 
26/**
27 * A sync adapter for Chromium.
28 */
29public abstract class ChromiumSyncAdapter extends AbstractThreadedSyncAdapter {
30    private static final String TAG = "ChromiumSyncAdapter";
31 
32    // TODO(nyquist) Make these fields package protected once downstream sync adapter tests are
33    // removed.
34    @VisibleForTesting
35    public static final String INVALIDATION_OBJECT_ID_KEY = "objectId";
36    @VisibleForTesting
37    public static final String INVALIDATION_VERSION_KEY = "version";
38    @VisibleForTesting
39    public static final String INVALIDATION_PAYLOAD_KEY = "payload";
40 
41    private final Application mApplication;
42    private final boolean mAsyncStartup;
43 
44    public ChromiumSyncAdapter(Context context, Application application) {
45        super(context, false);
46        mApplication = application;
47        mAsyncStartup = useAsyncStartup();
48    }
49 
50    protected abstract boolean useAsyncStartup();
51 
52    protected abstract void initCommandLine();
53 
54    @Override
55    public void onPerformSync(Account account, Bundle extras, String authority,
56                              ContentProviderClient provider, SyncResult syncResult) {
57        if (!DelayedSyncController.getInstance().shouldPerformSync(getContext(), extras, account)) {
58            return;
59        }
60 
61        // Browser startup is asynchronous, so we will need to wait for startup to finish.
62        Semaphore semaphore = new Semaphore(0);
63 
64        // Configure the callback with all the data it needs.
65        BrowserStartupController.StartupCallback callback =
66                getStartupCallback(mApplication, account, extras, syncResult, semaphore);
67        startBrowserProcess(callback, syncResult, semaphore);
68 
69        try {
70            // Wait for startup to complete.
71            semaphore.acquire();
72        } catch (InterruptedException e) {
73            Log.w(TAG, "Got InterruptedException when trying to request a sync.", e);
74            // Using numIoExceptions so Android will treat this as a soft error.
75            syncResult.stats.numIoExceptions++;
76        }
77    }
78 
79    private void startBrowserProcess(
80            final BrowserStartupController.StartupCallback callback,
81            final SyncResult syncResult, Semaphore semaphore) {
82        try {
83            ThreadUtils.runOnUiThreadBlocking(new Runnable() {
84                @Override
85                public void run() {
86                    initCommandLine();
87                    if (mAsyncStartup) {
88                        BrowserStartupController.get(mApplication)
89                                .startBrowserProcessesAsync(callback);
90                    } else {
91                        startBrowserProcessesSync(callback);
92                    }
93                }
94            });
95        } catch (RuntimeException e) {
96            // It is still unknown why we ever experience this. See http://crbug.com/180044.
97            Log.w(TAG, "Got exception when trying to request a sync. Informing Android system.", e);
98            // Using numIoExceptions so Android will treat this as a soft error.
99            syncResult.stats.numIoExceptions++;
100            semaphore.release();
101        }
102    }
103 
104    private void startBrowserProcessesSync(
105            final BrowserStartupController.StartupCallback callback) {
106        try {
107            AndroidBrowserProcess.init(
108                    mApplication, AndroidBrowserProcess.MAX_RENDERERS_LIMIT);
109            new Handler().post(new Runnable() {
110                @Override
111                public void run() {
112                    callback.onSuccess(false);
113                }
114            });
115        } catch (ProcessInitException e) {
116            Log.e(TAG, "Unable to start browser process.", e);
117            new Handler().post(new Runnable() {
118                @Override
119                public void run() {
120                    callback.onFailure();
121                }
122            });
123        }
124    }
125 
126    private BrowserStartupController.StartupCallback getStartupCallback(
127            final Context context, final Account acct, Bundle extras,
128            final SyncResult syncResult, final Semaphore semaphore) {
129        final boolean syncAllTypes = extras.getString(INVALIDATION_OBJECT_ID_KEY) == null;
130        final String objectId = syncAllTypes ? "" : extras.getString(INVALIDATION_OBJECT_ID_KEY);
131        final long version = syncAllTypes ? 0 : extras.getLong(INVALIDATION_VERSION_KEY);
132        final String payload = syncAllTypes ? "" : extras.getString(INVALIDATION_PAYLOAD_KEY);
133 
134        return new BrowserStartupController.StartupCallback() {
135            @Override
136            public void onSuccess(boolean alreadyStarted) {
137                // Startup succeeded, so we can tickle the sync engine.
138                if (syncAllTypes) {
139                    Log.v(TAG, "Received sync tickle for all types.");
140                    requestSyncForAllTypes();
141                } else {
142                    Log.v(TAG, "Received sync tickle for " + objectId + ".");
143                    requestSync(objectId, version, payload);
144                }
145                semaphore.release();
146            }
147 
148            @Override
149            public void onFailure() {
150                // The startup failed, so we reset the delayed sync state.
151                DelayedSyncController.getInstance().setDelayedSync(context, acct.name);
152                // Using numIoExceptions so Android will treat this as a soft error.
153                syncResult.stats.numIoExceptions++;
154                semaphore.release();
155            }
156        };
157    }
158 
159    @VisibleForTesting
160    public void requestSync(String objectId, long version, String payload) {
161        ProfileSyncService.get(mApplication)
162                .requestSyncFromNativeChrome(objectId, version, payload);
163    }
164 
165    @VisibleForTesting
166    public void requestSyncForAllTypes() {
167        ProfileSyncService.get(mApplication).requestSyncFromNativeChromeForAllTypes();
168    }
169}

[all classes][org.chromium.chrome.browser.sync]
EMMA 2.0.5312 (C) Vladimir Roubtsov